1*fb279d8bSVesa Jääskeläinen // SPDX-License-Identifier: BSD-2-Clause 2*fb279d8bSVesa Jääskeläinen /* 3*fb279d8bSVesa Jääskeläinen * Copyright (c) 2018-2020, Linaro Limited 4*fb279d8bSVesa Jääskeläinen */ 5*fb279d8bSVesa Jääskeläinen 6*fb279d8bSVesa Jääskeläinen #include <assert.h> 7*fb279d8bSVesa Jääskeläinen #include <compiler.h> 8*fb279d8bSVesa Jääskeläinen #include <tee_api_defines.h> 9*fb279d8bSVesa Jääskeläinen #include <tee_internal_api.h> 10*fb279d8bSVesa Jääskeläinen #include <tee_internal_api_extensions.h> 11*fb279d8bSVesa Jääskeläinen 12*fb279d8bSVesa Jääskeläinen #include "attributes.h" 13*fb279d8bSVesa Jääskeläinen #include "pkcs11_helpers.h" 14*fb279d8bSVesa Jääskeläinen #include "pkcs11_token.h" 15*fb279d8bSVesa Jääskeläinen #include "processing.h" 16*fb279d8bSVesa Jääskeläinen #include "serializer.h" 17*fb279d8bSVesa Jääskeläinen 18*fb279d8bSVesa Jääskeläinen bool processing_is_tee_asymm(uint32_t proc_id) 19*fb279d8bSVesa Jääskeläinen { 20*fb279d8bSVesa Jääskeläinen switch (proc_id) { 21*fb279d8bSVesa Jääskeläinen /* EC flavors */ 22*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA: 23*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA1: 24*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA224: 25*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA256: 26*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA384: 27*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA512: 28*fb279d8bSVesa Jääskeläinen return true; 29*fb279d8bSVesa Jääskeläinen default: 30*fb279d8bSVesa Jääskeläinen return false; 31*fb279d8bSVesa Jääskeläinen } 32*fb279d8bSVesa Jääskeläinen } 33*fb279d8bSVesa Jääskeläinen 34*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc 35*fb279d8bSVesa Jääskeläinen pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id, 36*fb279d8bSVesa Jääskeläinen enum processing_func function __unused, 37*fb279d8bSVesa Jääskeläinen struct pkcs11_attribute_head *proc_params, 38*fb279d8bSVesa Jääskeläinen struct pkcs11_object *obj) 39*fb279d8bSVesa Jääskeläinen { 40*fb279d8bSVesa Jääskeläinen static const struct { 41*fb279d8bSVesa Jääskeläinen enum pkcs11_mechanism_id mech_id; 42*fb279d8bSVesa Jääskeläinen uint32_t tee_id; 43*fb279d8bSVesa Jääskeläinen uint32_t tee_hash_id; 44*fb279d8bSVesa Jääskeläinen } pkcs2tee_algo[] = { 45*fb279d8bSVesa Jääskeläinen /* EC flavors (Must find key size from the object) */ 46*fb279d8bSVesa Jääskeläinen { PKCS11_CKM_ECDSA, 1, 0 }, 47*fb279d8bSVesa Jääskeläinen { PKCS11_CKM_ECDSA_SHA1, 1, TEE_ALG_SHA1 }, 48*fb279d8bSVesa Jääskeläinen { PKCS11_CKM_ECDSA_SHA224, 1, TEE_ALG_SHA224 }, 49*fb279d8bSVesa Jääskeläinen { PKCS11_CKM_ECDSA_SHA256, 1, TEE_ALG_SHA256 }, 50*fb279d8bSVesa Jääskeläinen { PKCS11_CKM_ECDSA_SHA384, 1, TEE_ALG_SHA384 }, 51*fb279d8bSVesa Jääskeläinen { PKCS11_CKM_ECDSA_SHA512, 1, TEE_ALG_SHA512 }, 52*fb279d8bSVesa Jääskeläinen }; 53*fb279d8bSVesa Jääskeläinen size_t n = 0; 54*fb279d8bSVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 55*fb279d8bSVesa Jääskeläinen 56*fb279d8bSVesa Jääskeläinen for (n = 0; n < ARRAY_SIZE(pkcs2tee_algo); n++) { 57*fb279d8bSVesa Jääskeläinen if (pkcs2tee_algo[n].mech_id == proc_params->id) { 58*fb279d8bSVesa Jääskeläinen *tee_id = pkcs2tee_algo[n].tee_id; 59*fb279d8bSVesa Jääskeläinen *tee_hash_id = pkcs2tee_algo[n].tee_hash_id; 60*fb279d8bSVesa Jääskeläinen break; 61*fb279d8bSVesa Jääskeläinen } 62*fb279d8bSVesa Jääskeläinen } 63*fb279d8bSVesa Jääskeläinen 64*fb279d8bSVesa Jääskeläinen if (n == ARRAY_SIZE(pkcs2tee_algo)) 65*fb279d8bSVesa Jääskeläinen return PKCS11_RV_NOT_IMPLEMENTED; 66*fb279d8bSVesa Jääskeläinen 67*fb279d8bSVesa Jääskeläinen switch (proc_params->id) { 68*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA: 69*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA1: 70*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA224: 71*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA256: 72*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA384: 73*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA512: 74*fb279d8bSVesa Jääskeläinen rc = pkcs2tee_algo_ecdsa(tee_id, proc_params, obj); 75*fb279d8bSVesa Jääskeläinen break; 76*fb279d8bSVesa Jääskeläinen default: 77*fb279d8bSVesa Jääskeläinen rc = PKCS11_CKR_OK; 78*fb279d8bSVesa Jääskeläinen break; 79*fb279d8bSVesa Jääskeläinen } 80*fb279d8bSVesa Jääskeläinen 81*fb279d8bSVesa Jääskeläinen return rc; 82*fb279d8bSVesa Jääskeläinen } 83*fb279d8bSVesa Jääskeläinen 84*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc pkcs2tee_key_type(uint32_t *tee_type, 85*fb279d8bSVesa Jääskeläinen struct pkcs11_object *obj, 86*fb279d8bSVesa Jääskeläinen enum processing_func function) 87*fb279d8bSVesa Jääskeläinen { 88*fb279d8bSVesa Jääskeläinen enum pkcs11_class_id class = get_class(obj->attributes); 89*fb279d8bSVesa Jääskeläinen enum pkcs11_key_type type = get_key_type(obj->attributes); 90*fb279d8bSVesa Jääskeläinen 91*fb279d8bSVesa Jääskeläinen switch (class) { 92*fb279d8bSVesa Jääskeläinen case PKCS11_CKO_PUBLIC_KEY: 93*fb279d8bSVesa Jääskeläinen case PKCS11_CKO_PRIVATE_KEY: 94*fb279d8bSVesa Jääskeläinen break; 95*fb279d8bSVesa Jääskeläinen default: 96*fb279d8bSVesa Jääskeläinen TEE_Panic(class); 97*fb279d8bSVesa Jääskeläinen break; 98*fb279d8bSVesa Jääskeläinen } 99*fb279d8bSVesa Jääskeläinen 100*fb279d8bSVesa Jääskeläinen switch (type) { 101*fb279d8bSVesa Jääskeläinen case PKCS11_CKK_EC: 102*fb279d8bSVesa Jääskeläinen assert(function != PKCS11_FUNCTION_DERIVE); 103*fb279d8bSVesa Jääskeläinen 104*fb279d8bSVesa Jääskeläinen if (class == PKCS11_CKO_PRIVATE_KEY) 105*fb279d8bSVesa Jääskeläinen *tee_type = TEE_TYPE_ECDSA_KEYPAIR; 106*fb279d8bSVesa Jääskeläinen else 107*fb279d8bSVesa Jääskeläinen *tee_type = TEE_TYPE_ECDSA_PUBLIC_KEY; 108*fb279d8bSVesa Jääskeläinen break; 109*fb279d8bSVesa Jääskeläinen default: 110*fb279d8bSVesa Jääskeläinen TEE_Panic(type); 111*fb279d8bSVesa Jääskeläinen break; 112*fb279d8bSVesa Jääskeläinen } 113*fb279d8bSVesa Jääskeläinen 114*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_OK; 115*fb279d8bSVesa Jääskeläinen } 116*fb279d8bSVesa Jääskeläinen 117*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc 118*fb279d8bSVesa Jääskeläinen allocate_tee_operation(struct pkcs11_session *session, 119*fb279d8bSVesa Jääskeläinen enum processing_func function, 120*fb279d8bSVesa Jääskeläinen struct pkcs11_attribute_head *params, 121*fb279d8bSVesa Jääskeläinen struct pkcs11_object *obj) 122*fb279d8bSVesa Jääskeläinen { 123*fb279d8bSVesa Jääskeläinen uint32_t size = (uint32_t)get_object_key_bit_size(obj); 124*fb279d8bSVesa Jääskeläinen uint32_t algo = 0; 125*fb279d8bSVesa Jääskeläinen uint32_t hash_algo = 0; 126*fb279d8bSVesa Jääskeläinen uint32_t mode = 0; 127*fb279d8bSVesa Jääskeläinen uint32_t hash_mode = 0; 128*fb279d8bSVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC; 129*fb279d8bSVesa Jääskeläinen struct active_processing *processing = session->processing; 130*fb279d8bSVesa Jääskeläinen 131*fb279d8bSVesa Jääskeläinen assert(processing->tee_op_handle == TEE_HANDLE_NULL); 132*fb279d8bSVesa Jääskeläinen assert(processing->tee_hash_op_handle == TEE_HANDLE_NULL); 133*fb279d8bSVesa Jääskeläinen 134*fb279d8bSVesa Jääskeläinen if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj)) 135*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_FUNCTION_FAILED; 136*fb279d8bSVesa Jääskeläinen 137*fb279d8bSVesa Jääskeläinen pkcs2tee_mode(&mode, function); 138*fb279d8bSVesa Jääskeläinen 139*fb279d8bSVesa Jääskeläinen if (hash_algo) { 140*fb279d8bSVesa Jääskeläinen pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST); 141*fb279d8bSVesa Jääskeläinen 142*fb279d8bSVesa Jääskeläinen res = TEE_AllocateOperation(&processing->tee_hash_op_handle, 143*fb279d8bSVesa Jääskeläinen hash_algo, hash_mode, 0); 144*fb279d8bSVesa Jääskeläinen if (res) { 145*fb279d8bSVesa Jääskeläinen EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32, 146*fb279d8bSVesa Jääskeläinen hash_algo, hash_mode); 147*fb279d8bSVesa Jääskeläinen 148*fb279d8bSVesa Jääskeläinen if (res == TEE_ERROR_NOT_SUPPORTED) 149*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_MECHANISM_INVALID; 150*fb279d8bSVesa Jääskeläinen return tee2pkcs_error(res); 151*fb279d8bSVesa Jääskeläinen } 152*fb279d8bSVesa Jääskeläinen processing->tee_hash_algo = hash_algo; 153*fb279d8bSVesa Jääskeläinen } 154*fb279d8bSVesa Jääskeläinen 155*fb279d8bSVesa Jääskeläinen res = TEE_AllocateOperation(&processing->tee_op_handle, 156*fb279d8bSVesa Jääskeläinen algo, mode, size); 157*fb279d8bSVesa Jääskeläinen if (res) 158*fb279d8bSVesa Jääskeläinen EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32" %#"PRIx32, 159*fb279d8bSVesa Jääskeläinen algo, mode, size); 160*fb279d8bSVesa Jääskeläinen 161*fb279d8bSVesa Jääskeläinen if (res == TEE_ERROR_NOT_SUPPORTED) 162*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_MECHANISM_INVALID; 163*fb279d8bSVesa Jääskeläinen 164*fb279d8bSVesa Jääskeläinen if (res != TEE_SUCCESS && 165*fb279d8bSVesa Jääskeläinen processing->tee_hash_op_handle != TEE_HANDLE_NULL) { 166*fb279d8bSVesa Jääskeläinen TEE_FreeOperation(session->processing->tee_hash_op_handle); 167*fb279d8bSVesa Jääskeläinen processing->tee_hash_op_handle = TEE_HANDLE_NULL; 168*fb279d8bSVesa Jääskeläinen processing->tee_hash_algo = 0; 169*fb279d8bSVesa Jääskeläinen } 170*fb279d8bSVesa Jääskeläinen 171*fb279d8bSVesa Jääskeläinen return tee2pkcs_error(res); 172*fb279d8bSVesa Jääskeläinen } 173*fb279d8bSVesa Jääskeläinen 174*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc load_tee_key(struct pkcs11_session *session, 175*fb279d8bSVesa Jääskeläinen struct pkcs11_object *obj, 176*fb279d8bSVesa Jääskeläinen enum processing_func function) 177*fb279d8bSVesa Jääskeläinen { 178*fb279d8bSVesa Jääskeläinen TEE_Attribute *tee_attrs = NULL; 179*fb279d8bSVesa Jääskeläinen size_t tee_attrs_count = 0; 180*fb279d8bSVesa Jääskeläinen size_t object_size = 0; 181*fb279d8bSVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 182*fb279d8bSVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC; 183*fb279d8bSVesa Jääskeläinen enum pkcs11_class_id __maybe_unused class = get_class(obj->attributes); 184*fb279d8bSVesa Jääskeläinen enum pkcs11_key_type type = get_key_type(obj->attributes); 185*fb279d8bSVesa Jääskeläinen 186*fb279d8bSVesa Jääskeläinen assert(class == PKCS11_CKO_PUBLIC_KEY || 187*fb279d8bSVesa Jääskeläinen class == PKCS11_CKO_PRIVATE_KEY); 188*fb279d8bSVesa Jääskeläinen 189*fb279d8bSVesa Jääskeläinen if (obj->key_handle != TEE_HANDLE_NULL) { 190*fb279d8bSVesa Jääskeläinen switch (type) { 191*fb279d8bSVesa Jääskeläinen case PKCS11_CKK_EC: 192*fb279d8bSVesa Jääskeläinen /* Reuse EC TEE key only if already DSA or DH */ 193*fb279d8bSVesa Jääskeläinen switch (obj->key_type) { 194*fb279d8bSVesa Jääskeläinen case TEE_TYPE_ECDSA_PUBLIC_KEY: 195*fb279d8bSVesa Jääskeläinen case TEE_TYPE_ECDSA_KEYPAIR: 196*fb279d8bSVesa Jääskeläinen if (function != PKCS11_FUNCTION_DERIVE) 197*fb279d8bSVesa Jääskeläinen goto key_ready; 198*fb279d8bSVesa Jääskeläinen break; 199*fb279d8bSVesa Jääskeläinen default: 200*fb279d8bSVesa Jääskeläinen assert(0); 201*fb279d8bSVesa Jääskeläinen break; 202*fb279d8bSVesa Jääskeläinen } 203*fb279d8bSVesa Jääskeläinen break; 204*fb279d8bSVesa Jääskeläinen default: 205*fb279d8bSVesa Jääskeläinen assert(0); 206*fb279d8bSVesa Jääskeläinen break; 207*fb279d8bSVesa Jääskeläinen } 208*fb279d8bSVesa Jääskeläinen 209*fb279d8bSVesa Jääskeläinen TEE_CloseObject(obj->key_handle); 210*fb279d8bSVesa Jääskeläinen obj->key_handle = TEE_HANDLE_NULL; 211*fb279d8bSVesa Jääskeläinen } 212*fb279d8bSVesa Jääskeläinen 213*fb279d8bSVesa Jääskeläinen rc = pkcs2tee_key_type(&obj->key_type, obj, function); 214*fb279d8bSVesa Jääskeläinen if (rc) 215*fb279d8bSVesa Jääskeläinen return rc; 216*fb279d8bSVesa Jääskeläinen 217*fb279d8bSVesa Jääskeläinen object_size = get_object_key_bit_size(obj); 218*fb279d8bSVesa Jääskeläinen if (!object_size) 219*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_GENERAL_ERROR; 220*fb279d8bSVesa Jääskeläinen 221*fb279d8bSVesa Jääskeläinen switch (type) { 222*fb279d8bSVesa Jääskeläinen case PKCS11_CKK_EC: 223*fb279d8bSVesa Jääskeläinen rc = load_tee_ec_key_attrs(&tee_attrs, &tee_attrs_count, obj); 224*fb279d8bSVesa Jääskeläinen break; 225*fb279d8bSVesa Jääskeläinen default: 226*fb279d8bSVesa Jääskeläinen break; 227*fb279d8bSVesa Jääskeläinen } 228*fb279d8bSVesa Jääskeläinen if (rc) 229*fb279d8bSVesa Jääskeläinen return rc; 230*fb279d8bSVesa Jääskeläinen 231*fb279d8bSVesa Jääskeläinen res = TEE_AllocateTransientObject(obj->key_type, object_size, 232*fb279d8bSVesa Jääskeläinen &obj->key_handle); 233*fb279d8bSVesa Jääskeläinen if (res) { 234*fb279d8bSVesa Jääskeläinen DMSG("TEE_AllocateTransientObject failed, %#"PRIx32, res); 235*fb279d8bSVesa Jääskeläinen 236*fb279d8bSVesa Jääskeläinen return tee2pkcs_error(res); 237*fb279d8bSVesa Jääskeläinen } 238*fb279d8bSVesa Jääskeläinen 239*fb279d8bSVesa Jääskeläinen res = TEE_PopulateTransientObject(obj->key_handle, 240*fb279d8bSVesa Jääskeläinen tee_attrs, tee_attrs_count); 241*fb279d8bSVesa Jääskeläinen 242*fb279d8bSVesa Jääskeläinen TEE_Free(tee_attrs); 243*fb279d8bSVesa Jääskeläinen 244*fb279d8bSVesa Jääskeläinen if (res) { 245*fb279d8bSVesa Jääskeläinen DMSG("TEE_PopulateTransientObject failed, %#"PRIx32, res); 246*fb279d8bSVesa Jääskeläinen 247*fb279d8bSVesa Jääskeläinen goto error; 248*fb279d8bSVesa Jääskeläinen } 249*fb279d8bSVesa Jääskeläinen 250*fb279d8bSVesa Jääskeläinen key_ready: 251*fb279d8bSVesa Jääskeläinen res = TEE_SetOperationKey(session->processing->tee_op_handle, 252*fb279d8bSVesa Jääskeläinen obj->key_handle); 253*fb279d8bSVesa Jääskeläinen if (res) { 254*fb279d8bSVesa Jääskeläinen DMSG("TEE_SetOperationKey failed, %#"PRIx32, res); 255*fb279d8bSVesa Jääskeläinen 256*fb279d8bSVesa Jääskeläinen goto error; 257*fb279d8bSVesa Jääskeläinen } 258*fb279d8bSVesa Jääskeläinen 259*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_OK; 260*fb279d8bSVesa Jääskeläinen 261*fb279d8bSVesa Jääskeläinen error: 262*fb279d8bSVesa Jääskeläinen TEE_FreeTransientObject(obj->key_handle); 263*fb279d8bSVesa Jääskeläinen obj->key_handle = TEE_HANDLE_NULL; 264*fb279d8bSVesa Jääskeläinen return tee2pkcs_error(res); 265*fb279d8bSVesa Jääskeläinen } 266*fb279d8bSVesa Jääskeläinen 267*fb279d8bSVesa Jääskeläinen static enum pkcs11_rc 268*fb279d8bSVesa Jääskeläinen init_tee_operation(struct pkcs11_session *session __unused, 269*fb279d8bSVesa Jääskeläinen struct pkcs11_attribute_head *proc_params __unused) 270*fb279d8bSVesa Jääskeläinen { 271*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_OK; 272*fb279d8bSVesa Jääskeläinen } 273*fb279d8bSVesa Jääskeläinen 274*fb279d8bSVesa Jääskeläinen enum pkcs11_rc init_asymm_operation(struct pkcs11_session *session, 275*fb279d8bSVesa Jääskeläinen enum processing_func function, 276*fb279d8bSVesa Jääskeläinen struct pkcs11_attribute_head *proc_params, 277*fb279d8bSVesa Jääskeläinen struct pkcs11_object *obj) 278*fb279d8bSVesa Jääskeläinen { 279*fb279d8bSVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 280*fb279d8bSVesa Jääskeläinen 281*fb279d8bSVesa Jääskeläinen assert(processing_is_tee_asymm(proc_params->id)); 282*fb279d8bSVesa Jääskeläinen 283*fb279d8bSVesa Jääskeläinen rc = allocate_tee_operation(session, function, proc_params, obj); 284*fb279d8bSVesa Jääskeläinen if (rc) 285*fb279d8bSVesa Jääskeläinen return rc; 286*fb279d8bSVesa Jääskeläinen 287*fb279d8bSVesa Jääskeläinen rc = load_tee_key(session, obj, function); 288*fb279d8bSVesa Jääskeläinen if (rc) 289*fb279d8bSVesa Jääskeläinen return rc; 290*fb279d8bSVesa Jääskeläinen 291*fb279d8bSVesa Jääskeläinen return init_tee_operation(session, proc_params); 292*fb279d8bSVesa Jääskeläinen } 293*fb279d8bSVesa Jääskeläinen 294*fb279d8bSVesa Jääskeläinen /* 295*fb279d8bSVesa Jääskeläinen * step_sym_step - step (update/oneshot/final) on a symmetric crypto operation 296*fb279d8bSVesa Jääskeläinen * 297*fb279d8bSVesa Jääskeläinen * @session - current session 298*fb279d8bSVesa Jääskeläinen * @function - processing function (encrypt, decrypt, sign, ...) 299*fb279d8bSVesa Jääskeläinen * @step - step ID in the processing (oneshot, update, final) 300*fb279d8bSVesa Jääskeläinen * @ptypes - invocation parameter types 301*fb279d8bSVesa Jääskeläinen * @params - invocation parameter references 302*fb279d8bSVesa Jääskeläinen */ 303*fb279d8bSVesa Jääskeläinen enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session, 304*fb279d8bSVesa Jääskeläinen enum processing_func function, 305*fb279d8bSVesa Jääskeläinen enum processing_step step, 306*fb279d8bSVesa Jääskeläinen uint32_t ptypes, TEE_Param *params) 307*fb279d8bSVesa Jääskeläinen { 308*fb279d8bSVesa Jääskeläinen enum pkcs11_rc rc = PKCS11_CKR_GENERAL_ERROR; 309*fb279d8bSVesa Jääskeläinen TEE_Result res = TEE_ERROR_GENERIC; 310*fb279d8bSVesa Jääskeläinen void *in_buf = NULL; 311*fb279d8bSVesa Jääskeläinen void *in2_buf = NULL; 312*fb279d8bSVesa Jääskeläinen void *out_buf = NULL; 313*fb279d8bSVesa Jääskeläinen void *hash_buf = NULL; 314*fb279d8bSVesa Jääskeläinen uint32_t in_size = 0; 315*fb279d8bSVesa Jääskeläinen uint32_t in2_size = 0; 316*fb279d8bSVesa Jääskeläinen uint32_t out_size = 0; 317*fb279d8bSVesa Jääskeläinen uint32_t hash_size = 0; 318*fb279d8bSVesa Jääskeläinen TEE_Attribute *tee_attrs = NULL; 319*fb279d8bSVesa Jääskeläinen size_t tee_attrs_count = 0; 320*fb279d8bSVesa Jääskeläinen bool output_data = false; 321*fb279d8bSVesa Jääskeläinen struct active_processing *proc = session->processing; 322*fb279d8bSVesa Jääskeläinen size_t sz = 0; 323*fb279d8bSVesa Jääskeläinen 324*fb279d8bSVesa Jääskeläinen if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) { 325*fb279d8bSVesa Jääskeläinen in_buf = params[1].memref.buffer; 326*fb279d8bSVesa Jääskeläinen in_size = params[1].memref.size; 327*fb279d8bSVesa Jääskeläinen if (in_size && !in_buf) 328*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 329*fb279d8bSVesa Jääskeläinen } 330*fb279d8bSVesa Jääskeläinen if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_INPUT) { 331*fb279d8bSVesa Jääskeläinen in2_buf = params[2].memref.buffer; 332*fb279d8bSVesa Jääskeläinen in2_size = params[2].memref.size; 333*fb279d8bSVesa Jääskeläinen if (in2_size && !in2_buf) 334*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 335*fb279d8bSVesa Jääskeläinen } 336*fb279d8bSVesa Jääskeläinen if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) { 337*fb279d8bSVesa Jääskeläinen out_buf = params[2].memref.buffer; 338*fb279d8bSVesa Jääskeläinen out_size = params[2].memref.size; 339*fb279d8bSVesa Jääskeläinen if (out_size && !out_buf) 340*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 341*fb279d8bSVesa Jääskeläinen } 342*fb279d8bSVesa Jääskeläinen if (TEE_PARAM_TYPE_GET(ptypes, 3) != TEE_PARAM_TYPE_NONE) 343*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_ARGUMENTS_BAD; 344*fb279d8bSVesa Jääskeläinen 345*fb279d8bSVesa Jääskeläinen switch (step) { 346*fb279d8bSVesa Jääskeläinen case PKCS11_FUNC_STEP_ONESHOT: 347*fb279d8bSVesa Jääskeläinen case PKCS11_FUNC_STEP_UPDATE: 348*fb279d8bSVesa Jääskeläinen case PKCS11_FUNC_STEP_FINAL: 349*fb279d8bSVesa Jääskeläinen break; 350*fb279d8bSVesa Jääskeläinen default: 351*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_GENERAL_ERROR; 352*fb279d8bSVesa Jääskeläinen } 353*fb279d8bSVesa Jääskeläinen 354*fb279d8bSVesa Jääskeläinen /* 355*fb279d8bSVesa Jääskeläinen * Handle multi stage update step for mechas needing hash 356*fb279d8bSVesa Jääskeläinen * calculation 357*fb279d8bSVesa Jääskeläinen */ 358*fb279d8bSVesa Jääskeläinen if (step == PKCS11_FUNC_STEP_UPDATE) { 359*fb279d8bSVesa Jääskeläinen switch (proc->mecha_type) { 360*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA1: 361*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA224: 362*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA256: 363*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA384: 364*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA512: 365*fb279d8bSVesa Jääskeläinen assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL); 366*fb279d8bSVesa Jääskeläinen 367*fb279d8bSVesa Jääskeläinen TEE_DigestUpdate(proc->tee_hash_op_handle, in_buf, 368*fb279d8bSVesa Jääskeläinen in_size); 369*fb279d8bSVesa Jääskeläinen break; 370*fb279d8bSVesa Jääskeläinen default: 371*fb279d8bSVesa Jääskeläinen /* 372*fb279d8bSVesa Jääskeläinen * Other mechanism do not expect multi stage 373*fb279d8bSVesa Jääskeläinen * operation 374*fb279d8bSVesa Jääskeläinen */ 375*fb279d8bSVesa Jääskeläinen rc = PKCS11_CKR_GENERAL_ERROR; 376*fb279d8bSVesa Jääskeläinen break; 377*fb279d8bSVesa Jääskeläinen } 378*fb279d8bSVesa Jääskeläinen 379*fb279d8bSVesa Jääskeläinen goto out; 380*fb279d8bSVesa Jääskeläinen } 381*fb279d8bSVesa Jääskeläinen 382*fb279d8bSVesa Jääskeläinen /* 383*fb279d8bSVesa Jääskeläinen * Handle multi stage one shot and final steps for mechas needing hash 384*fb279d8bSVesa Jääskeläinen * calculation 385*fb279d8bSVesa Jääskeläinen */ 386*fb279d8bSVesa Jääskeläinen switch (proc->mecha_type) { 387*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA1: 388*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA224: 389*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA256: 390*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA384: 391*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA512: 392*fb279d8bSVesa Jääskeläinen assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL); 393*fb279d8bSVesa Jääskeläinen 394*fb279d8bSVesa Jääskeläinen hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo); 395*fb279d8bSVesa Jääskeläinen hash_buf = TEE_Malloc(hash_size, 0); 396*fb279d8bSVesa Jääskeläinen if (!hash_buf) 397*fb279d8bSVesa Jääskeläinen return PKCS11_CKR_DEVICE_MEMORY; 398*fb279d8bSVesa Jääskeläinen 399*fb279d8bSVesa Jääskeläinen res = TEE_DigestDoFinal(proc->tee_hash_op_handle, 400*fb279d8bSVesa Jääskeläinen in_buf, in_size, hash_buf, 401*fb279d8bSVesa Jääskeläinen &hash_size); 402*fb279d8bSVesa Jääskeläinen 403*fb279d8bSVesa Jääskeläinen rc = tee2pkcs_error(res); 404*fb279d8bSVesa Jääskeläinen if (rc != PKCS11_CKR_OK) 405*fb279d8bSVesa Jääskeläinen goto out; 406*fb279d8bSVesa Jääskeläinen 407*fb279d8bSVesa Jääskeläinen break; 408*fb279d8bSVesa Jääskeläinen default: 409*fb279d8bSVesa Jääskeläinen break; 410*fb279d8bSVesa Jääskeläinen } 411*fb279d8bSVesa Jääskeläinen 412*fb279d8bSVesa Jääskeläinen /* 413*fb279d8bSVesa Jääskeläinen * Finalize either provided hash or calculated hash with signing 414*fb279d8bSVesa Jääskeläinen * operation 415*fb279d8bSVesa Jääskeläinen */ 416*fb279d8bSVesa Jääskeläinen 417*fb279d8bSVesa Jääskeläinen /* First determine amount of bytes for signing operation */ 418*fb279d8bSVesa Jääskeläinen switch (proc->mecha_type) { 419*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA: 420*fb279d8bSVesa Jääskeläinen sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle); 421*fb279d8bSVesa Jääskeläinen if (!in_size || !sz) { 422*fb279d8bSVesa Jääskeläinen rc = PKCS11_CKR_FUNCTION_FAILED; 423*fb279d8bSVesa Jääskeläinen goto out; 424*fb279d8bSVesa Jääskeläinen } 425*fb279d8bSVesa Jääskeläinen 426*fb279d8bSVesa Jääskeläinen /* 427*fb279d8bSVesa Jääskeläinen * Note 3) Input the entire raw digest. Internally, this will 428*fb279d8bSVesa Jääskeläinen * be truncated to the appropriate number of bits. 429*fb279d8bSVesa Jääskeläinen */ 430*fb279d8bSVesa Jääskeläinen if (in_size > sz) 431*fb279d8bSVesa Jääskeläinen in_size = sz; 432*fb279d8bSVesa Jääskeläinen 433*fb279d8bSVesa Jääskeläinen if (function == PKCS11_FUNCTION_VERIFY && in2_size != 2 * sz) { 434*fb279d8bSVesa Jääskeläinen rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; 435*fb279d8bSVesa Jääskeläinen goto out; 436*fb279d8bSVesa Jääskeläinen } 437*fb279d8bSVesa Jääskeläinen break; 438*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA1: 439*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA224: 440*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA256: 441*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA384: 442*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA512: 443*fb279d8bSVesa Jääskeläinen /* Get key size in bytes */ 444*fb279d8bSVesa Jääskeläinen sz = ecdsa_get_input_max_byte_size(proc->tee_op_handle); 445*fb279d8bSVesa Jääskeläinen if (!sz) { 446*fb279d8bSVesa Jääskeläinen rc = PKCS11_CKR_FUNCTION_FAILED; 447*fb279d8bSVesa Jääskeläinen goto out; 448*fb279d8bSVesa Jääskeläinen } 449*fb279d8bSVesa Jääskeläinen 450*fb279d8bSVesa Jääskeläinen if (function == PKCS11_FUNCTION_VERIFY && 451*fb279d8bSVesa Jääskeläinen in2_size != 2 * sz) { 452*fb279d8bSVesa Jääskeläinen rc = PKCS11_CKR_SIGNATURE_LEN_RANGE; 453*fb279d8bSVesa Jääskeläinen goto out; 454*fb279d8bSVesa Jääskeläinen } 455*fb279d8bSVesa Jääskeläinen break; 456*fb279d8bSVesa Jääskeläinen default: 457*fb279d8bSVesa Jääskeläinen break; 458*fb279d8bSVesa Jääskeläinen } 459*fb279d8bSVesa Jääskeläinen 460*fb279d8bSVesa Jääskeläinen /* Next perform actual signing operation */ 461*fb279d8bSVesa Jääskeläinen switch (proc->mecha_type) { 462*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA: 463*fb279d8bSVesa Jääskeläinen /* For operations using provided input data */ 464*fb279d8bSVesa Jääskeläinen switch (function) { 465*fb279d8bSVesa Jääskeläinen case PKCS11_FUNCTION_ENCRYPT: 466*fb279d8bSVesa Jääskeläinen res = TEE_AsymmetricEncrypt(proc->tee_op_handle, 467*fb279d8bSVesa Jääskeläinen tee_attrs, tee_attrs_count, 468*fb279d8bSVesa Jääskeläinen in_buf, in_size, 469*fb279d8bSVesa Jääskeläinen out_buf, &out_size); 470*fb279d8bSVesa Jääskeläinen output_data = true; 471*fb279d8bSVesa Jääskeläinen rc = tee2pkcs_error(res); 472*fb279d8bSVesa Jääskeläinen break; 473*fb279d8bSVesa Jääskeläinen 474*fb279d8bSVesa Jääskeläinen case PKCS11_FUNCTION_DECRYPT: 475*fb279d8bSVesa Jääskeläinen res = TEE_AsymmetricDecrypt(proc->tee_op_handle, 476*fb279d8bSVesa Jääskeläinen tee_attrs, tee_attrs_count, 477*fb279d8bSVesa Jääskeläinen in_buf, in_size, 478*fb279d8bSVesa Jääskeläinen out_buf, &out_size); 479*fb279d8bSVesa Jääskeläinen output_data = true; 480*fb279d8bSVesa Jääskeläinen rc = tee2pkcs_error(res); 481*fb279d8bSVesa Jääskeläinen break; 482*fb279d8bSVesa Jääskeläinen 483*fb279d8bSVesa Jääskeläinen case PKCS11_FUNCTION_SIGN: 484*fb279d8bSVesa Jääskeläinen res = TEE_AsymmetricSignDigest(proc->tee_op_handle, 485*fb279d8bSVesa Jääskeläinen tee_attrs, 486*fb279d8bSVesa Jääskeläinen tee_attrs_count, 487*fb279d8bSVesa Jääskeläinen in_buf, in_size, 488*fb279d8bSVesa Jääskeläinen out_buf, &out_size); 489*fb279d8bSVesa Jääskeläinen output_data = true; 490*fb279d8bSVesa Jääskeläinen rc = tee2pkcs_error(res); 491*fb279d8bSVesa Jääskeläinen break; 492*fb279d8bSVesa Jääskeläinen 493*fb279d8bSVesa Jääskeläinen case PKCS11_FUNCTION_VERIFY: 494*fb279d8bSVesa Jääskeläinen res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle, 495*fb279d8bSVesa Jääskeläinen tee_attrs, 496*fb279d8bSVesa Jääskeläinen tee_attrs_count, 497*fb279d8bSVesa Jääskeläinen in_buf, in_size, 498*fb279d8bSVesa Jääskeläinen in2_buf, in2_size); 499*fb279d8bSVesa Jääskeläinen rc = tee2pkcs_error(res); 500*fb279d8bSVesa Jääskeläinen break; 501*fb279d8bSVesa Jääskeläinen 502*fb279d8bSVesa Jääskeläinen default: 503*fb279d8bSVesa Jääskeläinen TEE_Panic(function); 504*fb279d8bSVesa Jääskeläinen break; 505*fb279d8bSVesa Jääskeläinen } 506*fb279d8bSVesa Jääskeläinen break; 507*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA1: 508*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA224: 509*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA256: 510*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA384: 511*fb279d8bSVesa Jääskeläinen case PKCS11_CKM_ECDSA_SHA512: 512*fb279d8bSVesa Jääskeläinen /* For operations having hash operation use calculated hash */ 513*fb279d8bSVesa Jääskeläinen switch (function) { 514*fb279d8bSVesa Jääskeläinen case PKCS11_FUNCTION_SIGN: 515*fb279d8bSVesa Jääskeläinen res = TEE_AsymmetricSignDigest(proc->tee_op_handle, 516*fb279d8bSVesa Jääskeläinen tee_attrs, 517*fb279d8bSVesa Jääskeläinen tee_attrs_count, 518*fb279d8bSVesa Jääskeläinen hash_buf, hash_size, 519*fb279d8bSVesa Jääskeläinen out_buf, &out_size); 520*fb279d8bSVesa Jääskeläinen output_data = true; 521*fb279d8bSVesa Jääskeläinen rc = tee2pkcs_error(res); 522*fb279d8bSVesa Jääskeläinen break; 523*fb279d8bSVesa Jääskeläinen 524*fb279d8bSVesa Jääskeläinen case PKCS11_FUNCTION_VERIFY: 525*fb279d8bSVesa Jääskeläinen res = TEE_AsymmetricVerifyDigest(proc->tee_op_handle, 526*fb279d8bSVesa Jääskeläinen tee_attrs, 527*fb279d8bSVesa Jääskeläinen tee_attrs_count, 528*fb279d8bSVesa Jääskeläinen hash_buf, hash_size, 529*fb279d8bSVesa Jääskeläinen in2_buf, in2_size); 530*fb279d8bSVesa Jääskeläinen rc = tee2pkcs_error(res); 531*fb279d8bSVesa Jääskeläinen break; 532*fb279d8bSVesa Jääskeläinen 533*fb279d8bSVesa Jääskeläinen default: 534*fb279d8bSVesa Jääskeläinen TEE_Panic(function); 535*fb279d8bSVesa Jääskeläinen break; 536*fb279d8bSVesa Jääskeläinen } 537*fb279d8bSVesa Jääskeläinen break; 538*fb279d8bSVesa Jääskeläinen default: 539*fb279d8bSVesa Jääskeläinen TEE_Panic(proc->mecha_type); 540*fb279d8bSVesa Jääskeläinen break; 541*fb279d8bSVesa Jääskeläinen } 542*fb279d8bSVesa Jääskeläinen 543*fb279d8bSVesa Jääskeläinen out: 544*fb279d8bSVesa Jääskeläinen if (output_data && 545*fb279d8bSVesa Jääskeläinen (rc == PKCS11_CKR_OK || rc == PKCS11_CKR_BUFFER_TOO_SMALL)) { 546*fb279d8bSVesa Jääskeläinen switch (TEE_PARAM_TYPE_GET(ptypes, 2)) { 547*fb279d8bSVesa Jääskeläinen case TEE_PARAM_TYPE_MEMREF_OUTPUT: 548*fb279d8bSVesa Jääskeläinen case TEE_PARAM_TYPE_MEMREF_INOUT: 549*fb279d8bSVesa Jääskeläinen params[2].memref.size = out_size; 550*fb279d8bSVesa Jääskeläinen break; 551*fb279d8bSVesa Jääskeläinen default: 552*fb279d8bSVesa Jääskeläinen rc = PKCS11_CKR_GENERAL_ERROR; 553*fb279d8bSVesa Jääskeläinen break; 554*fb279d8bSVesa Jääskeläinen } 555*fb279d8bSVesa Jääskeläinen } 556*fb279d8bSVesa Jääskeläinen 557*fb279d8bSVesa Jääskeläinen TEE_Free(hash_buf); 558*fb279d8bSVesa Jääskeläinen TEE_Free(tee_attrs); 559*fb279d8bSVesa Jääskeläinen 560*fb279d8bSVesa Jääskeläinen return rc; 561*fb279d8bSVesa Jääskeläinen } 562