1512cbf1dSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2512cbf1dSJens Wiklander /* 3512cbf1dSJens Wiklander * Copyright (c) 2018-2020, Linaro Limited 4512cbf1dSJens Wiklander */ 5512cbf1dSJens Wiklander 6512cbf1dSJens Wiklander #include <assert.h> 7512cbf1dSJens Wiklander #include <compiler.h> 8512cbf1dSJens Wiklander #include <tee_internal_api.h> 9*63778faaSEtienne Carriere #include <tee_internal_api_extensions.h> 10512cbf1dSJens Wiklander #include <trace.h> 11512cbf1dSJens Wiklander #include <util.h> 12512cbf1dSJens Wiklander 13512cbf1dSJens Wiklander #include "pkcs11_helpers.h" 14512cbf1dSJens Wiklander #include "pkcs11_token.h" 15512cbf1dSJens Wiklander #include "processing.h" 16512cbf1dSJens Wiklander #include "serializer.h" 17512cbf1dSJens Wiklander 18*63778faaSEtienne Carriere /* 19*63778faaSEtienne Carriere * Authenticated ciphering: (AES GCM) 20*63778faaSEtienne Carriere * 21*63778faaSEtienne Carriere * As per PKCS#11, GCM decryption shall not reveal the data until the 22*63778faaSEtienne Carriere * decryption is completed and the MAC verified. The pkcs11 TA retains the 23*63778faaSEtienne Carriere * ciphered data until the operation is completed. Therefore every chunk of 24*63778faaSEtienne Carriere * decrypted data is saved in a allocated buffer during AE update processing 25*63778faaSEtienne Carriere * and only copied into the client's output buffer at AE finalization when 26*63778faaSEtienne Carriere * tag is authenticated. 27*63778faaSEtienne Carriere * 28*63778faaSEtienne Carriere * As per PKCS#11, GCM decryption expect the tag data to be provided 29*63778faaSEtienne Carriere * inside the input data for C_DecryptUpdate() and friends, appended to the 30*63778faaSEtienne Carriere * input encyprted data hence we do not know which is the last call to 31*63778faaSEtienne Carriere * C_DecryptUpdate() where last bytes are not ciphered data but the requested 32*63778faaSEtienne Carriere * tag bytes for message autehntication. To handle this, the TA saves 33*63778faaSEtienne Carriere * the last input data bytes (length is defined by the tag byte size) in the 34*63778faaSEtienne Carriere * AE context and waits the C_DecryptFinal() to either treat these as data 35*63778faaSEtienne Carriere * bytes or tag/MAC bytes. Refer to pending_tag and pending_size in struct 36*63778faaSEtienne Carriere * ae_aes_context. 37*63778faaSEtienne Carriere */ 38*63778faaSEtienne Carriere 39*63778faaSEtienne Carriere /* 40*63778faaSEtienne Carriere * struct out_data_ref - AE decyrption output data chunks 41*63778faaSEtienne Carriere * @size - byte size of the allocated buffer 42*63778faaSEtienne Carriere * @data - pointer to allocated data 43*63778faaSEtienne Carriere */ 44*63778faaSEtienne Carriere struct out_data_ref { 45*63778faaSEtienne Carriere size_t size; 46*63778faaSEtienne Carriere void *data; 47*63778faaSEtienne Carriere }; 48*63778faaSEtienne Carriere 49*63778faaSEtienne Carriere /* 50*63778faaSEtienne Carriere * struct ae_aes_context - Extra context data got AE operations 51*63778faaSEtienne Carriere * @tag_byte_len - Tag size in byte 52*63778faaSEtienne Carriere * @pending_tag - Input data that could be the appended tag 53*63778faaSEtienne Carriere * @pending_size - Size of pending input data that could be the tag 54*63778faaSEtienne Carriere * @out_data - Pointer to an array of output data references. 55*63778faaSEtienne Carriere * @out_count - Number of buffer references in out_data 56*63778faaSEtienne Carriere */ 57*63778faaSEtienne Carriere struct ae_aes_context { 58*63778faaSEtienne Carriere size_t tag_byte_len; 59*63778faaSEtienne Carriere char *pending_tag; 60*63778faaSEtienne Carriere size_t pending_size; 61*63778faaSEtienne Carriere struct out_data_ref *out_data; 62*63778faaSEtienne Carriere size_t out_count; 63*63778faaSEtienne Carriere }; 64*63778faaSEtienne Carriere 65*63778faaSEtienne Carriere static enum pkcs11_rc init_ae_aes_context(struct ae_aes_context *ctx) 66*63778faaSEtienne Carriere { 67*63778faaSEtienne Carriere struct out_data_ref *out_data = NULL; 68*63778faaSEtienne Carriere char *pending_tag = NULL; 69*63778faaSEtienne Carriere 70*63778faaSEtienne Carriere assert(!ctx->out_data && !ctx->out_count && 71*63778faaSEtienne Carriere !ctx->pending_tag && !ctx->pending_size); 72*63778faaSEtienne Carriere 73*63778faaSEtienne Carriere out_data = TEE_Malloc(sizeof(*out_data), TEE_MALLOC_FILL_ZERO); 74*63778faaSEtienne Carriere pending_tag = TEE_Malloc(ctx->tag_byte_len, TEE_MALLOC_FILL_ZERO); 75*63778faaSEtienne Carriere 76*63778faaSEtienne Carriere if (!out_data || !pending_tag) { 77*63778faaSEtienne Carriere TEE_Free(out_data); 78*63778faaSEtienne Carriere TEE_Free(pending_tag); 79*63778faaSEtienne Carriere return PKCS11_CKR_DEVICE_MEMORY; 80*63778faaSEtienne Carriere } 81*63778faaSEtienne Carriere 82*63778faaSEtienne Carriere ctx->pending_tag = pending_tag; 83*63778faaSEtienne Carriere ctx->out_data = out_data; 84*63778faaSEtienne Carriere 85*63778faaSEtienne Carriere return PKCS11_CKR_OK; 86*63778faaSEtienne Carriere } 87*63778faaSEtienne Carriere 88*63778faaSEtienne Carriere static void release_ae_aes_context(struct ae_aes_context *ctx) 89*63778faaSEtienne Carriere { 90*63778faaSEtienne Carriere size_t n = 0; 91*63778faaSEtienne Carriere 92*63778faaSEtienne Carriere for (n = 0; n < ctx->out_count; n++) 93*63778faaSEtienne Carriere TEE_Free(ctx->out_data[n].data); 94*63778faaSEtienne Carriere 95*63778faaSEtienne Carriere TEE_Free(ctx->out_data); 96*63778faaSEtienne Carriere ctx->out_data = NULL; 97*63778faaSEtienne Carriere ctx->out_count = 0; 98*63778faaSEtienne Carriere 99*63778faaSEtienne Carriere TEE_Free(ctx->pending_tag); 100*63778faaSEtienne Carriere ctx->pending_tag = NULL; 101*63778faaSEtienne Carriere ctx->pending_size = 0; 102*63778faaSEtienne Carriere } 103*63778faaSEtienne Carriere 104*63778faaSEtienne Carriere /* 105*63778faaSEtienne Carriere * This function feeds the AE decryption processing with client 106*63778faaSEtienne Carriere * input data. There are 2 constraints to consider. 107*63778faaSEtienne Carriere * 108*63778faaSEtienne Carriere * Firstly we don't know yet which are the ciphered data and which are 109*63778faaSEtienne Carriere * the tag data. GP TEE Internal API function requires we split data and 110*63778faaSEtienne Carriere * tag when TEE_AEDecryptFinal() will be called. 111*63778faaSEtienne Carriere * 112*63778faaSEtienne Carriere * Secondly any generated data must be kept in the TA and only revealed 113*63778faaSEtienne Carriere * once tag if succefully processed. 114*63778faaSEtienne Carriere */ 115*63778faaSEtienne Carriere enum pkcs11_rc tee_ae_decrypt_update(struct pkcs11_session *session, 116*63778faaSEtienne Carriere void *in, size_t in_size) 117*63778faaSEtienne Carriere { 118*63778faaSEtienne Carriere struct ae_aes_context *ctx = session->processing->extra_ctx; 119*63778faaSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 120*63778faaSEtienne Carriere enum pkcs11_rc rc = PKCS11_CKR_OK; 121*63778faaSEtienne Carriere size_t data_len = 0; 122*63778faaSEtienne Carriere size_t ct_size = 0; 123*63778faaSEtienne Carriere void *ptr = NULL; 124*63778faaSEtienne Carriere char *ct = NULL; 125*63778faaSEtienne Carriere 126*63778faaSEtienne Carriere if (!in_size) 127*63778faaSEtienne Carriere return PKCS11_CKR_OK; 128*63778faaSEtienne Carriere 129*63778faaSEtienne Carriere if (!in) 130*63778faaSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 131*63778faaSEtienne Carriere 132*63778faaSEtienne Carriere /* 133*63778faaSEtienne Carriere * Save the last input bytes in case they are the tag 134*63778faaSEtienne Carriere * bytes and not ciphered data bytes to be decrypted. 135*63778faaSEtienne Carriere */ 136*63778faaSEtienne Carriere 137*63778faaSEtienne Carriere if (ctx->pending_size + in_size <= ctx->tag_byte_len) { 138*63778faaSEtienne Carriere /* 139*63778faaSEtienne Carriere * Data bytes are all potential tag bytes. 140*63778faaSEtienne Carriere * We only need to update the pending_tag buffer, 141*63778faaSEtienne Carriere * and cannot treat any byte as data byte. 142*63778faaSEtienne Carriere */ 143*63778faaSEtienne Carriere TEE_MemMove(ctx->pending_tag + ctx->pending_size, in, in_size); 144*63778faaSEtienne Carriere 145*63778faaSEtienne Carriere ctx->pending_size += in_size; 146*63778faaSEtienne Carriere 147*63778faaSEtienne Carriere return PKCS11_CKR_OK; 148*63778faaSEtienne Carriere } 149*63778faaSEtienne Carriere 150*63778faaSEtienne Carriere /* Size of data that are not potential tag in pending and input data */ 151*63778faaSEtienne Carriere data_len = in_size + ctx->pending_size - ctx->tag_byte_len; 152*63778faaSEtienne Carriere 153*63778faaSEtienne Carriere /* Process pending bytes that are effective data byte */ 154*63778faaSEtienne Carriere if (ctx->pending_size && 155*63778faaSEtienne Carriere (ctx->pending_size + in_size) >= ctx->tag_byte_len) { 156*63778faaSEtienne Carriere uint32_t len = MIN(data_len, ctx->pending_size); 157*63778faaSEtienne Carriere 158*63778faaSEtienne Carriere res = TEE_AEUpdate(session->processing->tee_op_handle, 159*63778faaSEtienne Carriere ctx->pending_tag, len, NULL, &ct_size); 160*63778faaSEtienne Carriere if (res && res != TEE_ERROR_SHORT_BUFFER) { 161*63778faaSEtienne Carriere rc = tee2pkcs_error(res); 162*63778faaSEtienne Carriere goto out; 163*63778faaSEtienne Carriere } 164*63778faaSEtienne Carriere assert(res == TEE_ERROR_SHORT_BUFFER || !ct_size); 165*63778faaSEtienne Carriere 166*63778faaSEtienne Carriere /* 167*63778faaSEtienne Carriere * If output data to store (not revealed yet), redo with 168*63778faaSEtienne Carriere * an allocated temporary reference. 169*63778faaSEtienne Carriere */ 170*63778faaSEtienne Carriere if (ct_size) { 171*63778faaSEtienne Carriere ct = TEE_Malloc(ct_size, TEE_MALLOC_FILL_ZERO); 172*63778faaSEtienne Carriere if (!ct) { 173*63778faaSEtienne Carriere rc = PKCS11_CKR_DEVICE_MEMORY; 174*63778faaSEtienne Carriere goto out; 175*63778faaSEtienne Carriere } 176*63778faaSEtienne Carriere 177*63778faaSEtienne Carriere res = TEE_AEUpdate(session->processing->tee_op_handle, 178*63778faaSEtienne Carriere ctx->pending_tag, len, ct, &ct_size); 179*63778faaSEtienne Carriere if (res) { 180*63778faaSEtienne Carriere rc = tee2pkcs_error(res); 181*63778faaSEtienne Carriere goto out; 182*63778faaSEtienne Carriere } 183*63778faaSEtienne Carriere assert(ct_size); 184*63778faaSEtienne Carriere } 185*63778faaSEtienne Carriere 186*63778faaSEtienne Carriere /* Save potential tag bytes for later */ 187*63778faaSEtienne Carriere TEE_MemMove(ctx->pending_tag, ctx->pending_tag + len, 188*63778faaSEtienne Carriere ctx->pending_size - len); 189*63778faaSEtienne Carriere 190*63778faaSEtienne Carriere ctx->pending_size -= len; 191*63778faaSEtienne Carriere data_len -= len; 192*63778faaSEtienne Carriere } 193*63778faaSEtienne Carriere 194*63778faaSEtienne Carriere /* Process input data that are not potential tag bytes */ 195*63778faaSEtienne Carriere if (data_len) { 196*63778faaSEtienne Carriere size_t size = 0; 197*63778faaSEtienne Carriere 198*63778faaSEtienne Carriere res = TEE_AEUpdate(session->processing->tee_op_handle, 199*63778faaSEtienne Carriere in, data_len, NULL, &size); 200*63778faaSEtienne Carriere if (res != TEE_ERROR_SHORT_BUFFER && 201*63778faaSEtienne Carriere (res != TEE_SUCCESS || size)) { 202*63778faaSEtienne Carriere /* This is not expected */ 203*63778faaSEtienne Carriere rc = PKCS11_CKR_GENERAL_ERROR; 204*63778faaSEtienne Carriere goto out; 205*63778faaSEtienne Carriere } 206*63778faaSEtienne Carriere 207*63778faaSEtienne Carriere if (size) { 208*63778faaSEtienne Carriere ptr = TEE_Realloc(ct, ct_size + size); 209*63778faaSEtienne Carriere if (!ptr) { 210*63778faaSEtienne Carriere rc = PKCS11_CKR_DEVICE_MEMORY; 211*63778faaSEtienne Carriere goto out; 212*63778faaSEtienne Carriere } 213*63778faaSEtienne Carriere ct = ptr; 214*63778faaSEtienne Carriere 215*63778faaSEtienne Carriere res = TEE_AEUpdate(session->processing->tee_op_handle, 216*63778faaSEtienne Carriere in, data_len, ct + ct_size, &size); 217*63778faaSEtienne Carriere if (res) { 218*63778faaSEtienne Carriere rc = tee2pkcs_error(res); 219*63778faaSEtienne Carriere goto out; 220*63778faaSEtienne Carriere } 221*63778faaSEtienne Carriere 222*63778faaSEtienne Carriere ct_size += size; 223*63778faaSEtienne Carriere } 224*63778faaSEtienne Carriere } 225*63778faaSEtienne Carriere 226*63778faaSEtienne Carriere /* Update pending tag in context if any */ 227*63778faaSEtienne Carriere data_len = in_size - data_len; 228*63778faaSEtienne Carriere if (data_len > (ctx->tag_byte_len - ctx->pending_size)) { 229*63778faaSEtienne Carriere /* This is not expected */ 230*63778faaSEtienne Carriere rc = PKCS11_CKR_GENERAL_ERROR; 231*63778faaSEtienne Carriere goto out; 232*63778faaSEtienne Carriere } 233*63778faaSEtienne Carriere 234*63778faaSEtienne Carriere if (data_len) { 235*63778faaSEtienne Carriere TEE_MemMove(ctx->pending_tag + ctx->pending_size, 236*63778faaSEtienne Carriere (char *)in + in_size - data_len, data_len); 237*63778faaSEtienne Carriere 238*63778faaSEtienne Carriere ctx->pending_size += data_len; 239*63778faaSEtienne Carriere } 240*63778faaSEtienne Carriere 241*63778faaSEtienne Carriere /* Save output data reference in the context */ 242*63778faaSEtienne Carriere if (ct_size) { 243*63778faaSEtienne Carriere ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) * 244*63778faaSEtienne Carriere sizeof(struct out_data_ref)); 245*63778faaSEtienne Carriere if (!ptr) { 246*63778faaSEtienne Carriere rc = PKCS11_CKR_DEVICE_MEMORY; 247*63778faaSEtienne Carriere goto out; 248*63778faaSEtienne Carriere } 249*63778faaSEtienne Carriere ctx->out_data = ptr; 250*63778faaSEtienne Carriere ctx->out_data[ctx->out_count].size = ct_size; 251*63778faaSEtienne Carriere ctx->out_data[ctx->out_count].data = ct; 252*63778faaSEtienne Carriere ctx->out_count++; 253*63778faaSEtienne Carriere } 254*63778faaSEtienne Carriere 255*63778faaSEtienne Carriere rc = PKCS11_CKR_OK; 256*63778faaSEtienne Carriere 257*63778faaSEtienne Carriere out: 258*63778faaSEtienne Carriere if (rc) 259*63778faaSEtienne Carriere TEE_Free(ct); 260*63778faaSEtienne Carriere 261*63778faaSEtienne Carriere return rc; 262*63778faaSEtienne Carriere } 263*63778faaSEtienne Carriere 264*63778faaSEtienne Carriere static enum pkcs11_rc reveal_ae_data(struct ae_aes_context *ctx, 265*63778faaSEtienne Carriere void *out, size_t *out_size) 266*63778faaSEtienne Carriere { 267*63778faaSEtienne Carriere uint32_t req_size = 0; 268*63778faaSEtienne Carriere char *out_ptr = out; 269*63778faaSEtienne Carriere size_t n = 0; 270*63778faaSEtienne Carriere 271*63778faaSEtienne Carriere for (req_size = 0, n = 0; n < ctx->out_count; n++) 272*63778faaSEtienne Carriere req_size += ctx->out_data[n].size; 273*63778faaSEtienne Carriere 274*63778faaSEtienne Carriere if (*out_size < req_size) { 275*63778faaSEtienne Carriere *out_size = req_size; 276*63778faaSEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL; 277*63778faaSEtienne Carriere } 278*63778faaSEtienne Carriere 279*63778faaSEtienne Carriere if (!out_ptr) 280*63778faaSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 281*63778faaSEtienne Carriere 282*63778faaSEtienne Carriere for (n = 0; n < ctx->out_count; n++) { 283*63778faaSEtienne Carriere TEE_MemMove(out_ptr, ctx->out_data[n].data, 284*63778faaSEtienne Carriere ctx->out_data[n].size); 285*63778faaSEtienne Carriere out_ptr += ctx->out_data[n].size; 286*63778faaSEtienne Carriere } 287*63778faaSEtienne Carriere 288*63778faaSEtienne Carriere release_ae_aes_context(ctx); 289*63778faaSEtienne Carriere 290*63778faaSEtienne Carriere *out_size = req_size; 291*63778faaSEtienne Carriere 292*63778faaSEtienne Carriere return PKCS11_CKR_OK; 293*63778faaSEtienne Carriere } 294*63778faaSEtienne Carriere 295*63778faaSEtienne Carriere enum pkcs11_rc tee_ae_decrypt_final(struct pkcs11_session *session, 296*63778faaSEtienne Carriere void *out, size_t *out_size) 297*63778faaSEtienne Carriere { 298*63778faaSEtienne Carriere struct ae_aes_context *ctx = session->processing->extra_ctx; 299*63778faaSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 300*63778faaSEtienne Carriere enum pkcs11_rc rc = 0; 301*63778faaSEtienne Carriere void *data_ptr = NULL; 302*63778faaSEtienne Carriere size_t data_size = 0; 303*63778faaSEtienne Carriere 304*63778faaSEtienne Carriere if (!out_size) { 305*63778faaSEtienne Carriere DMSG("Expect at least a buffer for the output data"); 306*63778faaSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 307*63778faaSEtienne Carriere } 308*63778faaSEtienne Carriere 309*63778faaSEtienne Carriere /* Final is already completed, only need to output the data */ 310*63778faaSEtienne Carriere if (!ctx->pending_tag) 311*63778faaSEtienne Carriere return reveal_ae_data(ctx, out, out_size); 312*63778faaSEtienne Carriere 313*63778faaSEtienne Carriere if (ctx->pending_size != ctx->tag_byte_len) { 314*63778faaSEtienne Carriere DMSG("Not enough samples: %zu/%zu", 315*63778faaSEtienne Carriere ctx->pending_size, ctx->tag_byte_len); 316*63778faaSEtienne Carriere return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE; 317*63778faaSEtienne Carriere } 318*63778faaSEtienne Carriere 319*63778faaSEtienne Carriere /* Query tag size if any */ 320*63778faaSEtienne Carriere data_size = 0; 321*63778faaSEtienne Carriere res = TEE_AEDecryptFinal(session->processing->tee_op_handle, 322*63778faaSEtienne Carriere NULL, 0, NULL, &data_size, 323*63778faaSEtienne Carriere ctx->pending_tag, ctx->tag_byte_len); 324*63778faaSEtienne Carriere 325*63778faaSEtienne Carriere if (res == TEE_ERROR_SHORT_BUFFER) { 326*63778faaSEtienne Carriere data_ptr = TEE_Malloc(data_size, TEE_MALLOC_FILL_ZERO); 327*63778faaSEtienne Carriere if (!data_ptr) { 328*63778faaSEtienne Carriere rc = PKCS11_CKR_DEVICE_MEMORY; 329*63778faaSEtienne Carriere goto out; 330*63778faaSEtienne Carriere } 331*63778faaSEtienne Carriere 332*63778faaSEtienne Carriere res = TEE_AEDecryptFinal(session->processing->tee_op_handle, 333*63778faaSEtienne Carriere NULL, 0, data_ptr, &data_size, 334*63778faaSEtienne Carriere ctx->pending_tag, ctx->tag_byte_len); 335*63778faaSEtienne Carriere assert(res || data_size); 336*63778faaSEtienne Carriere } 337*63778faaSEtienne Carriere 338*63778faaSEtienne Carriere /* AE decryption is completed */ 339*63778faaSEtienne Carriere TEE_Free(ctx->pending_tag); 340*63778faaSEtienne Carriere ctx->pending_tag = NULL; 341*63778faaSEtienne Carriere 342*63778faaSEtienne Carriere rc = tee2pkcs_error(res); 343*63778faaSEtienne Carriere if (rc) 344*63778faaSEtienne Carriere goto out; 345*63778faaSEtienne Carriere 346*63778faaSEtienne Carriere if (data_ptr) { 347*63778faaSEtienne Carriere void *tmp_ptr = NULL; 348*63778faaSEtienne Carriere 349*63778faaSEtienne Carriere tmp_ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) * 350*63778faaSEtienne Carriere sizeof(struct out_data_ref)); 351*63778faaSEtienne Carriere if (!tmp_ptr) { 352*63778faaSEtienne Carriere rc = PKCS11_CKR_DEVICE_MEMORY; 353*63778faaSEtienne Carriere goto out; 354*63778faaSEtienne Carriere } 355*63778faaSEtienne Carriere ctx->out_data = tmp_ptr; 356*63778faaSEtienne Carriere ctx->out_data[ctx->out_count].size = data_size; 357*63778faaSEtienne Carriere ctx->out_data[ctx->out_count].data = data_ptr; 358*63778faaSEtienne Carriere ctx->out_count++; 359*63778faaSEtienne Carriere 360*63778faaSEtienne Carriere data_ptr = NULL; 361*63778faaSEtienne Carriere } 362*63778faaSEtienne Carriere 363*63778faaSEtienne Carriere rc = reveal_ae_data(ctx, out, out_size); 364*63778faaSEtienne Carriere 365*63778faaSEtienne Carriere out: 366*63778faaSEtienne Carriere TEE_Free(data_ptr); 367*63778faaSEtienne Carriere 368*63778faaSEtienne Carriere return rc; 369*63778faaSEtienne Carriere } 370*63778faaSEtienne Carriere 371*63778faaSEtienne Carriere enum pkcs11_rc tee_ae_encrypt_final(struct pkcs11_session *session, 372*63778faaSEtienne Carriere void *out, size_t *out_size) 373*63778faaSEtienne Carriere { 374*63778faaSEtienne Carriere struct ae_aes_context *ctx = session->processing->extra_ctx; 375*63778faaSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC; 376*63778faaSEtienne Carriere uint8_t *tag = NULL; 377*63778faaSEtienne Carriere size_t tag_len = 0; 378*63778faaSEtienne Carriere size_t size = 0; 379*63778faaSEtienne Carriere 380*63778faaSEtienne Carriere if (!out || !out_size) 381*63778faaSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 382*63778faaSEtienne Carriere 383*63778faaSEtienne Carriere /* Check the required sizes (warning: 2 output len: data + tag) */ 384*63778faaSEtienne Carriere res = TEE_AEEncryptFinal(session->processing->tee_op_handle, 385*63778faaSEtienne Carriere NULL, 0, NULL, &size, 386*63778faaSEtienne Carriere &tag, &tag_len); 387*63778faaSEtienne Carriere 388*63778faaSEtienne Carriere if (tag_len != ctx->tag_byte_len || 389*63778faaSEtienne Carriere (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)) { 390*63778faaSEtienne Carriere EMSG("Unexpected tag length %zu/%zu or rc 0x%" PRIx32, 391*63778faaSEtienne Carriere tag_len, ctx->tag_byte_len, res); 392*63778faaSEtienne Carriere return PKCS11_CKR_GENERAL_ERROR; 393*63778faaSEtienne Carriere } 394*63778faaSEtienne Carriere 395*63778faaSEtienne Carriere if (*out_size < size + tag_len) { 396*63778faaSEtienne Carriere *out_size = size + tag_len; 397*63778faaSEtienne Carriere return PKCS11_CKR_BUFFER_TOO_SMALL; 398*63778faaSEtienne Carriere } 399*63778faaSEtienne Carriere 400*63778faaSEtienne Carriere /* Process data and tag input the client output buffer */ 401*63778faaSEtienne Carriere tag = (uint8_t *)out + size; 402*63778faaSEtienne Carriere 403*63778faaSEtienne Carriere res = TEE_AEEncryptFinal(session->processing->tee_op_handle, 404*63778faaSEtienne Carriere NULL, 0, out, &size, tag, &tag_len); 405*63778faaSEtienne Carriere 406*63778faaSEtienne Carriere if (tag_len != ctx->tag_byte_len) { 407*63778faaSEtienne Carriere EMSG("Unexpected tag length"); 408*63778faaSEtienne Carriere return PKCS11_CKR_GENERAL_ERROR; 409*63778faaSEtienne Carriere } 410*63778faaSEtienne Carriere 411*63778faaSEtienne Carriere if (!res) 412*63778faaSEtienne Carriere *out_size = size + tag_len; 413*63778faaSEtienne Carriere 414*63778faaSEtienne Carriere return tee2pkcs_error(res); 415*63778faaSEtienne Carriere } 416*63778faaSEtienne Carriere 417512cbf1dSJens Wiklander enum pkcs11_rc tee_init_ctr_operation(struct active_processing *processing, 418512cbf1dSJens Wiklander void *proc_params, size_t params_size) 419512cbf1dSJens Wiklander { 420512cbf1dSJens Wiklander struct serialargs args = { }; 421512cbf1dSJens Wiklander enum pkcs11_rc rc = PKCS11_CKR_OK; 422512cbf1dSJens Wiklander /* CTR parameters */ 423512cbf1dSJens Wiklander uint32_t incr_counter = 0; 424512cbf1dSJens Wiklander void *counter_bits = NULL; 425512cbf1dSJens Wiklander 426512cbf1dSJens Wiklander if (!proc_params) 427512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 428512cbf1dSJens Wiklander 429512cbf1dSJens Wiklander serialargs_init(&args, proc_params, params_size); 430512cbf1dSJens Wiklander 431512cbf1dSJens Wiklander rc = serialargs_get(&args, &incr_counter, sizeof(uint32_t)); 432512cbf1dSJens Wiklander if (rc) 433512cbf1dSJens Wiklander return rc; 434512cbf1dSJens Wiklander 435512cbf1dSJens Wiklander rc = serialargs_get_ptr(&args, &counter_bits, 16); 436512cbf1dSJens Wiklander if (rc) 437512cbf1dSJens Wiklander return rc; 438512cbf1dSJens Wiklander 439512cbf1dSJens Wiklander if (serialargs_remaining_bytes(&args)) 440512cbf1dSJens Wiklander return PKCS11_CKR_ARGUMENTS_BAD; 441512cbf1dSJens Wiklander 442512cbf1dSJens Wiklander if (incr_counter != 1) { 443512cbf1dSJens Wiklander DMSG("Supports only 1 bit increment counter: %"PRIu32, 444512cbf1dSJens Wiklander incr_counter); 445512cbf1dSJens Wiklander 446512cbf1dSJens Wiklander return PKCS11_CKR_MECHANISM_PARAM_INVALID; 447512cbf1dSJens Wiklander } 448512cbf1dSJens Wiklander 449512cbf1dSJens Wiklander TEE_CipherInit(processing->tee_op_handle, counter_bits, 16); 450512cbf1dSJens Wiklander 451512cbf1dSJens Wiklander return PKCS11_CKR_OK; 452512cbf1dSJens Wiklander } 453*63778faaSEtienne Carriere 454*63778faaSEtienne Carriere enum pkcs11_rc tee_init_gcm_operation(struct pkcs11_session *session, 455*63778faaSEtienne Carriere void *proc_params, size_t params_size) 456*63778faaSEtienne Carriere { 457*63778faaSEtienne Carriere struct ae_aes_context *params = NULL; 458*63778faaSEtienne Carriere enum pkcs11_rc rc = PKCS11_CKR_OK; 459*63778faaSEtienne Carriere struct serialargs args = { }; 460*63778faaSEtienne Carriere /* GCM parameters */ 461*63778faaSEtienne Carriere uint32_t tag_bitlen = 0; 462*63778faaSEtienne Carriere uint32_t tag_len = 0; 463*63778faaSEtienne Carriere uint32_t iv_len = 0; 464*63778faaSEtienne Carriere void *iv = NULL; 465*63778faaSEtienne Carriere uint32_t aad_len = 0; 466*63778faaSEtienne Carriere void *aad = NULL; 467*63778faaSEtienne Carriere 468*63778faaSEtienne Carriere TEE_MemFill(&args, 0, sizeof(args)); 469*63778faaSEtienne Carriere 470*63778faaSEtienne Carriere if (!proc_params) 471*63778faaSEtienne Carriere return PKCS11_CKR_ARGUMENTS_BAD; 472*63778faaSEtienne Carriere 473*63778faaSEtienne Carriere serialargs_init(&args, proc_params, params_size); 474*63778faaSEtienne Carriere 475*63778faaSEtienne Carriere rc = serialargs_get(&args, &iv_len, sizeof(uint32_t)); 476*63778faaSEtienne Carriere if (rc) 477*63778faaSEtienne Carriere goto out; 478*63778faaSEtienne Carriere 479*63778faaSEtienne Carriere rc = serialargs_get_ptr(&args, &iv, iv_len); 480*63778faaSEtienne Carriere if (rc) 481*63778faaSEtienne Carriere goto out; 482*63778faaSEtienne Carriere 483*63778faaSEtienne Carriere rc = serialargs_get(&args, &aad_len, sizeof(uint32_t)); 484*63778faaSEtienne Carriere if (rc) 485*63778faaSEtienne Carriere goto out; 486*63778faaSEtienne Carriere 487*63778faaSEtienne Carriere rc = serialargs_get_ptr(&args, &aad, aad_len); 488*63778faaSEtienne Carriere if (rc) 489*63778faaSEtienne Carriere goto out; 490*63778faaSEtienne Carriere 491*63778faaSEtienne Carriere rc = serialargs_get(&args, &tag_bitlen, sizeof(uint32_t)); 492*63778faaSEtienne Carriere if (rc) 493*63778faaSEtienne Carriere goto out; 494*63778faaSEtienne Carriere 495*63778faaSEtienne Carriere tag_len = ROUNDUP(tag_bitlen, 8) / 8; 496*63778faaSEtienne Carriere 497*63778faaSEtienne Carriere /* As per pkcs#11 mechanism specification */ 498*63778faaSEtienne Carriere if (tag_bitlen > 128 || !iv_len || iv_len > 256) { 499*63778faaSEtienne Carriere DMSG("Invalid parameters: tag_bit_len %"PRIu32 500*63778faaSEtienne Carriere ", iv_len %"PRIu32, tag_bitlen, iv_len); 501*63778faaSEtienne Carriere rc = PKCS11_CKR_MECHANISM_PARAM_INVALID; 502*63778faaSEtienne Carriere goto out; 503*63778faaSEtienne Carriere } 504*63778faaSEtienne Carriere 505*63778faaSEtienne Carriere params = TEE_Malloc(sizeof(*params), TEE_MALLOC_FILL_ZERO); 506*63778faaSEtienne Carriere if (!params) { 507*63778faaSEtienne Carriere rc = PKCS11_CKR_DEVICE_MEMORY; 508*63778faaSEtienne Carriere goto out; 509*63778faaSEtienne Carriere } 510*63778faaSEtienne Carriere 511*63778faaSEtienne Carriere /* Store the byte round up byte length for the tag */ 512*63778faaSEtienne Carriere params->tag_byte_len = tag_len; 513*63778faaSEtienne Carriere rc = init_ae_aes_context(params); 514*63778faaSEtienne Carriere if (rc) 515*63778faaSEtienne Carriere goto out; 516*63778faaSEtienne Carriere 517*63778faaSEtienne Carriere /* Session processing owns the active processing params */ 518*63778faaSEtienne Carriere assert(!session->processing->extra_ctx); 519*63778faaSEtienne Carriere session->processing->extra_ctx = params; 520*63778faaSEtienne Carriere 521*63778faaSEtienne Carriere TEE_AEInit(session->processing->tee_op_handle, 522*63778faaSEtienne Carriere iv, iv_len, tag_bitlen, 0, 0); 523*63778faaSEtienne Carriere 524*63778faaSEtienne Carriere if (aad_len) 525*63778faaSEtienne Carriere TEE_AEUpdateAAD(session->processing->tee_op_handle, 526*63778faaSEtienne Carriere aad, aad_len); 527*63778faaSEtienne Carriere 528*63778faaSEtienne Carriere /* 529*63778faaSEtienne Carriere * Save initialized operation state to reset to this state 530*63778faaSEtienne Carriere * on one-shot AE request that queries its output buffer size. 531*63778faaSEtienne Carriere */ 532*63778faaSEtienne Carriere TEE_CopyOperation(session->processing->tee_op_handle2, 533*63778faaSEtienne Carriere session->processing->tee_op_handle); 534*63778faaSEtienne Carriere 535*63778faaSEtienne Carriere rc = PKCS11_CKR_OK; 536*63778faaSEtienne Carriere 537*63778faaSEtienne Carriere out: 538*63778faaSEtienne Carriere if (rc && params) { 539*63778faaSEtienne Carriere release_ae_aes_context(params); 540*63778faaSEtienne Carriere TEE_Free(params); 541*63778faaSEtienne Carriere } 542*63778faaSEtienne Carriere 543*63778faaSEtienne Carriere return rc; 544*63778faaSEtienne Carriere } 545*63778faaSEtienne Carriere 546*63778faaSEtienne Carriere /* Release extra resources related to the GCM processing*/ 547*63778faaSEtienne Carriere void tee_release_gcm_operation(struct pkcs11_session *session) 548*63778faaSEtienne Carriere { 549*63778faaSEtienne Carriere struct ae_aes_context *ctx = session->processing->extra_ctx; 550*63778faaSEtienne Carriere 551*63778faaSEtienne Carriere release_ae_aes_context(ctx); 552*63778faaSEtienne Carriere TEE_Free(session->processing->extra_ctx); 553*63778faaSEtienne Carriere session->processing->extra_ctx = NULL; 554*63778faaSEtienne Carriere } 555*63778faaSEtienne Carriere 556*63778faaSEtienne Carriere /* Reset processing state to the state it was after initialization */ 557*63778faaSEtienne Carriere enum pkcs11_rc tee_ae_reinit_gcm_operation(struct pkcs11_session *session) 558*63778faaSEtienne Carriere { 559*63778faaSEtienne Carriere struct ae_aes_context *ctx = session->processing->extra_ctx; 560*63778faaSEtienne Carriere 561*63778faaSEtienne Carriere TEE_CopyOperation(session->processing->tee_op_handle, 562*63778faaSEtienne Carriere session->processing->tee_op_handle2); 563*63778faaSEtienne Carriere 564*63778faaSEtienne Carriere release_ae_aes_context(ctx); 565*63778faaSEtienne Carriere 566*63778faaSEtienne Carriere return init_ae_aes_context(ctx); 567*63778faaSEtienne Carriere } 568