Further tweaks and cleanup for functions dealing with PKCS#11 attributes
authorStef Walter <stefw@gnome.org>
Thu, 24 Jan 2013 13:36:59 +0000 (14:36 +0100)
committerStef Walter <stefw@gnome.org>
Mon, 4 Feb 2013 09:55:45 +0000 (10:55 +0100)
 * 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

common/attrs.c
common/attrs.h
common/tests/test-attrs.c

index dd91afc79bc435a6c00ca077d25235ee036b95da..ab1bc59aec23dd4b2f2657d3048c7be2814927c5 100644 (file)
 #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);
 }
index 12a2798623a3df4f738a605d91c8fbfcb458f5fb..870f0d15a640b78213a87c7230373126ef142201 100644 (file)
 #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_ */
index 445695f605661a17fce7b262e35bec7d73b2027b..ccbb8019895abbe677cab9311499919a7b58268a 100644 (file)
@@ -318,6 +318,52 @@ test_equal (CuTest *tc)
        CuAssertTrue (tc, !p11_attr_equal (&other, &content));
 }
 
+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)
 {
@@ -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);