]> granicus.if.org Git - p11-kit/commitdiff
trust: Handle incorrectly encoded CKA_SERIAL_NUMBER lookups
authorStef Walter <stefw@gnome.org>
Mon, 18 Mar 2013 19:05:52 +0000 (20:05 +0100)
committerStef Walter <stefw@gnome.org>
Mon, 18 Mar 2013 20:53:24 +0000 (21:53 +0100)
Handle lookups for trust objects (by NSS) which expect CKA_SERIAL_NUMBER
attributes without appropriate DER encoding.

In addition allow creation of NSS trust objects as PKCS#11 session
objects, so that we can test this behavior.

trust/builder.c
trust/module.c
trust/tests/test-module.c

index 65aa5ddd1165c596e4744f43aef4deabc5d6bf55..0a020cf18b58c8c96f5eaa91beaff23430ee016c 100644 (file)
@@ -728,7 +728,7 @@ build_for_schema (p11_builder *builder,
        if (attrs != NULL)
                attrs_filter_if_unchanged (attrs, merge);
 
-       if (creating) {
+       if (creating && (builder->flags & P11_BUILDER_FLAG_TOKEN)) {
                if (schema->build_flags & GENERATED_CLASS) {
                        p11_message ("objects of this type cannot be created");
                        return CKR_TEMPLATE_INCONSISTENT;
index dcf4e8f70886366c0750836e62b408c12d967cf8..3ef40342da4f3862df2f8a674ccc749cf70fbbc8 100644 (file)
@@ -45,6 +45,7 @@
 #include "module.h"
 #include "parser.h"
 #include "pkcs11.h"
+#include "pkcs11x.h"
 #include "session.h"
 #include "token.h"
 
@@ -1047,6 +1048,49 @@ sys_C_SetAttributeValue (CK_SESSION_HANDLE handle,
        return rv;
 }
 
+static CK_ATTRIBUTE *
+work_around_broken_nss_serial_number_lookups (CK_ATTRIBUTE *attrs)
+{
+       /*
+        * WORKAROUND: NSS calls us asking for CKA_SERIAL_NUMBER items that are
+        * not DER encoded. It shouldn't be doing this. We never return any certificate
+        * serial numbers that are not DER encoded.
+        *
+        * So work around the issue here while the NSS guys fix this issue.
+        * This code should be removed in future versions.
+        */
+
+       CK_OBJECT_CLASS klass;
+       CK_ATTRIBUTE *serial;
+       unsigned char *der;
+       size_t der_len;
+       int len_len;
+
+       if (!p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) ||
+           klass != CKO_NSS_TRUST)
+               return attrs;
+
+       serial = p11_attrs_find_valid (attrs, CKA_SERIAL_NUMBER);
+       if (!serial || p11_asn1_tlv_length (serial->pValue, serial->ulValueLen) >= 0)
+               return attrs;
+
+       p11_debug ("working around serial number lookup that's not DER encoded");
+
+       /* Assumption that 32 bytes is more than enough to store a ulong */
+       der_len = 1 + 32 + serial->ulValueLen;
+       der = malloc (der_len);
+       return_val_if_fail (der != NULL, NULL);
+
+       der[0] = ASN1_TAG_INTEGER | ASN1_CLASS_UNIVERSAL;
+       len_len = der_len - 1;
+       asn1_length_der (serial->ulValueLen, der + 1, &len_len);
+       assert (len_len < der_len - serial->ulValueLen);
+       memcpy (der + 1 + len_len, serial->pValue, serial->ulValueLen);
+       der_len = 1 + len_len + serial->ulValueLen;
+
+       return p11_attrs_take (attrs, CKA_SERIAL_NUMBER, der, der_len);
+}
+
 static CK_RV
 sys_C_FindObjectsInit (CK_SESSION_HANDLE handle,
                        CK_ATTRIBUTE_PTR template,
@@ -1095,6 +1139,9 @@ sys_C_FindObjectsInit (CK_SESSION_HANDLE handle,
                                find->match = p11_attrs_buildn (NULL, template, count);
                                warn_if_fail (find->match != NULL);
 
+                               find->match = work_around_broken_nss_serial_number_lookups (find->match);
+                               warn_if_fail (find->match != NULL);
+
                                /* Build a session snapshot of all objects */
                                find->iterator = 0;
                                find->snapshot = p11_index_snapshot (indices[0], indices[1], template, count);
index 4606a31491359f2c58a765b99eb8afefdc0600a0..de0a3b1a73b262acded245dfd217da77cdcbd9fc 100644 (file)
@@ -788,6 +788,71 @@ test_session_remove (CuTest *cu)
        teardown (cu);
 }
 
+static void
+test_find_serial_der_decoded (CuTest *cu)
+{
+       CK_OBJECT_CLASS nss_trust = CKO_NSS_TRUST;
+
+       CK_ATTRIBUTE object[] = {
+               { CKA_CLASS, &nss_trust, sizeof (nss_trust) },
+               { CKA_SERIAL_NUMBER, "\x02\x03\x01\x02\x03", 5 },
+               { CKA_INVALID }
+       };
+
+       CK_ATTRIBUTE match_decoded[] = {
+               { CKA_CLASS, &nss_trust, sizeof (nss_trust) },
+               { CKA_SERIAL_NUMBER, "\x01\x02\x03", 3 },
+               { CKA_INVALID }
+       };
+
+       CK_SESSION_HANDLE session;
+       CK_OBJECT_HANDLE handle;
+       CK_OBJECT_HANDLE check;
+       CK_ULONG count;
+       CK_RV rv;
+
+       /*
+        * WORKAROUND: NSS calls us asking for CKA_SERIAL_NUMBER items that are
+        * not DER encoded. It shouldn't be doing this. We never return any certificate
+        * serial numbers that are not DER encoded.
+        *
+        * So work around the issue here while the NSS guys fix this issue.
+        * This code should be removed in future versions.
+        *
+        * See work_around_broken_nss_serial_number_lookups().
+        */
+
+       setup (cu);
+
+       rv = test.module->C_OpenSession (test.slots[0], CKF_SERIAL_SESSION, NULL, NULL, &session);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+
+       rv = test.module->C_CreateObject (session, object, 2, &handle);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+
+       /* Do a standard find for the same object */
+       rv = test.module->C_FindObjectsInit (session, object, 2);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       rv = test.module->C_FindObjects (session, &check, 1, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, 1, count);
+       CuAssertIntEquals (cu, handle, check);
+       rv = test.module->C_FindObjectsFinal (session);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+
+       /* Do a find for the serial number decoded */
+       rv = test.module->C_FindObjectsInit (session, match_decoded, 2);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       rv = test.module->C_FindObjects (session, &check, 1, &count);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       CuAssertIntEquals (cu, 1, count);
+       CuAssertIntEquals (cu, handle, check);
+       rv = test.module->C_FindObjectsFinal (session);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+
+       teardown (cu);
+}
+
 int
 main (void)
 {
@@ -814,6 +879,7 @@ main (void)
        SUITE_ADD_TEST (suite, test_session_copy);
        SUITE_ADD_TEST (suite, test_session_remove);
        SUITE_ADD_TEST (suite, test_session_setattr);
+       SUITE_ADD_TEST (suite, test_find_serial_der_decoded);
 
        CuSuiteRun (suite);
        CuSuiteSummary (suite, output);