diff options
Diffstat (limited to 'trust')
-rw-r--r-- | trust/Makefile.am | 2 | ||||
-rw-r--r-- | trust/adapter.c | 456 | ||||
-rw-r--r-- | trust/adapter.h (renamed from trust/mozilla.h) | 8 | ||||
-rw-r--r-- | trust/p11-kit-trust.module | 3 | ||||
-rw-r--r-- | trust/parser.c | 5 | ||||
-rw-r--r-- | trust/tests/files/redhat-ca.der | bin | 0 -> 948 bytes | |||
-rw-r--r-- | trust/tests/test-parser.c | 352 |
7 files changed, 783 insertions, 43 deletions
diff --git a/trust/Makefile.am b/trust/Makefile.am index 9f3f119..92c122d 100644 --- a/trust/Makefile.am +++ b/trust/Makefile.am @@ -10,9 +10,9 @@ INCLUDES = \ $(NULL) MODULE_SRCS = \ + adapter.c adapter.h \ parser.c parser.h \ module.c module.h \ - mozilla.c mozilla.h \ session.c session.h \ token.c token.h \ $(NULL) diff --git a/trust/adapter.c b/trust/adapter.c new file mode 100644 index 0000000..c698382 --- /dev/null +++ b/trust/adapter.c @@ -0,0 +1,456 @@ +/* + * Copyright (C) 2012 Red Hat Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Author: Stef Walter <stefw@redhat.com> + */ + +#include "config.h" + +#include "adapter.h" +#include "attrs.h" +#include "checksum.h" +#include "dict.h" +#define P11_DEBUG_FLAG P11_DEBUG_TRUST +#include "debug.h" +#include "library.h" +#include "oid.h" +#include "parser.h" +#include "pkcs11.h" +#include "pkcs11x.h" +#include "x509.h" + +#include <stdlib.h> +#include <string.h> + +static CK_ATTRIBUTE * +build_trust_object_ku (p11_parser *parser, + p11_array *parsing, + CK_ATTRIBUTE *object, + CK_TRUST present) +{ + unsigned char *data = NULL; + unsigned int ku = 0; + p11_dict *defs; + size_t length; + CK_TRUST defawlt; + CK_ULONG i; + + struct { + CK_ATTRIBUTE_TYPE type; + unsigned int ku; + } ku_attribute_map[] = { + { CKA_TRUST_DIGITAL_SIGNATURE, P11_KU_DIGITAL_SIGNATURE }, + { CKA_TRUST_NON_REPUDIATION, P11_KU_NON_REPUDIATION }, + { CKA_TRUST_KEY_ENCIPHERMENT, P11_KU_KEY_ENCIPHERMENT }, + { CKA_TRUST_DATA_ENCIPHERMENT, P11_KU_DATA_ENCIPHERMENT }, + { CKA_TRUST_KEY_AGREEMENT, P11_KU_KEY_AGREEMENT }, + { CKA_TRUST_KEY_CERT_SIGN, P11_KU_KEY_CERT_SIGN }, + { CKA_TRUST_CRL_SIGN, P11_KU_CRL_SIGN }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE attrs[sizeof (ku_attribute_map)]; + + defawlt = present; + + /* If blacklisted, don't even bother looking at extensions */ + if (present != CKT_NETSCAPE_UNTRUSTED) + data = p11_parsing_get_extension (parser, parsing, P11_OID_KEY_USAGE, &length); + + if (data) { + /* + * If the certificate extension was missing, then *all* key + * usages are to be set. If the extension was invalid, then + * fail safe to none of the key usages. + */ + defawlt = CKT_NETSCAPE_TRUST_UNKNOWN; + + defs = p11_parser_get_asn1_defs (parser); + if (!p11_x509_parse_key_usage (defs, data, length, &ku)) + p11_message ("invalid key usage certificate extension"); + free (data); + } + + for (i = 0; ku_attribute_map[i].type != CKA_INVALID; i++) { + attrs[i].type = ku_attribute_map[i].type; + if (data && (ku & ku_attribute_map[i].ku) == ku_attribute_map[i].ku) { + attrs[i].pValue = &present; + attrs[i].ulValueLen = sizeof (present); + } else { + attrs[i].pValue = &defawlt; + attrs[i].ulValueLen = sizeof (defawlt); + } + } + + return p11_attrs_buildn (object, attrs, i); +} + +static CK_ATTRIBUTE * +build_trust_object_eku (p11_parser *parser, + p11_array *parsing, + CK_ATTRIBUTE *object, + CK_TRUST allow, + p11_dict *purposes, + p11_dict *rejects) +{ + CK_TRUST neutral; + CK_TRUST disallow; + CK_ULONG i; + + struct { + CK_ATTRIBUTE_TYPE type; + const char *oid; + } eku_attribute_map[] = { + { CKA_TRUST_SERVER_AUTH, P11_OID_SERVER_AUTH_STR }, + { CKA_TRUST_CLIENT_AUTH, P11_OID_CLIENT_AUTH_STR }, + { CKA_TRUST_CODE_SIGNING, P11_OID_CODE_SIGNING_STR }, + { CKA_TRUST_EMAIL_PROTECTION, P11_OID_EMAIL_PROTECTION_STR }, + { CKA_TRUST_IPSEC_END_SYSTEM, P11_OID_IPSEC_END_SYSTEM_STR }, + { CKA_TRUST_IPSEC_TUNNEL, P11_OID_IPSEC_TUNNEL_STR }, + { CKA_TRUST_IPSEC_USER, P11_OID_IPSEC_USER_STR }, + { CKA_TRUST_TIME_STAMPING, P11_OID_TIME_STAMPING_STR }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE attrs[sizeof (eku_attribute_map)]; + + /* The neutral value is set if an purpose is not present */ + if (allow == CKT_NETSCAPE_UNTRUSTED) + neutral = CKT_NETSCAPE_UNTRUSTED; + + /* If anything explicitly set, then neutral is unknown */ + else if (purposes || rejects) + neutral = CKT_NETSCAPE_TRUST_UNKNOWN; + + /* Otherwise neutral will allow any purpose */ + else + neutral = allow; + + /* The value set if a purpose is explictly rejected */ + disallow = CKT_NETSCAPE_UNTRUSTED; + + for (i = 0; eku_attribute_map[i].type != CKA_INVALID; i++) { + attrs[i].type = eku_attribute_map[i].type; + if (rejects && p11_dict_get (rejects, eku_attribute_map[i].oid)) { + attrs[i].pValue = &disallow; + attrs[i].ulValueLen = sizeof (disallow); + } else if (purposes && p11_dict_get (purposes, eku_attribute_map[i].oid)) { + attrs[i].pValue = &allow; + attrs[i].ulValueLen = sizeof (allow); + } else { + attrs[i].pValue = &neutral; + attrs[i].ulValueLen = sizeof (neutral); + } + } + + return p11_attrs_buildn (object, attrs, i); +} + +static void +build_nss_trust_object (p11_parser *parser, + p11_array *parsing, + CK_ATTRIBUTE *cert, + CK_BBOOL trust, + CK_BBOOL distrust, + CK_BBOOL authority, + p11_dict *purposes, + p11_dict *rejects) +{ + CK_ATTRIBUTE *object = NULL; + CK_TRUST allow; + + CK_OBJECT_CLASS vclass = CKO_NETSCAPE_TRUST; + CK_BYTE vsha1_hash[P11_CHECKSUM_SHA1_LENGTH]; + CK_BYTE vmd5_hash[P11_CHECKSUM_MD5_LENGTH]; + CK_BBOOL vfalse = CK_FALSE; + CK_BBOOL vtrue = CK_TRUE; + + CK_ATTRIBUTE klass = { CKA_CLASS, &vclass, sizeof (vclass) }; + CK_ATTRIBUTE token = { CKA_TOKEN, &vtrue, sizeof (vtrue) }; + CK_ATTRIBUTE private = { CKA_PRIVATE, &vfalse, sizeof (vfalse) }; + CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) }; + CK_ATTRIBUTE invalid = { CKA_INVALID, }; + + CK_ATTRIBUTE md5_hash = { CKA_CERT_MD5_HASH, vmd5_hash, sizeof (vmd5_hash) }; + CK_ATTRIBUTE sha1_hash = { CKA_CERT_SHA1_HASH, vsha1_hash, sizeof (vsha1_hash) }; + + CK_ATTRIBUTE step_up_approved = { CKA_TRUST_STEP_UP_APPROVED, &vfalse, sizeof (vfalse) }; + + CK_ATTRIBUTE_PTR label; + CK_ATTRIBUTE_PTR id; + CK_ATTRIBUTE_PTR der; + CK_ATTRIBUTE_PTR subject; + CK_ATTRIBUTE_PTR issuer; + CK_ATTRIBUTE_PTR serial_number; + + /* Setup the hashes of the DER certificate value */ + der = p11_attrs_find (cert, CKA_VALUE); + return_if_fail (der != NULL); + p11_checksum_md5 (vmd5_hash, der->pValue, der->ulValueLen, NULL); + p11_checksum_sha1 (vsha1_hash, der->pValue, der->ulValueLen, NULL); + + /* Copy all of the following attributes from certificate */ + id = p11_attrs_find (cert, CKA_ID); + return_if_fail (id != NULL); + subject = p11_attrs_find (cert, CKA_SUBJECT); + return_if_fail (subject != NULL); + issuer = p11_attrs_find (cert, CKA_ISSUER); + return_if_fail (issuer != NULL); + serial_number = p11_attrs_find (cert, CKA_SERIAL_NUMBER); + return_if_fail (serial_number != NULL); + + /* Try to use the same label */ + label = p11_attrs_find (cert, CKA_LABEL); + if (label == NULL) + label = &invalid; + + object = p11_attrs_build (NULL, &klass, &token, &private, &modifiable, id, label, + subject, issuer, serial_number, &md5_hash, &sha1_hash, + &step_up_approved, NULL); + return_if_fail (object != NULL); + + /* Calculate the default allow trust */ + if (distrust) + allow = CKT_NETSCAPE_UNTRUSTED; + else if (trust && authority) + allow = CKT_NETSCAPE_TRUSTED_DELEGATOR; + else if (trust) + allow = CKT_NETSCAPE_TRUSTED; + else + allow = CKT_NETSCAPE_TRUST_UNKNOWN; + + object = build_trust_object_ku (parser, parsing, object, allow); + return_if_fail (object != NULL); + + object = build_trust_object_eku (parser, parsing, object, allow, purposes, rejects); + return_if_fail (object != NULL); + + if (!p11_array_push (parsing, object)) + return_if_reached (); +} + +static const char * +yield_oid_from_vec (void **state) +{ + const char **oids = *state; + const char *ret = NULL; + if (*oids != NULL) + ret = *(oids++); + *state = oids; + return ret; +} + +static const char * +yield_oid_from_dict (void **state) +{ + p11_dictiter *iter = *state; + const char *ret = NULL; + if (iter && !p11_dict_next (iter, (void**)&ret, NULL)) + *state = NULL; + return ret; +} + +static void +build_assertions (p11_parser *parser, + p11_array *parsing, + CK_ATTRIBUTE *cert, + CK_X_ASSERTION_TYPE type, + const char * (oid_iter) (void **), + void *oid_state) +{ + CK_OBJECT_CLASS assertion = CKO_X_TRUST_ASSERTION; + CK_BBOOL vtrue = CK_TRUE; + CK_BBOOL vfalse = CK_FALSE; + + CK_ATTRIBUTE klass = { CKA_CLASS, &assertion, sizeof (assertion) }; + CK_ATTRIBUTE token = { CKA_TOKEN, &vtrue, sizeof (vtrue) }; + CK_ATTRIBUTE private = { CKA_PRIVATE, &vfalse, sizeof (vfalse) }; + CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &vfalse, sizeof (vfalse) }; + CK_ATTRIBUTE assertion_type = { CKA_X_ASSERTION_TYPE, &type, sizeof (type) }; + CK_ATTRIBUTE purpose = { CKA_X_PURPOSE, }; + CK_ATTRIBUTE invalid = { CKA_INVALID, }; + + CK_ATTRIBUTE *issuer; + CK_ATTRIBUTE *serial; + CK_ATTRIBUTE *value; + CK_ATTRIBUTE *label; + CK_ATTRIBUTE *id; + CK_ATTRIBUTE *object; + const char *oid_str; + + label = p11_attrs_find (cert, CKA_LABEL); + if (label == NULL) + label = &invalid; + + id = p11_attrs_find (cert, CKA_ID); + issuer = p11_attrs_find (cert, CKA_ISSUER); + serial = p11_attrs_find (cert, CKA_SERIAL_NUMBER); + value = p11_attrs_find (cert, CKA_VALUE); + + return_if_fail (id != NULL && issuer != NULL && serial != NULL && value != NULL); + + for (;;) { + oid_str = (oid_iter) (&oid_state); + if (!oid_str) + break; + + purpose.pValue = (void *)oid_str; + purpose.ulValueLen = strlen (oid_str); + + object = p11_attrs_build (NULL, &klass, &token, &private, &modifiable, + id, label, &assertion_type, &purpose, + issuer, serial, value, NULL); + return_if_fail (object != NULL); + + if (!p11_array_push (parsing, object)) + return_if_reached (); + } +} + +static void +build_trust_assertions (p11_parser *parser, + p11_array *parsing, + CK_ATTRIBUTE *cert, + CK_BBOOL trust, + CK_BBOOL distrust, + CK_BBOOL authority, + p11_dict *purposes, + p11_dict *rejects) +{ + p11_dictiter iter; + + const char *all_purposes[] = { + P11_OID_SERVER_AUTH_STR, + P11_OID_CLIENT_AUTH_STR, + P11_OID_CODE_SIGNING_STR, + P11_OID_EMAIL_PROTECTION_STR, + P11_OID_IPSEC_END_SYSTEM_STR, + P11_OID_IPSEC_TUNNEL_STR, + P11_OID_IPSEC_USER_STR, + P11_OID_TIME_STAMPING_STR, + NULL, + }; + + /* Build assertions for anything that's explicitly rejected */ + if (rejects) { + p11_dict_iterate (rejects, &iter); + build_assertions (parser, parsing, cert, CKT_X_DISTRUSTED_CERTIFICATE, + yield_oid_from_dict, &iter); + } + + if (distrust) { + /* + * 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 (parser, parsing, cert, CKT_X_DISTRUSTED_CERTIFICATE, + yield_oid_from_vec, all_purposes); + } + + /* + * TODO: Build pinned certificate assertions. That is, trusted + * certificates where not an authority. + */ + + if (trust && authority) { + if (purposes) { + /* If purposes explicitly set, then anchor for those purposes */ + p11_dict_iterate (purposes, &iter); + build_assertions (parser, parsing, cert, CKT_X_ANCHORED_CERTIFICATE, + yield_oid_from_dict, &iter); + } else { + /* If purposes not-explicitly set, then anchor for all known */ + build_assertions (parser, parsing, cert, CKT_X_ANCHORED_CERTIFICATE, + yield_oid_from_vec, all_purposes); + } + } +} + +void +p11_adapter_build_objects (p11_parser *parser, + p11_array *parsing) +{ + CK_ATTRIBUTE *cert; + CK_ULONG category; + CK_BBOOL trust = CK_FALSE; + CK_BBOOL distrust = CK_FALSE; + CK_BBOOL authority = CK_FALSE; + p11_dict *purposes = NULL; + p11_dict *rejects = NULL; + unsigned char *data; + p11_dict *defs; + size_t length; + + cert = p11_parsing_get_certificate (parser, parsing); + return_if_fail (cert != NULL); + + /* + * We look up all this information in advance, since it's used + * by the various adapter objects, and we don't have to parse + * it multiple times. + */ + + if (!p11_attrs_find_bool (cert, CKA_TRUSTED, &trust)) + trust = CK_FALSE; + if (!p11_attrs_find_bool (cert, CKA_X_DISTRUSTED, &distrust)) + distrust = CK_FALSE; + if (p11_attrs_find_ulong (cert, CKA_CERTIFICATE_CATEGORY, &category) && category == 2) + authority = CK_TRUE; + + if (!distrust) { + data = p11_parsing_get_extension (parser, parsing, P11_OID_EXTENDED_KEY_USAGE, &length); + if (data) { + defs = p11_parser_get_asn1_defs (parser); + purposes = p11_x509_parse_extended_key_usage (defs, data, length); + if (purposes == NULL) + p11_message ("invalid extended key usage certificate extension"); + free (data); + } + + data = p11_parsing_get_extension (parser, parsing, P11_OID_OPENSSL_REJECT, &length); + if (data) { + defs = p11_parser_get_asn1_defs (parser); + rejects = p11_x509_parse_extended_key_usage (defs, data, length); + if (rejects == NULL) + p11_message ("invalid reject key usage certificate extension"); + free (data); + } + } + + build_nss_trust_object (parser, parsing, cert, trust, distrust, + authority, purposes, rejects); + build_trust_assertions (parser, parsing, cert, trust, distrust, + authority, purposes, rejects); + + p11_dict_free (purposes); + p11_dict_free (rejects); +} diff --git a/trust/mozilla.h b/trust/adapter.h index 8d5b20a..fb4ad4e 100644 --- a/trust/mozilla.h +++ b/trust/adapter.h @@ -35,10 +35,10 @@ #include "array.h" #include "parser.h" -#ifndef P11_MOZILLA_H_ -#define P11_MOZILLA_H_ +#ifndef P11_ADAPTER_H_ +#define P11_ADAPTER_H_ -void p11_mozilla_build_trust_object (p11_parser *parser, +void p11_adapter_build_objects (p11_parser *parser, p11_array *parsing); -#endif +#endif /* P11_ADAPTER_H_ */ diff --git a/trust/p11-kit-trust.module b/trust/p11-kit-trust.module index ad0f254..1a6e94b 100644 --- a/trust/p11-kit-trust.module +++ b/trust/p11-kit-trust.module @@ -4,3 +4,6 @@ module: p11-kit-trust.so # The order in which this is loaded in the trust policy trust-policy: 1 + +# This is for drop-in compatibilty with glib-networking and gcr +x-trust-lookup: pkcs11:library-description=PKCS%2311%20Kit%20Trust%20Module diff --git a/trust/parser.c b/trust/parser.c index d33babb..4f8c407 100644 --- a/trust/parser.c +++ b/trust/parser.c @@ -34,6 +34,7 @@ #include "config.h" +#include "adapter.h" #include "array.h" #include "asn1.h" #include "attrs.h" @@ -43,7 +44,6 @@ #include "dict.h" #include "library.h" #include "module.h" -#include "mozilla.h" #include "oid.h" #include "parser.h" #include "pem.h" @@ -120,7 +120,7 @@ finish_parsing (p11_parser *parser, p11_parsing_update_certificate (parser, parser->parsing); /* Call all the hooks for generating further objects */ - p11_mozilla_build_trust_object (parser, parser->parsing); + p11_adapter_build_objects (parser, parser->parsing); for (i = 0; i < parser->parsing->num; i++) { attrs = parser->parsing->elem[i]; @@ -771,7 +771,6 @@ update_trust_and_distrust (p11_parser *parser, trusted = (parser->flags & P11_PARSE_FLAG_ANCHOR) ? CK_TRUE : CK_FALSE; distrusted = (parser->flags & P11_PARSE_FLAG_BLACKLIST) ? CK_TRUE : CK_FALSE; - /* See if we have a basic constraints extension */ data = p11_parsing_get_extension (parser, parser->parsing, P11_OID_EXTENDED_KEY_USAGE, &length); if (data) { ekus = p11_x509_parse_extended_key_usage (parser->asn1_defs, data, length); diff --git a/trust/tests/files/redhat-ca.der b/trust/tests/files/redhat-ca.der Binary files differnew file mode 100644 index 0000000..affae24 --- /dev/null +++ b/trust/tests/files/redhat-ca.der diff --git a/trust/tests/test-parser.c b/trust/tests/test-parser.c index 80f0f07..a504cab 100644 --- a/trust/tests/test-parser.c +++ b/trust/tests/test-parser.c @@ -159,6 +159,9 @@ test_parse_openssl_trusted (CuTest *cu) CK_TRUST unknown = CKT_NETSCAPE_TRUST_UNKNOWN; CK_OBJECT_CLASS certificate_extension = CKO_X_CERTIFICATE_EXTENSION; CK_OBJECT_CLASS trust_object = CKO_NETSCAPE_TRUST; + CK_OBJECT_CLASS trust_assertion = CKO_X_TRUST_ASSERTION; + CK_X_ASSERTION_TYPE anchored_certificate = CKT_X_ANCHORED_CERTIFICATE; + CK_X_ASSERTION_TYPE distrusted_certificate = CKT_X_DISTRUSTED_CERTIFICATE; CK_BBOOL vtrue = CK_TRUE; CK_BBOOL vfalse = CK_FALSE; @@ -207,10 +210,49 @@ test_parse_openssl_trusted (CuTest *cu) { CKA_INVALID, } }; + CK_ATTRIBUTE server_anchor[] = { + { CKA_LABEL, "Custom Label", 12 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE client_anchor[] = { + { CKA_LABEL, "Custom Label", 12 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE email_distrust[] = { + { CKA_LABEL, "Custom Label", 12 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { 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_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE *expected[] = { + NULL, + eku_extension, + reject_extension, + nss_trust, + email_distrust, + server_anchor, + client_anchor + }; + CK_ATTRIBUTE *cert; CK_ATTRIBUTE *object; CK_BBOOL bval; int ret; + int i; setup (cu); @@ -218,9 +260,16 @@ test_parse_openssl_trusted (CuTest *cu) P11_PARSE_FLAG_ANCHOR, on_parse_object, cu); CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret); - /* Should have gotten certificate, two stapled extensions, and a trust object */ - CuAssertIntEquals (cu, 4, test.objects->num); + /* + * Should have gotten: + * - 1 certificate + * - 2 stapled extensions + * - 1 trust object + * - 3 trust assertions + */ + CuAssertIntEquals (cu, 7, test.objects->num); + /* The certificate */ cert = test.objects->elem[0]; test_check_cacert3_ca (cu, cert, NULL); @@ -232,17 +281,12 @@ test_parse_openssl_trusted (CuTest *cu) CuFail (cu, "missing CKA_X_DISTRUSTED"); CuAssertIntEquals (cu, CK_FALSE, bval); - object = test.objects->elem[1]; - test_check_attrs (cu, eku_extension, object); - test_check_id (cu, cert, object); - - object = test.objects->elem[2]; - test_check_attrs (cu, reject_extension, object); - test_check_id (cu, cert, object); - - object = test.objects->elem[3]; - test_check_attrs (cu, nss_trust, object); - test_check_id (cu, cert, object); + /* The other objects */ + for (i = 1; i < 7; i++) { + object = test.objects->elem[i]; + test_check_attrs (cu, expected[i], object); + test_check_id (cu, cert, object); + } teardown (cu); } @@ -254,6 +298,8 @@ test_parse_openssl_distrusted (CuTest *cu) CK_OBJECT_CLASS certificate_extension = CKO_X_CERTIFICATE_EXTENSION; CK_OBJECT_CLASS trust_object = CKO_NETSCAPE_TRUST; CK_OBJECT_CLASS klass = CKO_CERTIFICATE; + CK_OBJECT_CLASS trust_assertion = CKO_X_TRUST_ASSERTION; + CK_X_ASSERTION_TYPE distrusted_certificate = CKT_X_DISTRUSTED_CERTIFICATE; CK_CERTIFICATE_TYPE x509 = CKC_X_509; CK_ULONG category = 2; /* authority */ CK_BBOOL vtrue = CK_TRUE; @@ -319,9 +365,122 @@ test_parse_openssl_distrusted (CuTest *cu) { CKA_INVALID, } }; + unsigned char red_hat_issuer[] = { + 0x30, 0x81, 0x9d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0e, 0x4e, 0x6f, 0x72, 0x74, 0x68, + 0x20, 0x43, 0x61, 0x72, 0x6f, 0x6c, 0x69, 0x6e, 0x61, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x13, 0x07, 0x52, 0x61, 0x6c, 0x65, 0x69, 0x67, 0x68, 0x31, 0x16, 0x30, 0x14, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x2c, 0x20, 0x49, + 0x6e, 0x63, 0x2e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x02, 0x49, 0x53, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x52, 0x65, 0x64, 0x20, 0x48, + 0x61, 0x74, 0x20, 0x49, 0x53, 0x20, 0x43, 0x41, 0x31, 0x26, 0x30, 0x24, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x17, 0x73, 0x79, 0x73, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x2d, 0x72, 0x64, 0x75, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, + }; + + unsigned char red_hat_serial[] = { + 0x02, 0x01, 0x01, + }; + + CK_ATTRIBUTE server_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE client_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE code_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_CODE_SIGNING_STR, strlen (P11_OID_CODE_SIGNING_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE email_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE ipsec_system_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_END_SYSTEM_STR, strlen (P11_OID_IPSEC_END_SYSTEM_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE ipsec_tunnel_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_TUNNEL_STR, strlen (P11_OID_IPSEC_TUNNEL_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE ipsec_user_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_USER_STR, strlen (P11_OID_IPSEC_USER_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE stamping_distrust[] = { + { CKA_LABEL, "Red Hat Is the CA", 17 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_ISSUER, (void *)red_hat_issuer, sizeof (red_hat_issuer) }, + { CKA_SERIAL_NUMBER, (void *)red_hat_serial, sizeof (red_hat_serial) }, + { CKA_X_ASSERTION_TYPE, &distrusted_certificate, sizeof (distrusted_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_TIME_STAMPING_STR, strlen (P11_OID_TIME_STAMPING_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE *expected[] = { + certificate, + eku_extension, + reject_extension, + nss_trust, + server_distrust, + client_distrust, + code_distrust, + email_distrust, + ipsec_system_distrust, + ipsec_tunnel_distrust, + ipsec_user_distrust, + stamping_distrust, + }; + CK_ATTRIBUTE *cert; CK_ATTRIBUTE *object; int ret; + int i; setup (cu); @@ -333,23 +492,22 @@ test_parse_openssl_distrusted (CuTest *cu) P11_PARSE_FLAG_ANCHOR, on_parse_object, cu); CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret); - /* Should have gotten certificate, one stapled extensions, and a trust object */ - CuAssertIntEquals (cu, 4, test.objects->num); - + /* + * Should have gotten: + * - 1 certificate + * - 2 stapled extensions + * - 1 trust object + * - 8 trust assertions + */ + CuAssertIntEquals (cu, 12, test.objects->num); cert = test.objects->elem[0]; - test_check_attrs (cu, certificate, cert); - - object = test.objects->elem[1]; - test_check_attrs (cu, eku_extension, object); - test_check_id (cu, cert, object); - - object = test.objects->elem[2]; - test_check_attrs (cu, reject_extension, object); - test_check_id (cu, cert, object); - object = test.objects->elem[3]; - test_check_attrs (cu, nss_trust, object); - test_check_id (cu, cert, object); + /* The other objects */ + for (i = 0; i < 12; i++) { + object = test.objects->elem[i]; + test_check_attrs (cu, expected[i], object); + test_check_id (cu, cert, object); + } teardown (cu); } @@ -447,12 +605,129 @@ test_parse_with_key_usage (CuTest *cu) static void test_parse_anchor (CuTest *cu) { + CK_BBOOL vtrue = CK_TRUE; + CK_OBJECT_CLASS trust_object = CKO_NETSCAPE_TRUST; + CK_ATTRIBUTE trusted = { CKA_TRUSTED, &vtrue, sizeof (vtrue) }; + CK_TRUST delegator = CKT_NETSCAPE_TRUSTED_DELEGATOR; + CK_OBJECT_CLASS trust_assertion = CKO_X_TRUST_ASSERTION; + CK_X_ASSERTION_TYPE anchored_certificate = CKT_X_ANCHORED_CERTIFICATE; + + CK_ATTRIBUTE nss_trust[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_object, sizeof (trust_object), }, + { 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_ISSUER, (void *)test_cacert3_ca_issuer, sizeof (test_cacert3_ca_issuer) }, + { CKA_SUBJECT, (void *)test_cacert3_ca_subject, sizeof (test_cacert3_ca_subject) }, + { CKA_SERIAL_NUMBER, (void *)test_cacert3_ca_serial, sizeof (test_cacert3_ca_serial) }, + { CKA_TRUST_SERVER_AUTH, &delegator, sizeof (delegator) }, + { CKA_TRUST_CLIENT_AUTH, &delegator, sizeof (delegator) }, + { CKA_TRUST_EMAIL_PROTECTION, &delegator, sizeof (delegator) }, + { CKA_TRUST_CODE_SIGNING, &delegator, sizeof (delegator) }, + { CKA_TRUST_IPSEC_END_SYSTEM, &delegator, sizeof (delegator) }, + { CKA_TRUST_IPSEC_TUNNEL, &delegator, sizeof (delegator) }, + { CKA_TRUST_IPSEC_USER, &delegator, sizeof (delegator) }, + { CKA_TRUST_TIME_STAMPING, &delegator, sizeof (delegator) }, + { CKA_TRUST_DIGITAL_SIGNATURE, &delegator, sizeof (delegator) }, + { CKA_TRUST_NON_REPUDIATION, &delegator, sizeof (delegator) }, + { CKA_TRUST_KEY_ENCIPHERMENT, &delegator, sizeof (delegator) }, + { CKA_TRUST_DATA_ENCIPHERMENT, &delegator, sizeof (delegator) }, + { CKA_TRUST_KEY_AGREEMENT, &delegator, sizeof (delegator) }, + { CKA_TRUST_KEY_CERT_SIGN, &delegator, sizeof (delegator) }, + { CKA_TRUST_CRL_SIGN, &delegator, sizeof (delegator) }, + { CKA_INVALID, } + }; + + CK_ATTRIBUTE server_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_SERVER_AUTH_STR, strlen (P11_OID_SERVER_AUTH_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE client_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_CLIENT_AUTH_STR, strlen (P11_OID_CLIENT_AUTH_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE code_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_CODE_SIGNING_STR, strlen (P11_OID_CODE_SIGNING_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE email_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_EMAIL_PROTECTION_STR, strlen (P11_OID_EMAIL_PROTECTION_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE ipsec_system_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_END_SYSTEM_STR, strlen (P11_OID_IPSEC_END_SYSTEM_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE ipsec_tunnel_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_TUNNEL_STR, strlen (P11_OID_IPSEC_TUNNEL_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE ipsec_user_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_IPSEC_USER_STR, strlen (P11_OID_IPSEC_USER_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE stamping_anchor[] = { + { CKA_LABEL, "cacert3.der", 11 }, + { CKA_CLASS, &trust_assertion, sizeof (trust_assertion) }, + { CKA_VALUE, (void *)test_cacert3_ca_der, sizeof (test_cacert3_ca_der) }, + { CKA_X_ASSERTION_TYPE, &anchored_certificate, sizeof (anchored_certificate) }, + { CKA_X_PURPOSE, (void *)P11_OID_TIME_STAMPING_STR, strlen (P11_OID_TIME_STAMPING_STR) }, + { CKA_INVALID }, + }; + + CK_ATTRIBUTE *expected[] = { + NULL, + nss_trust, + server_anchor, + client_anchor, + code_anchor, + email_anchor, + ipsec_system_anchor, + ipsec_tunnel_anchor, + ipsec_user_anchor, + stamping_anchor, + }; + CK_ATTRIBUTE *cert; CK_ATTRIBUTE *object; CK_ATTRIBUTE *attr; - CK_BBOOL vtrue = CK_TRUE; - CK_ATTRIBUTE trusted = { CKA_TRUSTED, &vtrue, sizeof (vtrue) }; int ret; + int i; setup (cu); @@ -460,17 +735,24 @@ test_parse_anchor (CuTest *cu) P11_PARSE_FLAG_ANCHOR, on_parse_object, cu); CuAssertIntEquals (cu, P11_PARSE_SUCCESS, ret); - /* Should have gotten a certificate and a trust object */ - CuAssertIntEquals (cu, 2, test.objects->num); + /* + * Should have gotten: + * - 1 certificate + * - 1 trust object + * - 8 trust assertions + */ + CuAssertIntEquals (cu, 10, test.objects->num); cert = test.objects->elem[0]; test_check_cacert3_ca (cu, cert, NULL); - attr = p11_attrs_find (cert, CKA_TRUSTED); test_check_attr (cu, &trusted, attr); - object = test.objects->elem[1]; - test_check_id (cu, cert, object); + for (i = 1; i < 10; i++) { + object = test.objects->elem[i]; + test_check_attrs (cu, expected[i], object); + test_check_id (cu, cert, object); + } teardown (cu); } |