1*b56b3d07SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2*b56b3d07SJens Wiklander /* 3*b56b3d07SJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 4*b56b3d07SJens Wiklander */ 5*b56b3d07SJens Wiklander 6*b56b3d07SJens Wiklander #include <assert.h> 7*b56b3d07SJens Wiklander #include <inttypes.h> 8*b56b3d07SJens Wiklander #include <string_ext.h> 9*b56b3d07SJens Wiklander #include <tee_internal_api.h> 10*b56b3d07SJens Wiklander #include <tee_internal_api_extensions.h> 11*b56b3d07SJens Wiklander 12*b56b3d07SJens Wiklander #include "attributes.h" 13*b56b3d07SJens Wiklander #include "handle.h" 14*b56b3d07SJens Wiklander #include "object.h" 15*b56b3d07SJens Wiklander #include "pkcs11_attributes.h" 16*b56b3d07SJens Wiklander #include "pkcs11_helpers.h" 17*b56b3d07SJens Wiklander #include "pkcs11_token.h" 18*b56b3d07SJens Wiklander #include "sanitize_object.h" 19*b56b3d07SJens Wiklander #include "serializer.h" 20*b56b3d07SJens Wiklander 21*b56b3d07SJens Wiklander struct pkcs11_object *pkcs11_handle2object(uint32_t handle, 22*b56b3d07SJens Wiklander struct pkcs11_session *session) 23*b56b3d07SJens Wiklander { 24*b56b3d07SJens Wiklander return handle_lookup(&session->object_handle_db, handle); 25*b56b3d07SJens Wiklander } 26*b56b3d07SJens Wiklander 27*b56b3d07SJens Wiklander uint32_t pkcs11_object2handle(struct pkcs11_object *obj, 28*b56b3d07SJens Wiklander struct pkcs11_session *session) 29*b56b3d07SJens Wiklander { 30*b56b3d07SJens Wiklander return handle_lookup_handle(&session->object_handle_db, obj); 31*b56b3d07SJens Wiklander } 32*b56b3d07SJens Wiklander 33*b56b3d07SJens Wiklander /* Currently handle pkcs11 sessions and tokens */ 34*b56b3d07SJens Wiklander 35*b56b3d07SJens Wiklander static struct object_list *get_session_objects(void *session) 36*b56b3d07SJens Wiklander { 37*b56b3d07SJens Wiklander /* Currently supporting only pkcs11 session */ 38*b56b3d07SJens Wiklander struct pkcs11_session *ck_session = session; 39*b56b3d07SJens Wiklander 40*b56b3d07SJens Wiklander return pkcs11_get_session_objects(ck_session); 41*b56b3d07SJens Wiklander } 42*b56b3d07SJens Wiklander 43*b56b3d07SJens Wiklander /* Release resources of a non-persistent object */ 44*b56b3d07SJens Wiklander static void cleanup_volatile_obj_ref(struct pkcs11_object *obj) 45*b56b3d07SJens Wiklander { 46*b56b3d07SJens Wiklander if (!obj) 47*b56b3d07SJens Wiklander return; 48*b56b3d07SJens Wiklander 49*b56b3d07SJens Wiklander if (obj->key_handle != TEE_HANDLE_NULL) 50*b56b3d07SJens Wiklander TEE_FreeTransientObject(obj->key_handle); 51*b56b3d07SJens Wiklander 52*b56b3d07SJens Wiklander if (obj->attribs_hdl != TEE_HANDLE_NULL) 53*b56b3d07SJens Wiklander TEE_CloseObject(obj->attribs_hdl); 54*b56b3d07SJens Wiklander 55*b56b3d07SJens Wiklander TEE_Free(obj->attributes); 56*b56b3d07SJens Wiklander TEE_Free(obj->uuid); 57*b56b3d07SJens Wiklander TEE_Free(obj); 58*b56b3d07SJens Wiklander } 59*b56b3d07SJens Wiklander 60*b56b3d07SJens Wiklander /* Release resources of a persistent object including volatile resources */ 61*b56b3d07SJens Wiklander static void cleanup_persistent_object(struct pkcs11_object *obj __unused, 62*b56b3d07SJens Wiklander struct ck_token *token __unused) 63*b56b3d07SJens Wiklander { 64*b56b3d07SJens Wiklander EMSG("Persistent object not yet supported, panic!"); 65*b56b3d07SJens Wiklander TEE_Panic(0); 66*b56b3d07SJens Wiklander } 67*b56b3d07SJens Wiklander 68*b56b3d07SJens Wiklander /* 69*b56b3d07SJens Wiklander * destroy_object - destroy an PKCS11 TA object 70*b56b3d07SJens Wiklander * 71*b56b3d07SJens Wiklander * @session - session requesting object destruction 72*b56b3d07SJens Wiklander * @obj - reference to the PKCS11 TA object 73*b56b3d07SJens Wiklander * @session_only - true if only session object shall be destroyed 74*b56b3d07SJens Wiklander */ 75*b56b3d07SJens Wiklander void destroy_object(struct pkcs11_session *session, struct pkcs11_object *obj, 76*b56b3d07SJens Wiklander bool session_only) 77*b56b3d07SJens Wiklander { 78*b56b3d07SJens Wiklander #ifdef DEBUG 79*b56b3d07SJens Wiklander trace_attributes("[destroy]", obj->attributes); 80*b56b3d07SJens Wiklander if (obj->uuid) 81*b56b3d07SJens Wiklander MSG_RAW("[destroy] obj uuid %pUl", (void *)obj->uuid); 82*b56b3d07SJens Wiklander #endif 83*b56b3d07SJens Wiklander 84*b56b3d07SJens Wiklander /* 85*b56b3d07SJens Wiklander * Remove from session list only if it was published. 86*b56b3d07SJens Wiklander * 87*b56b3d07SJens Wiklander * This depends on obj->link.le_prev always pointing on the 88*b56b3d07SJens Wiklander * link.le_next element in the previous object in the list even if 89*b56b3d07SJens Wiklander * there's only a single object in the list. In the first object in 90*b56b3d07SJens Wiklander * the list obj->link.le_prev instead points to lh_first in the 91*b56b3d07SJens Wiklander * list head. If list implementation is changed we need to revisit 92*b56b3d07SJens Wiklander * this. 93*b56b3d07SJens Wiklander */ 94*b56b3d07SJens Wiklander if (obj->link.le_next || obj->link.le_prev) 95*b56b3d07SJens Wiklander LIST_REMOVE(obj, link); 96*b56b3d07SJens Wiklander 97*b56b3d07SJens Wiklander if (session_only) { 98*b56b3d07SJens Wiklander /* Destroy object due to session closure */ 99*b56b3d07SJens Wiklander handle_put(&session->object_handle_db, 100*b56b3d07SJens Wiklander pkcs11_object2handle(obj, session)); 101*b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 102*b56b3d07SJens Wiklander 103*b56b3d07SJens Wiklander return; 104*b56b3d07SJens Wiklander } 105*b56b3d07SJens Wiklander 106*b56b3d07SJens Wiklander /* Destroy target object (persistent or not) */ 107*b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 108*b56b3d07SJens Wiklander EMSG("Persistent object not yet supported, panic!"); 109*b56b3d07SJens Wiklander TEE_Panic(0); 110*b56b3d07SJens Wiklander } else { 111*b56b3d07SJens Wiklander handle_put(&session->object_handle_db, 112*b56b3d07SJens Wiklander pkcs11_object2handle(obj, session)); 113*b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 114*b56b3d07SJens Wiklander } 115*b56b3d07SJens Wiklander } 116*b56b3d07SJens Wiklander 117*b56b3d07SJens Wiklander static struct pkcs11_object *create_obj_instance(struct obj_attrs *head) 118*b56b3d07SJens Wiklander { 119*b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL; 120*b56b3d07SJens Wiklander 121*b56b3d07SJens Wiklander obj = TEE_Malloc(sizeof(struct pkcs11_object), TEE_MALLOC_FILL_ZERO); 122*b56b3d07SJens Wiklander if (!obj) 123*b56b3d07SJens Wiklander return NULL; 124*b56b3d07SJens Wiklander 125*b56b3d07SJens Wiklander obj->key_handle = TEE_HANDLE_NULL; 126*b56b3d07SJens Wiklander obj->attribs_hdl = TEE_HANDLE_NULL; 127*b56b3d07SJens Wiklander obj->attributes = head; 128*b56b3d07SJens Wiklander 129*b56b3d07SJens Wiklander return obj; 130*b56b3d07SJens Wiklander } 131*b56b3d07SJens Wiklander 132*b56b3d07SJens Wiklander /* 133*b56b3d07SJens Wiklander * create_object - create an PKCS11 TA object from its attributes and value 134*b56b3d07SJens Wiklander * 135*b56b3d07SJens Wiklander * @sess - session requesting object creation 136*b56b3d07SJens Wiklander * @head - reference to serialized attributes 137*b56b3d07SJens Wiklander * @out_handle - generated handle for the created object 138*b56b3d07SJens Wiklander */ 139*b56b3d07SJens Wiklander enum pkcs11_rc create_object(void *sess, struct obj_attrs *head, 140*b56b3d07SJens Wiklander uint32_t *out_handle) 141*b56b3d07SJens Wiklander { 142*b56b3d07SJens Wiklander enum pkcs11_rc rc = 0; 143*b56b3d07SJens Wiklander struct pkcs11_object *obj = NULL; 144*b56b3d07SJens Wiklander struct pkcs11_session *session = (struct pkcs11_session *)sess; 145*b56b3d07SJens Wiklander uint32_t obj_handle = 0; 146*b56b3d07SJens Wiklander 147*b56b3d07SJens Wiklander #ifdef DEBUG 148*b56b3d07SJens Wiklander trace_attributes("[create]", head); 149*b56b3d07SJens Wiklander #endif 150*b56b3d07SJens Wiklander 151*b56b3d07SJens Wiklander /* 152*b56b3d07SJens Wiklander * We do not check the key attributes. At this point, key attributes 153*b56b3d07SJens Wiklander * are expected consistent and reliable. 154*b56b3d07SJens Wiklander */ 155*b56b3d07SJens Wiklander 156*b56b3d07SJens Wiklander obj = create_obj_instance(head); 157*b56b3d07SJens Wiklander if (!obj) 158*b56b3d07SJens Wiklander return PKCS11_CKR_DEVICE_MEMORY; 159*b56b3d07SJens Wiklander 160*b56b3d07SJens Wiklander /* Create a handle for the object in the session database */ 161*b56b3d07SJens Wiklander obj_handle = handle_get(&session->object_handle_db, obj); 162*b56b3d07SJens Wiklander if (!obj_handle) { 163*b56b3d07SJens Wiklander rc = PKCS11_CKR_DEVICE_MEMORY; 164*b56b3d07SJens Wiklander goto err; 165*b56b3d07SJens Wiklander } 166*b56b3d07SJens Wiklander 167*b56b3d07SJens Wiklander if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) { 168*b56b3d07SJens Wiklander EMSG("Persistent object not yet supported, panic!"); 169*b56b3d07SJens Wiklander TEE_Panic(0); 170*b56b3d07SJens Wiklander } else { 171*b56b3d07SJens Wiklander rc = PKCS11_CKR_OK; 172*b56b3d07SJens Wiklander LIST_INSERT_HEAD(get_session_objects(session), obj, link); 173*b56b3d07SJens Wiklander } 174*b56b3d07SJens Wiklander 175*b56b3d07SJens Wiklander *out_handle = obj_handle; 176*b56b3d07SJens Wiklander 177*b56b3d07SJens Wiklander return PKCS11_CKR_OK; 178*b56b3d07SJens Wiklander err: 179*b56b3d07SJens Wiklander /* make sure that supplied "head" isn't freed */ 180*b56b3d07SJens Wiklander obj->attributes = NULL; 181*b56b3d07SJens Wiklander handle_put(&session->object_handle_db, obj_handle); 182*b56b3d07SJens Wiklander if (get_bool(head, PKCS11_CKA_TOKEN)) 183*b56b3d07SJens Wiklander cleanup_persistent_object(obj, session->token); 184*b56b3d07SJens Wiklander else 185*b56b3d07SJens Wiklander cleanup_volatile_obj_ref(obj); 186*b56b3d07SJens Wiklander 187*b56b3d07SJens Wiklander return rc; 188*b56b3d07SJens Wiklander } 189*b56b3d07SJens Wiklander 190*b56b3d07SJens Wiklander enum pkcs11_rc entry_create_object(struct pkcs11_client *client, 191*b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 192*b56b3d07SJens Wiklander { 193*b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 194*b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 195*b56b3d07SJens Wiklander TEE_PARAM_TYPE_MEMREF_OUTPUT, 196*b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 197*b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 198*b56b3d07SJens Wiklander TEE_Param *ctrl = params; 199*b56b3d07SJens Wiklander TEE_Param *out = params + 2; 200*b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 201*b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 202*b56b3d07SJens Wiklander struct obj_attrs *head = NULL; 203*b56b3d07SJens Wiklander struct pkcs11_object_head *template = NULL; 204*b56b3d07SJens Wiklander uint32_t session_handle = 0; 205*b56b3d07SJens Wiklander size_t template_size = 0; 206*b56b3d07SJens Wiklander uint32_t obj_handle = 0; 207*b56b3d07SJens Wiklander 208*b56b3d07SJens Wiklander /* 209*b56b3d07SJens Wiklander * Collect the arguments of the request 210*b56b3d07SJens Wiklander */ 211*b56b3d07SJens Wiklander 212*b56b3d07SJens Wiklander if (!client || ptypes != exp_pt || 213*b56b3d07SJens Wiklander out->memref.size != sizeof(obj_handle)) 214*b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 215*b56b3d07SJens Wiklander 216*b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 217*b56b3d07SJens Wiklander 218*b56b3d07SJens Wiklander rc = serialargs_get(&ctrlargs, &session_handle, sizeof(uint32_t)); 219*b56b3d07SJens Wiklander if (rc) 220*b56b3d07SJens Wiklander return rc; 221*b56b3d07SJens Wiklander 222*b56b3d07SJens Wiklander rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 223*b56b3d07SJens Wiklander if (rc) 224*b56b3d07SJens Wiklander return rc; 225*b56b3d07SJens Wiklander 226*b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 227*b56b3d07SJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 228*b56b3d07SJens Wiklander goto out; 229*b56b3d07SJens Wiklander } 230*b56b3d07SJens Wiklander 231*b56b3d07SJens Wiklander session = pkcs11_handle2session(session_handle, client); 232*b56b3d07SJens Wiklander if (!session) { 233*b56b3d07SJens Wiklander rc = PKCS11_CKR_SESSION_HANDLE_INVALID; 234*b56b3d07SJens Wiklander goto out; 235*b56b3d07SJens Wiklander } 236*b56b3d07SJens Wiklander 237*b56b3d07SJens Wiklander template_size = sizeof(*template) + template->attrs_size; 238*b56b3d07SJens Wiklander 239*b56b3d07SJens Wiklander /* 240*b56b3d07SJens Wiklander * Prepare a clean initial state for the requested object attributes. 241*b56b3d07SJens Wiklander * Free temporary template once done. 242*b56b3d07SJens Wiklander */ 243*b56b3d07SJens Wiklander rc = create_attributes_from_template(&head, template, template_size, 244*b56b3d07SJens Wiklander NULL, PKCS11_FUNCTION_IMPORT, 245*b56b3d07SJens Wiklander PKCS11_PROCESSING_IMPORT); 246*b56b3d07SJens Wiklander TEE_Free(template); 247*b56b3d07SJens Wiklander template = NULL; 248*b56b3d07SJens Wiklander if (rc) 249*b56b3d07SJens Wiklander goto out; 250*b56b3d07SJens Wiklander 251*b56b3d07SJens Wiklander /* 252*b56b3d07SJens Wiklander * Check target object attributes match target processing 253*b56b3d07SJens Wiklander * Check target object attributes match token state 254*b56b3d07SJens Wiklander */ 255*b56b3d07SJens Wiklander rc = check_created_attrs_against_processing(PKCS11_PROCESSING_IMPORT, 256*b56b3d07SJens Wiklander head); 257*b56b3d07SJens Wiklander if (rc) 258*b56b3d07SJens Wiklander goto out; 259*b56b3d07SJens Wiklander 260*b56b3d07SJens Wiklander rc = check_created_attrs_against_token(session, head); 261*b56b3d07SJens Wiklander if (rc) 262*b56b3d07SJens Wiklander goto out; 263*b56b3d07SJens Wiklander 264*b56b3d07SJens Wiklander /* 265*b56b3d07SJens Wiklander * At this stage the object is almost created: all its attributes are 266*b56b3d07SJens Wiklander * referenced in @head, including the key value and are assumed 267*b56b3d07SJens Wiklander * reliable. Now need to register it and get a handle for it. 268*b56b3d07SJens Wiklander */ 269*b56b3d07SJens Wiklander rc = create_object(session, head, &obj_handle); 270*b56b3d07SJens Wiklander if (rc) 271*b56b3d07SJens Wiklander goto out; 272*b56b3d07SJens Wiklander 273*b56b3d07SJens Wiklander /* 274*b56b3d07SJens Wiklander * Now obj_handle (through the related struct pkcs11_object 275*b56b3d07SJens Wiklander * instance) owns the serialised buffer that holds the object 276*b56b3d07SJens Wiklander * attributes. We clear reference in head to NULL as the serializer 277*b56b3d07SJens Wiklander * object is now referred from obj_handle. This allows smooth pass 278*b56b3d07SJens Wiklander * through free at function exit. 279*b56b3d07SJens Wiklander */ 280*b56b3d07SJens Wiklander head = NULL; 281*b56b3d07SJens Wiklander 282*b56b3d07SJens Wiklander TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 283*b56b3d07SJens Wiklander out->memref.size = sizeof(obj_handle); 284*b56b3d07SJens Wiklander 285*b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": import object %#"PRIx32, 286*b56b3d07SJens Wiklander session->handle, obj_handle); 287*b56b3d07SJens Wiklander 288*b56b3d07SJens Wiklander out: 289*b56b3d07SJens Wiklander TEE_Free(template); 290*b56b3d07SJens Wiklander TEE_Free(head); 291*b56b3d07SJens Wiklander 292*b56b3d07SJens Wiklander return rc; 293*b56b3d07SJens Wiklander } 294*b56b3d07SJens Wiklander 295*b56b3d07SJens Wiklander enum pkcs11_rc entry_destroy_object(struct pkcs11_client *client, 296*b56b3d07SJens Wiklander uint32_t ptypes, TEE_Param *params) 297*b56b3d07SJens Wiklander { 298*b56b3d07SJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 299*b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 300*b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE, 301*b56b3d07SJens Wiklander TEE_PARAM_TYPE_NONE); 302*b56b3d07SJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 303*b56b3d07SJens Wiklander TEE_Param *ctrl = params; 304*b56b3d07SJens Wiklander struct serialargs ctrlargs = { }; 305*b56b3d07SJens Wiklander uint32_t object_handle = 0; 306*b56b3d07SJens Wiklander struct pkcs11_session *session = NULL; 307*b56b3d07SJens Wiklander struct pkcs11_object *object = NULL; 308*b56b3d07SJens Wiklander uint32_t session_handle = 0; 309*b56b3d07SJens Wiklander 310*b56b3d07SJens Wiklander if (!client || ptypes != exp_pt) 311*b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 312*b56b3d07SJens Wiklander 313*b56b3d07SJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 314*b56b3d07SJens Wiklander 315*b56b3d07SJens Wiklander rc = serialargs_get_u32(&ctrlargs, &session_handle); 316*b56b3d07SJens Wiklander if (rc) 317*b56b3d07SJens Wiklander return rc; 318*b56b3d07SJens Wiklander 319*b56b3d07SJens Wiklander rc = serialargs_get_u32(&ctrlargs, &object_handle); 320*b56b3d07SJens Wiklander if (rc) 321*b56b3d07SJens Wiklander return rc; 322*b56b3d07SJens Wiklander 323*b56b3d07SJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 324*b56b3d07SJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 325*b56b3d07SJens Wiklander 326*b56b3d07SJens Wiklander session = pkcs11_handle2session(session_handle, client); 327*b56b3d07SJens Wiklander if (!session) 328*b56b3d07SJens Wiklander return PKCS11_CKR_SESSION_HANDLE_INVALID; 329*b56b3d07SJens Wiklander 330*b56b3d07SJens Wiklander object = pkcs11_handle2object(object_handle, session); 331*b56b3d07SJens Wiklander if (!object) 332*b56b3d07SJens Wiklander return PKCS11_CKR_OBJECT_HANDLE_INVALID; 333*b56b3d07SJens Wiklander 334*b56b3d07SJens Wiklander destroy_object(session, object, false); 335*b56b3d07SJens Wiklander 336*b56b3d07SJens Wiklander DMSG("PKCS11 session %"PRIu32": destroy object %#"PRIx32, 337*b56b3d07SJens Wiklander session->handle, object_handle); 338*b56b3d07SJens Wiklander 339*b56b3d07SJens Wiklander return rc; 340*b56b3d07SJens Wiklander } 341