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 switch (session->processing->mecha_type) { 79512cbf1dSJens Wiklander case PKCS11_CKM_AES_CTR: 80512cbf1dSJens Wiklander tee_release_ctr_operation(session->processing); 81512cbf1dSJens Wiklander break; 82512cbf1dSJens Wiklander default: 83512cbf1dSJens Wiklander break; 84512cbf1dSJens Wiklander } 85512cbf1dSJens Wiklander 86512cbf1dSJens Wiklander if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 87512cbf1dSJens Wiklander TEE_FreeOperation(session->processing->tee_op_handle); 88512cbf1dSJens Wiklander session->processing->tee_op_handle = TEE_HANDLE_NULL; 89512cbf1dSJens Wiklander } 90512cbf1dSJens Wiklander 91512cbf1dSJens Wiklander TEE_Free(session->processing); 92512cbf1dSJens Wiklander session->processing = NULL; 93512cbf1dSJens Wiklander } 94512cbf1dSJens Wiklander 95512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj) 96512cbf1dSJens Wiklander { 97512cbf1dSJens Wiklander uint32_t a_size = 0; 98512cbf1dSJens Wiklander struct obj_attrs *attrs = obj->attributes; 99512cbf1dSJens Wiklander 100512cbf1dSJens Wiklander switch (get_key_type(attrs)) { 101512cbf1dSJens Wiklander case PKCS11_CKK_AES: 102*689f4e5bSRuchika Gupta case PKCS11_CKK_GENERIC_SECRET: 103*689f4e5bSRuchika Gupta case PKCS11_CKK_MD5_HMAC: 104*689f4e5bSRuchika Gupta case PKCS11_CKK_SHA_1_HMAC: 105*689f4e5bSRuchika Gupta case PKCS11_CKK_SHA224_HMAC: 106*689f4e5bSRuchika Gupta case PKCS11_CKK_SHA256_HMAC: 107*689f4e5bSRuchika Gupta case PKCS11_CKK_SHA384_HMAC: 108*689f4e5bSRuchika Gupta case PKCS11_CKK_SHA512_HMAC: 109512cbf1dSJens Wiklander if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 110512cbf1dSJens Wiklander return 0; 111512cbf1dSJens Wiklander 112512cbf1dSJens Wiklander return a_size * 8; 113512cbf1dSJens Wiklander default: 114512cbf1dSJens Wiklander TEE_Panic(0); 115512cbf1dSJens Wiklander return 0; 116512cbf1dSJens Wiklander } 117512cbf1dSJens Wiklander } 118512cbf1dSJens Wiklander 119512cbf1dSJens Wiklander /* 120512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing 121512cbf1dSJens Wiklander * 122512cbf1dSJens Wiklander * @client = client reference 123512cbf1dSJens Wiklander * @ptype = Invocation parameter types 124512cbf1dSJens Wiklander * @params = Invocation parameters reference 125512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 126512cbf1dSJens Wiklander */ 127512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 128512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 129512cbf1dSJens Wiklander enum processing_func function) 130512cbf1dSJens Wiklander { 131512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 132512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 133512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 134512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE); 135512cbf1dSJens Wiklander TEE_Param *ctrl = params; 136512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 137512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 138512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 139512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL; 140512cbf1dSJens Wiklander uint32_t key_handle = 0; 141512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL; 142512cbf1dSJens Wiklander 143512cbf1dSJens Wiklander if (!client || ptypes != exp_pt) 144512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 145512cbf1dSJens Wiklander 146512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 147512cbf1dSJens Wiklander 148512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 149512cbf1dSJens Wiklander if (rc) 150512cbf1dSJens Wiklander return rc; 151512cbf1dSJens Wiklander 152512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 153512cbf1dSJens Wiklander if (rc) 154512cbf1dSJens Wiklander return rc; 155512cbf1dSJens Wiklander 156512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 157512cbf1dSJens Wiklander if (rc) 158512cbf1dSJens Wiklander return rc; 159512cbf1dSJens Wiklander 160512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 161512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 162512cbf1dSJens Wiklander goto out; 163512cbf1dSJens Wiklander } 164512cbf1dSJens Wiklander 165512cbf1dSJens Wiklander rc = get_ready_session(session); 166512cbf1dSJens Wiklander if (rc) 167512cbf1dSJens Wiklander goto out; 168512cbf1dSJens Wiklander 169512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session); 170512cbf1dSJens Wiklander if (!obj) { 171512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID; 172512cbf1dSJens Wiklander goto out; 173512cbf1dSJens Wiklander } 174512cbf1dSJens Wiklander 175512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL); 176512cbf1dSJens Wiklander if (rc) 177512cbf1dSJens Wiklander goto out; 178512cbf1dSJens Wiklander 179512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id, 180512cbf1dSJens Wiklander function, 181512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT); 182512cbf1dSJens Wiklander if (rc) 183512cbf1dSJens Wiklander goto out; 184512cbf1dSJens Wiklander 185512cbf1dSJens Wiklander rc = check_parent_attrs_against_processing(proc_params->id, function, 186512cbf1dSJens Wiklander obj->attributes); 187512cbf1dSJens Wiklander if (rc) 188512cbf1dSJens Wiklander goto out; 189512cbf1dSJens Wiklander 190512cbf1dSJens Wiklander rc = check_access_attrs_against_token(session, obj->attributes); 191512cbf1dSJens Wiklander if (rc) 192512cbf1dSJens Wiklander goto out; 193512cbf1dSJens Wiklander 194512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id)) 195512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj); 196512cbf1dSJens Wiklander else 197512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 198512cbf1dSJens Wiklander 199512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 200512cbf1dSJens Wiklander session->processing->mecha_type = proc_params->id; 201512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s", 202512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id), 203512cbf1dSJens Wiklander id2str_function(function)); 204512cbf1dSJens Wiklander } 205512cbf1dSJens Wiklander 206512cbf1dSJens Wiklander out: 207512cbf1dSJens Wiklander if (rc && session) 208512cbf1dSJens Wiklander release_active_processing(session); 209512cbf1dSJens Wiklander 210512cbf1dSJens Wiklander TEE_Free(proc_params); 211512cbf1dSJens Wiklander 212512cbf1dSJens Wiklander return rc; 213512cbf1dSJens Wiklander } 214512cbf1dSJens Wiklander 215512cbf1dSJens Wiklander /* 216512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing 217512cbf1dSJens Wiklander * 218512cbf1dSJens Wiklander * @client = client reference 219512cbf1dSJens Wiklander * @ptype = Invocation parameter types 220512cbf1dSJens Wiklander * @params = Invocation parameters reference 221512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 222512cbf1dSJens Wiklander * @step - update, oneshot, final 223512cbf1dSJens Wiklander */ 224512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 225512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 226512cbf1dSJens Wiklander enum processing_func function, 227512cbf1dSJens Wiklander enum processing_step step) 228512cbf1dSJens Wiklander { 229512cbf1dSJens Wiklander TEE_Param *ctrl = params; 230512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 231512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 232512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 233512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 234512cbf1dSJens Wiklander 235512cbf1dSJens Wiklander if (!client || 236512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 237512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 238512cbf1dSJens Wiklander 239512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 240512cbf1dSJens Wiklander 241512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 242512cbf1dSJens Wiklander if (rc) 243512cbf1dSJens Wiklander return rc; 244512cbf1dSJens Wiklander 245512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 246512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 247512cbf1dSJens Wiklander 248512cbf1dSJens Wiklander rc = get_active_session(session, function); 249512cbf1dSJens Wiklander if (rc) 250512cbf1dSJens Wiklander return rc; 251512cbf1dSJens Wiklander 252512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 253512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 254512cbf1dSJens Wiklander function, step); 255512cbf1dSJens Wiklander if (rc) 256512cbf1dSJens Wiklander goto out; 257512cbf1dSJens Wiklander 258512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 259512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 260512cbf1dSJens Wiklander ptypes, params); 261512cbf1dSJens Wiklander else 262512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 263512cbf1dSJens Wiklander 264*689f4e5bSRuchika Gupta if (rc == PKCS11_CKR_OK && step == PKCS11_FUNC_STEP_UPDATE) { 265512cbf1dSJens Wiklander session->processing->updated = true; 266512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s", 267512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type), 268512cbf1dSJens Wiklander id2str_function(function)); 269512cbf1dSJens Wiklander } 270512cbf1dSJens Wiklander 271512cbf1dSJens Wiklander out: 272512cbf1dSJens Wiklander switch (step) { 273512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE: 274512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 275512cbf1dSJens Wiklander release_active_processing(session); 276512cbf1dSJens Wiklander break; 277512cbf1dSJens Wiklander default: 278512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */ 279512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 280512cbf1dSJens Wiklander release_active_processing(session); 281512cbf1dSJens Wiklander break; 282512cbf1dSJens Wiklander } 283512cbf1dSJens Wiklander 284512cbf1dSJens Wiklander return rc; 285512cbf1dSJens Wiklander } 286512cbf1dSJens Wiklander 287512cbf1dSJens Wiklander /* 288512cbf1dSJens Wiklander * entry_verify_oneshot - Run a single part verification processing 289512cbf1dSJens Wiklander * 290512cbf1dSJens Wiklander * @client = client reference 291512cbf1dSJens Wiklander * @ptype = Invocation parameter types 292512cbf1dSJens Wiklander * @params = Invocation parameters reference 293512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 294512cbf1dSJens Wiklander * @step - update, oneshot, final 295512cbf1dSJens Wiklander */ 296512cbf1dSJens Wiklander enum pkcs11_rc entry_verify_oneshot(struct pkcs11_client *client, 297512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 298512cbf1dSJens Wiklander enum processing_func function, 299512cbf1dSJens Wiklander enum processing_step step) 300512cbf1dSJens Wiklander 301512cbf1dSJens Wiklander { 302512cbf1dSJens Wiklander TEE_Param *ctrl = params; 303512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 304512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 305512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 306512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 307512cbf1dSJens Wiklander 308512cbf1dSJens Wiklander assert(function == PKCS11_FUNCTION_VERIFY); 309512cbf1dSJens Wiklander if (!client || 310512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 311512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 312512cbf1dSJens Wiklander 313512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 314512cbf1dSJens Wiklander 315512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 316512cbf1dSJens Wiklander if (rc) 317512cbf1dSJens Wiklander return rc; 318512cbf1dSJens Wiklander 319512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 320512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 321512cbf1dSJens Wiklander 322512cbf1dSJens Wiklander rc = get_active_session(session, function); 323512cbf1dSJens Wiklander if (rc) 324512cbf1dSJens Wiklander return rc; 325512cbf1dSJens Wiklander 326512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 327512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 328512cbf1dSJens Wiklander function, step); 329512cbf1dSJens Wiklander if (rc) 330512cbf1dSJens Wiklander goto out; 331512cbf1dSJens Wiklander 332512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 333512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 334512cbf1dSJens Wiklander ptypes, params); 335512cbf1dSJens Wiklander else 336512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 337512cbf1dSJens Wiklander 338512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": verify %s %s: %s", session->handle, 339512cbf1dSJens Wiklander id2str_proc(mecha_type), id2str_function(function), 340512cbf1dSJens Wiklander id2str_rc(rc)); 341512cbf1dSJens Wiklander 342512cbf1dSJens Wiklander out: 343512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 344512cbf1dSJens Wiklander release_active_processing(session); 345512cbf1dSJens Wiklander 346512cbf1dSJens Wiklander return rc; 347512cbf1dSJens Wiklander } 348