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 2102dbcc7eSEtienne Carriere /* 2202dbcc7eSEtienne Carriere * Temporary list used to register allocated struct pkcs11_object instances 2302dbcc7eSEtienne Carriere * so that destroy_object() can unconditionally remove the object from its 2402dbcc7eSEtienne Carriere * list, being from an object destruction request or because object creation 2502dbcc7eSEtienne Carriere * failed before being completed. Objects are moved to their target list at 2602dbcc7eSEtienne Carriere * creation completion. 2702dbcc7eSEtienne Carriere */ 2802dbcc7eSEtienne Carriere LIST_HEAD(temp_obj_list, pkcs11_object) temporary_object_list = 2902dbcc7eSEtienne Carriere LIST_HEAD_INITIALIZER(temp_obj_list); 3002dbcc7eSEtienne Carriere 31bc555ee0SVesa Jääskeläinen static struct ck_token *get_session_token(void *session); 32bc555ee0SVesa Jääskeläinen 33b56b3d07SJens Wiklander struct pkcs11_object *pkcs11_handle2object(uint32_t handle, 34b56b3d07SJens Wiklander struct pkcs11_session *session) 35b56b3d07SJens Wiklander { 36bc555ee0SVesa Jääskeläinen struct pkcs11_object *object = NULL; 37bc555ee0SVesa Jääskeläinen 38bc555ee0SVesa Jääskeläinen object = handle_lookup(get_object_handle_db(session), handle); 39bc555ee0SVesa Jääskeläinen if (!object) 40bc555ee0SVesa Jääskeläinen return NULL; 41bc555ee0SVesa Jääskeläinen 42bc555ee0SVesa Jääskeläinen /* 43bc555ee0SVesa Jääskeläinen * If object is session only then no extra checks are needed as session 44bc555ee0SVesa Jääskeläinen * objects has flat access control space 45bc555ee0SVesa Jääskeläinen */ 46bc555ee0SVesa Jääskeläinen if (!object->token) 47bc555ee0SVesa Jääskeläinen return object; 48bc555ee0SVesa Jääskeläinen 49bc555ee0SVesa Jääskeläinen /* 50bc555ee0SVesa Jääskeläinen * Only allow access to token object if session is associated with 51bc555ee0SVesa Jääskeläinen * the token 52bc555ee0SVesa Jääskeläinen */ 53bc555ee0SVesa Jääskeläinen if (object->token != get_session_token(session)) 54bc555ee0SVesa Jääskeläinen return NULL; 55bc555ee0SVesa Jääskeläinen 56bc555ee0SVesa Jääskeläinen return object; 57b56b3d07SJens Wiklander } 58b56b3d07SJens Wiklander 59b56b3d07SJens Wiklander uint32_t pkcs11_object2handle(struct pkcs11_object *obj, 60b56b3d07SJens Wiklander struct pkcs11_session *session) 61b56b3d07SJens Wiklander { 62bc555ee0SVesa Jääskeläinen return handle_lookup_handle(get_object_handle_db(session), obj); 63b56b3d07SJens Wiklander } 64b56b3d07SJens Wiklander 65b56b3d07SJens Wiklander /* Currently handle pkcs11 sessions and tokens */ 66b56b3d07SJens Wiklander 67b56b3d07SJens Wiklander static struct object_list *get_session_objects(void *session) 68b56b3d07SJens Wiklander { 69b56b3d07SJens Wiklander /* Currently supporting only pkcs11 session */ 70b56b3d07SJens Wiklander struct pkcs11_session *ck_session = session; 71b56b3d07SJens Wiklander 72b56b3d07SJens Wiklander return pkcs11_get_session_objects(ck_session); 73b56b3d07SJens Wiklander } 74b56b3d07SJens Wiklander 75334316feSJens Wiklander static struct ck_token *get_session_token(void *session) 76334316feSJens Wiklander { 77334316feSJens Wiklander struct pkcs11_session *ck_session = session; 78334316feSJens Wiklander 79334316feSJens Wiklander return pkcs11_session2token(ck_session); 80334316feSJens Wiklander } 81334316feSJens Wiklander 82b56b3d07SJens Wiklander /* Release resources of a non-persistent object */ 83b56b3d07SJens Wiklander static void cleanup_volatile_obj_ref(struct pkcs11_object *obj) 84b56b3d07SJens Wiklander { 85b56b3d07SJens Wiklander if (!obj) 86b56b3d07SJens Wiklander return; 87b56b3d07SJens Wiklander 8876948876SMengchi Cheng LIST_REMOVE(obj, link); 8976948876SMengchi Cheng 90b56b3d07SJens Wiklander if (obj->key_handle != TEE_HANDLE_NULL) 91b56b3d07SJens Wiklander TEE_FreeTransientObject(obj->key_handle); 92b56b3d07SJens Wiklander 93b56b3d07SJens Wiklander if (obj->attribs_hdl != TEE_HANDLE_NULL) 94b56b3d07SJens Wiklander TEE_CloseObject(obj->attribs_hdl); 95b56b3d07SJens Wiklander 96b56b3d07SJens Wiklander TEE_Free(obj->attributes); 97b56b3d07SJens Wiklander TEE_Free(obj->uuid); 98b56b3d07SJens Wiklander TEE_Free(obj); 99b56b3d07SJens Wiklander } 100b56b3d07SJens Wiklander 101b56b3d07SJens Wiklander /* Release resources of a persistent object including volatile resources */ 1027f12c782SRobin van der Gracht void cleanup_persistent_object(struct pkcs11_object *obj, 103334316feSJens Wiklander struct ck_token *token) 104b56b3d07SJens Wiklander { 105334316feSJens Wiklander TEE_Result res = TEE_SUCCESS; 106334316feSJens Wiklander 107334316feSJens Wiklander if (!obj) 108334316feSJens Wiklander return; 109334316feSJens Wiklander 110334316feSJens Wiklander /* Open handle with write properties to destroy the object */ 111334316feSJens Wiklander if (obj->attribs_hdl != TEE_HANDLE_NULL) 112334316feSJens Wiklander TEE_CloseObject(obj->attribs_hdl); 113334316feSJens Wiklander 114334316feSJens Wiklander res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, 115334316feSJens Wiklander obj->uuid, sizeof(TEE_UUID), 116334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE_META, 117334316feSJens Wiklander &obj->attribs_hdl); 118334316feSJens Wiklander if (!res) 119334316feSJens Wiklander TEE_CloseAndDeletePersistentObject1(obj->attribs_hdl); 120334316feSJens Wiklander 121334316feSJens Wiklander obj->attribs_hdl = TEE_HANDLE_NULL; 122334316feSJens Wiklander destroy_object_uuid(token, obj); 123334316feSJens Wiklander 124334316feSJens Wiklander cleanup_volatile_obj_ref(obj); 125b56b3d07SJens Wiklander } 126b56b3d07SJens Wiklander 127b56b3d07SJens Wiklander /* 128b56b3d07SJens Wiklander * destroy_object - destroy an PKCS11 TA object 129b56b3d07SJens Wiklander * 130b56b3d07SJens Wiklander * @session - session requesting object destruction 131b56b3d07SJens Wiklander * @obj - reference to the PKCS11 TA object 132b56b3d07SJens Wiklander * @session_only - true if only session object shall be destroyed 133b56b3d07SJens Wiklander */ 134b56b3d07SJens Wiklander void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj, 135b56b3d07SJens Wiklander bool session_only) 136b56b3d07SJens Wiklander { 137b56b3d07SJens Wiklander #ifdef DEBUG 138b56b3d07SJens Wiklander trace_attributes("[destroy]", obj->attributes); 139b56b3d07SJens Wiklander if (obj->uuid) 140b56b3d07SJens Wiklander MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid); 141b56b3d07SJens Wiklander #endif 142b56b3d07SJens Wiklander 143b56b3d07SJens Wiklander if (session_only) { 144b56b3d07SJens Wiklander /* Destroy object due to session closure */ 145bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session), 146b56b3d07SJens Wiklander pkcs11_object2handle(obj, session)); 147b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 148b56b3d07SJens Wiklander 149b56b3d07SJens Wiklander return; 150b56b3d07SJens Wiklander } 151b56b3d07SJens Wiklander 152b56b3d07SJens Wiklander /* Destroy target object (persistent or not) */ 153b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 154334316feSJens Wiklander assert(obj->uuid); 155334316feSJens Wiklander /* Try twice otherwise panic! */ 156334316feSJens Wiklander if (unregister_persistent_object(session->token, obj->uuid) && 157334316feSJens Wiklander unregister_persistent_object(session->token, obj->uuid)) 158b56b3d07SJens Wiklander TEE_Panic(0); 159334316feSJens Wiklander 160bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session), 161334316feSJens Wiklander pkcs11_object2handle(obj, session)); 162334316feSJens Wiklander cleanup_persistent_object(obj, session->token); 163bb5d1825SEtienne Carriere 164bb5d1825SEtienne Carriere token_invalidate_object_handles(obj); 165b56b3d07SJens Wiklander } else { 166bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session), 167b56b3d07SJens Wiklander pkcs11_object2handle(obj, session)); 168b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 169b56b3d07SJens Wiklander } 170b56b3d07SJens Wiklander } 171b56b3d07SJens Wiklander 172bc555ee0SVesa Jääskeläinen static struct pkcs11_object *create_obj_instance(struct obj_attrs *head, 173bc555ee0SVesa Jääskeläinen struct ck_token *token) 174b56b3d07SJens Wiklander { 175b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL; 176b56b3d07SJens Wiklander 177b56b3d07SJens Wiklander obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO); 178b56b3d07SJens Wiklander if (!obj) 179b56b3d07SJens Wiklander return NULL; 180b56b3d07SJens Wiklander 181b56b3d07SJens Wiklander obj->key_handle = TEE_HANDLE_NULL; 182b56b3d07SJens Wiklander obj->attribs_hdl = TEE_HANDLE_NULL; 183b56b3d07SJens Wiklander obj->attributes = head; 184bc555ee0SVesa Jääskeläinen obj->token = token; 185b56b3d07SJens Wiklander 186b56b3d07SJens Wiklander return obj; 187b56b3d07SJens Wiklander } 188b56b3d07SJens Wiklander 189334316feSJens Wiklander struct pkcs11_object *create_token_object(struct obj_attrs *head, 190bc555ee0SVesa Jääskeläinen TEE_UUID *uuid, 191bc555ee0SVesa Jääskeläinen struct ck_token *token) 192334316feSJens Wiklander { 193bc555ee0SVesa Jääskeläinen struct pkcs11_object *obj = create_obj_instance(head, token); 194334316feSJens Wiklander 195334316feSJens Wiklander if (obj) 196334316feSJens Wiklander obj->uuid = uuid; 197334316feSJens Wiklander 198334316feSJens Wiklander return obj; 199334316feSJens Wiklander } 200334316feSJens Wiklander 201b56b3d07SJens Wiklander /* 202b56b3d07SJens Wiklander * create_object - create an PKCS11 TA object from its attributes and value 203b56b3d07SJens Wiklander * 204b56b3d07SJens Wiklander * @sess - session requesting object creation 205b56b3d07SJens Wiklander * @head - reference to serialized attributes 206b56b3d07SJens Wiklander * @out_handle - generated handle for the created object 207b56b3d07SJens Wiklander */ 208b56b3d07SJens Wiklander enum pkcs11_rc create_object(void *sess, struct obj_attrs *head, 209b56b3d07SJens Wiklander uint32_t *out_handle) 210b56b3d07SJens Wiklander { 211fde67b24SEtienne Carriere enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 212b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL; 213b56b3d07SJens Wiklander struct pkcs11_session *session = (struct pkcs11_session *)sess; 214b56b3d07SJens Wiklander uint32_t obj_handle = 0; 215b56b3d07SJens Wiklander 216b56b3d07SJens Wiklander #ifdef DEBUG 217b56b3d07SJens Wiklander trace_attributes("[create]", head); 218b56b3d07SJens Wiklander #endif 219b56b3d07SJens Wiklander 220b56b3d07SJens Wiklander /* 221b56b3d07SJens Wiklander * We do not check the key attributes. At this point, key attributes 222b56b3d07SJens Wiklander * are expected consistent and reliable. 223b56b3d07SJens Wiklander */ 224b56b3d07SJens Wiklander 225bc555ee0SVesa Jääskeläinen obj = create_obj_instance(head, NULL); 226b56b3d07SJens Wiklander if (!obj) 227b56b3d07SJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 228b56b3d07SJens Wiklander 22902dbcc7eSEtienne Carriere LIST_INSERT_HEAD(&temporary_object_list, obj, link); 23002dbcc7eSEtienne Carriere 231b56b3d07SJens Wiklander /* Create a handle for the object in the session database */ 232bc555ee0SVesa Jääskeläinen obj_handle = handle_get(get_object_handle_db(session), obj); 233b56b3d07SJens Wiklander if (!obj_handle) { 234b56b3d07SJens Wiklander rc = PKCS11_CKR_DEVICE_MEMORY; 235b56b3d07SJens Wiklander goto err; 236b56b3d07SJens Wiklander } 237b56b3d07SJens Wiklander 238b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 239334316feSJens Wiklander TEE_Result res = TEE_SUCCESS; 240334316feSJens Wiklander 241334316feSJens Wiklander /* 242334316feSJens Wiklander * Get an ID for the persistent object 243334316feSJens Wiklander * Create the file 244334316feSJens Wiklander * Register the object in the persistent database 245334316feSJens Wiklander * (move the full sequence to persisent_db.c?) 246334316feSJens Wiklander */ 247334316feSJens Wiklander size_t size = sizeof(struct obj_attrs) + 248334316feSJens Wiklander obj->attributes->attrs_size; 249334316feSJens Wiklander uint32_t tee_obj_flags = TEE_DATA_FLAG_ACCESS_READ | 250334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE | 251334316feSJens Wiklander TEE_DATA_FLAG_ACCESS_WRITE_META; 252334316feSJens Wiklander 253334316feSJens Wiklander rc = create_object_uuid(get_session_token(session), obj); 254334316feSJens Wiklander if (rc) 255334316feSJens Wiklander goto err; 256334316feSJens Wiklander 257334316feSJens Wiklander res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, 258334316feSJens Wiklander obj->uuid, sizeof(TEE_UUID), 259334316feSJens Wiklander tee_obj_flags, 260334316feSJens Wiklander TEE_HANDLE_NULL, 261334316feSJens Wiklander obj->attributes, size, 262334316feSJens Wiklander &obj->attribs_hdl); 263334316feSJens Wiklander if (res) { 264334316feSJens Wiklander rc = tee2pkcs_error(res); 265334316feSJens Wiklander goto err; 266334316feSJens Wiklander } 267334316feSJens Wiklander 268334316feSJens Wiklander rc = register_persistent_object(get_session_token(session), 269334316feSJens Wiklander obj->uuid); 270334316feSJens Wiklander if (rc) 271334316feSJens Wiklander goto err; 272334316feSJens Wiklander 2730fafe5c7SVesa Jääskeläinen TEE_CloseObject(obj->attribs_hdl); 2740fafe5c7SVesa Jääskeläinen obj->attribs_hdl = TEE_HANDLE_NULL; 2750fafe5c7SVesa Jääskeläinen 27602dbcc7eSEtienne Carriere /* Move object from temporary list to target token list */ 27702dbcc7eSEtienne Carriere LIST_REMOVE(obj, link); 278334316feSJens Wiklander LIST_INSERT_HEAD(&session->token->object_list, obj, link); 279b56b3d07SJens Wiklander } else { 28002dbcc7eSEtienne Carriere /* Move object from temporary list to target session list */ 28102dbcc7eSEtienne Carriere LIST_REMOVE(obj, link); 282b56b3d07SJens Wiklander LIST_INSERT_HEAD(get_session_objects(session), obj, link); 283b56b3d07SJens Wiklander } 284b56b3d07SJens Wiklander 285b56b3d07SJens Wiklander *out_handle = obj_handle; 286b56b3d07SJens Wiklander 287b56b3d07SJens Wiklander return PKCS11_CKR_OK; 288b56b3d07SJens Wiklander err: 289b56b3d07SJens Wiklander /* make sure that supplied "head" isn't freed */ 290b56b3d07SJens Wiklander obj->attributes = NULL; 291bc555ee0SVesa Jääskeläinen handle_put(get_object_handle_db(session), obj_handle); 292b56b3d07SJens Wiklander if (get_bool(head, PKCS11_CKA_TOKEN)) 293b56b3d07SJens Wiklander cleanup_persistent_object(obj, session->token); 294b56b3d07SJens Wiklander else 295b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 296b56b3d07SJens Wiklander 297b56b3d07SJens Wiklander return rc; 298b56b3d07SJens Wiklander } 299b56b3d07SJens Wiklander 300b56b3d07SJens Wiklander enum pkcs11_rc entry_create_object(struct pkcs11_client *client, 301b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 302b56b3d07SJens Wiklander { 303b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 304b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 305b56b3d07SJens Wiklander TEE_PARAM_TYPE_MEMREF_OUTPUT, 306b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 307b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 308b56b3d07SJens Wiklander TEE_Param *ctrl = params; 309b56b3d07SJens Wiklander TEE_Param *out = params + 2; 310b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 311b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 312b56b3d07SJens Wiklander struct obj_attrs *head = NULL; 313b56b3d07SJens Wiklander struct pkcs11_object_head *template = NULL; 314b56b3d07SJens Wiklander size_t template_size = 0; 315b56b3d07SJens Wiklander uint32_t obj_handle = 0; 316b56b3d07SJens Wiklander 317b56b3d07SJens Wiklander /* 318b56b3d07SJens Wiklander * Collect the arguments of the request 319b56b3d07SJens Wiklander */ 320b56b3d07SJens Wiklander 321b56b3d07SJens Wiklander if (!client || ptypes != exp_pt || 322b56b3d07SJens Wiklander out->memref.size != sizeof(obj_handle)) 323b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 324b56b3d07SJens Wiklander 325b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 326b56b3d07SJens Wiklander 32759a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 328b56b3d07SJens Wiklander if (rc) 329b56b3d07SJens Wiklander return rc; 330b56b3d07SJens Wiklander 331b56b3d07SJens Wiklander rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 332b56b3d07SJens Wiklander if (rc) 333b56b3d07SJens Wiklander return rc; 334b56b3d07SJens Wiklander 335b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 336b56b3d07SJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 337b56b3d07SJens Wiklander goto out; 338b56b3d07SJens Wiklander } 339b56b3d07SJens Wiklander 340b56b3d07SJens Wiklander template_size = sizeof(*template) + template->attrs_size; 341b56b3d07SJens Wiklander 342b56b3d07SJens Wiklander /* 343b56b3d07SJens Wiklander * Prepare a clean initial state for the requested object attributes. 344b56b3d07SJens Wiklander * Free temporary template once done. 345b56b3d07SJens Wiklander */ 346b56b3d07SJens Wiklander rc = create_attributes_from_template(&head, template, template_size, 347b56b3d07SJens Wiklander NULL, PKCS11_FUNCTION_IMPORT, 3484cfce748SRuchika Gupta PKCS11_PROCESSING_IMPORT, 3494cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 350b56b3d07SJens Wiklander TEE_Free(template); 351b56b3d07SJens Wiklander template = NULL; 352b56b3d07SJens Wiklander if (rc) 353b56b3d07SJens Wiklander goto out; 354b56b3d07SJens Wiklander 355*bcac2127SMarouene Boubakri /* Set key check value attribute */ 356*bcac2127SMarouene Boubakri rc = set_check_value_attr(&head); 357*bcac2127SMarouene Boubakri if (rc) 358*bcac2127SMarouene Boubakri goto out; 359*bcac2127SMarouene Boubakri 360b56b3d07SJens Wiklander /* 361b56b3d07SJens Wiklander * Check target object attributes match target processing 362b56b3d07SJens Wiklander * Check target object attributes match token state 363b56b3d07SJens Wiklander */ 364b56b3d07SJens Wiklander rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT, 365b56b3d07SJens Wiklander head); 366b56b3d07SJens Wiklander if (rc) 367b56b3d07SJens Wiklander goto out; 368b56b3d07SJens Wiklander 369b56b3d07SJens Wiklander rc = check_created_attrs_against_token(session, head); 370b56b3d07SJens Wiklander if (rc) 371b56b3d07SJens Wiklander goto out; 372b56b3d07SJens Wiklander 373b68aca61SRuchika Gupta rc = check_access_attrs_against_token(session, head); 374b68aca61SRuchika Gupta if (rc) 375b68aca61SRuchika Gupta goto out; 376b68aca61SRuchika Gupta 377b56b3d07SJens Wiklander /* 378b56b3d07SJens Wiklander * At this stage the object is almost created: all its attributes are 379b56b3d07SJens Wiklander * referenced in @head, including the key value and are assumed 380b56b3d07SJens Wiklander * reliable. Now need to register it and get a handle for it. 381b56b3d07SJens Wiklander */ 382b56b3d07SJens Wiklander rc = create_object(session, head, &obj_handle); 383b56b3d07SJens Wiklander if (rc) 384b56b3d07SJens Wiklander goto out; 385b56b3d07SJens Wiklander 386b56b3d07SJens Wiklander /* 387b56b3d07SJens Wiklander * Now obj_handle (through the related struct pkcs11_object 388e3737878SRuchika Gupta * instance) owns the serialized buffer that holds the object 389b56b3d07SJens Wiklander * attributes. We clear reference in head to NULL as the serializer 390b56b3d07SJens Wiklander * object is now referred from obj_handle. This allows smooth pass 391b56b3d07SJens Wiklander * through free at function exit. 392b56b3d07SJens Wiklander */ 393b56b3d07SJens Wiklander head = NULL; 394b56b3d07SJens Wiklander 395b56b3d07SJens Wiklander TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 396b56b3d07SJens Wiklander out->memref.size = sizeof(obj_handle); 397b56b3d07SJens Wiklander 398b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32, 399b56b3d07SJens Wiklander session->handle, obj_handle); 400b56b3d07SJens Wiklander 401b56b3d07SJens Wiklander out: 402b56b3d07SJens Wiklander TEE_Free(template); 403b56b3d07SJens Wiklander TEE_Free(head); 404b56b3d07SJens Wiklander 405b56b3d07SJens Wiklander return rc; 406b56b3d07SJens Wiklander } 407b56b3d07SJens Wiklander 408b56b3d07SJens Wiklander enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, 409b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 410b56b3d07SJens Wiklander { 411b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 412b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 413b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 414b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 415b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 416b56b3d07SJens Wiklander TEE_Param *ctrl = params; 417b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 418b56b3d07SJens Wiklander uint32_t object_handle = 0; 419b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 420b56b3d07SJens Wiklander struct pkcs11_object *object = NULL; 421b56b3d07SJens Wiklander 422b56b3d07SJens Wiklander if (!client || ptypes != exp_pt) 423b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 424b56b3d07SJens Wiklander 425b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 426b56b3d07SJens Wiklander 42759a5257eSEtienne Carriere rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 428b56b3d07SJens Wiklander if (rc) 429b56b3d07SJens Wiklander return rc; 430b56b3d07SJens Wiklander 431b56b3d07SJens Wiklander rc = serialargs_get_u32(&ctrlargs, &object_handle); 432b56b3d07SJens Wiklander if (rc) 433b56b3d07SJens Wiklander return rc; 434b56b3d07SJens Wiklander 435b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 436b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 437b56b3d07SJens Wiklander 438b56b3d07SJens Wiklander object = pkcs11_handle2object(object_handle, session); 439b56b3d07SJens Wiklander if (!object) 440b56b3d07SJens Wiklander return PKCS11_CKR_OBJECT_HANDLE_INVALID; 441b56b3d07SJens Wiklander 442fab91492SRuchika Gupta /* Only session objects can be destroyed during a read-only session */ 443fab91492SRuchika Gupta if (get_bool(object->attributes, PKCS11_CKA_TOKEN) && 444fab91492SRuchika Gupta !pkcs11_session_is_read_write(session)) { 445fab91492SRuchika Gupta DMSG("Can't destroy persistent object"); 446fab91492SRuchika Gupta return PKCS11_CKR_SESSION_READ_ONLY; 447fab91492SRuchika Gupta } 448fab91492SRuchika Gupta 449fab91492SRuchika Gupta /* 450fab91492SRuchika Gupta * Only public objects can be destroyed unless normal user is logged in 451fab91492SRuchika Gupta */ 452fab91492SRuchika Gupta rc = check_access_attrs_against_token(session, object->attributes); 453fab91492SRuchika Gupta if (rc) 454fab91492SRuchika Gupta return PKCS11_CKR_USER_NOT_LOGGED_IN; 455fab91492SRuchika Gupta 456fab91492SRuchika Gupta /* Objects with PKCS11_CKA_DESTROYABLE as false aren't destroyable */ 457fab91492SRuchika Gupta if (!get_bool(object->attributes, PKCS11_CKA_DESTROYABLE)) 458fab91492SRuchika Gupta return PKCS11_CKR_ACTION_PROHIBITED; 459fab91492SRuchika Gupta 460b56b3d07SJens Wiklander destroy_object(session, object, false); 461b56b3d07SJens Wiklander 462b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32, 463b56b3d07SJens Wiklander session->handle, object_handle); 464b56b3d07SJens Wiklander 465b56b3d07SJens Wiklander return rc; 466b56b3d07SJens Wiklander } 467dc99b202SRuchika Gupta 468dc99b202SRuchika Gupta static void release_find_obj_context(struct pkcs11_find_objects *find_ctx) 469dc99b202SRuchika Gupta { 470dc99b202SRuchika Gupta if (!find_ctx) 471dc99b202SRuchika Gupta return; 472dc99b202SRuchika Gupta 473dc99b202SRuchika Gupta TEE_Free(find_ctx->attributes); 474dc99b202SRuchika Gupta TEE_Free(find_ctx->handles); 475dc99b202SRuchika Gupta TEE_Free(find_ctx); 476dc99b202SRuchika Gupta } 477dc99b202SRuchika Gupta 478dc99b202SRuchika Gupta static enum pkcs11_rc find_ctx_add(struct pkcs11_find_objects *find_ctx, 479dc99b202SRuchika Gupta uint32_t handle) 480dc99b202SRuchika Gupta { 481dc99b202SRuchika Gupta uint32_t *hdls = TEE_Realloc(find_ctx->handles, 482dc99b202SRuchika Gupta (find_ctx->count + 1) * sizeof(*hdls)); 483dc99b202SRuchika Gupta 484dc99b202SRuchika Gupta if (!hdls) 485dc99b202SRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY; 486dc99b202SRuchika Gupta 487dc99b202SRuchika Gupta find_ctx->handles = hdls; 488dc99b202SRuchika Gupta 489dc99b202SRuchika Gupta *(find_ctx->handles + find_ctx->count) = handle; 490dc99b202SRuchika Gupta find_ctx->count++; 491dc99b202SRuchika Gupta 492dc99b202SRuchika Gupta return PKCS11_CKR_OK; 493dc99b202SRuchika Gupta } 494dc99b202SRuchika Gupta 495dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects_init(struct pkcs11_client *client, 496dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 497dc99b202SRuchika Gupta { 498dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 499dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 500dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 501dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 502dc99b202SRuchika Gupta TEE_Param *ctrl = params; 503dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 504dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 505dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 506bc555ee0SVesa Jääskeläinen struct pkcs11_session *sess = NULL; 507dc99b202SRuchika Gupta struct pkcs11_object_head *template = NULL; 508dc99b202SRuchika Gupta struct obj_attrs *req_attrs = NULL; 509dc99b202SRuchika Gupta struct pkcs11_object *obj = NULL; 510dc99b202SRuchika Gupta struct pkcs11_find_objects *find_ctx = NULL; 511bc555ee0SVesa Jääskeläinen struct handle_db *object_db = NULL; 512dc99b202SRuchika Gupta 513dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 514dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 515dc99b202SRuchika Gupta 516dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 517dc99b202SRuchika Gupta 518dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 519dc99b202SRuchika Gupta if (rc) 520dc99b202SRuchika Gupta return rc; 521dc99b202SRuchika Gupta 522dc99b202SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 523dc99b202SRuchika Gupta if (rc) 524dc99b202SRuchika Gupta return rc; 525dc99b202SRuchika Gupta 526dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 527dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 528dc99b202SRuchika Gupta goto out; 529dc99b202SRuchika Gupta } 530dc99b202SRuchika Gupta 531dc99b202SRuchika Gupta /* Search objects only if no operation is on-going */ 532dc99b202SRuchika Gupta if (session_is_active(session)) { 533dc99b202SRuchika Gupta rc = PKCS11_CKR_OPERATION_ACTIVE; 534dc99b202SRuchika Gupta goto out; 535dc99b202SRuchika Gupta } 536dc99b202SRuchika Gupta 537dc99b202SRuchika Gupta if (session->find_ctx) { 538dc99b202SRuchika Gupta EMSG("Active object search already in progress"); 539dc99b202SRuchika Gupta rc = PKCS11_CKR_FUNCTION_FAILED; 540dc99b202SRuchika Gupta goto out; 541dc99b202SRuchika Gupta } 542dc99b202SRuchika Gupta 543dc99b202SRuchika Gupta rc = sanitize_client_object(&req_attrs, template, 544dc99b202SRuchika Gupta sizeof(*template) + template->attrs_size, 545dc99b202SRuchika Gupta PKCS11_UNDEFINED_ID, PKCS11_UNDEFINED_ID); 546dc99b202SRuchika Gupta if (rc) 547dc99b202SRuchika Gupta goto out; 548dc99b202SRuchika Gupta 549dc99b202SRuchika Gupta /* Must zero init the structure */ 550dc99b202SRuchika Gupta find_ctx = TEE_Malloc(sizeof(*find_ctx), TEE_MALLOC_FILL_ZERO); 551dc99b202SRuchika Gupta if (!find_ctx) { 552dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 553dc99b202SRuchika Gupta goto out; 554dc99b202SRuchika Gupta } 555dc99b202SRuchika Gupta 556dc99b202SRuchika Gupta TEE_Free(template); 557dc99b202SRuchika Gupta template = NULL; 558dc99b202SRuchika Gupta 559dc99b202SRuchika Gupta switch (get_class(req_attrs)) { 560dc99b202SRuchika Gupta case PKCS11_CKO_UNDEFINED_ID: 561dc99b202SRuchika Gupta /* Unspecified class searches among data objects */ 562dc99b202SRuchika Gupta case PKCS11_CKO_SECRET_KEY: 563dc99b202SRuchika Gupta case PKCS11_CKO_PUBLIC_KEY: 564dc99b202SRuchika Gupta case PKCS11_CKO_PRIVATE_KEY: 565dc99b202SRuchika Gupta case PKCS11_CKO_DATA: 5664137952dSVesa Jääskeläinen case PKCS11_CKO_CERTIFICATE: 567dc99b202SRuchika Gupta break; 568dc99b202SRuchika Gupta default: 569dc99b202SRuchika Gupta EMSG("Find object of class %s (%"PRIu32") is not supported", 570dc99b202SRuchika Gupta id2str_class(get_class(req_attrs)), 571dc99b202SRuchika Gupta get_class(req_attrs)); 572dc99b202SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 573dc99b202SRuchika Gupta goto out; 574dc99b202SRuchika Gupta } 575dc99b202SRuchika Gupta 576dc99b202SRuchika Gupta /* 577dc99b202SRuchika Gupta * Scan all objects (sessions and persistent ones) and set a list of 578dc99b202SRuchika Gupta * candidates that match caller attributes. 579dc99b202SRuchika Gupta */ 580dc99b202SRuchika Gupta 581bc555ee0SVesa Jääskeläinen /* Scan all session objects first */ 582bc555ee0SVesa Jääskeläinen TAILQ_FOREACH(sess, get_session_list(session), link) { 583bc555ee0SVesa Jääskeläinen LIST_FOREACH(obj, &sess->object_list, link) { 584bc555ee0SVesa Jääskeläinen /* 585bc555ee0SVesa Jääskeläinen * Skip all token objects as they could be from 586bc555ee0SVesa Jääskeläinen * different token which the session does not have 587bc555ee0SVesa Jääskeläinen * access 588bc555ee0SVesa Jääskeläinen */ 589bc555ee0SVesa Jääskeläinen if (obj->token) 590dc99b202SRuchika Gupta continue; 591dc99b202SRuchika Gupta 592bc555ee0SVesa Jääskeläinen if (!attributes_match_reference(obj->attributes, 593bc555ee0SVesa Jääskeläinen req_attrs)) 594dc99b202SRuchika Gupta continue; 595dc99b202SRuchika Gupta 596bc555ee0SVesa Jääskeläinen rc = find_ctx_add(find_ctx, 597bc555ee0SVesa Jääskeläinen pkcs11_object2handle(obj, session)); 598dc99b202SRuchika Gupta if (rc) 599dc99b202SRuchika Gupta goto out; 600dc99b202SRuchika Gupta } 601bc555ee0SVesa Jääskeläinen } 602dc99b202SRuchika Gupta 603bc555ee0SVesa Jääskeläinen object_db = get_object_handle_db(session); 604bc555ee0SVesa Jääskeläinen 605bc555ee0SVesa Jääskeläinen /* Scan token objects */ 606dc99b202SRuchika Gupta LIST_FOREACH(obj, &session->token->object_list, link) { 607dc99b202SRuchika Gupta uint32_t handle = 0; 608fa1ac767SRobin van der Gracht bool new_load = false; 609dc99b202SRuchika Gupta 610fa1ac767SRobin van der Gracht if (!obj->attributes) { 611fa1ac767SRobin van der Gracht rc = load_persistent_object_attributes(obj); 612b7964037SElvira Khabirova if (rc) { 613b7964037SElvira Khabirova rc = PKCS11_CKR_GENERAL_ERROR; 614b7964037SElvira Khabirova goto out; 615b7964037SElvira Khabirova } 616dc99b202SRuchika Gupta 617fa1ac767SRobin van der Gracht new_load = true; 618fa1ac767SRobin van der Gracht } 619fa1ac767SRobin van der Gracht 620fa1ac767SRobin van der Gracht if (!obj->attributes || 621fa1ac767SRobin van der Gracht check_access_attrs_against_token(session, 622fa1ac767SRobin van der Gracht obj->attributes) || 623fa1ac767SRobin van der Gracht !attributes_match_reference(obj->attributes, req_attrs)) { 624fa1ac767SRobin van der Gracht if (new_load) 625fa1ac767SRobin van der Gracht release_persistent_object_attributes(obj); 626fa1ac767SRobin van der Gracht 627dc99b202SRuchika Gupta continue; 628dc99b202SRuchika Gupta } 629dc99b202SRuchika Gupta 630bc555ee0SVesa Jääskeläinen /* Resolve object handle for object */ 631dc99b202SRuchika Gupta handle = pkcs11_object2handle(obj, session); 632dc99b202SRuchika Gupta if (!handle) { 633bc555ee0SVesa Jääskeläinen handle = handle_get(object_db, obj); 634dc99b202SRuchika Gupta if (!handle) { 635dc99b202SRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 636dc99b202SRuchika Gupta goto out; 637dc99b202SRuchika Gupta } 638dc99b202SRuchika Gupta } 639dc99b202SRuchika Gupta 640dc99b202SRuchika Gupta rc = find_ctx_add(find_ctx, handle); 641dc99b202SRuchika Gupta if (rc) 642dc99b202SRuchika Gupta goto out; 643dc99b202SRuchika Gupta } 644dc99b202SRuchika Gupta 645dc99b202SRuchika Gupta find_ctx->attributes = req_attrs; 646dc99b202SRuchika Gupta req_attrs = NULL; 647dc99b202SRuchika Gupta session->find_ctx = find_ctx; 648dc99b202SRuchika Gupta find_ctx = NULL; 649dc99b202SRuchika Gupta rc = PKCS11_CKR_OK; 650dc99b202SRuchika Gupta 651dc99b202SRuchika Gupta out: 652dc99b202SRuchika Gupta TEE_Free(req_attrs); 653dc99b202SRuchika Gupta TEE_Free(template); 654dc99b202SRuchika Gupta release_find_obj_context(find_ctx); 655dc99b202SRuchika Gupta 656dc99b202SRuchika Gupta return rc; 657dc99b202SRuchika Gupta } 658dc99b202SRuchika Gupta 659dc99b202SRuchika Gupta enum pkcs11_rc entry_find_objects(struct pkcs11_client *client, 660dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 661dc99b202SRuchika Gupta { 662dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 663dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 664dc99b202SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 665dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 666dc99b202SRuchika Gupta TEE_Param *ctrl = params; 667dc99b202SRuchika Gupta TEE_Param *out = params + 2; 668dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 669dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 670dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 671dc99b202SRuchika Gupta struct pkcs11_find_objects *ctx = NULL; 672dc99b202SRuchika Gupta uint8_t *out_handles = NULL; 673dc99b202SRuchika Gupta size_t out_count = 0; 674dc99b202SRuchika Gupta size_t count = 0; 675dc99b202SRuchika Gupta 676dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 677dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 678dc99b202SRuchika Gupta 679dc99b202SRuchika Gupta out_count = out->memref.size / sizeof(uint32_t); 680dc99b202SRuchika Gupta out_handles = out->memref.buffer; 681dc99b202SRuchika Gupta 682dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 683dc99b202SRuchika Gupta 684dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 685dc99b202SRuchika Gupta if (rc) 686dc99b202SRuchika Gupta return rc; 687dc99b202SRuchika Gupta 688dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 689dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 690dc99b202SRuchika Gupta 691dc99b202SRuchika Gupta ctx = session->find_ctx; 692dc99b202SRuchika Gupta 693dc99b202SRuchika Gupta if (!ctx) 694dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 695dc99b202SRuchika Gupta 696dc99b202SRuchika Gupta for (count = 0; ctx->next < ctx->count && count < out_count; 697dc99b202SRuchika Gupta ctx->next++, count++) 698dc99b202SRuchika Gupta TEE_MemMove(out_handles + count * sizeof(uint32_t), 699dc99b202SRuchika Gupta ctx->handles + ctx->next, sizeof(uint32_t)); 700dc99b202SRuchika Gupta 701dc99b202SRuchika Gupta /* Update output buffer according the number of handles provided */ 702dc99b202SRuchika Gupta out->memref.size = count * sizeof(uint32_t); 703dc99b202SRuchika Gupta 704dc99b202SRuchika Gupta DMSG("PKCS11 session %"PRIu32": finding objects", session->handle); 705dc99b202SRuchika Gupta 706dc99b202SRuchika Gupta return PKCS11_CKR_OK; 707dc99b202SRuchika Gupta } 708dc99b202SRuchika Gupta 709dc99b202SRuchika Gupta void release_session_find_obj_context(struct pkcs11_session *session) 710dc99b202SRuchika Gupta { 711dc99b202SRuchika Gupta release_find_obj_context(session->find_ctx); 712dc99b202SRuchika Gupta session->find_ctx = NULL; 713dc99b202SRuchika Gupta } 714dc99b202SRuchika Gupta 715e3737878SRuchika Gupta enum pkcs11_rc entry_find_objects_final(struct pkcs11_client *client, 716dc99b202SRuchika Gupta uint32_t ptypes, TEE_Param *params) 717dc99b202SRuchika Gupta { 718dc99b202SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 719dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 720dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE, 721dc99b202SRuchika Gupta TEE_PARAM_TYPE_NONE); 722dc99b202SRuchika Gupta TEE_Param *ctrl = params; 723dc99b202SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 724dc99b202SRuchika Gupta struct serialargs ctrlargs = { }; 725dc99b202SRuchika Gupta struct pkcs11_session *session = NULL; 726dc99b202SRuchika Gupta 727dc99b202SRuchika Gupta if (!client || ptypes != exp_pt) 728dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 729dc99b202SRuchika Gupta 730dc99b202SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 731dc99b202SRuchika Gupta 732dc99b202SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 733dc99b202SRuchika Gupta if (rc) 734dc99b202SRuchika Gupta return rc; 735dc99b202SRuchika Gupta 736dc99b202SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 737dc99b202SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 738dc99b202SRuchika Gupta 739dc99b202SRuchika Gupta if (!session->find_ctx) 740dc99b202SRuchika Gupta return PKCS11_CKR_OPERATION_NOT_INITIALIZED; 741dc99b202SRuchika Gupta 742dc99b202SRuchika Gupta release_session_find_obj_context(session); 743dc99b202SRuchika Gupta 744dc99b202SRuchika Gupta return PKCS11_CKR_OK; 745dc99b202SRuchika Gupta } 746783c1515SRuchika Gupta 747e3737878SRuchika Gupta enum pkcs11_rc entry_get_attribute_value(struct pkcs11_client *client, 748783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params) 749783c1515SRuchika Gupta { 750783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 751783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE, 752783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 753783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE); 754783c1515SRuchika Gupta TEE_Param *ctrl = params; 755783c1515SRuchika Gupta TEE_Param *out = params + 2; 756783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 757783c1515SRuchika Gupta struct serialargs ctrlargs = { }; 758783c1515SRuchika Gupta struct pkcs11_session *session = NULL; 759783c1515SRuchika Gupta struct pkcs11_object_head *template = NULL; 760783c1515SRuchika Gupta struct pkcs11_object *obj = NULL; 761783c1515SRuchika Gupta uint32_t object_handle = 0; 762783c1515SRuchika Gupta char *cur = NULL; 763783c1515SRuchika Gupta size_t len = 0; 764783c1515SRuchika Gupta char *end = NULL; 765783c1515SRuchika Gupta bool attr_sensitive = 0; 766783c1515SRuchika Gupta bool attr_type_invalid = 0; 767783c1515SRuchika Gupta bool buffer_too_small = 0; 768783c1515SRuchika Gupta 769783c1515SRuchika Gupta if (!client || ptypes != exp_pt) 770783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 771783c1515SRuchika Gupta 772783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 773783c1515SRuchika Gupta 774783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 775783c1515SRuchika Gupta if (rc) 776783c1515SRuchika Gupta return rc; 777783c1515SRuchika Gupta 778783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 779783c1515SRuchika Gupta if (rc) 780783c1515SRuchika Gupta return rc; 781783c1515SRuchika Gupta 782783c1515SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 783783c1515SRuchika Gupta if (rc) 784783c1515SRuchika Gupta return rc; 785783c1515SRuchika Gupta 786783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 787783c1515SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 788783c1515SRuchika Gupta goto out; 789783c1515SRuchika Gupta } 790783c1515SRuchika Gupta 791783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 792783c1515SRuchika Gupta if (!obj) { 793783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 794783c1515SRuchika Gupta goto out; 795783c1515SRuchika Gupta } 796783c1515SRuchika Gupta 797783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 798783c1515SRuchika Gupta if (rc) { 799783c1515SRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 800783c1515SRuchika Gupta goto out; 801783c1515SRuchika Gupta } 802783c1515SRuchika Gupta 803783c1515SRuchika Gupta /* Iterate over attributes and set their values */ 804783c1515SRuchika Gupta /* 805783c1515SRuchika Gupta * 1. If the specified attribute (i.e., the attribute specified by the 806783c1515SRuchika Gupta * type field) for the object cannot be revealed because the object is 807783c1515SRuchika Gupta * sensitive or unextractable, then the ulValueLen field in that triple 808783c1515SRuchika Gupta * is modified to hold the value PKCS11_CK_UNAVAILABLE_INFORMATION. 809783c1515SRuchika Gupta * 810783c1515SRuchika Gupta * 2. Otherwise, if the specified value for the object is invalid (the 811783c1515SRuchika Gupta * object does not possess such an attribute), then the ulValueLen field 812783c1515SRuchika Gupta * in that triple is modified to hold the value 813783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION. 814783c1515SRuchika Gupta * 815783c1515SRuchika Gupta * 3. Otherwise, if the pValue field has the value NULL_PTR, then the 816783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the 817783c1515SRuchika Gupta * specified attribute for the object. 818783c1515SRuchika Gupta * 819783c1515SRuchika Gupta * 4. Otherwise, if the length specified in ulValueLen is large enough 820783c1515SRuchika Gupta * to hold the value of the specified attribute for the object, then 821783c1515SRuchika Gupta * that attribute is copied into the buffer located at pValue, and the 822783c1515SRuchika Gupta * ulValueLen field is modified to hold the exact length of the 823783c1515SRuchika Gupta * attribute. 824783c1515SRuchika Gupta * 825783c1515SRuchika Gupta * 5. Otherwise, the ulValueLen field is modified to hold the value 826783c1515SRuchika Gupta * PKCS11_CK_UNAVAILABLE_INFORMATION. 827783c1515SRuchika Gupta */ 828783c1515SRuchika Gupta cur = (char *)template + sizeof(struct pkcs11_object_head); 829783c1515SRuchika Gupta end = cur + template->attrs_size; 830783c1515SRuchika Gupta 831783c1515SRuchika Gupta for (; cur < end; cur += len) { 832783c1515SRuchika Gupta struct pkcs11_attribute_head *cli_ref = (void *)cur; 83318cbc7a2SVesa Jääskeläinen struct pkcs11_attribute_head cli_head = { }; 83418cbc7a2SVesa Jääskeläinen void *data_ptr = NULL; 835783c1515SRuchika Gupta 83618cbc7a2SVesa Jääskeläinen /* Make copy of header so that is aligned properly. */ 83718cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_head, cli_ref, sizeof(cli_head)); 83818cbc7a2SVesa Jääskeläinen 83918cbc7a2SVesa Jääskeläinen len = sizeof(*cli_ref) + cli_head.size; 840783c1515SRuchika Gupta 841981966bcSVesa Jääskeläinen /* Treat hidden attributes as missing attributes */ 842981966bcSVesa Jääskeläinen if (attribute_is_hidden(&cli_head)) { 843981966bcSVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; 844981966bcSVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size, 845981966bcSVesa Jääskeläinen sizeof(cli_head.size)); 846981966bcSVesa Jääskeläinen attr_type_invalid = 1; 847981966bcSVesa Jääskeläinen continue; 848981966bcSVesa Jääskeläinen } 849981966bcSVesa Jääskeläinen 850372064dcSRuchika Gupta /* We don't support getting value of indirect templates */ 851372064dcSRuchika Gupta if (pkcs11_attr_has_indirect_attributes(cli_head.id)) { 852372064dcSRuchika Gupta attr_type_invalid = 1; 853372064dcSRuchika Gupta continue; 854372064dcSRuchika Gupta } 855372064dcSRuchika Gupta 856783c1515SRuchika Gupta /* Check 1. */ 85718cbc7a2SVesa Jääskeläinen if (!attribute_is_exportable(&cli_head, obj)) { 85818cbc7a2SVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; 85918cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size, 86018cbc7a2SVesa Jääskeläinen sizeof(cli_head.size)); 861783c1515SRuchika Gupta attr_sensitive = 1; 862783c1515SRuchika Gupta continue; 863783c1515SRuchika Gupta } 864783c1515SRuchika Gupta 86518cbc7a2SVesa Jääskeläinen /* Get real data pointer from template data */ 866f3178382SVesa Jääskeläinen data_ptr = cli_head.size ? cli_ref->data : NULL; 86718cbc7a2SVesa Jääskeläinen 868783c1515SRuchika Gupta /* 869783c1515SRuchika Gupta * We assume that if size is 0, pValue was NULL, so we return 870783c1515SRuchika Gupta * the size of the required buffer for it (3., 4.) 871783c1515SRuchika Gupta */ 872f3178382SVesa Jääskeläinen rc = get_attribute(obj->attributes, cli_head.id, data_ptr, 87318cbc7a2SVesa Jääskeläinen &cli_head.size); 874783c1515SRuchika Gupta /* Check 2. */ 875783c1515SRuchika Gupta switch (rc) { 876783c1515SRuchika Gupta case PKCS11_CKR_OK: 877783c1515SRuchika Gupta break; 878783c1515SRuchika Gupta case PKCS11_RV_NOT_FOUND: 87918cbc7a2SVesa Jääskeläinen cli_head.size = PKCS11_CK_UNAVAILABLE_INFORMATION; 880783c1515SRuchika Gupta attr_type_invalid = 1; 881783c1515SRuchika Gupta break; 882783c1515SRuchika Gupta case PKCS11_CKR_BUFFER_TOO_SMALL: 883f3178382SVesa Jääskeläinen if (data_ptr) 884783c1515SRuchika Gupta buffer_too_small = 1; 885783c1515SRuchika Gupta break; 886783c1515SRuchika Gupta default: 887783c1515SRuchika Gupta rc = PKCS11_CKR_GENERAL_ERROR; 888783c1515SRuchika Gupta goto out; 889783c1515SRuchika Gupta } 89018cbc7a2SVesa Jääskeläinen 89118cbc7a2SVesa Jääskeläinen TEE_MemMove(&cli_ref->size, &cli_head.size, 89218cbc7a2SVesa Jääskeläinen sizeof(cli_head.size)); 893783c1515SRuchika Gupta } 894783c1515SRuchika Gupta 895783c1515SRuchika Gupta /* 896783c1515SRuchika Gupta * If case 1 applies to any of the requested attributes, then the call 897783c1515SRuchika Gupta * should return the value CKR_ATTRIBUTE_SENSITIVE. If case 2 applies to 898783c1515SRuchika Gupta * any of the requested attributes, then the call should return the 899783c1515SRuchika Gupta * value CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the 900783c1515SRuchika Gupta * requested attributes, then the call should return the value 901783c1515SRuchika Gupta * CKR_BUFFER_TOO_SMALL. As usual, if more than one of these error codes 902783c1515SRuchika Gupta * is applicable, Cryptoki may return any of them. Only if none of them 903783c1515SRuchika Gupta * applies to any of the requested attributes will CKR_OK be returned. 904783c1515SRuchika Gupta */ 905783c1515SRuchika Gupta 906783c1515SRuchika Gupta rc = PKCS11_CKR_OK; 907783c1515SRuchika Gupta if (attr_sensitive) 908783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_SENSITIVE; 909783c1515SRuchika Gupta if (attr_type_invalid) 910783c1515SRuchika Gupta rc = PKCS11_CKR_ATTRIBUTE_TYPE_INVALID; 911783c1515SRuchika Gupta if (buffer_too_small) 912783c1515SRuchika Gupta rc = PKCS11_CKR_BUFFER_TOO_SMALL; 913783c1515SRuchika Gupta 914783c1515SRuchika Gupta /* Move updated template to out buffer */ 915783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, template, out->memref.size); 916783c1515SRuchika Gupta 917783c1515SRuchika Gupta DMSG("PKCS11 session %"PRIu32": get attributes %#"PRIx32, 918783c1515SRuchika Gupta session->handle, object_handle); 919783c1515SRuchika Gupta 920783c1515SRuchika Gupta out: 921783c1515SRuchika Gupta TEE_Free(template); 922783c1515SRuchika Gupta 923783c1515SRuchika Gupta return rc; 924783c1515SRuchika Gupta } 925783c1515SRuchika Gupta 926e3737878SRuchika Gupta enum pkcs11_rc entry_get_object_size(struct pkcs11_client *client, 927783c1515SRuchika Gupta uint32_t ptypes, TEE_Param *params) 928783c1515SRuchika Gupta { 929783c1515SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 930783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE, 931783c1515SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 932783c1515SRuchika Gupta TEE_PARAM_TYPE_NONE); 933783c1515SRuchika Gupta TEE_Param *ctrl = params; 934783c1515SRuchika Gupta TEE_Param *out = params + 2; 935783c1515SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 936783c1515SRuchika Gupta struct serialargs ctrlargs = { }; 937783c1515SRuchika Gupta struct pkcs11_session *session = NULL; 938783c1515SRuchika Gupta uint32_t object_handle = 0; 939783c1515SRuchika Gupta struct pkcs11_object *obj = NULL; 940783c1515SRuchika Gupta uint32_t obj_size = 0; 941783c1515SRuchika Gupta 942783c1515SRuchika Gupta if (!client || ptypes != exp_pt) 943783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 944783c1515SRuchika Gupta 945783c1515SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 946783c1515SRuchika Gupta 947783c1515SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 948783c1515SRuchika Gupta if (rc) 949783c1515SRuchika Gupta return rc; 950783c1515SRuchika Gupta 951783c1515SRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 952783c1515SRuchika Gupta if (rc) 953783c1515SRuchika Gupta return rc; 954783c1515SRuchika Gupta 955783c1515SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) 956783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 957783c1515SRuchika Gupta 958783c1515SRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 959783c1515SRuchika Gupta if (!obj) 960783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID; 961783c1515SRuchika Gupta 962783c1515SRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 963783c1515SRuchika Gupta if (rc) 964783c1515SRuchika Gupta return PKCS11_CKR_OBJECT_HANDLE_INVALID; 965783c1515SRuchika Gupta 966783c1515SRuchika Gupta if (out->memref.size != sizeof(uint32_t)) 967783c1515SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 968783c1515SRuchika Gupta 969783c1515SRuchika Gupta obj_size = ((struct obj_attrs *)obj->attributes)->attrs_size + 970783c1515SRuchika Gupta sizeof(struct obj_attrs); 971783c1515SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_size, sizeof(obj_size)); 972783c1515SRuchika Gupta 973783c1515SRuchika Gupta return PKCS11_CKR_OK; 974783c1515SRuchika Gupta } 9752d25a9bcSRuchika Gupta 9762d25a9bcSRuchika Gupta enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client, 9772d25a9bcSRuchika Gupta uint32_t ptypes, TEE_Param *params) 9782d25a9bcSRuchika Gupta { 9792d25a9bcSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 9802d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE, 9812d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE, 9822d25a9bcSRuchika Gupta TEE_PARAM_TYPE_NONE); 9832d25a9bcSRuchika Gupta TEE_Param *ctrl = params; 9842d25a9bcSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 9852d25a9bcSRuchika Gupta struct serialargs ctrlargs = { }; 9862d25a9bcSRuchika Gupta struct pkcs11_session *session = NULL; 9872d25a9bcSRuchika Gupta struct pkcs11_object_head *template = NULL; 9882d25a9bcSRuchika Gupta size_t template_size = 0; 9892d25a9bcSRuchika Gupta struct pkcs11_object *obj = NULL; 9902d25a9bcSRuchika Gupta struct obj_attrs *head = NULL; 9912d25a9bcSRuchika Gupta uint32_t object_handle = 0; 9922d25a9bcSRuchika Gupta enum processing_func function = PKCS11_FUNCTION_MODIFY; 9932d25a9bcSRuchika Gupta 9942d25a9bcSRuchika Gupta if (!client || ptypes != exp_pt) 9952d25a9bcSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 9962d25a9bcSRuchika Gupta 9972d25a9bcSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 9982d25a9bcSRuchika Gupta 9992d25a9bcSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 10002d25a9bcSRuchika Gupta if (rc) 10012d25a9bcSRuchika Gupta return rc; 10022d25a9bcSRuchika Gupta 10032d25a9bcSRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 10042d25a9bcSRuchika Gupta if (rc) 10052d25a9bcSRuchika Gupta return rc; 10062d25a9bcSRuchika Gupta 10072d25a9bcSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 10082d25a9bcSRuchika Gupta if (rc) 10092d25a9bcSRuchika Gupta return rc; 10102d25a9bcSRuchika Gupta 10112d25a9bcSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 10122d25a9bcSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 10132d25a9bcSRuchika Gupta goto out; 10142d25a9bcSRuchika Gupta } 10152d25a9bcSRuchika Gupta 10162d25a9bcSRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 10172d25a9bcSRuchika Gupta if (!obj) { 10182d25a9bcSRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 10192d25a9bcSRuchika Gupta goto out; 10202d25a9bcSRuchika Gupta } 10212d25a9bcSRuchika Gupta 10222d25a9bcSRuchika Gupta /* Only session objects can be modified during a read-only session */ 10232d25a9bcSRuchika Gupta if (object_is_token(obj->attributes) && 10242d25a9bcSRuchika Gupta !pkcs11_session_is_read_write(session)) { 10252d25a9bcSRuchika Gupta DMSG("Can't modify persistent object in a RO session"); 10262d25a9bcSRuchika Gupta rc = PKCS11_CKR_SESSION_READ_ONLY; 10272d25a9bcSRuchika Gupta goto out; 10282d25a9bcSRuchika Gupta } 10292d25a9bcSRuchika Gupta 10302d25a9bcSRuchika Gupta /* 10312d25a9bcSRuchika Gupta * Only public objects can be modified unless normal user is logged in 10322d25a9bcSRuchika Gupta */ 10332d25a9bcSRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 10342d25a9bcSRuchika Gupta if (rc) { 10352d25a9bcSRuchika Gupta rc = PKCS11_CKR_USER_NOT_LOGGED_IN; 10362d25a9bcSRuchika Gupta goto out; 10372d25a9bcSRuchika Gupta } 10382d25a9bcSRuchika Gupta 10392d25a9bcSRuchika Gupta /* Objects with PKCS11_CKA_MODIFIABLE as false aren't modifiable */ 10402d25a9bcSRuchika Gupta if (!object_is_modifiable(obj->attributes)) { 10412d25a9bcSRuchika Gupta rc = PKCS11_CKR_ACTION_PROHIBITED; 10422d25a9bcSRuchika Gupta goto out; 10432d25a9bcSRuchika Gupta } 10442d25a9bcSRuchika Gupta 10452d25a9bcSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 10462d25a9bcSRuchika Gupta 10472d25a9bcSRuchika Gupta /* 10482d25a9bcSRuchika Gupta * Prepare a clean initial state (@head) for the template. Helps in 10492d25a9bcSRuchika Gupta * removing any duplicates or inconsistent values from the 10502d25a9bcSRuchika Gupta * template. 10512d25a9bcSRuchika Gupta */ 10522d25a9bcSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 10532d25a9bcSRuchika Gupta NULL, function, 10542d25a9bcSRuchika Gupta PKCS11_CKM_UNDEFINED_ID, 10552d25a9bcSRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 10562d25a9bcSRuchika Gupta if (rc) 10572d25a9bcSRuchika Gupta goto out; 10582d25a9bcSRuchika Gupta 10592d25a9bcSRuchika Gupta /* Check the attributes in @head to see if they are modifiable */ 10602d25a9bcSRuchika Gupta rc = check_attrs_against_modification(session, head, obj, function); 10612d25a9bcSRuchika Gupta if (rc) 10622d25a9bcSRuchika Gupta goto out; 10632d25a9bcSRuchika Gupta 10642d25a9bcSRuchika Gupta /* 10652d25a9bcSRuchika Gupta * All checks complete. The attributes in @head have been checked and 10662d25a9bcSRuchika Gupta * can now be used to set/modify the object attributes. 10672d25a9bcSRuchika Gupta */ 10682d25a9bcSRuchika Gupta rc = modify_attributes_list(&obj->attributes, head); 10692d25a9bcSRuchika Gupta if (rc) 10702d25a9bcSRuchika Gupta goto out; 10712d25a9bcSRuchika Gupta 1072*bcac2127SMarouene Boubakri /* Set key check value attribute */ 1073*bcac2127SMarouene Boubakri rc = set_check_value_attr(&obj->attributes); 1074*bcac2127SMarouene Boubakri if (rc) 1075*bcac2127SMarouene Boubakri goto out; 1076*bcac2127SMarouene Boubakri 1077402d884aSRuchika Gupta if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 1078402d884aSRuchika Gupta rc = update_persistent_object_attributes(obj); 1079402d884aSRuchika Gupta if (rc) 1080402d884aSRuchika Gupta goto out; 1081402d884aSRuchika Gupta } 1082402d884aSRuchika Gupta 10832d25a9bcSRuchika Gupta DMSG("PKCS11 session %"PRIu32": set attributes %#"PRIx32, 10842d25a9bcSRuchika Gupta session->handle, object_handle); 10852d25a9bcSRuchika Gupta 10862d25a9bcSRuchika Gupta out: 10872d25a9bcSRuchika Gupta TEE_Free(head); 10882d25a9bcSRuchika Gupta TEE_Free(template); 10892d25a9bcSRuchika Gupta return rc; 10902d25a9bcSRuchika Gupta } 1091bc09507cSRuchika Gupta 1092bc09507cSRuchika Gupta enum pkcs11_rc entry_copy_object(struct pkcs11_client *client, uint32_t ptypes, 1093bc09507cSRuchika Gupta TEE_Param *params) 1094bc09507cSRuchika Gupta { 1095bc09507cSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1096bc09507cSRuchika Gupta TEE_PARAM_TYPE_NONE, 1097bc09507cSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 1098bc09507cSRuchika Gupta TEE_PARAM_TYPE_NONE); 1099bc09507cSRuchika Gupta TEE_Param *ctrl = params; 1100bc09507cSRuchika Gupta TEE_Param *out = params + 2; 1101bc09507cSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 1102bc09507cSRuchika Gupta struct serialargs ctrlargs = { }; 1103bc09507cSRuchika Gupta struct pkcs11_session *session = NULL; 1104bc09507cSRuchika Gupta struct pkcs11_object_head *template = NULL; 1105bc09507cSRuchika Gupta struct obj_attrs *head = NULL; 1106bc09507cSRuchika Gupta struct obj_attrs *head_new = NULL; 1107bc09507cSRuchika Gupta size_t template_size = 0; 1108bc09507cSRuchika Gupta struct pkcs11_object *obj = NULL; 1109bc09507cSRuchika Gupta uint32_t object_handle = 0; 1110bc09507cSRuchika Gupta uint32_t obj_handle = 0; 1111bc09507cSRuchika Gupta enum processing_func function = PKCS11_FUNCTION_COPY; 1112bc09507cSRuchika Gupta enum pkcs11_class_id class = PKCS11_CKO_UNDEFINED_ID; 1113bc09507cSRuchika Gupta 1114bc09507cSRuchika Gupta if (!client || ptypes != exp_pt || 1115bc09507cSRuchika Gupta out->memref.size != sizeof(obj_handle)) 1116bc09507cSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 1117bc09507cSRuchika Gupta 1118bc09507cSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1119bc09507cSRuchika Gupta 1120bc09507cSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1121bc09507cSRuchika Gupta if (rc) 1122bc09507cSRuchika Gupta return rc; 1123bc09507cSRuchika Gupta 1124bc09507cSRuchika Gupta rc = serialargs_get(&ctrlargs, &object_handle, sizeof(uint32_t)); 1125bc09507cSRuchika Gupta if (rc) 1126bc09507cSRuchika Gupta return rc; 1127bc09507cSRuchika Gupta 1128bc09507cSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 1129bc09507cSRuchika Gupta if (rc) 1130bc09507cSRuchika Gupta return rc; 1131bc09507cSRuchika Gupta 1132bc09507cSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 1133bc09507cSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 1134bc09507cSRuchika Gupta goto out; 1135bc09507cSRuchika Gupta } 1136bc09507cSRuchika Gupta 1137bc09507cSRuchika Gupta obj = pkcs11_handle2object(object_handle, session); 1138bc09507cSRuchika Gupta if (!obj) { 1139bc09507cSRuchika Gupta rc = PKCS11_CKR_OBJECT_HANDLE_INVALID; 1140bc09507cSRuchika Gupta goto out; 1141bc09507cSRuchika Gupta } 1142bc09507cSRuchika Gupta 1143bc09507cSRuchika Gupta /* Only session objects can be modified during a read-only session */ 1144bc09507cSRuchika Gupta if (object_is_token(obj->attributes) && 1145bc09507cSRuchika Gupta !pkcs11_session_is_read_write(session)) { 1146bc09507cSRuchika Gupta DMSG("Can't modify persistent object in a RO session"); 1147bc09507cSRuchika Gupta rc = PKCS11_CKR_SESSION_READ_ONLY; 1148bc09507cSRuchika Gupta goto out; 1149bc09507cSRuchika Gupta } 1150bc09507cSRuchika Gupta 1151bc09507cSRuchika Gupta /* 1152bc09507cSRuchika Gupta * Only public objects can be modified unless normal user is logged in 1153bc09507cSRuchika Gupta */ 1154bc09507cSRuchika Gupta rc = check_access_attrs_against_token(session, obj->attributes); 1155bc09507cSRuchika Gupta if (rc) { 1156bc09507cSRuchika Gupta rc = PKCS11_CKR_USER_NOT_LOGGED_IN; 1157bc09507cSRuchika Gupta goto out; 1158bc09507cSRuchika Gupta } 1159bc09507cSRuchika Gupta 1160bc09507cSRuchika Gupta /* Objects with PKCS11_CKA_COPYABLE as false can't be copied */ 1161bc09507cSRuchika Gupta if (!object_is_copyable(obj->attributes)) { 1162bc09507cSRuchika Gupta rc = PKCS11_CKR_ACTION_PROHIBITED; 1163bc09507cSRuchika Gupta goto out; 1164bc09507cSRuchika Gupta } 1165bc09507cSRuchika Gupta 1166bc09507cSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 1167bc09507cSRuchika Gupta 1168bc09507cSRuchika Gupta /* 1169bc09507cSRuchika Gupta * Prepare a clean initial state (@head) for the template. Helps in 1170bc09507cSRuchika Gupta * removing any duplicates or inconsistent values from the 1171bc09507cSRuchika Gupta * template. 1172bc09507cSRuchika Gupta */ 1173bc09507cSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 1174bc09507cSRuchika Gupta NULL, function, 1175bc09507cSRuchika Gupta PKCS11_CKM_UNDEFINED_ID, 1176bc09507cSRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 1177bc09507cSRuchika Gupta if (rc) 1178bc09507cSRuchika Gupta goto out; 1179bc09507cSRuchika Gupta 1180bc09507cSRuchika Gupta /* Check the attributes in @head to see if they are modifiable */ 1181bc09507cSRuchika Gupta rc = check_attrs_against_modification(session, head, obj, function); 1182bc09507cSRuchika Gupta if (rc) 1183bc09507cSRuchika Gupta goto out; 1184bc09507cSRuchika Gupta 1185bc09507cSRuchika Gupta class = get_class(obj->attributes); 1186bc09507cSRuchika Gupta 1187bc09507cSRuchika Gupta if (class == PKCS11_CKO_SECRET_KEY || 1188bc09507cSRuchika Gupta class == PKCS11_CKO_PRIVATE_KEY) { 1189bc09507cSRuchika Gupta /* 1190bc09507cSRuchika Gupta * If CKA_EXTRACTABLE attribute in passed template (@head) is 1191bc09507cSRuchika Gupta * modified to CKA_FALSE, CKA_NEVER_EXTRACTABLE should also 1192bc09507cSRuchika Gupta * change to CKA_FALSE in copied obj. So, add it to the 1193bc09507cSRuchika Gupta * passed template. 1194bc09507cSRuchika Gupta */ 1195bc09507cSRuchika Gupta uint8_t bbool = 0; 1196bc09507cSRuchika Gupta uint32_t size = sizeof(bbool); 1197bc09507cSRuchika Gupta 1198bc09507cSRuchika Gupta rc = get_attribute(head, PKCS11_CKA_EXTRACTABLE, &bbool, &size); 1199bc09507cSRuchika Gupta if (!rc && !bbool) { 1200bc09507cSRuchika Gupta rc = add_attribute(&head, PKCS11_CKA_NEVER_EXTRACTABLE, 1201bc09507cSRuchika Gupta &bbool, sizeof(uint8_t)); 1202bc09507cSRuchika Gupta if (rc) 1203bc09507cSRuchika Gupta goto out; 1204bc09507cSRuchika Gupta } 1205bc09507cSRuchika Gupta rc = PKCS11_CKR_OK; 1206bc09507cSRuchika Gupta } 1207bc09507cSRuchika Gupta 1208bc09507cSRuchika Gupta /* 1209bc09507cSRuchika Gupta * All checks have passed. Create a copy of the serialized buffer which 1210bc09507cSRuchika Gupta * holds the object attributes in @head_new for the new object 1211bc09507cSRuchika Gupta */ 1212bc09507cSRuchika Gupta template_size = sizeof(*obj->attributes) + obj->attributes->attrs_size; 1213bc09507cSRuchika Gupta head_new = TEE_Malloc(template_size, TEE_MALLOC_FILL_ZERO); 1214bc09507cSRuchika Gupta if (!head_new) { 1215bc09507cSRuchika Gupta rc = PKCS11_CKR_DEVICE_MEMORY; 1216bc09507cSRuchika Gupta goto out; 1217bc09507cSRuchika Gupta } 1218bc09507cSRuchika Gupta 1219bc09507cSRuchika Gupta TEE_MemMove(head_new, obj->attributes, template_size); 1220bc09507cSRuchika Gupta 1221bc09507cSRuchika Gupta /* 1222bc09507cSRuchika Gupta * Modify the copied attribute @head_new based on the template @head 1223bc09507cSRuchika Gupta * given by the callee 1224bc09507cSRuchika Gupta */ 1225bc09507cSRuchika Gupta rc = modify_attributes_list(&head_new, head); 1226bc09507cSRuchika Gupta if (rc) 1227bc09507cSRuchika Gupta goto out; 1228bc09507cSRuchika Gupta 1229*bcac2127SMarouene Boubakri /* Set key check value attribute */ 1230*bcac2127SMarouene Boubakri rc = set_check_value_attr(&head_new); 1231*bcac2127SMarouene Boubakri if (rc) 1232*bcac2127SMarouene Boubakri goto out; 1233*bcac2127SMarouene Boubakri 1234bc09507cSRuchika Gupta /* 1235bc09507cSRuchika Gupta * At this stage the object is almost created: all its attributes are 1236bc09507cSRuchika Gupta * referenced in @head_new, including the key value and are assumed 1237bc09507cSRuchika Gupta * reliable. Now need to register it and get a handle for it. 1238bc09507cSRuchika Gupta */ 1239bc09507cSRuchika Gupta rc = create_object(session, head_new, &obj_handle); 1240bc09507cSRuchika Gupta if (rc) 1241bc09507cSRuchika Gupta goto out; 1242bc09507cSRuchika Gupta 1243bc09507cSRuchika Gupta /* 1244bc09507cSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object 1245e3737878SRuchika Gupta * instance) owns the serialized buffer that holds the object 1246bc09507cSRuchika Gupta * attributes. We clear reference in head to NULL as the serializer 1247bc09507cSRuchika Gupta * object is now referred from obj_handle. This allows smooth pass 1248bc09507cSRuchika Gupta * through free at function exit. 1249bc09507cSRuchika Gupta */ 1250bc09507cSRuchika Gupta head_new = NULL; 1251bc09507cSRuchika Gupta 1252bc09507cSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 1253bc09507cSRuchika Gupta out->memref.size = sizeof(obj_handle); 1254bc09507cSRuchika Gupta 1255bc09507cSRuchika Gupta DMSG("PKCS11 session %"PRIu32": copy object %#"PRIx32, 1256bc09507cSRuchika Gupta session->handle, obj_handle); 1257bc09507cSRuchika Gupta 1258bc09507cSRuchika Gupta out: 1259bc09507cSRuchika Gupta TEE_Free(head_new); 1260bc09507cSRuchika Gupta TEE_Free(head); 1261bc09507cSRuchika Gupta TEE_Free(template); 1262bc09507cSRuchika Gupta return rc; 1263bc09507cSRuchika Gupta } 1264