diff options
author | Ruchika Gupta <ruchika.gupta@linaro.org> | 2020-12-22 13:42:11 +0530 |
---|---|---|
committer | Jérôme Forissier <jerome@forissier.org> | 2021-01-13 19:13:46 +0100 |
commit | dc99b202f3997248adbe7508698c051f6d677cd0 (patch) | |
tree | 60fe0f70f0fa4716344eead64d248f38a7405945 | |
parent | c2f85e817e908395f34ed228b80596d8ad0308cc (diff) |
ta: pkcs11: Add support for finding objects
Implement commands
- PKCS11_CMD_FIND_OBJECTS_INIT
- PKCS11_CMD_FIND_OBJECTS
- PKCS11_CMD_FIND_OBJECTS_FINAL
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/src/attributes.c | 31 | ||||
-rw-r--r-- | ta/pkcs11/src/attributes.h | 9 | ||||
-rw-r--r-- | ta/pkcs11/src/entry.c | 9 | ||||
-rw-r--r-- | ta/pkcs11/src/object.c | 336 | ||||
-rw-r--r-- | ta/pkcs11/src/object.h | 12 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_helpers.c | 3 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_token.c | 2 | ||||
-rw-r--r-- | ta/pkcs11/src/pkcs11_token.h | 17 |
8 files changed, 419 insertions, 0 deletions
diff --git a/ta/pkcs11/src/attributes.c b/ta/pkcs11/src/attributes.c index 3454f7a8..c420f914 100644 --- a/ta/pkcs11/src/attributes.c +++ b/ta/pkcs11/src/attributes.c @@ -207,6 +207,37 @@ bool get_bool(struct obj_attrs *head, uint32_t attribute) return bbool; } +bool attributes_match_reference(struct obj_attrs *candidate, + struct obj_attrs *ref) +{ + size_t count = ref->attrs_count; + unsigned char *ref_attr = ref->attrs; + uint32_t rc = PKCS11_CKR_GENERAL_ERROR; + + if (!ref->attrs_count) { + DMSG("Empty reference: no match"); + return false; + } + + for (count = 0; count < ref->attrs_count; count++) { + struct pkcs11_attribute_head pkcs11_ref = { }; + void *value = NULL; + uint32_t size = 0; + + TEE_MemMove(&pkcs11_ref, ref_attr, sizeof(pkcs11_ref)); + + rc = get_attribute_ptr(candidate, pkcs11_ref.id, &value, &size); + + if (rc || !value || size != pkcs11_ref.size || + TEE_MemCompare(ref_attr + sizeof(pkcs11_ref), value, size)) + return false; + + ref_attr += sizeof(pkcs11_ref) + pkcs11_ref.size; + } + + return true; +} + #if CFG_TEE_TA_LOG_LEVEL > 0 /* * Debug: dump CK attribute array to output trace diff --git a/ta/pkcs11/src/attributes.h b/ta/pkcs11/src/attributes.h index 353989f4..38f47695 100644 --- a/ta/pkcs11/src/attributes.h +++ b/ta/pkcs11/src/attributes.h @@ -180,6 +180,15 @@ static inline enum pkcs11_rc get_u32_attribute(struct obj_attrs *head, } /* + * Return true if all attributes from the reference are found and match value + * in the candidate attribute list. + * + * Return PKCS11_CKR_OK on success, or a PKCS11 return code. + */ +bool attributes_match_reference(struct obj_attrs *ref, + struct obj_attrs *candidate); + +/* * get_class() - Get class ID of an object * @head: Pointer to serialized attributes * diff --git a/ta/pkcs11/src/entry.c b/ta/pkcs11/src/entry.c index 947f71bd..beba07db 100644 --- a/ta/pkcs11/src/entry.c +++ b/ta/pkcs11/src/entry.c @@ -288,6 +288,15 @@ TEE_Result TA_InvokeCommandEntryPoint(void *tee_session, uint32_t cmd, case PKCS11_CMD_GENERATE_KEY: rc = entry_generate_secret(client, ptypes, params); break; + case PKCS11_CMD_FIND_OBJECTS_INIT: + rc = entry_find_objects_init(client, ptypes, params); + break; + case PKCS11_CMD_FIND_OBJECTS: + rc = entry_find_objects(client, ptypes, params); + break; + case PKCS11_CMD_FIND_OBJECTS_FINAL: + rc = entry_find_objects_final(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 3d9f1ab6..7b237bea 100644 --- a/ta/pkcs11/src/object.c +++ b/ta/pkcs11/src/object.c @@ -427,3 +427,339 @@ enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, return rc; } + +static enum pkcs11_rc token_obj_matches_ref(struct obj_attrs *req_attrs, + struct pkcs11_object *obj) +{ + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + TEE_Result res = TEE_ERROR_GENERIC; + TEE_ObjectHandle hdl = obj->attribs_hdl; + TEE_ObjectInfo info = { }; + struct obj_attrs *attr = NULL; + uint32_t read_bytes = 0; + + if (obj->attributes) { + if (!attributes_match_reference(obj->attributes, req_attrs)) + return PKCS11_RV_NOT_FOUND; + + return PKCS11_CKR_OK; + } + + if (hdl == TEE_HANDLE_NULL) { + res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, + obj->uuid, sizeof(*obj->uuid), + TEE_DATA_FLAG_ACCESS_READ, + &hdl); + if (res) { + EMSG("OpenPersistent failed %#"PRIx32, res); + return tee2pkcs_error(res); + } + } + + res = TEE_GetObjectInfo1(hdl, &info); + if (res) { + EMSG("GetObjectInfo failed %#"PRIx32, res); + rc = tee2pkcs_error(res); + goto out; + } + + attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO); + if (!attr) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes); + if (!res) { + res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET); + if (res) + EMSG("Seek to 0 failed with %#"PRIx32, res); + } + + if (res) { + rc = tee2pkcs_error(res); + EMSG("Read %"PRIu32" bytes, failed %#"PRIx32, + read_bytes, res); + goto out; + } + + if (read_bytes != info.dataSize) { + EMSG("Read %"PRIu32" bytes, expected %"PRIu32, + read_bytes, info.dataSize); + rc = PKCS11_CKR_GENERAL_ERROR; + goto out; + } + + if (!attributes_match_reference(attr, req_attrs)) { + rc = PKCS11_RV_NOT_FOUND; + goto out; + } + + obj->attributes = attr; + attr = NULL; + obj->attribs_hdl = hdl; + hdl = TEE_HANDLE_NULL; + + rc = PKCS11_CKR_OK; + +out: + TEE_Free(attr); + if (obj->attribs_hdl == TEE_HANDLE_NULL) + TEE_CloseObject(hdl); + + return rc; +} + +static void release_find_obj_context(struct pkcs11_find_objects *find_ctx) +{ + if (!find_ctx) + return; + + TEE_Free(find_ctx->attributes); + TEE_Free(find_ctx->handles); + TEE_Free(find_ctx); +} + +static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx, + uint32_t handle) +{ + uint32_t *hdls = TEE_Realloc(find_ctx->handles, + (find_ctx->count + 1) * sizeof(*hdls)); + + if (!hdls) + return PKCS11_CKR_DEVICE_MEMORY; + + find_ctx->handles = hdls; + + *(find_ctx->handles + find_ctx->count) = handle; + find_ctx->count++; + + return PKCS11_CKR_OK; +} + +enum pkcs11_rc entry_find_objects_init(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_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + struct pkcs11_object_head *template = NULL; + struct obj_attrs *req_attrs = NULL; + struct pkcs11_object *obj = NULL; + struct pkcs11_find_objects *find_ctx = NULL; + + 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_alloc_get_attributes(&ctrlargs, &template); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) { + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + /* Search objects only if no operation is on-going */ + if (session_is_active(session)) { + rc = PKCS11_CKR_OPERATION_ACTIVE; + goto out; + } + + if (session->find_ctx) { + EMSG("Active object search already in progress"); + rc = PKCS11_CKR_FUNCTION_FAILED; + goto out; + } + + rc = sanitize_client_object(&req_attrs, template, + sizeof(*template) + template->attrs_size, + PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID); + if (rc) + goto out; + + /* Must zero init the structure */ + find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO); + if (!find_ctx) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + + TEE_Free(template); + template = NULL; + + switch (get_class(req_attrs)) { + case PKCS11_CKO_UNDEFINED_ID: + /* Unspecified class searches among data objects */ + case PKCS11_CKO_SECRET_KEY: + case PKCS11_CKO_PUBLIC_KEY: + case PKCS11_CKO_PRIVATE_KEY: + case PKCS11_CKO_DATA: + break; + default: + EMSG("Find object of class %s (%"PRIu32") is not supported", + id2str_class(get_class(req_attrs)), + get_class(req_attrs)); + rc = PKCS11_CKR_ARGUMENTS_BAD; + goto out; + } + + /* + * Scan all objects (sessions and persistent ones) and set a list of + * candidates that match caller attributes. + */ + + LIST_FOREACH(obj, &session->object_list, link) { + if (check_access_attrs_against_token(session, obj->attributes)) + continue; + + if (req_attrs->attrs_count && + !attributes_match_reference(obj->attributes, req_attrs)) + continue; + + rc = find_ctx_add(find_ctx, pkcs11_object2handle(obj, session)); + if (rc) + goto out; + } + + LIST_FOREACH(obj, &session->token->object_list, link) { + uint32_t handle = 0; + + if (check_access_attrs_against_token(session, obj->attributes)) + continue; + + if (req_attrs->attrs_count) { + rc = token_obj_matches_ref(req_attrs, obj); + if (rc == PKCS11_RV_NOT_FOUND) + continue; + if (rc != PKCS11_CKR_OK) + goto out; + } + + /* Object may not yet be published in the session */ + handle = pkcs11_object2handle(obj, session); + if (!handle) { + handle = handle_get(&session->object_handle_db, obj); + if (!handle) { + rc = PKCS11_CKR_DEVICE_MEMORY; + goto out; + } + } + + rc = find_ctx_add(find_ctx, handle); + if (rc) + goto out; + } + + find_ctx->attributes = req_attrs; + req_attrs = NULL; + session->find_ctx = find_ctx; + find_ctx = NULL; + rc = PKCS11_CKR_OK; + +out: + TEE_Free(req_attrs); + TEE_Free(template); + release_find_obj_context(find_ctx); + + return rc; +} + +enum pkcs11_rc entry_find_objects(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_find_objects *ctx = NULL; + uint8_t *out_handles = NULL; + size_t out_count = 0; + size_t count = 0; + + if (!client || ptypes != exp_pt) + return PKCS11_CKR_ARGUMENTS_BAD; + + out_count = out->memref.size / sizeof(uint32_t); + out_handles = out->memref.buffer; + + serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); + + rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); + if (rc) + return rc; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + ctx = session->find_ctx; + + if (!ctx) + return PKCS11_CKR_OPERATION_NOT_INITIALIZED; + + for (count = 0; ctx->next < ctx->count && count < out_count; + ctx->next++, count++) + TEE_MemMove(out_handles + count * sizeof(uint32_t), + ctx->handles + ctx->next, sizeof(uint32_t)); + + /* Update output buffer according the number of handles provided */ + out->memref.size = count * sizeof(uint32_t); + + DMSG("PKCS11 session %"PRIu32": finding objects", session->handle); + + return PKCS11_CKR_OK; +} + +void release_session_find_obj_context(struct pkcs11_session *session) +{ + release_find_obj_context(session->find_ctx); + session->find_ctx = NULL; +} + +uint32_t entry_find_objects_final(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_NONE, + TEE_PARAM_TYPE_NONE); + TEE_Param *ctrl = params; + enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; + struct serialargs ctrlargs = { }; + struct pkcs11_session *session = NULL; + + 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; + + if (serialargs_remaining_bytes(&ctrlargs)) + return PKCS11_CKR_ARGUMENTS_BAD; + + if (!session->find_ctx) + return PKCS11_CKR_OPERATION_NOT_INITIALIZED; + + release_session_find_obj_context(session); + + return PKCS11_CKR_OK; +} diff --git a/ta/pkcs11/src/object.h b/ta/pkcs11/src/object.h index 12b624da..b2d54ca3 100644 --- a/ta/pkcs11/src/object.h +++ b/ta/pkcs11/src/object.h @@ -60,4 +60,16 @@ enum pkcs11_rc entry_create_object(struct pkcs11_client *client, enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, + uint32_t ptypes, TEE_Param *params); + +enum pkcs11_rc entry_find_objects_final(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_helpers.c b/ta/pkcs11/src/pkcs11_helpers.c index 6de2838a..95d09488 100644 --- a/ta/pkcs11/src/pkcs11_helpers.c +++ b/ta/pkcs11/src/pkcs11_helpers.c @@ -170,6 +170,9 @@ static const struct any_id __maybe_unused string_ta_cmd[] = { PKCS11_ID(PKCS11_CMD_SIGN_ONESHOT), PKCS11_ID(PKCS11_CMD_VERIFY_ONESHOT), PKCS11_ID(PKCS11_CMD_GENERATE_KEY), + PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_INIT), + PKCS11_ID(PKCS11_CMD_FIND_OBJECTS), + PKCS11_ID(PKCS11_CMD_FIND_OBJECTS_FINAL), }; static const struct any_id __maybe_unused string_slot_flags[] = { diff --git a/ta/pkcs11/src/pkcs11_token.c b/ta/pkcs11/src/pkcs11_token.c index 9a2521f1..d6948339 100644 --- a/ta/pkcs11/src/pkcs11_token.c +++ b/ta/pkcs11/src/pkcs11_token.c @@ -662,6 +662,8 @@ static void close_ck_session(struct pkcs11_session *session) destroy_object(session, LIST_FIRST(&session->object_list), true); + release_session_find_obj_context(session); + TAILQ_REMOVE(&session->client->session_list, session, link); handle_put(&session->client->session_handle_db, session->handle); handle_db_destroy(&session->object_handle_db); diff --git a/ta/pkcs11/src/pkcs11_token.h b/ta/pkcs11/src/pkcs11_token.h index b201e33e..5cd333c2 100644 --- a/ta/pkcs11/src/pkcs11_token.h +++ b/ta/pkcs11/src/pkcs11_token.h @@ -149,6 +149,21 @@ struct active_processing { }; /* + * Pkcs11 objects search context + * + * @attributes - matching attributes list searched (null if no search) + * @count - number of matching handle found + * @handles - array of handle of matching objects + * @next - index of the next object handle to return to C_FindObject + */ +struct pkcs11_find_objects { + void *attributes; + size_t count; + uint32_t *handles; + size_t next; +}; + +/* * Structure tracking the PKCS#11 sessions * * @link - List of the session belonging to a client @@ -159,6 +174,7 @@ struct active_processing { * @object_handle_db - Database for object handles published by the session * @state - R/W SO, R/W user, RO user, R/W public, RO public. * @processing - Reference to initialized processing context if any + * @find_ctx - Reference to active search context (null if no active search) */ struct pkcs11_session { TAILQ_ENTRY(pkcs11_session) link; @@ -169,6 +185,7 @@ struct pkcs11_session { struct handle_db object_handle_db; enum pkcs11_session_state state; struct active_processing *processing; + struct pkcs11_find_objects *find_ctx; }; /* Initialize static token instance(s) from default/persistent database */ |