[Cryptech-Commits] [sw/pkcs11] 01/04: Add C_CreateObject(), which required refactoring some of the template-checking code.

git at cryptech.is git at cryptech.is
Wed Sep 16 05:01:09 UTC 2015


This is an automated email from the git hooks/post-receive script.

sra at hactrn.net pushed a commit to branch ecdsa
in repository sw/pkcs11.

commit cdb4d3a72091bebc4f0763980aabcea5dc0bc93d
Author: Rob Austein <sra at hactrn.net>
Date:   Tue Sep 15 14:14:16 2015 -0400

    Add C_CreateObject(), which required refactoring some of the template-checking code.
---
 pkcs11.c           | 243 +++++++++++++++++++++++++++++++++++++++++++----------
 py11/attributes.py |   6 ++
 2 files changed, 205 insertions(+), 44 deletions(-)

diff --git a/pkcs11.c b/pkcs11.c
index 2f6fcde..83d0ed4 100644
--- a/pkcs11.c
+++ b/pkcs11.c
@@ -726,13 +726,13 @@ static int p11_attribute_get(const CK_OBJECT_HANDLE object_handle,
  * Wrappers to set and get CK_BBOOL and CK_ULONG values.
  */
 
-#if 0
-
 static int p11_attribute_set_bbool(const CK_OBJECT_HANDLE object_handle, const CK_ATTRIBUTE_TYPE type, const CK_BBOOL value)
 {
   return p11_attribute_set(object_handle, type, &value, sizeof(value));
 }
 
+#if 0
+
 static int p11_attribute_set_ulong(const CK_OBJECT_HANDLE object_handle, const CK_ATTRIBUTE_TYPE type, const CK_ULONG value)
 {
   return p11_attribute_set(object_handle, type, &value, sizeof(value));
@@ -761,10 +761,8 @@ static int p11_attribute_find_in_template(const CK_ATTRIBUTE_TYPE type,
                                           const CK_ATTRIBUTE_PTR template,
                                           const CK_ULONG length)
 {
-  int i;
-
   if (template != NULL)
-    for (i = 0; i < length; i++)
+    for (int i = 0; i < length; i++)
       if (template[i].type == type)
         return i;
 
@@ -772,6 +770,19 @@ static int p11_attribute_find_in_template(const CK_ATTRIBUTE_TYPE type,
 }
 
 /*
+ * Find an attribute in a CK_ATTRIBUTE_PTR template.  Returns pointer
+ * to attribute value, or NULL if not found.
+ */
+
+static void *p11_attribute_find_value_in_template(const CK_ATTRIBUTE_TYPE type,
+                                                  const CK_ATTRIBUTE_PTR template,
+                                                  const CK_ULONG length)
+{
+  const int i = p11_attribute_find_in_template(type, template, length);
+  return i < 0 ? NULL : template[i].pValue;
+}
+
+/*
  * Map a keyusage-related attribute to a keyusage bit flag.
  *
  * Assumes that calling code has already checked whether this
@@ -1676,8 +1687,7 @@ static int psnprintf(void *buffer_, size_t size, const char *format, ...)
 /*
  * Template checking and key generation.
  *
- * This may need refactoring at some point, eg, when we add support
- * for C_CreateObject().
+ * The checking code needs refactoring to support C_CreateObject().
  */
 
 /*
@@ -1686,16 +1696,17 @@ static int psnprintf(void *buffer_, size_t size, const char *format, ...)
  * attribute type.
  */
 
-static CK_RV p11_check_keypair_attributes_check_template_1(const CK_ATTRIBUTE_TYPE type,
-                                                           const void * const val,
-                                                           const size_t len,
-                                                           const p11_descriptor_t * const descriptor)
+static CK_RV p11_template_check_1(const CK_ATTRIBUTE_TYPE type,
+                                  const void * const val,
+                                  const size_t len,
+                                  const p11_descriptor_t * const descriptor,
+                                  unsigned long forbidden_flag)
 {
   const p11_attribute_descriptor_t * const atd = p11_find_attribute_in_descriptor(descriptor, type);
   CK_RV rv;
 
   /* Attribute not allowed or not allowed for key generation */
-  if (atd == NULL || (atd->flags & P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE) != 0)
+  if (atd == NULL || (atd->flags & forbidden_flag) != 0)
     lose(CKR_ATTRIBUTE_TYPE_INVALID);
 
   /* NULL or wrong-sized attribute values */
@@ -1710,13 +1721,14 @@ static CK_RV p11_check_keypair_attributes_check_template_1(const CK_ATTRIBUTE_TY
   if (atd->value != NULL && (atd->flags & P11_DESCRIPTOR_DEFAULT_VALUE) == 0 && memcmp(val, atd->value, atd->length) != 0)
     lose(CKR_TEMPLATE_INCONSISTENT);
 
+#warning Add _LATCH checks here? 
+
   rv = CKR_OK;
 
  fail:
 #if DEBUG_PKCS11
   if (rv != CKR_OK)
-    fprintf(stderr, "p11_check_keypair_attributes_check_template_1() rejected attribute 0x%08lx\n",
-            (unsigned long) type);
+    fprintf(stderr, "p11_template_check_1() rejected attribute 0x%08lx\n", (unsigned long) type);
 #endif
   return rv;
 }
@@ -1726,10 +1738,12 @@ static CK_RV p11_check_keypair_attributes_check_template_1(const CK_ATTRIBUTE_TY
  * required for that template has been specified exactly once.
  */
 
-static CK_RV p11_check_keypair_attributes_check_template_2(const p11_session_t *session,
-                                                           const p11_descriptor_t * const descriptor,
-                                                           const CK_ATTRIBUTE_PTR template,
-                                                           const CK_ULONG template_length)
+static CK_RV p11_template_check_2(const p11_session_t *session,
+                                  const p11_descriptor_t * const descriptor,
+                                  const CK_ATTRIBUTE_PTR template,
+                                  const CK_ULONG template_length,
+                                  unsigned long required_flag,
+                                  unsigned long forbidden_flag)
 {
   const CK_BBOOL *object_is_private;
   CK_RV rv;
@@ -1743,11 +1757,7 @@ static CK_RV p11_check_keypair_attributes_check_template_2(const p11_session_t *
   case CKS_RO_PUBLIC_SESSION:
   case CKS_RW_PUBLIC_SESSION:
   case CKS_RW_SO_FUNCTIONS:
-    if ((i = p11_attribute_find_in_template(CKA_PRIVATE, template, template_length)) >= 0) {
-      assert(template[i].pValue != NULL);
-      object_is_private = template[i].pValue;
-    }
-    else {
+    if ((object_is_private = p11_attribute_find_value_in_template(CKA_PRIVATE, template, template_length)) == NULL) {
       const p11_attribute_descriptor_t * const atd = p11_find_attribute_in_descriptor(descriptor, CKA_PRIVATE);
       assert(atd != NULL && atd->value != NULL);
       object_is_private = atd->value;
@@ -1758,8 +1768,8 @@ static CK_RV p11_check_keypair_attributes_check_template_2(const p11_session_t *
 
   for (i = 0; i < descriptor->n_attributes; i++) {
     const p11_attribute_descriptor_t * const atd = &descriptor->attributes[i];
-    const int required_by_api  = (atd->flags & P11_DESCRIPTOR_REQUIRED_BY_GENERATE) != 0;
-    const int forbidden_by_api = (atd->flags & P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE) != 0;
+    const int required_by_api  = (atd->flags & required_flag) != 0;
+    const int forbidden_by_api = (atd->flags & forbidden_flag) != 0;
     const int in_descriptor    = (atd->flags & P11_DESCRIPTOR_DEFAULT_VALUE) != 0 || atd->value != NULL;
     const int pos_in_template  = p11_attribute_find_in_template(atd->type, template, template_length);
 
@@ -1835,7 +1845,8 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
     const void * const       val = pPublicKeyTemplate[i].pValue;
     const size_t             len = pPublicKeyTemplate[i].ulValueLen;
 
-    if ((rv = p11_check_keypair_attributes_check_template_1(type, val, len, public_descriptor)) != CKR_OK)
+    if ((rv = p11_template_check_1(type, val, len, public_descriptor,
+                                   P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE)) != CKR_OK)
       goto fail;
 
     p11_attribute_apply_keyusage(&public_keyusage, type, val);
@@ -1846,7 +1857,8 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
     const void * const       val = pPrivateKeyTemplate[i].pValue;
     const size_t             len = pPrivateKeyTemplate[i].ulValueLen;
 
-    if ((rv = p11_check_keypair_attributes_check_template_1(type, val, len, private_descriptor)) != CKR_OK)
+    if ((rv = p11_template_check_1(type, val, len, private_descriptor,
+                                   P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE)) != CKR_OK)
       goto fail;
 
     p11_attribute_apply_keyusage(&private_keyusage, type, val);
@@ -1864,14 +1876,18 @@ static CK_RV p11_check_keypair_attributes(const p11_session_t *session,
    * Check that all required attributes have been specified.
    */
 
-  if ((rv = p11_check_keypair_attributes_check_template_2(session,
-                                                          public_descriptor,
-                                                          pPublicKeyTemplate,
-                                                          ulPublicKeyAttributeCount))  != CKR_OK ||
-      (rv = p11_check_keypair_attributes_check_template_2(session,
-                                                          private_descriptor,
-                                                          pPrivateKeyTemplate,
-                                                          ulPrivateKeyAttributeCount)) != CKR_OK)
+  if ((rv = p11_template_check_2(session,
+                                 public_descriptor,
+                                 pPublicKeyTemplate,
+                                 ulPublicKeyAttributeCount,
+                                 P11_DESCRIPTOR_REQUIRED_BY_GENERATE,
+                                 P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE))  != CKR_OK ||
+      (rv = p11_template_check_2(session,
+                                 private_descriptor,
+                                 pPrivateKeyTemplate,
+                                 ulPrivateKeyAttributeCount,
+                                 P11_DESCRIPTOR_REQUIRED_BY_GENERATE,
+                                 P11_DESCRIPTOR_FORBIDDEN_BY_GENERATE)) != CKR_OK)
     goto fail;
 
   /*
@@ -2100,6 +2116,69 @@ static CK_RV generate_keypair(p11_session_t *session,
   return rv;
 }
 
+/*
+ * Mechanism-independent checks for templates and descriptors when
+ * import objects via C_CreateObject().
+ *
+ * Fun question exactly how calling code knows what descriptor to
+ * pass.  p11_descriptor_from_key_type() will suffice for key objects.
+ * Drive off that bridge when we get to it.
+ */
+
+static CK_RV p11_check_create_attributes(const p11_session_t *session,
+                                         const CK_ATTRIBUTE_PTR pTemplate,
+                                         const CK_ULONG ulCount,
+                                         const p11_descriptor_t * const descriptor)
+{
+  CK_RV rv = CKR_OK;
+  int i;
+
+  assert(session != NULL && pTemplate != NULL && descriptor != NULL);
+
+  /*
+   * Read-only sessions can't create objects, doh.
+   */
+
+  switch (session->state) {
+  case CKS_RO_PUBLIC_SESSION:
+  case CKS_RO_USER_FUNCTIONS:
+    lose(CKR_SESSION_READ_ONLY);
+  }
+
+  /*
+   * Check values provided in the template.
+   */
+
+  for (i = 0; i < ulCount; i++) {
+    const CK_ATTRIBUTE_TYPE type = pTemplate[i].type;
+    const void * const       val = pTemplate[i].pValue;
+    const size_t             len = pTemplate[i].ulValueLen;
+
+    if ((rv = p11_template_check_1(type, val, len, descriptor,
+                                   P11_DESCRIPTOR_FORBIDDEN_BY_CREATEOBJECT)) != CKR_OK)
+      goto fail;
+  }
+
+  /*
+   * Check that all required attributes have been specified.
+   */
+
+  if ((rv = p11_template_check_2(session, descriptor, pTemplate, ulCount,
+                                 P11_DESCRIPTOR_REQUIRED_BY_CREATEOBJECT,
+                                 P11_DESCRIPTOR_FORBIDDEN_BY_CREATEOBJECT)) != CKR_OK)
+    goto fail;
+
+  /*
+   * If we get this far, we're happy.  Maybe.
+   */
+
+  rv = CKR_OK;
+
+ fail:
+  return rv;
+}
+
+
 

 
 /*
@@ -3061,6 +3140,91 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
   mutex_unlock_return_with_rv(rv, p11_global_mutex);
 }
 
+CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
+                     CK_ATTRIBUTE_PTR pTemplate,
+                     CK_ULONG ulCount,
+                     CK_OBJECT_HANDLE_PTR phObject)
+{
+  ENTER_PUBLIC_FUNCTION(C_CreateObject);
+
+  p11_session_t *session;
+  CK_RV rv;
+
+  mutex_lock_or_return_failure(p11_global_mutex);
+
+  if ((session = p11_session_find(hSession)) == NULL)
+    lose(CKR_SESSION_HANDLE_INVALID);
+
+  if (pTemplate == NULL || phObject == NULL)
+    lose(CKR_ARGUMENTS_BAD);
+
+  const CK_OBJECT_CLASS * const cka_class = p11_attribute_find_value_in_template(CKA_CLASS,    pTemplate, ulCount);
+  const CK_KEY_TYPE * const cka_key_type  = p11_attribute_find_value_in_template(CKA_KEY_TYPE, pTemplate, ulCount);
+  const CK_BBOOL * const cka_token        = p11_attribute_find_value_in_template(CKA_TOKEN,    pTemplate, ulCount);
+
+  if (cka_class == NULL)
+    lose(CKR_TEMPLATE_INCOMPLETE);
+
+  switch (*cka_class) {
+  case CKO_PUBLIC_KEY:
+  case CKO_PRIVATE_KEY:
+  case CKO_SECRET_KEY:
+    break;
+  default:
+    lose(CKR_TEMPLATE_INCONSISTENT);
+  }
+
+  if (cka_key_type == NULL)
+    lose(CKR_TEMPLATE_INCOMPLETE);
+
+  const p11_descriptor_t * const
+    descriptor = p11_descriptor_from_key_type(*cka_class, *cka_key_type);
+
+  if (descriptor == NULL)
+    lose(CKR_TEMPLATE_INCONSISTENT);
+
+  if ((rv = p11_check_create_attributes(session, pTemplate, ulCount, descriptor)) != CKR_OK)
+    goto fail;
+
+  switch (session->state) {
+  case CKS_RO_PUBLIC_SESSION:
+  case CKS_RO_USER_FUNCTIONS:
+    if (cka_token != NULL && *cka_token)
+      lose(CKR_SESSION_READ_ONLY);
+  }
+
+  if (!sql_exec("BEGIN"))
+    lose(CKR_FUNCTION_FAILED);
+
+  const handle_flavor_t flavor
+    = cka_token == NULL ? handle_flavor_session_object : p11_handle_flavor_from_cka_token(cka_token);
+
+  CK_OBJECT_HANDLE handle = p11_object_create(session, flavor, pTemplate, ulCount, descriptor, NULL);
+
+  if (!p11_attribute_set_bbool(handle, CKA_LOCAL, CK_FALSE))
+    lose(CKR_FUNCTION_FAILED);
+
+  switch (*cka_class) {
+  case CKO_PRIVATE_KEY:
+  case CKO_SECRET_KEY:
+    if (!p11_attribute_set_bbool(handle, CKA_ALWAYS_SENSITIVE,  CK_FALSE) || 
+        !p11_attribute_set_bbool(handle, CKA_NEVER_EXTRACTABLE, CK_FALSE))
+      lose(CKR_FUNCTION_FAILED);
+  }
+
+  if (!sql_exec("COMMIT"))
+    lose(CKR_FUNCTION_FAILED);
+
+  *phObject = handle;
+
+  return mutex_unlock(p11_global_mutex);
+
+ fail:
+  if (!sql_exec("ROLLBACK"))
+    rv = CKR_GENERAL_ERROR;
+  mutex_unlock_return_with_rv(rv, p11_global_mutex);
+}
+
 CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession,
                       CK_OBJECT_HANDLE hObject)
 {
@@ -4237,15 +4401,6 @@ CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession,
   return CKR_FUNCTION_NOT_SUPPORTED;
 }
 
-CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
-                     CK_ATTRIBUTE_PTR pTemplate,
-                     CK_ULONG ulCount,
-                     CK_OBJECT_HANDLE_PTR phObject)
-{
-  ENTER_PUBLIC_FUNCTION(C_CreateObject);
-  return CKR_FUNCTION_NOT_SUPPORTED;
-}
-
 CK_RV C_CopyObject(CK_SESSION_HANDLE hSession,
                    CK_OBJECT_HANDLE hObject,
                    CK_ATTRIBUTE_PTR pTemplate,
diff --git a/py11/attributes.py b/py11/attributes.py
index 7c90768..32cf940 100644
--- a/py11/attributes.py
+++ b/py11/attributes.py
@@ -93,3 +93,9 @@ class AttributeDB(object):
       template[i].pValue = create_string_buffer(v)
       template[i].ulValueLen = len(v)
     return template
+
+  def attribute_name(self, code):
+    return self.db[code].name
+
+  def attribute_code(self, name):
+    return self.db[name].code



More information about the Commits mailing list