From 57697eda68a3343c2e54e5f8f3f4ce65a99383f5 Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 31 Jan 2018 14:07:51 +0100 Subject: trust: Filter out duplicate extensions The trust policy module keeps all the objects in the database, while PKIX doesn't allow multiple extensions identified by the same OID can be attached to a certificate. Add a check to C_FindObjects to exclude any duplicates and only return the first matching object. It would be better if the module rejects such duplicates when loading, but it would make startup slower. https://bugzilla.redhat.com/show_bug.cgi?id=1141241 --- trust/module.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) (limited to 'trust/module.c') diff --git a/trust/module.c b/trust/module.c index 7fce465..e6fb7a9 100644 --- a/trust/module.c +++ b/trust/module.c @@ -45,6 +45,7 @@ #include "library.h" #include "message.h" #include "module.h" +#include "oid.h" #include "parser.h" #include "path.h" #include "pkcs11.h" @@ -77,6 +78,8 @@ typedef struct _FindObjects { CK_ATTRIBUTE *match; CK_OBJECT_HANDLE *snapshot; CK_ULONG iterator; + CK_ATTRIBUTE *public_key; + p11_dict *extensions; } FindObjects; static CK_FUNCTION_LIST sys_function_list; @@ -87,6 +90,7 @@ find_objects_free (void *data) FindObjects *find = data; p11_attrs_free (find->match); free (find->snapshot); + p11_dict_free (find->extensions); free (find); } @@ -1147,6 +1151,7 @@ sys_C_FindObjectsInit (CK_SESSION_HANDLE handle, char *string; CK_RV rv; int n = 0; + CK_OBJECT_CLASS klass; if (p11_debugging) { string = p11_attrs_to_string (template, count); @@ -1190,6 +1195,14 @@ sys_C_FindObjectsInit (CK_SESSION_HANDLE handle, find->iterator = 0; find->snapshot = p11_index_snapshot (indices[0], indices[1], template, count); warn_if_fail (find->snapshot != NULL); + + if (p11_attrs_find_ulong (find->match, CKA_CLASS, &klass) && + klass == CKO_X_CERTIFICATE_EXTENSION) { + find->public_key = p11_attrs_find (find->match, CKA_PUBLIC_KEY_INFO); + find->extensions = p11_dict_new (p11_oid_hash, + p11_oid_equal, + free, NULL); + } } if (!find || !find->snapshot || !find->match) @@ -1243,10 +1256,10 @@ match_for_broken_nss_serial_number_lookups (CK_ATTRIBUTE *attr, static bool find_objects_match (CK_ATTRIBUTE *attrs, - CK_ATTRIBUTE *match) + FindObjects *find) { CK_OBJECT_CLASS klass; - CK_ATTRIBUTE *attr; + CK_ATTRIBUTE *attr, *match = find->match; for (; !p11_attrs_terminator (match); match++) { attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match->type); @@ -1274,6 +1287,29 @@ find_objects_match (CK_ATTRIBUTE *attrs, return false; } + /* + * WORKAROUND: We keep all objects in the database, while PKIX + * doesn't allow multiple extensions identified by the same + * OID can be attached to a certificate. Check any duplicate + * and only return the first matching object. + */ + if (find->public_key && + p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) && + klass == CKO_X_CERTIFICATE_EXTENSION) { + CK_ATTRIBUTE *oid = p11_attrs_find (attrs, CKA_OBJECT_ID); + if (oid) { + void *value; + if (p11_oid_simple (oid->pValue, oid->ulValueLen) && + p11_dict_get (find->extensions, oid->pValue)) { + p11_debug ("duplicate extension object"); + return false; + } + value = memdup (oid->pValue, oid->ulValueLen); + return_val_if_fail (value != NULL, false); + p11_dict_set (find->extensions, value, value); + } + } + return true; } @@ -1317,7 +1353,7 @@ sys_C_FindObjects (CK_SESSION_HANDLE handle, if (attrs == NULL) continue; - if (find_objects_match (attrs, find->match)) { + if (find_objects_match (attrs, find)) { objects[matched] = object; matched++; } -- cgit v1.1