]> granicus.if.org Git - p11-kit/commitdiff
trust: Better generation of nss objects and assertions for serial+issuer
authorStef Walter <stefw@gnome.org>
Mon, 18 Mar 2013 15:00:55 +0000 (16:00 +0100)
committerStef Walter <stefw@gnome.org>
Mon, 18 Mar 2013 15:00:55 +0000 (16:00 +0100)
In many cases certficates are distrusted by serial+issuer. Make sure
this works, and fix various cases where we weren't generating
compat NSS objects and compat trust assertions for these types
of input.

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

index 87e16b2507b433cf54862f8c0824d7288b65c256..65aa5ddd1165c596e4744f43aef4deabc5d6bf55 100644 (file)
@@ -1052,19 +1052,19 @@ replace_nss_trust_object (p11_builder *builder,
                           const char **rejects)
 {
        CK_ATTRIBUTE *attrs = NULL;
+       CK_ATTRIBUTE *match = NULL;
        CK_TRUST allow;
        CK_RV rv;
 
        CK_OBJECT_CLASS klassv = CKO_NSS_TRUST;
        CK_BYTE sha1v[P11_CHECKSUM_SHA1_LENGTH];
        CK_BYTE md5v[P11_CHECKSUM_MD5_LENGTH];
-       CK_BBOOL generated = CK_FALSE;
+       CK_BBOOL generatedv = CK_FALSE;
        CK_BBOOL falsev = CK_FALSE;
-       CK_BBOOL truev = CK_TRUE;
 
        CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) };
        CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &falsev, sizeof (falsev) };
-       CK_ATTRIBUTE autogen = { CKA_X_GENERATED, &truev, sizeof (truev) };
+       CK_ATTRIBUTE generated = { CKA_X_GENERATED, &generatedv, sizeof (generatedv) };
        CK_ATTRIBUTE invalid = { CKA_INVALID, };
 
        CK_ATTRIBUTE md5_hash = { CKA_CERT_MD5_HASH, md5v, sizeof (md5v) };
