aboutsummaryrefslogtreecommitdiff
path: root/pkcs11.c
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2015-09-15 14:14:16 -0400
committerRob Austein <sra@hactrn.net>2015-09-15 14:14:16 -0400
commitcdb4d3a72091bebc4f0763980aabcea5dc0bc93d (patch)
treebd8e873c1ed9786c5bf54d39c5ac5f93c7dd21e5 /pkcs11.c
parent3345ef8b1a7ad719dbd3a0f26697c6bc4bd884b1 (diff)
Add C_CreateObject(), which required refactoring some of the template-checking code.
Diffstat (limited to 'pkcs11.c')
-rw-r--r--pkcs11.c243
1 files changed, 199 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,