diff options
author | Stef Walter <stefw@gnome.org> | 2013-03-18 20:05:52 +0100 |
---|---|---|
committer | Stef Walter <stefw@gnome.org> | 2013-03-18 21:53:24 +0100 |
commit | 1ad9f98b11f3f0d411bf9517f1dc8985ea3dbe2a (patch) | |
tree | e93f94fbe7522db404bca4c6794e8c3ae65ba341 /trust | |
parent | f40e5f7129ece4b74aa2cb23b28b24b381bbe223 (diff) |
trust: Handle incorrectly encoded CKA_SERIAL_NUMBER lookups
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.
Diffstat (limited to 'trust')
-rw-r--r-- | trust/builder.c | 2 | ||||
-rw-r--r-- | trust/module.c | 47 | ||||
-rw-r--r-- | trust/tests/test-module.c | 66 |
3 files changed, 114 insertions, 1 deletions
diff --git a/trust/builder.c b/trust/builder.c index 65aa5dd..0a020cf 100644 --- a/trust/builder.c +++ b/trust/builder.c @@ -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; diff --git a/trust/module.c b/trust/module.c index dcf4e8f..3ef4034 100644 --- a/trust/module.c +++ b/trust/module.c @@ -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); diff --git a/trust/tests/test-module.c b/trust/tests/test-module.c index 4606a31..de0a3b1 100644 --- a/trust/tests/test-module.c +++ b/trust/tests/test-module.c @@ -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); |