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; 49*9e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_UPDATE: 50*9e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_KEY: 51*9e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_ONESHOT: 52*9e91a619SVesa Jääskeläinen case PKCS11_CMD_DIGEST_FINAL: 53*9e91a619SVesa 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 312512cbf1dSJens Wiklander /* 313512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing 314512cbf1dSJens Wiklander * 315512cbf1dSJens Wiklander * @client = client reference 316512cbf1dSJens Wiklander * @ptype = Invocation parameter types 317512cbf1dSJens Wiklander * @params = Invocation parameters reference 318512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 319512cbf1dSJens Wiklander */ 320512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 321512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 322512cbf1dSJens Wiklander enum processing_func function) 323512cbf1dSJens Wiklander { 324512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 325512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 326512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 327512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE); 328512cbf1dSJens Wiklander TEE_Param *ctrl = params; 329512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 330512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 331512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 332512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL; 333512cbf1dSJens Wiklander uint32_t key_handle = 0; 334512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL; 335512cbf1dSJens Wiklander 336512cbf1dSJens Wiklander if (!client || ptypes != exp_pt) 337512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 338512cbf1dSJens Wiklander 339512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 340512cbf1dSJens Wiklander 341512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 342512cbf1dSJens Wiklander if (rc) 343512cbf1dSJens Wiklander return rc; 344512cbf1dSJens Wiklander 345*9e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) { 346512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 347512cbf1dSJens Wiklander if (rc) 348512cbf1dSJens Wiklander return rc; 349*9e91a619SVesa Jääskeläinen } 350512cbf1dSJens Wiklander 351512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 352512cbf1dSJens Wiklander if (rc) 353512cbf1dSJens Wiklander return rc; 354512cbf1dSJens Wiklander 355512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 356512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 357512cbf1dSJens Wiklander goto out; 358512cbf1dSJens Wiklander } 359512cbf1dSJens Wiklander 360512cbf1dSJens Wiklander rc = get_ready_session(session); 361512cbf1dSJens Wiklander if (rc) 362512cbf1dSJens Wiklander goto out; 363512cbf1dSJens Wiklander 364*9e91a619SVesa Jääskeläinen if (function != PKCS11_FUNCTION_DIGEST) { 365512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session); 366512cbf1dSJens Wiklander if (!obj) { 367512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID; 368512cbf1dSJens Wiklander goto out; 369512cbf1dSJens Wiklander } 370*9e91a619SVesa Jääskeläinen } 371512cbf1dSJens Wiklander 372512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL); 373512cbf1dSJens Wiklander if (rc) 374512cbf1dSJens Wiklander goto out; 375512cbf1dSJens Wiklander 376512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id, 377512cbf1dSJens Wiklander function, 378512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT); 379512cbf1dSJens Wiklander if (rc) 380512cbf1dSJens Wiklander goto out; 381512cbf1dSJens Wiklander 382*9e91a619SVesa Jääskeläinen if (obj) { 383*9e91a619SVesa Jääskeläinen rc = check_parent_attrs_against_processing(proc_params->id, 384*9e91a619SVesa Jääskeläinen function, 385512cbf1dSJens Wiklander obj->attributes); 386512cbf1dSJens Wiklander if (rc) 387512cbf1dSJens Wiklander goto out; 388512cbf1dSJens Wiklander 389*9e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session, 390*9e91a619SVesa Jääskeläinen obj->attributes); 391512cbf1dSJens Wiklander if (rc) 392512cbf1dSJens Wiklander goto out; 393*9e91a619SVesa Jääskeläinen } 394512cbf1dSJens Wiklander 395512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id)) 396512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj); 397*9e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(proc_params->id)) 398*9e91a619SVesa Jääskeläinen rc = init_digest_operation(session, proc_params); 399512cbf1dSJens Wiklander else 400512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 401512cbf1dSJens Wiklander 402512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 403512cbf1dSJens Wiklander session->processing->mecha_type = proc_params->id; 404512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s", 405512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id), 406512cbf1dSJens Wiklander id2str_function(function)); 407512cbf1dSJens Wiklander } 408512cbf1dSJens Wiklander 409512cbf1dSJens Wiklander out: 410512cbf1dSJens Wiklander if (rc && session) 411512cbf1dSJens Wiklander release_active_processing(session); 412512cbf1dSJens Wiklander 413512cbf1dSJens Wiklander TEE_Free(proc_params); 414512cbf1dSJens Wiklander 415512cbf1dSJens Wiklander return rc; 416512cbf1dSJens Wiklander } 417512cbf1dSJens Wiklander 418512cbf1dSJens Wiklander /* 419512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing 420512cbf1dSJens Wiklander * 421512cbf1dSJens Wiklander * @client = client reference 422512cbf1dSJens Wiklander * @ptype = Invocation parameter types 423512cbf1dSJens Wiklander * @params = Invocation parameters reference 424512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 425512cbf1dSJens Wiklander * @step - update, oneshot, final 426512cbf1dSJens Wiklander */ 427512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 428512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 429512cbf1dSJens Wiklander enum processing_func function, 430512cbf1dSJens Wiklander enum processing_step step) 431512cbf1dSJens Wiklander { 432512cbf1dSJens Wiklander TEE_Param *ctrl = params; 433512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 434512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 435512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 436512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 437*9e91a619SVesa Jääskeläinen uint32_t key_handle = 0; 438*9e91a619SVesa Jääskeläinen struct pkcs11_object *obj = NULL; 439512cbf1dSJens Wiklander 440512cbf1dSJens Wiklander if (!client || 441512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 442512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 443512cbf1dSJens Wiklander 444512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 445512cbf1dSJens Wiklander 446512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 447512cbf1dSJens Wiklander if (rc) 448512cbf1dSJens Wiklander return rc; 449512cbf1dSJens Wiklander 450*9e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 451*9e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST); 452*9e91a619SVesa Jääskeläinen 453*9e91a619SVesa Jääskeläinen rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 454*9e91a619SVesa Jääskeläinen if (rc) 455*9e91a619SVesa Jääskeläinen return rc; 456*9e91a619SVesa Jääskeläinen } 457*9e91a619SVesa Jääskeläinen 458512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 459512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 460512cbf1dSJens Wiklander 461512cbf1dSJens Wiklander rc = get_active_session(session, function); 462512cbf1dSJens Wiklander if (rc) 463512cbf1dSJens Wiklander return rc; 464512cbf1dSJens Wiklander 465*9e91a619SVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE_KEY) { 466*9e91a619SVesa Jääskeläinen assert(function == PKCS11_FUNCTION_DIGEST); 467*9e91a619SVesa Jääskeläinen 468*9e91a619SVesa Jääskeläinen obj = pkcs11_handle2object(key_handle, session); 469*9e91a619SVesa Jääskeläinen if (!obj) { 470*9e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID; 471*9e91a619SVesa Jääskeläinen goto out; 472*9e91a619SVesa Jääskeläinen } 473*9e91a619SVesa Jääskeläinen 474*9e91a619SVesa Jääskeläinen rc = check_access_attrs_against_token(session, 475*9e91a619SVesa Jääskeläinen obj->attributes); 476*9e91a619SVesa Jääskeläinen if (rc) { 477*9e91a619SVesa Jääskeläinen rc = PKCS11_CKR_KEY_HANDLE_INVALID; 478*9e91a619SVesa Jääskeläinen goto out; 479*9e91a619SVesa Jääskeläinen } 480*9e91a619SVesa Jääskeläinen } 481*9e91a619SVesa Jääskeläinen 482512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 483512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 484512cbf1dSJens Wiklander function, step); 485512cbf1dSJens Wiklander if (rc) 486512cbf1dSJens Wiklander goto out; 487512cbf1dSJens Wiklander 488512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 489512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 490512cbf1dSJens Wiklander ptypes, params); 491*9e91a619SVesa Jääskeläinen else if (processing_is_tee_digest(mecha_type)) 492*9e91a619SVesa Jääskeläinen rc = step_digest_operation(session, step, obj, ptypes, params); 493512cbf1dSJens Wiklander else 494512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 495512cbf1dSJens Wiklander 496*9e91a619SVesa Jääskeläinen if (rc == PKCS11_CKR_OK && (step == PKCS11_FUNC_STEP_UPDATE || 497*9e91a619SVesa Jääskeläinen step == PKCS11_FUNC_STEP_UPDATE_KEY)) { 498512cbf1dSJens Wiklander session->processing->updated = true; 499512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s", 500512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type), 501512cbf1dSJens Wiklander id2str_function(function)); 502512cbf1dSJens Wiklander } 503512cbf1dSJens Wiklander 504512cbf1dSJens Wiklander out: 505512cbf1dSJens Wiklander switch (step) { 506512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE: 507*9e91a619SVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE_KEY: 508512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 509512cbf1dSJens Wiklander release_active_processing(session); 510512cbf1dSJens Wiklander break; 511512cbf1dSJens Wiklander default: 512512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */ 513512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 514512cbf1dSJens Wiklander release_active_processing(session); 515512cbf1dSJens Wiklander break; 516512cbf1dSJens Wiklander } 517512cbf1dSJens Wiklander 518512cbf1dSJens Wiklander return rc; 519512cbf1dSJens Wiklander } 52048799892SRuchika Gupta 5214dad6642SRuchika Gupta enum pkcs11_rc entry_processing_key(struct pkcs11_client *client, 5224dad6642SRuchika Gupta uint32_t ptypes, TEE_Param *params, 5234dad6642SRuchika Gupta enum processing_func function) 52448799892SRuchika Gupta { 52548799892SRuchika Gupta const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 52648799892SRuchika Gupta TEE_PARAM_TYPE_NONE, 52748799892SRuchika Gupta TEE_PARAM_TYPE_MEMREF_OUTPUT, 52848799892SRuchika Gupta TEE_PARAM_TYPE_NONE); 52948799892SRuchika Gupta TEE_Param *ctrl = params; 53048799892SRuchika Gupta TEE_Param *out = params + 2; 53148799892SRuchika Gupta enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 53248799892SRuchika Gupta struct serialargs ctrlargs = { }; 53348799892SRuchika Gupta struct pkcs11_session *session = NULL; 53448799892SRuchika Gupta struct pkcs11_attribute_head *proc_params = NULL; 53548799892SRuchika Gupta struct pkcs11_object_head *template = NULL; 53648799892SRuchika Gupta uint32_t parent_handle = 0; 53748799892SRuchika Gupta uint32_t obj_handle = 0; 53848799892SRuchika Gupta struct pkcs11_object *parent = NULL; 53948799892SRuchika Gupta struct obj_attrs *head = NULL; 54048799892SRuchika Gupta size_t template_size = 0; 5418c499324SRuchika Gupta void *out_buf = NULL; 5428c499324SRuchika Gupta uint32_t out_size = 0; 54348799892SRuchika Gupta 54448799892SRuchika Gupta if (!client || ptypes != exp_pt || 54548799892SRuchika Gupta out->memref.size != sizeof(obj_handle)) 54648799892SRuchika Gupta return PKCS11_CKR_ARGUMENTS_BAD; 54748799892SRuchika Gupta 54848799892SRuchika Gupta serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 54948799892SRuchika Gupta 55048799892SRuchika Gupta rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 55148799892SRuchika Gupta if (rc) 55248799892SRuchika Gupta return rc; 55348799892SRuchika Gupta 55448799892SRuchika Gupta rc = serialargs_get(&ctrlargs, &parent_handle, sizeof(uint32_t)); 55548799892SRuchika Gupta if (rc) 55648799892SRuchika Gupta return rc; 55748799892SRuchika Gupta 55848799892SRuchika Gupta rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 55948799892SRuchika Gupta if (rc) 56048799892SRuchika Gupta goto out_free; 56148799892SRuchika Gupta 56248799892SRuchika Gupta rc = serialargs_alloc_get_attributes(&ctrlargs, &template); 56348799892SRuchika Gupta if (rc) 56448799892SRuchika Gupta goto out_free; 56548799892SRuchika Gupta 56648799892SRuchika Gupta if (serialargs_remaining_bytes(&ctrlargs)) { 56748799892SRuchika Gupta rc = PKCS11_CKR_ARGUMENTS_BAD; 56848799892SRuchika Gupta goto out_free; 56948799892SRuchika Gupta } 57048799892SRuchika Gupta 57148799892SRuchika Gupta /* Return error if processing already active */ 57248799892SRuchika Gupta rc = get_ready_session(session); 57348799892SRuchika Gupta if (rc) 57448799892SRuchika Gupta goto out_free; 57548799892SRuchika Gupta 57648799892SRuchika Gupta /* Check parent handle */ 57748799892SRuchika Gupta parent = pkcs11_handle2object(parent_handle, session); 57848799892SRuchika Gupta if (!parent) { 57948799892SRuchika Gupta rc = PKCS11_CKR_KEY_HANDLE_INVALID; 58048799892SRuchika Gupta goto out_free; 58148799892SRuchika Gupta } 58248799892SRuchika Gupta 58348799892SRuchika Gupta /* Check if mechanism can be used for derivation function */ 58448799892SRuchika Gupta rc = check_mechanism_against_processing(session, proc_params->id, 58548799892SRuchika Gupta function, 58648799892SRuchika Gupta PKCS11_FUNC_STEP_INIT); 58748799892SRuchika Gupta if (rc) 58848799892SRuchika Gupta goto out_free; 58948799892SRuchika Gupta 59048799892SRuchika Gupta /* Set the processing state to active */ 59148799892SRuchika Gupta rc = set_processing_state(session, function, parent, NULL); 59248799892SRuchika Gupta if (rc) 59348799892SRuchika Gupta goto out_free; 59448799892SRuchika Gupta 59548799892SRuchika Gupta /* 59648799892SRuchika Gupta * Check if base/parent key has CKA_DERIVE set and its key type is 59748799892SRuchika Gupta * compatible with the mechanism passed 59848799892SRuchika Gupta */ 59948799892SRuchika Gupta rc = check_parent_attrs_against_processing(proc_params->id, function, 60048799892SRuchika Gupta parent->attributes); 601d05ab5feSRuchika Gupta if (rc) { 602d05ab5feSRuchika Gupta /* 603d05ab5feSRuchika Gupta * CKR_KEY_FUNCTION_NOT_PERMITTED is not in the list of errors 604d05ab5feSRuchika Gupta * specified with C_Derive/Unwrap() in the specification. So 605d05ab5feSRuchika Gupta * return the next most appropriate error. 606d05ab5feSRuchika Gupta */ 607d05ab5feSRuchika Gupta if (rc == PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED) 608d05ab5feSRuchika Gupta rc = PKCS11_CKR_KEY_TYPE_INCONSISTENT; 60948799892SRuchika Gupta goto out; 610d05ab5feSRuchika Gupta } 61148799892SRuchika Gupta 61248799892SRuchika Gupta /* Check access of base/parent key */ 61348799892SRuchika Gupta rc = check_access_attrs_against_token(session, parent->attributes); 61448799892SRuchika Gupta if (rc) 61548799892SRuchika Gupta goto out; 61648799892SRuchika Gupta 61748799892SRuchika Gupta template_size = sizeof(*template) + template->attrs_size; 61848799892SRuchika Gupta /* 61948799892SRuchika Gupta * Prepare a clean initial state for the requested object attributes 62048799892SRuchika Gupta * using base/parent key attributes. Free temporary template once done. 62148799892SRuchika Gupta */ 62248799892SRuchika Gupta rc = create_attributes_from_template(&head, template, template_size, 62348799892SRuchika Gupta parent->attributes, 62448799892SRuchika Gupta function, 62548799892SRuchika Gupta proc_params->id, 62648799892SRuchika Gupta PKCS11_CKO_UNDEFINED_ID); 62748799892SRuchika Gupta if (rc) 62848799892SRuchika Gupta goto out; 62948799892SRuchika Gupta 63048799892SRuchika Gupta TEE_Free(template); 63148799892SRuchika Gupta template = NULL; 63248799892SRuchika Gupta 63348799892SRuchika Gupta /* check_created_attrs() is called later once key size is known */ 63448799892SRuchika Gupta 63548799892SRuchika Gupta rc = check_created_attrs_against_processing(proc_params->id, head); 63648799892SRuchika Gupta if (rc) 63748799892SRuchika Gupta goto out; 63848799892SRuchika Gupta 63948799892SRuchika Gupta rc = check_created_attrs_against_token(session, head); 64048799892SRuchika Gupta if (rc) 64148799892SRuchika Gupta goto out; 64248799892SRuchika Gupta 6438c499324SRuchika Gupta if (processing_is_tee_symm(proc_params->id)) { 64448799892SRuchika Gupta /* 64548799892SRuchika Gupta * These derivation mechanism require encryption to be 64648799892SRuchika Gupta * performed on the data passed in proc_params by parent 64748799892SRuchika Gupta * key. Hence pass function as PKCS11_FUNCTION_ENCRYPT 64848799892SRuchika Gupta * to init_symm_operation() 64948799892SRuchika Gupta */ 65048799892SRuchika Gupta rc = init_symm_operation(session, PKCS11_FUNCTION_ENCRYPT, 65148799892SRuchika Gupta proc_params, parent); 65248799892SRuchika Gupta if (rc) 65348799892SRuchika Gupta goto out; 65448799892SRuchika Gupta 6558c499324SRuchika Gupta session->processing->mecha_type = proc_params->id; 6568c499324SRuchika Gupta 6578c499324SRuchika Gupta rc = derive_key_by_symm_enc(session, &out_buf, &out_size); 65848799892SRuchika Gupta if (rc) 65948799892SRuchika Gupta goto out; 6608c499324SRuchika Gupta } else { 66148799892SRuchika Gupta rc = PKCS11_CKR_MECHANISM_INVALID; 66248799892SRuchika Gupta goto out; 66348799892SRuchika Gupta } 66448799892SRuchika Gupta 6658c499324SRuchika Gupta rc = set_key_data(&head, out_buf, out_size); 6668c499324SRuchika Gupta if (rc) 6678c499324SRuchika Gupta goto out; 6688c499324SRuchika Gupta 6698c499324SRuchika Gupta TEE_Free(out_buf); 6708c499324SRuchika Gupta out_buf = NULL; 6718c499324SRuchika Gupta 67248799892SRuchika Gupta TEE_Free(proc_params); 67348799892SRuchika Gupta proc_params = NULL; 67448799892SRuchika Gupta 67548799892SRuchika Gupta /* 67648799892SRuchika Gupta * Object is ready, register it and return a handle. 67748799892SRuchika Gupta */ 67848799892SRuchika Gupta rc = create_object(session, head, &obj_handle); 67948799892SRuchika Gupta if (rc) 68048799892SRuchika Gupta goto out; 68148799892SRuchika Gupta 68248799892SRuchika Gupta /* 68348799892SRuchika Gupta * Now obj_handle (through the related struct pkcs11_object instance) 68448799892SRuchika Gupta * owns the serialized buffer that holds the object attributes. 68548799892SRuchika Gupta * We reset head to NULL as it is no more the buffer owner and would 68648799892SRuchika Gupta * be freed at function out. 68748799892SRuchika Gupta */ 68848799892SRuchika Gupta head = NULL; 68948799892SRuchika Gupta 69048799892SRuchika Gupta TEE_MemMove(out->memref.buffer, &obj_handle, sizeof(obj_handle)); 69148799892SRuchika Gupta out->memref.size = sizeof(obj_handle); 69248799892SRuchika Gupta 69348799892SRuchika Gupta DMSG("PKCS11 session %"PRIu32": derive secret %#"PRIx32, 69448799892SRuchika Gupta session->handle, obj_handle); 69548799892SRuchika Gupta 69648799892SRuchika Gupta out: 69748799892SRuchika Gupta release_active_processing(session); 69848799892SRuchika Gupta out_free: 69948799892SRuchika Gupta TEE_Free(proc_params); 70048799892SRuchika Gupta TEE_Free(template); 70148799892SRuchika Gupta TEE_Free(head); 7028c499324SRuchika Gupta TEE_Free(out_buf); 70348799892SRuchika Gupta 70448799892SRuchika Gupta return rc; 70548799892SRuchika Gupta } 706eb6141b6SVesa Jääskeläinen 707eb6141b6SVesa Jääskeläinen enum pkcs11_rc entry_release_active_processing(struct pkcs11_client *client, 708eb6141b6SVesa Jääskeläinen uint32_t ptypes, 709eb6141b6SVesa Jääskeläinen TEE_Param *params) 710eb6141b6SVesa Jääskeläinen { 711eb6141b6SVesa Jääskeläinen const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 712eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 713eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE, 714eb6141b6SVesa Jääskeläinen TEE_PARAM_TYPE_NONE); 715eb6141b6SVesa Jääskeläinen TEE_Param *ctrl = params; 716eb6141b6SVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_OK; 717eb6141b6SVesa Jääskeläinen struct serialargs ctrlargs = { }; 718eb6141b6SVesa Jääskeläinen struct pkcs11_session *session = NULL; 719eb6141b6SVesa Jääskeläinen enum processing_func function = PKCS11_FUNCTION_UNKNOWN; 720eb6141b6SVesa Jääskeläinen uint32_t cmd = 0; 721eb6141b6SVesa Jääskeläinen 722eb6141b6SVesa Jääskeläinen if (!client || ptypes != exp_pt) 723eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 724eb6141b6SVesa Jääskeläinen 725eb6141b6SVesa Jääskeläinen serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 726eb6141b6SVesa Jääskeläinen 727eb6141b6SVesa Jääskeläinen rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 728eb6141b6SVesa Jääskeläinen if (rc) 729eb6141b6SVesa Jääskeläinen return rc; 730eb6141b6SVesa Jääskeläinen 731eb6141b6SVesa Jääskeläinen rc = serialargs_get_u32(&ctrlargs, &cmd); 732eb6141b6SVesa Jääskeläinen 733eb6141b6SVesa Jääskeläinen if (serialargs_remaining_bytes(&ctrlargs)) 734eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 735eb6141b6SVesa Jääskeläinen 736eb6141b6SVesa Jääskeläinen function = func_for_cmd(cmd); 737eb6141b6SVesa Jääskeläinen if (function == PKCS11_FUNCTION_UNKNOWN) 738eb6141b6SVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 739eb6141b6SVesa Jääskeläinen 740eb6141b6SVesa Jääskeläinen rc = get_active_session(session, function); 741eb6141b6SVesa Jääskeläinen if (rc) 742eb6141b6SVesa Jääskeläinen return rc; 743eb6141b6SVesa Jääskeläinen 744eb6141b6SVesa Jääskeläinen release_active_processing(session); 745eb6141b6SVesa Jääskeläinen 746eb6141b6SVesa Jääskeläinen DMSG("PKCS11 session %"PRIu32": release processing", session->handle); 747eb6141b6SVesa Jääskeläinen 748eb6141b6SVesa Jääskeläinen return PKCS11_CKR_OK; 749eb6141b6SVesa Jääskeläinen } 750