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 30512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function, 31512cbf1dSJens Wiklander enum pkcs11_proc_state state) 32512cbf1dSJens Wiklander { 33512cbf1dSJens Wiklander switch (function) { 34512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT: 35512cbf1dSJens Wiklander return state == PKCS11_SESSION_ENCRYPTING || 36512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING || 37512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 38512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT: 39512cbf1dSJens Wiklander return state == PKCS11_SESSION_DECRYPTING || 40512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_DIGESTING || 41512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 42512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST: 43512cbf1dSJens Wiklander return state == PKCS11_SESSION_DIGESTING || 44512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING; 45512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN: 46512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING || 47512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 48512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY: 49512cbf1dSJens Wiklander return state == PKCS11_SESSION_VERIFYING || 50512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 51512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN_RECOVER: 52512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 53512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY_RECOVER: 54512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 55512cbf1dSJens Wiklander default: 56512cbf1dSJens Wiklander TEE_Panic(function); 57512cbf1dSJens Wiklander return false; 58512cbf1dSJens Wiklander } 59512cbf1dSJens Wiklander } 60512cbf1dSJens Wiklander 61512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session, 62512cbf1dSJens Wiklander enum processing_func function) 63512cbf1dSJens Wiklander { 64512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; 65512cbf1dSJens Wiklander 66512cbf1dSJens Wiklander if (session->processing && 67512cbf1dSJens Wiklander func_matches_state(function, session->processing->state)) 68512cbf1dSJens Wiklander rc = PKCS11_CKR_OK; 69512cbf1dSJens Wiklander 70512cbf1dSJens Wiklander return rc; 71512cbf1dSJens Wiklander } 72512cbf1dSJens Wiklander 73512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session) 74512cbf1dSJens Wiklander { 75512cbf1dSJens Wiklander if (!session->processing) 76512cbf1dSJens Wiklander return; 77512cbf1dSJens Wiklander 78512cbf1dSJens Wiklander if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 79512cbf1dSJens Wiklander TEE_FreeOperation(session->processing->tee_op_handle); 80512cbf1dSJens Wiklander session->processing->tee_op_handle = TEE_HANDLE_NULL; 81512cbf1dSJens Wiklander } 82512cbf1dSJens Wiklander 832158ea6cSRuchika Gupta TEE_Free(session->processing->extra_ctx); 842158ea6cSRuchika Gupta 85512cbf1dSJens Wiklander TEE_Free(session->processing); 86512cbf1dSJens Wiklander session->processing = NULL; 87512cbf1dSJens Wiklander } 88512cbf1dSJens Wiklander 89512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj) 90512cbf1dSJens Wiklander { 91512cbf1dSJens Wiklander uint32_t a_size = 0; 92512cbf1dSJens Wiklander struct obj_attrs *attrs = obj->attributes; 93512cbf1dSJens Wiklander 94512cbf1dSJens Wiklander switch (get_key_type(attrs)) { 95512cbf1dSJens Wiklander case PKCS11_CKK_AES: 96689f4e5bSRuchika Gupta case PKCS11_CKK_GENERIC_SECRET: 97689f4e5bSRuchika Gupta case PKCS11_CKK_MD5_HMAC: 98689f4e5bSRuchika Gupta case PKCS11_CKK_SHA_1_HMAC: 99689f4e5bSRuchika Gupta case PKCS11_CKK_SHA224_HMAC: 100689f4e5bSRuchika Gupta case PKCS11_CKK_SHA256_HMAC: 101689f4e5bSRuchika Gupta case PKCS11_CKK_SHA384_HMAC: 102689f4e5bSRuchika Gupta case PKCS11_CKK_SHA512_HMAC: 103512cbf1dSJens Wiklander if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 104512cbf1dSJens Wiklander return 0; 105512cbf1dSJens Wiklander 106512cbf1dSJens Wiklander return a_size * 8; 107512cbf1dSJens Wiklander default: 108512cbf1dSJens Wiklander TEE_Panic(0); 109512cbf1dSJens Wiklander return 0; 110512cbf1dSJens Wiklander } 111512cbf1dSJens Wiklander } 112512cbf1dSJens Wiklander 113fa247a2aSRuchika Gupta static enum pkcs11_rc generate_random_key_value(struct obj_attrs **head) 114fa247a2aSRuchika Gupta { 115fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 116fa247a2aSRuchika Gupta void *data = NULL; 117fa247a2aSRuchika Gupta uint32_t data_size = 0; 118fa247a2aSRuchika Gupta uint32_t value_len = 0; 119fa247a2aSRuchika Gupta void *value = NULL; 120fa247a2aSRuchika Gupta 121fa247a2aSRuchika Gupta if (!*head) 122fa247a2aSRuchika Gupta return PKCS11_CKR_TEMPLATE_INCONSISTENT; 123fa247a2aSRuchika Gupta 124fa247a2aSRuchika Gupta rc = get_attribute_ptr(*head, PKCS11_CKA_VALUE_LEN, &data, &data_size); 125fa247a2aSRuchika Gupta if (rc || data_size != sizeof(uint32_t)) { 126fa247a2aSRuchika Gupta DMSG("%s", rc ? "No attribute value_len found" : 127fa247a2aSRuchika Gupta "Invalid size for attribute VALUE_LEN"); 128fa247a2aSRuchika Gupta 129fa247a2aSRuchika Gupta return PKCS11_CKR_ATTRIBUTE_VALUE_INVALID; 130fa247a2aSRuchika Gupta } 131fa247a2aSRuchika Gupta TEE_MemMove(&value_len, data, data_size); 132fa247a2aSRuchika Gupta 133fa247a2aSRuchika Gupta /* Remove the default empty value attribute if found */ 134fa247a2aSRuchika Gupta rc = remove_empty_attribute(head, PKCS11_CKA_VALUE); 135fa247a2aSRuchika Gupta if (rc != PKCS11_CKR_OK && rc != PKCS11_RV_NOT_FOUND) 136fa247a2aSRuchika Gupta return PKCS11_CKR_GENERAL_ERROR; 137fa247a2aSRuchika Gupta 138fa247a2aSRuchika Gupta value = TEE_Malloc(value_len, TEE_USER_MEM_HINT_NO_FILL_ZERO); 139fa247a2aSRuchika Gupta if (!value) 140fa247a2aSRuchika Gupta return PKCS11_CKR_DEVICE_MEMORY; 141fa247a2aSRuchika Gupta 142fa247a2aSRuchika Gupta TEE_GenerateRandom(value, value_len); 143fa247a2aSRuchika Gupta 144fa247a2aSRuchika Gupta rc = add_attribute(head, PKCS11_CKA_VALUE, value, value_len); 145fa247a2aSRuchika Gupta 146fa247a2aSRuchika Gupta TEE_Free(value); 147fa247a2aSRuchika Gupta 148fa247a2aSRuchika Gupta return rc; 149fa247a2aSRuchika Gupta } 150fa247a2aSRuchika Gupta 151fa247a2aSRuchika Gupta enum pkcs11_rc entry_generate_secret(struct pkcs11_client *client, 152fa247a2aSRuchika Gupta uint32_t ptypes, TEE_Param *params) 153fa247a2aSRuchika Gupta { 154fa247a2aSRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 155fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE, 156fa247a2aSRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 157fa247a2aSRuchika Gupta TEE_PARAM_TYPE_NONE); 158fa247a2aSRuchika Gupta TEE_Param *ctrl = params; 159fa247a2aSRuchika Gupta TEE_Param *out = params + 2; 160fa247a2aSRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 161fa247a2aSRuchika Gupta struct serialargs ctrlargs = { }; 162fa247a2aSRuchika Gupta struct pkcs11_session *session = NULL; 163fa247a2aSRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 164fa247a2aSRuchika Gupta struct obj_attrs *head = NULL; 165fa247a2aSRuchika Gupta struct pkcs11_object_head *template = NULL; 166fa247a2aSRuchika Gupta size_t template_size = 0; 167fa247a2aSRuchika Gupta uint32_t obj_handle = 0; 168fa247a2aSRuchika Gupta 169fa247a2aSRuchika Gupta if (!client || ptypes != exp_pt || 170fa247a2aSRuchika Gupta out->memref.size != sizeof(obj_handle)) 171fa247a2aSRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 172fa247a2aSRuchika Gupta 173fa247a2aSRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 174fa247a2aSRuchika Gupta 175fa247a2aSRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 176fa247a2aSRuchika Gupta if (rc) 177fa247a2aSRuchika Gupta return rc; 178fa247a2aSRuchika Gupta 179fa247a2aSRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 180fa247a2aSRuchika Gupta if (rc) 181fa247a2aSRuchika Gupta goto out; 182fa247a2aSRuchika Gupta 183fa247a2aSRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 184fa247a2aSRuchika Gupta if (rc) 185fa247a2aSRuchika Gupta goto out; 186fa247a2aSRuchika Gupta 187fa247a2aSRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 188fa247a2aSRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 189fa247a2aSRuchika Gupta goto out; 190fa247a2aSRuchika Gupta } 191fa247a2aSRuchika Gupta 192fa247a2aSRuchika Gupta rc = get_ready_session(session); 193fa247a2aSRuchika Gupta if (rc) 194fa247a2aSRuchika Gupta goto out; 195fa247a2aSRuchika Gupta 196fa247a2aSRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 197fa247a2aSRuchika Gupta 198fa247a2aSRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 199fa247a2aSRuchika Gupta PKCS11_FUNCTION_GENERATE, 200fa247a2aSRuchika Gupta PKCS11_FUNC_STEP_INIT); 201fa247a2aSRuchika Gupta if (rc) { 202fa247a2aSRuchika Gupta DMSG("Invalid mechanism %#"PRIx32": %#x", proc_params->id, rc); 203fa247a2aSRuchika Gupta goto out; 204fa247a2aSRuchika Gupta } 205fa247a2aSRuchika Gupta 206fa247a2aSRuchika Gupta /* 207fa247a2aSRuchika Gupta * Prepare a clean initial state for the requested object attributes. 208fa247a2aSRuchika Gupta * Free temporary template once done. 209fa247a2aSRuchika Gupta */ 210fa247a2aSRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 211fa247a2aSRuchika Gupta NULL, PKCS11_FUNCTION_GENERATE, 2124cfce748SRuchika Gupta proc_params->id, 2134cfce748SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 214fa247a2aSRuchika Gupta if (rc) 215fa247a2aSRuchika Gupta goto out; 216fa247a2aSRuchika Gupta 217fa247a2aSRuchika Gupta TEE_Free(template); 218fa247a2aSRuchika Gupta template = NULL; 219fa247a2aSRuchika Gupta 220fa247a2aSRuchika Gupta rc = check_created_attrs(head, NULL); 221fa247a2aSRuchika Gupta if (rc) 222fa247a2aSRuchika Gupta goto out; 223fa247a2aSRuchika Gupta 224fa247a2aSRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 225fa247a2aSRuchika Gupta if (rc) 226fa247a2aSRuchika Gupta goto out; 227fa247a2aSRuchika Gupta 228fa247a2aSRuchika Gupta rc = check_created_attrs_against_token(session, head); 229fa247a2aSRuchika Gupta if (rc) 230fa247a2aSRuchika Gupta goto out; 231fa247a2aSRuchika Gupta 232fa247a2aSRuchika Gupta /* 233fa247a2aSRuchika Gupta * Execute target processing and add value as attribute 234fa247a2aSRuchika Gupta * PKCS11_CKA_VALUE. Symm key generation: depends on target 235fa247a2aSRuchika Gupta * processing to be used. 236fa247a2aSRuchika Gupta */ 237fa247a2aSRuchika Gupta switch (proc_params->id) { 238fa247a2aSRuchika Gupta case PKCS11_CKM_GENERIC_SECRET_KEY_GEN: 239fa247a2aSRuchika Gupta case PKCS11_CKM_AES_KEY_GEN: 240fa247a2aSRuchika Gupta /* Generate random of size specified by attribute VALUE_LEN */ 241fa247a2aSRuchika Gupta rc = generate_random_key_value(&head); 242fa247a2aSRuchika Gupta if (rc) 243fa247a2aSRuchika Gupta goto out; 244fa247a2aSRuchika Gupta break; 245fa247a2aSRuchika Gupta 246fa247a2aSRuchika Gupta default: 247fa247a2aSRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 248fa247a2aSRuchika Gupta goto out; 249fa247a2aSRuchika Gupta } 250fa247a2aSRuchika Gupta 251fa247a2aSRuchika Gupta TEE_Free(proc_params); 252fa247a2aSRuchika Gupta proc_params = NULL; 253fa247a2aSRuchika Gupta 254fa247a2aSRuchika Gupta /* 255fa247a2aSRuchika Gupta * Object is ready, register it and return a handle. 256fa247a2aSRuchika Gupta */ 257fa247a2aSRuchika Gupta rc = create_object(session, head, &obj_handle); 258fa247a2aSRuchika Gupta if (rc) 259fa247a2aSRuchika Gupta goto out; 260fa247a2aSRuchika Gupta 261fa247a2aSRuchika Gupta /* 262fa247a2aSRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 263fa247a2aSRuchika Gupta * owns the serialized buffer that holds the object attributes. 264fa247a2aSRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 265fa247a2aSRuchika Gupta * be freed at function out. 266fa247a2aSRuchika Gupta */ 267fa247a2aSRuchika Gupta head = NULL; 268fa247a2aSRuchika Gupta 269fa247a2aSRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 270fa247a2aSRuchika Gupta out->memref.size = sizeof(obj_handle); 271fa247a2aSRuchika Gupta 272fa247a2aSRuchika Gupta DMSG("PKCS11 session %"PRIu32": generate secret %#"PRIx32, 273fa247a2aSRuchika Gupta session->handle, obj_handle); 274fa247a2aSRuchika Gupta 275fa247a2aSRuchika Gupta out: 276fa247a2aSRuchika Gupta TEE_Free(proc_params); 277fa247a2aSRuchika Gupta TEE_Free(template); 278fa247a2aSRuchika Gupta TEE_Free(head); 279fa247a2aSRuchika Gupta 280fa247a2aSRuchika Gupta return rc; 281fa247a2aSRuchika Gupta } 282fa247a2aSRuchika Gupta 283512cbf1dSJens Wiklander /* 284512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing 285512cbf1dSJens Wiklander * 286512cbf1dSJens Wiklander * @client = client reference 287512cbf1dSJens Wiklander * @ptype = Invocation parameter types 288512cbf1dSJens Wiklander * @params = Invocation parameters reference 289512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 290512cbf1dSJens Wiklander */ 291512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 292512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 293512cbf1dSJens Wiklander enum processing_func function) 294512cbf1dSJens Wiklander { 295512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 296512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 297512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 298512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE); 299512cbf1dSJens Wiklander TEE_Param *ctrl = params; 300512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 301512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 302512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 303512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL; 304512cbf1dSJens Wiklander uint32_t key_handle = 0; 305512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL; 306512cbf1dSJens Wiklander 307512cbf1dSJens Wiklander if (!client || ptypes != exp_pt) 308512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 309512cbf1dSJens Wiklander 310512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 311512cbf1dSJens Wiklander 312512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 313512cbf1dSJens Wiklander if (rc) 314512cbf1dSJens Wiklander return rc; 315512cbf1dSJens Wiklander 316512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 317512cbf1dSJens Wiklander if (rc) 318512cbf1dSJens Wiklander return rc; 319512cbf1dSJens Wiklander 320512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 321512cbf1dSJens Wiklander if (rc) 322512cbf1dSJens Wiklander return rc; 323512cbf1dSJens Wiklander 324512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 325512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 326512cbf1dSJens Wiklander goto out; 327512cbf1dSJens Wiklander } 328512cbf1dSJens Wiklander 329512cbf1dSJens Wiklander rc = get_ready_session(session); 330512cbf1dSJens Wiklander if (rc) 331512cbf1dSJens Wiklander goto out; 332512cbf1dSJens Wiklander 333512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session); 334512cbf1dSJens Wiklander if (!obj) { 335512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID; 336512cbf1dSJens Wiklander goto out; 337512cbf1dSJens Wiklander } 338512cbf1dSJens Wiklander 339512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL); 340512cbf1dSJens Wiklander if (rc) 341512cbf1dSJens Wiklander goto out; 342512cbf1dSJens Wiklander 343512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id, 344512cbf1dSJens Wiklander function, 345512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT); 346512cbf1dSJens Wiklander if (rc) 347512cbf1dSJens Wiklander goto out; 348512cbf1dSJens Wiklander 349512cbf1dSJens Wiklander rc = check_parent_attrs_against_processing(proc_params->id, function, 350512cbf1dSJens Wiklander obj->attributes); 351512cbf1dSJens Wiklander if (rc) 352512cbf1dSJens Wiklander goto out; 353512cbf1dSJens Wiklander 354512cbf1dSJens Wiklander rc = check_access_attrs_against_token(session, obj->attributes); 355512cbf1dSJens Wiklander if (rc) 356512cbf1dSJens Wiklander goto out; 357512cbf1dSJens Wiklander 358512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id)) 359512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj); 360512cbf1dSJens Wiklander else 361512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 362512cbf1dSJens Wiklander 363512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 364512cbf1dSJens Wiklander session->processing->mecha_type = proc_params->id; 365512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s", 366512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id), 367512cbf1dSJens Wiklander id2str_function(function)); 368512cbf1dSJens Wiklander } 369512cbf1dSJens Wiklander 370512cbf1dSJens Wiklander out: 371512cbf1dSJens Wiklander if (rc && session) 372512cbf1dSJens Wiklander release_active_processing(session); 373512cbf1dSJens Wiklander 374512cbf1dSJens Wiklander TEE_Free(proc_params); 375512cbf1dSJens Wiklander 376512cbf1dSJens Wiklander return rc; 377512cbf1dSJens Wiklander } 378512cbf1dSJens Wiklander 379512cbf1dSJens Wiklander /* 380512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing 381512cbf1dSJens Wiklander * 382512cbf1dSJens Wiklander * @client = client reference 383512cbf1dSJens Wiklander * @ptype = Invocation parameter types 384512cbf1dSJens Wiklander * @params = Invocation parameters reference 385512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 386512cbf1dSJens Wiklander * @step - update, oneshot, final 387512cbf1dSJens Wiklander */ 388512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 389512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 390512cbf1dSJens Wiklander enum processing_func function, 391512cbf1dSJens Wiklander enum processing_step step) 392512cbf1dSJens Wiklander { 393512cbf1dSJens Wiklander TEE_Param *ctrl = params; 394512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 395512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 396512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 397512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 398512cbf1dSJens Wiklander 399512cbf1dSJens Wiklander if (!client || 400512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 401512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 402512cbf1dSJens Wiklander 403512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 404512cbf1dSJens Wiklander 405512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 406512cbf1dSJens Wiklander if (rc) 407512cbf1dSJens Wiklander return rc; 408512cbf1dSJens Wiklander 409512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 410512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 411512cbf1dSJens Wiklander 412512cbf1dSJens Wiklander rc = get_active_session(session, function); 413512cbf1dSJens Wiklander if (rc) 414512cbf1dSJens Wiklander return rc; 415512cbf1dSJens Wiklander 416512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 417512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 418512cbf1dSJens Wiklander function, step); 419512cbf1dSJens Wiklander if (rc) 420512cbf1dSJens Wiklander goto out; 421512cbf1dSJens Wiklander 422512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 423512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 424512cbf1dSJens Wiklander ptypes, params); 425512cbf1dSJens Wiklander else 426512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 427512cbf1dSJens Wiklander 428689f4e5bSRuchika Gupta if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) { 429512cbf1dSJens Wiklander session->processing->updated = true; 430512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s", 431512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type), 432512cbf1dSJens Wiklander id2str_function(function)); 433512cbf1dSJens Wiklander } 434512cbf1dSJens Wiklander 435512cbf1dSJens Wiklander out: 436512cbf1dSJens Wiklander switch (step) { 437512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE: 438512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 439512cbf1dSJens Wiklander release_active_processing(session); 440512cbf1dSJens Wiklander break; 441512cbf1dSJens Wiklander default: 442512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */ 443512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 444512cbf1dSJens Wiklander release_active_processing(session); 445512cbf1dSJens Wiklander break; 446512cbf1dSJens Wiklander } 447512cbf1dSJens Wiklander 448512cbf1dSJens Wiklander return rc; 449512cbf1dSJens Wiklander } 450*48799892SRuchika Gupta 451*48799892SRuchika Gupta enum pkcs11_rc entry_derive_key(struct pkcs11_client *client, 452*48799892SRuchika Gupta uint32_t ptypes, TEE_Param *params) 453*48799892SRuchika Gupta { 454*48799892SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 455*48799892SRuchika Gupta TEE_PARAM_TYPE_NONE, 456*48799892SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 457*48799892SRuchika Gupta TEE_PARAM_TYPE_NONE); 458*48799892SRuchika Gupta TEE_Param *ctrl = params; 459*48799892SRuchika Gupta TEE_Param *out = params + 2; 460*48799892SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 461*48799892SRuchika Gupta struct serialargs ctrlargs = { }; 462*48799892SRuchika Gupta struct pkcs11_session *session = NULL; 463*48799892SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 464*48799892SRuchika Gupta struct pkcs11_object_head *template = NULL; 465*48799892SRuchika Gupta uint32_t parent_handle = 0; 466*48799892SRuchika Gupta uint32_t obj_handle = 0; 467*48799892SRuchika Gupta struct pkcs11_object *parent = NULL; 468*48799892SRuchika Gupta struct obj_attrs *head = NULL; 469*48799892SRuchika Gupta size_t template_size = 0; 470*48799892SRuchika Gupta enum processing_func function = PKCS11_FUNCTION_DERIVE; 471*48799892SRuchika Gupta 472*48799892SRuchika Gupta if (!client || ptypes != exp_pt || 473*48799892SRuchika Gupta out->memref.size != sizeof(obj_handle)) 474*48799892SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 475*48799892SRuchika Gupta 476*48799892SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 477*48799892SRuchika Gupta 478*48799892SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 479*48799892SRuchika Gupta if (rc) 480*48799892SRuchika Gupta return rc; 481*48799892SRuchika Gupta 482*48799892SRuchika Gupta rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); 483*48799892SRuchika Gupta if (rc) 484*48799892SRuchika Gupta return rc; 485*48799892SRuchika Gupta 486*48799892SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 487*48799892SRuchika Gupta if (rc) 488*48799892SRuchika Gupta goto out_free; 489*48799892SRuchika Gupta 490*48799892SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 491*48799892SRuchika Gupta if (rc) 492*48799892SRuchika Gupta goto out_free; 493*48799892SRuchika Gupta 494*48799892SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 495*48799892SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 496*48799892SRuchika Gupta goto out_free; 497*48799892SRuchika Gupta } 498*48799892SRuchika Gupta 499*48799892SRuchika Gupta /* Return error if processing already active */ 500*48799892SRuchika Gupta rc = get_ready_session(session); 501*48799892SRuchika Gupta if (rc) 502*48799892SRuchika Gupta goto out_free; 503*48799892SRuchika Gupta 504*48799892SRuchika Gupta /* Check parent handle */ 505*48799892SRuchika Gupta parent = pkcs11_handle2object(parent_handle, session); 506*48799892SRuchika Gupta if (!parent) { 507*48799892SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID; 508*48799892SRuchika Gupta goto out_free; 509*48799892SRuchika Gupta } 510*48799892SRuchika Gupta 511*48799892SRuchika Gupta /* Check if mechanism supplied is supported for key derivation */ 512*48799892SRuchika Gupta switch (proc_params->id) { 513*48799892SRuchika Gupta case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: 514*48799892SRuchika Gupta case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: 515*48799892SRuchika Gupta break; 516*48799892SRuchika Gupta default: 517*48799892SRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 518*48799892SRuchika Gupta goto out_free; 519*48799892SRuchika Gupta } 520*48799892SRuchika Gupta 521*48799892SRuchika Gupta /* Check if mechanism can be used for derivation function */ 522*48799892SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 523*48799892SRuchika Gupta function, 524*48799892SRuchika Gupta PKCS11_FUNC_STEP_INIT); 525*48799892SRuchika Gupta if (rc) 526*48799892SRuchika Gupta goto out_free; 527*48799892SRuchika Gupta 528*48799892SRuchika Gupta /* Set the processing state to active */ 529*48799892SRuchika Gupta rc = set_processing_state(session, function, parent, NULL); 530*48799892SRuchika Gupta if (rc) 531*48799892SRuchika Gupta goto out_free; 532*48799892SRuchika Gupta 533*48799892SRuchika Gupta /* 534*48799892SRuchika Gupta * Check if base/parent key has CKA_DERIVE set and its key type is 535*48799892SRuchika Gupta * compatible with the mechanism passed 536*48799892SRuchika Gupta */ 537*48799892SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function, 538*48799892SRuchika Gupta parent->attributes); 539*48799892SRuchika Gupta if (rc) 540*48799892SRuchika Gupta goto out; 541*48799892SRuchika Gupta 542*48799892SRuchika Gupta /* Check access of base/parent key */ 543*48799892SRuchika Gupta rc = check_access_attrs_against_token(session, parent->attributes); 544*48799892SRuchika Gupta if (rc) 545*48799892SRuchika Gupta goto out; 546*48799892SRuchika Gupta 547*48799892SRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 548*48799892SRuchika Gupta /* 549*48799892SRuchika Gupta * Prepare a clean initial state for the requested object attributes 550*48799892SRuchika Gupta * using base/parent key attributes. Free temporary template once done. 551*48799892SRuchika Gupta */ 552*48799892SRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 553*48799892SRuchika Gupta parent->attributes, 554*48799892SRuchika Gupta function, 555*48799892SRuchika Gupta proc_params->id, 556*48799892SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 557*48799892SRuchika Gupta if (rc) 558*48799892SRuchika Gupta goto out; 559*48799892SRuchika Gupta 560*48799892SRuchika Gupta TEE_Free(template); 561*48799892SRuchika Gupta template = NULL; 562*48799892SRuchika Gupta 563*48799892SRuchika Gupta /* check_created_attrs() is called later once key size is known */ 564*48799892SRuchika Gupta 565*48799892SRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 566*48799892SRuchika Gupta if (rc) 567*48799892SRuchika Gupta goto out; 568*48799892SRuchika Gupta 569*48799892SRuchika Gupta rc = check_created_attrs_against_token(session, head); 570*48799892SRuchika Gupta if (rc) 571*48799892SRuchika Gupta goto out; 572*48799892SRuchika Gupta 573*48799892SRuchika Gupta /* 574*48799892SRuchika Gupta * Execute target processing and add value as attribute 575*48799892SRuchika Gupta * PKCS11_CKA_VALUE. Symm key generation: depends on target 576*48799892SRuchika Gupta * processing to be used. 577*48799892SRuchika Gupta */ 578*48799892SRuchika Gupta switch (proc_params->id) { 579*48799892SRuchika Gupta case PKCS11_CKM_AES_ECB_ENCRYPT_DATA: 580*48799892SRuchika Gupta case PKCS11_CKM_AES_CBC_ENCRYPT_DATA: 581*48799892SRuchika Gupta /* 582*48799892SRuchika Gupta * These derivation mechanism require encryption to be 583*48799892SRuchika Gupta * performed on the data passed in proc_params by parent 584*48799892SRuchika Gupta * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT 585*48799892SRuchika Gupta * to init_symm_operation() 586*48799892SRuchika Gupta */ 587*48799892SRuchika Gupta rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, 588*48799892SRuchika Gupta proc_params, parent); 589*48799892SRuchika Gupta if (rc) 590*48799892SRuchika Gupta goto out; 591*48799892SRuchika Gupta 592*48799892SRuchika Gupta rc = derive_key_by_symm_enc(session, &head); 593*48799892SRuchika Gupta if (rc) 594*48799892SRuchika Gupta goto out; 595*48799892SRuchika Gupta break; 596*48799892SRuchika Gupta default: 597*48799892SRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 598*48799892SRuchika Gupta goto out; 599*48799892SRuchika Gupta } 600*48799892SRuchika Gupta 601*48799892SRuchika Gupta TEE_Free(proc_params); 602*48799892SRuchika Gupta proc_params = NULL; 603*48799892SRuchika Gupta 604*48799892SRuchika Gupta /* 605*48799892SRuchika Gupta * Object is ready, register it and return a handle. 606*48799892SRuchika Gupta */ 607*48799892SRuchika Gupta rc = create_object(session, head, &obj_handle); 608*48799892SRuchika Gupta if (rc) 609*48799892SRuchika Gupta goto out; 610*48799892SRuchika Gupta 611*48799892SRuchika Gupta /* 612*48799892SRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 613*48799892SRuchika Gupta * owns the serialized buffer that holds the object attributes. 614*48799892SRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 615*48799892SRuchika Gupta * be freed at function out. 616*48799892SRuchika Gupta */ 617*48799892SRuchika Gupta head = NULL; 618*48799892SRuchika Gupta 619*48799892SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 620*48799892SRuchika Gupta out->memref.size = sizeof(obj_handle); 621*48799892SRuchika Gupta 622*48799892SRuchika Gupta DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, 623*48799892SRuchika Gupta session->handle, obj_handle); 624*48799892SRuchika Gupta 625*48799892SRuchika Gupta out: 626*48799892SRuchika Gupta release_active_processing(session); 627*48799892SRuchika Gupta out_free: 628*48799892SRuchika Gupta TEE_Free(proc_params); 629*48799892SRuchika Gupta TEE_Free(template); 630*48799892SRuchika Gupta TEE_Free(head); 631*48799892SRuchika Gupta 632*48799892SRuchika Gupta return rc; 633*48799892SRuchika Gupta } 634