summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuchika Gupta <ruchika.gupta@linaro.org>2021-01-13 10:33:43 +0530
committerJérôme Forissier <jerome@forissier.org>2021-01-13 19:13:46 +0100
commit783c1515c2f9b22497651dee269cd849fd908a56 (patch)
treebe649a8fbba8e5f75f3d478731c758752362916b
parentdc99b202f3997248adbe7508698c051f6d677cd0 (diff)
ta: pkcs11: Add support for getting object size and attribute value
Implement commands - PKCS11_CMD_GET_OBJECT_SIZE - PKCS11_CMD_GET_ATTRIBUTE_VALUE Co-developed-by: Etienne Carriere <etienne.carriere@linaro.org> Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org> Co-developed-by: Gabor Szekely <szvgabor@gmail.com> Signed-off-by: Gabor Szekely <szvgabor@gmail.com> Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org> Reviewed-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
-rw-r--r--ta/pkcs11/include/pkcs11_ta.h35
-rw-r--r--ta/pkcs11/src/entry.c6
-rw-r--r--ta/pkcs11/src/object.c201
-rw-r--r--ta/pkcs11/src/object.h6
-rw-r--r--ta/pkcs11/src/pkcs11_attributes.c39
-rw-r--r--ta/pkcs11/src/pkcs11_attributes.h3
-rw-r--r--ta/pkcs11/src/pkcs11_helpers.c2
7 files changed, 292 insertions, 0 deletions
diff --git a/ta/pkcs11/include/pkcs11_ta.h b/ta/pkcs11/include/pkcs11_ta.h
index 3b9706dc..53ddbca8 100644
--- a/ta/pkcs11/include/pkcs11_ta.h
+++ b/ta/pkcs11/include/pkcs11_ta.h
@@ -474,6 +474,41 @@ enum pkcs11_ta_cmd {
* This command relates to the PKCS#11 API function C_FindOjectsFinal().
*/
PKCS11_CMD_FIND_OBJECTS_FINAL = 36,
+
+ /*
+ * PKCS11_CMD_GET_OBJECT_SIZE - Get byte size used by object in the TEE
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit object handle
+ * ]
+ * [out] memref[0] = 32bit return code, enum pkcs11_rc
+ * [out] memref[2] = 32bit object_byte_size
+ *
+ * This command relates to the PKCS#11 API function C_GetObjectSize().
+ */
+ PKCS11_CMD_GET_OBJECT_SIZE = 37,
+
+ /*
+ * PKCS11_CMD_GET_ATTRIBUTE_VALUE - Get the value of object attribute(s)
+ *
+ * [in] memref[0] = [
+ * 32bit session handle,
+ * 32bit object handle,
+ * (struct pkcs11_object_head)attribs + attributes data
+ * ]
+ * [out] memref[0] = 32bit return code, enum pkcs11_rc
+ * [out] memref[2] = (struct pkcs11_object_head)attribs + attributes
+ * data
+ *
+ * This command relates to the PKCS#11 API function C_GetAttributeValue.
+ * Caller provides an attribute template as 3rd argument in memref[0]
+ * (referred here as attribs + attributes data). Upon successful
+ * completion, the TA returns the provided template filled with expected
+ * data through output argument memref[2] (referred here again as
+ * attribs + attributes data).
+ */
+ PKCS11_CMD_GET_ATTRIBUTE_VALUE = 38,
};
/*
diff --git a/ta/pkcs11/src/entry.c b/ta/pkcs11/src/entry.c
index beba07db..321d5d43 100644
--- a/ta/pkcs11/src/entry.c
+++ b/ta/pkcs11/src/entry.c
@@ -297,6 +297,12 @@ TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd,
case PKCS11_CMD_FIND_OBJECTS_FINAL:
rc = entry_find_objects_final(client, ptypes, params);
break;
+ case PKCS11_CMD_GET_ATTRIBUTE_VALUE:
+ rc = entry_get_attribute_value(client, ptypes, params);
+ break;
+ case PKCS11_CMD_GET_OBJECT_SIZE:
+ rc = entry_get_object_size(client, ptypes, params);
+ break;
default:
EMSG("Command %#"PRIx32" is not supported", cmd);
return TEE_ERROR_NOT_SUPPORTED;
diff --git a/ta/pkcs11/src/object.c b/ta/pkcs11/src/object.c
index 7b237bea..6ddf9720 100644
--- a/ta/pkcs11/src/object.c
+++ b/ta/pkcs11/src/object.c
@@ -763,3 +763,204 @@ uint32_t entry_find_objects_final(struct pkcs11_client *client,
return PKCS11_CKR_OK;
}
+
+uint32_t entry_get_attribute_value(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_object_head *template = NULL;
+ struct pkcs11_object *obj = NULL;
+ uint32_t object_handle = 0;
+ char *cur = NULL;
+ size_t len = 0;
+ char *end = NULL;
+ bool attr_sensitive = 0;
+ bool attr_type_invalid = 0;
+ bool buffer_too_small = 0;
+
+ if (!client || ptypes != exp_pt)
+ 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_get(&ctrlargs, &object_handle, sizeof(uint32_t));
+ if (rc)
+ return rc;
+
+ rc = serialargs_alloc_get_attributes(&ctrlargs, &template);
+ if (rc)
+ return rc;
+
+ if (serialargs_remaining_bytes(&ctrlargs)) {
+ rc = PKCS11_CKR_ARGUMENTS_BAD;
+ goto out;
+ }
+
+ obj = pkcs11_handle2object(object_handle, session);
+ if (!obj) {
+ rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
+ goto out;
+ }
+
+ rc = check_access_attrs_against_token(session, obj->attributes);
+ if (rc) {
+ rc = PKCS11_CKR_OBJECT_HANDLE_INVALID;
+ goto out;
+ }
+
+ /* Iterate over attributes and set their values */
+ /*
+ * 1. If the specified attribute (i.e., the attribute specified by the
+ * type field) for the object cannot be revealed because the object is
+ * sensitive or unextractable, then the ulValueLen field in that triple
+ * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION.
+ *
+ * 2. Otherwise, if the specified value for the object is invalid (the
+ * object does not possess such an attribute), then the ulValueLen field
+ * in that triple is modified to hold the value
+ * PKCS11_CK_UNAVAILABLE_INFORMATION.
+ *
+ * 3. Otherwise, if the pValue field has the value NULL_PTR, then the
+ * ulValueLen field is modified to hold the exact length of the
+ * specified attribute for the object.
+ *
+ * 4. Otherwise, if the length specified in ulValueLen is large enough
+ * to hold the value of the specified attribute for the object, then
+ * that attribute is copied into the buffer located at pValue, and the
+ * ulValueLen field is modified to hold the exact length of the
+ * attribute.
+ *
+ * 5. Otherwise, the ulValueLen field is modified to hold the value
+ * PKCS11_CK_UNAVAILABLE_INFORMATION.
+ */
+ cur = (char *)template + sizeof(struct pkcs11_object_head);
+ end = cur + template->attrs_size;
+
+ for (; cur < end; cur += len) {
+ struct pkcs11_attribute_head *cli_ref = (void *)cur;
+
+ len = sizeof(*cli_ref) + cli_ref->size;
+
+ /* Check 1. */
+ if (!attribute_is_exportable(cli_ref, obj)) {
+ cli_ref->size = PKCS11_CK_UNAVAILABLE_INFORMATION;
+ attr_sensitive = 1;
+ continue;
+ }
+
+ /*
+ * We assume that if size is 0, pValue was NULL, so we return
+ * the size of the required buffer for it (3., 4.)
+ */
+ rc = get_attribute(obj->attributes, cli_ref->id,
+ cli_ref->size ? cli_ref->data : NULL,
+ &cli_ref->size);
+ /* Check 2. */
+ switch (rc) {
+ case PKCS11_CKR_OK:
+ break;
+ case PKCS11_RV_NOT_FOUND:
+ cli_ref->size = PKCS11_CK_UNAVAILABLE_INFORMATION;
+ attr_type_invalid = 1;
+ break;
+ case PKCS11_CKR_BUFFER_TOO_SMALL:
+ buffer_too_small = 1;
+ break;
+ default:
+ rc = PKCS11_CKR_GENERAL_ERROR;
+ goto out;
+ }
+ }
+
+ /*
+ * If case 1 applies to any of the requested attributes, then the call
+ * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to
+ * any of the requested attributes, then the call should return the
+ * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the
+ * requested attributes, then the call should return the value
+ * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes
+ * is applicable, Cryptoki may return any of them. Only if none of them
+ * applies to any of the requested attributes will CKR_OK be returned.
+ */
+
+ rc = PKCS11_CKR_OK;
+ if (attr_sensitive)
+ rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE;
+ if (attr_type_invalid)
+ rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID;
+ if (buffer_too_small)
+ rc = PKCS11_CKR_BUFFER_TOO_SMALL;
+
+ /* Move updated template to out buffer */
+ TEE_MemMove(out->memref.buffer, template, out->memref.size);
+
+ DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32,
+ session->handle, object_handle);
+
+out:
+ TEE_Free(template);
+
+ return rc;
+}
+
+uint32_t entry_get_object_size(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;
+ uint32_t object_handle = 0;
+ struct pkcs11_object *obj = NULL;
+ uint32_t obj_size = 0;
+
+ if (!client || ptypes != exp_pt)
+ 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_get(&ctrlargs, &object_handle, sizeof(uint32_t));
+ if (rc)
+ return rc;
+
+ if (serialargs_remaining_bytes(&ctrlargs))
+ return PKCS11_CKR_ARGUMENTS_BAD;
+
+ obj = pkcs11_handle2object(object_handle, session);
+ if (!obj)
+ return PKCS11_CKR_OBJECT_HANDLE_INVALID;
+
+ rc = check_access_attrs_against_token(session, obj->attributes);
+ if (rc)
+ return PKCS11_CKR_OBJECT_HANDLE_INVALID;
+
+ if (out->memref.size != sizeof(uint32_t))
+ return PKCS11_CKR_ARGUMENTS_BAD;
+
+ obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size +
+ sizeof(struct obj_attrs);
+ TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size));
+
+ return PKCS11_CKR_OK;
+}
diff --git a/ta/pkcs11/src/object.h b/ta/pkcs11/src/object.h
index b2d54ca3..20dfb53a 100644
--- a/ta/pkcs11/src/object.h
+++ b/ta/pkcs11/src/object.h
@@ -70,6 +70,12 @@ enum pkcs11_rc entry_find_objects(struct pkcs11_client *client,
enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client,
uint32_t ptypes, TEE_Param *params);
+enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client,
+ uint32_t ptypes, TEE_Param *params);
+
+enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client,
+ uint32_t ptypes, TEE_Param *params);
+
void release_session_find_obj_context(struct pkcs11_session *session);
#endif /*PKCS11_TA_OBJECT_H*/
diff --git a/ta/pkcs11/src/pkcs11_attributes.c b/ta/pkcs11/src/pkcs11_attributes.c
index 6ed141ea..ae018e27 100644
--- a/ta/pkcs11/src/pkcs11_attributes.c
+++ b/ta/pkcs11/src/pkcs11_attributes.c
@@ -1252,3 +1252,42 @@ check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
return PKCS11_CKR_OK;
}
+
+bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,
+ struct pkcs11_object *obj)
+{
+ uint8_t boolval = 0;
+ uint32_t boolsize = 0;
+ enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR;
+ enum pkcs11_class_id key_class = get_class(obj->attributes);
+
+ if (key_class != PKCS11_CKO_SECRET_KEY &&
+ key_class != PKCS11_CKO_PRIVATE_KEY)
+ return true;
+
+ switch (req_attr->id) {
+ case PKCS11_CKA_PRIVATE_EXPONENT:
+ case PKCS11_CKA_PRIME_1:
+ case PKCS11_CKA_PRIME_2:
+ case PKCS11_CKA_EXPONENT_1:
+ case PKCS11_CKA_EXPONENT_2:
+ case PKCS11_CKA_COEFFICIENT:
+ case PKCS11_CKA_VALUE:
+ boolsize = sizeof(boolval);
+ rc = get_attribute(obj->attributes, PKCS11_CKA_EXTRACTABLE,
+ &boolval, &boolsize);
+ if (rc || boolval == PKCS11_FALSE)
+ return false;
+
+ boolsize = sizeof(boolval);
+ rc = get_attribute(obj->attributes, PKCS11_CKA_SENSITIVE,
+ &boolval, &boolsize);
+ if (rc || boolval == PKCS11_TRUE)
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
diff --git a/ta/pkcs11/src/pkcs11_attributes.h b/ta/pkcs11/src/pkcs11_attributes.h
index d73bc44a..9d5e655b 100644
--- a/ta/pkcs11/src/pkcs11_attributes.h
+++ b/ta/pkcs11/src/pkcs11_attributes.h
@@ -160,4 +160,7 @@ check_mechanism_against_processing(struct pkcs11_session *session,
enum processing_func function,
enum processing_step step);
+bool attribute_is_exportable(struct pkcs11_attribute_head *req_attr,
+ struct pkcs11_object *obj);
+
#endif /*PKCS11_TA_PKCS11_ATTRIBUTES_H*/
diff --git a/ta/pkcs11/src/pkcs11_helpers.c b/ta/pkcs11/src/pkcs11_helpers.c
index 95d09488..062a7c0c 100644
--- a/ta/pkcs11/src/pkcs11_helpers.c
+++ b/ta/pkcs11/src/pkcs11_helpers.c
@@ -173,6 +173,8 @@ static const struct any_id __maybe_unused string_ta_cmd[] = {
PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_INIT),
PKCS11_ID(PKCS11_CMD_FIND_OBJECTS),
PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_FINAL),
+ PKCS11_ID(PKCS11_CMD_GET_OBJECT_SIZE),
+ PKCS11_ID(PKCS11_CMD_GET_ATTRIBUTE_VALUE),
};
static const struct any_id __maybe_unused string_slot_flags[] = {