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 30*eb6141b6SVesa Jääskeläinen static enum processing_func func_for_cmd(enum pkcs11_ta_cmd cmd) 31*eb6141b6SVesa Jääskeläinen { 32*eb6141b6SVesa Jääskeläinen switch (cmd) { 33*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_UPDATE: 34*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_ONESHOT: 35*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_ENCRYPT_FINAL: 36*eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_ENCRYPT; 37*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_UPDATE: 38*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_ONESHOT: 39*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_DECRYPT_FINAL: 40*eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_DECRYPT; 41*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_ONESHOT: 42*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_UPDATE: 43*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_SIGN_FINAL: 44*eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_SIGN; 45*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_ONESHOT: 46*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_UPDATE: 47*eb6141b6SVesa Jääskeläinen case PKCS11_CMD_VERIFY_FINAL: 48*eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_VERIFY; 49*eb6141b6SVesa Jääskeläinen default: 50*eb6141b6SVesa Jääskeläinen return PKCS11_FUNCTION_UNKNOWN; 51*eb6141b6SVesa Jääskeläinen } 52*eb6141b6SVesa Jääskeläinen } 53*eb6141b6SVesa Jääskeläinen 54512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function, 55512cbf1dSJens Wiklander enum pkcs11_proc_state state) 56512cbf1dSJens Wiklander { 57512cbf1dSJens Wiklander switch (function) { 58512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT: 59512cbf1dSJens Wiklander return state == PKCS11_SESSION_ENCRYPTING || 60512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING || 61512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 62512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT: 63512cbf1dSJens Wiklander return state == PKCS11_SESSION_DECRYPTING || 64512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_DIGESTING || 65512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 66512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST: 67512cbf1dSJens Wiklander return state == PKCS11_SESSION_DIGESTING || 68512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING; 69512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN: 70512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING || 71512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 72512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY: 73512cbf1dSJens Wiklander return state == PKCS11_SESSION_VERIFYING || 74512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 75512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN_RECOVER: 76512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 77512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY_RECOVER: 78512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 79512cbf1dSJens Wiklander default: 80512cbf1dSJens Wiklander TEE_Panic(function); 81512cbf1dSJens Wiklander return false; 82512cbf1dSJens Wiklander } 83512cbf1dSJens Wiklander } 84512cbf1dSJens Wiklander 85512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session, 86512cbf1dSJens Wiklander enum processing_func function) 87512cbf1dSJens Wiklander { 88512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; 89512cbf1dSJens Wiklander 90512cbf1dSJens Wiklander if (session->processing && 91512cbf1dSJens Wiklander func_matches_state(function, session->processing->state)) 92512cbf1dSJens Wiklander rc = PKCS11_CKR_OK; 93512cbf1dSJens Wiklander 94512cbf1dSJens Wiklander return rc; 95512cbf1dSJens Wiklander } 96512cbf1dSJens Wiklander 97512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session) 98512cbf1dSJens Wiklander { 99512cbf1dSJens Wiklander if (!session->processing) 100512cbf1dSJens Wiklander return; 101512cbf1dSJens Wiklander 102512cbf1dSJens Wiklander if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 103512cbf1dSJens Wiklander TEE_FreeOperation(session->processing->tee_op_handle); 104512cbf1dSJens Wiklander session->processing->tee_op_handle = TEE_HANDLE_NULL; 105512cbf1dSJens Wiklander } 106512cbf1dSJens Wiklander 1072158ea6cSRuchika Gupta TEE_Free(session->processing->extra_ctx); 1082158ea6cSRuchika Gupta 109512cbf1dSJens Wiklander TEE_Free(session->processing); 110512cbf1dSJens Wiklander session->processing = NULL; 111512cbf1dSJens Wiklander } 112512cbf1dSJens Wiklander 113512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj) 114512cbf1dSJens Wiklander { 115512cbf1dSJens Wiklander uint32_t a_size = 0; 116512cbf1dSJens Wiklander struct obj_attrs *attrs = obj->attributes; 117512cbf1dSJens Wiklander 118512cbf1dSJens Wiklander switch (get_key_type(attrs)) { 119512cbf1dSJens Wiklander case PKCS11_CKK_AES: 120689f4e5bSRuchika Gupta case PKCS11_CKK_GENERIC_SECRET: 121689f4e5bSRuchika Gupta case PKCS11_CKK_MD5_HMAC: 122689f4e5bSRuchika Gupta case PKCS11_CKK_SHA_1_HMAC: 123689f4e5bSRuchika Gupta case PKCS11_CKK_SHA224_HMAC: 124689f4e5bSRuchika Gupta case PKCS11_CKK_SHA256_HMAC: 125689f4e5bSRuchika Gupta case PKCS11_CKK_SHA384_HMAC: 126689f4e5bSRuchika Gupta case PKCS11_CKK_SHA512_HMAC: 127512cbf1dSJens Wiklander if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 128512cbf1dSJens Wiklander return 0; 129512cbf1dSJens Wiklander 130512cbf1dSJens Wiklander return a_size * 8; 131512cbf1dSJens Wiklander default: 132512cbf1dSJens Wiklander TEE_Panic(0); 133512cbf1dSJens Wiklander return 0; 134512cbf1dSJens Wiklander } 135512cbf1dSJens Wiklander } 136512cbf1dSJens Wiklander 137fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) 138fa247a2aSRuchika Gupta { 139fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 140fa247a2aSRuchika Gupta void *data = NULL; 141fa247a2aSRuchika Gupta uint32_t data_size = 0; 142fa247a2aSRuchika Gupta uint32_t value_len = 0; 143fa247a2aSRuchika Gupta void *value = NULL; 144fa247a2aSRuchika Gupta 145fa247a2aSRuchika Gupta if (!*head) 146fa247a2aSRuchika Gupta return PKCS11_CKR_TEMPLATE_INCONSISTENT; 147fa247a2aSRuchika Gupta 148fa247a2aSRuchika Gupta rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); 149fa247a2aSRuchika Gupta if (rc || data_size != sizeof(uint32_t)) { 150fa247a2aSRuchika Gupta DMSG("%s", rc ? "No attribute value_len found" : 151fa247a2aSRuchika Gupta "Invalid size for attribute VALUE_LEN"); 152fa247a2aSRuchika Gupta 153fa247a2aSRuchika Gupta return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; 154fa247a2aSRuchika Gupta } 155fa247a2aSRuchika Gupta TEE_MemMove(&value_len, data, data_size); 156fa247a2aSRuchika Gupta 157fa247a2aSRuchika Gupta /* Remove the default empty value attribute if found */ 158fa247a2aSRuchika Gupta rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); 159fa247a2aSRuchika Gupta if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) 160fa247a2aSRuchika Gupta return PKCS11_CKR_GENERAL_ERROR; 161fa247a2aSRuchika Gupta 162fa247a2aSRuchika Gupta value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 163fa247a2aSRuchika Gupta if (!value) 164fa247a2aSRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY; 165fa247a2aSRuchika Gupta 166fa247a2aSRuchika Gupta TEE_GenerateRandom(value, value_len); 167fa247a2aSRuchika Gupta 168fa247a2aSRuchika Gupta rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); 169fa247a2aSRuchika Gupta 170fa247a2aSRuchika Gupta TEE_Free(value); 171fa247a2aSRuchika Gupta 172fa247a2aSRuchika Gupta return rc; 173fa247a2aSRuchika Gupta } 174fa247a2aSRuchika Gupta 175fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, 176fa247a2aSRuchika Gupta uint32_t ptypes, TEE_Param *params) 177fa247a2aSRuchika Gupta { 178fa247a2aSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 179fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE, 180fa247a2aSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 181fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE); 182fa247a2aSRuchika Gupta TEE_Param *ctrl = params; 183fa247a2aSRuchika Gupta TEE_Param *out = params + 2; 184fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 185fa247a2aSRuchika Gupta struct serialargs ctrlargs = { }; 186fa247a2aSRuchika Gupta struct pkcs11_session *session = NULL; 187fa247a2aSRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 188fa247a2aSRuchika Gupta struct obj_attrs *head = NULL; 189fa247a2aSRuchika Gupta struct pkcs11_object_head *template = NULL; 190fa247a2aSRuchika Gupta size_t template_size = 0; 191fa247a2aSRuchika Gupta uint32_t obj_handle = 0; 192fa247a2aSRuchika Gupta 193fa247a2aSRuchika Gupta if (!client || ptypes != exp_pt || 194fa247a2aSRuchika Gupta out->memref.size != sizeof(obj_handle)) 195fa247a2aSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 196fa247a2aSRuchika Gupta 197fa247a2aSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 198fa247a2aSRuchika Gupta 199fa247a2aSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 200fa247a2aSRuchika Gupta if (rc) 201fa247a2aSRuchika Gupta return rc; 202fa247a2aSRuchika Gupta 203fa247a2aSRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 204fa247a2aSRuchika Gupta if (rc) 205fa247a2aSRuchika Gupta goto out; 206fa247a2aSRuchika Gupta 207fa247a2aSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 208fa247a2aSRuchika Gupta if (rc) 209fa247a2aSRuchika Gupta goto out; 210fa247a2aSRuchika Gupta 211fa247a2aSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 212fa247a2aSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 213fa247a2aSRuchika Gupta goto out; 214fa247a2aSRuchika Gupta } 215fa247a2aSRuchika Gupta 216fa247a2aSRuchika Gupta rc = get_ready_session(session); 217fa247a2aSRuchika Gupta if (rc) 218fa247a2aSRuchika Gupta goto out; 219fa247a2aSRuchika Gupta 220fa247a2aSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 221fa247a2aSRuchika Gupta 222fa247a2aSRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 223fa247a2aSRuchika Gupta PKCS11_FUNCTION_GENERATE, 224fa247a2aSRuchika Gupta PKCS11_FUNC_STEP_INIT); 225fa247a2aSRuchika Gupta if (rc) { 226fa247a2aSRuchika Gupta DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); 227fa247a2aSRuchika Gupta goto out; 228fa247a2aSRuchika Gupta } 229fa247a2aSRuchika Gupta 230fa247a2aSRuchika Gupta /* 231fa247a2aSRuchika Gupta * Prepare a clean initial state for the requested object attributes. 232fa247a2aSRuchika Gupta * Free temporary template once done. 233fa247a2aSRuchika Gupta */ 234fa247a2aSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 235fa247a2aSRuchika Gupta NULL, PKCS11_FUNCTION_GENERATE, 2364cfce748SRuchika Gupta proc_params->id, 2374cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 238fa247a2aSRuchika Gupta if (rc) 239fa247a2aSRuchika Gupta goto out; 240fa247a2aSRuchika Gupta 241fa247a2aSRuchika Gupta TEE_Free(template); 242fa247a2aSRuchika Gupta template = NULL; 243fa247a2aSRuchika Gupta 244fa247a2aSRuchika Gupta rc = check_created_attrs(head, NULL); 245fa247a2aSRuchika Gupta if (rc) 246fa247a2aSRuchika Gupta goto out; 247fa247a2aSRuchika Gupta 248fa247a2aSRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 249fa247a2aSRuchika Gupta if (rc) 250fa247a2aSRuchika Gupta goto out; 251fa247a2aSRuchika Gupta 252fa247a2aSRuchika Gupta rc = check_created_attrs_against_token(session, head); 253fa247a2aSRuchika Gupta if (rc) 254fa247a2aSRuchika Gupta goto out; 255fa247a2aSRuchika Gupta 256fa247a2aSRuchika Gupta /* 257fa247a2aSRuchika Gupta * Execute target processing and add value as attribute 258fa247a2aSRuchika Gupta * PKCS11_CKA_VALUE. Symm key generation: depends on target 259fa247a2aSRuchika Gupta * processing to be used. 260fa247a2aSRuchika Gupta */ 261fa247a2aSRuchika Gupta switch (proc_params->id) { 262fa247a2aSRuchika Gupta case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: 263fa247a2aSRuchika Gupta case PKCS11_CKM_AES_KEY_GEN: 264fa247a2aSRuchika Gupta /* Generate random of size specified by attribute VALUE_LEN */ 265fa247a2aSRuchika Gupta rc = generate_random_key_value(&head); 266fa247a2aSRuchika Gupta if (rc) 267fa247a2aSRuchika Gupta goto out; 268fa247a2aSRuchika Gupta break; 269fa247a2aSRuchika Gupta 270fa247a2aSRuchika Gupta default: 271fa247a2aSRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 272fa247a2aSRuchika Gupta goto out; 273fa247a2aSRuchika Gupta } 274fa247a2aSRuchika Gupta 275fa247a2aSRuchika Gupta TEE_Free(proc_params); 276fa247a2aSRuchika Gupta proc_params = NULL; 277fa247a2aSRuchika Gupta 278fa247a2aSRuchika Gupta /* 279fa247a2aSRuchika Gupta * Object is ready, register it and return a handle. 280fa247a2aSRuchika Gupta */ 281fa247a2aSRuchika Gupta rc = create_object(session, head, &obj_handle); 282fa247a2aSRuchika Gupta if (rc) 283fa247a2aSRuchika Gupta goto out; 284fa247a2aSRuchika Gupta 285fa247a2aSRuchika Gupta /* 286fa247a2aSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 287fa247a2aSRuchika Gupta * owns the serialized buffer that holds the object attributes. 288fa247a2aSRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 289fa247a2aSRuchika Gupta * be freed at function out. 290fa247a2aSRuchika Gupta */ 291fa247a2aSRuchika Gupta head = NULL; 292fa247a2aSRuchika Gupta 293fa247a2aSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 294fa247a2aSRuchika Gupta out->memref.size = sizeof(obj_handle); 295fa247a2aSRuchika Gupta 296fa247a2aSRuchika Gupta DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, 297fa247a2aSRuchika Gupta session->handle, obj_handle); 298fa247a2aSRuchika Gupta 299fa247a2aSRuchika Gupta out: 300fa247a2aSRuchika Gupta TEE_Free(proc_params); 301fa247a2aSRuchika Gupta TEE_Free(template); 302fa247a2aSRuchika Gupta TEE_Free(head); 303fa247a2aSRuchika Gupta 304fa247a2aSRuchika Gupta return rc; 305fa247a2aSRuchika Gupta } 306fa247a2aSRuchika Gupta 307512cbf1dSJens Wiklander /* 308512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing 309512cbf1dSJens Wiklander * 310512cbf1dSJens Wiklander * @client = client reference 311512cbf1dSJens Wiklander * @ptype = Invocation parameter types 312512cbf1dSJens Wiklander * @params = Invocation parameters reference 313512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 314512cbf1dSJens Wiklander */ 315512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 316512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 317512cbf1dSJens Wiklander enum processing_func function) 318512cbf1dSJens Wiklander { 319512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 320512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 321512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 322512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE); 323512cbf1dSJens Wiklander TEE_Param *ctrl = params; 324512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 325512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 326512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 327512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL; 328512cbf1dSJens Wiklander uint32_t key_handle = 0; 329512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL; 330512cbf1dSJens Wiklander 331512cbf1dSJens Wiklander if (!client || ptypes != exp_pt) 332512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 333512cbf1dSJens Wiklander 334512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 335512cbf1dSJens Wiklander 336512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 337512cbf1dSJens Wiklander if (rc) 338512cbf1dSJens Wiklander return rc; 339512cbf1dSJens Wiklander 340512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 341512cbf1dSJens Wiklander if (rc) 342512cbf1dSJens Wiklander return rc; 343512cbf1dSJens Wiklander 344512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 345512cbf1dSJens Wiklander if (rc) 346512cbf1dSJens Wiklander return rc; 347512cbf1dSJens Wiklander 348512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 349512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 350512cbf1dSJens Wiklander goto out; 351512cbf1dSJens Wiklander } 352512cbf1dSJens Wiklander 353512cbf1dSJens Wiklander rc = get_ready_session(session); 354512cbf1dSJens Wiklander if (rc) 355512cbf1dSJens Wiklander goto out; 356512cbf1dSJens Wiklander 357512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session); 358512cbf1dSJens Wiklander if (!obj) { 359512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID; 360512cbf1dSJens Wiklander goto out; 361512cbf1dSJens Wiklander } 362512cbf1dSJens Wiklander 363512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL); 364512cbf1dSJens Wiklander if (rc) 365512cbf1dSJens Wiklander goto out; 366512cbf1dSJens Wiklander 367512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id, 368512cbf1dSJens Wiklander function, 369512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT); 370512cbf1dSJens Wiklander if (rc) 371512cbf1dSJens Wiklander goto out; 372512cbf1dSJens Wiklander 373512cbf1dSJens Wiklander rc = check_parent_attrs_against_processing(proc_params->id, function, 374512cbf1dSJens Wiklander obj->attributes); 375512cbf1dSJens Wiklander if (rc) 376512cbf1dSJens Wiklander goto out; 377512cbf1dSJens Wiklander 378512cbf1dSJens Wiklander rc = check_access_attrs_against_token(session, obj->attributes); 379512cbf1dSJens Wiklander if (rc) 380512cbf1dSJens Wiklander goto out; 381512cbf1dSJens Wiklander 382512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id)) 383512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj); 384512cbf1dSJens Wiklander else 385512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 386512cbf1dSJens Wiklander 387512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 388512cbf1dSJens Wiklander session->processing->mecha_type = proc_params->id; 389512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s", 390512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id), 391512cbf1dSJens Wiklander id2str_function(function)); 392512cbf1dSJens Wiklander } 393512cbf1dSJens Wiklander 394512cbf1dSJens Wiklander out: 395512cbf1dSJens Wiklander if (rc && session) 396512cbf1dSJens Wiklander release_active_processing(session); 397512cbf1dSJens Wiklander 398512cbf1dSJens Wiklander TEE_Free(proc_params); 399512cbf1dSJens Wiklander 400512cbf1dSJens Wiklander return rc; 401512cbf1dSJens Wiklander } 402512cbf1dSJens Wiklander 403512cbf1dSJens Wiklander /* 404512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing 405512cbf1dSJens Wiklander * 406512cbf1dSJens Wiklander * @client = client reference 407512cbf1dSJens Wiklander * @ptype = Invocation parameter types 408512cbf1dSJens Wiklander * @params = Invocation parameters reference 409512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 410512cbf1dSJens Wiklander * @step - update, oneshot, final 411512cbf1dSJens Wiklander */ 412512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 413512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 414512cbf1dSJens Wiklander enum processing_func function, 415512cbf1dSJens Wiklander enum processing_step step) 416512cbf1dSJens Wiklander { 417512cbf1dSJens Wiklander TEE_Param *ctrl = params; 418512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 419512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 420512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 421512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 422512cbf1dSJens Wiklander 423512cbf1dSJens Wiklander if (!client || 424512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 425512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 426512cbf1dSJens Wiklander 427512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 428512cbf1dSJens Wiklander 429512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 430512cbf1dSJens Wiklander if (rc) 431512cbf1dSJens Wiklander return rc; 432512cbf1dSJens Wiklander 433512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 434512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 435512cbf1dSJens Wiklander 436512cbf1dSJens Wiklander rc = get_active_session(session, function); 437512cbf1dSJens Wiklander if (rc) 438512cbf1dSJens Wiklander return rc; 439512cbf1dSJens Wiklander 440512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 441512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 442512cbf1dSJens Wiklander function, step); 443512cbf1dSJens Wiklander if (rc) 444512cbf1dSJens Wiklander goto out; 445512cbf1dSJens Wiklander 446512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 447512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 448512cbf1dSJens Wiklander ptypes, params); 449512cbf1dSJens Wiklander else 450512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 451512cbf1dSJens Wiklander 452689f4e5bSRuchika Gupta if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) { 453512cbf1dSJens Wiklander session->processing->updated = true; 454512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s", 455512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type), 456512cbf1dSJens Wiklander id2str_function(function)); 457512cbf1dSJens Wiklander } 458512cbf1dSJens Wiklander 459512cbf1dSJens Wiklander out: 460512cbf1dSJens Wiklander switch (step) { 461512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE: 462512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 463512cbf1dSJens Wiklander release_active_processing(session); 464512cbf1dSJens Wiklander break; 465512cbf1dSJens Wiklander default: 466512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */ 467512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 468512cbf1dSJens Wiklander release_active_processing(session); 469512cbf1dSJens Wiklander break; 470512cbf1dSJens Wiklander } 471512cbf1dSJens Wiklander 472512cbf1dSJens Wiklander return rc; 473512cbf1dSJens Wiklander } 47448799892SRuchika Gupta 4754dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, 4764dad6642SRuchika Gupta uint32_t ptypes, TEE_Param *params, 4774dad6642SRuchika Gupta enum processing_func function) 47848799892SRuchika Gupta { 47948799892SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 48048799892SRuchika Gupta TEE_PARAM_TYPE_NONE, 48148799892SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 48248799892SRuchika Gupta TEE_PARAM_TYPE_NONE); 48348799892SRuchika Gupta TEE_Param *ctrl = params; 48448799892SRuchika Gupta TEE_Param *out = params + 2; 48548799892SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 48648799892SRuchika Gupta struct serialargs ctrlargs = { }; 48748799892SRuchika Gupta struct pkcs11_session *session = NULL; 48848799892SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 48948799892SRuchika Gupta struct pkcs11_object_head *template = NULL; 49048799892SRuchika Gupta uint32_t parent_handle = 0; 49148799892SRuchika Gupta uint32_t obj_handle = 0; 49248799892SRuchika Gupta struct pkcs11_object *parent = NULL; 49348799892SRuchika Gupta struct obj_attrs *head = NULL; 49448799892SRuchika Gupta size_t template_size = 0; 4958c499324SRuchika Gupta void *out_buf = NULL; 4968c499324SRuchika Gupta uint32_t out_size = 0; 49748799892SRuchika Gupta 49848799892SRuchika Gupta if (!client || ptypes != exp_pt || 49948799892SRuchika Gupta out->memref.size != sizeof(obj_handle)) 50048799892SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 50148799892SRuchika Gupta 50248799892SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 50348799892SRuchika Gupta 50448799892SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 50548799892SRuchika Gupta if (rc) 50648799892SRuchika Gupta return rc; 50748799892SRuchika Gupta 50848799892SRuchika Gupta rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); 50948799892SRuchika Gupta if (rc) 51048799892SRuchika Gupta return rc; 51148799892SRuchika Gupta 51248799892SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 51348799892SRuchika Gupta if (rc) 51448799892SRuchika Gupta goto out_free; 51548799892SRuchika Gupta 51648799892SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 51748799892SRuchika Gupta if (rc) 51848799892SRuchika Gupta goto out_free; 51948799892SRuchika Gupta 52048799892SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 52148799892SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 52248799892SRuchika Gupta goto out_free; 52348799892SRuchika Gupta } 52448799892SRuchika Gupta 52548799892SRuchika Gupta /* Return error if processing already active */ 52648799892SRuchika Gupta rc = get_ready_session(session); 52748799892SRuchika Gupta if (rc) 52848799892SRuchika Gupta goto out_free; 52948799892SRuchika Gupta 53048799892SRuchika Gupta /* Check parent handle */ 53148799892SRuchika Gupta parent = pkcs11_handle2object(parent_handle, session); 53248799892SRuchika Gupta if (!parent) { 53348799892SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID; 53448799892SRuchika Gupta goto out_free; 53548799892SRuchika Gupta } 53648799892SRuchika Gupta 53748799892SRuchika Gupta /* Check if mechanism can be used for derivation function */ 53848799892SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 53948799892SRuchika Gupta function, 54048799892SRuchika Gupta PKCS11_FUNC_STEP_INIT); 54148799892SRuchika Gupta if (rc) 54248799892SRuchika Gupta goto out_free; 54348799892SRuchika Gupta 54448799892SRuchika Gupta /* Set the processing state to active */ 54548799892SRuchika Gupta rc = set_processing_state(session, function, parent, NULL); 54648799892SRuchika Gupta if (rc) 54748799892SRuchika Gupta goto out_free; 54848799892SRuchika Gupta 54948799892SRuchika Gupta /* 55048799892SRuchika Gupta * Check if base/parent key has CKA_DERIVE set and its key type is 55148799892SRuchika Gupta * compatible with the mechanism passed 55248799892SRuchika Gupta */ 55348799892SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function, 55448799892SRuchika Gupta parent->attributes); 555d05ab5feSRuchika Gupta if (rc) { 556d05ab5feSRuchika Gupta /* 557d05ab5feSRuchika Gupta * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors 558d05ab5feSRuchika Gupta * specified with C_Derive/Unwrap() in the specification. So 559d05ab5feSRuchika Gupta * return the next most appropriate error. 560d05ab5feSRuchika Gupta */ 561d05ab5feSRuchika Gupta if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) 562d05ab5feSRuchika Gupta rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; 56348799892SRuchika Gupta goto out; 564d05ab5feSRuchika Gupta } 56548799892SRuchika Gupta 56648799892SRuchika Gupta /* Check access of base/parent key */ 56748799892SRuchika Gupta rc = check_access_attrs_against_token(session, parent->attributes); 56848799892SRuchika Gupta if (rc) 56948799892SRuchika Gupta goto out; 57048799892SRuchika Gupta 57148799892SRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 57248799892SRuchika Gupta /* 57348799892SRuchika Gupta * Prepare a clean initial state for the requested object attributes 57448799892SRuchika Gupta * using base/parent key attributes. Free temporary template once done. 57548799892SRuchika Gupta */ 57648799892SRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 57748799892SRuchika Gupta parent->attributes, 57848799892SRuchika Gupta function, 57948799892SRuchika Gupta proc_params->id, 58048799892SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 58148799892SRuchika Gupta if (rc) 58248799892SRuchika Gupta goto out; 58348799892SRuchika Gupta 58448799892SRuchika Gupta TEE_Free(template); 58548799892SRuchika Gupta template = NULL; 58648799892SRuchika Gupta 58748799892SRuchika Gupta /* check_created_attrs() is called later once key size is known */ 58848799892SRuchika Gupta 58948799892SRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 59048799892SRuchika Gupta if (rc) 59148799892SRuchika Gupta goto out; 59248799892SRuchika Gupta 59348799892SRuchika Gupta rc = check_created_attrs_against_token(session, head); 59448799892SRuchika Gupta if (rc) 59548799892SRuchika Gupta goto out; 59648799892SRuchika Gupta 5978c499324SRuchika Gupta if (processing_is_tee_symm(proc_params->id)) { 59848799892SRuchika Gupta /* 59948799892SRuchika Gupta * These derivation mechanism require encryption to be 60048799892SRuchika Gupta * performed on the data passed in proc_params by parent 60148799892SRuchika Gupta * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT 60248799892SRuchika Gupta * to init_symm_operation() 60348799892SRuchika Gupta */ 60448799892SRuchika Gupta rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, 60548799892SRuchika Gupta proc_params, parent); 60648799892SRuchika Gupta if (rc) 60748799892SRuchika Gupta goto out; 60848799892SRuchika Gupta 6098c499324SRuchika Gupta session->processing->mecha_type = proc_params->id; 6108c499324SRuchika Gupta 6118c499324SRuchika Gupta rc = derive_key_by_symm_enc(session, &out_buf, &out_size); 61248799892SRuchika Gupta if (rc) 61348799892SRuchika Gupta goto out; 6148c499324SRuchika Gupta } else { 61548799892SRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 61648799892SRuchika Gupta goto out; 61748799892SRuchika Gupta } 61848799892SRuchika Gupta 6198c499324SRuchika Gupta rc = set_key_data(&head, out_buf, out_size); 6208c499324SRuchika Gupta if (rc) 6218c499324SRuchika Gupta goto out; 6228c499324SRuchika Gupta 6238c499324SRuchika Gupta TEE_Free(out_buf); 6248c499324SRuchika Gupta out_buf = NULL; 6258c499324SRuchika Gupta 62648799892SRuchika Gupta TEE_Free(proc_params); 62748799892SRuchika Gupta proc_params = NULL; 62848799892SRuchika Gupta 62948799892SRuchika Gupta /* 63048799892SRuchika Gupta * Object is ready, register it and return a handle. 63148799892SRuchika Gupta */ 63248799892SRuchika Gupta rc = create_object(session, head, &obj_handle); 63348799892SRuchika Gupta if (rc) 63448799892SRuchika Gupta goto out; 63548799892SRuchika Gupta 63648799892SRuchika Gupta /* 63748799892SRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 63848799892SRuchika Gupta * owns the serialized buffer that holds the object attributes. 63948799892SRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 64048799892SRuchika Gupta * be freed at function out. 64148799892SRuchika Gupta */ 64248799892SRuchika Gupta head = NULL; 64348799892SRuchika Gupta 64448799892SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 64548799892SRuchika Gupta out->memref.size = sizeof(obj_handle); 64648799892SRuchika Gupta 64748799892SRuchika Gupta DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, 64848799892SRuchika Gupta session->handle, obj_handle); 64948799892SRuchika Gupta 65048799892SRuchika Gupta out: 65148799892SRuchika Gupta release_active_processing(session); 65248799892SRuchika Gupta out_free: 65348799892SRuchika Gupta TEE_Free(proc_params); 65448799892SRuchika Gupta TEE_Free(template); 65548799892SRuchika Gupta TEE_Free(head); 6568c499324SRuchika Gupta TEE_Free(out_buf); 65748799892SRuchika Gupta 65848799892SRuchika Gupta return rc; 65948799892SRuchika Gupta } 660*eb6141b6SVesa Jääskeläinen 661*eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, 662*eb6141b6SVesa Jääskeläinen uint32_t ptypes, 663*eb6141b6SVesa Jääskeläinen TEE_Param *params) 664*eb6141b6SVesa Jääskeläinen { 665*eb6141b6SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 666*eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 667*eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 668*eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 669*eb6141b6SVesa Jääskeläinen TEE_Param *ctrl = params; 670*eb6141b6SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK; 671*eb6141b6SVesa Jääskeläinen struct serialargs ctrlargs = { }; 672*eb6141b6SVesa Jääskeläinen struct pkcs11_session *session = NULL; 673*eb6141b6SVesa Jääskeläinen enum processing_func function = PKCS11_FUNCTION_UNKNOWN; 674*eb6141b6SVesa Jääskeläinen uint32_t cmd = 0; 675*eb6141b6SVesa Jääskeläinen 676*eb6141b6SVesa Jääskeläinen if (!client || ptypes != exp_pt) 677*eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 678*eb6141b6SVesa Jääskeläinen 679*eb6141b6SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 680*eb6141b6SVesa Jääskeläinen 681*eb6141b6SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 682*eb6141b6SVesa Jääskeläinen if (rc) 683*eb6141b6SVesa Jääskeläinen return rc; 684*eb6141b6SVesa Jääskeläinen 685*eb6141b6SVesa Jääskeläinen rc = serialargs_get_u32(&ctrlargs, &cmd); 686*eb6141b6SVesa Jääskeläinen 687*eb6141b6SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) 688*eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 689*eb6141b6SVesa Jääskeläinen 690*eb6141b6SVesa Jääskeläinen function = func_for_cmd(cmd); 691*eb6141b6SVesa Jääskeläinen if (function == PKCS11_FUNCTION_UNKNOWN) 692*eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 693*eb6141b6SVesa Jääskeläinen 694*eb6141b6SVesa Jääskeläinen rc = get_active_session(session, function); 695*eb6141b6SVesa Jääskeläinen if (rc) 696*eb6141b6SVesa Jääskeläinen return rc; 697*eb6141b6SVesa Jääskeläinen 698*eb6141b6SVesa Jääskeläinen release_active_processing(session); 699*eb6141b6SVesa Jääskeläinen 700*eb6141b6SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": release processing", session->handle); 701*eb6141b6SVesa Jääskeläinen 702*eb6141b6SVesa Jääskeläinen return PKCS11_CKR_OK; 703*eb6141b6SVesa Jääskeläinen } 704