@@ -1078,69 +1078,82 @@ replace_nss_trust_object (p11_builder *builder,
        CK_ATTRIBUTE_PTR issuer;
        CK_ATTRIBUTE_PTR serial_number;
 
-       void *der;
-       size_t der_len;
-
-       CK_ATTRIBUTE match[] = {
-               { CKA_CERT_SHA1_HASH, sha1v, sizeof (sha1v) },
-               { CKA_CLASS, &klassv, sizeof (klassv) },
-               { CKA_X_GENERATED, &generated, sizeof (generated) },
-               { CKA_INVALID }
-       };
+       void *value;
+       size_t length;
 
-       /* Setup the hashes of the DER certificate value */
-       der = p11_attrs_find_value (cert, CKA_VALUE, &der_len);
-       return_if_fail (der != NULL);
-       p11_checksum_md5 (md5v, der, der_len, NULL);
-       p11_checksum_sha1 (sha1v, der, der_len, NULL);
+       issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
+       serial_number = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
+       value = p11_attrs_find_value (cert, CKA_VALUE, &length);
 
-       /* If there is a non-auto-generated NSS trust object, then step away */
-       generated = CK_FALSE;
-       if (p11_index_find (index, match))
+       if (!issuer && !serial_number && !value) {
+               p11_debug ("can't generate nss trust object for certificate without issuer+serial or value");
                return;
+       }
 
-       /* Copy all of the following attributes from certificate */
-       id = p11_attrs_find_valid (cert, CKA_ID);
-       return_if_fail (id != NULL);
-       subject = p11_attrs_find_valid (cert, CKA_SUBJECT);
-       if (subject == NULL)
-               subject = &invalid;
-       issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
-       if (issuer == NULL)
+       if (value == NULL) {
+               md5_hash.type = CKA_INVALID;
+               sha1_hash.type = CKA_INVALID;
+       } else {
+               p11_checksum_md5 (md5v, value, length, NULL);
+               p11_checksum_sha1 (sha1v, value, length, NULL);
+       }
+       if (!issuer)
                issuer = &invalid;
-       serial_number = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
-       if (serial_number == NULL)
+       if (!serial_number)
                serial_number = &invalid;
 
-       /* Try to use the same label */
-       label = p11_attrs_find_valid (cert, CKA_LABEL);
-       if (label == NULL)
-               label = &invalid;
+       match = p11_attrs_build (NULL, issuer, serial_number, sha1_hash,
+                                &generated, &klass, NULL);
+       return_if_fail (match != NULL);
 
-       attrs = p11_attrs_build (NULL, &klass, &modifiable, id, label,
-                                subject, issuer, serial_number, &md5_hash, &sha1_hash,
-                                &step_up_approved, &autogen, NULL);
-       return_if_fail (attrs != NULL);
+       /* If we find a non-generated object, then don't generate */
+       if (p11_index_find (index, match)) {
+               p11_debug ("not generating nss trust object because one already exists");
+               attrs = NULL;
 
-       /* Calculate the default allow trust */
-       if (distrust)
-               allow = CKT_NSS_NOT_TRUSTED;
-       else if (trust && authority)
-               allow = CKT_NSS_TRUSTED_DELEGATOR;
-       else if (trust)
-               allow = CKT_NSS_TRUSTED;
-       else
-               allow = CKT_NSS_TRUST_UNKNOWN;
+       } else {
+               generatedv = CK_TRUE;
+               match = p11_attrs_build (match, &generated, NULL);
+               return_if_fail (match != NULL);
+
+               /* Copy all of the following attributes from certificate */
+               id = p11_attrs_find_valid (cert, CKA_ID);
+               if (id == NULL)
+                       id = &invalid;
+               subject = p11_attrs_find_valid (cert, CKA_SUBJECT);
+               if (subject == NULL)
+                       subject = &invalid;
+               label = p11_attrs_find_valid (cert, CKA_LABEL);
+               if (label == NULL)
+                       label = &invalid;
+
+               attrs = p11_attrs_dup (match);
+               return_if_fail (attrs != NULL);
 
-       attrs = build_trust_object_ku (builder, index, cert, attrs, allow);
-       return_if_fail (attrs != NULL);
+               attrs = p11_attrs_build (attrs, &klass, &modifiable, id, label,
+                                        subject, issuer, serial_number,
+                                        &md5_hash, &sha1_hash, &step_up_approved, NULL);
+               return_if_fail (attrs != NULL);
 
-       attrs = build_trust_object_eku (attrs, allow, purposes, rejects);
-       return_if_fail (attrs != NULL);
+               /* Calculate the default allow trust */
+               if (distrust)
+                       allow = CKT_NSS_NOT_TRUSTED;
+               else if (trust && authority)
+                       allow = CKT_NSS_TRUSTED_DELEGATOR;
+               else if (trust)
+                       allow = CKT_NSS_TRUSTED;
+               else
+                       allow = CKT_NSS_TRUST_UNKNOWN;
+
+               attrs = build_trust_object_ku (builder, index, cert, attrs, allow);
+               return_if_fail (attrs != NULL);
+
+               attrs = build_trust_object_eku (attrs, allow, purposes, rejects);
+               return_if_fail (attrs != NULL);
+       }
 
-       /* Replace related generated objects with this new one */
-       generated = CK_TRUE;
-       rv = p11_index_replace (index, match, CKA_CERT_MD5_HASH, attrs);
+       /* Replace related generated object with this new one */
+       rv = p11_index_replace (index, match, CKA_INVALID, attrs);
        return_if_fail (rv == CKR_OK);
 }
 
