1*512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2*512cbf1dSJens Wiklander /* 3*512cbf1dSJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 4*512cbf1dSJens Wiklander */ 5*512cbf1dSJens Wiklander 6*512cbf1dSJens Wiklander #include <assert.h> 7*512cbf1dSJens Wiklander #include <pkcs11_ta.h> 8*512cbf1dSJens Wiklander #include <string.h> 9*512cbf1dSJens Wiklander #include <tee_api_defines.h> 10*512cbf1dSJens Wiklander #include <tee_internal_api.h> 11*512cbf1dSJens Wiklander #include <tee_internal_api_extensions.h> 12*512cbf1dSJens Wiklander #include <util.h> 13*512cbf1dSJens Wiklander 14*512cbf1dSJens Wiklander #include "attributes.h" 15*512cbf1dSJens Wiklander #include "object.h" 16*512cbf1dSJens Wiklander #include "pkcs11_attributes.h" 17*512cbf1dSJens Wiklander #include "pkcs11_helpers.h" 18*512cbf1dSJens Wiklander #include "pkcs11_token.h" 19*512cbf1dSJens Wiklander #include "processing.h" 20*512cbf1dSJens Wiklander #include "serializer.h" 21*512cbf1dSJens Wiklander 22*512cbf1dSJens Wiklander static enum pkcs11_rc get_ready_session(struct pkcs11_session *session) 23*512cbf1dSJens Wiklander { 24*512cbf1dSJens Wiklander if (session_is_active(session)) 25*512cbf1dSJens Wiklander return PKCS11_CKR_OPERATION_ACTIVE; 26*512cbf1dSJens Wiklander 27*512cbf1dSJens Wiklander return PKCS11_CKR_OK; 28*512cbf1dSJens Wiklander } 29*512cbf1dSJens Wiklander 30*512cbf1dSJens Wiklander static bool func_matches_state(enum processing_func function, 31*512cbf1dSJens Wiklander enum pkcs11_proc_state state) 32*512cbf1dSJens Wiklander { 33*512cbf1dSJens Wiklander switch (function) { 34*512cbf1dSJens Wiklander case PKCS11_FUNCTION_ENCRYPT: 35*512cbf1dSJens Wiklander return state == PKCS11_SESSION_ENCRYPTING || 36*512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING || 37*512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 38*512cbf1dSJens Wiklander case PKCS11_FUNCTION_DECRYPT: 39*512cbf1dSJens Wiklander return state == PKCS11_SESSION_DECRYPTING || 40*512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_DIGESTING || 41*512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 42*512cbf1dSJens Wiklander case PKCS11_FUNCTION_DIGEST: 43*512cbf1dSJens Wiklander return state == PKCS11_SESSION_DIGESTING || 44*512cbf1dSJens Wiklander state == PKCS11_SESSION_DIGESTING_ENCRYPTING; 45*512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN: 46*512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING || 47*512cbf1dSJens Wiklander state == PKCS11_SESSION_SIGNING_ENCRYPTING; 48*512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY: 49*512cbf1dSJens Wiklander return state == PKCS11_SESSION_VERIFYING || 50*512cbf1dSJens Wiklander state == PKCS11_SESSION_DECRYPTING_VERIFYING; 51*512cbf1dSJens Wiklander case PKCS11_FUNCTION_SIGN_RECOVER: 52*512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 53*512cbf1dSJens Wiklander case PKCS11_FUNCTION_VERIFY_RECOVER: 54*512cbf1dSJens Wiklander return state == PKCS11_SESSION_SIGNING_RECOVER; 55*512cbf1dSJens Wiklander default: 56*512cbf1dSJens Wiklander TEE_Panic(function); 57*512cbf1dSJens Wiklander return false; 58*512cbf1dSJens Wiklander } 59*512cbf1dSJens Wiklander } 60*512cbf1dSJens Wiklander 61*512cbf1dSJens Wiklander static enum pkcs11_rc get_active_session(struct pkcs11_session *session, 62*512cbf1dSJens Wiklander enum processing_func function) 63*512cbf1dSJens Wiklander { 64*512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OPERATION_NOT_INITIALIZED; 65*512cbf1dSJens Wiklander 66*512cbf1dSJens Wiklander if (session->processing && 67*512cbf1dSJens Wiklander func_matches_state(function, session->processing->state)) 68*512cbf1dSJens Wiklander rc = PKCS11_CKR_OK; 69*512cbf1dSJens Wiklander 70*512cbf1dSJens Wiklander return rc; 71*512cbf1dSJens Wiklander } 72*512cbf1dSJens Wiklander 73*512cbf1dSJens Wiklander void release_active_processing(struct pkcs11_session *session) 74*512cbf1dSJens Wiklander { 75*512cbf1dSJens Wiklander if (!session->processing) 76*512cbf1dSJens Wiklander return; 77*512cbf1dSJens Wiklander 78*512cbf1dSJens Wiklander switch (session->processing->mecha_type) { 79*512cbf1dSJens Wiklander case PKCS11_CKM_AES_CTR: 80*512cbf1dSJens Wiklander tee_release_ctr_operation(session->processing); 81*512cbf1dSJens Wiklander break; 82*512cbf1dSJens Wiklander default: 83*512cbf1dSJens Wiklander break; 84*512cbf1dSJens Wiklander } 85*512cbf1dSJens Wiklander 86*512cbf1dSJens Wiklander if (session->processing->tee_op_handle != TEE_HANDLE_NULL) { 87*512cbf1dSJens Wiklander TEE_FreeOperation(session->processing->tee_op_handle); 88*512cbf1dSJens Wiklander session->processing->tee_op_handle = TEE_HANDLE_NULL; 89*512cbf1dSJens Wiklander } 90*512cbf1dSJens Wiklander 91*512cbf1dSJens Wiklander TEE_Free(session->processing); 92*512cbf1dSJens Wiklander session->processing = NULL; 93*512cbf1dSJens Wiklander } 94*512cbf1dSJens Wiklander 95*512cbf1dSJens Wiklander size_t get_object_key_bit_size(struct pkcs11_object *obj) 96*512cbf1dSJens Wiklander { 97*512cbf1dSJens Wiklander uint32_t a_size = 0; 98*512cbf1dSJens Wiklander struct obj_attrs *attrs = obj->attributes; 99*512cbf1dSJens Wiklander 100*512cbf1dSJens Wiklander switch (get_key_type(attrs)) { 101*512cbf1dSJens Wiklander case PKCS11_CKK_AES: 102*512cbf1dSJens Wiklander if (get_attribute_ptr(attrs, PKCS11_CKA_VALUE, NULL, &a_size)) 103*512cbf1dSJens Wiklander return 0; 104*512cbf1dSJens Wiklander 105*512cbf1dSJens Wiklander return a_size * 8; 106*512cbf1dSJens Wiklander default: 107*512cbf1dSJens Wiklander TEE_Panic(0); 108*512cbf1dSJens Wiklander return 0; 109*512cbf1dSJens Wiklander } 110*512cbf1dSJens Wiklander } 111*512cbf1dSJens Wiklander 112*512cbf1dSJens Wiklander /* 113*512cbf1dSJens Wiklander * entry_processing_init - Generic entry for initializing a processing 114*512cbf1dSJens Wiklander * 115*512cbf1dSJens Wiklander * @client = client reference 116*512cbf1dSJens Wiklander * @ptype = Invocation parameter types 117*512cbf1dSJens Wiklander * @params = Invocation parameters reference 118*512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 119*512cbf1dSJens Wiklander */ 120*512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_init(struct pkcs11_client *client, 121*512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 122*512cbf1dSJens Wiklander enum processing_func function) 123*512cbf1dSJens Wiklander { 124*512cbf1dSJens Wiklander const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT, 125*512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 126*512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE, 127*512cbf1dSJens Wiklander TEE_PARAM_TYPE_NONE); 128*512cbf1dSJens Wiklander TEE_Param *ctrl = params; 129*512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 130*512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 131*512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 132*512cbf1dSJens Wiklander struct pkcs11_attribute_head *proc_params = NULL; 133*512cbf1dSJens Wiklander uint32_t key_handle = 0; 134*512cbf1dSJens Wiklander struct pkcs11_object *obj = NULL; 135*512cbf1dSJens Wiklander 136*512cbf1dSJens Wiklander if (!client || ptypes != exp_pt) 137*512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 138*512cbf1dSJens Wiklander 139*512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 140*512cbf1dSJens Wiklander 141*512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 142*512cbf1dSJens Wiklander if (rc) 143*512cbf1dSJens Wiklander return rc; 144*512cbf1dSJens Wiklander 145*512cbf1dSJens Wiklander rc = serialargs_get(&ctrlargs, &key_handle, sizeof(uint32_t)); 146*512cbf1dSJens Wiklander if (rc) 147*512cbf1dSJens Wiklander return rc; 148*512cbf1dSJens Wiklander 149*512cbf1dSJens Wiklander rc = serialargs_alloc_get_one_attribute(&ctrlargs, &proc_params); 150*512cbf1dSJens Wiklander if (rc) 151*512cbf1dSJens Wiklander return rc; 152*512cbf1dSJens Wiklander 153*512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) { 154*512cbf1dSJens Wiklander rc = PKCS11_CKR_ARGUMENTS_BAD; 155*512cbf1dSJens Wiklander goto out; 156*512cbf1dSJens Wiklander } 157*512cbf1dSJens Wiklander 158*512cbf1dSJens Wiklander rc = get_ready_session(session); 159*512cbf1dSJens Wiklander if (rc) 160*512cbf1dSJens Wiklander goto out; 161*512cbf1dSJens Wiklander 162*512cbf1dSJens Wiklander obj = pkcs11_handle2object(key_handle, session); 163*512cbf1dSJens Wiklander if (!obj) { 164*512cbf1dSJens Wiklander rc = PKCS11_CKR_KEY_HANDLE_INVALID; 165*512cbf1dSJens Wiklander goto out; 166*512cbf1dSJens Wiklander } 167*512cbf1dSJens Wiklander 168*512cbf1dSJens Wiklander rc = set_processing_state(session, function, obj, NULL); 169*512cbf1dSJens Wiklander if (rc) 170*512cbf1dSJens Wiklander goto out; 171*512cbf1dSJens Wiklander 172*512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, proc_params->id, 173*512cbf1dSJens Wiklander function, 174*512cbf1dSJens Wiklander PKCS11_FUNC_STEP_INIT); 175*512cbf1dSJens Wiklander if (rc) 176*512cbf1dSJens Wiklander goto out; 177*512cbf1dSJens Wiklander 178*512cbf1dSJens Wiklander rc = check_parent_attrs_against_processing(proc_params->id, function, 179*512cbf1dSJens Wiklander obj->attributes); 180*512cbf1dSJens Wiklander if (rc) 181*512cbf1dSJens Wiklander goto out; 182*512cbf1dSJens Wiklander 183*512cbf1dSJens Wiklander rc = check_access_attrs_against_token(session, obj->attributes); 184*512cbf1dSJens Wiklander if (rc) 185*512cbf1dSJens Wiklander goto out; 186*512cbf1dSJens Wiklander 187*512cbf1dSJens Wiklander if (processing_is_tee_symm(proc_params->id)) 188*512cbf1dSJens Wiklander rc = init_symm_operation(session, function, proc_params, obj); 189*512cbf1dSJens Wiklander else 190*512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 191*512cbf1dSJens Wiklander 192*512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 193*512cbf1dSJens Wiklander session->processing->mecha_type = proc_params->id; 194*512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": init processing %s %s", 195*512cbf1dSJens Wiklander session->handle, id2str_proc(proc_params->id), 196*512cbf1dSJens Wiklander id2str_function(function)); 197*512cbf1dSJens Wiklander } 198*512cbf1dSJens Wiklander 199*512cbf1dSJens Wiklander out: 200*512cbf1dSJens Wiklander if (rc && session) 201*512cbf1dSJens Wiklander release_active_processing(session); 202*512cbf1dSJens Wiklander 203*512cbf1dSJens Wiklander TEE_Free(proc_params); 204*512cbf1dSJens Wiklander 205*512cbf1dSJens Wiklander return rc; 206*512cbf1dSJens Wiklander } 207*512cbf1dSJens Wiklander 208*512cbf1dSJens Wiklander /* 209*512cbf1dSJens Wiklander * entry_processing_step - Generic entry on active processing 210*512cbf1dSJens Wiklander * 211*512cbf1dSJens Wiklander * @client = client reference 212*512cbf1dSJens Wiklander * @ptype = Invocation parameter types 213*512cbf1dSJens Wiklander * @params = Invocation parameters reference 214*512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 215*512cbf1dSJens Wiklander * @step - update, oneshot, final 216*512cbf1dSJens Wiklander */ 217*512cbf1dSJens Wiklander enum pkcs11_rc entry_processing_step(struct pkcs11_client *client, 218*512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 219*512cbf1dSJens Wiklander enum processing_func function, 220*512cbf1dSJens Wiklander enum processing_step step) 221*512cbf1dSJens Wiklander { 222*512cbf1dSJens Wiklander TEE_Param *ctrl = params; 223*512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 224*512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 225*512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 226*512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 227*512cbf1dSJens Wiklander 228*512cbf1dSJens Wiklander if (!client || 229*512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 230*512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 231*512cbf1dSJens Wiklander 232*512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 233*512cbf1dSJens Wiklander 234*512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 235*512cbf1dSJens Wiklander if (rc) 236*512cbf1dSJens Wiklander return rc; 237*512cbf1dSJens Wiklander 238*512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 239*512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 240*512cbf1dSJens Wiklander 241*512cbf1dSJens Wiklander rc = get_active_session(session, function); 242*512cbf1dSJens Wiklander if (rc) 243*512cbf1dSJens Wiklander return rc; 244*512cbf1dSJens Wiklander 245*512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 246*512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 247*512cbf1dSJens Wiklander function, step); 248*512cbf1dSJens Wiklander if (rc) 249*512cbf1dSJens Wiklander goto out; 250*512cbf1dSJens Wiklander 251*512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 252*512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 253*512cbf1dSJens Wiklander ptypes, params); 254*512cbf1dSJens Wiklander else 255*512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 256*512cbf1dSJens Wiklander 257*512cbf1dSJens Wiklander if (rc == PKCS11_CKR_OK) { 258*512cbf1dSJens Wiklander session->processing->updated = true; 259*512cbf1dSJens Wiklander DMSG("PKCS11 session%"PRIu32": processing %s %s", 260*512cbf1dSJens Wiklander session->handle, id2str_proc(mecha_type), 261*512cbf1dSJens Wiklander id2str_function(function)); 262*512cbf1dSJens Wiklander } 263*512cbf1dSJens Wiklander 264*512cbf1dSJens Wiklander out: 265*512cbf1dSJens Wiklander switch (step) { 266*512cbf1dSJens Wiklander case PKCS11_FUNC_STEP_UPDATE: 267*512cbf1dSJens Wiklander if (rc != PKCS11_CKR_OK && rc != PKCS11_CKR_BUFFER_TOO_SMALL) 268*512cbf1dSJens Wiklander release_active_processing(session); 269*512cbf1dSJens Wiklander break; 270*512cbf1dSJens Wiklander default: 271*512cbf1dSJens Wiklander /* ONESHOT and FINAL terminates processing on success */ 272*512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 273*512cbf1dSJens Wiklander release_active_processing(session); 274*512cbf1dSJens Wiklander break; 275*512cbf1dSJens Wiklander } 276*512cbf1dSJens Wiklander 277*512cbf1dSJens Wiklander return rc; 278*512cbf1dSJens Wiklander } 279*512cbf1dSJens Wiklander 280*512cbf1dSJens Wiklander /* 281*512cbf1dSJens Wiklander * entry_verify_oneshot - Run a single part verification processing 282*512cbf1dSJens Wiklander * 283*512cbf1dSJens Wiklander * @client = client reference 284*512cbf1dSJens Wiklander * @ptype = Invocation parameter types 285*512cbf1dSJens Wiklander * @params = Invocation parameters reference 286*512cbf1dSJens Wiklander * @function - encrypt, decrypt, sign, verify, digest, ... 287*512cbf1dSJens Wiklander * @step - update, oneshot, final 288*512cbf1dSJens Wiklander */ 289*512cbf1dSJens Wiklander enum pkcs11_rc entry_verify_oneshot(struct pkcs11_client *client, 290*512cbf1dSJens Wiklander uint32_t ptypes, TEE_Param *params, 291*512cbf1dSJens Wiklander enum processing_func function, 292*512cbf1dSJens Wiklander enum processing_step step) 293*512cbf1dSJens Wiklander 294*512cbf1dSJens Wiklander { 295*512cbf1dSJens Wiklander TEE_Param *ctrl = params; 296*512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 297*512cbf1dSJens Wiklander struct serialargs ctrlargs = { }; 298*512cbf1dSJens Wiklander struct pkcs11_session *session = NULL; 299*512cbf1dSJens Wiklander enum pkcs11_mechanism_id mecha_type = PKCS11_CKM_UNDEFINED_ID; 300*512cbf1dSJens Wiklander 301*512cbf1dSJens Wiklander assert(function == PKCS11_FUNCTION_VERIFY); 302*512cbf1dSJens Wiklander if (!client || 303*512cbf1dSJens Wiklander TEE_PARAM_TYPE_GET(ptypes, 0) != TEE_PARAM_TYPE_MEMREF_INOUT) 304*512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 305*512cbf1dSJens Wiklander 306*512cbf1dSJens Wiklander serialargs_init(&ctrlargs, ctrl->memref.buffer, ctrl->memref.size); 307*512cbf1dSJens Wiklander 308*512cbf1dSJens Wiklander rc = serialargs_get_session_from_handle(&ctrlargs, client, &session); 309*512cbf1dSJens Wiklander if (rc) 310*512cbf1dSJens Wiklander return rc; 311*512cbf1dSJens Wiklander 312*512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&ctrlargs)) 313*512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 314*512cbf1dSJens Wiklander 315*512cbf1dSJens Wiklander rc = get_active_session(session, function); 316*512cbf1dSJens Wiklander if (rc) 317*512cbf1dSJens Wiklander return rc; 318*512cbf1dSJens Wiklander 319*512cbf1dSJens Wiklander mecha_type = session->processing->mecha_type; 320*512cbf1dSJens Wiklander rc = check_mechanism_against_processing(session, mecha_type, 321*512cbf1dSJens Wiklander function, step); 322*512cbf1dSJens Wiklander if (rc) 323*512cbf1dSJens Wiklander goto out; 324*512cbf1dSJens Wiklander 325*512cbf1dSJens Wiklander if (processing_is_tee_symm(mecha_type)) 326*512cbf1dSJens Wiklander rc = step_symm_operation(session, function, step, 327*512cbf1dSJens Wiklander ptypes, params); 328*512cbf1dSJens Wiklander else 329*512cbf1dSJens Wiklander rc = PKCS11_CKR_MECHANISM_INVALID; 330*512cbf1dSJens Wiklander 331*512cbf1dSJens Wiklander DMSG("PKCS11 session %"PRIu32": verify %s %s: %s", session->handle, 332*512cbf1dSJens Wiklander id2str_proc(mecha_type), id2str_function(function), 333*512cbf1dSJens Wiklander id2str_rc(rc)); 334*512cbf1dSJens Wiklander 335*512cbf1dSJens Wiklander out: 336*512cbf1dSJens Wiklander if (rc != PKCS11_CKR_BUFFER_TOO_SMALL) 337*512cbf1dSJens Wiklander release_active_processing(session); 338*512cbf1dSJens Wiklander 339*512cbf1dSJens Wiklander return rc; 340*512cbf1dSJens Wiklander } 341