summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 4cbb7ea)
raw | patch | inline | side by side (parent: 4cbb7ea)
author | Ruchika Gupta <ruchika.gupta@linaro.org> | |
Thu, 10 Dec 2020 09:47:50 +0000 (15:17 +0530) | ||
committer | Jérôme Forissier <jerome@forissier.org> | |
Wed, 23 Dec 2020 08:51:29 +0000 (09:51 +0100) |
Adds support of mechanisms PKCS11_CKM_GENERIC_SECRET_KEY_GEN,
PKCS11_CKM_AES_KEY_GEN for key generation API.
Co-developed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org>
Reviewed-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
PKCS11_CKM_AES_KEY_GEN for key generation API.
Co-developed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org>
Reviewed-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
index 4c23281e50f8b6cb915ab605e8709a95d02b8094..3454f7a8fa1ccd5ad09e49771140cc9ef338acb6 100644 (file)
return rc;
}
+static enum pkcs11_rc _remove_attribute(struct obj_attrs **head,
+ uint32_t attribute, bool empty)
+{
+ struct obj_attrs *h = *head;
+ char *cur = NULL;
+ char *end = NULL;
+ size_t next_off = 0;
+
+ /* Let's find the target attribute */
+ cur = (char *)h + sizeof(struct obj_attrs);
+ end = cur + h->attrs_size;
+ for (; cur < end; cur += next_off) {
+ struct pkcs11_attribute_head pkcs11_ref = { };
+
+ TEE_MemMove(&pkcs11_ref, cur, sizeof(pkcs11_ref));
+ next_off = sizeof(pkcs11_ref) + pkcs11_ref.size;
+
+ if (pkcs11_ref.id != attribute)
+ continue;
+
+ if (empty && pkcs11_ref.size)
+ return PKCS11_CKR_FUNCTION_FAILED;
+
+ TEE_MemMove(cur, cur + next_off, end - (cur + next_off));
+
+ h->attrs_count--;
+ h->attrs_size -= next_off;
+ end -= next_off;
+ next_off = 0;
+
+ return PKCS11_CKR_OK;
+ }
+
+ DMSG("Attribute %s (%#x) not found", id2str_attr(attribute), attribute);
+ return PKCS11_RV_NOT_FOUND;
+}
+
+enum pkcs11_rc remove_empty_attribute(struct obj_attrs **head,
+ uint32_t attribute)
+{
+ return _remove_attribute(head, attribute, true /* empty */);
+}
+
void get_attribute_ptrs(struct obj_attrs *head, uint32_t attribute,
void **attr, uint32_t *attr_size, size_t *count)
{
index 293c67fd109d4958c8b2178a62e31848ff4fd1eb..353989f4a43f3f7a7606bb0ae8710437f6d044fd 100644 (file)
enum pkcs11_rc add_attribute(struct obj_attrs **head, uint32_t attribute,
void *data, size_t size);
+/*
+ * Update serialized attributes to remove an empty entry. Can relocate the
+ * attribute list buffer. Only 1 instance of the entry is expected.
+ *
+ * Return PKCS11_CKR_OK on success or a PKCS11 return code.
+ */
+enum pkcs11_rc remove_empty_attribute(struct obj_attrs **head, uint32_t attrib);
+
/*
* get_attribute_ptrs() - Get pointers to attributes with a given ID
* @head: Pointer to serialized attributes
diff --git a/ta/pkcs11/src/entry.c b/ta/pkcs11/src/entry.c
index c4bd04d2a26f48dc9d07946f3ad860a826b356c0..947f71bd93ad5ce767204de82effc6cb26bbe7a9 100644 (file)
--- a/ta/pkcs11/src/entry.c
+++ b/ta/pkcs11/src/entry.c
PKCS11_FUNCTION_VERIFY,
PKCS11_FUNC_STEP_FINAL);
break;
+ case PKCS11_CMD_GENERATE_KEY:
+ rc = entry_generate_secret(client, ptypes, params);
+ break;
default:
EMSG("Command %#"PRIx32" is not supported", cmd);
return TEE_ERROR_NOT_SUPPORTED;
index c183f910ddb3566569a15bd7fea364fb1fdb0a91..2d7148a68a3d663dd37d20a8a2bbeaabb1bc464c 100644 (file)
size_t template_size,
struct obj_attrs *parent __unused,
enum processing_func function,
- enum pkcs11_mechanism_id mecha __unused)
+ enum pkcs11_mechanism_id mecha)
{
struct obj_attrs *temp = NULL;
struct obj_attrs *attrs = NULL;
uint8_t local = 0;
uint8_t always_sensitive = 0;
uint8_t never_extract = 0;
+ uint32_t class = PKCS11_UNDEFINED_ID;
+ uint32_t type = PKCS11_UNDEFINED_ID;
uint32_t mechanism_id = PKCS11_CKM_UNDEFINED_ID;
#ifdef DEBUG /* Sanity: check function argument */
trace_attributes_from_api_head("template", template, template_size);
switch (function) {
+ case PKCS11_FUNCTION_GENERATE:
case PKCS11_FUNCTION_IMPORT:
break;
default:
/* If class/type not defined, match from mechanism */
if (get_class(temp) == PKCS11_UNDEFINED_ID &&
get_key_type(temp) == PKCS11_UNDEFINED_ID) {
- EMSG("Unable to define class/type from mechanism");
- rc = PKCS11_CKR_TEMPLATE_INCOMPLETE;
- goto out;
+ switch (mecha) {
+ case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
+ class = PKCS11_CKO_SECRET_KEY;
+ type = PKCS11_CKK_GENERIC_SECRET;
+ break;
+ case PKCS11_CKM_AES_KEY_GEN:
+ class = PKCS11_CKO_SECRET_KEY;
+ type = PKCS11_CKK_AES;
+ break;
+ default:
+ EMSG("Unable to define class/type from mechanism");
+ rc = PKCS11_CKR_TEMPLATE_INCOMPLETE;
+ goto out;
+ }
+ if (class != PKCS11_UNDEFINED_ID) {
+ rc = add_attribute(&temp, PKCS11_CKA_CLASS,
+ &class, sizeof(uint32_t));
+ if (rc)
+ goto out;
+ }
+ if (type != PKCS11_UNDEFINED_ID) {
+ rc = add_attribute(&temp, PKCS11_CKA_KEY_TYPE,
+ &type, sizeof(uint32_t));
+ if (rc)
+ goto out;
+ }
+ }
+
+ switch (mecha) {
+ case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
+ if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
+ get_key_type(temp) != PKCS11_CKK_GENERIC_SECRET) {
+ rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
+ goto out;
+ }
+ break;
+ case PKCS11_CKM_AES_KEY_GEN:
+ if (get_class(temp) != PKCS11_CKO_SECRET_KEY ||
+ get_key_type(temp) != PKCS11_CKK_AES) {
+ rc = PKCS11_CKR_TEMPLATE_INCONSISTENT;
+ goto out;
+ }
+ break;
+ default:
+ break;
}
if (!sanitize_consistent_class_and_type(temp)) {
}
switch (function) {
+ case PKCS11_FUNCTION_GENERATE:
+ local = PKCS11_TRUE;
+ break;
case PKCS11_FUNCTION_IMPORT:
default:
local = PKCS11_FALSE;
always_sensitive = PKCS11_FALSE;
never_extract = PKCS11_FALSE;
+ switch (function) {
+ case PKCS11_FUNCTION_GENERATE:
+ always_sensitive = get_bool(attrs,
+ PKCS11_CKA_SENSITIVE);
+ never_extract = !get_bool(attrs,
+ PKCS11_CKA_EXTRACTABLE);
+ break;
+ default:
+ break;
+ }
+
rc = add_attribute(&attrs, PKCS11_CKA_ALWAYS_SENSITIVE,
&always_sensitive, sizeof(always_sensitive));
if (rc)
goto out;
/* Keys mandate attribute PKCS11_CKA_KEY_GEN_MECHANISM */
- mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
+ if (local)
+ mechanism_id = mecha;
+ else
+ mechanism_id = PKCS11_CK_UNAVAILABLE_INFORMATION;
+
rc = add_attribute(&attrs, PKCS11_CKA_KEY_GEN_MECHANISM,
&mechanism_id, sizeof(mechanism_id));
if (rc)
case PKCS11_PROCESSING_IMPORT:
assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, false));
break;
+ case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
+ case PKCS11_CKM_AES_KEY_GEN:
+ assert(check_attr_bval(proc_id, head, PKCS11_CKA_LOCAL, true));
+ break;
default:
TEE_Panic(proc_id);
break;
}
+ switch (proc_id) {
+ case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
+ assert(get_key_type(head) == PKCS11_CKK_GENERIC_SECRET);
+ break;
+ case PKCS11_CKM_AES_KEY_GEN:
+ assert(get_key_type(head) == PKCS11_CKK_AES);
+ break;
+ case PKCS11_PROCESSING_IMPORT:
+ default:
+ break;
+ }
+
return PKCS11_CKR_OK;
}
enum pkcs11_mechanism_id mechanism = PKCS11_CKM_UNDEFINED_ID;
switch (key_type) {
+ case PKCS11_CKK_GENERIC_SECRET:
+ mechanism = PKCS11_CKM_GENERIC_SECRET_KEY_GEN;
+ break;
case PKCS11_CKK_AES:
mechanism = PKCS11_CKM_AES_KEY_GEN;
break;
index d5b0d4b1403514ba9fe3214b8f5ec9d2ac3b1546..bd2a8ee548d9b4dff1f6f0549ca1c5c993943caa 100644 (file)
PKCS11_ID(PKCS11_CMD_VERIFY_FINAL),
PKCS11_ID(PKCS11_CMD_SIGN_ONESHOT),
PKCS11_ID(PKCS11_CMD_VERIFY_ONESHOT),
+ PKCS11_ID(PKCS11_CMD_GENERATE_KEY),
};
static const struct any_id __maybe_unused string_slot_flags[] = {
index 6fbeb1bb6e08519202b05e61d546ed8f7c0a8b1e..06ddbe4a5c9e2281659e8851de4027c5bb94dd38 100644 (file)
}
}
+static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head)
+{
+ enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
+ void *data = NULL;
+ uint32_t data_size = 0;
+ uint32_t value_len = 0;
+ void *value = NULL;
+
+ if (!*head)
+ return PKCS11_CKR_TEMPLATE_INCONSISTENT;
+
+ rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size);
+ if (rc || data_size != sizeof(uint32_t)) {
+ DMSG("%s", rc ? "No attribute value_len found" :
+ "Invalid size for attribute VALUE_LEN");
+
+ return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ TEE_MemMove(&value_len, data, data_size);
+
+ if (get_key_type(*head) == PKCS11_CKK_GENERIC_SECRET)
+ value_len = (value_len + 7) / 8;
+
+ /* Remove the default empty value attribute if found */
+ rc = remove_empty_attribute(head, PKCS11_CKA_VALUE);
+ if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND)
+ return PKCS11_CKR_GENERAL_ERROR;
+
+ value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+ if (!value)
+ return PKCS11_CKR_DEVICE_MEMORY;
+
+ TEE_GenerateRandom(value, value_len);
+
+ rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len);
+
+ TEE_Free(value);
+
+ return rc;
+}
+
+enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
+ uint32_t ptypes, TEE_Param *params)
+{
+ const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_MEMREF_OUTPUT,
+ TEE_PARAM_TYPE_NONE);
+ TEE_Param *ctrl = params;
+ TEE_Param *out = params + 2;
+ enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
+ struct serialargs ctrlargs = { };
+ struct pkcs11_session *session = NULL;
+ struct pkcs11_attribute_head *proc_params = NULL;
+ struct obj_attrs *head = NULL;
+ struct pkcs11_object_head *template = NULL;
+ size_t template_size = 0;
+ uint32_t obj_handle = 0;
+
+ if (!client || ptypes != exp_pt ||
+ out->memref.size != sizeof(obj_handle))
+ return PKCS11_CKR_ARGUMENTS_BAD;
+
+ serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size);
+
+ rc = serialargs_get_session_from_handle(&ctrlargs, client, &session);
+ if (rc)
+ return rc;
+
+ rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params);
+ if (rc)
+ goto out;
+
+ rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rc)
+ goto out;
+
+ if (serialargs_remaining_bytes(&ctrlargs)) {
+ rc = PKCS11_CKR_ARGUMENTS_BAD;
+ goto out;
+ }
+
+ rc = get_ready_session(session);
+ if (rc)
+ goto out;
+
+ template_size = sizeof(*template) + template->attrs_size;
+
+ rc = check_mechanism_against_processing(session, proc_params->id,
+ PKCS11_FUNCTION_GENERATE,
+ PKCS11_FUNC_STEP_INIT);
+ if (rc) {
+ DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc);
+ goto out;
+ }
+
+ /*
+ * Prepare a clean initial state for the requested object attributes.
+ * Free temporary template once done.
+ */
+ rc = create_attributes_from_template(&head, template, template_size,
+ NULL, PKCS11_FUNCTION_GENERATE,
+ proc_params->id);
+ if (rc)
+ goto out;
+
+ TEE_Free(template);
+ template = NULL;
+
+ rc = check_created_attrs(head, NULL);
+ if (rc)
+ goto out;
+
+ rc = check_created_attrs_against_processing(proc_params->id, head);
+ if (rc)
+ goto out;
+
+ rc = check_created_attrs_against_token(session, head);
+ if (rc)
+ goto out;
+
+ /*
+ * Execute target processing and add value as attribute
+ * PKCS11_CKA_VALUE. Symm key generation: depends on target
+ * processing to be used.
+ */
+ switch (proc_params->id) {
+ case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
+ case PKCS11_CKM_AES_KEY_GEN:
+ /* Generate random of size specified by attribute VALUE_LEN */
+ rc = generate_random_key_value(&head);
+ if (rc)
+ goto out;
+ break;
+
+ default:
+ rc = PKCS11_CKR_MECHANISM_INVALID;
+ goto out;
+ }
+
+ TEE_Free(proc_params);
+ proc_params = NULL;
+
+ /*
+ * Object is ready, register it and return a handle.
+ */
+ rc = create_object(session, head, &obj_handle);
+ if (rc)
+ goto out;
+
+ /*
+ * Now obj_handle (through the related struct pkcs11_object instance)
+ * owns the serialized buffer that holds the object attributes.
+ * We reset head to NULL as it is no more the buffer owner and would
+ * be freed at function out.
+ */
+ head = NULL;
+
+ TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle));
+ out->memref.size = sizeof(obj_handle);
+
+ DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32,
+ session->handle, obj_handle);
+
+out:
+ TEE_Free(proc_params);
+ TEE_Free(template);
+ TEE_Free(head);
+
+ return rc;
+}
+
/*
* entry_processing_init - Generic entry for initializing a processing
*
index d668b53e109ad0ed6b5d0336fae5ca6b14eb2ec7..afeaf2aae4d32df1f2c09bbba8eea0dec885fc50 100644 (file)
* Entry points from PKCS11 TA invocation commands
*/
+enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client,
+ uint32_t ptypes, TEE_Param *params);
+
enum pkcs11_rc entry_processing_init(struct pkcs11_client *client,
uint32_t ptypes, TEE_Param *params,
enum processing_func function);
index 7d985fcebbef5f5920e756e070a949495981efb3..06f928919b0a431f724af09a66055dd1740d65ac 100644 (file)
MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE,
ANY_PART),
MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE, ANY_PART),
+ MECHANISM(PKCS11_CKM_GENERIC_SECRET_KEY_GEN, PKCS11_CKFM_GENERATE,
+ ANY_PART),
/* HMAC */
MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
TA_MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER),
TA_MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
TA_MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
+ TA_MECHANISM(PKCS11_CKM_AES_KEY_GEN, PKCS11_CKFM_GENERATE),
+ TA_MECHANISM(PKCS11_CKM_GENERIC_SECRET_KEY_GEN, PKCS11_CKFM_GENERATE),
TA_MECHANISM(PKCS11_CKM_MD5_HMAC, CKFM_AUTH_NO_RECOVER),
TA_MECHANISM(PKCS11_CKM_SHA_1_HMAC, CKFM_AUTH_NO_RECOVER),
TA_MECHANISM(PKCS11_CKM_SHA224_HMAC, CKFM_AUTH_NO_RECOVER),
uint32_t *max_key_size)
{
switch (proc_id) {
+ case PKCS11_CKM_GENERIC_SECRET_KEY_GEN:
+ /* This mechanism expects the keysize to be returned in bits */
+ *min_key_size = 1; /* in bits */
+ *max_key_size = 4096; /* in bits */
+ break;
case PKCS11_CKM_MD5_HMAC:
*min_key_size = 8;
*max_key_size = 64;