@@ -1170,16 +1183,33 @@ build_assertions (p11_array *array,
        CK_ATTRIBUTE *attrs;
        int i;
 
-       label = p11_attrs_find_valid (cert, CKA_LABEL);
-       if (label == NULL)
-               label = &invalid;
+       if (type == CKT_X_DISTRUSTED_CERTIFICATE) {
+               value = &invalid;
+               issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
+               serial = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
 
-       id = p11_attrs_find_valid (cert, CKA_ID);
-       issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
-       serial = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
-       value = p11_attrs_find_valid (cert, CKA_VALUE);
+               if (!issuer || !serial) {
+                       p11_debug ("not building negative trust assertion for certificate without serial or issuer");
+                       return;
+               }
 
-       return_if_fail (id != NULL && issuer != NULL && serial != NULL && value != NULL);
+       } else {
+               issuer = &invalid;
+               serial = &invalid;
+               value = p11_attrs_find_valid (cert, CKA_VALUE);
+
+               if (value == NULL) {
+                       p11_debug ("not building positive trust assertion for certificate without value");
+                       return;
+               }
+       }
+
+       label = p11_attrs_find (cert, CKA_LABEL);
+       if (label == NULL)
+               label = &invalid;
+       id = p11_attrs_find (cert, CKA_ID);
+       if (id == NULL)
+               id = &invalid;
 
        for (i = 0; oids[i] != NULL; i++) {
                purpose.pValue = (void *)oids[i];
@@ -1196,7 +1226,8 @@ build_assertions (p11_array *array,
 }
 
 static void
-build_trust_assertions (p11_array *built,
+build_trust_assertions (p11_array *positives,
+                        p11_array *negatives,
                         CK_ATTRIBUTE *cert,
                         CK_BBOOL trust,
                         CK_BBOOL distrust,
@@ -1217,17 +1248,17 @@ build_trust_assertions (p11_array *built,
        };
 
        /* Build assertions for anything that's explicitly rejected */
-       if (rejects) {
-               build_assertions (built, cert, CKT_X_DISTRUSTED_CERTIFICATE, rejects);
+       if (rejects && negatives) {
+               build_assertions (negatives, cert, CKT_X_DISTRUSTED_CERTIFICATE, rejects);
        }
 
-       if (distrust) {
+       if (distrust && negatives) {
                /*
                 * Trust assertions are defficient in that they don't blacklist a certificate
                 * for any purposes. So we just have to go wild and write out a bunch of
                 * assertions for all our known purposes.
                 */
-               build_assertions (built, cert, CKT_X_DISTRUSTED_CERTIFICATE, all_purposes);
+               build_assertions (negatives, cert, CKT_X_DISTRUSTED_CERTIFICATE, all_purposes);
        }
 
        /*
@@ -1235,13 +1266,13 @@ build_trust_assertions (p11_array *built,
         * certificates where not an authority.
         */
 
-       if (trust && authority) {
+       if (trust && authority && positives) {
                if (purposes) {
                        /* If purposes explicitly set, then anchor for those purposes */
-                       build_assertions (built, cert, CKT_X_ANCHORED_CERTIFICATE, purposes);
+                       build_assertions (positives, cert, CKT_X_ANCHORED_CERTIFICATE, purposes);
                } else {
                        /* If purposes not-explicitly set, then anchor for all known */
-                       build_assertions (built, cert, CKT_X_ANCHORED_CERTIFICATE, all_purposes);
+                       build_assertions (positives, cert, CKT_X_ANCHORED_CERTIFICATE, all_purposes);
                }
        }
 }
@@ -1257,31 +1288,57 @@ replace_trust_assertions (p11_builder *builder,
                           const char **rejects)
 {
        CK_OBJECT_CLASS assertion = CKO_X_TRUST_ASSERTION;
-       CK_BBOOL generated = CK_FALSE;
+       CK_BBOOL generated = CK_TRUE;
+       p11_array *positives = NULL;
+       p11_array *negatives = NULL;
        CK_ATTRIBUTE *value;
-       p11_array *built;
+       CK_ATTRIBUTE *issuer;
+       CK_ATTRIBUTE *serial;
        CK_RV rv;
 
-       CK_ATTRIBUTE match[] = {
+       CK_ATTRIBUTE match_positive[] = {
                { CKA_VALUE, },
                { CKA_CLASS, &assertion, sizeof (assertion) },
                { CKA_X_GENERATED, &generated, sizeof (generated) },
                { CKA_INVALID }
        };
 
+       CK_ATTRIBUTE match_negative[] = {
+               { CKA_ISSUER, },
+               { CKA_SERIAL_NUMBER, },
+               { CKA_CLASS, &assertion, sizeof (assertion) },
+               { CKA_X_GENERATED, &generated, sizeof (generated) },
+               { CKA_INVALID }
+       };
+
        value = p11_attrs_find_valid (cert, CKA_VALUE);
-       return_if_fail (value != NULL);
+       if (value) {
+               positives = p11_array_new (NULL);
+               memcpy (match_positive, value, sizeof (CK_ATTRIBUTE));
+       }
 
-       built = p11_array_new (NULL);
-       build_trust_assertions (built, cert, trust, distrust, authority, purposes, rejects);
+       issuer = p11_attrs_find_valid (cert, CKA_ISSUER);
+       serial = p11_attrs_find_valid (cert, CKA_SERIAL_NUMBER);
+       if (issuer && serial) {
+               negatives = p11_array_new (NULL);
+               memcpy (match_negative + 0, issuer, sizeof (CK_ATTRIBUTE));
+               memcpy (match_negative + 1, serial, sizeof (CK_ATTRIBUTE));
+       }
 
-       generated = CK_TRUE;
-       match[0].pValue = value->pValue;
-       match[0].ulValueLen = value->ulValueLen;
-       rv = p11_index_replace_all (index, match, CKA_X_PURPOSE, built);
-       return_if_fail (rv == CKR_OK);
+       build_trust_assertions (positives, negatives, cert, trust, distrust,
+                               authority, purposes, rejects);
+
+       if (positives) {
+               rv = p11_index_replace_all (index, match_positive, CKA_X_PURPOSE, positives);
+               return_if_fail (rv == CKR_OK);
+               p11_array_free (positives);
+       }
 
-       p11_array_free (built);
+       if (negatives) {
+               rv = p11_index_replace_all (index, match_negative, CKA_X_PURPOSE, negatives);
+               return_if_fail (rv == CKR_OK);
+               p11_array_free (negatives);
+       }
 }
 
 static void
@@ -1289,30 +1346,12 @@ remove_trust_and_assertions (p11_builder *builder,
                              p11_index *index,
                              CK_ATTRIBUTE *attrs)
 {
-       CK_BBOOL truev = CK_TRUE;
-       CK_ATTRIBUTE *id;
-       p11_array *array;
-       CK_RV rv;
-
-       CK_ATTRIBUTE match[] = {
-               { CKA_ID, },
-               { CKA_X_GENERATED, &truev, sizeof (truev) },
-               { CKA_INVALID }
-       };
-
-       id = p11_attrs_find_valid (attrs, CKA_ID);
-       return_if_fail (id != NULL);
-
-       /* An empty array of replacements */
-       array = p11_array_new (NULL);
-
-       /* Remove all related NSS trust objects */
-       match[0].pValue = id->pValue;
-       match[0].ulValueLen = id->ulValueLen;
-       rv = p11_index_replace_all (index, match, CKA_INVALID, array);
-       return_if_fail (rv == CKR_OK);
-
-       p11_array_free (array);
+       replace_nss_trust_object (builder, index, attrs,
+                                 CK_FALSE, CK_FALSE, CK_FALSE,
+                                 NULL, NULL);
+       replace_trust_assertions (builder, index, attrs,
+                                 CK_FALSE, CK_FALSE, CK_FALSE,
+                                 NULL, NULL);
 }
 
 static void
@@ -1392,9 +1431,7 @@ replace_compat_for_cert (p11_builder *builder,
 {
        static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE;
        static CK_CERTIFICATE_TYPE x509 = CKC_X_509;
-
        CK_ATTRIBUTE *value;
-       CK_ATTRIBUTE *id;
 
        CK_ATTRIBUTE match[] = {
                { CKA_VALUE, },
@@ -1403,20 +1440,18 @@ replace_compat_for_cert (p11_builder *builder,
                { CKA_INVALID }
        };
 
-       value = p11_attrs_find_valid (attrs, CKA_VALUE);
-       id = p11_attrs_find_valid (attrs, CKA_ID);
-       if (value == NULL || id == NULL)
-               return;
-
        /*
         * If this certificate is going away, then find duplicate. In this
         * case all the trust assertions are recalculated with this new
         * certificate in mind.
         */
        if (handle == 0) {
-               match[0].pValue = value->pValue;
-               match[0].ulValueLen = value->ulValueLen;
-               handle = p11_index_find (index, match);
+               value = p11_attrs_find_valid (attrs, CKA_VALUE);
+               if (value != NULL) {
+                       match[0].pValue = value->pValue;
+                       match[0].ulValueLen = value->ulValueLen;
+                       handle = p11_index_find (index, match);
+               }
                if (handle != 0)
                        attrs = p11_index_lookup (index, handle);
        }
index 786d840ae62c820a2ee579f346daf17d29816575..17370bcf11295836aedce655fbb819e95c505557 100644 (file)
@@ -412,7 +412,8 @@ p11_index_replace (p11_index *index,
                    CK_ATTRIBUTE *replace)
 {
        return_val_if_fail (index != NULL, CKR_GENERAL_ERROR);
-       return index_replacev (index, match, key, &replace, 1);
+       return index_replacev (index, match, key, &replace,
+                              replace ? 1 : 0);
 }
 
 CK_RV
index 3d3d067ebe1dab74da1e744f68c1ffc603c5519e..536d7dc930bfa69e40ff1a9c21ef098bec174e05 100644 (file)
@@ -889,6 +889,86 @@ test_modify_not_modifiable (CuTest *cu)
        teardown (cu);
 }
 
+static CK_ATTRIBUTE cacert3_assert_distrust_server[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, sizeof (P11_OID_SERVER_AUTH_STR) - 1 },
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
+static CK_ATTRIBUTE cacert3_assert_distrust_client[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, sizeof (P11_OID_CLIENT_AUTH_STR) - 1},
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
+static CK_ATTRIBUTE cacert3_assert_distrust_code[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_CODE_SIGNING_STR, sizeof (P11_OID_CODE_SIGNING_STR) - 1},
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
+static CK_ATTRIBUTE cacert3_assert_distrust_email[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, sizeof (P11_OID_EMAIL_PROTECTION_STR) - 1},
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
+static CK_ATTRIBUTE cacert3_assert_distrust_system[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_END_SYSTEM_STR, sizeof (P11_OID_IPSEC_END_SYSTEM_STR) - 1},
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
+static CK_ATTRIBUTE cacert3_assert_distrust_tunnel[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_TUNNEL_STR, sizeof (P11_OID_IPSEC_TUNNEL_STR) - 1},
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
+static CK_ATTRIBUTE cacert3_assert_distrust_user[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_USER_STR, sizeof (P11_OID_IPSEC_USER_STR) - 1},
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
+static CK_ATTRIBUTE cacert3_assert_distrust_time[] = {
+       { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
+       { CKA_X_PURPOSE, (void *)P11_OID_TIME_STAMPING_STR, sizeof (P11_OID_TIME_STAMPING_STR) - 1},
+       { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+       { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
+       { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
+       { CKA_ID, "cacert3", 7 },
+       { CKA_INVALID },
+};
+
 static void
 test_changed_trusted_certificate (CuTest *cu)
 {
@@ -985,17 +1065,6 @@ test_changed_trusted_certificate (CuTest *cu)
                { CKA_INVALID },
        };
 
-       static CK_ATTRIBUTE email_distrust_assertion[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, sizeof (P11_OID_EMAIL_PROTECTION_STR) - 1 },
-               { CKA_LABEL, "Custom Label", 12 },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
-               { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "cacert3", 7 },
-               { CKA_INVALID },
-       };
-
        /*
         * We should get an NSS trust object and various assertions here.
         * The first two attributes of each object are enough to look it up,
@@ -1004,7 +1073,7 @@ test_changed_trusted_certificate (CuTest *cu)
 
        CK_ATTRIBUTE *expected[] = {
                nss_trust_server_and_client_distrust_email,
-               email_distrust_assertion,
+               cacert3_assert_distrust_email,
                server_anchor_assertion,
                client_anchor_assertion,
                NULL,
@@ -1046,7 +1115,7 @@ test_changed_trusted_certificate (CuTest *cu)
 }
 
 static void
-test_changed_distrusted (CuTest *cu)
+test_changed_distrust_value (CuTest *cu)
 {
        CK_ATTRIBUTE distrust_cert[] = {
                { CKA_CLASS, &certificate, sizeof (certificate), },
@@ -1057,7 +1126,7 @@ test_changed_distrusted (CuTest *cu)
                { CKA_TRUSTED, &falsev, sizeof (falsev) },
                { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
                { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) },
-               { CKA_ID, "the id", 6 },
+               { CKA_ID, "cacert3", 7 },
                { CKA_INVALID },
        };
 
@@ -1066,7 +1135,7 @@ test_changed_distrusted (CuTest *cu)
                { CKA_OBJECT_ID, (void *)P11_OID_EXTENDED_KEY_USAGE, sizeof (P11_OID_EXTENDED_KEY_USAGE) },
                { CKA_X_CRITICAL, &truev, sizeof (truev) },
                { CKA_VALUE, "\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x99\x77\x06\x0a\x10", 14 },
-               { CKA_ID, "the id", 6 },
+               { CKA_ID, "cacert3", 7 },
                { CKA_INVALID },
        };
 
@@ -1075,13 +1144,13 @@ test_changed_distrusted (CuTest *cu)
                { CKA_OBJECT_ID, (void *)P11_OID_OPENSSL_REJECT, sizeof (P11_OID_OPENSSL_REJECT) },
                { CKA_X_CRITICAL, &falsev, sizeof (falsev) },
                { CKA_VALUE, "\x30\x0a\x06\x08\x2b\x06\x01\x05\x05\x07\x03\x02", 12 },
-               { CKA_ID, "the id", 6 },
+               { CKA_ID, "cacert3", 7 },
                { CKA_INVALID },
        };
 
        CK_ATTRIBUTE nss_trust_nothing[] = {
                { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
-               { CKA_ID, "the id", 6 },
+               { CKA_ID, "cacert3", 7 },
                { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
                { CKA_CERT_MD5_HASH, "\xf7\x25\x12\x82\x4e\x67\xb5\xd0\x8d\x92\xb7\x7c\x0b\x86\x7a\x42", 16 },
                { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) },
@@ -1105,84 +1174,94 @@ test_changed_distrusted (CuTest *cu)
                { CKA_INVALID, }
        };
 
-       CK_ATTRIBUTE server_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
-               { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
-               { CKA_INVALID },
-       };
+       /*
+        * We should get an NSS trust object and various assertions here.
+        * The first two attributes of each object are enough to look it up,
+        * and then we check the rest of the attributes match.
+        */
 
-       CK_ATTRIBUTE client_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
-               { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
-               { CKA_INVALID },
+       CK_ATTRIBUTE *expected[] = {
+               nss_trust_nothing,
+               cacert3_assert_distrust_server,
+               cacert3_assert_distrust_client,
+               cacert3_assert_distrust_code,
+               cacert3_assert_distrust_email,
+               cacert3_assert_distrust_system,
+               cacert3_assert_distrust_tunnel,
+               cacert3_assert_distrust_user,
+               cacert3_assert_distrust_time,
+               NULL
        };
 
-       CK_ATTRIBUTE code_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_CODE_SIGNING_STR, strlen (P11_OID_CODE_SIGNING_STR) },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
-               { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
-               { CKA_INVALID },
-       };
+       CK_OBJECT_HANDLE handle;
+       CK_ATTRIBUTE *attrs;
+       CK_RV rv;
+       int i;
 
-       CK_ATTRIBUTE email_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
-               { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
-               { CKA_INVALID },
-       };
+       setup (cu);
 
-       CK_ATTRIBUTE ipsec_system_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_END_SYSTEM_STR, strlen (P11_OID_IPSEC_END_SYSTEM_STR) },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
-               { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
-               { CKA_INVALID },
-       };
+       /*
+        * A distrusted certificate with a value, plus some extra
+        * extensions (which should be ignored).
+        */
+       p11_index_batch (test.index);
+       rv = p11_index_take (test.index, p11_attrs_dup (distrust_cert), NULL);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       rv = p11_index_take (test.index, p11_attrs_dup (eku_extension), NULL);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       rv = p11_index_take (test.index, p11_attrs_dup (reject_extension), NULL);
+       CuAssertIntEquals (cu, CKR_OK, rv);
+       p11_index_finish (test.index);
 
-       CK_ATTRIBUTE ipsec_tunnel_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_TUNNEL_STR, strlen (P11_OID_IPSEC_TUNNEL_STR) },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
-               { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
-               { CKA_INVALID },
-       };
+       /* The other objects */
+       for (i = 0; expected[i]; i++) {
+               handle = p11_index_findn (test.index, expected[i], 2);
+               CuAssertTrue (cu, handle != 0);
 
-       CK_ATTRIBUTE ipsec_user_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_USER_STR, strlen (P11_OID_IPSEC_USER_STR) },
-               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+               attrs = p11_index_lookup (test.index, handle);
+               CuAssertPtrNotNull (cu, attrs);
+
+               test_check_attrs (cu, expected[i], attrs);
+       }
+
+       teardown (cu);
+}
+
+static void
+test_changed_distrust_serial (CuTest *cu)
+{
+       CK_ATTRIBUTE distrust_cert[] = {
+               { CKA_CLASS, &certificate, sizeof (certificate), },
                { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
+               { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
+               { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) },
+               { CKA_TRUSTED, &falsev, sizeof (falsev) },
+               { CKA_X_DISTRUSTED, &truev, sizeof (truev) },
+               { CKA_ID, "cacert3", 7 },
                { CKA_INVALID },
        };
 
-       CK_ATTRIBUTE stamping_distrust[] = {
-               { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) },
-               { CKA_X_PURPOSE, (void *)P11_OID_TIME_STAMPING_STR, strlen (P11_OID_TIME_STAMPING_STR) },
+       CK_ATTRIBUTE nss_trust_distrust[] = {
+               { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+               { CKA_ID, "cacert3", 7 },
                { CKA_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) },
                { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) },
-               { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) },
-               { CKA_ID, "the id", 6 },
-               { CKA_INVALID },
+               { CKA_TRUST_SERVER_AUTH, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_CLIENT_AUTH, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_EMAIL_PROTECTION, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_CODE_SIGNING, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_IPSEC_END_SYSTEM, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_IPSEC_TUNNEL, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_IPSEC_USER, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_TIME_STAMPING, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_DIGITAL_SIGNATURE, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_NON_REPUDIATION, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_KEY_ENCIPHERMENT, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_DATA_ENCIPHERMENT, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_KEY_AGREEMENT, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_KEY_CERT_SIGN, &not_trusted, sizeof (not_trusted) },
+               { CKA_TRUST_CRL_SIGN, &not_trusted, sizeof (not_trusted) },
+               { CKA_INVALID, }
        };
 
        /*
@@ -1192,15 +1271,15 @@ test_changed_distrusted (CuTest *cu)
         */
 
        CK_ATTRIBUTE *expected[] = {
-               nss_trust_nothing,
-               server_distrust,
-               client_distrust,
-               code_distrust,
-               email_distrust,
-               ipsec_system_distrust,
-               ipsec_tunnel_distrust,
-               ipsec_user_distrust,
-               stamping_distrust,
+               nss_trust_distrust,
+               cacert3_assert_distrust_server,
+               cacert3_assert_distrust_client,
+               cacert3_assert_distrust_code,
+               cacert3_assert_distrust_email,
+               cacert3_assert_distrust_system,
+               cacert3_assert_distrust_tunnel,
+               cacert3_assert_distrust_user,
+               cacert3_assert_distrust_time,
                NULL
        };
 
@@ -1212,26 +1291,18 @@ test_changed_distrusted (CuTest *cu)
        setup (cu);
 
        /*
-        * A trusted cetrificate, trusted for server and client purposes,
-        * and explicitly rejects the email and timestamping purposes.
+        * A distrusted certificate without a value.
         */
        p11_index_batch (test.index);
        rv = p11_index_take (test.index, p11_attrs_dup (distrust_cert), NULL);
        CuAssertIntEquals (cu, CKR_OK, rv);
-       rv = p11_index_take (test.index, p11_attrs_dup (eku_extension), NULL);
-       CuAssertIntEquals (cu, CKR_OK, rv);
-       rv = p11_index_take (test.index, p11_attrs_dup (reject_extension), NULL);
-       CuAssertIntEquals (cu, CKR_OK, rv);
        p11_index_finish (test.index);
 
-       /* The other objects */
        for (i = 0; expected[i]; i++) {
                handle = p11_index_findn (test.index, expected[i], 2);
                CuAssertTrue (cu, handle != 0);
-
                attrs = p11_index_lookup (test.index, handle);
                CuAssertPtrNotNull (cu, attrs);
-
                test_check_attrs (cu, expected[i], attrs);
        }
 
@@ -1277,6 +1348,14 @@ test_changed_dup_certificates (CuTest *cu)
                { CKA_INVALID, }
        };
 
+       static CK_ATTRIBUTE unknown_nss[] = {
+               { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
+               { CKA_CERT_SHA1_HASH, "\xad\x7c\x3f\x64\xfc\x44\x39\xfe\xf4\xe9\x0b\xe8\xf4\x7c\x6c\xfa\x8a\xad\xfd\xce", 20 },
+               { CKA_TRUST_SERVER_AUTH, &trust_unknown, sizeof (trust_unknown) },
+               { CKA_ID, "cacert3", 7 },
+               { CKA_INVALID, }
+       };
+
        static CK_ATTRIBUTE match_nss[] = {
                { CKA_CLASS, &nss_trust, sizeof (nss_trust), },
                { CKA_ID, "cacert3", 7 },
@@ -1361,12 +1440,12 @@ test_changed_dup_certificates (CuTest *cu)
        handle = p11_index_find (test.index, distrust_assertion);
        CuAssertTrue (cu, handle == 0);
 
-       /* Now remove the original certificate, no more nss/assertions */
+       /* Now remove the original certificate, unknown nss and no assertions */
        rv = p11_index_remove (test.index, handle1);
        CuAssertIntEquals (cu, CKR_OK, rv);
 
-       handle = p11_index_find (test.index, match_nss);
-       CuAssertTrue (cu, handle == 0);
+       handle = p11_index_find (test.index, unknown_nss);
+       CuAssertTrue (cu, handle != 0);
        handle = p11_index_find (test.index, match_assertion);
        CuAssertTrue (cu, handle == 0);
 
@@ -1393,8 +1472,8 @@ test_changed_without_id (CuTest *cu)
        };
 
        /*
-        * A cetrificate without a CKA_ID that's created should not
-        * automatically create any compat objects.
+        * A cetrificate without a CKA_ID that's created should still
+        * automatically create compat objects.
         */
 
        CK_OBJECT_HANDLE handle;
@@ -1409,11 +1488,11 @@ test_changed_without_id (CuTest *cu)
 
        klass = CKO_NSS_TRUST;
        handle = p11_index_find (test.index, match);
-       CuAssertIntEquals (cu, 0, handle);
+       CuAssertTrue (cu, handle != 0);
 
        klass = CKO_X_TRUST_ASSERTION;
        handle = p11_index_find (test.index, match);
-       CuAssertIntEquals (cu, 0, handle);
+       CuAssertTrue (cu, handle != 0);
 
        teardown (cu);
 }
@@ -1570,7 +1649,8 @@ main (void)
        SUITE_ADD_TEST (suite, test_modify_not_modifiable);
 
        SUITE_ADD_TEST (suite, test_changed_trusted_certificate);
-       SUITE_ADD_TEST (suite, test_changed_distrusted);
+       SUITE_ADD_TEST (suite, test_changed_distrust_value);
+       SUITE_ADD_TEST (suite, test_changed_distrust_serial);
        SUITE_ADD_TEST (suite, test_changed_without_id);
        SUITE_ADD_TEST (suite, test_changed_staple_ca);
        SUITE_ADD_TEST (suite, test_changed_staple_ku);