diff options
author | Stef Walter <stefw@gnome.org> | 2013-01-24 14:36:59 +0100 |
---|---|---|
committer | Stef Walter <stefw@gnome.org> | 2013-02-04 10:55:45 +0100 |
commit | 7ddff6795830deff6ec5fb1b8b0c704fbdea2c97 (patch) | |
tree | d9d4ad6c4889fa8d9ec6d01a7a76222bd9efac4f | |
parent | 322b4739cb51aa45568d9479224f2b07ac82a35f (diff) |
Further tweaks and cleanup for functions dealing with PKCS#11 attributes
* Check that the size is correct when looking for a boolean
or a ulong.
* Make sure that the length is not the invalid negative ulong.
* Functions for dumping out attribute contents
* Make it possible to use attributes in hash tables
-rw-r--r-- | common/attrs.c | 795 | ||||
-rw-r--r-- | common/attrs.h | 59 | ||||
-rw-r--r-- | common/tests/test-attrs.c | 126 |
3 files changed, 910 insertions, 70 deletions
diff --git a/common/attrs.c b/common/attrs.c index dd91afc..ab1bc59 100644 --- a/common/attrs.c +++ b/common/attrs.c @@ -36,22 +36,26 @@ #include "config.h" #include "attrs.h" +#include "buffer.h" #include "compat.h" #include "debug.h" +#include "pkcs11.h" +#include "pkcs11x.h" #include <assert.h> #include <stdarg.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -CK_BBOOL -p11_attrs_is_empty (CK_ATTRIBUTE *attrs) +bool +p11_attrs_is_empty (const CK_ATTRIBUTE *attrs) { return (attrs == NULL || attrs->type == CKA_INVALID); } CK_ULONG -p11_attrs_count (CK_ATTRIBUTE *attrs) +p11_attrs_count (const CK_ATTRIBUTE *attrs) { CK_ULONG count; @@ -169,7 +173,7 @@ template_generator (void *state) CK_ATTRIBUTE * p11_attrs_buildn (CK_ATTRIBUTE *attrs, - CK_ATTRIBUTE *add, + const CK_ATTRIBUTE *add, CK_ULONG count) { return attrs_build (attrs, count, true, template_generator, &add); @@ -187,7 +191,7 @@ p11_attrs_take (CK_ATTRIBUTE *attrs, } CK_ATTRIBUTE * -p11_attrs_dup (CK_ATTRIBUTE *attrs) +p11_attrs_dup (const CK_ATTRIBUTE *attrs) { CK_ULONG count; @@ -224,7 +228,116 @@ p11_attrs_findn (CK_ATTRIBUTE *attrs, return NULL; } -CK_BBOOL +bool +p11_attrs_find_bool (CK_ATTRIBUTE *attrs, + CK_ATTRIBUTE_TYPE type, + CK_BBOOL *value) +{ + CK_ULONG i; + + for (i = 0; !p11_attrs_is_empty (attrs + i); i++) { + if (attrs[i].type == type && + attrs[i].ulValueLen == sizeof (CK_BBOOL) && + attrs[i].pValue != NULL) { + *value = *((CK_BBOOL *)attrs[i].pValue); + return true; + } + } + + return false; +} + +bool +p11_attrs_findn_bool (CK_ATTRIBUTE *attrs, + CK_ULONG count, + CK_ATTRIBUTE_TYPE type, + CK_BBOOL *value) +{ + CK_ULONG i; + + for (i = 0; i < count; i++) { + if (attrs[i].type == type && + attrs[i].ulValueLen == sizeof (CK_BBOOL) && + attrs[i].pValue != NULL) { + *value = *((CK_BBOOL *)attrs[i].pValue); + return true; + } + } + + return false; +} + +bool +p11_attrs_find_ulong (CK_ATTRIBUTE *attrs, + CK_ATTRIBUTE_TYPE type, + CK_ULONG *value) +{ + CK_ULONG i; + + for (i = 0; !p11_attrs_is_empty (attrs + i); i++) { + if (attrs[i].type == type && + attrs[i].ulValueLen == sizeof (CK_ULONG) && + attrs[i].pValue != NULL) { + *value = *((CK_ULONG *)attrs[i].pValue); + return true; + } + } + + return false; +} + +bool +p11_attrs_findn_ulong (CK_ATTRIBUTE *attrs, + CK_ULONG count, + CK_ATTRIBUTE_TYPE type, + CK_ULONG *value) +{ + CK_ULONG i; + + for (i = 0; i < count; i++) { + if (attrs[i].type == type && + attrs[i].ulValueLen == sizeof (CK_ULONG) && + attrs[i].pValue != NULL) { + *value = *((CK_ULONG *)attrs[i].pValue); + return true; + } + } + + return false; +} + +CK_ATTRIBUTE * +p11_attrs_find_valid (CK_ATTRIBUTE *attrs, + CK_ATTRIBUTE_TYPE type) +{ + CK_ULONG i; + + for (i = 0; !p11_attrs_is_empty (attrs + i); i++) { + if (attrs[i].type == type && + attrs[i].ulValueLen != (CK_ULONG)-1) + return attrs + i; + } + + return NULL; +} + +CK_ATTRIBUTE * +p11_attrs_findn_valid (CK_ATTRIBUTE *attrs, + CK_ULONG count, + CK_ATTRIBUTE_TYPE type) +{ + CK_ULONG i; + + for (i = 0; i < count; i++) { + if (attrs[i].type == type && + attrs[i].ulValueLen != (CK_ULONG)-1) + return attrs + i; + } + + return NULL; +} + +bool p11_attrs_remove (CK_ATTRIBUTE *attrs, CK_ATTRIBUTE_TYPE type) { @@ -238,73 +351,675 @@ p11_attrs_remove (CK_ATTRIBUTE *attrs, } if (i == count) - return CK_FALSE; + return false; if (attrs[i].pValue) free (attrs[i].pValue); memmove (attrs + i, attrs + i + 1, (count - (i + 1)) * sizeof (CK_ATTRIBUTE)); attrs[count - 1].type = CKA_INVALID; - return CK_TRUE; + return true; } -CK_BBOOL -p11_attrs_match (CK_ATTRIBUTE *attrs, - CK_ATTRIBUTE *match) +bool +p11_attrs_match (const CK_ATTRIBUTE *attrs, + const CK_ATTRIBUTE *match) { CK_ATTRIBUTE *attr; for (; !p11_attrs_is_empty (match); match++) { - attr = p11_attrs_find (attrs, match->type); + attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match->type); if (!attr) - return CK_FALSE; + return false; if (!p11_attr_equal (attr, match)) - return CK_FALSE; + return false; } - return CK_TRUE; + return true; } -CK_BBOOL -p11_attrs_matchn (CK_ATTRIBUTE *attrs, - CK_ATTRIBUTE *match, +bool +p11_attrs_matchn (const CK_ATTRIBUTE *attrs, + const CK_ATTRIBUTE *match, CK_ULONG count) { CK_ATTRIBUTE *attr; CK_ULONG i; for (i = 0; i < count; i++) { - attr = p11_attrs_find (attrs, match[i].type); + attr = p11_attrs_find ((CK_ATTRIBUTE *)attrs, match[i].type); if (!attr) - return CK_FALSE; + return false; if (!p11_attr_equal (attr, match + i)) - return CK_FALSE; + return false; } - return CK_TRUE; + return true; + +} + + +bool +p11_attr_match_value (const CK_ATTRIBUTE *attr, + const void *value, + ssize_t length) +{ + if (length < 0) + length = strlen (value); + return (attr != NULL && + attr->ulValueLen == length && + (attr->pValue == value || + (attr->pValue && value && + memcmp (attr->pValue, value, attr->ulValueLen) == 0))); +} + +bool +p11_attr_equal (const void *v1, + const void *v2) +{ + const CK_ATTRIBUTE *one = v1; + const CK_ATTRIBUTE *two = v2; + + return (one == two || + (one && two && one->type == two->type && + p11_attr_match_value (one, two->pValue, two->ulValueLen))); +} + +unsigned int +p11_attr_hash (const void *data) +{ + const CK_ATTRIBUTE *attr = data; + unsigned int hash = (unsigned int)attr->type; + const char *p, *end; + + for (p = attr->pValue, end = p + attr->ulValueLen ; p != NULL && p != end; p++) + hash = (hash << 5) - hash + *p; + + return hash; +} + +static void +buffer_append_printf (p11_buffer *buffer, + const char *format, + ...) +{ + char *string; + va_list va; + + va_start (va, format); + if (vasprintf (&string, format, va) < 0) + return_if_reached (); + va_end (va); + p11_buffer_add (buffer, string, -1); + free (string); +} + +static bool +attribute_is_ulong_of_type (const CK_ATTRIBUTE *attr, + CK_ULONG type) +{ + if (attr->type != type) + return false; + if (attr->ulValueLen != sizeof (CK_ULONG)) + return false; + if (!attr->pValue) + return false; + return true; +} + +static bool +attribute_is_trust_value (const CK_ATTRIBUTE *attr) +{ + 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: + break; + default: + return false; + } + + return attribute_is_ulong_of_type (attr, attr->type); +} + +static bool +attribute_is_sensitive (const CK_ATTRIBUTE *attr) +{ + /* + * Don't print any just attribute, since they may contain + * sensitive data + */ + + switch (attr->type) { + #define X(x) case x: return false; + X (CKA_CLASS) + X (CKA_TOKEN) + X (CKA_PRIVATE) + X (CKA_LABEL) + X (CKA_APPLICATION) + X (CKA_OBJECT_ID) + X (CKA_CERTIFICATE_TYPE) + X (CKA_ISSUER) + X (CKA_SERIAL_NUMBER) + X (CKA_AC_ISSUER) + X (CKA_OWNER) + X (CKA_ATTR_TYPES) + X (CKA_TRUSTED) + X (CKA_CERTIFICATE_CATEGORY) + X (CKA_JAVA_MIDP_SECURITY_DOMAIN) + X (CKA_URL) + X (CKA_HASH_OF_SUBJECT_PUBLIC_KEY) + X (CKA_HASH_OF_ISSUER_PUBLIC_KEY) + X (CKA_CHECK_VALUE) + X (CKA_KEY_TYPE) + X (CKA_SUBJECT) + X (CKA_ID) + X (CKA_SENSITIVE) + X (CKA_ENCRYPT) + X (CKA_DECRYPT) + X (CKA_WRAP) + X (CKA_UNWRAP) + X (CKA_SIGN) + X (CKA_SIGN_RECOVER) + X (CKA_VERIFY) + X (CKA_VERIFY_RECOVER) + X (CKA_DERIVE) + X (CKA_START_DATE) + X (CKA_END_DATE) + X (CKA_MODULUS_BITS) + X (CKA_PRIME_BITS) + /* X (CKA_SUBPRIME_BITS) */ + /* X (CKA_SUB_PRIME_BITS) */ + X (CKA_VALUE_BITS) + X (CKA_VALUE_LEN) + X (CKA_EXTRACTABLE) + X (CKA_LOCAL) + X (CKA_NEVER_EXTRACTABLE) + X (CKA_ALWAYS_SENSITIVE) + X (CKA_KEY_GEN_MECHANISM) + X (CKA_MODIFIABLE) + X (CKA_SECONDARY_AUTH) + X (CKA_AUTH_PIN_FLAGS) + X (CKA_ALWAYS_AUTHENTICATE) + X (CKA_WRAP_WITH_TRUSTED) + X (CKA_WRAP_TEMPLATE) + X (CKA_UNWRAP_TEMPLATE) + X (CKA_HW_FEATURE_TYPE) + X (CKA_RESET_ON_INIT) + X (CKA_HAS_RESET) + X (CKA_PIXEL_X) + X (CKA_PIXEL_Y) + X (CKA_RESOLUTION) + X (CKA_CHAR_ROWS) + X (CKA_CHAR_COLUMNS) + X (CKA_COLOR) + X (CKA_BITS_PER_PIXEL) + X (CKA_CHAR_SETS) + X (CKA_ENCODING_METHODS) + X (CKA_MIME_TYPES) + X (CKA_MECHANISM_TYPE) + X (CKA_REQUIRED_CMS_ATTRIBUTES) + X (CKA_DEFAULT_CMS_ATTRIBUTES) + X (CKA_SUPPORTED_CMS_ATTRIBUTES) + X (CKA_ALLOWED_MECHANISMS) + X (CKA_X_ASSERTION_TYPE) + X (CKA_X_CERTIFICATE_VALUE) + X (CKA_X_PURPOSE) + X (CKA_X_PEER) + X (CKA_X_DISTRUSTED) + X (CKA_X_CRITICAL) + X (CKA_NETSCAPE_URL) + X (CKA_NETSCAPE_EMAIL) + X (CKA_NETSCAPE_SMIME_INFO) + X (CKA_NETSCAPE_SMIME_TIMESTAMP) + X (CKA_NETSCAPE_PKCS8_SALT) + X (CKA_NETSCAPE_PASSWORD_CHECK) + X (CKA_NETSCAPE_EXPIRES) + X (CKA_NETSCAPE_KRL) + X (CKA_NETSCAPE_PQG_COUNTER) + X (CKA_NETSCAPE_PQG_SEED) + X (CKA_NETSCAPE_PQG_H) + X (CKA_NETSCAPE_PQG_SEED_BITS) + X (CKA_NETSCAPE_MODULE_SPEC) + X (CKA_TRUST_DIGITAL_SIGNATURE) + X (CKA_TRUST_NON_REPUDIATION) + X (CKA_TRUST_KEY_ENCIPHERMENT) + X (CKA_TRUST_DATA_ENCIPHERMENT) + X (CKA_TRUST_KEY_AGREEMENT) + X (CKA_TRUST_KEY_CERT_SIGN) + X (CKA_TRUST_CRL_SIGN) + X (CKA_TRUST_SERVER_AUTH) + X (CKA_TRUST_CLIENT_AUTH) + X (CKA_TRUST_CODE_SIGNING) + X (CKA_TRUST_EMAIL_PROTECTION) + X (CKA_TRUST_IPSEC_END_SYSTEM) + X (CKA_TRUST_IPSEC_TUNNEL) + X (CKA_TRUST_IPSEC_USER) + X (CKA_TRUST_TIME_STAMPING) + X (CKA_TRUST_STEP_UP_APPROVED) + X (CKA_CERT_SHA1_HASH) + X (CKA_CERT_MD5_HASH) + #undef X + } + + return true; +} + +static void +format_class (p11_buffer *buffer, + CK_OBJECT_CLASS klass) +{ + const char *string = NULL; + + switch (klass) { + #define X(x) case x: string = #x; break; + X (CKO_DATA) + X (CKO_CERTIFICATE) + X (CKO_PUBLIC_KEY) + X (CKO_PRIVATE_KEY) + X (CKO_SECRET_KEY) + X (CKO_HW_FEATURE) + X (CKO_DOMAIN_PARAMETERS) + X (CKO_MECHANISM) + X (CKO_X_TRUST_ASSERTION) + X (CKO_X_CERTIFICATE_EXTENSION) + X (CKO_NETSCAPE_CRL) + X (CKO_NETSCAPE_SMIME) + X (CKO_NETSCAPE_TRUST) + X (CKO_NETSCAPE_BUILTIN_ROOT_LIST) + X (CKO_NETSCAPE_NEWSLOT) + X (CKO_NETSCAPE_DELSLOT) + #undef X + } + + if (string != NULL) + p11_buffer_add (buffer, string, -1); + else + buffer_append_printf (buffer, "0x%08lX", klass); +} + +static void +format_assertion_type (p11_buffer *buffer, + CK_X_ASSERTION_TYPE type) +{ + const char *string = NULL; + + switch (type) { + #define X(x) case x: string = #x; break; + X (CKT_X_DISTRUSTED_CERTIFICATE) + X (CKT_X_PINNED_CERTIFICATE) + X (CKT_X_ANCHORED_CERTIFICATE) + #undef X + } + + if (string != NULL) + p11_buffer_add (buffer, string, -1); + else + buffer_append_printf (buffer, "0x%08lX", type); +} + +static void +format_key_type (p11_buffer *buffer, + CK_KEY_TYPE type) +{ + const char *string = NULL; + + switch (type) { + #define X(x) case x: string = #x; break; + X (CKK_RSA) + X (CKK_DSA) + X (CKK_DH) + /* X (CKK_ECDSA) */ + X (CKK_EC) + X (CKK_X9_42_DH) + X (CKK_KEA) + X (CKK_GENERIC_SECRET) + X (CKK_RC2) + X (CKK_RC4) + X (CKK_DES) + X (CKK_DES2) + X (CKK_DES3) + X (CKK_CAST) + X (CKK_CAST3) + X (CKK_CAST128) + X (CKK_RC5) + X (CKK_IDEA) + X (CKK_SKIPJACK) + X (CKK_BATON) + X (CKK_JUNIPER) + X (CKK_CDMF) + X (CKK_AES) + X (CKK_BLOWFISH) + X (CKK_TWOFISH) + X (CKK_NETSCAPE_PKCS8) + #undef X + } + + if (string != NULL) + p11_buffer_add (buffer, string, -1); + else + buffer_append_printf (buffer, "0x%08lX", type); +} + +static void +format_certificate_type (p11_buffer *buffer, + CK_CERTIFICATE_TYPE type) +{ + const char *string = NULL; + + switch (type) { + #define X(x) case x: string = #x; break; + X (CKC_X_509) + X (CKC_X_509_ATTR_CERT) + X (CKC_WTLS) + } + + if (string != NULL) + p11_buffer_add (buffer, string, -1); + else + buffer_append_printf (buffer, "0x%08lX", type); +} + +static void +format_trust_value (p11_buffer *buffer, + CK_TRUST trust) +{ + const char *string = NULL; + + switch (trust) { + #define X(x) case x: string = #x; break; + X (CKT_NETSCAPE_TRUSTED) + X (CKT_NETSCAPE_TRUSTED_DELEGATOR) + X (CKT_NETSCAPE_UNTRUSTED) + X (CKT_NETSCAPE_MUST_VERIFY) + X (CKT_NETSCAPE_TRUST_UNKNOWN) + } + + if (string != NULL) + p11_buffer_add (buffer, string, -1); + else + buffer_append_printf (buffer, "0x%08lX", trust); +} + +static void +format_certificate_category (p11_buffer *buffer, + CK_ULONG category) +{ + const char *string = NULL; + + switch (category) { + case 0: + string = "unspecified"; + break; + case 1: + string = "token-user"; + break; + case 2: + string = "authority"; + break; + case 3: + string = "other-entry"; + break; + } + + if (string != NULL) + buffer_append_printf (buffer, "%lu (%s)", category, string); + else + buffer_append_printf (buffer, "%lu", category); +} + +static void +format_attribute_type (p11_buffer *buffer, + CK_ULONG type) +{ + const char *string = NULL; + + switch (type) { + #define X(x) case x: string = #x; break; + X (CKA_CLASS) + X (CKA_TOKEN) + X (CKA_PRIVATE) + X (CKA_LABEL) + X (CKA_APPLICATION) + X (CKA_VALUE) + X (CKA_OBJECT_ID) + X (CKA_CERTIFICATE_TYPE) + X (CKA_ISSUER) + X (CKA_SERIAL_NUMBER) + X (CKA_AC_ISSUER) + X (CKA_OWNER) + X (CKA_ATTR_TYPES) + X (CKA_TRUSTED) + X (CKA_CERTIFICATE_CATEGORY) + X (CKA_JAVA_MIDP_SECURITY_DOMAIN) + X (CKA_URL) + X (CKA_HASH_OF_SUBJECT_PUBLIC_KEY) + X (CKA_HASH_OF_ISSUER_PUBLIC_KEY) + X (CKA_CHECK_VALUE) + X (CKA_KEY_TYPE) + X (CKA_SUBJECT) + X (CKA_ID) + X (CKA_SENSITIVE) + X (CKA_ENCRYPT) + X (CKA_DECRYPT) + X (CKA_WRAP) + X (CKA_UNWRAP) + X (CKA_SIGN) + X (CKA_SIGN_RECOVER) + X (CKA_VERIFY) + X (CKA_VERIFY_RECOVER) + X (CKA_DERIVE) + X (CKA_START_DATE) + X (CKA_END_DATE) + X (CKA_MODULUS) + X (CKA_MODULUS_BITS) + X (CKA_PUBLIC_EXPONENT) + X (CKA_PRIVATE_EXPONENT) + X (CKA_PRIME_1) + X (CKA_PRIME_2) + X (CKA_EXPONENT_1) + X (CKA_EXPONENT_2) + X (CKA_COEFFICIENT) + X (CKA_PRIME) + X (CKA_SUBPRIME) + X (CKA_BASE) + X (CKA_PRIME_BITS) + /* X (CKA_SUBPRIME_BITS) */ + /* X (CKA_SUB_PRIME_BITS) */ + X (CKA_VALUE_BITS) + X (CKA_VALUE_LEN) + X (CKA_EXTRACTABLE) + X (CKA_LOCAL) + X (CKA_NEVER_EXTRACTABLE) + X (CKA_ALWAYS_SENSITIVE) + X (CKA_KEY_GEN_MECHANISM) + X (CKA_MODIFIABLE) + X (CKA_ECDSA_PARAMS) + /* X (CKA_EC_PARAMS) */ + X (CKA_EC_POINT) + X (CKA_SECONDARY_AUTH) + X (CKA_AUTH_PIN_FLAGS) + X (CKA_ALWAYS_AUTHENTICATE) + X (CKA_WRAP_WITH_TRUSTED) + X (CKA_WRAP_TEMPLATE) + X (CKA_UNWRAP_TEMPLATE) + X (CKA_HW_FEATURE_TYPE) + X (CKA_RESET_ON_INIT) + X (CKA_HAS_RESET) + X (CKA_PIXEL_X) + X (CKA_PIXEL_Y) + X (CKA_RESOLUTION) + X (CKA_CHAR_ROWS) + X (CKA_CHAR_COLUMNS) + X (CKA_COLOR) + X (CKA_BITS_PER_PIXEL) + X (CKA_CHAR_SETS) + X (CKA_ENCODING_METHODS) + X (CKA_MIME_TYPES) + X (CKA_MECHANISM_TYPE) + X (CKA_REQUIRED_CMS_ATTRIBUTES) + X (CKA_DEFAULT_CMS_ATTRIBUTES) + X (CKA_SUPPORTED_CMS_ATTRIBUTES) + X (CKA_ALLOWED_MECHANISMS) + X (CKA_X_ASSERTION_TYPE) + X (CKA_X_CERTIFICATE_VALUE) + X (CKA_X_PURPOSE) + X (CKA_X_PEER) + X (CKA_X_DISTRUSTED) + X (CKA_X_CRITICAL) + X (CKA_NETSCAPE_URL) + X (CKA_NETSCAPE_EMAIL) + X (CKA_NETSCAPE_SMIME_INFO) + X (CKA_NETSCAPE_SMIME_TIMESTAMP) + X (CKA_NETSCAPE_PKCS8_SALT) + X (CKA_NETSCAPE_PASSWORD_CHECK) + X (CKA_NETSCAPE_EXPIRES) + X (CKA_NETSCAPE_KRL) + X (CKA_NETSCAPE_PQG_COUNTER) + X (CKA_NETSCAPE_PQG_SEED) + X (CKA_NETSCAPE_PQG_H) + X (CKA_NETSCAPE_PQG_SEED_BITS) + X (CKA_NETSCAPE_MODULE_SPEC) + X (CKA_TRUST_DIGITAL_SIGNATURE) + X (CKA_TRUST_NON_REPUDIATION) + X (CKA_TRUST_KEY_ENCIPHERMENT) + X (CKA_TRUST_DATA_ENCIPHERMENT) + X (CKA_TRUST_KEY_AGREEMENT) + X (CKA_TRUST_KEY_CERT_SIGN) + X (CKA_TRUST_CRL_SIGN) + X (CKA_TRUST_SERVER_AUTH) + X (CKA_TRUST_CLIENT_AUTH) + X (CKA_TRUST_CODE_SIGNING) + X (CKA_TRUST_EMAIL_PROTECTION) + X (CKA_TRUST_IPSEC_END_SYSTEM) + X (CKA_TRUST_IPSEC_TUNNEL) + X (CKA_TRUST_IPSEC_USER) + X (CKA_TRUST_TIME_STAMPING) + X (CKA_TRUST_STEP_UP_APPROVED) + X (CKA_CERT_SHA1_HASH) + X (CKA_CERT_MD5_HASH) + #undef X + } + + if (string != NULL) + p11_buffer_add (buffer, string, -1); + else + buffer_append_printf (buffer, "CKA_0x%08lX", type); +} + +static void +format_some_bytes (p11_buffer *buffer, + void *bytes, + CK_ULONG length) +{ + unsigned char ch; + const unsigned char *data = bytes; + CK_ULONG i; + + if (bytes == NULL) { + p11_buffer_add (buffer, "NULL", -1); + return; + } + + p11_buffer_add (buffer, "\"", 1); + for (i = 0; i < length && i < 128; i++) { + ch = data[i]; + if (ch == '\t') + p11_buffer_add (buffer, "\\t", -1); + else if (ch == '\n') + p11_buffer_add (buffer, "\\n", -1); + else if (ch == '\r') + p11_buffer_add (buffer, "\\r", -1); + else if (ch >= 32 && ch < 127) + p11_buffer_add (buffer, &ch, 1); + else + buffer_append_printf (buffer, "\\x%02x", ch); + } + + if (i < length) + buffer_append_printf (buffer, "..."); + p11_buffer_add (buffer, "\"", 1); +} + +static void +format_attribute (p11_buffer *buffer, + const CK_ATTRIBUTE *attr) +{ + p11_buffer_add (buffer, "{ ", -1); + format_attribute_type (buffer, attr->type); + p11_buffer_add (buffer, " = ", -1); + if (attr->ulValueLen == CKA_INVALID) { + buffer_append_printf (buffer, "(-1) INVALID"); + } else if (attribute_is_ulong_of_type (attr, CKA_CLASS)) { + format_class (buffer, *((CK_OBJECT_CLASS *)attr->pValue)); + } else if (attribute_is_ulong_of_type (attr, CKA_X_ASSERTION_TYPE)) { + format_assertion_type (buffer, *((CK_X_ASSERTION_TYPE *)attr->pValue)); + } else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_TYPE)) { + format_certificate_type (buffer, *((CK_CERTIFICATE_TYPE *)attr->pValue)); + } else if (attribute_is_ulong_of_type (attr, CKA_CERTIFICATE_CATEGORY)) { + format_certificate_category (buffer, *((CK_ULONG *)attr->pValue)); + } else if (attribute_is_ulong_of_type (attr, CKA_KEY_TYPE)) { + format_key_type (buffer, *((CK_KEY_TYPE *)attr->pValue)); + } else if (attribute_is_trust_value (attr)) { + format_trust_value (buffer, *((CK_TRUST *)attr->pValue)); + } else if (attribute_is_sensitive (attr)) { + buffer_append_printf (buffer, "(%lu) NOT-PRINTED", attr->ulValueLen); + } else { + buffer_append_printf (buffer, "(%lu) ", attr->ulValueLen); + format_some_bytes (buffer, attr->pValue, attr->ulValueLen); + } + p11_buffer_add (buffer, " }", -1); +} + +static void +format_attributes (p11_buffer *buffer, + const CK_ATTRIBUTE *attrs) +{ + CK_BBOOL first = CK_TRUE; + int count, i; + + count = p11_attrs_count (attrs); + buffer_append_printf (buffer, "(%d) [", count); + for (i = 0; i < count; i++) { + if (first) + p11_buffer_add (buffer, " ", 1); + else + p11_buffer_add (buffer, ", ", 2); + first = CK_FALSE; + format_attribute (buffer, attrs + i); + } + p11_buffer_add (buffer, " ]", -1); } -CK_BBOOL -p11_attr_match_boolean (CK_ATTRIBUTE *attr, - CK_BBOOL value) +char * +p11_attrs_to_string (const CK_ATTRIBUTE *attrs) { - return (attr->ulValueLen == sizeof (value) && - attr->pValue != NULL && - memcmp (attr->pValue, &value, sizeof (value)) == 0); + p11_buffer buffer; + if (!p11_buffer_init_null (&buffer, 128)) + return_val_if_reached (NULL); + format_attributes (&buffer, attrs); + return p11_buffer_steal (&buffer, NULL); } -CK_BBOOL -p11_attr_equal (CK_ATTRIBUTE *one, - CK_ATTRIBUTE *two) +char * +p11_attr_to_string (const CK_ATTRIBUTE *attr) { - if (one == two) - return CK_TRUE; - if (!one || !two || one->type != two->type || one->ulValueLen != two->ulValueLen) - return CK_FALSE; - if (one->pValue == two->pValue) - return TRUE; - if (!one->pValue || !two->pValue) - return FALSE; - return memcmp (one->pValue, two->pValue, one->ulValueLen) == 0; + p11_buffer buffer; + if (!p11_buffer_init_null (&buffer, 32)) + return_val_if_reached (NULL); + format_attribute (&buffer, attr); + return p11_buffer_steal (&buffer, NULL); } diff --git a/common/attrs.h b/common/attrs.h index 12a2798..870f0d1 100644 --- a/common/attrs.h +++ b/common/attrs.h @@ -36,17 +36,18 @@ #ifndef P11_ATTRS_H_ #define P11_ATTRS_H_ +#include "compat.h" #include "pkcs11.h" #define CKA_INVALID ((CK_ULONG)-1) -CK_ATTRIBUTE * p11_attrs_dup (CK_ATTRIBUTE *attrs); +CK_ATTRIBUTE * p11_attrs_dup (const CK_ATTRIBUTE *attrs); CK_ATTRIBUTE * p11_attrs_build (CK_ATTRIBUTE *attrs, ...); CK_ATTRIBUTE * p11_attrs_buildn (CK_ATTRIBUTE *attrs, - CK_ATTRIBUTE *add, + const CK_ATTRIBUTE *add, CK_ULONG count); CK_ATTRIBUTE * p11_attrs_take (CK_ATTRIBUTE *attrs, @@ -54,9 +55,9 @@ CK_ATTRIBUTE * p11_attrs_take (CK_ATTRIBUTE *attrs, CK_VOID_PTR value, CK_ULONG length); -CK_BBOOL p11_attrs_is_empty (CK_ATTRIBUTE *attrs); +bool p11_attrs_is_empty (const CK_ATTRIBUTE *attrs); -CK_ULONG p11_attrs_count (CK_ATTRIBUTE *attrs); +CK_ULONG p11_attrs_count (const CK_ATTRIBUTE *attrs); void p11_attrs_free (void *attrs); @@ -67,20 +68,52 @@ CK_ATTRIBUTE * p11_attrs_findn (CK_ATTRIBUTE *attrs, CK_ULONG count, CK_ATTRIBUTE_TYPE type); -CK_BBOOL p11_attrs_remove (CK_ATTRIBUTE *attrs, +bool p11_attrs_find_bool (CK_ATTRIBUTE *attrs, + CK_ATTRIBUTE_TYPE type, + CK_BBOOL *value); + +bool p11_attrs_findn_bool (CK_ATTRIBUTE *attrs, + CK_ULONG count, + CK_ATTRIBUTE_TYPE type, + CK_BBOOL *value); + +bool p11_attrs_find_ulong (CK_ATTRIBUTE *attrs, + CK_ATTRIBUTE_TYPE type, + CK_ULONG *value); + +bool p11_attrs_findn_ulong (CK_ATTRIBUTE *attrs, + CK_ULONG count, + CK_ATTRIBUTE_TYPE type, + CK_ULONG *value); + +CK_ATTRIBUTE * p11_attrs_find_valid (CK_ATTRIBUTE *attrs, CK_ATTRIBUTE_TYPE type); -CK_BBOOL p11_attrs_match (CK_ATTRIBUTE *attrs, - CK_ATTRIBUTE *match); +CK_ATTRIBUTE * p11_attrs_findn_valid (CK_ATTRIBUTE *attrs, + CK_ULONG count, + CK_ATTRIBUTE_TYPE type); + +bool p11_attrs_remove (CK_ATTRIBUTE *attrs, + CK_ATTRIBUTE_TYPE type); -CK_BBOOL p11_attrs_matchn (CK_ATTRIBUTE *attrs, - CK_ATTRIBUTE *match, +bool p11_attrs_match (const CK_ATTRIBUTE *attrs, + const CK_ATTRIBUTE *match); + +bool p11_attrs_matchn (const CK_ATTRIBUTE *attrs, + const CK_ATTRIBUTE *match, CK_ULONG count); -CK_BBOOL p11_attr_equal (CK_ATTRIBUTE *one, - CK_ATTRIBUTE *two); +char * p11_attrs_to_string (const CK_ATTRIBUTE *attrs); + +char * p11_attr_to_string (const CK_ATTRIBUTE *attr); + +bool p11_attr_equal (const void *one, + const void *two); + +unsigned int p11_attr_hash (const void *data); -CK_BBOOL p11_attr_match_boolean (CK_ATTRIBUTE *attr, - CK_BBOOL value); +bool p11_attr_match_value (const CK_ATTRIBUTE *attr, + const void *value, + ssize_t length); #endif /* P11_ATTRS_H_ */ diff --git a/common/tests/test-attrs.c b/common/tests/test-attrs.c index 445695f..ccbb801 100644 --- a/common/tests/test-attrs.c +++ b/common/tests/test-attrs.c @@ -319,6 +319,52 @@ test_equal (CuTest *tc) } static void +test_hash (CuTest *tc) +{ + char *data = "extra attribute"; + CK_ATTRIBUTE one = { CKA_LABEL, "yay", 3 }; + CK_ATTRIBUTE null = { CKA_LABEL, NULL, 3 }; + CK_ATTRIBUTE two = { CKA_VALUE, "yay", 3 }; + CK_ATTRIBUTE other = { CKA_VALUE, data, 5 }; + CK_ATTRIBUTE overflow = { CKA_VALUE, data, 5 }; + CK_ATTRIBUTE content = { CKA_VALUE, "conte", 5 }; + unsigned int hash; + + hash = p11_attr_hash (&one); + CuAssertTrue (tc, hash != 0); + + CuAssertTrue (tc, p11_attr_hash (&one) == hash); + CuAssertTrue (tc, p11_attr_hash (&two) != hash); + CuAssertTrue (tc, p11_attr_hash (&other) != hash); + CuAssertTrue (tc, p11_attr_hash (&overflow) != hash); + CuAssertTrue (tc, p11_attr_hash (&null) != hash); + CuAssertTrue (tc, p11_attr_hash (&content) != hash); +} + +static void +test_to_string (CuTest *tc) +{ + char *data = "extra attribute"; + CK_ATTRIBUTE one = { CKA_LABEL, "yay", 3 }; + CK_ATTRIBUTE attrs[] = { + { CKA_LABEL, "yay", 3 }, + { CKA_VALUE, data, 5 }, + { CKA_INVALID }, + }; + + char *string; + + + string = p11_attr_to_string (&one); + CuAssertStrEquals (tc, "{ CKA_LABEL = (3) \"yay\" }", string); + free (string); + + string = p11_attrs_to_string (attrs); + CuAssertStrEquals (tc, "(2) [ { CKA_LABEL = (3) \"yay\" }, { CKA_VALUE = (5) NOT-PRINTED } ]", string); + free (string); +} + +static void test_find (CuTest *tc) { CK_BBOOL vtrue = CK_TRUE; @@ -461,23 +507,65 @@ test_matchn (CuTest *tc) } static void -test_match_boolean (CuTest *tc) +test_find_bool (CuTest *tc) { CK_BBOOL vtrue = CK_TRUE; CK_BBOOL vfalse = CK_FALSE; - CK_ATTRIBUTE one = { CKA_LABEL, "\x01yy", 3 }; - CK_ATTRIBUTE two = { CKA_LABEL, "\x00yy", 3 }; - CK_ATTRIBUTE atrue = { CKA_TOKEN, &vtrue, sizeof (CK_BBOOL) }; - CK_ATTRIBUTE afalse = { CKA_TOKEN, &vfalse, sizeof (CK_BBOOL) }; - - CuAssertTrue (tc, p11_attr_match_boolean (&atrue, CK_TRUE)); - CuAssertTrue (tc, !p11_attr_match_boolean (&atrue, CK_FALSE)); - CuAssertTrue (tc, p11_attr_match_boolean (&afalse, CK_FALSE)); - CuAssertTrue (tc, !p11_attr_match_boolean (&afalse, CK_TRUE)); - CuAssertTrue (tc, !p11_attr_match_boolean (&one, CK_TRUE)); - CuAssertTrue (tc, !p11_attr_match_boolean (&one, CK_FALSE)); - CuAssertTrue (tc, !p11_attr_match_boolean (&two, CK_FALSE)); - CuAssertTrue (tc, !p11_attr_match_boolean (&two, CK_TRUE)); + CK_BBOOL value; + + CK_ATTRIBUTE attrs[] = { + { CKA_LABEL, "\x01yy", 3 }, + { CKA_VALUE, &vtrue, (CK_ULONG)-1 }, + { CKA_TOKEN, &vtrue, sizeof (CK_BBOOL) }, + { CKA_TOKEN, &vfalse, sizeof (CK_BBOOL) }, + { CKA_INVALID }, + }; + + CuAssertTrue (tc, p11_attrs_find_bool (attrs, CKA_TOKEN, &value) && value == CK_TRUE); + CuAssertTrue (tc, !p11_attrs_find_bool (attrs, CKA_LABEL, &value)); + CuAssertTrue (tc, !p11_attrs_find_bool (attrs, CKA_VALUE, &value)); +} + +static void +test_find_ulong (CuTest *tc) +{ + CK_ULONG v33 = 33UL; + CK_ULONG v45 = 45UL; + CK_ULONG value; + + CK_ATTRIBUTE attrs[] = { + { CKA_LABEL, &v33, 2 }, + { CKA_VALUE, &v45, (CK_ULONG)-1 }, + { CKA_BITS_PER_PIXEL, &v33, sizeof (CK_ULONG) }, + { CKA_BITS_PER_PIXEL, &v45, sizeof (CK_ULONG) }, + { CKA_INVALID }, + }; + + CuAssertTrue (tc, p11_attrs_find_ulong (attrs, CKA_BITS_PER_PIXEL, &value) && value == v33); + CuAssertTrue (tc, !p11_attrs_find_ulong (attrs, CKA_LABEL, &value)); + CuAssertTrue (tc, !p11_attrs_find_ulong (attrs, CKA_VALUE, &value)); +} + +static void +test_find_valid (CuTest *tc) +{ + CK_ATTRIBUTE *attr; + + CK_ATTRIBUTE attrs[] = { + { CKA_LABEL, "", (CK_ULONG)-1 }, + { CKA_LABEL, "test", 4 }, + { CKA_VALUE, NULL, 0 }, + { CKA_INVALID }, + }; + + attr = p11_attrs_find_valid (attrs, CKA_LABEL); + CuAssertPtrEquals (tc, attrs + 1, attr); + + attr = p11_attrs_find_valid (attrs, CKA_VALUE); + CuAssertPtrEquals (tc, attrs + 2, attr); + + attr = p11_attrs_find_valid (attrs, CKA_TOKEN); + CuAssertPtrEquals (tc, NULL, attr); } int @@ -490,6 +578,10 @@ main (void) setenv ("P11_KIT_STRICT", "1", 1); p11_debug_init (); + SUITE_ADD_TEST (suite, test_equal); + SUITE_ADD_TEST (suite, test_hash); + SUITE_ADD_TEST (suite, test_to_string); + SUITE_ADD_TEST (suite, test_count); SUITE_ADD_TEST (suite, test_build_one); SUITE_ADD_TEST (suite, test_build_two); @@ -505,11 +597,11 @@ main (void) SUITE_ADD_TEST (suite, test_matchn); SUITE_ADD_TEST (suite, test_find); SUITE_ADD_TEST (suite, test_findn); + SUITE_ADD_TEST (suite, test_find_bool); + SUITE_ADD_TEST (suite, test_find_ulong); + SUITE_ADD_TEST (suite, test_find_valid); SUITE_ADD_TEST (suite, test_remove); - SUITE_ADD_TEST (suite, test_match_boolean); - SUITE_ADD_TEST (suite, test_equal); - CuSuiteRun (suite); CuSuiteSummary (suite, output); CuSuiteDetails (suite, output); |