1b56b3d07SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2b56b3d07SJens Wiklander /* 3b56b3d07SJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 4b56b3d07SJens Wiklander */ 5b56b3d07SJens Wiklander 6b56b3d07SJens Wiklander #include <assert.h> 7b56b3d07SJens Wiklander #include <inttypes.h> 8b56b3d07SJens Wiklander #include <string_ext.h> 9b56b3d07SJens Wiklander #include <tee_internal_api.h> 10b56b3d07SJens Wiklander #include <tee_internal_api_extensions.h> 11b56b3d07SJens Wiklander 12b56b3d07SJens Wiklander #include "attributes.h" 13b56b3d07SJens Wiklander #include "handle.h" 14b56b3d07SJens Wiklander #include "object.h" 15b56b3d07SJens Wiklander #include "pkcs11_attributes.h" 16b56b3d07SJens Wiklander #include "pkcs11_helpers.h" 17b56b3d07SJens Wiklander #include "pkcs11_token.h" 18b56b3d07SJens Wiklander #include "sanitize_object.h" 19b56b3d07SJens Wiklander #include "serializer.h" 20b56b3d07SJens Wiklander 21b56b3d07SJens Wiklander struct pkcs11_object *pkcs11_handle2object(uint32_t handle, 22b56b3d07SJens Wiklander struct pkcs11_session *session) 23b56b3d07SJens Wiklander { 24b56b3d07SJens Wiklander return handle_lookup(&session->object_handle_db, handle); 25b56b3d07SJens Wiklander } 26b56b3d07SJens Wiklander 27b56b3d07SJens Wiklander uint32_t pkcs11_object2handle(struct pkcs11_object *obj, 28b56b3d07SJens Wiklander struct pkcs11_session *session) 29b56b3d07SJens Wiklander { 30b56b3d07SJens Wiklander return handle_lookup_handle(&session->object_handle_db, obj); 31b56b3d07SJens Wiklander } 32b56b3d07SJens Wiklander 33b56b3d07SJens Wiklander /* Currently handle pkcs11 sessions and tokens */ 34b56b3d07SJens Wiklander 35b56b3d07SJens Wiklander static struct object_list *get_session_objects(void *session) 36b56b3d07SJens Wiklander { 37b56b3d07SJens Wiklander /* Currently supporting only pkcs11 session */ 38b56b3d07SJens Wiklander struct pkcs11_session *ck_session = session; 39b56b3d07SJens Wiklander 40b56b3d07SJens Wiklander return pkcs11_get_session_objects(ck_session); 41b56b3d07SJens Wiklander } 42b56b3d07SJens Wiklander 43334316feSJens Wiklander static struct ck_token *get_session_token(void *session) 44334316feSJens Wiklander { 45334316feSJens Wiklander struct pkcs11_session *ck_session = session; 46334316feSJens Wiklander 47334316feSJens Wiklander return pkcs11_session2token(ck_session); 48334316feSJens Wiklander } 49334316feSJens Wiklander 50b56b3d07SJens Wiklander /* Release resources of a non-persistent object */ 51b56b3d07SJens Wiklander static void cleanup_volatile_obj_ref(struct pkcs11_object *obj) 52b56b3d07SJens Wiklander { 53b56b3d07SJens Wiklander if (!obj) 54b56b3d07SJens Wiklander return; 55b56b3d07SJens Wiklander 56b56b3d07SJens Wiklander if (obj->key_handle != TEE_HANDLE_NULL) 57b56b3d07SJens Wiklander TEE_FreeTransientObject(obj->key_handle); 58b56b3d07SJens Wiklander 59b56b3d07SJens Wiklander if (obj->attribs_hdl != TEE_HANDLE_NULL) 60b56b3d07SJens Wiklander TEE_CloseObject(obj->attribs_hdl); 61b56b3d07SJens Wiklander 62b56b3d07SJens Wiklander TEE_Free(obj->attributes); 63b56b3d07SJens Wiklander TEE_Free(obj->uuid); 64b56b3d07SJens Wiklander TEE_Free(obj); 65b56b3d07SJens Wiklander } 66b56b3d07SJens Wiklander 67b56b3d07SJens Wiklander /* Release resources of a persistent object including volatile resources */ 687f12c782SRobin van der Gracht void cleanup_persistent_object(struct pkcs11_object *obj, 69334316feSJens Wiklander struct ck_token *token) 70b56b3d07SJens Wiklander { 71334316feSJens Wiklander TEE_Result res = TEE_SUCCESS; 72334316feSJens Wiklander 73334316feSJens Wiklander if (!obj) 74334316feSJens Wiklander return; 75334316feSJens Wiklander 76334316feSJens Wiklander /* Open handle with write properties to destroy the object */ 77334316feSJens Wiklander if (obj->attribs_hdl != TEE_HANDLE_NULL) 78334316feSJens Wiklander TEE_CloseObject(obj->attribs_hdl); 79334316feSJens Wiklander 80334316feSJens Wiklander res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, 81334316feSJens Wiklander obj->uuid, sizeof(TEE_UUID), 82334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE_META, 83334316feSJens Wiklander &obj->attribs_hdl); 84334316feSJens Wiklander if (!res) 85334316feSJens Wiklander TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl); 86334316feSJens Wiklander 87334316feSJens Wiklander obj->attribs_hdl = TEE_HANDLE_NULL; 88334316feSJens Wiklander destroy_object_uuid(token, obj); 89334316feSJens Wiklander 90334316feSJens Wiklander LIST_REMOVE(obj, link); 91334316feSJens Wiklander 92334316feSJens Wiklander cleanup_volatile_obj_ref(obj); 93b56b3d07SJens Wiklander } 94b56b3d07SJens Wiklander 95b56b3d07SJens Wiklander /* 96b56b3d07SJens Wiklander * destroy_object - destroy an PKCS11 TA object 97b56b3d07SJens Wiklander * 98b56b3d07SJens Wiklander * @session - session requesting object destruction 99b56b3d07SJens Wiklander * @obj - reference to the PKCS11 TA object 100b56b3d07SJens Wiklander * @session_only - true if only session object shall be destroyed 101b56b3d07SJens Wiklander */ 102b56b3d07SJens Wiklander void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj, 103b56b3d07SJens Wiklander bool session_only) 104b56b3d07SJens Wiklander { 105b56b3d07SJens Wiklander #ifdef DEBUG 106b56b3d07SJens Wiklander trace_attributes("[destroy]", obj->attributes); 107b56b3d07SJens Wiklander if (obj->uuid) 108b56b3d07SJens Wiklander MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid); 109b56b3d07SJens Wiklander #endif 110b56b3d07SJens Wiklander 111b56b3d07SJens Wiklander /* 112b56b3d07SJens Wiklander * Remove from session list only if it was published. 113b56b3d07SJens Wiklander * 114b56b3d07SJens Wiklander * This depends on obj->link.le_prev always pointing on the 115b56b3d07SJens Wiklander * link.le_next element in the previous object in the list even if 116b56b3d07SJens Wiklander * there's only a single object in the list. In the first object in 117b56b3d07SJens Wiklander * the list obj->link.le_prev instead points to lh_first in the 118b56b3d07SJens Wiklander * list head. If list implementation is changed we need to revisit 119b56b3d07SJens Wiklander * this. 120b56b3d07SJens Wiklander */ 121b56b3d07SJens Wiklander if (obj->link.le_next || obj->link.le_prev) 122b56b3d07SJens Wiklander LIST_REMOVE(obj, link); 123b56b3d07SJens Wiklander 124b56b3d07SJens Wiklander if (session_only) { 125b56b3d07SJens Wiklander /* Destroy object due to session closure */ 126b56b3d07SJens Wiklander handle_put(&session->object_handle_db, 127b56b3d07SJens Wiklander pkcs11_object2handle(obj, session)); 128b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 129b56b3d07SJens Wiklander 130b56b3d07SJens Wiklander return; 131b56b3d07SJens Wiklander } 132b56b3d07SJens Wiklander 133b56b3d07SJens Wiklander /* Destroy target object (persistent or not) */ 134b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 135334316feSJens Wiklander assert(obj->uuid); 136334316feSJens Wiklander /* Try twice otherwise panic! */ 137334316feSJens Wiklander if (unregister_persistent_object(session->token, obj->uuid) && 138334316feSJens Wiklander unregister_persistent_object(session->token, obj->uuid)) 139b56b3d07SJens Wiklander TEE_Panic(0); 140334316feSJens Wiklander 141334316feSJens Wiklander handle_put(&session->object_handle_db, 142334316feSJens Wiklander pkcs11_object2handle(obj, session)); 143334316feSJens Wiklander cleanup_persistent_object(obj, session->token); 144b56b3d07SJens Wiklander } else { 145b56b3d07SJens Wiklander handle_put(&session->object_handle_db, 146b56b3d07SJens Wiklander pkcs11_object2handle(obj, session)); 147b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 148b56b3d07SJens Wiklander } 149b56b3d07SJens Wiklander } 150b56b3d07SJens Wiklander 151b56b3d07SJens Wiklander static struct pkcs11_object *create_obj_instance(struct obj_attrs *head) 152b56b3d07SJens Wiklander { 153b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL; 154b56b3d07SJens Wiklander 155b56b3d07SJens Wiklander obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO); 156b56b3d07SJens Wiklander if (!obj) 157b56b3d07SJens Wiklander return NULL; 158b56b3d07SJens Wiklander 159b56b3d07SJens Wiklander obj->key_handle = TEE_HANDLE_NULL; 160b56b3d07SJens Wiklander obj->attribs_hdl = TEE_HANDLE_NULL; 161b56b3d07SJens Wiklander obj->attributes = head; 162b56b3d07SJens Wiklander 163b56b3d07SJens Wiklander return obj; 164b56b3d07SJens Wiklander } 165b56b3d07SJens Wiklander 166334316feSJens Wiklander struct pkcs11_object *create_token_object(struct obj_attrs *head, 167334316feSJens Wiklander TEE_UUID *uuid) 168334316feSJens Wiklander { 169334316feSJens Wiklander struct pkcs11_object *obj = create_obj_instance(head); 170334316feSJens Wiklander 171334316feSJens Wiklander if (obj) 172334316feSJens Wiklander obj->uuid = uuid; 173334316feSJens Wiklander 174334316feSJens Wiklander return obj; 175334316feSJens Wiklander } 176334316feSJens Wiklander 177b56b3d07SJens Wiklander /* 178b56b3d07SJens Wiklander * create_object - create an PKCS11 TA object from its attributes and value 179b56b3d07SJens Wiklander * 180b56b3d07SJens Wiklander * @sess - session requesting object creation 181b56b3d07SJens Wiklander * @head - reference to serialized attributes 182b56b3d07SJens Wiklander * @out_handle - generated handle for the created object 183b56b3d07SJens Wiklander */ 184b56b3d07SJens Wiklander enum pkcs11_rc create_object(void *sess, struct obj_attrs *head, 185b56b3d07SJens Wiklander uint32_t *out_handle) 186b56b3d07SJens Wiklander { 187fde67b24SEtienne Carriere enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 188b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL; 189b56b3d07SJens Wiklander struct pkcs11_session *session = (struct pkcs11_session *)sess; 190b56b3d07SJens Wiklander uint32_t obj_handle = 0; 191b56b3d07SJens Wiklander 192b56b3d07SJens Wiklander #ifdef DEBUG 193b56b3d07SJens Wiklander trace_attributes("[create]", head); 194b56b3d07SJens Wiklander #endif 195b56b3d07SJens Wiklander 196b56b3d07SJens Wiklander /* 197b56b3d07SJens Wiklander * We do not check the key attributes. At this point, key attributes 198b56b3d07SJens Wiklander * are expected consistent and reliable. 199b56b3d07SJens Wiklander */ 200b56b3d07SJens Wiklander 201b56b3d07SJens Wiklander obj = create_obj_instance(head); 202b56b3d07SJens Wiklander if (!obj) 203b56b3d07SJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 204b56b3d07SJens Wiklander 205b56b3d07SJens Wiklander /* Create a handle for the object in the session database */ 206b56b3d07SJens Wiklander obj_handle = handle_get(&session->object_handle_db, obj); 207b56b3d07SJens Wiklander if (!obj_handle) { 208b56b3d07SJens Wiklander rc = PKCS11_CKR_DEVICE_MEMORY; 209b56b3d07SJens Wiklander goto err; 210b56b3d07SJens Wiklander } 211b56b3d07SJens Wiklander 212b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 213334316feSJens Wiklander TEE_Result res = TEE_SUCCESS; 214334316feSJens Wiklander 215334316feSJens Wiklander /* 216334316feSJens Wiklander * Get an ID for the persistent object 217334316feSJens Wiklander * Create the file 218334316feSJens Wiklander * Register the object in the persistent database 219334316feSJens Wiklander * (move the full sequence to persisent_db.c?) 220334316feSJens Wiklander */ 221334316feSJens Wiklander size_t size = sizeof(struct obj_attrs) + 222334316feSJens Wiklander obj->attributes->attrs_size; 223334316feSJens Wiklander uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ | 224334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE | 225334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE_META; 226334316feSJens Wiklander 227334316feSJens Wiklander rc = create_object_uuid(get_session_token(session), obj); 228334316feSJens Wiklander if (rc) 229334316feSJens Wiklander goto err; 230334316feSJens Wiklander 231334316feSJens Wiklander res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 232334316feSJens Wiklander obj->uuid, sizeof(TEE_UUID), 233334316feSJens Wiklander tee_obj_flags, 234334316feSJens Wiklander TEE_HANDLE_NULL, 235334316feSJens Wiklander obj->attributes, size, 236334316feSJens Wiklander &obj->attribs_hdl); 237334316feSJens Wiklander if (res) { 238334316feSJens Wiklander rc = tee2pkcs_error(res); 239334316feSJens Wiklander goto err; 240334316feSJens Wiklander } 241334316feSJens Wiklander 242334316feSJens Wiklander rc = register_persistent_object(get_session_token(session), 243334316feSJens Wiklander obj->uuid); 244334316feSJens Wiklander if (rc) 245334316feSJens Wiklander goto err; 246334316feSJens Wiklander 247334316feSJens Wiklander LIST_INSERT_HEAD(&session->token->object_list, obj, link); 248b56b3d07SJens Wiklander } else { 249b56b3d07SJens Wiklander rc = PKCS11_CKR_OK; 250b56b3d07SJens Wiklander LIST_INSERT_HEAD(get_session_objects(session), obj, link); 251b56b3d07SJens Wiklander } 252b56b3d07SJens Wiklander 253b56b3d07SJens Wiklander *out_handle = obj_handle; 254b56b3d07SJens Wiklander 255b56b3d07SJens Wiklander return PKCS11_CKR_OK; 256b56b3d07SJens Wiklander err: 257b56b3d07SJens Wiklander /* make sure that supplied "head" isn't freed */ 258b56b3d07SJens Wiklander obj->attributes = NULL; 259b56b3d07SJens Wiklander handle_put(&session->object_handle_db, obj_handle); 260b56b3d07SJens Wiklander if (get_bool(head, PKCS11_CKA_TOKEN)) 261b56b3d07SJens Wiklander cleanup_persistent_object(obj, session->token); 262b56b3d07SJens Wiklander else 263b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 264b56b3d07SJens Wiklander 265b56b3d07SJens Wiklander return rc; 266b56b3d07SJens Wiklander } 267b56b3d07SJens Wiklander 268b56b3d07SJens Wiklander enum pkcs11_rc entry_create_object(struct pkcs11_client *client, 269b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 270b56b3d07SJens Wiklander { 271b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 272b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 273b56b3d07SJens Wiklander TEE_PARAM_TYPE_MEMREF_OUTPUT, 274b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 275b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 276b56b3d07SJens Wiklander TEE_Param *ctrl = params; 277b56b3d07SJens Wiklander TEE_Param *out = params + 2; 278b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 279b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 280b56b3d07SJens Wiklander struct obj_attrs *head = NULL; 281b56b3d07SJens Wiklander struct pkcs11_object_head *template = NULL; 282b56b3d07SJens Wiklander size_t template_size = 0; 283b56b3d07SJens Wiklander uint32_t obj_handle = 0; 284b56b3d07SJens Wiklander 285b56b3d07SJens Wiklander /* 286b56b3d07SJens Wiklander * Collect the arguments of the request 287b56b3d07SJens Wiklander */ 288b56b3d07SJens Wiklander 289b56b3d07SJens Wiklander if (!client || ptypes != exp_pt || 290b56b3d07SJens Wiklander out->memref.size != sizeof(obj_handle)) 291b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 292b56b3d07SJens Wiklander 293b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 294b56b3d07SJens Wiklander 29559a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 296b56b3d07SJens Wiklander if (rc) 297b56b3d07SJens Wiklander return rc; 298b56b3d07SJens Wiklander 299b56b3d07SJens Wiklander rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 300b56b3d07SJens Wiklander if (rc) 301b56b3d07SJens Wiklander return rc; 302b56b3d07SJens Wiklander 303b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 304b56b3d07SJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 305b56b3d07SJens Wiklander goto out; 306b56b3d07SJens Wiklander } 307b56b3d07SJens Wiklander 308b56b3d07SJens Wiklander template_size = sizeof(*template) + template->attrs_size; 309b56b3d07SJens Wiklander 310b56b3d07SJens Wiklander /* 311b56b3d07SJens Wiklander * Prepare a clean initial state for the requested object attributes. 312b56b3d07SJens Wiklander * Free temporary template once done. 313b56b3d07SJens Wiklander */ 314b56b3d07SJens Wiklander rc = create_attributes_from_template(&head, template, template_size, 315b56b3d07SJens Wiklander NULL, PKCS11_FUNCTION_IMPORT, 3164cfce748SRuchika Gupta PKCS11_PROCESSING_IMPORT, 3174cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 318b56b3d07SJens Wiklander TEE_Free(template); 319b56b3d07SJens Wiklander template = NULL; 320b56b3d07SJens Wiklander if (rc) 321b56b3d07SJens Wiklander goto out; 322b56b3d07SJens Wiklander 323b56b3d07SJens Wiklander /* 324b56b3d07SJens Wiklander * Check target object attributes match target processing 325b56b3d07SJens Wiklander * Check target object attributes match token state 326b56b3d07SJens Wiklander */ 327b56b3d07SJens Wiklander rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT, 328b56b3d07SJens Wiklander head); 329b56b3d07SJens Wiklander if (rc) 330b56b3d07SJens Wiklander goto out; 331b56b3d07SJens Wiklander 332b56b3d07SJens Wiklander rc = check_created_attrs_against_token(session, head); 333b56b3d07SJens Wiklander if (rc) 334b56b3d07SJens Wiklander goto out; 335b56b3d07SJens Wiklander 336b68aca61SRuchika Gupta rc = check_access_attrs_against_token(session, head); 337b68aca61SRuchika Gupta if (rc) 338b68aca61SRuchika Gupta goto out; 339b68aca61SRuchika Gupta 340b56b3d07SJens Wiklander /* 341b56b3d07SJens Wiklander * At this stage the object is almost created: all its attributes are 342b56b3d07SJens Wiklander * referenced in @head, including the key value and are assumed 343b56b3d07SJens Wiklander * reliable. Now need to register it and get a handle for it. 344b56b3d07SJens Wiklander */ 345b56b3d07SJens Wiklander rc = create_object(session, head, &obj_handle); 346b56b3d07SJens Wiklander if (rc) 347b56b3d07SJens Wiklander goto out; 348b56b3d07SJens Wiklander 349b56b3d07SJens Wiklander /* 350b56b3d07SJens Wiklander * Now obj_handle (through the related struct pkcs11_object 351b56b3d07SJens Wiklander * instance) owns the serialised buffer that holds the object 352b56b3d07SJens Wiklander * attributes. We clear reference in head to NULL as the serializer 353b56b3d07SJens Wiklander * object is now referred from obj_handle. This allows smooth pass 354b56b3d07SJens Wiklander * through free at function exit. 355b56b3d07SJens Wiklander */ 356b56b3d07SJens Wiklander head = NULL; 357b56b3d07SJens Wiklander 358b56b3d07SJens Wiklander TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 359b56b3d07SJens Wiklander out->memref.size = sizeof(obj_handle); 360b56b3d07SJens Wiklander 361b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32, 362b56b3d07SJens Wiklander session->handle, obj_handle); 363b56b3d07SJens Wiklander 364b56b3d07SJens Wiklander out: 365b56b3d07SJens Wiklander TEE_Free(template); 366b56b3d07SJens Wiklander TEE_Free(head); 367b56b3d07SJens Wiklander 368b56b3d07SJens Wiklander return rc; 369b56b3d07SJens Wiklander } 370b56b3d07SJens Wiklander 371b56b3d07SJens Wiklander enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, 372b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 373b56b3d07SJens Wiklander { 374b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 375b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 376b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 377b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 378b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 379b56b3d07SJens Wiklander TEE_Param *ctrl = params; 380b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 381b56b3d07SJens Wiklander uint32_t object_handle = 0; 382b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 383b56b3d07SJens Wiklander struct pkcs11_object *object = NULL; 384b56b3d07SJens Wiklander 385b56b3d07SJens Wiklander if (!client || ptypes != exp_pt) 386b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 387b56b3d07SJens Wiklander 388b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 389b56b3d07SJens Wiklander 39059a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 391b56b3d07SJens Wiklander if (rc) 392b56b3d07SJens Wiklander return rc; 393b56b3d07SJens Wiklander 394b56b3d07SJens Wiklander rc = serialargs_get_u32(&ctrlargs, &object_handle); 395b56b3d07SJens Wiklander if (rc) 396b56b3d07SJens Wiklander return rc; 397b56b3d07SJens Wiklander 398b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 399b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 400b56b3d07SJens Wiklander 401b56b3d07SJens Wiklander object = pkcs11_handle2object(object_handle, session); 402b56b3d07SJens Wiklander if (!object) 403b56b3d07SJens Wiklander return PKCS11_CKR_OBJECT_HANDLE_INVALID; 404b56b3d07SJens Wiklander 405fab91492SRuchika Gupta /* Only session objects can be destroyed during a read-only session */ 406fab91492SRuchika Gupta if (get_bool(object->attributes, PKCS11_CKA_TOKEN) && 407fab91492SRuchika Gupta !pkcs11_session_is_read_write(session)) { 408fab91492SRuchika Gupta DMSG("Can't destroy persistent object"); 409fab91492SRuchika Gupta return PKCS11_CKR_SESSION_READ_ONLY; 410fab91492SRuchika Gupta } 411fab91492SRuchika Gupta 412fab91492SRuchika Gupta /* 413fab91492SRuchika Gupta * Only public objects can be destroyed unless normal user is logged in 414fab91492SRuchika Gupta */ 415fab91492SRuchika Gupta rc = check_access_attrs_against_token(session, object->attributes); 416fab91492SRuchika Gupta if (rc) 417fab91492SRuchika Gupta return PKCS11_CKR_USER_NOT_LOGGED_IN; 418fab91492SRuchika Gupta 419fab91492SRuchika Gupta /* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */ 420fab91492SRuchika Gupta if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE)) 421fab91492SRuchika Gupta return PKCS11_CKR_ACTION_PROHIBITED; 422fab91492SRuchika Gupta 423b56b3d07SJens Wiklander destroy_object(session, object, false); 424b56b3d07SJens Wiklander 425b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32, 426b56b3d07SJens Wiklander session->handle, object_handle); 427b56b3d07SJens Wiklander 428b56b3d07SJens Wiklander return rc; 429b56b3d07SJens Wiklander } 430dc99b202SRuchika Gupta 431dc99b202SRuchika Gupta static enum pkcs11_rc token_obj_matches_ref(struct obj_attrs *req_attrs, 432dc99b202SRuchika Gupta struct pkcs11_object *obj) 433dc99b202SRuchika Gupta { 434dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 435dc99b202SRuchika Gupta TEE_Result res = TEE_ERROR_GENERIC; 436dc99b202SRuchika Gupta TEE_ObjectHandle hdl = obj->attribs_hdl; 437dc99b202SRuchika Gupta TEE_ObjectInfo info = { }; 438dc99b202SRuchika Gupta struct obj_attrs *attr = NULL; 439dc99b202SRuchika Gupta uint32_t read_bytes = 0; 440dc99b202SRuchika Gupta 441dc99b202SRuchika Gupta if (obj->attributes) { 442dc99b202SRuchika Gupta if (!attributes_match_reference(obj->attributes, req_attrs)) 443dc99b202SRuchika Gupta return PKCS11_RV_NOT_FOUND; 444dc99b202SRuchika Gupta 445dc99b202SRuchika Gupta return PKCS11_CKR_OK; 446dc99b202SRuchika Gupta } 447dc99b202SRuchika Gupta 448dc99b202SRuchika Gupta if (hdl == TEE_HANDLE_NULL) { 449dc99b202SRuchika Gupta res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, 450dc99b202SRuchika Gupta obj->uuid, sizeof(*obj->uuid), 451dc99b202SRuchika Gupta TEE_DATA_FLAG_ACCESS_READ, 452dc99b202SRuchika Gupta &hdl); 453dc99b202SRuchika Gupta if (res) { 454dc99b202SRuchika Gupta EMSG("OpenPersistent failed %#"PRIx32, res); 455dc99b202SRuchika Gupta return tee2pkcs_error(res); 456dc99b202SRuchika Gupta } 457dc99b202SRuchika Gupta } 458dc99b202SRuchika Gupta 459dc99b202SRuchika Gupta res = TEE_GetObjectInfo1(hdl, &info); 460dc99b202SRuchika Gupta if (res) { 461dc99b202SRuchika Gupta EMSG("GetObjectInfo failed %#"PRIx32, res); 462dc99b202SRuchika Gupta rc = tee2pkcs_error(res); 463dc99b202SRuchika Gupta goto out; 464dc99b202SRuchika Gupta } 465dc99b202SRuchika Gupta 466dc99b202SRuchika Gupta attr = TEE_Malloc(info.dataSize, TEE_MALLOC_FILL_ZERO); 467dc99b202SRuchika Gupta if (!attr) { 468dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 469dc99b202SRuchika Gupta goto out; 470dc99b202SRuchika Gupta } 471dc99b202SRuchika Gupta 472dc99b202SRuchika Gupta res = TEE_ReadObjectData(hdl, attr, info.dataSize, &read_bytes); 473dc99b202SRuchika Gupta if (!res) { 474dc99b202SRuchika Gupta res = TEE_SeekObjectData(hdl, 0, TEE_DATA_SEEK_SET); 475dc99b202SRuchika Gupta if (res) 476dc99b202SRuchika Gupta EMSG("Seek to 0 failed with %#"PRIx32, res); 477dc99b202SRuchika Gupta } 478dc99b202SRuchika Gupta 479dc99b202SRuchika Gupta if (res) { 480dc99b202SRuchika Gupta rc = tee2pkcs_error(res); 481dc99b202SRuchika Gupta EMSG("Read %"PRIu32" bytes, failed %#"PRIx32, 482dc99b202SRuchika Gupta read_bytes, res); 483dc99b202SRuchika Gupta goto out; 484dc99b202SRuchika Gupta } 485dc99b202SRuchika Gupta 486dc99b202SRuchika Gupta if (read_bytes != info.dataSize) { 487dc99b202SRuchika Gupta EMSG("Read %"PRIu32" bytes, expected %"PRIu32, 488dc99b202SRuchika Gupta read_bytes, info.dataSize); 489dc99b202SRuchika Gupta rc = PKCS11_CKR_GENERAL_ERROR; 490dc99b202SRuchika Gupta goto out; 491dc99b202SRuchika Gupta } 492dc99b202SRuchika Gupta 493dc99b202SRuchika Gupta if (!attributes_match_reference(attr, req_attrs)) { 494dc99b202SRuchika Gupta rc = PKCS11_RV_NOT_FOUND; 495dc99b202SRuchika Gupta goto out; 496dc99b202SRuchika Gupta } 497dc99b202SRuchika Gupta 498dc99b202SRuchika Gupta obj->attributes = attr; 499dc99b202SRuchika Gupta attr = NULL; 500dc99b202SRuchika Gupta obj->attribs_hdl = hdl; 501dc99b202SRuchika Gupta hdl = TEE_HANDLE_NULL; 502dc99b202SRuchika Gupta 503dc99b202SRuchika Gupta rc = PKCS11_CKR_OK; 504dc99b202SRuchika Gupta 505dc99b202SRuchika Gupta out: 506dc99b202SRuchika Gupta TEE_Free(attr); 507dc99b202SRuchika Gupta if (obj->attribs_hdl == TEE_HANDLE_NULL) 508dc99b202SRuchika Gupta TEE_CloseObject(hdl); 509dc99b202SRuchika Gupta 510dc99b202SRuchika Gupta return rc; 511dc99b202SRuchika Gupta } 512dc99b202SRuchika Gupta 513dc99b202SRuchika Gupta static void release_find_obj_context(struct pkcs11_find_objects *find_ctx) 514dc99b202SRuchika Gupta { 515dc99b202SRuchika Gupta if (!find_ctx) 516dc99b202SRuchika Gupta return; 517dc99b202SRuchika Gupta 518dc99b202SRuchika Gupta TEE_Free(find_ctx->attributes); 519dc99b202SRuchika Gupta TEE_Free(find_ctx->handles); 520dc99b202SRuchika Gupta TEE_Free(find_ctx); 521dc99b202SRuchika Gupta } 522dc99b202SRuchika Gupta 523dc99b202SRuchika Gupta static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx, 524dc99b202SRuchika Gupta uint32_t handle) 525dc99b202SRuchika Gupta { 526dc99b202SRuchika Gupta uint32_t *hdls = TEE_Realloc(find_ctx->handles, 527dc99b202SRuchika Gupta (find_ctx->count + 1) * sizeof(*hdls)); 528dc99b202SRuchika Gupta 529dc99b202SRuchika Gupta if (!hdls) 530dc99b202SRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY; 531dc99b202SRuchika Gupta 532dc99b202SRuchika Gupta find_ctx->handles = hdls; 533dc99b202SRuchika Gupta 534dc99b202SRuchika Gupta *(find_ctx->handles + find_ctx->count) = handle; 535dc99b202SRuchika Gupta find_ctx->count++; 536dc99b202SRuchika Gupta 537dc99b202SRuchika Gupta return PKCS11_CKR_OK; 538dc99b202SRuchika Gupta } 539dc99b202SRuchika Gupta 540dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, 541dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 542dc99b202SRuchika Gupta { 543dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 544dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 545dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 546dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 547dc99b202SRuchika Gupta TEE_Param *ctrl = params; 548dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 549dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 550dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 551dc99b202SRuchika Gupta struct pkcs11_object_head *template = NULL; 552dc99b202SRuchika Gupta struct obj_attrs *req_attrs = NULL; 553dc99b202SRuchika Gupta struct pkcs11_object *obj = NULL; 554dc99b202SRuchika Gupta struct pkcs11_find_objects *find_ctx = NULL; 555dc99b202SRuchika Gupta 556dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 557dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 558dc99b202SRuchika Gupta 559dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 560dc99b202SRuchika Gupta 561dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 562dc99b202SRuchika Gupta if (rc) 563dc99b202SRuchika Gupta return rc; 564dc99b202SRuchika Gupta 565dc99b202SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 566dc99b202SRuchika Gupta if (rc) 567dc99b202SRuchika Gupta return rc; 568dc99b202SRuchika Gupta 569dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 570dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 571dc99b202SRuchika Gupta goto out; 572dc99b202SRuchika Gupta } 573dc99b202SRuchika Gupta 574dc99b202SRuchika Gupta /* Search objects only if no operation is on-going */ 575dc99b202SRuchika Gupta if (session_is_active(session)) { 576dc99b202SRuchika Gupta rc = PKCS11_CKR_OPERATION_ACTIVE; 577dc99b202SRuchika Gupta goto out; 578dc99b202SRuchika Gupta } 579dc99b202SRuchika Gupta 580dc99b202SRuchika Gupta if (session->find_ctx) { 581dc99b202SRuchika Gupta EMSG("Active object search already in progress"); 582dc99b202SRuchika Gupta rc = PKCS11_CKR_FUNCTION_FAILED; 583dc99b202SRuchika Gupta goto out; 584dc99b202SRuchika Gupta } 585dc99b202SRuchika Gupta 586dc99b202SRuchika Gupta rc = sanitize_client_object(&req_attrs, template, 587dc99b202SRuchika Gupta sizeof(*template) + template->attrs_size, 588dc99b202SRuchika Gupta PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID); 589dc99b202SRuchika Gupta if (rc) 590dc99b202SRuchika Gupta goto out; 591dc99b202SRuchika Gupta 592dc99b202SRuchika Gupta /* Must zero init the structure */ 593dc99b202SRuchika Gupta find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO); 594dc99b202SRuchika Gupta if (!find_ctx) { 595dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 596dc99b202SRuchika Gupta goto out; 597dc99b202SRuchika Gupta } 598dc99b202SRuchika Gupta 599dc99b202SRuchika Gupta TEE_Free(template); 600dc99b202SRuchika Gupta template = NULL; 601dc99b202SRuchika Gupta 602dc99b202SRuchika Gupta switch (get_class(req_attrs)) { 603dc99b202SRuchika Gupta case PKCS11_CKO_UNDEFINED_ID: 604dc99b202SRuchika Gupta /* Unspecified class searches among data objects */ 605dc99b202SRuchika Gupta case PKCS11_CKO_SECRET_KEY: 606dc99b202SRuchika Gupta case PKCS11_CKO_PUBLIC_KEY: 607dc99b202SRuchika Gupta case PKCS11_CKO_PRIVATE_KEY: 608dc99b202SRuchika Gupta case PKCS11_CKO_DATA: 609dc99b202SRuchika Gupta break; 610dc99b202SRuchika Gupta default: 611dc99b202SRuchika Gupta EMSG("Find object of class %s (%"PRIu32") is not supported", 612dc99b202SRuchika Gupta id2str_class(get_class(req_attrs)), 613dc99b202SRuchika Gupta get_class(req_attrs)); 614dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 615dc99b202SRuchika Gupta goto out; 616dc99b202SRuchika Gupta } 617dc99b202SRuchika Gupta 618dc99b202SRuchika Gupta /* 619dc99b202SRuchika Gupta * Scan all objects (sessions and persistent ones) and set a list of 620dc99b202SRuchika Gupta * candidates that match caller attributes. 621dc99b202SRuchika Gupta */ 622dc99b202SRuchika Gupta 623dc99b202SRuchika Gupta LIST_FOREACH(obj, &session->object_list, link) { 624dc99b202SRuchika Gupta if (check_access_attrs_against_token(session, obj->attributes)) 625dc99b202SRuchika Gupta continue; 626dc99b202SRuchika Gupta 627dc99b202SRuchika Gupta if (req_attrs->attrs_count && 628dc99b202SRuchika Gupta !attributes_match_reference(obj->attributes, req_attrs)) 629dc99b202SRuchika Gupta continue; 630dc99b202SRuchika Gupta 631dc99b202SRuchika Gupta rc = find_ctx_add(find_ctx, pkcs11_object2handle(obj, session)); 632dc99b202SRuchika Gupta if (rc) 633dc99b202SRuchika Gupta goto out; 634dc99b202SRuchika Gupta } 635dc99b202SRuchika Gupta 636dc99b202SRuchika Gupta LIST_FOREACH(obj, &session->token->object_list, link) { 637dc99b202SRuchika Gupta uint32_t handle = 0; 638dc99b202SRuchika Gupta 639dc99b202SRuchika Gupta if (check_access_attrs_against_token(session, obj->attributes)) 640dc99b202SRuchika Gupta continue; 641dc99b202SRuchika Gupta 642dc99b202SRuchika Gupta if (req_attrs->attrs_count) { 643dc99b202SRuchika Gupta rc = token_obj_matches_ref(req_attrs, obj); 644dc99b202SRuchika Gupta if (rc == PKCS11_RV_NOT_FOUND) 645dc99b202SRuchika Gupta continue; 646dc99b202SRuchika Gupta if (rc != PKCS11_CKR_OK) 647dc99b202SRuchika Gupta goto out; 648dc99b202SRuchika Gupta } 649dc99b202SRuchika Gupta 650dc99b202SRuchika Gupta /* Object may not yet be published in the session */ 651dc99b202SRuchika Gupta handle = pkcs11_object2handle(obj, session); 652dc99b202SRuchika Gupta if (!handle) { 653dc99b202SRuchika Gupta handle = handle_get(&session->object_handle_db, obj); 654dc99b202SRuchika Gupta if (!handle) { 655dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 656dc99b202SRuchika Gupta goto out; 657dc99b202SRuchika Gupta } 658dc99b202SRuchika Gupta } 659dc99b202SRuchika Gupta 660dc99b202SRuchika Gupta rc = find_ctx_add(find_ctx, handle); 661dc99b202SRuchika Gupta if (rc) 662dc99b202SRuchika Gupta goto out; 663dc99b202SRuchika Gupta } 664dc99b202SRuchika Gupta 665dc99b202SRuchika Gupta find_ctx->attributes = req_attrs; 666dc99b202SRuchika Gupta req_attrs = NULL; 667dc99b202SRuchika Gupta session->find_ctx = find_ctx; 668dc99b202SRuchika Gupta find_ctx = NULL; 669dc99b202SRuchika Gupta rc = PKCS11_CKR_OK; 670dc99b202SRuchika Gupta 671dc99b202SRuchika Gupta out: 672dc99b202SRuchika Gupta TEE_Free(req_attrs); 673dc99b202SRuchika Gupta TEE_Free(template); 674dc99b202SRuchika Gupta release_find_obj_context(find_ctx); 675dc99b202SRuchika Gupta 676dc99b202SRuchika Gupta return rc; 677dc99b202SRuchika Gupta } 678dc99b202SRuchika Gupta 679dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, 680dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 681dc99b202SRuchika Gupta { 682dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 683dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 684dc99b202SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 685dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 686dc99b202SRuchika Gupta TEE_Param *ctrl = params; 687dc99b202SRuchika Gupta TEE_Param *out = params + 2; 688dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 689dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 690dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 691dc99b202SRuchika Gupta struct pkcs11_find_objects *ctx = NULL; 692dc99b202SRuchika Gupta uint8_t *out_handles = NULL; 693dc99b202SRuchika Gupta size_t out_count = 0; 694dc99b202SRuchika Gupta size_t count = 0; 695dc99b202SRuchika Gupta 696dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 697dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 698dc99b202SRuchika Gupta 699dc99b202SRuchika Gupta out_count = out->memref.size / sizeof(uint32_t); 700dc99b202SRuchika Gupta out_handles = out->memref.buffer; 701dc99b202SRuchika Gupta 702dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 703dc99b202SRuchika Gupta 704dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 705dc99b202SRuchika Gupta if (rc) 706dc99b202SRuchika Gupta return rc; 707dc99b202SRuchika Gupta 708dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 709dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 710dc99b202SRuchika Gupta 711dc99b202SRuchika Gupta ctx = session->find_ctx; 712dc99b202SRuchika Gupta 713dc99b202SRuchika Gupta if (!ctx) 714dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 715dc99b202SRuchika Gupta 716dc99b202SRuchika Gupta for (count = 0; ctx->next < ctx->count && count < out_count; 717dc99b202SRuchika Gupta ctx->next++, count++) 718dc99b202SRuchika Gupta TEE_MemMove(out_handles + count * sizeof(uint32_t), 719dc99b202SRuchika Gupta ctx->handles + ctx->next, sizeof(uint32_t)); 720dc99b202SRuchika Gupta 721dc99b202SRuchika Gupta /* Update output buffer according the number of handles provided */ 722dc99b202SRuchika Gupta out->memref.size = count * sizeof(uint32_t); 723dc99b202SRuchika Gupta 724dc99b202SRuchika Gupta DMSG("PKCS11 session %"PRIu32": finding objects", session->handle); 725dc99b202SRuchika Gupta 726dc99b202SRuchika Gupta return PKCS11_CKR_OK; 727dc99b202SRuchika Gupta } 728dc99b202SRuchika Gupta 729dc99b202SRuchika Gupta void release_session_find_obj_context(struct pkcs11_session *session) 730dc99b202SRuchika Gupta { 731dc99b202SRuchika Gupta release_find_obj_context(session->find_ctx); 732dc99b202SRuchika Gupta session->find_ctx = NULL; 733dc99b202SRuchika Gupta } 734dc99b202SRuchika Gupta 735dc99b202SRuchika Gupta uint32_t entry_find_objects_final(struct pkcs11_client *client, 736dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 737dc99b202SRuchika Gupta { 738dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 739dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 740dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 741dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 742dc99b202SRuchika Gupta TEE_Param *ctrl = params; 743dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 744dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 745dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 746dc99b202SRuchika Gupta 747dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 748dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 749dc99b202SRuchika Gupta 750dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 751dc99b202SRuchika Gupta 752dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 753dc99b202SRuchika Gupta if (rc) 754dc99b202SRuchika Gupta return rc; 755dc99b202SRuchika Gupta 756dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 757dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 758dc99b202SRuchika Gupta 759dc99b202SRuchika Gupta if (!session->find_ctx) 760dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 761dc99b202SRuchika Gupta 762dc99b202SRuchika Gupta release_session_find_obj_context(session); 763dc99b202SRuchika Gupta 764dc99b202SRuchika Gupta return PKCS11_CKR_OK; 765dc99b202SRuchika Gupta } 766*783c1515SRuchika Gupta 767*783c1515SRuchika Gupta uint32_t entry_get_attribute_value(struct pkcs11_client *client, 768*783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params) 769*783c1515SRuchika Gupta { 770*783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 771*783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE, 772*783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 773*783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE); 774*783c1515SRuchika Gupta TEE_Param *ctrl = params; 775*783c1515SRuchika Gupta TEE_Param *out = params + 2; 776*783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 777*783c1515SRuchika Gupta struct serialargs ctrlargs = { }; 778*783c1515SRuchika Gupta struct pkcs11_session *session = NULL; 779*783c1515SRuchika Gupta struct pkcs11_object_head *template = NULL; 780*783c1515SRuchika Gupta struct pkcs11_object *obj = NULL; 781*783c1515SRuchika Gupta uint32_t object_handle = 0; 782*783c1515SRuchika Gupta char *cur = NULL; 783*783c1515SRuchika Gupta size_t len = 0; 784*783c1515SRuchika Gupta char *end = NULL; 785*783c1515SRuchika Gupta bool attr_sensitive = 0; 786*783c1515SRuchika Gupta bool attr_type_invalid = 0; 787*783c1515SRuchika Gupta bool buffer_too_small = 0; 788*783c1515SRuchika Gupta 789*783c1515SRuchika Gupta if (!client || ptypes != exp_pt) 790*783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 791*783c1515SRuchika Gupta 792*783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 793*783c1515SRuchika Gupta 794*783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 795*783c1515SRuchika Gupta if (rc) 796*783c1515SRuchika Gupta return rc; 797*783c1515SRuchika Gupta 798*783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 799*783c1515SRuchika Gupta if (rc) 800*783c1515SRuchika Gupta return rc; 801*783c1515SRuchika Gupta 802*783c1515SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 803*783c1515SRuchika Gupta if (rc) 804*783c1515SRuchika Gupta return rc; 805*783c1515SRuchika Gupta 806*783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 807*783c1515SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 808*783c1515SRuchika Gupta goto out; 809*783c1515SRuchika Gupta } 810*783c1515SRuchika Gupta 811*783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 812*783c1515SRuchika Gupta if (!obj) { 813*783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 814*783c1515SRuchika Gupta goto out; 815*783c1515SRuchika Gupta } 816*783c1515SRuchika Gupta 817*783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 818*783c1515SRuchika Gupta if (rc) { 819*783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 820*783c1515SRuchika Gupta goto out; 821*783c1515SRuchika Gupta } 822*783c1515SRuchika Gupta 823*783c1515SRuchika Gupta /* Iterate over attributes and set their values */ 824*783c1515SRuchika Gupta /* 825*783c1515SRuchika Gupta * 1. If the specified attribute (i.e., the attribute specified by the 826*783c1515SRuchika Gupta * type field) for the object cannot be revealed because the object is 827*783c1515SRuchika Gupta * sensitive or unextractable, then the ulValueLen field in that triple 828*783c1515SRuchika Gupta * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION. 829*783c1515SRuchika Gupta * 830*783c1515SRuchika Gupta * 2. Otherwise, if the specified value for the object is invalid (the 831*783c1515SRuchika Gupta * object does not possess such an attribute), then the ulValueLen field 832*783c1515SRuchika Gupta * in that triple is modified to hold the value 833*783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION. 834*783c1515SRuchika Gupta * 835*783c1515SRuchika Gupta * 3. Otherwise, if the pValue field has the value NULL_PTR, then the 836*783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the 837*783c1515SRuchika Gupta * specified attribute for the object. 838*783c1515SRuchika Gupta * 839*783c1515SRuchika Gupta * 4. Otherwise, if the length specified in ulValueLen is large enough 840*783c1515SRuchika Gupta * to hold the value of the specified attribute for the object, then 841*783c1515SRuchika Gupta * that attribute is copied into the buffer located at pValue, and the 842*783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the 843*783c1515SRuchika Gupta * attribute. 844*783c1515SRuchika Gupta * 845*783c1515SRuchika Gupta * 5. Otherwise, the ulValueLen field is modified to hold the value 846*783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION. 847*783c1515SRuchika Gupta */ 848*783c1515SRuchika Gupta cur = (char *)template + sizeof(struct pkcs11_object_head); 849*783c1515SRuchika Gupta end = cur + template->attrs_size; 850*783c1515SRuchika Gupta 851*783c1515SRuchika Gupta for (; cur < end; cur += len) { 852*783c1515SRuchika Gupta struct pkcs11_attribute_head *cli_ref = (void *)cur; 853*783c1515SRuchika Gupta 854*783c1515SRuchika Gupta len = sizeof(*cli_ref) + cli_ref->size; 855*783c1515SRuchika Gupta 856*783c1515SRuchika Gupta /* Check 1. */ 857*783c1515SRuchika Gupta if (!attribute_is_exportable(cli_ref, obj)) { 858*783c1515SRuchika Gupta cli_ref->size = PKCS11_CK_UNAVAILABLE_INFORMATION; 859*783c1515SRuchika Gupta attr_sensitive = 1; 860*783c1515SRuchika Gupta continue; 861*783c1515SRuchika Gupta } 862*783c1515SRuchika Gupta 863*783c1515SRuchika Gupta /* 864*783c1515SRuchika Gupta * We assume that if size is 0, pValue was NULL, so we return 865*783c1515SRuchika Gupta * the size of the required buffer for it (3., 4.) 866*783c1515SRuchika Gupta */ 867*783c1515SRuchika Gupta rc = get_attribute(obj->attributes, cli_ref->id, 868*783c1515SRuchika Gupta cli_ref->size ? cli_ref->data : NULL, 869*783c1515SRuchika Gupta &cli_ref->size); 870*783c1515SRuchika Gupta /* Check 2. */ 871*783c1515SRuchika Gupta switch (rc) { 872*783c1515SRuchika Gupta case PKCS11_CKR_OK: 873*783c1515SRuchika Gupta break; 874*783c1515SRuchika Gupta case PKCS11_RV_NOT_FOUND: 875*783c1515SRuchika Gupta cli_ref->size = PKCS11_CK_UNAVAILABLE_INFORMATION; 876*783c1515SRuchika Gupta attr_type_invalid = 1; 877*783c1515SRuchika Gupta break; 878*783c1515SRuchika Gupta case PKCS11_CKR_BUFFER_TOO_SMALL: 879*783c1515SRuchika Gupta buffer_too_small = 1; 880*783c1515SRuchika Gupta break; 881*783c1515SRuchika Gupta default: 882*783c1515SRuchika Gupta rc = PKCS11_CKR_GENERAL_ERROR; 883*783c1515SRuchika Gupta goto out; 884*783c1515SRuchika Gupta } 885*783c1515SRuchika Gupta } 886*783c1515SRuchika Gupta 887*783c1515SRuchika Gupta /* 888*783c1515SRuchika Gupta * If case 1 applies to any of the requested attributes, then the call 889*783c1515SRuchika Gupta * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to 890*783c1515SRuchika Gupta * any of the requested attributes, then the call should return the 891*783c1515SRuchika Gupta * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the 892*783c1515SRuchika Gupta * requested attributes, then the call should return the value 893*783c1515SRuchika Gupta * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes 894*783c1515SRuchika Gupta * is applicable, Cryptoki may return any of them. Only if none of them 895*783c1515SRuchika Gupta * applies to any of the requested attributes will CKR_OK be returned. 896*783c1515SRuchika Gupta */ 897*783c1515SRuchika Gupta 898*783c1515SRuchika Gupta rc = PKCS11_CKR_OK; 899*783c1515SRuchika Gupta if (attr_sensitive) 900*783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE; 901*783c1515SRuchika Gupta if (attr_type_invalid) 902*783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; 903*783c1515SRuchika Gupta if (buffer_too_small) 904*783c1515SRuchika Gupta rc = PKCS11_CKR_BUFFER_TOO_SMALL; 905*783c1515SRuchika Gupta 906*783c1515SRuchika Gupta /* Move updated template to out buffer */ 907*783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, template, out->memref.size); 908*783c1515SRuchika Gupta 909*783c1515SRuchika Gupta DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32, 910*783c1515SRuchika Gupta session->handle, object_handle); 911*783c1515SRuchika Gupta 912*783c1515SRuchika Gupta out: 913*783c1515SRuchika Gupta TEE_Free(template); 914*783c1515SRuchika Gupta 915*783c1515SRuchika Gupta return rc; 916*783c1515SRuchika Gupta } 917*783c1515SRuchika Gupta 918*783c1515SRuchika Gupta uint32_t entry_get_object_size(struct pkcs11_client *client, 919*783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params) 920*783c1515SRuchika Gupta { 921*783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 922*783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE, 923*783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 924*783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE); 925*783c1515SRuchika Gupta TEE_Param *ctrl = params; 926*783c1515SRuchika Gupta TEE_Param *out = params + 2; 927*783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 928*783c1515SRuchika Gupta struct serialargs ctrlargs = { }; 929*783c1515SRuchika Gupta struct pkcs11_session *session = NULL; 930*783c1515SRuchika Gupta uint32_t object_handle = 0; 931*783c1515SRuchika Gupta struct pkcs11_object *obj = NULL; 932*783c1515SRuchika Gupta uint32_t obj_size = 0; 933*783c1515SRuchika Gupta 934*783c1515SRuchika Gupta if (!client || ptypes != exp_pt) 935*783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 936*783c1515SRuchika Gupta 937*783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 938*783c1515SRuchika Gupta 939*783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 940*783c1515SRuchika Gupta if (rc) 941*783c1515SRuchika Gupta return rc; 942*783c1515SRuchika Gupta 943*783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 944*783c1515SRuchika Gupta if (rc) 945*783c1515SRuchika Gupta return rc; 946*783c1515SRuchika Gupta 947*783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 948*783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 949*783c1515SRuchika Gupta 950*783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 951*783c1515SRuchika Gupta if (!obj) 952*783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID; 953*783c1515SRuchika Gupta 954*783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 955*783c1515SRuchika Gupta if (rc) 956*783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID; 957*783c1515SRuchika Gupta 958*783c1515SRuchika Gupta if (out->memref.size != sizeof(uint32_t)) 959*783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 960*783c1515SRuchika Gupta 961*783c1515SRuchika Gupta obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size + 962*783c1515SRuchika Gupta sizeof(struct obj_attrs); 963*783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size)); 964*783c1515SRuchika Gupta 965*783c1515SRuchika Gupta return PKCS11_CKR_OK; 966*783c1515SRuchika Gupta } 967