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 107512cbf1dSJens Wiklander if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 108512cbf1dSJens Wiklander TEE_FreeOperation(session->processing->tee_op_handle); 109512cbf1dSJens Wiklander session->processing->tee_op_handle = TEE_HANDLE_NULL; 110512cbf1dSJens Wiklander } 111512cbf1dSJens Wiklander 1122158ea6cSRuchika Gupta TEE_Free(session->processing->extra_ctx); 1132158ea6cSRuchika Gupta 114512cbf1dSJens Wiklander TEE_Free(session->processing); 115512cbf1dSJens Wiklander session->processing = NULL; 116512cbf1dSJens Wiklander } 117512cbf1dSJens Wiklander 118512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj) 119512cbf1dSJens Wiklander { 120512cbf1dSJens Wiklander uint32_t a_size = 0; 121512cbf1dSJens Wiklander struct obj_attrs *attrs = obj->attributes; 122512cbf1dSJens Wiklander 123512cbf1dSJens Wiklander switch (get_key_type(attrs)) { 124512cbf1dSJens Wiklander case PKCS11_CKK_AES: 125689f4e5bSRuchika Gupta case PKCS11_CKK_GENERIC_SECRET: 126689f4e5bSRuchika Gupta case PKCS11_CKK_MD5_HMAC: 127689f4e5bSRuchika Gupta case PKCS11_CKK_SHA_1_HMAC: 128689f4e5bSRuchika Gupta case PKCS11_CKK_SHA224_HMAC: 129689f4e5bSRuchika Gupta case PKCS11_CKK_SHA256_HMAC: 130689f4e5bSRuchika Gupta case PKCS11_CKK_SHA384_HMAC: 131689f4e5bSRuchika Gupta case PKCS11_CKK_SHA512_HMAC: 132512cbf1dSJens Wiklander if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 133512cbf1dSJens Wiklander return 0; 134512cbf1dSJens Wiklander 135512cbf1dSJens Wiklander return a_size * 8; 136512cbf1dSJens Wiklander default: 137512cbf1dSJens Wiklander TEE_Panic(0); 138512cbf1dSJens Wiklander return 0; 139512cbf1dSJens Wiklander } 140512cbf1dSJens Wiklander } 141512cbf1dSJens Wiklander 142fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) 143fa247a2aSRuchika Gupta { 144fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 145fa247a2aSRuchika Gupta void *data = NULL; 146fa247a2aSRuchika Gupta uint32_t data_size = 0; 147fa247a2aSRuchika Gupta uint32_t value_len = 0; 148fa247a2aSRuchika Gupta void *value = NULL; 149fa247a2aSRuchika Gupta 150fa247a2aSRuchika Gupta if (!*head) 151fa247a2aSRuchika Gupta return PKCS11_CKR_TEMPLATE_INCONSISTENT; 152fa247a2aSRuchika Gupta 153fa247a2aSRuchika Gupta rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); 154fa247a2aSRuchika Gupta if (rc || data_size != sizeof(uint32_t)) { 155fa247a2aSRuchika Gupta DMSG("%s", rc ? "No attribute value_len found" : 156fa247a2aSRuchika Gupta "Invalid size for attribute VALUE_LEN"); 157fa247a2aSRuchika Gupta 158fa247a2aSRuchika Gupta return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; 159fa247a2aSRuchika Gupta } 160fa247a2aSRuchika Gupta TEE_MemMove(&value_len, data, data_size); 161fa247a2aSRuchika Gupta 162fa247a2aSRuchika Gupta /* Remove the default empty value attribute if found */ 163fa247a2aSRuchika Gupta rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); 164fa247a2aSRuchika Gupta if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) 165fa247a2aSRuchika Gupta return PKCS11_CKR_GENERAL_ERROR; 166fa247a2aSRuchika Gupta 167fa247a2aSRuchika Gupta value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 168fa247a2aSRuchika Gupta if (!value) 169fa247a2aSRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY; 170fa247a2aSRuchika Gupta 171fa247a2aSRuchika Gupta TEE_GenerateRandom(value, value_len); 172fa247a2aSRuchika Gupta 173fa247a2aSRuchika Gupta rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); 174fa247a2aSRuchika Gupta 175fa247a2aSRuchika Gupta TEE_Free(value); 176fa247a2aSRuchika Gupta 177fa247a2aSRuchika Gupta return rc; 178fa247a2aSRuchika Gupta } 179fa247a2aSRuchika Gupta 180fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, 181fa247a2aSRuchika Gupta uint32_t ptypes, TEE_Param *params) 182fa247a2aSRuchika Gupta { 183fa247a2aSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 184fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE, 185fa247a2aSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 186fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE); 187fa247a2aSRuchika Gupta TEE_Param *ctrl = params; 188fa247a2aSRuchika Gupta TEE_Param *out = params + 2; 189fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 190fa247a2aSRuchika Gupta struct serialargs ctrlargs = { }; 191fa247a2aSRuchika Gupta struct pkcs11_session *session = NULL; 192fa247a2aSRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 193fa247a2aSRuchika Gupta struct obj_attrs *head = NULL; 194fa247a2aSRuchika Gupta struct pkcs11_object_head *template = NULL; 195fa247a2aSRuchika Gupta size_t template_size = 0; 196fa247a2aSRuchika Gupta uint32_t obj_handle = 0; 197fa247a2aSRuchika Gupta 198fa247a2aSRuchika Gupta if (!client || ptypes != exp_pt || 199fa247a2aSRuchika Gupta out->memref.size != sizeof(obj_handle)) 200fa247a2aSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 201fa247a2aSRuchika Gupta 202fa247a2aSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 203fa247a2aSRuchika Gupta 204fa247a2aSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 205fa247a2aSRuchika Gupta if (rc) 206fa247a2aSRuchika Gupta return rc; 207fa247a2aSRuchika Gupta 208fa247a2aSRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 209fa247a2aSRuchika Gupta if (rc) 210fa247a2aSRuchika Gupta goto out; 211fa247a2aSRuchika Gupta 212fa247a2aSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 213fa247a2aSRuchika Gupta if (rc) 214fa247a2aSRuchika Gupta goto out; 215fa247a2aSRuchika Gupta 216fa247a2aSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 217fa247a2aSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 218fa247a2aSRuchika Gupta goto out; 219fa247a2aSRuchika Gupta } 220fa247a2aSRuchika Gupta 221fa247a2aSRuchika Gupta rc = get_ready_session(session); 222fa247a2aSRuchika Gupta if (rc) 223fa247a2aSRuchika Gupta goto out; 224fa247a2aSRuchika Gupta 225fa247a2aSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 226fa247a2aSRuchika Gupta 227fa247a2aSRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 228fa247a2aSRuchika Gupta PKCS11_FUNCTION_GENERATE, 229fa247a2aSRuchika Gupta PKCS11_FUNC_STEP_INIT); 230fa247a2aSRuchika Gupta if (rc) { 231fa247a2aSRuchika Gupta DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); 232fa247a2aSRuchika Gupta goto out; 233fa247a2aSRuchika Gupta } 234fa247a2aSRuchika Gupta 235fa247a2aSRuchika Gupta /* 236fa247a2aSRuchika Gupta * Prepare a clean initial state for the requested object attributes. 237fa247a2aSRuchika Gupta * Free temporary template once done. 238fa247a2aSRuchika Gupta */ 239fa247a2aSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 240fa247a2aSRuchika Gupta NULL, PKCS11_FUNCTION_GENERATE, 2414cfce748SRuchika Gupta proc_params->id, 2424cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 243fa247a2aSRuchika Gupta if (rc) 244fa247a2aSRuchika Gupta goto out; 245fa247a2aSRuchika Gupta 246fa247a2aSRuchika Gupta TEE_Free(template); 247fa247a2aSRuchika Gupta template = NULL; 248fa247a2aSRuchika Gupta 249fa247a2aSRuchika Gupta rc = check_created_attrs(head, NULL); 250fa247a2aSRuchika Gupta if (rc) 251fa247a2aSRuchika Gupta goto out; 252fa247a2aSRuchika Gupta 253fa247a2aSRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 254fa247a2aSRuchika Gupta if (rc) 255fa247a2aSRuchika Gupta goto out; 256fa247a2aSRuchika Gupta 257fa247a2aSRuchika Gupta rc = check_created_attrs_against_token(session, head); 258fa247a2aSRuchika Gupta if (rc) 259fa247a2aSRuchika Gupta goto out; 260fa247a2aSRuchika Gupta 261fa247a2aSRuchika Gupta /* 262fa247a2aSRuchika Gupta * Execute target processing and add value as attribute 263fa247a2aSRuchika Gupta * PKCS11_CKA_VALUE. Symm key generation: depends on target 264fa247a2aSRuchika Gupta * processing to be used. 265fa247a2aSRuchika Gupta */ 266fa247a2aSRuchika Gupta switch (proc_params->id) { 267fa247a2aSRuchika Gupta case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: 268fa247a2aSRuchika Gupta case PKCS11_CKM_AES_KEY_GEN: 269fa247a2aSRuchika Gupta /* Generate random of size specified by attribute VALUE_LEN */ 270fa247a2aSRuchika Gupta rc = generate_random_key_value(&head); 271fa247a2aSRuchika Gupta if (rc) 272fa247a2aSRuchika Gupta goto out; 273fa247a2aSRuchika Gupta break; 274fa247a2aSRuchika Gupta 275fa247a2aSRuchika Gupta default: 276fa247a2aSRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 277fa247a2aSRuchika Gupta goto out; 278fa247a2aSRuchika Gupta } 279fa247a2aSRuchika Gupta 280fa247a2aSRuchika Gupta TEE_Free(proc_params); 281fa247a2aSRuchika Gupta proc_params = NULL; 282fa247a2aSRuchika Gupta 283fa247a2aSRuchika Gupta /* 284fa247a2aSRuchika Gupta * Object is ready, register it and return a handle. 285fa247a2aSRuchika Gupta */ 286fa247a2aSRuchika Gupta rc = create_object(session, head, &obj_handle); 287fa247a2aSRuchika Gupta if (rc) 288fa247a2aSRuchika Gupta goto out; 289fa247a2aSRuchika Gupta 290fa247a2aSRuchika Gupta /* 291fa247a2aSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 292fa247a2aSRuchika Gupta * owns the serialized buffer that holds the object attributes. 293fa247a2aSRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 294fa247a2aSRuchika Gupta * be freed at function out. 295fa247a2aSRuchika Gupta */ 296fa247a2aSRuchika Gupta head = NULL; 297fa247a2aSRuchika Gupta 298fa247a2aSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 299fa247a2aSRuchika Gupta out->memref.size = sizeof(obj_handle); 300fa247a2aSRuchika Gupta 301fa247a2aSRuchika Gupta DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, 302fa247a2aSRuchika Gupta session->handle, obj_handle); 303fa247a2aSRuchika Gupta 304fa247a2aSRuchika Gupta out: 305fa247a2aSRuchika Gupta TEE_Free(proc_params); 306fa247a2aSRuchika Gupta TEE_Free(template); 307fa247a2aSRuchika Gupta TEE_Free(head); 308fa247a2aSRuchika Gupta 309fa247a2aSRuchika Gupta return rc; 310fa247a2aSRuchika Gupta } 311fa247a2aSRuchika Gupta 312*013934d8SVesa Jääskeläinen enum pkcs11_rc alloc_get_tee_attribute_data(TEE_ObjectHandle tee_obj, 313*013934d8SVesa Jääskeläinen uint32_t attribute, 314*013934d8SVesa Jääskeläinen void **data, size_t *size) 315*013934d8SVesa Jääskeläinen { 316*013934d8SVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC; 317*013934d8SVesa Jääskeläinen void *ptr = NULL; 318*013934d8SVesa Jääskeläinen uint32_t sz = 0; 319*013934d8SVesa Jääskeläinen 320*013934d8SVesa Jääskeläinen res = TEE_GetObjectBufferAttribute(tee_obj, attribute, NULL, &sz); 321*013934d8SVesa Jääskeläinen if (res != TEE_ERROR_SHORT_BUFFER) 322*013934d8SVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED; 323*013934d8SVesa Jääskeläinen 324*013934d8SVesa Jääskeläinen ptr = TEE_Malloc(sz, TEE_USER_MEM_HINT_NO_FILL_ZERO); 325*013934d8SVesa Jääskeläinen if (!ptr) 326*013934d8SVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY; 327*013934d8SVesa Jääskeläinen 328*013934d8SVesa Jääskeläinen res = TEE_GetObjectBufferAttribute(tee_obj, attribute, ptr, &sz); 329*013934d8SVesa Jääskeläinen if (res) { 330*013934d8SVesa Jääskeläinen TEE_Free(ptr); 331*013934d8SVesa Jääskeläinen } else { 332*013934d8SVesa Jääskeläinen *data = ptr; 333*013934d8SVesa Jääskeläinen *size = sz; 334*013934d8SVesa Jääskeläinen } 335*013934d8SVesa Jääskeläinen 336*013934d8SVesa Jääskeläinen return tee2pkcs_error(res); 337*013934d8SVesa Jääskeläinen } 338*013934d8SVesa Jääskeläinen 339*013934d8SVesa Jääskeläinen enum pkcs11_rc tee2pkcs_add_attribute(struct obj_attrs **head, 340*013934d8SVesa Jääskeläinen uint32_t pkcs11_id, 341*013934d8SVesa Jääskeläinen TEE_ObjectHandle tee_obj, 342*013934d8SVesa Jääskeläinen uint32_t tee_id) 343*013934d8SVesa Jääskeläinen { 344*013934d8SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 345*013934d8SVesa Jääskeläinen void *a_ptr = NULL; 346*013934d8SVesa Jääskeläinen size_t a_size = 0; 347*013934d8SVesa Jääskeläinen 348*013934d8SVesa Jääskeläinen rc = alloc_get_tee_attribute_data(tee_obj, tee_id, &a_ptr, &a_size); 349*013934d8SVesa Jääskeläinen if (rc) 350*013934d8SVesa Jääskeläinen goto out; 351*013934d8SVesa Jääskeläinen 352*013934d8SVesa Jääskeläinen rc = add_attribute(head, pkcs11_id, a_ptr, a_size); 353*013934d8SVesa Jääskeläinen 354*013934d8SVesa Jääskeläinen TEE_Free(a_ptr); 355*013934d8SVesa Jääskeläinen 356*013934d8SVesa Jääskeläinen out: 357*013934d8SVesa Jääskeläinen if (rc) 358*013934d8SVesa Jääskeläinen EMSG("Failed TEE attribute %#"PRIx32" for %#"PRIx32"/%s", 359*013934d8SVesa Jääskeläinen tee_id, pkcs11_id, id2str_attr(pkcs11_id)); 360*013934d8SVesa Jääskeläinen return rc; 361*013934d8SVesa Jääskeläinen } 362*013934d8SVesa Jääskeläinen 363*013934d8SVesa Jääskeläinen enum pkcs11_rc entry_generate_key_pair(struct pkcs11_client *client, 364*013934d8SVesa Jääskeläinen uint32_t ptypes, TEE_Param *params) 365*013934d8SVesa Jääskeläinen { 366*013934d8SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 367*013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 368*013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_MEMREF_OUTPUT, 369*013934d8SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 370*013934d8SVesa Jääskeläinen TEE_Param *ctrl = params; 371*013934d8SVesa Jääskeläinen TEE_Param *out = params + 2; 372*013934d8SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 373*013934d8SVesa Jääskeläinen struct serialargs ctrlargs = { }; 374*013934d8SVesa Jääskeläinen struct pkcs11_session *session = NULL; 375*013934d8SVesa Jääskeläinen struct pkcs11_attribute_head *proc_params = NULL; 376*013934d8SVesa Jääskeläinen struct obj_attrs *pub_head = NULL; 377*013934d8SVesa Jääskeläinen struct obj_attrs *priv_head = NULL; 378*013934d8SVesa Jääskeläinen struct pkcs11_object_head *pub_template = NULL; 379*013934d8SVesa Jääskeläinen struct pkcs11_object_head *priv_template = NULL; 380*013934d8SVesa Jääskeläinen struct pkcs11_object *object = NULL; 381*013934d8SVesa Jääskeläinen size_t pub_template_size = 0; 382*013934d8SVesa Jääskeläinen size_t priv_template_size = 0; 383*013934d8SVesa Jääskeläinen uint32_t pubkey_handle = 0; 384*013934d8SVesa Jääskeläinen uint32_t privkey_handle = 0; 385*013934d8SVesa Jääskeläinen uint32_t *hdl_ptr = NULL; 386*013934d8SVesa Jääskeläinen size_t out_ref_size = sizeof(pubkey_handle) + sizeof(privkey_handle); 387*013934d8SVesa Jääskeläinen 388*013934d8SVesa Jääskeläinen if (!client || ptypes != exp_pt || out->memref.size != out_ref_size) 389*013934d8SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 390*013934d8SVesa Jääskeläinen 391*013934d8SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 392*013934d8SVesa Jääskeläinen 393*013934d8SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 394*013934d8SVesa Jääskeläinen if (rc) 395*013934d8SVesa Jääskeläinen return rc; 396*013934d8SVesa Jääskeläinen 397*013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 398*013934d8SVesa Jääskeläinen if (rc) 399*013934d8SVesa Jääskeläinen goto out; 400*013934d8SVesa Jääskeläinen 401*013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_attributes(&ctrlargs, &pub_template); 402*013934d8SVesa Jääskeläinen if (rc) 403*013934d8SVesa Jääskeläinen goto out; 404*013934d8SVesa Jääskeläinen 405*013934d8SVesa Jääskeläinen rc = serialargs_alloc_get_attributes(&ctrlargs, &priv_template); 406*013934d8SVesa Jääskeläinen if (rc) 407*013934d8SVesa Jääskeläinen goto out; 408*013934d8SVesa Jääskeläinen 409*013934d8SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) { 410*013934d8SVesa Jääskeläinen rc = PKCS11_CKR_ARGUMENTS_BAD; 411*013934d8SVesa Jääskeläinen goto out; 412*013934d8SVesa Jääskeläinen } 413*013934d8SVesa Jääskeläinen 414*013934d8SVesa Jääskeläinen rc = get_ready_session(session); 415*013934d8SVesa Jääskeläinen if (rc) 416*013934d8SVesa Jääskeläinen goto out; 417*013934d8SVesa Jääskeläinen 418*013934d8SVesa Jääskeläinen rc = check_mechanism_against_processing(session, proc_params->id, 419*013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR, 420*013934d8SVesa Jääskeläinen PKCS11_FUNC_STEP_INIT); 421*013934d8SVesa Jääskeläinen if (rc) 422*013934d8SVesa Jääskeläinen goto out; 423*013934d8SVesa Jääskeläinen 424*013934d8SVesa Jääskeläinen pub_template_size = sizeof(*pub_template) + pub_template->attrs_size; 425*013934d8SVesa Jääskeläinen 426*013934d8SVesa Jääskeläinen rc = create_attributes_from_template(&pub_head, pub_template, 427*013934d8SVesa Jääskeläinen pub_template_size, NULL, 428*013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR, 429*013934d8SVesa Jääskeläinen proc_params->id, 430*013934d8SVesa Jääskeläinen PKCS11_CKO_PUBLIC_KEY); 431*013934d8SVesa Jääskeläinen if (rc) 432*013934d8SVesa Jääskeläinen goto out; 433*013934d8SVesa Jääskeläinen 434*013934d8SVesa Jääskeläinen TEE_Free(pub_template); 435*013934d8SVesa Jääskeläinen pub_template = NULL; 436*013934d8SVesa Jääskeläinen 437*013934d8SVesa Jääskeläinen priv_template_size = sizeof(*priv_template) + 438*013934d8SVesa Jääskeläinen priv_template->attrs_size; 439*013934d8SVesa Jääskeläinen 440*013934d8SVesa Jääskeläinen rc = create_attributes_from_template(&priv_head, priv_template, 441*013934d8SVesa Jääskeläinen priv_template_size, NULL, 442*013934d8SVesa Jääskeläinen PKCS11_FUNCTION_GENERATE_PAIR, 443*013934d8SVesa Jääskeläinen proc_params->id, 444*013934d8SVesa Jääskeläinen PKCS11_CKO_PRIVATE_KEY); 445*013934d8SVesa Jääskeläinen if (rc) 446*013934d8SVesa Jääskeläinen goto out; 447*013934d8SVesa Jääskeläinen 448*013934d8SVesa Jääskeläinen TEE_Free(priv_template); 449*013934d8SVesa Jääskeläinen priv_template = NULL; 450*013934d8SVesa Jääskeläinen 451*013934d8SVesa Jääskeläinen /* Generate CKA_ID for keys if not specified by the templates */ 452*013934d8SVesa Jääskeläinen rc = add_missing_attribute_id(&pub_head, &priv_head); 453*013934d8SVesa Jääskeläinen if (rc) 454*013934d8SVesa Jääskeläinen goto out; 455*013934d8SVesa Jääskeläinen 456*013934d8SVesa Jääskeläinen /* Check created object against processing and token state */ 457*013934d8SVesa Jääskeläinen rc = check_created_attrs(pub_head, priv_head); 458*013934d8SVesa Jääskeläinen if (rc) 459*013934d8SVesa Jääskeläinen goto out; 460*013934d8SVesa Jääskeläinen 461*013934d8SVesa Jääskeläinen rc = check_created_attrs_against_processing(proc_params->id, pub_head); 462*013934d8SVesa Jääskeläinen if (rc) 463*013934d8SVesa Jääskeläinen goto out; 464*013934d8SVesa Jääskeläinen 465*013934d8SVesa Jääskeläinen rc = check_created_attrs_against_processing(proc_params->id, 466*013934d8SVesa Jääskeläinen priv_head); 467*013934d8SVesa Jääskeläinen if (rc) 468*013934d8SVesa Jääskeläinen goto out; 469*013934d8SVesa Jääskeläinen 470*013934d8SVesa Jääskeläinen rc = check_created_attrs_against_token(session, pub_head); 471*013934d8SVesa Jääskeläinen if (rc) 472*013934d8SVesa Jääskeläinen goto out; 473*013934d8SVesa Jääskeläinen 474*013934d8SVesa Jääskeläinen rc = check_access_attrs_against_token(session, pub_head); 475*013934d8SVesa Jääskeläinen if (rc) 476*013934d8SVesa Jääskeläinen goto out; 477*013934d8SVesa Jääskeläinen 478*013934d8SVesa Jääskeläinen rc = check_created_attrs_against_token(session, priv_head); 479*013934d8SVesa Jääskeläinen if (rc) 480*013934d8SVesa Jääskeläinen goto out; 481*013934d8SVesa Jääskeläinen 482*013934d8SVesa Jääskeläinen rc = check_access_attrs_against_token(session, priv_head); 483*013934d8SVesa Jääskeläinen if (rc) 484*013934d8SVesa Jääskeläinen goto out; 485*013934d8SVesa Jääskeläinen 486*013934d8SVesa Jääskeläinen /* Generate key pair */ 487*013934d8SVesa Jääskeläinen switch (proc_params->id) { 488*013934d8SVesa Jääskeläinen default: 489*013934d8SVesa Jääskeläinen rc = PKCS11_CKR_MECHANISM_INVALID; 490*013934d8SVesa Jääskeläinen break; 491*013934d8SVesa Jääskeläinen } 492*013934d8SVesa Jääskeläinen if (rc) 493*013934d8SVesa Jääskeläinen goto out; 494*013934d8SVesa Jääskeläinen 495*013934d8SVesa Jääskeläinen TEE_Free(proc_params); 496*013934d8SVesa Jääskeläinen proc_params = NULL; 497*013934d8SVesa Jääskeläinen 498*013934d8SVesa Jääskeläinen /* 499*013934d8SVesa Jääskeläinen * Object is ready, register it and return a handle. 500*013934d8SVesa Jääskeläinen */ 501*013934d8SVesa Jääskeläinen rc = create_object(session, pub_head, &pubkey_handle); 502*013934d8SVesa Jääskeläinen if (rc) 503*013934d8SVesa Jääskeläinen goto out; 504*013934d8SVesa Jääskeläinen 505*013934d8SVesa Jääskeläinen /* 506*013934d8SVesa Jääskeläinen * Now obj_handle (through the related struct pkcs11_object instance) 507*013934d8SVesa Jääskeläinen * owns the serialized buffer that holds the object attributes. 508*013934d8SVesa Jääskeläinen * We reset local pub_head to NULL to mark that ownership has been 509*013934d8SVesa Jääskeläinen * transferred. 510*013934d8SVesa Jääskeläinen */ 511*013934d8SVesa Jääskeläinen pub_head = NULL; 512*013934d8SVesa Jääskeläinen 513*013934d8SVesa Jääskeläinen rc = create_object(session, priv_head, &privkey_handle); 514*013934d8SVesa Jääskeläinen if (rc) 515*013934d8SVesa Jääskeläinen goto out; 516*013934d8SVesa Jääskeläinen 517*013934d8SVesa Jääskeläinen /* Ownership has been transferred so mark it with NULL */ 518*013934d8SVesa Jääskeläinen priv_head = NULL; 519*013934d8SVesa Jääskeläinen 520*013934d8SVesa Jääskeläinen hdl_ptr = (uint32_t *)out->memref.buffer; 521*013934d8SVesa Jääskeläinen 522*013934d8SVesa Jääskeläinen TEE_MemMove(hdl_ptr, &pubkey_handle, sizeof(pubkey_handle)); 523*013934d8SVesa Jääskeläinen TEE_MemMove(hdl_ptr + 1, &privkey_handle, sizeof(privkey_handle)); 524*013934d8SVesa Jääskeläinen 525*013934d8SVesa Jääskeläinen pubkey_handle = 0; 526*013934d8SVesa Jääskeläinen privkey_handle = 0; 527*013934d8SVesa Jääskeläinen 528*013934d8SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": create key pair %#"PRIx32"/%#"PRIx32, 529*013934d8SVesa Jääskeläinen session->handle, privkey_handle, pubkey_handle); 530*013934d8SVesa Jääskeläinen 531*013934d8SVesa Jääskeläinen out: 532*013934d8SVesa Jääskeläinen if (pubkey_handle) { 533*013934d8SVesa Jääskeläinen object = pkcs11_handle2object(pubkey_handle, session); 534*013934d8SVesa Jääskeläinen if (!object) 535*013934d8SVesa Jääskeläinen TEE_Panic(0); 536*013934d8SVesa Jääskeläinen destroy_object(session, object, false); 537*013934d8SVesa Jääskeläinen } 538*013934d8SVesa Jääskeläinen TEE_Free(priv_head); 539*013934d8SVesa Jääskeläinen TEE_Free(pub_head); 540*013934d8SVesa Jääskeläinen TEE_Free(priv_template); 541*013934d8SVesa Jääskeläinen TEE_Free(pub_template); 542*013934d8SVesa Jääskeläinen TEE_Free(proc_params); 543*013934d8SVesa Jääskeläinen 544*013934d8SVesa Jääskeläinen return rc; 545*013934d8SVesa Jääskeläinen } 546*013934d8SVesa Jääskeläinen 547512cbf1dSJens Wiklander /* 548512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing 549512cbf1dSJens Wiklander * 550512cbf1dSJens Wiklander * @client = client reference 551512cbf1dSJens Wiklander * @ptype = Invocation parameter types 552512cbf1dSJens Wiklander * @params = Invocation parameters reference 553512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 554512cbf1dSJens Wiklander */ 555512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 556512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 557512cbf1dSJens Wiklander enum processing_func function) 558512cbf1dSJens Wiklander { 559512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 560512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 561512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 562512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE); 563512cbf1dSJens Wiklander TEE_Param *ctrl = params; 564512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 565512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 566512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 567512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL; 568512cbf1dSJens Wiklander uint32_t key_handle = 0; 569512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL; 570512cbf1dSJens Wiklander 571512cbf1dSJens Wiklander if (!client || ptypes != exp_pt) 572512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 573512cbf1dSJens Wiklander 574512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 575512cbf1dSJens Wiklander 576512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 577512cbf1dSJens Wiklander if (rc) 578512cbf1dSJens Wiklander return rc; 579512cbf1dSJens Wiklander 5809e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) { 581512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 582512cbf1dSJens Wiklander if (rc) 583512cbf1dSJens Wiklander return rc; 5849e91a619SVesa Jääskeläinen } 585512cbf1dSJens Wiklander 586512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 587512cbf1dSJens Wiklander if (rc) 588512cbf1dSJens Wiklander return rc; 589512cbf1dSJens Wiklander 590512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 591512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 592512cbf1dSJens Wiklander goto out; 593512cbf1dSJens Wiklander } 594512cbf1dSJens Wiklander 595512cbf1dSJens Wiklander rc = get_ready_session(session); 596512cbf1dSJens Wiklander if (rc) 597512cbf1dSJens Wiklander goto out; 598512cbf1dSJens Wiklander 5999e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) { 600512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session); 601512cbf1dSJens Wiklander if (!obj) { 602512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID; 603512cbf1dSJens Wiklander goto out; 604512cbf1dSJens Wiklander } 6059e91a619SVesa Jääskeläinen } 606512cbf1dSJens Wiklander 607512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL); 608512cbf1dSJens Wiklander if (rc) 609512cbf1dSJens Wiklander goto out; 610512cbf1dSJens Wiklander 611512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id, 612512cbf1dSJens Wiklander function, 613512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT); 614512cbf1dSJens Wiklander if (rc) 615512cbf1dSJens Wiklander goto out; 616512cbf1dSJens Wiklander 6179e91a619SVesa Jääskeläinen if (obj) { 6189e91a619SVesa Jääskeläinen rc = check_parent_attrs_against_processing(proc_params->id, 6199e91a619SVesa Jääskeläinen function, 620512cbf1dSJens Wiklander obj->attributes); 621512cbf1dSJens Wiklander if (rc) 622512cbf1dSJens Wiklander goto out; 623512cbf1dSJens Wiklander 6249e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session, 6259e91a619SVesa Jääskeläinen obj->attributes); 626512cbf1dSJens Wiklander if (rc) 627512cbf1dSJens Wiklander goto out; 6289e91a619SVesa Jääskeläinen } 629512cbf1dSJens Wiklander 630512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id)) 631512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj); 6329e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(proc_params->id)) 6339e91a619SVesa Jääskeläinen rc = init_digest_operation(session, proc_params); 634512cbf1dSJens Wiklander else 635512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 636512cbf1dSJens Wiklander 637512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 638512cbf1dSJens Wiklander session->processing->mecha_type = proc_params->id; 639512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s", 640512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id), 641512cbf1dSJens Wiklander id2str_function(function)); 642512cbf1dSJens Wiklander } 643512cbf1dSJens Wiklander 644512cbf1dSJens Wiklander out: 645512cbf1dSJens Wiklander if (rc && session) 646512cbf1dSJens Wiklander release_active_processing(session); 647512cbf1dSJens Wiklander 648512cbf1dSJens Wiklander TEE_Free(proc_params); 649512cbf1dSJens Wiklander 650512cbf1dSJens Wiklander return rc; 651512cbf1dSJens Wiklander } 652512cbf1dSJens Wiklander 653512cbf1dSJens Wiklander /* 654512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing 655512cbf1dSJens Wiklander * 656512cbf1dSJens Wiklander * @client = client reference 657512cbf1dSJens Wiklander * @ptype = Invocation parameter types 658512cbf1dSJens Wiklander * @params = Invocation parameters reference 659512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 660512cbf1dSJens Wiklander * @step - update, oneshot, final 661512cbf1dSJens Wiklander */ 662512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 663512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 664512cbf1dSJens Wiklander enum processing_func function, 665512cbf1dSJens Wiklander enum processing_step step) 666512cbf1dSJens Wiklander { 667512cbf1dSJens Wiklander TEE_Param *ctrl = params; 668512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 669512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 670512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 671512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 6729e91a619SVesa Jääskeläinen uint32_t key_handle = 0; 6739e91a619SVesa Jääskeläinen struct pkcs11_object *obj = NULL; 674512cbf1dSJens Wiklander 675512cbf1dSJens Wiklander if (!client || 676512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 677512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 678512cbf1dSJens Wiklander 679512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 680512cbf1dSJens Wiklander 681512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 682512cbf1dSJens Wiklander if (rc) 683512cbf1dSJens Wiklander return rc; 684512cbf1dSJens Wiklander 6859e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 6869e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST); 6879e91a619SVesa Jääskeläinen 6889e91a619SVesa Jääskeläinen rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 6899e91a619SVesa Jääskeläinen if (rc) 6909e91a619SVesa Jääskeläinen return rc; 6919e91a619SVesa Jääskeläinen } 6929e91a619SVesa Jääskeläinen 693512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 694512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 695512cbf1dSJens Wiklander 696512cbf1dSJens Wiklander rc = get_active_session(session, function); 697512cbf1dSJens Wiklander if (rc) 698512cbf1dSJens Wiklander return rc; 699512cbf1dSJens Wiklander 7009e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 7019e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST); 7029e91a619SVesa Jääskeläinen 7039e91a619SVesa Jääskeläinen obj = pkcs11_handle2object(key_handle, session); 7049e91a619SVesa Jääskeläinen if (!obj) { 7059e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID; 7069e91a619SVesa Jääskeläinen goto out; 7079e91a619SVesa Jääskeläinen } 7089e91a619SVesa Jääskeläinen 7099e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session, 7109e91a619SVesa Jääskeläinen obj->attributes); 7119e91a619SVesa Jääskeläinen if (rc) { 7129e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID; 7139e91a619SVesa Jääskeläinen goto out; 7149e91a619SVesa Jääskeläinen } 7159e91a619SVesa Jääskeläinen } 7169e91a619SVesa Jääskeläinen 717512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 718512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 719512cbf1dSJens Wiklander function, step); 720512cbf1dSJens Wiklander if (rc) 721512cbf1dSJens Wiklander goto out; 722512cbf1dSJens Wiklander 723512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 724512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 725512cbf1dSJens Wiklander ptypes, params); 7269e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(mecha_type)) 7279e91a619SVesa Jääskeläinen rc = step_digest_operation(session, step, obj, ptypes, params); 728512cbf1dSJens Wiklander else 729512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 730512cbf1dSJens Wiklander 7319e91a619SVesa Jääskeläinen if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE || 7329e91a619SVesa Jääskeläinen step == PKCS11_FUNC_STEP_UPDATE_KEY)) { 733512cbf1dSJens Wiklander session->processing->updated = true; 734512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s", 735512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type), 736512cbf1dSJens Wiklander id2str_function(function)); 737512cbf1dSJens Wiklander } 738512cbf1dSJens Wiklander 739512cbf1dSJens Wiklander out: 740512cbf1dSJens Wiklander switch (step) { 741512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE: 7429e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE_KEY: 743512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 744512cbf1dSJens Wiklander release_active_processing(session); 745512cbf1dSJens Wiklander break; 746512cbf1dSJens Wiklander default: 747512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */ 748512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 749512cbf1dSJens Wiklander release_active_processing(session); 750512cbf1dSJens Wiklander break; 751512cbf1dSJens Wiklander } 752512cbf1dSJens Wiklander 753512cbf1dSJens Wiklander return rc; 754512cbf1dSJens Wiklander } 75548799892SRuchika Gupta 7564dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, 7574dad6642SRuchika Gupta uint32_t ptypes, TEE_Param *params, 7584dad6642SRuchika Gupta enum processing_func function) 75948799892SRuchika Gupta { 76048799892SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 76148799892SRuchika Gupta TEE_PARAM_TYPE_NONE, 76248799892SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 76348799892SRuchika Gupta TEE_PARAM_TYPE_NONE); 76448799892SRuchika Gupta TEE_Param *ctrl = params; 76548799892SRuchika Gupta TEE_Param *out = params + 2; 76648799892SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 76748799892SRuchika Gupta struct serialargs ctrlargs = { }; 76848799892SRuchika Gupta struct pkcs11_session *session = NULL; 76948799892SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 77048799892SRuchika Gupta struct pkcs11_object_head *template = NULL; 77148799892SRuchika Gupta uint32_t parent_handle = 0; 77248799892SRuchika Gupta uint32_t obj_handle = 0; 77348799892SRuchika Gupta struct pkcs11_object *parent = NULL; 77448799892SRuchika Gupta struct obj_attrs *head = NULL; 77548799892SRuchika Gupta size_t template_size = 0; 7768c499324SRuchika Gupta void *out_buf = NULL; 7778c499324SRuchika Gupta uint32_t out_size = 0; 77848799892SRuchika Gupta 77948799892SRuchika Gupta if (!client || ptypes != exp_pt || 78048799892SRuchika Gupta out->memref.size != sizeof(obj_handle)) 78148799892SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 78248799892SRuchika Gupta 78348799892SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 78448799892SRuchika Gupta 78548799892SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 78648799892SRuchika Gupta if (rc) 78748799892SRuchika Gupta return rc; 78848799892SRuchika Gupta 78948799892SRuchika Gupta rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); 79048799892SRuchika Gupta if (rc) 79148799892SRuchika Gupta return rc; 79248799892SRuchika Gupta 79348799892SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 79448799892SRuchika Gupta if (rc) 79548799892SRuchika Gupta goto out_free; 79648799892SRuchika Gupta 79748799892SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 79848799892SRuchika Gupta if (rc) 79948799892SRuchika Gupta goto out_free; 80048799892SRuchika Gupta 80148799892SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 80248799892SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 80348799892SRuchika Gupta goto out_free; 80448799892SRuchika Gupta } 80548799892SRuchika Gupta 80648799892SRuchika Gupta /* Return error if processing already active */ 80748799892SRuchika Gupta rc = get_ready_session(session); 80848799892SRuchika Gupta if (rc) 80948799892SRuchika Gupta goto out_free; 81048799892SRuchika Gupta 81148799892SRuchika Gupta /* Check parent handle */ 81248799892SRuchika Gupta parent = pkcs11_handle2object(parent_handle, session); 81348799892SRuchika Gupta if (!parent) { 81448799892SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID; 81548799892SRuchika Gupta goto out_free; 81648799892SRuchika Gupta } 81748799892SRuchika Gupta 81848799892SRuchika Gupta /* Check if mechanism can be used for derivation function */ 81948799892SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 82048799892SRuchika Gupta function, 82148799892SRuchika Gupta PKCS11_FUNC_STEP_INIT); 82248799892SRuchika Gupta if (rc) 82348799892SRuchika Gupta goto out_free; 82448799892SRuchika Gupta 82548799892SRuchika Gupta /* Set the processing state to active */ 82648799892SRuchika Gupta rc = set_processing_state(session, function, parent, NULL); 82748799892SRuchika Gupta if (rc) 82848799892SRuchika Gupta goto out_free; 82948799892SRuchika Gupta 83048799892SRuchika Gupta /* 83148799892SRuchika Gupta * Check if base/parent key has CKA_DERIVE set and its key type is 83248799892SRuchika Gupta * compatible with the mechanism passed 83348799892SRuchika Gupta */ 83448799892SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function, 83548799892SRuchika Gupta parent->attributes); 836d05ab5feSRuchika Gupta if (rc) { 837d05ab5feSRuchika Gupta /* 838d05ab5feSRuchika Gupta * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors 839d05ab5feSRuchika Gupta * specified with C_Derive/Unwrap() in the specification. So 840d05ab5feSRuchika Gupta * return the next most appropriate error. 841d05ab5feSRuchika Gupta */ 842d05ab5feSRuchika Gupta if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) 843d05ab5feSRuchika Gupta rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; 84448799892SRuchika Gupta goto out; 845d05ab5feSRuchika Gupta } 84648799892SRuchika Gupta 84748799892SRuchika Gupta /* Check access of base/parent key */ 84848799892SRuchika Gupta rc = check_access_attrs_against_token(session, parent->attributes); 84948799892SRuchika Gupta if (rc) 85048799892SRuchika Gupta goto out; 85148799892SRuchika Gupta 85248799892SRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 85348799892SRuchika Gupta /* 85448799892SRuchika Gupta * Prepare a clean initial state for the requested object attributes 85548799892SRuchika Gupta * using base/parent key attributes. Free temporary template once done. 85648799892SRuchika Gupta */ 85748799892SRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 85848799892SRuchika Gupta parent->attributes, 85948799892SRuchika Gupta function, 86048799892SRuchika Gupta proc_params->id, 86148799892SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 86248799892SRuchika Gupta if (rc) 86348799892SRuchika Gupta goto out; 86448799892SRuchika Gupta 86548799892SRuchika Gupta TEE_Free(template); 86648799892SRuchika Gupta template = NULL; 86748799892SRuchika Gupta 86848799892SRuchika Gupta /* check_created_attrs() is called later once key size is known */ 86948799892SRuchika Gupta 87048799892SRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 87148799892SRuchika Gupta if (rc) 87248799892SRuchika Gupta goto out; 87348799892SRuchika Gupta 87448799892SRuchika Gupta rc = check_created_attrs_against_token(session, head); 87548799892SRuchika Gupta if (rc) 87648799892SRuchika Gupta goto out; 87748799892SRuchika Gupta 8788c499324SRuchika Gupta if (processing_is_tee_symm(proc_params->id)) { 87948799892SRuchika Gupta /* 88048799892SRuchika Gupta * These derivation mechanism require encryption to be 88148799892SRuchika Gupta * performed on the data passed in proc_params by parent 88248799892SRuchika Gupta * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT 88348799892SRuchika Gupta * to init_symm_operation() 88448799892SRuchika Gupta */ 88548799892SRuchika Gupta rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, 88648799892SRuchika Gupta proc_params, parent); 88748799892SRuchika Gupta if (rc) 88848799892SRuchika Gupta goto out; 88948799892SRuchika Gupta 8908c499324SRuchika Gupta session->processing->mecha_type = proc_params->id; 8918c499324SRuchika Gupta 8928c499324SRuchika Gupta rc = derive_key_by_symm_enc(session, &out_buf, &out_size); 89348799892SRuchika Gupta if (rc) 89448799892SRuchika Gupta goto out; 8958c499324SRuchika Gupta } else { 89648799892SRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 89748799892SRuchika Gupta goto out; 89848799892SRuchika Gupta } 89948799892SRuchika Gupta 9008c499324SRuchika Gupta rc = set_key_data(&head, out_buf, out_size); 9018c499324SRuchika Gupta if (rc) 9028c499324SRuchika Gupta goto out; 9038c499324SRuchika Gupta 9048c499324SRuchika Gupta TEE_Free(out_buf); 9058c499324SRuchika Gupta out_buf = NULL; 9068c499324SRuchika Gupta 90748799892SRuchika Gupta TEE_Free(proc_params); 90848799892SRuchika Gupta proc_params = NULL; 90948799892SRuchika Gupta 91048799892SRuchika Gupta /* 91148799892SRuchika Gupta * Object is ready, register it and return a handle. 91248799892SRuchika Gupta */ 91348799892SRuchika Gupta rc = create_object(session, head, &obj_handle); 91448799892SRuchika Gupta if (rc) 91548799892SRuchika Gupta goto out; 91648799892SRuchika Gupta 91748799892SRuchika Gupta /* 91848799892SRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 91948799892SRuchika Gupta * owns the serialized buffer that holds the object attributes. 92048799892SRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 92148799892SRuchika Gupta * be freed at function out. 92248799892SRuchika Gupta */ 92348799892SRuchika Gupta head = NULL; 92448799892SRuchika Gupta 92548799892SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 92648799892SRuchika Gupta out->memref.size = sizeof(obj_handle); 92748799892SRuchika Gupta 92848799892SRuchika Gupta DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, 92948799892SRuchika Gupta session->handle, obj_handle); 93048799892SRuchika Gupta 93148799892SRuchika Gupta out: 93248799892SRuchika Gupta release_active_processing(session); 93348799892SRuchika Gupta out_free: 93448799892SRuchika Gupta TEE_Free(proc_params); 93548799892SRuchika Gupta TEE_Free(template); 93648799892SRuchika Gupta TEE_Free(head); 9378c499324SRuchika Gupta TEE_Free(out_buf); 93848799892SRuchika Gupta 93948799892SRuchika Gupta return rc; 94048799892SRuchika Gupta } 941eb6141b6SVesa Jääskeläinen 942eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, 943eb6141b6SVesa Jääskeläinen uint32_t ptypes, 944eb6141b6SVesa Jääskeläinen TEE_Param *params) 945eb6141b6SVesa Jääskeläinen { 946eb6141b6SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 947eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 948eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 949eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 950eb6141b6SVesa Jääskeläinen TEE_Param *ctrl = params; 951eb6141b6SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK; 952eb6141b6SVesa Jääskeläinen struct serialargs ctrlargs = { }; 953eb6141b6SVesa Jääskeläinen struct pkcs11_session *session = NULL; 954eb6141b6SVesa Jääskeläinen enum processing_func function = PKCS11_FUNCTION_UNKNOWN; 955eb6141b6SVesa Jääskeläinen uint32_t cmd = 0; 956eb6141b6SVesa Jääskeläinen 957eb6141b6SVesa Jääskeläinen if (!client || ptypes != exp_pt) 958eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 959eb6141b6SVesa Jääskeläinen 960eb6141b6SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 961eb6141b6SVesa Jääskeläinen 962eb6141b6SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 963eb6141b6SVesa Jääskeläinen if (rc) 964eb6141b6SVesa Jääskeläinen return rc; 965eb6141b6SVesa Jääskeläinen 966eb6141b6SVesa Jääskeläinen rc = serialargs_get_u32(&ctrlargs, &cmd); 967eb6141b6SVesa Jääskeläinen 968eb6141b6SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) 969eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 970eb6141b6SVesa Jääskeläinen 971eb6141b6SVesa Jääskeläinen function = func_for_cmd(cmd); 972eb6141b6SVesa Jääskeläinen if (function == PKCS11_FUNCTION_UNKNOWN) 973eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 974eb6141b6SVesa Jääskeläinen 975eb6141b6SVesa Jääskeläinen rc = get_active_session(session, function); 976eb6141b6SVesa Jääskeläinen if (rc) 977eb6141b6SVesa Jääskeläinen return rc; 978eb6141b6SVesa Jääskeläinen 979eb6141b6SVesa Jääskeläinen release_active_processing(session); 980eb6141b6SVesa Jääskeläinen 981eb6141b6SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": release processing", session->handle); 982eb6141b6SVesa Jääskeläinen 983eb6141b6SVesa Jääskeläinen return PKCS11_CKR_OK; 984eb6141b6SVesa Jääskeläinen } 985