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 2470fafe5c7SVesa Jääskeläinen TEE_CloseObject(obj->attribs_hdl); 2480fafe5c7SVesa Jääskeläinen obj->attribs_hdl = TEE_HANDLE_NULL; 2490fafe5c7SVesa Jääskeläinen 250334316feSJens Wiklander LIST_INSERT_HEAD(&session->token->object_list, obj, link); 251b56b3d07SJens Wiklander } else { 252b56b3d07SJens Wiklander rc = PKCS11_CKR_OK; 253b56b3d07SJens Wiklander LIST_INSERT_HEAD(get_session_objects(session), obj, link); 254b56b3d07SJens Wiklander } 255b56b3d07SJens Wiklander 256b56b3d07SJens Wiklander *out_handle = obj_handle; 257b56b3d07SJens Wiklander 258b56b3d07SJens Wiklander return PKCS11_CKR_OK; 259b56b3d07SJens Wiklander err: 260b56b3d07SJens Wiklander /* make sure that supplied "head" isn't freed */ 261b56b3d07SJens Wiklander obj->attributes = NULL; 262b56b3d07SJens Wiklander handle_put(&session->object_handle_db, obj_handle); 263b56b3d07SJens Wiklander if (get_bool(head, PKCS11_CKA_TOKEN)) 264b56b3d07SJens Wiklander cleanup_persistent_object(obj, session->token); 265b56b3d07SJens Wiklander else 266b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 267b56b3d07SJens Wiklander 268b56b3d07SJens Wiklander return rc; 269b56b3d07SJens Wiklander } 270b56b3d07SJens Wiklander 271b56b3d07SJens Wiklander enum pkcs11_rc entry_create_object(struct pkcs11_client *client, 272b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 273b56b3d07SJens Wiklander { 274b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 275b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 276b56b3d07SJens Wiklander TEE_PARAM_TYPE_MEMREF_OUTPUT, 277b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 278b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 279b56b3d07SJens Wiklander TEE_Param *ctrl = params; 280b56b3d07SJens Wiklander TEE_Param *out = params + 2; 281b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 282b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 283b56b3d07SJens Wiklander struct obj_attrs *head = NULL; 284b56b3d07SJens Wiklander struct pkcs11_object_head *template = NULL; 285b56b3d07SJens Wiklander size_t template_size = 0; 286b56b3d07SJens Wiklander uint32_t obj_handle = 0; 287b56b3d07SJens Wiklander 288b56b3d07SJens Wiklander /* 289b56b3d07SJens Wiklander * Collect the arguments of the request 290b56b3d07SJens Wiklander */ 291b56b3d07SJens Wiklander 292b56b3d07SJens Wiklander if (!client || ptypes != exp_pt || 293b56b3d07SJens Wiklander out->memref.size != sizeof(obj_handle)) 294b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 295b56b3d07SJens Wiklander 296b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 297b56b3d07SJens Wiklander 29859a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 299b56b3d07SJens Wiklander if (rc) 300b56b3d07SJens Wiklander return rc; 301b56b3d07SJens Wiklander 302b56b3d07SJens Wiklander rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 303b56b3d07SJens Wiklander if (rc) 304b56b3d07SJens Wiklander return rc; 305b56b3d07SJens Wiklander 306b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 307b56b3d07SJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 308b56b3d07SJens Wiklander goto out; 309b56b3d07SJens Wiklander } 310b56b3d07SJens Wiklander 311b56b3d07SJens Wiklander template_size = sizeof(*template) + template->attrs_size; 312b56b3d07SJens Wiklander 313b56b3d07SJens Wiklander /* 314b56b3d07SJens Wiklander * Prepare a clean initial state for the requested object attributes. 315b56b3d07SJens Wiklander * Free temporary template once done. 316b56b3d07SJens Wiklander */ 317b56b3d07SJens Wiklander rc = create_attributes_from_template(&head, template, template_size, 318b56b3d07SJens Wiklander NULL, PKCS11_FUNCTION_IMPORT, 3194cfce748SRuchika Gupta PKCS11_PROCESSING_IMPORT, 3204cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 321b56b3d07SJens Wiklander TEE_Free(template); 322b56b3d07SJens Wiklander template = NULL; 323b56b3d07SJens Wiklander if (rc) 324b56b3d07SJens Wiklander goto out; 325b56b3d07SJens Wiklander 326b56b3d07SJens Wiklander /* 327b56b3d07SJens Wiklander * Check target object attributes match target processing 328b56b3d07SJens Wiklander * Check target object attributes match token state 329b56b3d07SJens Wiklander */ 330b56b3d07SJens Wiklander rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT, 331b56b3d07SJens Wiklander head); 332b56b3d07SJens Wiklander if (rc) 333b56b3d07SJens Wiklander goto out; 334b56b3d07SJens Wiklander 335b56b3d07SJens Wiklander rc = check_created_attrs_against_token(session, head); 336b56b3d07SJens Wiklander if (rc) 337b56b3d07SJens Wiklander goto out; 338b56b3d07SJens Wiklander 339b68aca61SRuchika Gupta rc = check_access_attrs_against_token(session, head); 340b68aca61SRuchika Gupta if (rc) 341b68aca61SRuchika Gupta goto out; 342b68aca61SRuchika Gupta 343b56b3d07SJens Wiklander /* 344b56b3d07SJens Wiklander * At this stage the object is almost created: all its attributes are 345b56b3d07SJens Wiklander * referenced in @head, including the key value and are assumed 346b56b3d07SJens Wiklander * reliable. Now need to register it and get a handle for it. 347b56b3d07SJens Wiklander */ 348b56b3d07SJens Wiklander rc = create_object(session, head, &obj_handle); 349b56b3d07SJens Wiklander if (rc) 350b56b3d07SJens Wiklander goto out; 351b56b3d07SJens Wiklander 352b56b3d07SJens Wiklander /* 353b56b3d07SJens Wiklander * Now obj_handle (through the related struct pkcs11_object 354e3737878SRuchika Gupta * instance) owns the serialized buffer that holds the object 355b56b3d07SJens Wiklander * attributes. We clear reference in head to NULL as the serializer 356b56b3d07SJens Wiklander * object is now referred from obj_handle. This allows smooth pass 357b56b3d07SJens Wiklander * through free at function exit. 358b56b3d07SJens Wiklander */ 359b56b3d07SJens Wiklander head = NULL; 360b56b3d07SJens Wiklander 361b56b3d07SJens Wiklander TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 362b56b3d07SJens Wiklander out->memref.size = sizeof(obj_handle); 363b56b3d07SJens Wiklander 364b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32, 365b56b3d07SJens Wiklander session->handle, obj_handle); 366b56b3d07SJens Wiklander 367b56b3d07SJens Wiklander out: 368b56b3d07SJens Wiklander TEE_Free(template); 369b56b3d07SJens Wiklander TEE_Free(head); 370b56b3d07SJens Wiklander 371b56b3d07SJens Wiklander return rc; 372b56b3d07SJens Wiklander } 373b56b3d07SJens Wiklander 374b56b3d07SJens Wiklander enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, 375b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 376b56b3d07SJens Wiklander { 377b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 378b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 379b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 380b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 381b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 382b56b3d07SJens Wiklander TEE_Param *ctrl = params; 383b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 384b56b3d07SJens Wiklander uint32_t object_handle = 0; 385b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 386b56b3d07SJens Wiklander struct pkcs11_object *object = NULL; 387b56b3d07SJens Wiklander 388b56b3d07SJens Wiklander if (!client || ptypes != exp_pt) 389b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 390b56b3d07SJens Wiklander 391b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 392b56b3d07SJens Wiklander 39359a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 394b56b3d07SJens Wiklander if (rc) 395b56b3d07SJens Wiklander return rc; 396b56b3d07SJens Wiklander 397b56b3d07SJens Wiklander rc = serialargs_get_u32(&ctrlargs, &object_handle); 398b56b3d07SJens Wiklander if (rc) 399b56b3d07SJens Wiklander return rc; 400b56b3d07SJens Wiklander 401b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 402b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 403b56b3d07SJens Wiklander 404b56b3d07SJens Wiklander object = pkcs11_handle2object(object_handle, session); 405b56b3d07SJens Wiklander if (!object) 406b56b3d07SJens Wiklander return PKCS11_CKR_OBJECT_HANDLE_INVALID; 407b56b3d07SJens Wiklander 408fab91492SRuchika Gupta /* Only session objects can be destroyed during a read-only session */ 409fab91492SRuchika Gupta if (get_bool(object->attributes, PKCS11_CKA_TOKEN) && 410fab91492SRuchika Gupta !pkcs11_session_is_read_write(session)) { 411fab91492SRuchika Gupta DMSG("Can't destroy persistent object"); 412fab91492SRuchika Gupta return PKCS11_CKR_SESSION_READ_ONLY; 413fab91492SRuchika Gupta } 414fab91492SRuchika Gupta 415fab91492SRuchika Gupta /* 416fab91492SRuchika Gupta * Only public objects can be destroyed unless normal user is logged in 417fab91492SRuchika Gupta */ 418fab91492SRuchika Gupta rc = check_access_attrs_against_token(session, object->attributes); 419fab91492SRuchika Gupta if (rc) 420fab91492SRuchika Gupta return PKCS11_CKR_USER_NOT_LOGGED_IN; 421fab91492SRuchika Gupta 422fab91492SRuchika Gupta /* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */ 423fab91492SRuchika Gupta if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE)) 424fab91492SRuchika Gupta return PKCS11_CKR_ACTION_PROHIBITED; 425fab91492SRuchika Gupta 426b56b3d07SJens Wiklander destroy_object(session, object, false); 427b56b3d07SJens Wiklander 428b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32, 429b56b3d07SJens Wiklander session->handle, object_handle); 430b56b3d07SJens Wiklander 431b56b3d07SJens Wiklander return rc; 432b56b3d07SJens Wiklander } 433dc99b202SRuchika Gupta 434dc99b202SRuchika Gupta static void release_find_obj_context(struct pkcs11_find_objects *find_ctx) 435dc99b202SRuchika Gupta { 436dc99b202SRuchika Gupta if (!find_ctx) 437dc99b202SRuchika Gupta return; 438dc99b202SRuchika Gupta 439dc99b202SRuchika Gupta TEE_Free(find_ctx->attributes); 440dc99b202SRuchika Gupta TEE_Free(find_ctx->handles); 441dc99b202SRuchika Gupta TEE_Free(find_ctx); 442dc99b202SRuchika Gupta } 443dc99b202SRuchika Gupta 444dc99b202SRuchika Gupta static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx, 445dc99b202SRuchika Gupta uint32_t handle) 446dc99b202SRuchika Gupta { 447dc99b202SRuchika Gupta uint32_t *hdls = TEE_Realloc(find_ctx->handles, 448dc99b202SRuchika Gupta (find_ctx->count + 1) * sizeof(*hdls)); 449dc99b202SRuchika Gupta 450dc99b202SRuchika Gupta if (!hdls) 451dc99b202SRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY; 452dc99b202SRuchika Gupta 453dc99b202SRuchika Gupta find_ctx->handles = hdls; 454dc99b202SRuchika Gupta 455dc99b202SRuchika Gupta *(find_ctx->handles + find_ctx->count) = handle; 456dc99b202SRuchika Gupta find_ctx->count++; 457dc99b202SRuchika Gupta 458dc99b202SRuchika Gupta return PKCS11_CKR_OK; 459dc99b202SRuchika Gupta } 460dc99b202SRuchika Gupta 461dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, 462dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 463dc99b202SRuchika Gupta { 464dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 465dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 466dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 467dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 468dc99b202SRuchika Gupta TEE_Param *ctrl = params; 469dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 470dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 471dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 472dc99b202SRuchika Gupta struct pkcs11_object_head *template = NULL; 473dc99b202SRuchika Gupta struct obj_attrs *req_attrs = NULL; 474dc99b202SRuchika Gupta struct pkcs11_object *obj = NULL; 475dc99b202SRuchika Gupta struct pkcs11_find_objects *find_ctx = NULL; 476dc99b202SRuchika Gupta 477dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 478dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 479dc99b202SRuchika Gupta 480dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 481dc99b202SRuchika Gupta 482dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 483dc99b202SRuchika Gupta if (rc) 484dc99b202SRuchika Gupta return rc; 485dc99b202SRuchika Gupta 486dc99b202SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 487dc99b202SRuchika Gupta if (rc) 488dc99b202SRuchika Gupta return rc; 489dc99b202SRuchika Gupta 490dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 491dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 492dc99b202SRuchika Gupta goto out; 493dc99b202SRuchika Gupta } 494dc99b202SRuchika Gupta 495dc99b202SRuchika Gupta /* Search objects only if no operation is on-going */ 496dc99b202SRuchika Gupta if (session_is_active(session)) { 497dc99b202SRuchika Gupta rc = PKCS11_CKR_OPERATION_ACTIVE; 498dc99b202SRuchika Gupta goto out; 499dc99b202SRuchika Gupta } 500dc99b202SRuchika Gupta 501dc99b202SRuchika Gupta if (session->find_ctx) { 502dc99b202SRuchika Gupta EMSG("Active object search already in progress"); 503dc99b202SRuchika Gupta rc = PKCS11_CKR_FUNCTION_FAILED; 504dc99b202SRuchika Gupta goto out; 505dc99b202SRuchika Gupta } 506dc99b202SRuchika Gupta 507dc99b202SRuchika Gupta rc = sanitize_client_object(&req_attrs, template, 508dc99b202SRuchika Gupta sizeof(*template) + template->attrs_size, 509dc99b202SRuchika Gupta PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID); 510dc99b202SRuchika Gupta if (rc) 511dc99b202SRuchika Gupta goto out; 512dc99b202SRuchika Gupta 513dc99b202SRuchika Gupta /* Must zero init the structure */ 514dc99b202SRuchika Gupta find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO); 515dc99b202SRuchika Gupta if (!find_ctx) { 516dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 517dc99b202SRuchika Gupta goto out; 518dc99b202SRuchika Gupta } 519dc99b202SRuchika Gupta 520dc99b202SRuchika Gupta TEE_Free(template); 521dc99b202SRuchika Gupta template = NULL; 522dc99b202SRuchika Gupta 523dc99b202SRuchika Gupta switch (get_class(req_attrs)) { 524dc99b202SRuchika Gupta case PKCS11_CKO_UNDEFINED_ID: 525dc99b202SRuchika Gupta /* Unspecified class searches among data objects */ 526dc99b202SRuchika Gupta case PKCS11_CKO_SECRET_KEY: 527dc99b202SRuchika Gupta case PKCS11_CKO_PUBLIC_KEY: 528dc99b202SRuchika Gupta case PKCS11_CKO_PRIVATE_KEY: 529dc99b202SRuchika Gupta case PKCS11_CKO_DATA: 530dc99b202SRuchika Gupta break; 531dc99b202SRuchika Gupta default: 532dc99b202SRuchika Gupta EMSG("Find object of class %s (%"PRIu32") is not supported", 533dc99b202SRuchika Gupta id2str_class(get_class(req_attrs)), 534dc99b202SRuchika Gupta get_class(req_attrs)); 535dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 536dc99b202SRuchika Gupta goto out; 537dc99b202SRuchika Gupta } 538dc99b202SRuchika Gupta 539dc99b202SRuchika Gupta /* 540dc99b202SRuchika Gupta * Scan all objects (sessions and persistent ones) and set a list of 541dc99b202SRuchika Gupta * candidates that match caller attributes. 542dc99b202SRuchika Gupta */ 543dc99b202SRuchika Gupta 544dc99b202SRuchika Gupta LIST_FOREACH(obj, &session->object_list, link) { 545dc99b202SRuchika Gupta if (check_access_attrs_against_token(session, obj->attributes)) 546dc99b202SRuchika Gupta continue; 547dc99b202SRuchika Gupta 548fa1ac767SRobin van der Gracht if (!attributes_match_reference(obj->attributes, req_attrs)) 549dc99b202SRuchika Gupta continue; 550dc99b202SRuchika Gupta 551dc99b202SRuchika Gupta rc = find_ctx_add(find_ctx, pkcs11_object2handle(obj, session)); 552dc99b202SRuchika Gupta if (rc) 553dc99b202SRuchika Gupta goto out; 554dc99b202SRuchika Gupta } 555dc99b202SRuchika Gupta 556dc99b202SRuchika Gupta LIST_FOREACH(obj, &session->token->object_list, link) { 557dc99b202SRuchika Gupta uint32_t handle = 0; 558fa1ac767SRobin van der Gracht bool new_load = false; 559dc99b202SRuchika Gupta 560fa1ac767SRobin van der Gracht if (!obj->attributes) { 561fa1ac767SRobin van der Gracht rc = load_persistent_object_attributes(obj); 562fa1ac767SRobin van der Gracht if (rc) 563fa1ac767SRobin van der Gracht return PKCS11_CKR_GENERAL_ERROR; 564dc99b202SRuchika Gupta 565fa1ac767SRobin van der Gracht new_load = true; 566fa1ac767SRobin van der Gracht } 567fa1ac767SRobin van der Gracht 568fa1ac767SRobin van der Gracht if (!obj->attributes || 569fa1ac767SRobin van der Gracht check_access_attrs_against_token(session, 570fa1ac767SRobin van der Gracht obj->attributes) || 571fa1ac767SRobin van der Gracht !attributes_match_reference(obj->attributes, req_attrs)) { 572fa1ac767SRobin van der Gracht if (new_load) 573fa1ac767SRobin van der Gracht release_persistent_object_attributes(obj); 574fa1ac767SRobin van der Gracht 575dc99b202SRuchika Gupta continue; 576dc99b202SRuchika Gupta } 577dc99b202SRuchika Gupta 578dc99b202SRuchika Gupta /* Object may not yet be published in the session */ 579dc99b202SRuchika Gupta handle = pkcs11_object2handle(obj, session); 580dc99b202SRuchika Gupta if (!handle) { 581dc99b202SRuchika Gupta handle = handle_get(&session->object_handle_db, obj); 582dc99b202SRuchika Gupta if (!handle) { 583dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 584dc99b202SRuchika Gupta goto out; 585dc99b202SRuchika Gupta } 586dc99b202SRuchika Gupta } 587dc99b202SRuchika Gupta 588dc99b202SRuchika Gupta rc = find_ctx_add(find_ctx, handle); 589dc99b202SRuchika Gupta if (rc) 590dc99b202SRuchika Gupta goto out; 591dc99b202SRuchika Gupta } 592dc99b202SRuchika Gupta 593dc99b202SRuchika Gupta find_ctx->attributes = req_attrs; 594dc99b202SRuchika Gupta req_attrs = NULL; 595dc99b202SRuchika Gupta session->find_ctx = find_ctx; 596dc99b202SRuchika Gupta find_ctx = NULL; 597dc99b202SRuchika Gupta rc = PKCS11_CKR_OK; 598dc99b202SRuchika Gupta 599dc99b202SRuchika Gupta out: 600dc99b202SRuchika Gupta TEE_Free(req_attrs); 601dc99b202SRuchika Gupta TEE_Free(template); 602dc99b202SRuchika Gupta release_find_obj_context(find_ctx); 603dc99b202SRuchika Gupta 604dc99b202SRuchika Gupta return rc; 605dc99b202SRuchika Gupta } 606dc99b202SRuchika Gupta 607dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, 608dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 609dc99b202SRuchika Gupta { 610dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 611dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 612dc99b202SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 613dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 614dc99b202SRuchika Gupta TEE_Param *ctrl = params; 615dc99b202SRuchika Gupta TEE_Param *out = params + 2; 616dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 617dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 618dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 619dc99b202SRuchika Gupta struct pkcs11_find_objects *ctx = NULL; 620dc99b202SRuchika Gupta uint8_t *out_handles = NULL; 621dc99b202SRuchika Gupta size_t out_count = 0; 622dc99b202SRuchika Gupta size_t count = 0; 623dc99b202SRuchika Gupta 624dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 625dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 626dc99b202SRuchika Gupta 627dc99b202SRuchika Gupta out_count = out->memref.size / sizeof(uint32_t); 628dc99b202SRuchika Gupta out_handles = out->memref.buffer; 629dc99b202SRuchika Gupta 630dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 631dc99b202SRuchika Gupta 632dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 633dc99b202SRuchika Gupta if (rc) 634dc99b202SRuchika Gupta return rc; 635dc99b202SRuchika Gupta 636dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 637dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 638dc99b202SRuchika Gupta 639dc99b202SRuchika Gupta ctx = session->find_ctx; 640dc99b202SRuchika Gupta 641dc99b202SRuchika Gupta if (!ctx) 642dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 643dc99b202SRuchika Gupta 644dc99b202SRuchika Gupta for (count = 0; ctx->next < ctx->count && count < out_count; 645dc99b202SRuchika Gupta ctx->next++, count++) 646dc99b202SRuchika Gupta TEE_MemMove(out_handles + count * sizeof(uint32_t), 647dc99b202SRuchika Gupta ctx->handles + ctx->next, sizeof(uint32_t)); 648dc99b202SRuchika Gupta 649dc99b202SRuchika Gupta /* Update output buffer according the number of handles provided */ 650dc99b202SRuchika Gupta out->memref.size = count * sizeof(uint32_t); 651dc99b202SRuchika Gupta 652dc99b202SRuchika Gupta DMSG("PKCS11 session %"PRIu32": finding objects", session->handle); 653dc99b202SRuchika Gupta 654dc99b202SRuchika Gupta return PKCS11_CKR_OK; 655dc99b202SRuchika Gupta } 656dc99b202SRuchika Gupta 657dc99b202SRuchika Gupta void release_session_find_obj_context(struct pkcs11_session *session) 658dc99b202SRuchika Gupta { 659dc99b202SRuchika Gupta release_find_obj_context(session->find_ctx); 660dc99b202SRuchika Gupta session->find_ctx = NULL; 661dc99b202SRuchika Gupta } 662dc99b202SRuchika Gupta 663e3737878SRuchika Gupta enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client, 664dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 665dc99b202SRuchika Gupta { 666dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 667dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 668dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 669dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 670dc99b202SRuchika Gupta TEE_Param *ctrl = params; 671dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 672dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 673dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 674dc99b202SRuchika Gupta 675dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 676dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 677dc99b202SRuchika Gupta 678dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 679dc99b202SRuchika Gupta 680dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 681dc99b202SRuchika Gupta if (rc) 682dc99b202SRuchika Gupta return rc; 683dc99b202SRuchika Gupta 684dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 685dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 686dc99b202SRuchika Gupta 687dc99b202SRuchika Gupta if (!session->find_ctx) 688dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 689dc99b202SRuchika Gupta 690dc99b202SRuchika Gupta release_session_find_obj_context(session); 691dc99b202SRuchika Gupta 692dc99b202SRuchika Gupta return PKCS11_CKR_OK; 693dc99b202SRuchika Gupta } 694783c1515SRuchika Gupta 695e3737878SRuchika Gupta enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client, 696783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params) 697783c1515SRuchika Gupta { 698783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 699783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE, 700783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 701783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE); 702783c1515SRuchika Gupta TEE_Param *ctrl = params; 703783c1515SRuchika Gupta TEE_Param *out = params + 2; 704783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 705783c1515SRuchika Gupta struct serialargs ctrlargs = { }; 706783c1515SRuchika Gupta struct pkcs11_session *session = NULL; 707783c1515SRuchika Gupta struct pkcs11_object_head *template = NULL; 708783c1515SRuchika Gupta struct pkcs11_object *obj = NULL; 709783c1515SRuchika Gupta uint32_t object_handle = 0; 710783c1515SRuchika Gupta char *cur = NULL; 711783c1515SRuchika Gupta size_t len = 0; 712783c1515SRuchika Gupta char *end = NULL; 713783c1515SRuchika Gupta bool attr_sensitive = 0; 714783c1515SRuchika Gupta bool attr_type_invalid = 0; 715783c1515SRuchika Gupta bool buffer_too_small = 0; 716783c1515SRuchika Gupta 717783c1515SRuchika Gupta if (!client || ptypes != exp_pt) 718783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 719783c1515SRuchika Gupta 720783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 721783c1515SRuchika Gupta 722783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 723783c1515SRuchika Gupta if (rc) 724783c1515SRuchika Gupta return rc; 725783c1515SRuchika Gupta 726783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 727783c1515SRuchika Gupta if (rc) 728783c1515SRuchika Gupta return rc; 729783c1515SRuchika Gupta 730783c1515SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 731783c1515SRuchika Gupta if (rc) 732783c1515SRuchika Gupta return rc; 733783c1515SRuchika Gupta 734783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 735783c1515SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 736783c1515SRuchika Gupta goto out; 737783c1515SRuchika Gupta } 738783c1515SRuchika Gupta 739783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 740783c1515SRuchika Gupta if (!obj) { 741783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 742783c1515SRuchika Gupta goto out; 743783c1515SRuchika Gupta } 744783c1515SRuchika Gupta 745783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 746783c1515SRuchika Gupta if (rc) { 747783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 748783c1515SRuchika Gupta goto out; 749783c1515SRuchika Gupta } 750783c1515SRuchika Gupta 751783c1515SRuchika Gupta /* Iterate over attributes and set their values */ 752783c1515SRuchika Gupta /* 753783c1515SRuchika Gupta * 1. If the specified attribute (i.e., the attribute specified by the 754783c1515SRuchika Gupta * type field) for the object cannot be revealed because the object is 755783c1515SRuchika Gupta * sensitive or unextractable, then the ulValueLen field in that triple 756783c1515SRuchika Gupta * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION. 757783c1515SRuchika Gupta * 758783c1515SRuchika Gupta * 2. Otherwise, if the specified value for the object is invalid (the 759783c1515SRuchika Gupta * object does not possess such an attribute), then the ulValueLen field 760783c1515SRuchika Gupta * in that triple is modified to hold the value 761783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION. 762783c1515SRuchika Gupta * 763783c1515SRuchika Gupta * 3. Otherwise, if the pValue field has the value NULL_PTR, then the 764783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the 765783c1515SRuchika Gupta * specified attribute for the object. 766783c1515SRuchika Gupta * 767783c1515SRuchika Gupta * 4. Otherwise, if the length specified in ulValueLen is large enough 768783c1515SRuchika Gupta * to hold the value of the specified attribute for the object, then 769783c1515SRuchika Gupta * that attribute is copied into the buffer located at pValue, and the 770783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the 771783c1515SRuchika Gupta * attribute. 772783c1515SRuchika Gupta * 773783c1515SRuchika Gupta * 5. Otherwise, the ulValueLen field is modified to hold the value 774783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION. 775783c1515SRuchika Gupta */ 776783c1515SRuchika Gupta cur = (char *)template + sizeof(struct pkcs11_object_head); 777783c1515SRuchika Gupta end = cur + template->attrs_size; 778783c1515SRuchika Gupta 779783c1515SRuchika Gupta for (; cur < end; cur += len) { 780783c1515SRuchika Gupta struct pkcs11_attribute_head *cli_ref = (void *)cur; 78118cbc7a2SVesa Jääskeläinen struct pkcs11_attribute_head cli_head = { }; 78218cbc7a2SVesa Jääskeläinen void *data_ptr = NULL; 783783c1515SRuchika Gupta 78418cbc7a2SVesa Jääskeläinen /* Make copy of header so that is aligned properly. */ 78518cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_head, cli_ref, sizeof(cli_head)); 78618cbc7a2SVesa Jääskeläinen 78718cbc7a2SVesa Jääskeläinen len = sizeof(*cli_ref) + cli_head.size; 788783c1515SRuchika Gupta 789783c1515SRuchika Gupta /* Check 1. */ 79018cbc7a2SVesa Jääskeläinen if (!attribute_is_exportable(&cli_head, obj)) { 79118cbc7a2SVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; 79218cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size, 79318cbc7a2SVesa Jääskeläinen sizeof(cli_head.size)); 794783c1515SRuchika Gupta attr_sensitive = 1; 795783c1515SRuchika Gupta continue; 796783c1515SRuchika Gupta } 797783c1515SRuchika Gupta 79818cbc7a2SVesa Jääskeläinen /* Get real data pointer from template data */ 799f3178382SVesa Jääskeläinen data_ptr = cli_head.size ? cli_ref->data : NULL; 80018cbc7a2SVesa Jääskeläinen 801783c1515SRuchika Gupta /* 802783c1515SRuchika Gupta * We assume that if size is 0, pValue was NULL, so we return 803783c1515SRuchika Gupta * the size of the required buffer for it (3., 4.) 804783c1515SRuchika Gupta */ 805f3178382SVesa Jääskeläinen rc = get_attribute(obj->attributes, cli_head.id, data_ptr, 80618cbc7a2SVesa Jääskeläinen &cli_head.size); 807783c1515SRuchika Gupta /* Check 2. */ 808783c1515SRuchika Gupta switch (rc) { 809783c1515SRuchika Gupta case PKCS11_CKR_OK: 810783c1515SRuchika Gupta break; 811783c1515SRuchika Gupta case PKCS11_RV_NOT_FOUND: 81218cbc7a2SVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; 813783c1515SRuchika Gupta attr_type_invalid = 1; 814783c1515SRuchika Gupta break; 815783c1515SRuchika Gupta case PKCS11_CKR_BUFFER_TOO_SMALL: 816f3178382SVesa Jääskeläinen if (data_ptr) 817783c1515SRuchika Gupta buffer_too_small = 1; 818783c1515SRuchika Gupta break; 819783c1515SRuchika Gupta default: 820783c1515SRuchika Gupta rc = PKCS11_CKR_GENERAL_ERROR; 821783c1515SRuchika Gupta goto out; 822783c1515SRuchika Gupta } 82318cbc7a2SVesa Jääskeläinen 82418cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size, 82518cbc7a2SVesa Jääskeläinen sizeof(cli_head.size)); 826783c1515SRuchika Gupta } 827783c1515SRuchika Gupta 828783c1515SRuchika Gupta /* 829783c1515SRuchika Gupta * If case 1 applies to any of the requested attributes, then the call 830783c1515SRuchika Gupta * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to 831783c1515SRuchika Gupta * any of the requested attributes, then the call should return the 832783c1515SRuchika Gupta * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the 833783c1515SRuchika Gupta * requested attributes, then the call should return the value 834783c1515SRuchika Gupta * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes 835783c1515SRuchika Gupta * is applicable, Cryptoki may return any of them. Only if none of them 836783c1515SRuchika Gupta * applies to any of the requested attributes will CKR_OK be returned. 837783c1515SRuchika Gupta */ 838783c1515SRuchika Gupta 839783c1515SRuchika Gupta rc = PKCS11_CKR_OK; 840783c1515SRuchika Gupta if (attr_sensitive) 841783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE; 842783c1515SRuchika Gupta if (attr_type_invalid) 843783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; 844783c1515SRuchika Gupta if (buffer_too_small) 845783c1515SRuchika Gupta rc = PKCS11_CKR_BUFFER_TOO_SMALL; 846783c1515SRuchika Gupta 847783c1515SRuchika Gupta /* Move updated template to out buffer */ 848783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, template, out->memref.size); 849783c1515SRuchika Gupta 850783c1515SRuchika Gupta DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32, 851783c1515SRuchika Gupta session->handle, object_handle); 852783c1515SRuchika Gupta 853783c1515SRuchika Gupta out: 854783c1515SRuchika Gupta TEE_Free(template); 855783c1515SRuchika Gupta 856783c1515SRuchika Gupta return rc; 857783c1515SRuchika Gupta } 858783c1515SRuchika Gupta 859e3737878SRuchika Gupta enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client, 860783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params) 861783c1515SRuchika Gupta { 862783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 863783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE, 864783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 865783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE); 866783c1515SRuchika Gupta TEE_Param *ctrl = params; 867783c1515SRuchika Gupta TEE_Param *out = params + 2; 868783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 869783c1515SRuchika Gupta struct serialargs ctrlargs = { }; 870783c1515SRuchika Gupta struct pkcs11_session *session = NULL; 871783c1515SRuchika Gupta uint32_t object_handle = 0; 872783c1515SRuchika Gupta struct pkcs11_object *obj = NULL; 873783c1515SRuchika Gupta uint32_t obj_size = 0; 874783c1515SRuchika Gupta 875783c1515SRuchika Gupta if (!client || ptypes != exp_pt) 876783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 877783c1515SRuchika Gupta 878783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 879783c1515SRuchika Gupta 880783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 881783c1515SRuchika Gupta if (rc) 882783c1515SRuchika Gupta return rc; 883783c1515SRuchika Gupta 884783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 885783c1515SRuchika Gupta if (rc) 886783c1515SRuchika Gupta return rc; 887783c1515SRuchika Gupta 888783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 889783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 890783c1515SRuchika Gupta 891783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 892783c1515SRuchika Gupta if (!obj) 893783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID; 894783c1515SRuchika Gupta 895783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 896783c1515SRuchika Gupta if (rc) 897783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID; 898783c1515SRuchika Gupta 899783c1515SRuchika Gupta if (out->memref.size != sizeof(uint32_t)) 900783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 901783c1515SRuchika Gupta 902783c1515SRuchika Gupta obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size + 903783c1515SRuchika Gupta sizeof(struct obj_attrs); 904783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size)); 905783c1515SRuchika Gupta 906783c1515SRuchika Gupta return PKCS11_CKR_OK; 907783c1515SRuchika Gupta } 9082d25a9bcSRuchika Gupta 9092d25a9bcSRuchika Gupta enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, 9102d25a9bcSRuchika Gupta uint32_t ptypes, TEE_Param *params) 9112d25a9bcSRuchika Gupta { 9122d25a9bcSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 9132d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE, 9142d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE, 9152d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE); 9162d25a9bcSRuchika Gupta TEE_Param *ctrl = params; 9172d25a9bcSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 9182d25a9bcSRuchika Gupta struct serialargs ctrlargs = { }; 9192d25a9bcSRuchika Gupta struct pkcs11_session *session = NULL; 9202d25a9bcSRuchika Gupta struct pkcs11_object_head *template = NULL; 9212d25a9bcSRuchika Gupta size_t template_size = 0; 9222d25a9bcSRuchika Gupta struct pkcs11_object *obj = NULL; 9232d25a9bcSRuchika Gupta struct obj_attrs *head = NULL; 9242d25a9bcSRuchika Gupta uint32_t object_handle = 0; 9252d25a9bcSRuchika Gupta enum processing_func function = PKCS11_FUNCTION_MODIFY; 9262d25a9bcSRuchika Gupta 9272d25a9bcSRuchika Gupta if (!client || ptypes != exp_pt) 9282d25a9bcSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 9292d25a9bcSRuchika Gupta 9302d25a9bcSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 9312d25a9bcSRuchika Gupta 9322d25a9bcSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 9332d25a9bcSRuchika Gupta if (rc) 9342d25a9bcSRuchika Gupta return rc; 9352d25a9bcSRuchika Gupta 9362d25a9bcSRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 9372d25a9bcSRuchika Gupta if (rc) 9382d25a9bcSRuchika Gupta return rc; 9392d25a9bcSRuchika Gupta 9402d25a9bcSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 9412d25a9bcSRuchika Gupta if (rc) 9422d25a9bcSRuchika Gupta return rc; 9432d25a9bcSRuchika Gupta 9442d25a9bcSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 9452d25a9bcSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 9462d25a9bcSRuchika Gupta goto out; 9472d25a9bcSRuchika Gupta } 9482d25a9bcSRuchika Gupta 9492d25a9bcSRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 9502d25a9bcSRuchika Gupta if (!obj) { 9512d25a9bcSRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 9522d25a9bcSRuchika Gupta goto out; 9532d25a9bcSRuchika Gupta } 9542d25a9bcSRuchika Gupta 9552d25a9bcSRuchika Gupta /* Only session objects can be modified during a read-only session */ 9562d25a9bcSRuchika Gupta if (object_is_token(obj->attributes) && 9572d25a9bcSRuchika Gupta !pkcs11_session_is_read_write(session)) { 9582d25a9bcSRuchika Gupta DMSG("Can't modify persistent object in a RO session"); 9592d25a9bcSRuchika Gupta rc = PKCS11_CKR_SESSION_READ_ONLY; 9602d25a9bcSRuchika Gupta goto out; 9612d25a9bcSRuchika Gupta } 9622d25a9bcSRuchika Gupta 9632d25a9bcSRuchika Gupta /* 9642d25a9bcSRuchika Gupta * Only public objects can be modified unless normal user is logged in 9652d25a9bcSRuchika Gupta */ 9662d25a9bcSRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 9672d25a9bcSRuchika Gupta if (rc) { 9682d25a9bcSRuchika Gupta rc = PKCS11_CKR_USER_NOT_LOGGED_IN; 9692d25a9bcSRuchika Gupta goto out; 9702d25a9bcSRuchika Gupta } 9712d25a9bcSRuchika Gupta 9722d25a9bcSRuchika Gupta /* Objects with PKCS11_CKA_MODIFIABLE as false aren't modifiable */ 9732d25a9bcSRuchika Gupta if (!object_is_modifiable(obj->attributes)) { 9742d25a9bcSRuchika Gupta rc = PKCS11_CKR_ACTION_PROHIBITED; 9752d25a9bcSRuchika Gupta goto out; 9762d25a9bcSRuchika Gupta } 9772d25a9bcSRuchika Gupta 9782d25a9bcSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 9792d25a9bcSRuchika Gupta 9802d25a9bcSRuchika Gupta /* 9812d25a9bcSRuchika Gupta * Prepare a clean initial state (@head) for the template. Helps in 9822d25a9bcSRuchika Gupta * removing any duplicates or inconsistent values from the 9832d25a9bcSRuchika Gupta * template. 9842d25a9bcSRuchika Gupta */ 9852d25a9bcSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 9862d25a9bcSRuchika Gupta NULL, function, 9872d25a9bcSRuchika Gupta PKCS11_CKM_UNDEFINED_ID, 9882d25a9bcSRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 9892d25a9bcSRuchika Gupta if (rc) 9902d25a9bcSRuchika Gupta goto out; 9912d25a9bcSRuchika Gupta 9922d25a9bcSRuchika Gupta /* Check the attributes in @head to see if they are modifiable */ 9932d25a9bcSRuchika Gupta rc = check_attrs_against_modification(session, head, obj, function); 9942d25a9bcSRuchika Gupta if (rc) 9952d25a9bcSRuchika Gupta goto out; 9962d25a9bcSRuchika Gupta 9972d25a9bcSRuchika Gupta /* 9982d25a9bcSRuchika Gupta * All checks complete. The attributes in @head have been checked and 9992d25a9bcSRuchika Gupta * can now be used to set/modify the object attributes. 10002d25a9bcSRuchika Gupta */ 10012d25a9bcSRuchika Gupta rc = modify_attributes_list(&obj->attributes, head); 10022d25a9bcSRuchika Gupta if (rc) 10032d25a9bcSRuchika Gupta goto out; 10042d25a9bcSRuchika Gupta 1005*402d884aSRuchika Gupta if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 1006*402d884aSRuchika Gupta rc = update_persistent_object_attributes(obj); 1007*402d884aSRuchika Gupta if (rc) 1008*402d884aSRuchika Gupta goto out; 1009*402d884aSRuchika Gupta } 1010*402d884aSRuchika Gupta 10112d25a9bcSRuchika Gupta DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32, 10122d25a9bcSRuchika Gupta session->handle, object_handle); 10132d25a9bcSRuchika Gupta 10142d25a9bcSRuchika Gupta out: 10152d25a9bcSRuchika Gupta TEE_Free(head); 10162d25a9bcSRuchika Gupta TEE_Free(template); 10172d25a9bcSRuchika Gupta return rc; 10182d25a9bcSRuchika Gupta } 1019bc09507cSRuchika Gupta 1020bc09507cSRuchika Gupta enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes, 1021bc09507cSRuchika Gupta TEE_Param *params) 1022bc09507cSRuchika Gupta { 1023bc09507cSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1024bc09507cSRuchika Gupta TEE_PARAM_TYPE_NONE, 1025bc09507cSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 1026bc09507cSRuchika Gupta TEE_PARAM_TYPE_NONE); 1027bc09507cSRuchika Gupta TEE_Param *ctrl = params; 1028bc09507cSRuchika Gupta TEE_Param *out = params + 2; 1029bc09507cSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 1030bc09507cSRuchika Gupta struct serialargs ctrlargs = { }; 1031bc09507cSRuchika Gupta struct pkcs11_session *session = NULL; 1032bc09507cSRuchika Gupta struct pkcs11_object_head *template = NULL; 1033bc09507cSRuchika Gupta struct obj_attrs *head = NULL; 1034bc09507cSRuchika Gupta struct obj_attrs *head_new = NULL; 1035bc09507cSRuchika Gupta size_t template_size = 0; 1036bc09507cSRuchika Gupta struct pkcs11_object *obj = NULL; 1037bc09507cSRuchika Gupta uint32_t object_handle = 0; 1038bc09507cSRuchika Gupta uint32_t obj_handle = 0; 1039bc09507cSRuchika Gupta enum processing_func function = PKCS11_FUNCTION_COPY; 1040bc09507cSRuchika Gupta enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; 1041bc09507cSRuchika Gupta 1042bc09507cSRuchika Gupta if (!client || ptypes != exp_pt || 1043bc09507cSRuchika Gupta out->memref.size != sizeof(obj_handle)) 1044bc09507cSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 1045bc09507cSRuchika Gupta 1046bc09507cSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1047bc09507cSRuchika Gupta 1048bc09507cSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1049bc09507cSRuchika Gupta if (rc) 1050bc09507cSRuchika Gupta return rc; 1051bc09507cSRuchika Gupta 1052bc09507cSRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 1053bc09507cSRuchika Gupta if (rc) 1054bc09507cSRuchika Gupta return rc; 1055bc09507cSRuchika Gupta 1056bc09507cSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 1057bc09507cSRuchika Gupta if (rc) 1058bc09507cSRuchika Gupta return rc; 1059bc09507cSRuchika Gupta 1060bc09507cSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 1061bc09507cSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 1062bc09507cSRuchika Gupta goto out; 1063bc09507cSRuchika Gupta } 1064bc09507cSRuchika Gupta 1065bc09507cSRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 1066bc09507cSRuchika Gupta if (!obj) { 1067bc09507cSRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 1068bc09507cSRuchika Gupta goto out; 1069bc09507cSRuchika Gupta } 1070bc09507cSRuchika Gupta 1071bc09507cSRuchika Gupta /* Only session objects can be modified during a read-only session */ 1072bc09507cSRuchika Gupta if (object_is_token(obj->attributes) && 1073bc09507cSRuchika Gupta !pkcs11_session_is_read_write(session)) { 1074bc09507cSRuchika Gupta DMSG("Can't modify persistent object in a RO session"); 1075bc09507cSRuchika Gupta rc = PKCS11_CKR_SESSION_READ_ONLY; 1076bc09507cSRuchika Gupta goto out; 1077bc09507cSRuchika Gupta } 1078bc09507cSRuchika Gupta 1079bc09507cSRuchika Gupta /* 1080bc09507cSRuchika Gupta * Only public objects can be modified unless normal user is logged in 1081bc09507cSRuchika Gupta */ 1082bc09507cSRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 1083bc09507cSRuchika Gupta if (rc) { 1084bc09507cSRuchika Gupta rc = PKCS11_CKR_USER_NOT_LOGGED_IN; 1085bc09507cSRuchika Gupta goto out; 1086bc09507cSRuchika Gupta } 1087bc09507cSRuchika Gupta 1088bc09507cSRuchika Gupta /* Objects with PKCS11_CKA_COPYABLE as false can't be copied */ 1089bc09507cSRuchika Gupta if (!object_is_copyable(obj->attributes)) { 1090bc09507cSRuchika Gupta rc = PKCS11_CKR_ACTION_PROHIBITED; 1091bc09507cSRuchika Gupta goto out; 1092bc09507cSRuchika Gupta } 1093bc09507cSRuchika Gupta 1094bc09507cSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 1095bc09507cSRuchika Gupta 1096bc09507cSRuchika Gupta /* 1097bc09507cSRuchika Gupta * Prepare a clean initial state (@head) for the template. Helps in 1098bc09507cSRuchika Gupta * removing any duplicates or inconsistent values from the 1099bc09507cSRuchika Gupta * template. 1100bc09507cSRuchika Gupta */ 1101bc09507cSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 1102bc09507cSRuchika Gupta NULL, function, 1103bc09507cSRuchika Gupta PKCS11_CKM_UNDEFINED_ID, 1104bc09507cSRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 1105bc09507cSRuchika Gupta if (rc) 1106bc09507cSRuchika Gupta goto out; 1107bc09507cSRuchika Gupta 1108bc09507cSRuchika Gupta /* Check the attributes in @head to see if they are modifiable */ 1109bc09507cSRuchika Gupta rc = check_attrs_against_modification(session, head, obj, function); 1110bc09507cSRuchika Gupta if (rc) 1111bc09507cSRuchika Gupta goto out; 1112bc09507cSRuchika Gupta 1113bc09507cSRuchika Gupta class = get_class(obj->attributes); 1114bc09507cSRuchika Gupta 1115bc09507cSRuchika Gupta if (class == PKCS11_CKO_SECRET_KEY || 1116bc09507cSRuchika Gupta class == PKCS11_CKO_PRIVATE_KEY) { 1117bc09507cSRuchika Gupta /* 1118bc09507cSRuchika Gupta * If CKA_EXTRACTABLE attribute in passed template (@head) is 1119bc09507cSRuchika Gupta * modified to CKA_FALSE, CKA_NEVER_EXTRACTABLE should also 1120bc09507cSRuchika Gupta * change to CKA_FALSE in copied obj. So, add it to the 1121bc09507cSRuchika Gupta * passed template. 1122bc09507cSRuchika Gupta */ 1123bc09507cSRuchika Gupta uint8_t bbool = 0; 1124bc09507cSRuchika Gupta uint32_t size = sizeof(bbool); 1125bc09507cSRuchika Gupta 1126bc09507cSRuchika Gupta rc = get_attribute(head, PKCS11_CKA_EXTRACTABLE, &bbool, &size); 1127bc09507cSRuchika Gupta if (!rc && !bbool) { 1128bc09507cSRuchika Gupta rc = add_attribute(&head, PKCS11_CKA_NEVER_EXTRACTABLE, 1129bc09507cSRuchika Gupta &bbool, sizeof(uint8_t)); 1130bc09507cSRuchika Gupta if (rc) 1131bc09507cSRuchika Gupta goto out; 1132bc09507cSRuchika Gupta } 1133bc09507cSRuchika Gupta rc = PKCS11_CKR_OK; 1134bc09507cSRuchika Gupta } 1135bc09507cSRuchika Gupta 1136bc09507cSRuchika Gupta /* 1137bc09507cSRuchika Gupta * All checks have passed. Create a copy of the serialized buffer which 1138bc09507cSRuchika Gupta * holds the object attributes in @head_new for the new object 1139bc09507cSRuchika Gupta */ 1140bc09507cSRuchika Gupta template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size; 1141bc09507cSRuchika Gupta head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO); 1142bc09507cSRuchika Gupta if (!head_new) { 1143bc09507cSRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 1144bc09507cSRuchika Gupta goto out; 1145bc09507cSRuchika Gupta } 1146bc09507cSRuchika Gupta 1147bc09507cSRuchika Gupta TEE_MemMove(head_new, obj->attributes, template_size); 1148bc09507cSRuchika Gupta 1149bc09507cSRuchika Gupta /* 1150bc09507cSRuchika Gupta * Modify the copied attribute @head_new based on the template @head 1151bc09507cSRuchika Gupta * given by the callee 1152bc09507cSRuchika Gupta */ 1153bc09507cSRuchika Gupta rc = modify_attributes_list(&head_new, head); 1154bc09507cSRuchika Gupta if (rc) 1155bc09507cSRuchika Gupta goto out; 1156bc09507cSRuchika Gupta 1157bc09507cSRuchika Gupta /* 1158bc09507cSRuchika Gupta * At this stage the object is almost created: all its attributes are 1159bc09507cSRuchika Gupta * referenced in @head_new, including the key value and are assumed 1160bc09507cSRuchika Gupta * reliable. Now need to register it and get a handle for it. 1161bc09507cSRuchika Gupta */ 1162bc09507cSRuchika Gupta rc = create_object(session, head_new, &obj_handle); 1163bc09507cSRuchika Gupta if (rc) 1164bc09507cSRuchika Gupta goto out; 1165bc09507cSRuchika Gupta 1166bc09507cSRuchika Gupta /* 1167bc09507cSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object 1168e3737878SRuchika Gupta * instance) owns the serialized buffer that holds the object 1169bc09507cSRuchika Gupta * attributes. We clear reference in head to NULL as the serializer 1170bc09507cSRuchika Gupta * object is now referred from obj_handle. This allows smooth pass 1171bc09507cSRuchika Gupta * through free at function exit. 1172bc09507cSRuchika Gupta */ 1173bc09507cSRuchika Gupta head_new = NULL; 1174bc09507cSRuchika Gupta 1175bc09507cSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 1176bc09507cSRuchika Gupta out->memref.size = sizeof(obj_handle); 1177bc09507cSRuchika Gupta 1178bc09507cSRuchika Gupta DMSG("PKCS11 session %"PRIu32": copy object %#"PRIx32, 1179bc09507cSRuchika Gupta session->handle, obj_handle); 1180bc09507cSRuchika Gupta 1181bc09507cSRuchika Gupta out: 1182bc09507cSRuchika Gupta TEE_Free(head_new); 1183bc09507cSRuchika Gupta TEE_Free(head); 1184bc09507cSRuchika Gupta TEE_Free(template); 1185bc09507cSRuchika Gupta return rc; 1186bc09507cSRuchika Gupta } 1187