diff options
author | Ruchika Gupta <ruchika.gupta@linaro.org> | 2021-01-13 10:33:43 +0530 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2021-01-13 19:13:46 +0100 |
commit | 783c1515c2f9b22497651dee269cd849fd908a56 (patch) | |
tree | be649a8fbba8e5f75f3d478731c758752362916b | |
parent | dc99b202f3997248adbe7508698c051f6d677cd0 (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.h | 35 | ||||
-rw-r--r-- | ta/pkcs11/src/entry.c | 6 | ||||
-rw-r--r-- | ta/pkcs11/src/object.c | 201 | ||||
-rw-r--r-- | ta/pkcs11/src/object.h | 6 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_attributes.c | 39 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_attributes.h | 3 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_helpers.c | 2 |
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[] = { |