1512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2512cbf1dSJens Wiklander /* 3512cbf1dSJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 4512cbf1dSJens Wiklander */ 5512cbf1dSJens Wiklander 6512cbf1dSJens Wiklander #include <assert.h> 7512cbf1dSJens Wiklander #include <pkcs11_ta.h> 8512cbf1dSJens Wiklander #include <string.h> 9512cbf1dSJens Wiklander #include <tee_api_defines.h> 10512cbf1dSJens Wiklander #include <tee_internal_api.h> 11512cbf1dSJens Wiklander #include <tee_internal_api_extensions.h> 12512cbf1dSJens Wiklander #include <util.h> 13512cbf1dSJens Wiklander 14512cbf1dSJens Wiklander #include "attributes.h" 15512cbf1dSJens Wiklander #include "object.h" 16512cbf1dSJens Wiklander #include "pkcs11_attributes.h" 17512cbf1dSJens Wiklander #include "pkcs11_helpers.h" 18512cbf1dSJens Wiklander #include "pkcs11_token.h" 19512cbf1dSJens Wiklander #include "processing.h" 20512cbf1dSJens Wiklander #include "serializer.h" 21512cbf1dSJens Wiklander 22512cbf1dSJens Wiklander static enum pkcs11_rc get_ready_session(struct pkcs11_session *session) 23512cbf1dSJens Wiklander { 24512cbf1dSJens Wiklander if (session_is_active(session)) 25512cbf1dSJens Wiklander return PKCS11_CKR_OPERATION_ACTIVE; 26512cbf1dSJens Wiklander 27512cbf1dSJens Wiklander return PKCS11_CKR_OK; 28512cbf1dSJens Wiklander } 29512cbf1dSJens Wiklander 30eb6141b6SVesa Jääskeläinen static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd) 31eb6141b6SVesa Jääskeläinen { 32eb6141b6SVesa Jääskeläinen switch (cmd) { 33eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_UPDATE: 34eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_ONESHOT: 35eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_FINAL: 36eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_ENCRYPT; 37eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_UPDATE: 38eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_ONESHOT: 39eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_FINAL: 40eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_DECRYPT; 41eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_ONESHOT: 42eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_UPDATE: 43eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_FINAL: 44eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_SIGN; 45eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_ONESHOT: 46eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_UPDATE: 47eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_FINAL: 48eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_VERIFY; 499e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_UPDATE: 509e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_KEY: 519e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_ONESHOT: 529e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_FINAL: 539e91a619SVesa Jääskeläinen return PKCS11_FUNCTION_DIGEST; 54eb6141b6SVesa Jääskeläinen default: 55eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_UNKNOWN; 56eb6141b6SVesa Jääskeläinen } 57eb6141b6SVesa Jääskeläinen } 58eb6141b6SVesa Jääskeläinen 59512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function, 60512cbf1dSJens Wiklander enum pkcs11_proc_state state) 61512cbf1dSJens Wiklander { 62512cbf1dSJens Wiklander switch (function) { 63512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT: 64512cbf1dSJens Wiklander return state == PKCS11_SESSION_ENCRYPTING || 65512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING || 66512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 67512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT: 68512cbf1dSJens Wiklander return state == PKCS11_SESSION_DECRYPTING || 69512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_DIGESTING || 70512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 71512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST: 72512cbf1dSJens Wiklander return state == PKCS11_SESSION_DIGESTING || 73512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING; 74512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN: 75512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING || 76512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 77512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY: 78512cbf1dSJens Wiklander return state == PKCS11_SESSION_VERIFYING || 79512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 80512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN_RECOVER: 81512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 82512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY_RECOVER: 83512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 84512cbf1dSJens Wiklander default: 85512cbf1dSJens Wiklander TEE_Panic(function); 86512cbf1dSJens Wiklander return false; 87512cbf1dSJens Wiklander } 88512cbf1dSJens Wiklander } 89512cbf1dSJens Wiklander 90512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session, 91512cbf1dSJens Wiklander enum processing_func function) 92512cbf1dSJens Wiklander { 93512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; 94512cbf1dSJens Wiklander 95512cbf1dSJens Wiklander if (session->processing && 96512cbf1dSJens Wiklander func_matches_state(function, session->processing->state)) 97512cbf1dSJens Wiklander rc = PKCS11_CKR_OK; 98512cbf1dSJens Wiklander 99512cbf1dSJens Wiklander return rc; 100512cbf1dSJens Wiklander } 101512cbf1dSJens Wiklander 102512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session) 103512cbf1dSJens Wiklander { 104512cbf1dSJens Wiklander if (!session->processing) 105512cbf1dSJens Wiklander return; 106512cbf1dSJens Wiklander 107*63778faaSEtienne Carriere switch (session->processing->mecha_type) { 108*63778faaSEtienne Carriere case PKCS11_CKM_AES_GCM: 109*63778faaSEtienne Carriere tee_release_gcm_operation(session); 110*63778faaSEtienne Carriere break; 111*63778faaSEtienne Carriere default: 112*63778faaSEtienne Carriere break; 113*63778faaSEtienne Carriere } 114*63778faaSEtienne Carriere 115fb279d8bSVesa Jääskeläinen if (session->processing->tee_hash_op_handle != TEE_HANDLE_NULL) { 116fb279d8bSVesa Jääskeläinen TEE_FreeOperation(session->processing->tee_hash_op_handle); 117fb279d8bSVesa Jääskeläinen session->processing->tee_hash_op_handle = TEE_HANDLE_NULL; 118fb279d8bSVesa Jääskeläinen session->processing->tee_hash_algo = 0; 119fb279d8bSVesa Jääskeläinen } 120fb279d8bSVesa Jääskeläinen 121512cbf1dSJens Wiklander if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 122512cbf1dSJens Wiklander TEE_FreeOperation(session->processing->tee_op_handle); 123512cbf1dSJens Wiklander session->processing->tee_op_handle = TEE_HANDLE_NULL; 124512cbf1dSJens Wiklander } 125512cbf1dSJens Wiklander 126*63778faaSEtienne Carriere if (session->processing->tee_op_handle2 != TEE_HANDLE_NULL) { 127*63778faaSEtienne Carriere TEE_FreeOperation(session->processing->tee_op_handle2); 128*63778faaSEtienne Carriere session->processing->tee_op_handle2 = TEE_HANDLE_NULL; 129*63778faaSEtienne Carriere } 130*63778faaSEtienne Carriere 1312158ea6cSRuchika Gupta TEE_Free(session->processing->extra_ctx); 1322158ea6cSRuchika Gupta 133512cbf1dSJens Wiklander TEE_Free(session->processing); 134512cbf1dSJens Wiklander session->processing = NULL; 135512cbf1dSJens Wiklander } 136512cbf1dSJens Wiklander 137512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj) 138512cbf1dSJens Wiklander { 139fb279d8bSVesa Jääskeläinen void *a_ptr = NULL; 140512cbf1dSJens Wiklander uint32_t a_size = 0; 141512cbf1dSJens Wiklander struct obj_attrs *attrs = obj->attributes; 142512cbf1dSJens Wiklander 143512cbf1dSJens Wiklander switch (get_key_type(attrs)) { 144512cbf1dSJens Wiklander case PKCS11_CKK_AES: 145689f4e5bSRuchika Gupta case PKCS11_CKK_GENERIC_SECRET: 146689f4e5bSRuchika Gupta case PKCS11_CKK_MD5_HMAC: 147689f4e5bSRuchika Gupta case PKCS11_CKK_SHA_1_HMAC: 148689f4e5bSRuchika Gupta case PKCS11_CKK_SHA224_HMAC: 149689f4e5bSRuchika Gupta case PKCS11_CKK_SHA256_HMAC: 150689f4e5bSRuchika Gupta case PKCS11_CKK_SHA384_HMAC: 151689f4e5bSRuchika Gupta case PKCS11_CKK_SHA512_HMAC: 152512cbf1dSJens Wiklander if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 153512cbf1dSJens Wiklander return 0; 154512cbf1dSJens Wiklander 155512cbf1dSJens Wiklander return a_size * 8; 1560442c956SVesa Jääskeläinen case PKCS11_CKK_RSA: 1570442c956SVesa Jääskeläinen if (get_attribute_ptr(attrs, PKCS11_CKA_MODULUS, NULL, &a_size)) 1580442c956SVesa Jääskeläinen return 0; 1590442c956SVesa Jääskeläinen 1600442c956SVesa Jääskeläinen return a_size * 8; 161fb279d8bSVesa Jääskeläinen case PKCS11_CKK_EC: 162fb279d8bSVesa Jääskeläinen if (get_attribute_ptr(attrs, PKCS11_CKA_EC_PARAMS, 163fb279d8bSVesa Jääskeläinen &a_ptr, &a_size) || !a_ptr) 164fb279d8bSVesa Jääskeläinen return 0; 165fb279d8bSVesa Jääskeläinen 166fb279d8bSVesa Jääskeläinen return ec_params2tee_keysize(a_ptr, a_size); 167ecd7f426SValerii Chubar case PKCS11_CKK_EC_EDWARDS: 168ecd7f426SValerii Chubar if (get_attribute_ptr(attrs, PKCS11_CKA_EC_POINT, NULL, 169ecd7f426SValerii Chubar &a_size)) 170ecd7f426SValerii Chubar return 0; 171ecd7f426SValerii Chubar 172ecd7f426SValerii Chubar return a_size * 8; 173512cbf1dSJens Wiklander default: 174512cbf1dSJens Wiklander TEE_Panic(0); 175512cbf1dSJens Wiklander return 0; 176512cbf1dSJens Wiklander } 177512cbf1dSJens Wiklander } 178512cbf1dSJens Wiklander 179fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) 180fa247a2aSRuchika Gupta { 181fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 182fa247a2aSRuchika Gupta uint32_t data_size = 0; 183fa247a2aSRuchika Gupta uint32_t value_len = 0; 184fa247a2aSRuchika Gupta void *value = NULL; 185bcac2127SMarouene Boubakri void *data = NULL; 186fa247a2aSRuchika Gupta 187fa247a2aSRuchika Gupta if (!*head) 188fa247a2aSRuchika Gupta return PKCS11_CKR_TEMPLATE_INCONSISTENT; 189fa247a2aSRuchika Gupta 190fa247a2aSRuchika Gupta rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); 191fa247a2aSRuchika Gupta if (rc || data_size != sizeof(uint32_t)) { 192fa247a2aSRuchika Gupta DMSG("%s", rc ? "No attribute value_len found" : 193fa247a2aSRuchika Gupta "Invalid size for attribute VALUE_LEN"); 194fa247a2aSRuchika Gupta 195fa247a2aSRuchika Gupta return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; 196fa247a2aSRuchika Gupta } 197fa247a2aSRuchika Gupta TEE_MemMove(&value_len, data, data_size); 198fa247a2aSRuchika Gupta 199fa247a2aSRuchika Gupta /* Remove the default empty value attribute if found */ 200fa247a2aSRuchika Gupta rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); 201fa247a2aSRuchika Gupta if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) 202fa247a2aSRuchika Gupta return PKCS11_CKR_GENERAL_ERROR; 203fa247a2aSRuchika Gupta 204fa247a2aSRuchika Gupta value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 205fa247a2aSRuchika Gupta if (!value) 206fa247a2aSRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY; 207fa247a2aSRuchika Gupta 208fa247a2aSRuchika Gupta TEE_GenerateRandom(value, value_len); 209fa247a2aSRuchika Gupta 210fa247a2aSRuchika Gupta rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); 211fa247a2aSRuchika Gupta 212bcac2127SMarouene Boubakri if (rc == PKCS11_CKR_OK) 213bcac2127SMarouene Boubakri rc = set_check_value_attr(head); 214bcac2127SMarouene Boubakri 215fa247a2aSRuchika Gupta TEE_Free(value); 216fa247a2aSRuchika Gupta 217fa247a2aSRuchika Gupta return rc; 218fa247a2aSRuchika Gupta } 219fa247a2aSRuchika Gupta 220fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, 221fa247a2aSRuchika Gupta uint32_t ptypes, TEE_Param *params) 222fa247a2aSRuchika Gupta { 223fa247a2aSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 224fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE, 225fa247a2aSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 226fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE); 227fa247a2aSRuchika Gupta TEE_Param *ctrl = params; 228fa247a2aSRuchika Gupta TEE_Param *out = params + 2; 229fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 230fa247a2aSRuchika Gupta struct serialargs ctrlargs = { }; 231fa247a2aSRuchika Gupta struct pkcs11_session *session = NULL; 232fa247a2aSRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 233fa247a2aSRuchika Gupta struct obj_attrs *head = NULL; 234fa247a2aSRuchika Gupta struct pkcs11_object_head *template = NULL; 235fa247a2aSRuchika Gupta size_t template_size = 0; 236fa247a2aSRuchika Gupta uint32_t obj_handle = 0; 237fa247a2aSRuchika Gupta 238fa247a2aSRuchika Gupta if (!client || ptypes != exp_pt || 239fa247a2aSRuchika Gupta out->memref.size != sizeof(obj_handle)) 240fa247a2aSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 241fa247a2aSRuchika Gupta 242fa247a2aSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 243fa247a2aSRuchika Gupta 244fa247a2aSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 245fa247a2aSRuchika Gupta if (rc) 246fa247a2aSRuchika Gupta return rc; 247fa247a2aSRuchika Gupta 248fa247a2aSRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 249fa247a2aSRuchika Gupta if (rc) 250fa247a2aSRuchika Gupta goto out; 251fa247a2aSRuchika Gupta 252fa247a2aSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 253fa247a2aSRuchika Gupta if (rc) 254fa247a2aSRuchika Gupta goto out; 255fa247a2aSRuchika Gupta 256fa247a2aSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 257fa247a2aSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 258fa247a2aSRuchika Gupta goto out; 259fa247a2aSRuchika Gupta } 260fa247a2aSRuchika Gupta 261fa247a2aSRuchika Gupta rc = get_ready_session(session); 262fa247a2aSRuchika Gupta if (rc) 263fa247a2aSRuchika Gupta goto out; 264fa247a2aSRuchika Gupta 265fa247a2aSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 266fa247a2aSRuchika Gupta 267fa247a2aSRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 268fa247a2aSRuchika Gupta PKCS11_FUNCTION_GENERATE, 269fa247a2aSRuchika Gupta PKCS11_FUNC_STEP_INIT); 270fa247a2aSRuchika Gupta if (rc) { 271fa247a2aSRuchika Gupta DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); 272fa247a2aSRuchika Gupta goto out; 273fa247a2aSRuchika Gupta } 274fa247a2aSRuchika Gupta 275fa247a2aSRuchika Gupta /* 276fa247a2aSRuchika Gupta * Prepare a clean initial state for the requested object attributes. 277fa247a2aSRuchika Gupta * Free temporary template once done. 278fa247a2aSRuchika Gupta */ 279fa247a2aSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 280fa247a2aSRuchika Gupta NULL, PKCS11_FUNCTION_GENERATE, 2814cfce748SRuchika Gupta proc_params->id, 2824cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 283fa247a2aSRuchika Gupta if (rc) 284fa247a2aSRuchika Gupta goto out; 285fa247a2aSRuchika Gupta 286fa247a2aSRuchika Gupta TEE_Free(template); 287fa247a2aSRuchika Gupta template = NULL; 288fa247a2aSRuchika Gupta 289fa247a2aSRuchika Gupta rc = check_created_attrs(head, NULL); 290fa247a2aSRuchika Gupta if (rc) 291fa247a2aSRuchika Gupta goto out; 292fa247a2aSRuchika Gupta 293fa247a2aSRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 294fa247a2aSRuchika Gupta if (rc) 295fa247a2aSRuchika Gupta goto out; 296fa247a2aSRuchika Gupta 297fa247a2aSRuchika Gupta rc = check_created_attrs_against_token(session, head); 298fa247a2aSRuchika Gupta if (rc) 299fa247a2aSRuchika Gupta goto out; 300fa247a2aSRuchika Gupta 301fa247a2aSRuchika Gupta /* 302fa247a2aSRuchika Gupta * Execute target processing and add value as attribute 303fa247a2aSRuchika Gupta * PKCS11_CKA_VALUE. Symm key generation: depends on target 304fa247a2aSRuchika Gupta * processing to be used. 305fa247a2aSRuchika Gupta */ 306fa247a2aSRuchika Gupta switch (proc_params->id) { 307fa247a2aSRuchika Gupta case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: 308fa247a2aSRuchika Gupta case PKCS11_CKM_AES_KEY_GEN: 309fa247a2aSRuchika Gupta /* Generate random of size specified by attribute VALUE_LEN */ 310fa247a2aSRuchika Gupta rc = generate_random_key_value(&head); 311fa247a2aSRuchika Gupta if (rc) 312fa247a2aSRuchika Gupta goto out; 313fa247a2aSRuchika Gupta break; 314fa247a2aSRuchika Gupta 315fa247a2aSRuchika Gupta default: 316fa247a2aSRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 317fa247a2aSRuchika Gupta goto out; 318fa247a2aSRuchika Gupta } 319fa247a2aSRuchika Gupta 320fa247a2aSRuchika Gupta TEE_Free(proc_params); 321fa247a2aSRuchika Gupta proc_params = NULL; 322fa247a2aSRuchika Gupta 323fa247a2aSRuchika Gupta /* 324fa247a2aSRuchika Gupta * Object is ready, register it and return a handle. 325fa247a2aSRuchika Gupta */ 326fa247a2aSRuchika Gupta rc = create_object(session, head, &obj_handle); 327fa247a2aSRuchika Gupta if (rc) 328fa247a2aSRuchika Gupta goto out; 329fa247a2aSRuchika Gupta 330fa247a2aSRuchika Gupta /* 331fa247a2aSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 332fa247a2aSRuchika Gupta * owns the serialized buffer that holds the object attributes. 333fa247a2aSRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 334fa247a2aSRuchika Gupta * be freed at function out. 335fa247a2aSRuchika Gupta */ 336fa247a2aSRuchika Gupta head = NULL; 337fa247a2aSRuchika Gupta 338fa247a2aSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 339fa247a2aSRuchika Gupta out->memref.size = sizeof(obj_handle); 340fa247a2aSRuchika Gupta 341fa247a2aSRuchika Gupta DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, 342fa247a2aSRuchika Gupta session->handle, obj_handle); 343fa247a2aSRuchika Gupta 344fa247a2aSRuchika Gupta out: 345fa247a2aSRuchika Gupta TEE_Free(proc_params); 346fa247a2aSRuchika Gupta TEE_Free(template); 347fa247a2aSRuchika Gupta TEE_Free(head); 348fa247a2aSRuchika Gupta 349fa247a2aSRuchika Gupta return rc; 350fa247a2aSRuchika Gupta } 351fa247a2aSRuchika Gupta 352013934d8SVesa Jääskeläinen enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj, 353013934d8SVesa Jääskeläinen uint32_t attribute, 354013934d8SVesa Jääskeläinen void **data, size_t *size) 355013934d8SVesa Jääskeläinen { 356013934d8SVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC; 357013934d8SVesa Jääskeläinen void *ptr = NULL; 358c7f1b4f7SJens Wiklander size_t sz = 0; 359013934d8SVesa Jääskeläinen 360013934d8SVesa Jääskeläinen res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz); 361013934d8SVesa Jääskeläinen if (res != TEE_ERROR_SHORT_BUFFER) 362013934d8SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED; 363013934d8SVesa Jääskeläinen 364013934d8SVesa Jääskeläinen ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO); 365013934d8SVesa Jääskeläinen if (!ptr) 366013934d8SVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY; 367013934d8SVesa Jääskeläinen 368013934d8SVesa Jääskeläinen res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz); 369013934d8SVesa Jääskeläinen if (res) { 370013934d8SVesa Jääskeläinen TEE_Free(ptr); 371013934d8SVesa Jääskeläinen } else { 372013934d8SVesa Jääskeläinen *data = ptr; 373013934d8SVesa Jääskeläinen *size = sz; 374013934d8SVesa Jääskeläinen } 375013934d8SVesa Jääskeläinen 376013934d8SVesa Jääskeläinen return tee2pkcs_error(res); 377013934d8SVesa Jääskeläinen } 378013934d8SVesa Jääskeläinen 379013934d8SVesa Jääskeläinen enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head, 380013934d8SVesa Jääskeläinen uint32_t pkcs11_id, 381013934d8SVesa Jääskeläinen TEE_ObjectHandle tee_obj, 382013934d8SVesa Jääskeläinen uint32_t tee_id) 383013934d8SVesa Jääskeläinen { 384013934d8SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 385013934d8SVesa Jääskeläinen void *a_ptr = NULL; 386013934d8SVesa Jääskeläinen size_t a_size = 0; 387013934d8SVesa Jääskeläinen 388013934d8SVesa Jääskeläinen rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size); 389013934d8SVesa Jääskeläinen if (rc) 390013934d8SVesa Jääskeläinen goto out; 391013934d8SVesa Jääskeläinen 392013934d8SVesa Jääskeläinen rc = add_attribute(head, pkcs11_id, a_ptr, a_size); 393013934d8SVesa Jääskeläinen 394013934d8SVesa Jääskeläinen TEE_Free(a_ptr); 395013934d8SVesa Jääskeläinen 396013934d8SVesa Jääskeläinen out: 397013934d8SVesa Jääskeläinen if (rc) 398013934d8SVesa Jääskeläinen EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s", 399013934d8SVesa Jääskeläinen tee_id, pkcs11_id, id2str_attr(pkcs11_id)); 400013934d8SVesa Jääskeläinen return rc; 401013934d8SVesa Jääskeläinen } 402013934d8SVesa Jääskeläinen 403013934d8SVesa Jääskeläinen enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client, 404013934d8SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params) 405013934d8SVesa Jääskeläinen { 406013934d8SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 407013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 408013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_MEMREF_OUTPUT, 409013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 410013934d8SVesa Jääskeläinen TEE_Param *ctrl = params; 411013934d8SVesa Jääskeläinen TEE_Param *out = params + 2; 412013934d8SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 413013934d8SVesa Jääskeläinen struct serialargs ctrlargs = { }; 414013934d8SVesa Jääskeläinen struct pkcs11_session *session = NULL; 415013934d8SVesa Jääskeläinen struct pkcs11_attribute_head *proc_params = NULL; 416013934d8SVesa Jääskeläinen struct obj_attrs *pub_head = NULL; 417013934d8SVesa Jääskeläinen struct obj_attrs *priv_head = NULL; 418013934d8SVesa Jääskeläinen struct pkcs11_object_head *pub_template = NULL; 419013934d8SVesa Jääskeläinen struct pkcs11_object_head *priv_template = NULL; 420013934d8SVesa Jääskeläinen struct pkcs11_object *object = NULL; 421013934d8SVesa Jääskeläinen size_t pub_template_size = 0; 422013934d8SVesa Jääskeläinen size_t priv_template_size = 0; 423013934d8SVesa Jääskeläinen uint32_t pubkey_handle = 0; 424013934d8SVesa Jääskeläinen uint32_t privkey_handle = 0; 425013934d8SVesa Jääskeläinen uint32_t *hdl_ptr = NULL; 426013934d8SVesa Jääskeläinen size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle); 427013934d8SVesa Jääskeläinen 428013934d8SVesa Jääskeläinen if (!client || ptypes != exp_pt || out->memref.size != out_ref_size) 429013934d8SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 430013934d8SVesa Jääskeläinen 431013934d8SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 432013934d8SVesa Jääskeläinen 433013934d8SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 434013934d8SVesa Jääskeläinen if (rc) 435013934d8SVesa Jääskeläinen return rc; 436013934d8SVesa Jääskeläinen 437013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 438013934d8SVesa Jääskeläinen if (rc) 439013934d8SVesa Jääskeläinen goto out; 440013934d8SVesa Jääskeläinen 441013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template); 442013934d8SVesa Jääskeläinen if (rc) 443013934d8SVesa Jääskeläinen goto out; 444013934d8SVesa Jääskeläinen 445013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template); 446013934d8SVesa Jääskeläinen if (rc) 447013934d8SVesa Jääskeläinen goto out; 448013934d8SVesa Jääskeläinen 449013934d8SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) { 450013934d8SVesa Jääskeläinen rc = PKCS11_CKR_ARGUMENTS_BAD; 451013934d8SVesa Jääskeläinen goto out; 452013934d8SVesa Jääskeläinen } 453013934d8SVesa Jääskeläinen 454013934d8SVesa Jääskeläinen rc = get_ready_session(session); 455013934d8SVesa Jääskeläinen if (rc) 456013934d8SVesa Jääskeläinen goto out; 457013934d8SVesa Jääskeläinen 458013934d8SVesa Jääskeläinen rc = check_mechanism_against_processing(session, proc_params->id, 459013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR, 460013934d8SVesa Jääskeläinen PKCS11_FUNC_STEP_INIT); 461013934d8SVesa Jääskeläinen if (rc) 462013934d8SVesa Jääskeläinen goto out; 463013934d8SVesa Jääskeläinen 464013934d8SVesa Jääskeläinen pub_template_size = sizeof(*pub_template) + pub_template->attrs_size; 465013934d8SVesa Jääskeläinen 466013934d8SVesa Jääskeläinen rc = create_attributes_from_template(&pub_head, pub_template, 467013934d8SVesa Jääskeläinen pub_template_size, NULL, 468013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR, 469013934d8SVesa Jääskeläinen proc_params->id, 470013934d8SVesa Jääskeläinen PKCS11_CKO_PUBLIC_KEY); 471013934d8SVesa Jääskeläinen if (rc) 472013934d8SVesa Jääskeläinen goto out; 473013934d8SVesa Jääskeläinen 474013934d8SVesa Jääskeläinen TEE_Free(pub_template); 475013934d8SVesa Jääskeläinen pub_template = NULL; 476013934d8SVesa Jääskeläinen 477013934d8SVesa Jääskeläinen priv_template_size = sizeof(*priv_template) + 478013934d8SVesa Jääskeläinen priv_template->attrs_size; 479013934d8SVesa Jääskeläinen 480013934d8SVesa Jääskeläinen rc = create_attributes_from_template(&priv_head, priv_template, 481013934d8SVesa Jääskeläinen priv_template_size, NULL, 482013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR, 483013934d8SVesa Jääskeläinen proc_params->id, 484013934d8SVesa Jääskeläinen PKCS11_CKO_PRIVATE_KEY); 485013934d8SVesa Jääskeläinen if (rc) 486013934d8SVesa Jääskeläinen goto out; 487013934d8SVesa Jääskeläinen 488013934d8SVesa Jääskeläinen TEE_Free(priv_template); 489013934d8SVesa Jääskeläinen priv_template = NULL; 490013934d8SVesa Jääskeläinen 491013934d8SVesa Jääskeläinen /* Generate CKA_ID for keys if not specified by the templates */ 492013934d8SVesa Jääskeläinen rc = add_missing_attribute_id(&pub_head, &priv_head); 493013934d8SVesa Jääskeläinen if (rc) 494013934d8SVesa Jääskeläinen goto out; 495013934d8SVesa Jääskeläinen 496013934d8SVesa Jääskeläinen /* Check created object against processing and token state */ 497013934d8SVesa Jääskeläinen rc = check_created_attrs(pub_head, priv_head); 498013934d8SVesa Jääskeläinen if (rc) 499013934d8SVesa Jääskeläinen goto out; 500013934d8SVesa Jääskeläinen 501013934d8SVesa Jääskeläinen rc = check_created_attrs_against_processing(proc_params->id, pub_head); 502013934d8SVesa Jääskeläinen if (rc) 503013934d8SVesa Jääskeläinen goto out; 504013934d8SVesa Jääskeläinen 505013934d8SVesa Jääskeläinen rc = check_created_attrs_against_processing(proc_params->id, 506013934d8SVesa Jääskeläinen priv_head); 507013934d8SVesa Jääskeläinen if (rc) 508013934d8SVesa Jääskeläinen goto out; 509013934d8SVesa Jääskeläinen 510013934d8SVesa Jääskeläinen rc = check_created_attrs_against_token(session, pub_head); 511013934d8SVesa Jääskeläinen if (rc) 512013934d8SVesa Jääskeläinen goto out; 513013934d8SVesa Jääskeläinen 514013934d8SVesa Jääskeläinen rc = check_access_attrs_against_token(session, pub_head); 515013934d8SVesa Jääskeläinen if (rc) 516013934d8SVesa Jääskeläinen goto out; 517013934d8SVesa Jääskeläinen 518013934d8SVesa Jääskeläinen rc = check_created_attrs_against_token(session, priv_head); 519013934d8SVesa Jääskeläinen if (rc) 520013934d8SVesa Jääskeläinen goto out; 521013934d8SVesa Jääskeläinen 522013934d8SVesa Jääskeläinen rc = check_access_attrs_against_token(session, priv_head); 523013934d8SVesa Jääskeläinen if (rc) 524013934d8SVesa Jääskeläinen goto out; 525013934d8SVesa Jääskeläinen 526013934d8SVesa Jääskeläinen /* Generate key pair */ 527013934d8SVesa Jääskeläinen switch (proc_params->id) { 52803e07432SValerii Chubar case PKCS11_CKM_EC_EDWARDS_KEY_PAIR_GEN: 52903e07432SValerii Chubar rc = generate_eddsa_keys(proc_params, &pub_head, &priv_head); 53003e07432SValerii Chubar break; 53102b16804SVesa Jääskeläinen case PKCS11_CKM_EC_KEY_PAIR_GEN: 53202b16804SVesa Jääskeläinen rc = generate_ec_keys(proc_params, &pub_head, &priv_head); 53302b16804SVesa Jääskeläinen break; 53486922832SVesa Jääskeläinen case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN: 53586922832SVesa Jääskeläinen rc = generate_rsa_keys(proc_params, &pub_head, &priv_head); 53686922832SVesa Jääskeläinen break; 537013934d8SVesa Jääskeläinen default: 538013934d8SVesa Jääskeläinen rc = PKCS11_CKR_MECHANISM_INVALID; 539013934d8SVesa Jääskeläinen break; 540013934d8SVesa Jääskeläinen } 541013934d8SVesa Jääskeläinen if (rc) 542013934d8SVesa Jääskeläinen goto out; 543013934d8SVesa Jääskeläinen 544013934d8SVesa Jääskeläinen TEE_Free(proc_params); 545013934d8SVesa Jääskeläinen proc_params = NULL; 546013934d8SVesa Jääskeläinen 547013934d8SVesa Jääskeläinen /* 548013934d8SVesa Jääskeläinen * Object is ready, register it and return a handle. 549013934d8SVesa Jääskeläinen */ 550013934d8SVesa Jääskeläinen rc = create_object(session, pub_head, &pubkey_handle); 551013934d8SVesa Jääskeläinen if (rc) 552013934d8SVesa Jääskeläinen goto out; 553013934d8SVesa Jääskeläinen 554013934d8SVesa Jääskeläinen /* 555013934d8SVesa Jääskeläinen * Now obj_handle (through the related struct pkcs11_object instance) 556013934d8SVesa Jääskeläinen * owns the serialized buffer that holds the object attributes. 557013934d8SVesa Jääskeläinen * We reset local pub_head to NULL to mark that ownership has been 558013934d8SVesa Jääskeläinen * transferred. 559013934d8SVesa Jääskeläinen */ 560013934d8SVesa Jääskeläinen pub_head = NULL; 561013934d8SVesa Jääskeläinen 562013934d8SVesa Jääskeläinen rc = create_object(session, priv_head, &privkey_handle); 563013934d8SVesa Jääskeläinen if (rc) 564013934d8SVesa Jääskeläinen goto out; 565013934d8SVesa Jääskeläinen 566013934d8SVesa Jääskeläinen /* Ownership has been transferred so mark it with NULL */ 567013934d8SVesa Jääskeläinen priv_head = NULL; 568013934d8SVesa Jääskeläinen 569013934d8SVesa Jääskeläinen hdl_ptr = (uint32_t *)out->memref.buffer; 570013934d8SVesa Jääskeläinen 571013934d8SVesa Jääskeläinen TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle)); 572013934d8SVesa Jääskeläinen TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle)); 573013934d8SVesa Jääskeläinen 574013934d8SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32, 575013934d8SVesa Jääskeläinen session->handle, privkey_handle, pubkey_handle); 576013934d8SVesa Jääskeläinen 5772f7f001aSSergiy Kibrik pubkey_handle = 0; 5782f7f001aSSergiy Kibrik privkey_handle = 0; 579013934d8SVesa Jääskeläinen out: 580013934d8SVesa Jääskeläinen if (pubkey_handle) { 581013934d8SVesa Jääskeläinen object = pkcs11_handle2object(pubkey_handle, session); 582013934d8SVesa Jääskeläinen if (!object) 583013934d8SVesa Jääskeläinen TEE_Panic(0); 584013934d8SVesa Jääskeläinen destroy_object(session, object, false); 585013934d8SVesa Jääskeläinen } 586013934d8SVesa Jääskeläinen TEE_Free(priv_head); 587013934d8SVesa Jääskeläinen TEE_Free(pub_head); 588013934d8SVesa Jääskeläinen TEE_Free(priv_template); 589013934d8SVesa Jääskeläinen TEE_Free(pub_template); 590013934d8SVesa Jääskeläinen TEE_Free(proc_params); 591013934d8SVesa Jääskeläinen 592013934d8SVesa Jääskeläinen return rc; 593013934d8SVesa Jääskeläinen } 594013934d8SVesa Jääskeläinen 595512cbf1dSJens Wiklander /* 596512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing 597512cbf1dSJens Wiklander * 598512cbf1dSJens Wiklander * @client = client reference 599512cbf1dSJens Wiklander * @ptype = Invocation parameter types 600512cbf1dSJens Wiklander * @params = Invocation parameters reference 601512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 602512cbf1dSJens Wiklander */ 603512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 604512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 605512cbf1dSJens Wiklander enum processing_func function) 606512cbf1dSJens Wiklander { 607512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 608512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 609512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 610512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE); 611512cbf1dSJens Wiklander TEE_Param *ctrl = params; 612512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 613512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 614512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 615512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL; 616512cbf1dSJens Wiklander uint32_t key_handle = 0; 617512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL; 618512cbf1dSJens Wiklander 619512cbf1dSJens Wiklander if (!client || ptypes != exp_pt) 620512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 621512cbf1dSJens Wiklander 622512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 623512cbf1dSJens Wiklander 624512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 625512cbf1dSJens Wiklander if (rc) 626512cbf1dSJens Wiklander return rc; 627512cbf1dSJens Wiklander 6289e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) { 629512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 630512cbf1dSJens Wiklander if (rc) 631512cbf1dSJens Wiklander return rc; 6329e91a619SVesa Jääskeläinen } 633512cbf1dSJens Wiklander 634512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 635512cbf1dSJens Wiklander if (rc) 636512cbf1dSJens Wiklander return rc; 637512cbf1dSJens Wiklander 638512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 639512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 6408abbc8f7SVesa Jääskeläinen goto out_free; 641512cbf1dSJens Wiklander } 642512cbf1dSJens Wiklander 643512cbf1dSJens Wiklander rc = get_ready_session(session); 644512cbf1dSJens Wiklander if (rc) 6458abbc8f7SVesa Jääskeläinen goto out_free; 646512cbf1dSJens Wiklander 6479e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) { 648512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session); 649512cbf1dSJens Wiklander if (!obj) { 650512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID; 6518abbc8f7SVesa Jääskeläinen goto out_free; 652512cbf1dSJens Wiklander } 6539e91a619SVesa Jääskeläinen } 654512cbf1dSJens Wiklander 655512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL); 656512cbf1dSJens Wiklander if (rc) 657512cbf1dSJens Wiklander goto out; 658512cbf1dSJens Wiklander 659512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id, 660512cbf1dSJens Wiklander function, 661512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT); 662512cbf1dSJens Wiklander if (rc) 663512cbf1dSJens Wiklander goto out; 664512cbf1dSJens Wiklander 6659e91a619SVesa Jääskeläinen if (obj) { 6669e91a619SVesa Jääskeläinen rc = check_parent_attrs_against_processing(proc_params->id, 6679e91a619SVesa Jääskeläinen function, 668512cbf1dSJens Wiklander obj->attributes); 669512cbf1dSJens Wiklander if (rc) 670512cbf1dSJens Wiklander goto out; 671512cbf1dSJens Wiklander 6729e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session, 6739e91a619SVesa Jääskeläinen obj->attributes); 674512cbf1dSJens Wiklander if (rc) 675512cbf1dSJens Wiklander goto out; 6769e91a619SVesa Jääskeläinen } 677512cbf1dSJens Wiklander 678512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id)) 679512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj); 680fb279d8bSVesa Jääskeläinen else if (processing_is_tee_asymm(proc_params->id)) 681fb279d8bSVesa Jääskeläinen rc = init_asymm_operation(session, function, proc_params, obj); 6829e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(proc_params->id)) 6839e91a619SVesa Jääskeläinen rc = init_digest_operation(session, proc_params); 684512cbf1dSJens Wiklander else 685512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 686512cbf1dSJens Wiklander 687512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 688512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s", 689512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id), 690512cbf1dSJens Wiklander id2str_function(function)); 691512cbf1dSJens Wiklander } 692512cbf1dSJens Wiklander 693512cbf1dSJens Wiklander out: 6948abbc8f7SVesa Jääskeläinen if (rc) 695512cbf1dSJens Wiklander release_active_processing(session); 6968abbc8f7SVesa Jääskeläinen out_free: 697512cbf1dSJens Wiklander TEE_Free(proc_params); 698512cbf1dSJens Wiklander 699512cbf1dSJens Wiklander return rc; 700512cbf1dSJens Wiklander } 701512cbf1dSJens Wiklander 702512cbf1dSJens Wiklander /* 703512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing 704512cbf1dSJens Wiklander * 705512cbf1dSJens Wiklander * @client = client reference 706512cbf1dSJens Wiklander * @ptype = Invocation parameter types 707512cbf1dSJens Wiklander * @params = Invocation parameters reference 708512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 709512cbf1dSJens Wiklander * @step - update, oneshot, final 710512cbf1dSJens Wiklander */ 711512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 712512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 713512cbf1dSJens Wiklander enum processing_func function, 714512cbf1dSJens Wiklander enum processing_step step) 715512cbf1dSJens Wiklander { 716512cbf1dSJens Wiklander TEE_Param *ctrl = params; 717512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 718512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 719512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 720512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 7219e91a619SVesa Jääskeläinen uint32_t key_handle = 0; 7229e91a619SVesa Jääskeläinen struct pkcs11_object *obj = NULL; 723512cbf1dSJens Wiklander 724512cbf1dSJens Wiklander if (!client || 725512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 726512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 727512cbf1dSJens Wiklander 728512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 729512cbf1dSJens Wiklander 730512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 731512cbf1dSJens Wiklander if (rc) 732512cbf1dSJens Wiklander return rc; 733512cbf1dSJens Wiklander 7349e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 7359e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST); 7369e91a619SVesa Jääskeläinen 7379e91a619SVesa Jääskeläinen rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 7389e91a619SVesa Jääskeläinen if (rc) 7399e91a619SVesa Jääskeläinen return rc; 7409e91a619SVesa Jääskeläinen } 7419e91a619SVesa Jääskeläinen 742512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 743512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 744512cbf1dSJens Wiklander 745512cbf1dSJens Wiklander rc = get_active_session(session, function); 746512cbf1dSJens Wiklander if (rc) 747512cbf1dSJens Wiklander return rc; 748512cbf1dSJens Wiklander 7499e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 7509e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST); 7519e91a619SVesa Jääskeläinen 7529e91a619SVesa Jääskeläinen obj = pkcs11_handle2object(key_handle, session); 7539e91a619SVesa Jääskeläinen if (!obj) { 7549e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID; 7559e91a619SVesa Jääskeläinen goto out; 7569e91a619SVesa Jääskeläinen } 7579e91a619SVesa Jääskeläinen 7589e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session, 7599e91a619SVesa Jääskeläinen obj->attributes); 7609e91a619SVesa Jääskeläinen if (rc) { 7619e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID; 7629e91a619SVesa Jääskeläinen goto out; 7639e91a619SVesa Jääskeläinen } 7649e91a619SVesa Jääskeläinen } 7659e91a619SVesa Jääskeläinen 766512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 767512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 768512cbf1dSJens Wiklander function, step); 769512cbf1dSJens Wiklander if (rc) 770512cbf1dSJens Wiklander goto out; 771512cbf1dSJens Wiklander 772512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 773512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 774512cbf1dSJens Wiklander ptypes, params); 775fb279d8bSVesa Jääskeläinen else if (processing_is_tee_asymm(mecha_type)) 776fb279d8bSVesa Jääskeläinen rc = step_asymm_operation(session, function, step, 777fb279d8bSVesa Jääskeläinen ptypes, params); 7789e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(mecha_type)) 7799e91a619SVesa Jääskeläinen rc = step_digest_operation(session, step, obj, ptypes, params); 780512cbf1dSJens Wiklander else 781512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 782512cbf1dSJens Wiklander 7839e91a619SVesa Jääskeläinen if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE || 7849e91a619SVesa Jääskeläinen step == PKCS11_FUNC_STEP_UPDATE_KEY)) { 7852364aa69SRuchika Gupta session->processing->step = PKCS11_FUNC_STEP_UPDATE; 786512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s", 787512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type), 788512cbf1dSJens Wiklander id2str_function(function)); 789512cbf1dSJens Wiklander } 790512cbf1dSJens Wiklander 7912364aa69SRuchika Gupta if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && 7922364aa69SRuchika Gupta step == PKCS11_FUNC_STEP_ONESHOT) 7932364aa69SRuchika Gupta session->processing->step = PKCS11_FUNC_STEP_ONESHOT; 7942364aa69SRuchika Gupta 7952364aa69SRuchika Gupta if (rc == PKCS11_CKR_BUFFER_TOO_SMALL && step == PKCS11_FUNC_STEP_FINAL) 7962364aa69SRuchika Gupta session->processing->step = PKCS11_FUNC_STEP_FINAL; 7972364aa69SRuchika Gupta 798512cbf1dSJens Wiklander out: 799512cbf1dSJens Wiklander switch (step) { 800512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE: 8019e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE_KEY: 802512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 803512cbf1dSJens Wiklander release_active_processing(session); 804512cbf1dSJens Wiklander break; 805512cbf1dSJens Wiklander default: 806512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */ 807512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 808512cbf1dSJens Wiklander release_active_processing(session); 809512cbf1dSJens Wiklander break; 810512cbf1dSJens Wiklander } 811512cbf1dSJens Wiklander 812512cbf1dSJens Wiklander return rc; 813512cbf1dSJens Wiklander } 81448799892SRuchika Gupta 8154dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, 8164dad6642SRuchika Gupta uint32_t ptypes, TEE_Param *params, 8174dad6642SRuchika Gupta enum processing_func function) 81848799892SRuchika Gupta { 81948799892SRuchika Gupta TEE_Param *ctrl = params; 82048799892SRuchika Gupta TEE_Param *out = params + 2; 82148799892SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 82248799892SRuchika Gupta struct serialargs ctrlargs = { }; 82348799892SRuchika Gupta struct pkcs11_session *session = NULL; 82448799892SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 82548799892SRuchika Gupta struct pkcs11_object_head *template = NULL; 82648799892SRuchika Gupta uint32_t parent_handle = 0; 82748799892SRuchika Gupta uint32_t obj_handle = 0; 82848799892SRuchika Gupta struct pkcs11_object *parent = NULL; 82948799892SRuchika Gupta struct obj_attrs *head = NULL; 83048799892SRuchika Gupta size_t template_size = 0; 8313668310bSRuchika Gupta void *in_buf = NULL; 8323668310bSRuchika Gupta uint32_t in_size = 0; 8338c499324SRuchika Gupta void *out_buf = NULL; 8348c499324SRuchika Gupta uint32_t out_size = 0; 8353668310bSRuchika Gupta enum processing_func operation = PKCS11_FUNCTION_UNKNOWN; 83648799892SRuchika Gupta 8373668310bSRuchika Gupta if (!client || 8383668310bSRuchika Gupta TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT || 8393668310bSRuchika Gupta TEE_PARAM_TYPE_GET(ptypes, 2) != TEE_PARAM_TYPE_MEMREF_OUTPUT || 8403668310bSRuchika Gupta out->memref.size != sizeof(obj_handle) || 8413668310bSRuchika Gupta TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) 84248799892SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 84348799892SRuchika Gupta 8443668310bSRuchika Gupta switch (function) { 8453668310bSRuchika Gupta case PKCS11_FUNCTION_UNWRAP: 8463668310bSRuchika Gupta if (TEE_PARAM_TYPE_GET(ptypes, 1) != 8473668310bSRuchika Gupta TEE_PARAM_TYPE_MEMREF_INPUT) 8483668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 8493668310bSRuchika Gupta 8503668310bSRuchika Gupta in_buf = params[1].memref.buffer; 8513668310bSRuchika Gupta in_size = params[1].memref.size; 8523668310bSRuchika Gupta if (in_size && !in_buf) 8533668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 8543668310bSRuchika Gupta 8553668310bSRuchika Gupta /* 8563668310bSRuchika Gupta * Some unwrap mechanisms require encryption to be 8573668310bSRuchika Gupta * performed on the data passed in proc_params by parent 8583668310bSRuchika Gupta * key. Hence set operation as PKCS11_FUNCTION_DECRYPT 8593668310bSRuchika Gupta * to be used with init_symm_operation() 8603668310bSRuchika Gupta */ 8613668310bSRuchika Gupta operation = PKCS11_FUNCTION_DECRYPT; 8623668310bSRuchika Gupta break; 8633668310bSRuchika Gupta case PKCS11_FUNCTION_DERIVE: 8643668310bSRuchika Gupta if (TEE_PARAM_TYPE_GET(ptypes, 1) != TEE_PARAM_TYPE_NONE) 8653668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 8663668310bSRuchika Gupta 8673668310bSRuchika Gupta /* 8683668310bSRuchika Gupta * Some derivation mechanism require encryption to be 8693668310bSRuchika Gupta * performed on the data passed in proc_params by parent 8703668310bSRuchika Gupta * key. Hence set operation as PKCS11_FUNCTION_ENCRYPT 8713668310bSRuchika Gupta * to be used with init_symm_operation() 8723668310bSRuchika Gupta */ 8733668310bSRuchika Gupta operation = PKCS11_FUNCTION_ENCRYPT; 8743668310bSRuchika Gupta break; 8753668310bSRuchika Gupta default: 8763668310bSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 8773668310bSRuchika Gupta } 8783668310bSRuchika Gupta 87948799892SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 88048799892SRuchika Gupta 88148799892SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 88248799892SRuchika Gupta if (rc) 88348799892SRuchika Gupta return rc; 88448799892SRuchika Gupta 88548799892SRuchika Gupta rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); 88648799892SRuchika Gupta if (rc) 88748799892SRuchika Gupta return rc; 88848799892SRuchika Gupta 88948799892SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 89048799892SRuchika Gupta if (rc) 8915f80f270SRuchika Gupta return rc; 89248799892SRuchika Gupta 89348799892SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 89448799892SRuchika Gupta if (rc) 89548799892SRuchika Gupta goto out_free; 89648799892SRuchika Gupta 89748799892SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 89848799892SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 89948799892SRuchika Gupta goto out_free; 90048799892SRuchika Gupta } 90148799892SRuchika Gupta 90248799892SRuchika Gupta /* Return error if processing already active */ 90348799892SRuchika Gupta rc = get_ready_session(session); 90448799892SRuchika Gupta if (rc) 90548799892SRuchika Gupta goto out_free; 90648799892SRuchika Gupta 90748799892SRuchika Gupta /* Check parent handle */ 90848799892SRuchika Gupta parent = pkcs11_handle2object(parent_handle, session); 90948799892SRuchika Gupta if (!parent) { 91048799892SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID; 91148799892SRuchika Gupta goto out_free; 91248799892SRuchika Gupta } 91348799892SRuchika Gupta 91448799892SRuchika Gupta /* Check if mechanism can be used for derivation function */ 91548799892SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 91648799892SRuchika Gupta function, 91748799892SRuchika Gupta PKCS11_FUNC_STEP_INIT); 91848799892SRuchika Gupta if (rc) 91948799892SRuchika Gupta goto out_free; 92048799892SRuchika Gupta 92148799892SRuchika Gupta /* Set the processing state to active */ 92248799892SRuchika Gupta rc = set_processing_state(session, function, parent, NULL); 92348799892SRuchika Gupta if (rc) 92448799892SRuchika Gupta goto out_free; 92548799892SRuchika Gupta 92648799892SRuchika Gupta /* 92748799892SRuchika Gupta * Check if base/parent key has CKA_DERIVE set and its key type is 92848799892SRuchika Gupta * compatible with the mechanism passed 92948799892SRuchika Gupta */ 93048799892SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function, 93148799892SRuchika Gupta parent->attributes); 932d05ab5feSRuchika Gupta if (rc) { 933d05ab5feSRuchika Gupta /* 934d05ab5feSRuchika Gupta * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors 935d05ab5feSRuchika Gupta * specified with C_Derive/Unwrap() in the specification. So 936d05ab5feSRuchika Gupta * return the next most appropriate error. 937d05ab5feSRuchika Gupta */ 9383668310bSRuchika Gupta if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) { 9393668310bSRuchika Gupta if (function == PKCS11_FUNCTION_UNWRAP) 9403668310bSRuchika Gupta rc = 9413668310bSRuchika Gupta PKCS11_CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT; 9423668310bSRuchika Gupta else 943d05ab5feSRuchika Gupta rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; 9443668310bSRuchika Gupta } 94548799892SRuchika Gupta goto out; 946d05ab5feSRuchika Gupta } 94748799892SRuchika Gupta 94848799892SRuchika Gupta /* Check access of base/parent key */ 94948799892SRuchika Gupta rc = check_access_attrs_against_token(session, parent->attributes); 95048799892SRuchika Gupta if (rc) 95148799892SRuchika Gupta goto out; 95248799892SRuchika Gupta 95348799892SRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 95448799892SRuchika Gupta /* 95548799892SRuchika Gupta * Prepare a clean initial state for the requested object attributes 95648799892SRuchika Gupta * using base/parent key attributes. Free temporary template once done. 95748799892SRuchika Gupta */ 95848799892SRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 95948799892SRuchika Gupta parent->attributes, 96048799892SRuchika Gupta function, 96148799892SRuchika Gupta proc_params->id, 96248799892SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 96348799892SRuchika Gupta if (rc) 96448799892SRuchika Gupta goto out; 96548799892SRuchika Gupta 96648799892SRuchika Gupta TEE_Free(template); 96748799892SRuchika Gupta template = NULL; 96848799892SRuchika Gupta 96948799892SRuchika Gupta /* check_created_attrs() is called later once key size is known */ 97048799892SRuchika Gupta 97148799892SRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 97248799892SRuchika Gupta if (rc) 97348799892SRuchika Gupta goto out; 97448799892SRuchika Gupta 97548799892SRuchika Gupta rc = check_created_attrs_against_token(session, head); 97648799892SRuchika Gupta if (rc) 97748799892SRuchika Gupta goto out; 97848799892SRuchika Gupta 979f5c0739cSRuchika Gupta rc = check_access_attrs_against_token(session, head); 980f5c0739cSRuchika Gupta if (rc) 981f5c0739cSRuchika Gupta goto out; 982f5c0739cSRuchika Gupta 9838c499324SRuchika Gupta if (processing_is_tee_symm(proc_params->id)) { 9843668310bSRuchika Gupta rc = init_symm_operation(session, operation, proc_params, 9853668310bSRuchika Gupta parent); 98648799892SRuchika Gupta if (rc) 98748799892SRuchika Gupta goto out; 98848799892SRuchika Gupta 9893668310bSRuchika Gupta switch (function) { 9903668310bSRuchika Gupta case PKCS11_FUNCTION_DERIVE: 9913668310bSRuchika Gupta rc = derive_key_by_symm_enc(session, &out_buf, 9923668310bSRuchika Gupta &out_size); 9933668310bSRuchika Gupta break; 9943668310bSRuchika Gupta case PKCS11_FUNCTION_UNWRAP: 9953668310bSRuchika Gupta rc = unwrap_key_by_symm(session, in_buf, in_size, 9963668310bSRuchika Gupta &out_buf, &out_size); 9973668310bSRuchika Gupta break; 9983668310bSRuchika Gupta default: 9993668310bSRuchika Gupta TEE_Panic(function); 10003668310bSRuchika Gupta } 100148799892SRuchika Gupta if (rc) 100248799892SRuchika Gupta goto out; 1003cc062b46SJorge Ramirez-Ortiz 1004cc062b46SJorge Ramirez-Ortiz } else if (processing_is_tee_asymm(proc_params->id)) { 100545d40bdaSValerii Chubar switch (function) { 100645d40bdaSValerii Chubar case PKCS11_FUNCTION_DERIVE: 100745d40bdaSValerii Chubar rc = init_asymm_operation(session, function, 100845d40bdaSValerii Chubar proc_params, parent); 1009cc062b46SJorge Ramirez-Ortiz if (rc) 1010cc062b46SJorge Ramirez-Ortiz goto out; 1011cc062b46SJorge Ramirez-Ortiz 1012cc062b46SJorge Ramirez-Ortiz rc = do_asymm_derivation(session, proc_params, &head); 101345d40bdaSValerii Chubar if (!rc) 101445d40bdaSValerii Chubar goto done; 101545d40bdaSValerii Chubar break; 101645d40bdaSValerii Chubar case PKCS11_FUNCTION_UNWRAP: 101745d40bdaSValerii Chubar rc = init_asymm_operation(session, operation, 101845d40bdaSValerii Chubar proc_params, parent); 1019cc062b46SJorge Ramirez-Ortiz if (rc) 1020cc062b46SJorge Ramirez-Ortiz goto out; 1021cc062b46SJorge Ramirez-Ortiz 102245d40bdaSValerii Chubar rc = unwrap_key_by_asymm(session, in_buf, in_size, 102345d40bdaSValerii Chubar &out_buf, &out_size); 102445d40bdaSValerii Chubar break; 102545d40bdaSValerii Chubar default: 102645d40bdaSValerii Chubar TEE_Panic(function); 102745d40bdaSValerii Chubar } 102845d40bdaSValerii Chubar 102945d40bdaSValerii Chubar if (rc) 103045d40bdaSValerii Chubar goto out; 10318c499324SRuchika Gupta } else { 103248799892SRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 103348799892SRuchika Gupta goto out; 103448799892SRuchika Gupta } 103548799892SRuchika Gupta 10368c499324SRuchika Gupta rc = set_key_data(&head, out_buf, out_size); 10378c499324SRuchika Gupta if (rc) 10388c499324SRuchika Gupta goto out; 10398c499324SRuchika Gupta 1040cc062b46SJorge Ramirez-Ortiz done: 10418c499324SRuchika Gupta TEE_Free(out_buf); 10428c499324SRuchika Gupta out_buf = NULL; 10438c499324SRuchika Gupta 104448799892SRuchika Gupta TEE_Free(proc_params); 104548799892SRuchika Gupta proc_params = NULL; 104648799892SRuchika Gupta 104748799892SRuchika Gupta /* 104848799892SRuchika Gupta * Object is ready, register it and return a handle. 104948799892SRuchika Gupta */ 105048799892SRuchika Gupta rc = create_object(session, head, &obj_handle); 105148799892SRuchika Gupta if (rc) 105248799892SRuchika Gupta goto out; 105348799892SRuchika Gupta 105448799892SRuchika Gupta /* 105548799892SRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 105648799892SRuchika Gupta * owns the serialized buffer that holds the object attributes. 105748799892SRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 105848799892SRuchika Gupta * be freed at function out. 105948799892SRuchika Gupta */ 106048799892SRuchika Gupta head = NULL; 106148799892SRuchika Gupta 106248799892SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 106348799892SRuchika Gupta out->memref.size = sizeof(obj_handle); 106448799892SRuchika Gupta 106548799892SRuchika Gupta DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, 106648799892SRuchika Gupta session->handle, obj_handle); 106748799892SRuchika Gupta 106848799892SRuchika Gupta out: 106948799892SRuchika Gupta release_active_processing(session); 107048799892SRuchika Gupta out_free: 107148799892SRuchika Gupta TEE_Free(proc_params); 107248799892SRuchika Gupta TEE_Free(template); 107348799892SRuchika Gupta TEE_Free(head); 10748c499324SRuchika Gupta TEE_Free(out_buf); 107548799892SRuchika Gupta 107648799892SRuchika Gupta return rc; 107748799892SRuchika Gupta } 1078eb6141b6SVesa Jääskeläinen 1079eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, 1080eb6141b6SVesa Jääskeläinen uint32_t ptypes, 1081eb6141b6SVesa Jääskeläinen TEE_Param *params) 1082eb6141b6SVesa Jääskeläinen { 1083eb6141b6SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 1084eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 1085eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 1086eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 1087eb6141b6SVesa Jääskeläinen TEE_Param *ctrl = params; 1088eb6141b6SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK; 1089eb6141b6SVesa Jääskeläinen struct serialargs ctrlargs = { }; 1090eb6141b6SVesa Jääskeläinen struct pkcs11_session *session = NULL; 1091eb6141b6SVesa Jääskeläinen enum processing_func function = PKCS11_FUNCTION_UNKNOWN; 1092eb6141b6SVesa Jääskeläinen uint32_t cmd = 0; 1093eb6141b6SVesa Jääskeläinen 1094eb6141b6SVesa Jääskeläinen if (!client || ptypes != exp_pt) 1095eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 1096eb6141b6SVesa Jääskeläinen 1097eb6141b6SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 1098eb6141b6SVesa Jääskeläinen 1099eb6141b6SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 1100eb6141b6SVesa Jääskeläinen if (rc) 1101eb6141b6SVesa Jääskeläinen return rc; 1102eb6141b6SVesa Jääskeläinen 1103eb6141b6SVesa Jääskeläinen rc = serialargs_get_u32(&ctrlargs, &cmd); 1104eb6141b6SVesa Jääskeläinen 1105eb6141b6SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) 1106eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 1107eb6141b6SVesa Jääskeläinen 1108eb6141b6SVesa Jääskeläinen function = func_for_cmd(cmd); 1109eb6141b6SVesa Jääskeläinen if (function == PKCS11_FUNCTION_UNKNOWN) 1110eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 1111eb6141b6SVesa Jääskeläinen 1112eb6141b6SVesa Jääskeläinen rc = get_active_session(session, function); 1113eb6141b6SVesa Jääskeläinen if (rc) 1114eb6141b6SVesa Jääskeläinen return rc; 1115eb6141b6SVesa Jääskeläinen 1116eb6141b6SVesa Jääskeläinen release_active_processing(session); 1117eb6141b6SVesa Jääskeläinen 1118eb6141b6SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": release processing", session->handle); 1119eb6141b6SVesa Jääskeläinen 1120eb6141b6SVesa Jääskeläinen return PKCS11_CKR_OK; 1121eb6141b6SVesa Jääskeläinen } 11225f80f270SRuchika Gupta 11235f80f270SRuchika Gupta enum pkcs11_rc entry_wrap_key(struct pkcs11_client *client, 11245f80f270SRuchika Gupta uint32_t ptypes, TEE_Param *params) 11255f80f270SRuchika Gupta { 11265f80f270SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 11275f80f270SRuchika Gupta TEE_PARAM_TYPE_NONE, 11285f80f270SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 11295f80f270SRuchika Gupta TEE_PARAM_TYPE_NONE); 11305f80f270SRuchika Gupta TEE_Param *ctrl = params; 11315f80f270SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 11325f80f270SRuchika Gupta struct serialargs ctrlargs = { }; 11335f80f270SRuchika Gupta struct pkcs11_session *session = NULL; 11345f80f270SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 11355f80f270SRuchika Gupta struct pkcs11_object *wrapping_key = NULL; 11365f80f270SRuchika Gupta struct pkcs11_object *key = NULL; 11375f80f270SRuchika Gupta void *req_attrs = NULL; 11385f80f270SRuchika Gupta uint32_t wrapping_key_handle = 0; 11395f80f270SRuchika Gupta uint32_t key_handle = 0; 11405f80f270SRuchika Gupta uint32_t size = 0; 11415f80f270SRuchika Gupta void *key_data = NULL; 11425f80f270SRuchika Gupta uint32_t key_sz = 0; 11435f80f270SRuchika Gupta void *out_buf = params[2].memref.buffer; 11445f80f270SRuchika Gupta uint32_t out_size = params[2].memref.size; 11455f80f270SRuchika Gupta const enum processing_func function = PKCS11_FUNCTION_WRAP; 11465f80f270SRuchika Gupta 11475f80f270SRuchika Gupta if (!client || ptypes != exp_pt || 11485f80f270SRuchika Gupta (out_size && !out_buf)) 11495f80f270SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 11505f80f270SRuchika Gupta 11515f80f270SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 11525f80f270SRuchika Gupta 11535f80f270SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 11545f80f270SRuchika Gupta if (rc) 11555f80f270SRuchika Gupta return rc; 11565f80f270SRuchika Gupta 11575f80f270SRuchika Gupta rc = serialargs_get(&ctrlargs, &wrapping_key_handle, sizeof(uint32_t)); 11585f80f270SRuchika Gupta if (rc) 11595f80f270SRuchika Gupta return rc; 11605f80f270SRuchika Gupta 11615f80f270SRuchika Gupta rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 11625f80f270SRuchika Gupta if (rc) 11635f80f270SRuchika Gupta return rc; 11645f80f270SRuchika Gupta 11655f80f270SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 11665f80f270SRuchika Gupta if (rc) 11675f80f270SRuchika Gupta return rc; 11685f80f270SRuchika Gupta 11695f80f270SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 11705f80f270SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 11715f80f270SRuchika Gupta goto out_free; 11725f80f270SRuchika Gupta } 11735f80f270SRuchika Gupta 11745f80f270SRuchika Gupta rc = get_ready_session(session); 11755f80f270SRuchika Gupta if (rc) 11765f80f270SRuchika Gupta goto out_free; 11775f80f270SRuchika Gupta 11785f80f270SRuchika Gupta wrapping_key = pkcs11_handle2object(wrapping_key_handle, session); 11795f80f270SRuchika Gupta if (!wrapping_key) { 11805f80f270SRuchika Gupta rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID; 11815f80f270SRuchika Gupta goto out_free; 11825f80f270SRuchika Gupta } 11835f80f270SRuchika Gupta 11845f80f270SRuchika Gupta key = pkcs11_handle2object(key_handle, session); 11855f80f270SRuchika Gupta if (!key) { 11865f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID; 11875f80f270SRuchika Gupta goto out_free; 11885f80f270SRuchika Gupta } 11895f80f270SRuchika Gupta 11905f80f270SRuchika Gupta /* 11915f80f270SRuchika Gupta * The wrapping key and key to be wrapped shouldn't be same. 11925f80f270SRuchika Gupta * PKCS#11 spec doesn't explicitly state that but logically this isn't 11935f80f270SRuchika Gupta * a use case and also acts as an attack vector, so explicitly 11945f80f270SRuchika Gupta * disallow this. 11955f80f270SRuchika Gupta */ 11965f80f270SRuchika Gupta if (key == wrapping_key) { 11975f80f270SRuchika Gupta rc = PKCS11_CKR_WRAPPING_KEY_HANDLE_INVALID; 11985f80f270SRuchika Gupta goto out_free; 11995f80f270SRuchika Gupta } 12005f80f270SRuchika Gupta 12015f80f270SRuchika Gupta rc = set_processing_state(session, function, wrapping_key, NULL); 12025f80f270SRuchika Gupta if (rc) 12035f80f270SRuchika Gupta goto out_free; 12045f80f270SRuchika Gupta 12055f80f270SRuchika Gupta /* Check if mechanism can be used for wrapping function */ 12065f80f270SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 12075f80f270SRuchika Gupta function, 12085f80f270SRuchika Gupta PKCS11_FUNC_STEP_INIT); 12095f80f270SRuchika Gupta if (rc) 12105f80f270SRuchika Gupta goto out; 12115f80f270SRuchika Gupta 12125f80f270SRuchika Gupta /* 12135f80f270SRuchika Gupta * Check if wrapping key has CKA_WRAP set and its key type is 12145f80f270SRuchika Gupta * compatible with the mechanism passed 12155f80f270SRuchika Gupta */ 12165f80f270SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function, 12175f80f270SRuchika Gupta wrapping_key->attributes); 12185f80f270SRuchika Gupta if (rc) { 12195f80f270SRuchika Gupta /* 12205f80f270SRuchika Gupta * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors 12215f80f270SRuchika Gupta * specified with C_Wrap() in the specification. So 12225f80f270SRuchika Gupta * return the next most appropriate error. 12235f80f270SRuchika Gupta */ 12245f80f270SRuchika Gupta if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) 12255f80f270SRuchika Gupta rc = PKCS11_CKR_WRAPPING_KEY_TYPE_INCONSISTENT; 12265f80f270SRuchika Gupta 12275f80f270SRuchika Gupta goto out; 12285f80f270SRuchika Gupta } 12295f80f270SRuchika Gupta 12305f80f270SRuchika Gupta /* Check access of wrapping key */ 12315f80f270SRuchika Gupta rc = check_access_attrs_against_token(session, 12325f80f270SRuchika Gupta wrapping_key->attributes); 12335f80f270SRuchika Gupta if (rc) 12345f80f270SRuchika Gupta goto out; 12355f80f270SRuchika Gupta 12365f80f270SRuchika Gupta switch (get_class(key->attributes)) { 12375f80f270SRuchika Gupta case PKCS11_CKO_SECRET_KEY: 12385f80f270SRuchika Gupta case PKCS11_CKO_PRIVATE_KEY: 123945d40bdaSValerii Chubar break; 12405f80f270SRuchika Gupta default: 12415f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_NOT_WRAPPABLE; 12425f80f270SRuchika Gupta goto out; 12435f80f270SRuchika Gupta } 12445f80f270SRuchika Gupta 12455f80f270SRuchika Gupta /* Check if key to be wrapped is extractable */ 12465f80f270SRuchika Gupta if (!get_bool(key->attributes, PKCS11_CKA_EXTRACTABLE)) { 12475f80f270SRuchika Gupta DMSG("Extractable property is false"); 12485f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_UNEXTRACTABLE; 12495f80f270SRuchika Gupta goto out; 12505f80f270SRuchika Gupta } 12515f80f270SRuchika Gupta 12525f80f270SRuchika Gupta if (get_bool(key->attributes, PKCS11_CKA_WRAP_WITH_TRUSTED) && 12535f80f270SRuchika Gupta !get_bool(wrapping_key->attributes, PKCS11_CKA_TRUSTED)) { 12545f80f270SRuchika Gupta DMSG("Wrap with trusted not satisfied"); 12555f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_NOT_WRAPPABLE; 12565f80f270SRuchika Gupta goto out; 12575f80f270SRuchika Gupta } 12585f80f270SRuchika Gupta 12595f80f270SRuchika Gupta rc = check_access_attrs_against_token(session, key->attributes); 12605f80f270SRuchika Gupta if (rc) 12615f80f270SRuchika Gupta goto out; 12625f80f270SRuchika Gupta 12635f80f270SRuchika Gupta rc = get_attribute_ptr(wrapping_key->attributes, 12645f80f270SRuchika Gupta PKCS11_CKA_WRAP_TEMPLATE, &req_attrs, &size); 12655f80f270SRuchika Gupta if (rc == PKCS11_CKR_OK && size != 0) { 12665f80f270SRuchika Gupta if (!attributes_match_reference(key->attributes, req_attrs)) { 12675f80f270SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID; 12685f80f270SRuchika Gupta goto out; 12695f80f270SRuchika Gupta } 12705f80f270SRuchika Gupta } 12715f80f270SRuchika Gupta 1272a9aa45d8SValerii Chubar rc = alloc_key_data_to_wrap(key->attributes, &key_data, &key_sz); 12735f80f270SRuchika Gupta if (rc) 12745f80f270SRuchika Gupta goto out; 12755f80f270SRuchika Gupta 12765f80f270SRuchika Gupta if (processing_is_tee_symm(proc_params->id)) { 12775f80f270SRuchika Gupta rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, 12785f80f270SRuchika Gupta proc_params, wrapping_key); 12795f80f270SRuchika Gupta if (rc) 12805f80f270SRuchika Gupta goto out; 12815f80f270SRuchika Gupta 12825f80f270SRuchika Gupta rc = wrap_data_by_symm_enc(session, key_data, key_sz, out_buf, 12835f80f270SRuchika Gupta &out_size); 12845f80f270SRuchika Gupta } else { 128545d40bdaSValerii Chubar rc = init_asymm_operation(session, PKCS11_FUNCTION_ENCRYPT, 128645d40bdaSValerii Chubar proc_params, wrapping_key); 128745d40bdaSValerii Chubar if (rc) 128845d40bdaSValerii Chubar goto out; 128945d40bdaSValerii Chubar 129045d40bdaSValerii Chubar rc = wrap_data_by_asymm_enc(session, key_data, key_sz, out_buf, 129145d40bdaSValerii Chubar &out_size); 12925f80f270SRuchika Gupta } 12935f80f270SRuchika Gupta 12945f80f270SRuchika Gupta if (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL) 12955f80f270SRuchika Gupta params[2].memref.size = out_size; 12965f80f270SRuchika Gupta 12975f80f270SRuchika Gupta out: 12985f80f270SRuchika Gupta release_active_processing(session); 12995f80f270SRuchika Gupta out_free: 1300a9aa45d8SValerii Chubar TEE_Free(key_data); 13015f80f270SRuchika Gupta TEE_Free(proc_params); 13025f80f270SRuchika Gupta return rc; 13035f80f270SRuchika Gupta } 1304