diff options
author | Stef Walter <stefw@gnome.org> | 2013-05-21 21:46:27 +0200 |
---|---|---|
committer | Stef Walter <stefw@gnome.org> | 2013-05-27 10:46:11 +0200 |
commit | 96771f49dc945800ae28c77ff407753cbb995c7f (patch) | |
tree | 595d2bc1779c55b12912c32bd05920bff8d41e36 | |
parent | daf63f2cf66669b3555f2f15498a0aa2db234b2f (diff) |
persist: Support for writing out p11-kit persist files
-rw-r--r-- | trust/parser.c | 10 | ||||
-rw-r--r-- | trust/persist.c | 458 | ||||
-rw-r--r-- | trust/persist.h | 4 | ||||
-rw-r--r-- | trust/tests/test-persist.c | 203 | ||||
-rw-r--r-- | trust/tests/test-trust.c | 2 |
5 files changed, 587 insertions, 90 deletions
diff --git a/trust/parser.c b/trust/parser.c index 7690d6a..21b693b 100644 --- a/trust/parser.c +++ b/trust/parser.c @@ -675,10 +675,14 @@ parse_p11_kit_persist (p11_parser *parser, const unsigned char *data, size_t length) { + CK_BBOOL modifiablev = CK_FALSE; + CK_ATTRIBUTE *attrs; p11_array *objects; bool ret; int i; + CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) }; + if (!p11_persist_magic (data, length)) return P11_PARSE_UNRECOGNIZED; @@ -692,8 +696,10 @@ parse_p11_kit_persist (p11_parser *parser, ret = p11_persist_read (parser->persist, parser->basename, data, length, objects); if (ret) { - for (i = 0; i < objects->num; i++) - sink_object (parser, objects->elem[i]); + for (i = 0; i < objects->num; i++) { + attrs = p11_attrs_build (objects->elem[i], &modifiable, NULL); + sink_object (parser, attrs); + } } p11_array_free (objects); diff --git a/trust/persist.c b/trust/persist.c index 69af697..ad80683 100644 --- a/trust/persist.c +++ b/trust/persist.c @@ -41,12 +41,15 @@ #include "lexer.h" #include "pem.h" #include "persist.h" +#include "pkcs11.h" +#include "pkcs11x.h" #include "url.h" #include "basic.asn.h" #include <libtasn1.h> +#include <assert.h> #include <stdlib.h> #include <string.h> @@ -55,12 +58,6 @@ struct _p11_persist { p11_dict *constants; node_asn *asn1_defs; - - /* Used during parsing */ - p11_lexer lexer; - CK_ATTRIBUTE *attrs; - bool result; - bool skip; }; bool @@ -127,6 +124,20 @@ parse_string (p11_lexer *lexer, return true; } +static void +format_string (CK_ATTRIBUTE *attr, + p11_buffer *buf) +{ + const unsigned char *value; + + assert (attr->ulValueLen != CK_UNAVAILABLE_INFORMATION); + + p11_buffer_add (buf, "\"", 1); + value = attr->pValue; + p11_url_encode (value, value + attr->ulValueLen, P11_URL_VERBATIM, buf); + p11_buffer_add (buf, "\"", 1); +} + static bool parse_bool (p11_lexer *lexer, CK_ATTRIBUTE *attr) @@ -152,6 +163,56 @@ parse_bool (p11_lexer *lexer, } static bool +format_bool (CK_ATTRIBUTE *attr, + p11_buffer *buf) +{ + const CK_BBOOL *value; + + if (attr->ulValueLen != sizeof (CK_BBOOL)) + return false; + + switch (attr->type) { + case CKA_TOKEN: + case CKA_PRIVATE: + case CKA_TRUSTED: + case CKA_SENSITIVE: + case CKA_ENCRYPT: + case CKA_DECRYPT: + case CKA_WRAP: + case CKA_UNWRAP: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_DERIVE: + case CKA_EXTRACTABLE: + case CKA_LOCAL: + case CKA_NEVER_EXTRACTABLE: + case CKA_ALWAYS_SENSITIVE: + case CKA_MODIFIABLE: + case CKA_SECONDARY_AUTH: + case CKA_ALWAYS_AUTHENTICATE: + case CKA_WRAP_WITH_TRUSTED: + case CKA_RESET_ON_INIT: + case CKA_HAS_RESET: + case CKA_COLOR: + break; + default: + return false; + } + + value = attr->pValue; + if (*value == CK_TRUE) + p11_buffer_add (buf, "true", -1); + else if (*value == CK_FALSE) + p11_buffer_add (buf, "false", -1); + else + return false; + + return true; +} + +static bool parse_ulong (p11_lexer *lexer, CK_ATTRIBUTE *attr) { @@ -172,6 +233,66 @@ parse_ulong (p11_lexer *lexer, } static bool +format_ulong (CK_ATTRIBUTE *attr, + p11_buffer *buf) +{ + char string[sizeof (CK_ULONG) * 4]; + const CK_ULONG *value; + + if (attr->ulValueLen != sizeof (CK_ULONG)) + return false; + + switch (attr->type) { + case CKA_CERTIFICATE_CATEGORY: + case CKA_CERTIFICATE_TYPE: + case CKA_CLASS: + case CKA_JAVA_MIDP_SECURITY_DOMAIN: + case CKA_KEY_GEN_MECHANISM: + case CKA_KEY_TYPE: + case CKA_MECHANISM_TYPE: + case CKA_MODULUS_BITS: + case CKA_PRIME_BITS: + case CKA_SUB_PRIME_BITS: + case CKA_VALUE_BITS: + case CKA_VALUE_LEN: + case CKA_TRUST_DIGITAL_SIGNATURE: + case CKA_TRUST_NON_REPUDIATION: + case CKA_TRUST_KEY_ENCIPHERMENT: + case CKA_TRUST_DATA_ENCIPHERMENT: + case CKA_TRUST_KEY_AGREEMENT: + case CKA_TRUST_KEY_CERT_SIGN: + case CKA_TRUST_CRL_SIGN: + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_CODE_SIGNING: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_IPSEC_END_SYSTEM: + case CKA_TRUST_IPSEC_TUNNEL: + case CKA_TRUST_IPSEC_USER: + case CKA_TRUST_TIME_STAMPING: + case CKA_TRUST_STEP_UP_APPROVED: + case CKA_X_ASSERTION_TYPE: + case CKA_AUTH_PIN_FLAGS: + case CKA_HW_FEATURE_TYPE: + case CKA_PIXEL_X: + case CKA_PIXEL_Y: + case CKA_RESOLUTION: + case CKA_CHAR_ROWS: + case CKA_CHAR_COLUMNS: + case CKA_BITS_PER_PIXEL: + break; + default: + return false; + } + + value = attr->pValue; + snprintf (string, sizeof (string), "%lu", *value); + + p11_buffer_add (buf, string, -1); + return true; +} + +static bool parse_constant (p11_persist *persist, p11_lexer *lexer, CK_ATTRIBUTE *attr) @@ -190,6 +311,70 @@ parse_constant (p11_persist *persist, return true; } +static bool +format_constant (CK_ATTRIBUTE *attr, + p11_buffer *buf) +{ + const p11_constant *table; + const CK_ULONG *value; + const char *nick; + + if (attr->ulValueLen != sizeof (CK_ULONG)) + return false; + + switch (attr->type) { + case CKA_TRUST_DIGITAL_SIGNATURE: + case CKA_TRUST_NON_REPUDIATION: + case CKA_TRUST_KEY_ENCIPHERMENT: + case CKA_TRUST_DATA_ENCIPHERMENT: + case CKA_TRUST_KEY_AGREEMENT: + case CKA_TRUST_KEY_CERT_SIGN: + case CKA_TRUST_CRL_SIGN: + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_CODE_SIGNING: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_IPSEC_END_SYSTEM: + case CKA_TRUST_IPSEC_TUNNEL: + case CKA_TRUST_IPSEC_USER: + case CKA_TRUST_TIME_STAMPING: + table = p11_constant_trusts; + break; + case CKA_CLASS: + table = p11_constant_classes; + break; + case CKA_CERTIFICATE_TYPE: + table = p11_constant_certs; + break; + case CKA_KEY_TYPE: + table = p11_constant_keys; + break; + case CKA_X_ASSERTION_TYPE: + table = p11_constant_asserts; + break; + case CKA_CERTIFICATE_CATEGORY: + table = p11_constant_categories; + break; + case CKA_KEY_GEN_MECHANISM: + case CKA_MECHANISM_TYPE: + table = p11_constant_mechanisms; + break; + default: + table = NULL; + }; + + if (!table) + return false; + + value = attr->pValue; + nick = p11_constant_nick (table, *value); + + if (!nick) + return false; + + p11_buffer_add (buf, nick, -1); + return true; +} static bool parse_oid (p11_persist *persist, @@ -249,6 +434,60 @@ parse_oid (p11_persist *persist, } static bool +format_oid (p11_persist *persist, + CK_ATTRIBUTE *attr, + p11_buffer *buf) +{ + char message[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = { 0, }; + node_asn *asn; + char *data; + int len; + int ret; + + if (attr->type != CKA_OBJECT_ID) + return false; + + if (!persist->asn1_defs) { + ret = asn1_array2tree (basic_asn1_tab, &persist->asn1_defs, message); + if (ret != ASN1_SUCCESS) { + p11_debug_precond ("failed to load BASIC definitions: %s: %s\n", + asn1_strerror (ret), message); + return false; + } + } + + ret = asn1_create_element (persist->asn1_defs, "BASIC.ObjectIdentifier", &asn); + if (ret != ASN1_SUCCESS) { + p11_debug_precond ("failed to create ObjectIdentifier element: %s\n", + asn1_strerror (ret)); + return false; + } + + ret = asn1_der_decoding (&asn, attr->pValue, attr->ulValueLen, message); + if (ret != ASN1_SUCCESS) { + p11_debug_precond ("invalid oid value: %s", message); + return false; + } + + len = 0; + ret = asn1_read_value (asn, "", NULL, &len); + return_val_if_fail (ret == ASN1_MEM_ERROR, false); + + data = calloc (len + 1, 1); + return_val_if_fail (data != NULL, false); + + ret = asn1_read_value (asn, "", data, &len); + return_val_if_fail (ret == ASN1_SUCCESS, false); + + asn1_delete_structure (&asn); + + p11_buffer_add (buf, data, len - 1); + free (data); + + return true; +} + +static bool parse_value (p11_persist *persist, p11_lexer *lexer, CK_ATTRIBUTE *attr) @@ -260,16 +499,41 @@ parse_value (p11_persist *persist, parse_oid (persist, lexer, attr); } +static void +format_value (p11_persist *persist, + CK_ATTRIBUTE *attr, + p11_buffer *buf) +{ + assert (attr->ulValueLen != CK_UNAVAILABLE_INFORMATION); + + if (format_bool (attr, buf) || + format_constant (attr, buf) || + format_ulong (attr, buf) || + format_oid (persist, attr, buf)) + return; + + /* Everything else as string */ + format_string (attr, buf); +} + static bool field_to_attribute (p11_persist *persist, - p11_lexer *lexer) + p11_lexer *lexer, + CK_ATTRIBUTE **attrs) { CK_ATTRIBUTE attr = { 0, }; + char *end; - attr.type = p11_constant_resolve (persist->constants, lexer->tok.field.name); - if (attr.type == CKA_INVALID || !p11_constant_name (p11_constant_types, attr.type)) { - p11_lexer_msg (lexer, "invalid or unsupported attribute"); - return false; + end = NULL; + attr.type = strtoul (lexer->tok.field.name, &end, 10); + + /* Not a valid number value, probably a constant */ + if (!end || *end != '\0') { + attr.type = p11_constant_resolve (persist->constants, lexer->tok.field.name); + if (attr.type == CKA_INVALID || !p11_constant_name (p11_constant_types, attr.type)) { + p11_lexer_msg (lexer, "invalid or unsupported attribute"); + return false; + } } if (!parse_value (persist, lexer, &attr)) { @@ -277,51 +541,61 @@ field_to_attribute (p11_persist *persist, return false; } - persist->attrs = p11_attrs_take (persist->attrs, attr.type, - attr.pValue, attr.ulValueLen); + *attrs = p11_attrs_take (*attrs, attr.type, + attr.pValue, attr.ulValueLen); return true; } -static void -on_pem_block (const char *type, - const unsigned char *contents, - size_t length, - void *user_data) +static CK_ATTRIBUTE * +certificate_to_attributes (const unsigned char *der, + size_t length) { CK_OBJECT_CLASS klassv = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE x509 = CKC_X_509; - CK_BBOOL modifiablev = CK_FALSE; - CK_ATTRIBUTE modifiable = { CKA_MODIFIABLE, &modifiablev, sizeof (modifiablev) }; CK_ATTRIBUTE klass = { CKA_CLASS, &klassv, sizeof (klassv) }; CK_ATTRIBUTE certificate_type = { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) }; - CK_ATTRIBUTE value = { CKA_VALUE, }; + CK_ATTRIBUTE value = { CKA_VALUE, (void *)der, length }; + + return p11_attrs_build (NULL, &klass, &certificate_type, &value, NULL); +} - p11_persist *store = user_data; +typedef struct { + p11_lexer *lexer; + CK_ATTRIBUTE *attrs; + bool result; +} parse_block; + +static void +on_pem_block (const char *type, + const unsigned char *contents, + size_t length, + void *user_data) +{ + parse_block *pb = user_data; CK_ATTRIBUTE *attrs; if (strcmp (type, "CERTIFICATE") == 0) { - value.pValue = (void *)contents; - value.ulValueLen = length; - attrs = p11_attrs_build (NULL, &klass, &modifiable, &certificate_type, &value, NULL); - store->attrs = p11_attrs_merge (store->attrs, attrs, false); - store->result = true; + attrs = certificate_to_attributes (contents, length); + pb->attrs = p11_attrs_merge (pb->attrs, attrs, false); + pb->result = true; } else { - p11_lexer_msg (&store->lexer, "unsupported pem block in store"); - store->result = false; + p11_lexer_msg (pb->lexer, "unsupported pem block in store"); + pb->result = false; } } static bool -pem_to_attributes (p11_persist *store, - p11_lexer *lexer) +pem_to_attributes (p11_lexer *lexer, + CK_ATTRIBUTE **attrs) { + parse_block pb = { lexer, *attrs, false }; unsigned int count; count = p11_pem_parse (lexer->tok.pem.begin, lexer->tok.pem.length, - on_pem_block, store); + on_pem_block, &pb); if (count == 0) { p11_lexer_msg (lexer, "invalid pem block"); @@ -330,7 +604,8 @@ pem_to_attributes (p11_persist *store, /* The lexer should have only matched one block */ return_val_if_fail (count == 1, false); - return store->result; + *attrs = pb.attrs; + return pb.result; } bool @@ -340,50 +615,53 @@ p11_persist_read (p11_persist *persist, size_t length, p11_array *objects) { - bool failed = false; + p11_lexer lexer; + CK_ATTRIBUTE *attrs; + bool failed; + bool skip; return_val_if_fail (persist != NULL, false); return_val_if_fail (objects != NULL, false); - persist->skip = false; - persist->result = false; - persist->attrs = NULL; + skip = false; + attrs = NULL; + failed = false; - p11_lexer_init (&persist->lexer, filename, (const char *)data, length); - while (p11_lexer_next (&persist->lexer, &failed)) { - switch (persist->lexer.tok_type) { + p11_lexer_init (&lexer, filename, (const char *)data, length); + while (p11_lexer_next (&lexer, &failed)) { + switch (lexer.tok_type) { case TOK_SECTION: - if (persist->attrs && !p11_array_push (objects, persist->attrs)) + if (attrs && !p11_array_push (objects, attrs)) return_val_if_reached (false); - persist->attrs = NULL; - if (strcmp (persist->lexer.tok.section.name, PERSIST_HEADER) != 0) { - p11_lexer_msg (&persist->lexer, "unrecognized or invalid section header"); - persist->skip = true; + attrs = NULL; + if (strcmp (lexer.tok.section.name, PERSIST_HEADER) != 0) { + p11_lexer_msg (&lexer, "unrecognized or invalid section header"); + skip = true; } else { - persist->attrs = p11_attrs_build (NULL, NULL); - return_val_if_fail (persist->attrs != NULL, false); - persist->skip = false; + attrs = p11_attrs_build (NULL, NULL); + return_val_if_fail (attrs != NULL, false); + skip = false; } failed = false; break; case TOK_FIELD: - if (persist->skip) { + if (skip) { failed = false; - } else if (!persist->attrs) { - p11_lexer_msg (&persist->lexer, "attribute before p11-kit section header"); + } else if (!attrs) { + p11_lexer_msg (&lexer, "attribute before p11-kit section header"); failed = true; } else { - failed = !field_to_attribute (persist, &persist->lexer); + failed = !field_to_attribute (persist, &lexer, &attrs); } break; case TOK_PEM: - if (persist->skip) { + if (skip) { failed = false; - } else if (!persist->attrs) { - p11_lexer_msg (&persist->lexer, "pem block before p11-kit section header"); + } else if (!attrs) { + p11_lexer_msg (&lexer, "pem block before p11-kit section header"); failed = true; } else { - failed = !pem_to_attributes (persist, &persist->lexer); + failed = !pem_to_attributes (&lexer, &attrs); } break; } @@ -392,10 +670,72 @@ p11_persist_read (p11_persist *persist, break; } - if (persist->attrs && !p11_array_push (objects, persist->attrs)) + if (attrs && !p11_array_push (objects, attrs)) return_val_if_reached (false); - persist->attrs = NULL; + attrs = NULL; - p11_lexer_done (&persist->lexer); + p11_lexer_done (&lexer); return !failed; } + +static CK_ATTRIBUTE * +find_certificate_value (CK_ATTRIBUTE *attrs) +{ + CK_OBJECT_CLASS klass; + CK_CERTIFICATE_TYPE type; + + if (!p11_attrs_find_ulong (attrs, CKA_CLASS, &klass) || + klass != CKO_CERTIFICATE) + return NULL; + if (!p11_attrs_find_ulong (attrs, CKA_CERTIFICATE_TYPE, &type) || + type != CKC_X_509) + return NULL; + return p11_attrs_find_valid (attrs, CKA_VALUE); +} + +bool +p11_persist_write (p11_persist *persist, + CK_ATTRIBUTE *attrs, + p11_buffer *buf) +{ + char string[sizeof (CK_ULONG) * 4]; + CK_ATTRIBUTE *cert_value; + const char *nick; + int i; + + cert_value = find_certificate_value (attrs); + + p11_buffer_add (buf, "[" PERSIST_HEADER "]\n", -1); + + for (i = 0; !p11_attrs_terminator (attrs + i); i++) { + + /* These are written later? */ + if (cert_value != NULL && + (attrs[i].type == CKA_CLASS || + attrs[i].type == CKA_CERTIFICATE_TYPE || + attrs[i].type == CKA_VALUE)) + continue; + + if (attrs[i].ulValueLen == CK_UNAVAILABLE_INFORMATION) + continue; + + nick = p11_constant_nick (p11_constant_types, attrs[i].type); + if (nick == NULL) { + snprintf (string, sizeof (string), "%lu", attrs[i].type); + nick = string; + } + + p11_buffer_add (buf, nick, -1); + p11_buffer_add (buf, ": ", 2); + format_value (persist, attrs + i, buf); + p11_buffer_add (buf, "\n", 1); + } + + if (cert_value != NULL) { + if (!p11_pem_write (cert_value->pValue, cert_value->ulValueLen, "CERTIFICATE", buf)) + return_val_if_reached (false); + } + + p11_buffer_add (buf, "\n", 1); + return p11_buffer_ok (buf); +} diff --git a/trust/persist.h b/trust/persist.h index 04762f4..0ef142c 100644 --- a/trust/persist.h +++ b/trust/persist.h @@ -54,6 +54,10 @@ bool p11_persist_read (p11_persist *persist, size_t length, p11_array *objects); +bool p11_persist_write (p11_persist *persist, + CK_ATTRIBUTE *object, + p11_buffer *buf); + void p11_persist_free (p11_persist *persist); #endif /* P11_PERSIST_H_ */ diff --git a/trust/tests/test-persist.c b/trust/tests/test-persist.c index defeecf..107f131 100644 --- a/trust/tests/test-persist.c +++ b/trust/tests/test-persist.c @@ -127,12 +127,44 @@ check_read_msg (const char *file, p11_array_free (expected); } +static void +check_write_msg (const char *file, + int line, + const char *function, + const char *expected, + p11_array *input) +{ + p11_persist *persist; + p11_buffer buf; + int i; + + persist = p11_persist_new (); + p11_buffer_init_null (&buf, 0); + + for (i = 0; i < input->num; i++) { + if (!p11_persist_write (persist, input->elem[i], &buf)) + p11_test_fail (file, line, function, "persist write failed"); + } + + if (strcmp (buf.data, expected) != 0) { + p11_test_fail (file, line, function, "persist doesn't match: (\n%s----\n%s\n)", \ + expected, (char *)buf.data); + } + + p11_buffer_uninit (&buf); + p11_array_free (input); + p11_persist_free (persist); +} + #define check_read_success(input, objs) \ check_read_msg (__FILE__, __LINE__, __FUNCTION__, input, args_to_array objs) #define check_read_failure(input) \ check_read_msg (__FILE__, __LINE__, __FUNCTION__, input, NULL) +#define check_write_success(expected, inputs) \ + check_write_msg (__FILE__, __LINE__, __FUNCTION__, expected, args_to_array inputs) + static CK_OBJECT_CLASS certificate = CKO_CERTIFICATE; static CK_CERTIFICATE_TYPE x509 = CKC_X_509; static CK_OBJECT_CLASS nss_trust = CKO_NSS_TRUST; @@ -143,51 +175,53 @@ static CK_BBOOL falsev = CK_FALSE; static void test_simple (void) { - const char *input = "[p11-kit-object-v1]\n" + const char *output = "[p11-kit-object-v1]\n" "class: data\n" "value: \"blah\"\n" - "application: \"test-persist\"\n"; + "application: \"test-persist\"\n\n"; - CK_ATTRIBUTE expected[] = { + CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &data, sizeof (data) }, { CKA_VALUE, "blah", 4 }, { CKA_APPLICATION, "test-persist", 12 }, { CKA_INVALID }, }; - check_read_success (input, (expected, NULL)); + check_read_success (output, (attrs, NULL)); + check_write_success (output, (attrs, NULL)); } static void test_number (void) { - const char *input = "[p11-kit-object-v1]\n" + const char *output = "[p11-kit-object-v1]\n" "class: data\n" - "value: 29202390\n" - "application: \"test-persist\"\n"; + "value-len: 29202390\n" + "application: \"test-persist\"\n\n"; CK_ULONG value = 29202390; - CK_ATTRIBUTE expected[] = { + CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &data, sizeof (data) }, - { CKA_VALUE, &value, sizeof (value) }, + { CKA_VALUE_LEN, &value, sizeof (value) }, { CKA_APPLICATION, "test-persist", 12 }, { CKA_INVALID }, }; - check_read_success (input, (expected, NULL)); + check_read_success (output, (attrs, NULL)); + check_write_success (output, (attrs, NULL)); } static void test_bool (void) { - const char *input = "[p11-kit-object-v1]\n" + const char *output = "[p11-kit-object-v1]\n" "class: data\n" "private: true\n" "modifiable: false\n" - "application: \"test-persist\"\n"; + "application: \"test-persist\"\n\n"; - CK_ATTRIBUTE expected[] = { + CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &data, sizeof (data) }, { CKA_PRIVATE, &truev, sizeof (truev) }, { CKA_MODIFIABLE, &falsev, sizeof (falsev) }, @@ -195,73 +229,144 @@ test_bool (void) { CKA_INVALID }, }; - check_read_success (input, (expected, NULL)); + check_read_success (output, (attrs, NULL)); + check_write_success (output, (attrs, NULL)); } static void test_oid (void) { - const char *input = "[p11-kit-object-v1]\n" + const char *output = "[p11-kit-object-v1]\n" "class: data\n" - "object-id: 1.2.3.4"; + "object-id: 1.2.3.4\n\n"; - CK_ATTRIBUTE expected[] = { + CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &data, sizeof (data) }, { CKA_OBJECT_ID, "\x06\x03*\x03\x04", 5 }, { CKA_INVALID }, }; - check_read_success (input, (expected, NULL)); + check_read_success (output, (attrs, NULL)); + check_write_success (output, (attrs, NULL)); } static void test_constant (void) { - const char *input = "[p11-kit-object-v1]\n" + const char *output = "[p11-kit-object-v1]\n" "class: data\n" - "trust-server-auth: nss-trust-unknown"; + "certificate-type: x-509-attr-cert\n" + "key-type: rsa\n" + "x-assertion-type: x-pinned-certificate\n" + "certificate-category: authority\n" + "mechanism-type: rsa-pkcs-key-pair-gen\n" + "trust-server-auth: nss-trust-unknown\n\n"; CK_TRUST trust = CKT_NSS_TRUST_UNKNOWN; + CK_CERTIFICATE_TYPE type = CKC_X_509_ATTR_CERT; + CK_X_ASSERTION_TYPE ass = CKT_X_PINNED_CERTIFICATE; + CK_MECHANISM_TYPE mech = CKM_RSA_PKCS_KEY_PAIR_GEN; + CK_ULONG category = 2; + CK_KEY_TYPE key = CKK_RSA; - CK_ATTRIBUTE expected[] = { + CK_ATTRIBUTE attrs[] = { { CKA_CLASS, &data, sizeof (data) }, + { CKA_CERTIFICATE_TYPE, &type, sizeof (type) }, + { CKA_KEY_TYPE, &key, sizeof (key) }, + { CKA_X_ASSERTION_TYPE, &ass, sizeof (ass) }, + { CKA_CERTIFICATE_CATEGORY, &category, sizeof (category) }, + { CKA_MECHANISM_TYPE, &mech, sizeof (mech) }, { CKA_TRUST_SERVER_AUTH, &trust, sizeof (trust) }, { CKA_INVALID }, }; - check_read_success (input, (expected, NULL)); + check_read_success (output, (attrs, NULL)); + check_write_success (output, (attrs, NULL)); +} + +static void +test_unknown (void) +{ + const char *output = "[p11-kit-object-v1]\n" + "class: data\n" + "38383838: \"the-value-here\"\n\n"; + + CK_ATTRIBUTE attrs[] = { + { CKA_CLASS, &data, sizeof (data) }, + { 38383838, "the-value-here", 14 }, + { CKA_INVALID }, + }; + + check_read_success (output, (attrs, NULL)); + check_write_success (output, (attrs, NULL)); } static void test_multiple (void) { - const char *input = "[p11-kit-object-v1]\n" + const char *output = "[p11-kit-object-v1]\n" "class: data\n" - "object-id: 1.2.3.4\n" + "object-id: 1.2.3.4\n\n" "[p11-kit-object-v1]\n" "class: nss-trust\n" - "trust-server-auth: nss-trust-unknown"; + "trust-server-auth: nss-trust-unknown\n\n"; CK_TRUST trust = CKT_NSS_TRUST_UNKNOWN; - CK_ATTRIBUTE expected1[] = { + CK_ATTRIBUTE attrs1[] = { { CKA_CLASS, &data, sizeof (data) }, { CKA_OBJECT_ID, "\x06\x03*\x03\x04", 5 }, { CKA_INVALID }, }; - CK_ATTRIBUTE expected2[] = { + CK_ATTRIBUTE attrs2[] = { { CKA_CLASS, &nss_trust, sizeof (nss_trust) }, { CKA_TRUST_SERVER_AUTH, &trust, sizeof (trust) }, { CKA_INVALID }, }; - check_read_success (input, (expected1, expected2, NULL)); + check_read_success (output, (attrs1, attrs2, NULL)); + check_write_success (output, (attrs1, attrs2, NULL)); } static void test_pem_block (void) { + const char *output = "[p11-kit-object-v1]\n" + "id: \"292c92\"\n" + "trusted: true\n" + "-----BEGIN CERTIFICATE-----\n" + "MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG\n" + "A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz\n" + "cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2\n" + "MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV\n" + "BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt\n" + "YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN\n" + "ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f\n" + "zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi\n" + "TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G\n" + "CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW\n" + "NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV\n" + "Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb\n" + "-----END CERTIFICATE-----\n" + "\n"; + + CK_ATTRIBUTE attrs[] = { + { CKA_CLASS, &certificate, sizeof (certificate) }, + { CKA_ID, "292c92", 6, }, + { CKA_CERTIFICATE_TYPE, &x509, sizeof (x509) }, + { CKA_VALUE, &verisign_v1_ca, sizeof (verisign_v1_ca) }, + { CKA_TRUSTED, &truev, sizeof (truev) }, + { CKA_INVALID }, + }; + + check_read_success (output, (attrs, NULL)); + check_write_success (output, (attrs, NULL)); +} + +static void +test_pem_middle (void) +{ const char *input = "[p11-kit-object-v1]\n" "class: certificate\n" "id: \"292c92\"\n" @@ -436,6 +541,44 @@ test_attribute_first (void) p11_message_loud (); } +static void +test_not_boolean (void) +{ + const char *output = "[p11-kit-object-v1]\n" + "private: \"x\"\n\n"; + + CK_ATTRIBUTE attrs[] = { + { CKA_PRIVATE, "x", 1 }, + { CKA_INVALID }, + }; + + check_write_success (output, (attrs, NULL)); +} + +static void +test_not_ulong (void) +{ + char buffer[sizeof (CK_ULONG) + 1]; + char *output; + + CK_ATTRIBUTE attrs[] = { + { CKA_BITS_PER_PIXEL, "xx", 2 }, + { CKA_VALUE, buffer, sizeof (CK_ULONG) }, + { CKA_INVALID }, + }; + + memset (buffer, 'x', sizeof (buffer)); + buffer[sizeof (CK_ULONG)] = 0; + + if (asprintf (&output, "[p11-kit-object-v1]\n" + "bits-per-pixel: \"xx\"\n" + "value: \"%s\"\n\n", buffer) < 0) + assert_not_reached (); + + check_write_success (output, (attrs, NULL)); + free (output); +} + int main (int argc, char *argv[]) @@ -446,8 +589,10 @@ main (int argc, p11_test (test_bool, "/persist/bool"); p11_test (test_oid, "/persist/oid"); p11_test (test_constant, "/persist/constant"); + p11_test (test_unknown, "/persist/unknown"); p11_test (test_multiple, "/persist/multiple"); p11_test (test_pem_block, "/persist/pem_block"); + p11_test (test_pem_middle, "/persist/pem-middle"); p11_test (test_pem_invalid, "/persist/pem_invalid"); p11_test (test_pem_unsupported, "/persist/pem_unsupported"); p11_test (test_pem_first, "/persist/pem_first"); @@ -456,5 +601,7 @@ main (int argc, p11_test (test_bad_field, "/persist/bad_field"); p11_test (test_skip_unknown, "/persist/skip_unknown"); p11_test (test_attribute_first, "/persist/attribute_first"); + p11_test (test_not_boolean, "/persist/not-boolean"); + p11_test (test_not_ulong, "/persist/not-ulong"); return p11_test_run (argc, argv); } diff --git a/trust/tests/test-trust.c b/trust/tests/test-trust.c index 6b990dc..6a22946 100644 --- a/trust/tests/test-trust.c +++ b/trust/tests/test-trust.c @@ -147,6 +147,6 @@ test_check_attr_msg (const char *file, p11_test_fail (file, line, function, "attribute does not match: (expected %s but found %s)", p11_attr_to_string (expected, klass), - p11_attr_to_string (attr, klass)); + attr ? p11_attr_to_string (attr, klass) : "(null)"); } } |