summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-03-18 20:05:52 +0100
committerStef Walter <stefw@gnome.org>2013-03-18 21:53:24 +0100
commit1ad9f98b11f3f0d411bf9517f1dc8985ea3dbe2a (patch)
treee93f94fbe7522db404bca4c6794e8c3ae65ba341
parentf40e5f7129ece4b74aa2cb23b28b24b381bbe223 (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.
-rw-r--r--trust/builder.c2
-rw-r--r--trust/module.c47
-rw-r--r--trust/tests/test-module.c66
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
@@ -730,3 +730,3 @@ build_for_schema (p11_builder *builder,
- if (creating) {
+ if (creating && (builder->flags & P11_BUILDER_FLAG_TOKEN)) {
if (schema->build_flags & GENERATED_CLASS) {
diff --git a/trust/module.c b/trust/module.c
index dcf4e8f..3ef4034 100644
--- a/trust/module.c
+++ b/trust/module.c
@@ -47,2 +47,3 @@
#include "pkcs11.h"
+#include "pkcs11x.h"
#include "session.h"
@@ -1049,2 +1050,45 @@ sys_C_SetAttributeValue (CK_SESSION_HANDLE handle,
+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
@@ -1097,2 +1141,5 @@ sys_C_FindObjectsInit (CK_SESSION_HANDLE handle,
+ find->match = work_around_broken_nss_serial_number_lookups (find->match);
+ warn_if_fail (find->match != NULL);
+
/* Build a session snapshot of all objects */
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
@@ -790,2 +790,67 @@ test_session_remove (CuTest *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
@@ -816,2 +881,3 @@ main (void)
SUITE_ADD_TEST (suite, test_session_setattr);
+ SUITE_ADD_TEST (suite, test_find_serial_der_decoded);