1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 21fca7e26SJens Wiklander /* 31fca7e26SJens Wiklander * Copyright (c) 2017, Linaro Limited 41fca7e26SJens Wiklander */ 51fca7e26SJens Wiklander 661b4cd9cSJens Wiklander #include <assert.h> 71fca7e26SJens Wiklander #include <crypto/internal_aes-gcm.h> 81fca7e26SJens Wiklander #include <io.h> 91fca7e26SJens Wiklander #include <string_ext.h> 101fca7e26SJens Wiklander #include <string.h> 111fca7e26SJens Wiklander #include <tee_api_types.h> 121fca7e26SJens Wiklander #include <types_ext.h> 131fca7e26SJens Wiklander #include <utee_defines.h> 141fca7e26SJens Wiklander #include <util.h> 151fca7e26SJens Wiklander 16b8c186b5SJens Wiklander #include "aes-gcm-private.h" 17b8c186b5SJens Wiklander 181fca7e26SJens Wiklander static void xor_buf(uint8_t *dst, const uint8_t *src, size_t len) 191fca7e26SJens Wiklander { 201fca7e26SJens Wiklander size_t n; 211fca7e26SJens Wiklander 221fca7e26SJens Wiklander for (n = 0; n < len; n++) 231fca7e26SJens Wiklander dst[n] ^= src[n]; 241fca7e26SJens Wiklander } 251fca7e26SJens Wiklander 261fca7e26SJens Wiklander 2754af8d67SJens Wiklander static void ghash_update_pad_zero(struct internal_aes_gcm_state *state, 281fca7e26SJens Wiklander const uint8_t *data, size_t len) 291fca7e26SJens Wiklander { 301fca7e26SJens Wiklander size_t n = len / TEE_AES_BLOCK_SIZE; 311fca7e26SJens Wiklander uint64_t block[2]; 321fca7e26SJens Wiklander 331fca7e26SJens Wiklander if (n) { 34b8c186b5SJens Wiklander if (internal_aes_gcm_ptr_is_block_aligned(data)) { 3554af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, NULL, data, n); 361fca7e26SJens Wiklander } else { 371fca7e26SJens Wiklander size_t m; 381fca7e26SJens Wiklander 391fca7e26SJens Wiklander for (m = 0; m < n; m++) { 401fca7e26SJens Wiklander 411fca7e26SJens Wiklander memcpy(block, data + m * sizeof(block), 421fca7e26SJens Wiklander sizeof(block)); 4354af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, NULL, 441fca7e26SJens Wiklander (void *)block, 1); 451fca7e26SJens Wiklander } 461fca7e26SJens Wiklander } 471fca7e26SJens Wiklander } 481fca7e26SJens Wiklander 491fca7e26SJens Wiklander if (len - n * TEE_AES_BLOCK_SIZE) { 501fca7e26SJens Wiklander memset(block, 0, sizeof(block)); 511fca7e26SJens Wiklander memcpy(block, data + n * TEE_AES_BLOCK_SIZE, 521fca7e26SJens Wiklander len - n * TEE_AES_BLOCK_SIZE); 5354af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, block, NULL, 0); 541fca7e26SJens Wiklander } 551fca7e26SJens Wiklander } 561fca7e26SJens Wiklander 5754af8d67SJens Wiklander static void ghash_update_lengths(struct internal_aes_gcm_state *state, 5854af8d67SJens Wiklander uint32_t l1, uint32_t l2) 591fca7e26SJens Wiklander { 601fca7e26SJens Wiklander uint64_t len_fields[2] = { 611fca7e26SJens Wiklander TEE_U64_TO_BIG_ENDIAN(l1 * 8), 621fca7e26SJens Wiklander TEE_U64_TO_BIG_ENDIAN(l2 * 8) 631fca7e26SJens Wiklander }; 641fca7e26SJens Wiklander 651fca7e26SJens Wiklander COMPILE_TIME_ASSERT(sizeof(len_fields) == TEE_AES_BLOCK_SIZE); 6654af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, (uint8_t *)len_fields, NULL, 0); 671fca7e26SJens Wiklander } 681fca7e26SJens Wiklander 6954af8d67SJens Wiklander static TEE_Result __gcm_init(struct internal_aes_gcm_state *state, 7054af8d67SJens Wiklander const struct internal_aes_gcm_key *ek, 7154af8d67SJens Wiklander TEE_OperationMode mode, const void *nonce, 721fca7e26SJens Wiklander size_t nonce_len, size_t tag_len) 731fca7e26SJens Wiklander { 7454af8d67SJens Wiklander COMPILE_TIME_ASSERT(sizeof(state->ctr) == TEE_AES_BLOCK_SIZE); 751fca7e26SJens Wiklander 7654af8d67SJens Wiklander if (tag_len > sizeof(state->buf_tag)) 771fca7e26SJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 781fca7e26SJens Wiklander 7954af8d67SJens Wiklander memset(state, 0, sizeof(*state)); 801fca7e26SJens Wiklander 8154af8d67SJens Wiklander state->tag_len = tag_len; 8254af8d67SJens Wiklander internal_aes_gcm_set_key(state, ek); 831fca7e26SJens Wiklander 841fca7e26SJens Wiklander if (nonce_len == (96 / 8)) { 8554af8d67SJens Wiklander memcpy(state->ctr, nonce, nonce_len); 8654af8d67SJens Wiklander internal_aes_gcm_inc_ctr(state); 871fca7e26SJens Wiklander } else { 8854af8d67SJens Wiklander ghash_update_pad_zero(state, nonce, nonce_len); 8954af8d67SJens Wiklander ghash_update_lengths(state, 0, nonce_len); 901fca7e26SJens Wiklander 9154af8d67SJens Wiklander memcpy(state->ctr, state->hash_state, sizeof(state->ctr)); 9254af8d67SJens Wiklander memset(state->hash_state, 0, sizeof(state->hash_state)); 931fca7e26SJens Wiklander } 941fca7e26SJens Wiklander 9554af8d67SJens Wiklander internal_aes_gcm_encrypt_block(ek, state->ctr, state->buf_tag); 9654af8d67SJens Wiklander internal_aes_gcm_inc_ctr(state); 971fca7e26SJens Wiklander if (mode == TEE_MODE_ENCRYPT) { 981fca7e26SJens Wiklander /* 991fca7e26SJens Wiklander * Encryption uses the pre-encrypted xor-buffer to encrypt 1001fca7e26SJens Wiklander * while decryption encrypts the xor-buffer when needed 1011fca7e26SJens Wiklander * instead. 1021fca7e26SJens Wiklander * 1031fca7e26SJens Wiklander * The reason for this is that the combined encryption and 1041fca7e26SJens Wiklander * ghash implementation does both operations intertwined. 1051fca7e26SJens Wiklander * In the decrypt case the xor-buffer is needed at the end 1061fca7e26SJens Wiklander * of processing each block, while the encryption case 1071fca7e26SJens Wiklander * needs xor-buffer before processing each block. 1081fca7e26SJens Wiklander * 1091fca7e26SJens Wiklander * In a pure software implementation we wouldn't have any 1101fca7e26SJens Wiklander * use for this kind of optimization, but since this 1111fca7e26SJens Wiklander * AES-GCM implementation is aimed at being combined with 1121fca7e26SJens Wiklander * accelerated routines it's more convenient to always have 1131fca7e26SJens Wiklander * this optimization activated. 1141fca7e26SJens Wiklander */ 11554af8d67SJens Wiklander internal_aes_gcm_encrypt_block(ek, state->ctr, state->buf_cryp); 11654af8d67SJens Wiklander internal_aes_gcm_inc_ctr(state); 1171fca7e26SJens Wiklander } 1181fca7e26SJens Wiklander 1191fca7e26SJens Wiklander return TEE_SUCCESS; 1201fca7e26SJens Wiklander } 1211fca7e26SJens Wiklander 12254af8d67SJens Wiklander TEE_Result internal_aes_gcm_init(struct internal_aes_gcm_ctx *ctx, 12354af8d67SJens Wiklander TEE_OperationMode mode, const void *key, 12454af8d67SJens Wiklander size_t key_len, const void *nonce, 12554af8d67SJens Wiklander size_t nonce_len, size_t tag_len) 12654af8d67SJens Wiklander { 12754af8d67SJens Wiklander TEE_Result res = internal_aes_gcm_expand_enc_key(key, key_len, 12854af8d67SJens Wiklander &ctx->key); 12954af8d67SJens Wiklander if (res) 13054af8d67SJens Wiklander return res; 13154af8d67SJens Wiklander 13254af8d67SJens Wiklander return __gcm_init(&ctx->state, &ctx->key, mode, nonce, nonce_len, 13354af8d67SJens Wiklander tag_len); 13454af8d67SJens Wiklander } 13554af8d67SJens Wiklander 136043411e5SJens Wiklander static TEE_Result __gcm_update_aad(struct internal_aes_gcm_state *state, 1371fca7e26SJens Wiklander const void *data, size_t len) 1381fca7e26SJens Wiklander { 1391fca7e26SJens Wiklander const uint8_t *d = data; 1401fca7e26SJens Wiklander size_t l = len; 1411fca7e26SJens Wiklander const uint8_t *head = NULL; 1421fca7e26SJens Wiklander size_t n; 1431fca7e26SJens Wiklander 14454af8d67SJens Wiklander if (state->payload_bytes) 1451fca7e26SJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 1461fca7e26SJens Wiklander 14754af8d67SJens Wiklander state->aad_bytes += len; 1481fca7e26SJens Wiklander 1491fca7e26SJens Wiklander while (l) { 15054af8d67SJens Wiklander if (state->buf_pos || 15154af8d67SJens Wiklander !internal_aes_gcm_ptr_is_block_aligned(d) || 1521fca7e26SJens Wiklander l < TEE_AES_BLOCK_SIZE) { 15354af8d67SJens Wiklander n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l); 15454af8d67SJens Wiklander memcpy(state->buf_hash + state->buf_pos, d, n); 15554af8d67SJens Wiklander state->buf_pos += n; 1561fca7e26SJens Wiklander 15754af8d67SJens Wiklander if (state->buf_pos != TEE_AES_BLOCK_SIZE) 1581fca7e26SJens Wiklander return TEE_SUCCESS; 1591fca7e26SJens Wiklander 16054af8d67SJens Wiklander state->buf_pos = 0; 16154af8d67SJens Wiklander head = state->buf_hash; 1621fca7e26SJens Wiklander d += n; 1631fca7e26SJens Wiklander l -= n; 1641fca7e26SJens Wiklander } 1651fca7e26SJens Wiklander 166b8c186b5SJens Wiklander if (internal_aes_gcm_ptr_is_block_aligned(d)) 1671fca7e26SJens Wiklander n = l / TEE_AES_BLOCK_SIZE; 1681fca7e26SJens Wiklander else 1691fca7e26SJens Wiklander n = 0; 1701fca7e26SJens Wiklander 17154af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, head, d, n); 1721fca7e26SJens Wiklander l -= n * TEE_AES_BLOCK_SIZE; 1731fca7e26SJens Wiklander d += n * TEE_AES_BLOCK_SIZE; 1741fca7e26SJens Wiklander } 1751fca7e26SJens Wiklander 1761fca7e26SJens Wiklander return TEE_SUCCESS; 1771fca7e26SJens Wiklander } 1781fca7e26SJens Wiklander 179043411e5SJens Wiklander TEE_Result internal_aes_gcm_update_aad(struct internal_aes_gcm_ctx *ctx, 180043411e5SJens Wiklander const void *data, size_t len) 1811fca7e26SJens Wiklander { 182043411e5SJens Wiklander return __gcm_update_aad(&ctx->state, data, len); 183043411e5SJens Wiklander } 184043411e5SJens Wiklander 185043411e5SJens Wiklander static TEE_Result 186043411e5SJens Wiklander __gcm_update_payload(struct internal_aes_gcm_state *state, 187043411e5SJens Wiklander const struct internal_aes_gcm_key *ek, 188043411e5SJens Wiklander TEE_OperationMode mode, const void *src, 189043411e5SJens Wiklander size_t len, void *dst) 190043411e5SJens Wiklander { 1911fca7e26SJens Wiklander size_t n; 1921fca7e26SJens Wiklander const uint8_t *s = src; 1931fca7e26SJens Wiklander uint8_t *d = dst; 1941fca7e26SJens Wiklander size_t l = len; 1951fca7e26SJens Wiklander 19654af8d67SJens Wiklander if (!state->payload_bytes && state->buf_pos) { 1971fca7e26SJens Wiklander /* AAD part done, finish up the last bits. */ 19854af8d67SJens Wiklander memset(state->buf_hash + state->buf_pos, 0, 19954af8d67SJens Wiklander TEE_AES_BLOCK_SIZE - state->buf_pos); 20054af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0); 20154af8d67SJens Wiklander state->buf_pos = 0; 2021fca7e26SJens Wiklander } 2031fca7e26SJens Wiklander 20454af8d67SJens Wiklander state->payload_bytes += len; 2051fca7e26SJens Wiklander 2061fca7e26SJens Wiklander while (l) { 20754af8d67SJens Wiklander if (state->buf_pos || 20854af8d67SJens Wiklander !internal_aes_gcm_ptr_is_block_aligned(s) || 209b8c186b5SJens Wiklander !internal_aes_gcm_ptr_is_block_aligned(d) || 210b8c186b5SJens Wiklander l < TEE_AES_BLOCK_SIZE) { 21154af8d67SJens Wiklander n = MIN(TEE_AES_BLOCK_SIZE - state->buf_pos, l); 2121fca7e26SJens Wiklander 21354af8d67SJens Wiklander if (!state->buf_pos && mode == TEE_MODE_DECRYPT) { 21454af8d67SJens Wiklander internal_aes_gcm_encrypt_block(ek, state->ctr, 21554af8d67SJens Wiklander state->buf_cryp); 2161fca7e26SJens Wiklander } 2171fca7e26SJens Wiklander 21854af8d67SJens Wiklander xor_buf(state->buf_cryp + state->buf_pos, s, n); 21954af8d67SJens Wiklander memcpy(d, state->buf_cryp + state->buf_pos, n); 2201fca7e26SJens Wiklander if (mode == TEE_MODE_ENCRYPT) 22154af8d67SJens Wiklander memcpy(state->buf_hash + state->buf_pos, 22254af8d67SJens Wiklander state->buf_cryp + state->buf_pos, n); 2231fca7e26SJens Wiklander else 22454af8d67SJens Wiklander memcpy(state->buf_hash + state->buf_pos, s, n); 2251fca7e26SJens Wiklander 22654af8d67SJens Wiklander state->buf_pos += n; 2271fca7e26SJens Wiklander 22854af8d67SJens Wiklander if (state->buf_pos != TEE_AES_BLOCK_SIZE) 2291fca7e26SJens Wiklander return TEE_SUCCESS; 2301fca7e26SJens Wiklander 23154af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, state->buf_hash, 2321fca7e26SJens Wiklander NULL, 0); 23354af8d67SJens Wiklander state->buf_pos = 0; 2341fca7e26SJens Wiklander d += n; 2351fca7e26SJens Wiklander s += n; 2361fca7e26SJens Wiklander l -= n; 2371fca7e26SJens Wiklander 2381fca7e26SJens Wiklander if (mode == TEE_MODE_ENCRYPT) 23954af8d67SJens Wiklander internal_aes_gcm_encrypt_block(ek, state->ctr, 24054af8d67SJens Wiklander state->buf_cryp); 24154af8d67SJens Wiklander internal_aes_gcm_inc_ctr(state); 2421fca7e26SJens Wiklander } else { 2431fca7e26SJens Wiklander n = l / TEE_AES_BLOCK_SIZE; 24454af8d67SJens Wiklander internal_aes_gcm_update_payload_block_aligned(state, ek, 24554af8d67SJens Wiklander mode, 2461fca7e26SJens Wiklander s, n, d); 2471fca7e26SJens Wiklander s += n * TEE_AES_BLOCK_SIZE; 2481fca7e26SJens Wiklander d += n * TEE_AES_BLOCK_SIZE; 2491fca7e26SJens Wiklander l -= n * TEE_AES_BLOCK_SIZE; 2501fca7e26SJens Wiklander } 2511fca7e26SJens Wiklander } 2521fca7e26SJens Wiklander 2531fca7e26SJens Wiklander return TEE_SUCCESS; 2541fca7e26SJens Wiklander } 2551fca7e26SJens Wiklander 256043411e5SJens Wiklander TEE_Result internal_aes_gcm_update_payload(struct internal_aes_gcm_ctx *ctx, 257043411e5SJens Wiklander TEE_OperationMode mode, 258043411e5SJens Wiklander const void *src, size_t len, 259043411e5SJens Wiklander void *dst) 260043411e5SJens Wiklander { 261043411e5SJens Wiklander return __gcm_update_payload(&ctx->state, &ctx->key, mode, src, len, 262043411e5SJens Wiklander dst); 263043411e5SJens Wiklander } 264043411e5SJens Wiklander 265043411e5SJens Wiklander static TEE_Result operation_final(struct internal_aes_gcm_state *state, 266043411e5SJens Wiklander const struct internal_aes_gcm_key *enc_key, 2671fca7e26SJens Wiklander TEE_OperationMode m, const uint8_t *src, 2681fca7e26SJens Wiklander size_t len, uint8_t *dst) 2691fca7e26SJens Wiklander { 2701fca7e26SJens Wiklander TEE_Result res; 2711fca7e26SJens Wiklander 272043411e5SJens Wiklander res = __gcm_update_payload(state, enc_key, m, src, len, dst); 2731fca7e26SJens Wiklander if (res) 2741fca7e26SJens Wiklander return res; 2751fca7e26SJens Wiklander 27654af8d67SJens Wiklander if (state->buf_pos) { 27754af8d67SJens Wiklander memset(state->buf_hash + state->buf_pos, 0, 27854af8d67SJens Wiklander sizeof(state->buf_hash) - state->buf_pos); 27954af8d67SJens Wiklander internal_aes_gcm_ghash_update(state, state->buf_hash, NULL, 0); 2801fca7e26SJens Wiklander } 2811fca7e26SJens Wiklander 28254af8d67SJens Wiklander ghash_update_lengths(state, state->aad_bytes, state->payload_bytes); 2831fca7e26SJens Wiklander /* buf_tag was filled in with the first counter block aes_gcm_init() */ 28454af8d67SJens Wiklander xor_buf(state->buf_tag, state->hash_state, state->tag_len); 2851fca7e26SJens Wiklander 2861fca7e26SJens Wiklander return TEE_SUCCESS; 2871fca7e26SJens Wiklander } 2881fca7e26SJens Wiklander 289043411e5SJens Wiklander static TEE_Result __gcm_enc_final(struct internal_aes_gcm_state *state, 290043411e5SJens Wiklander const struct internal_aes_gcm_key *enc_key, 2911fca7e26SJens Wiklander const void *src, size_t len, void *dst, 2921fca7e26SJens Wiklander void *tag, size_t *tag_len) 2931fca7e26SJens Wiklander { 2941fca7e26SJens Wiklander TEE_Result res; 2951fca7e26SJens Wiklander 29654af8d67SJens Wiklander if (*tag_len < state->tag_len) 2971fca7e26SJens Wiklander return TEE_ERROR_SHORT_BUFFER; 2981fca7e26SJens Wiklander 299043411e5SJens Wiklander res = operation_final(state, enc_key, TEE_MODE_ENCRYPT, src, len, dst); 3001fca7e26SJens Wiklander if (res) 3011fca7e26SJens Wiklander return res; 3021fca7e26SJens Wiklander 30354af8d67SJens Wiklander memcpy(tag, state->buf_tag, state->tag_len); 30454af8d67SJens Wiklander *tag_len = state->tag_len; 3051fca7e26SJens Wiklander 3061fca7e26SJens Wiklander return TEE_SUCCESS; 3071fca7e26SJens Wiklander } 3081fca7e26SJens Wiklander 309043411e5SJens Wiklander TEE_Result internal_aes_gcm_enc_final(struct internal_aes_gcm_ctx *ctx, 310043411e5SJens Wiklander const void *src, size_t len, void *dst, 311043411e5SJens Wiklander void *tag, size_t *tag_len) 312043411e5SJens Wiklander { 313043411e5SJens Wiklander return __gcm_enc_final(&ctx->state, &ctx->key, src, len, dst, tag, 314043411e5SJens Wiklander tag_len); 315043411e5SJens Wiklander } 316043411e5SJens Wiklander 317043411e5SJens Wiklander static TEE_Result __gcm_dec_final(struct internal_aes_gcm_state *state, 318043411e5SJens Wiklander const struct internal_aes_gcm_key *enc_key, 3191fca7e26SJens Wiklander const void *src, size_t len, void *dst, 3201fca7e26SJens Wiklander const void *tag, size_t tag_len) 3211fca7e26SJens Wiklander { 3221fca7e26SJens Wiklander TEE_Result res; 3231fca7e26SJens Wiklander 32454af8d67SJens Wiklander if (tag_len != state->tag_len) 3251fca7e26SJens Wiklander return TEE_ERROR_MAC_INVALID; 3261fca7e26SJens Wiklander 327043411e5SJens Wiklander res = operation_final(state, enc_key, TEE_MODE_DECRYPT, src, len, dst); 3281fca7e26SJens Wiklander if (res) 3291fca7e26SJens Wiklander return res; 3301fca7e26SJens Wiklander 331*48e10604SJerome Forissier if (consttime_memcmp(state->buf_tag, tag, tag_len)) 3321fca7e26SJens Wiklander return TEE_ERROR_MAC_INVALID; 3331fca7e26SJens Wiklander 3341fca7e26SJens Wiklander return TEE_SUCCESS; 3351fca7e26SJens Wiklander } 3361fca7e26SJens Wiklander 337043411e5SJens Wiklander TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx, 338043411e5SJens Wiklander const void *src, size_t len, void *dst, 339043411e5SJens Wiklander const void *tag, size_t tag_len) 340043411e5SJens Wiklander { 341043411e5SJens Wiklander return __gcm_dec_final(&ctx->state, &ctx->key, src, len, dst, tag, 342043411e5SJens Wiklander tag_len); 343043411e5SJens Wiklander } 344043411e5SJens Wiklander 34554af8d67SJens Wiklander void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state) 3461fca7e26SJens Wiklander { 3471fca7e26SJens Wiklander uint64_t c; 3481fca7e26SJens Wiklander 34954af8d67SJens Wiklander c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]) + 1; 35054af8d67SJens Wiklander state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c); 3511fca7e26SJens Wiklander if (!c) { 35254af8d67SJens Wiklander c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[0]) + 1; 35354af8d67SJens Wiklander state->ctr[0] = TEE_U64_TO_BIG_ENDIAN(c); 3541fca7e26SJens Wiklander } 3551fca7e26SJens Wiklander } 3561fca7e26SJens Wiklander 357043411e5SJens Wiklander TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key, 358043411e5SJens Wiklander const void *nonce, size_t nonce_len, 359043411e5SJens Wiklander const void *aad, size_t aad_len, 360043411e5SJens Wiklander const void *src, size_t len, void *dst, 361043411e5SJens Wiklander void *tag, size_t *tag_len) 362043411e5SJens Wiklander { 363043411e5SJens Wiklander TEE_Result res; 364043411e5SJens Wiklander struct internal_aes_gcm_state state; 365043411e5SJens Wiklander 366043411e5SJens Wiklander res = __gcm_init(&state, enc_key, TEE_MODE_ENCRYPT, nonce, nonce_len, 367043411e5SJens Wiklander *tag_len); 368043411e5SJens Wiklander if (res) 369043411e5SJens Wiklander return res; 370043411e5SJens Wiklander 371043411e5SJens Wiklander if (aad) { 372043411e5SJens Wiklander res = __gcm_update_aad(&state, aad, aad_len); 373043411e5SJens Wiklander if (res) 374043411e5SJens Wiklander return res; 375043411e5SJens Wiklander } 376043411e5SJens Wiklander 377043411e5SJens Wiklander return __gcm_enc_final(&state, enc_key, src, len, dst, tag, tag_len); 378043411e5SJens Wiklander } 379043411e5SJens Wiklander 380043411e5SJens Wiklander TEE_Result internal_aes_gcm_dec(const struct internal_aes_gcm_key *enc_key, 381043411e5SJens Wiklander const void *nonce, size_t nonce_len, 382043411e5SJens Wiklander const void *aad, size_t aad_len, 383043411e5SJens Wiklander const void *src, size_t len, void *dst, 384043411e5SJens Wiklander const void *tag, size_t tag_len) 385043411e5SJens Wiklander { 386043411e5SJens Wiklander TEE_Result res; 387043411e5SJens Wiklander struct internal_aes_gcm_state state; 388043411e5SJens Wiklander 389043411e5SJens Wiklander res = __gcm_init(&state, enc_key, TEE_MODE_DECRYPT, nonce, nonce_len, 390043411e5SJens Wiklander tag_len); 391043411e5SJens Wiklander if (res) 392043411e5SJens Wiklander return res; 393043411e5SJens Wiklander 394043411e5SJens Wiklander if (aad) { 395043411e5SJens Wiklander res = __gcm_update_aad(&state, aad, aad_len); 396043411e5SJens Wiklander if (res) 397043411e5SJens Wiklander return res; 398043411e5SJens Wiklander } 399043411e5SJens Wiklander 400043411e5SJens Wiklander return __gcm_dec_final(&state, enc_key, src, len, dst, tag, tag_len); 401043411e5SJens Wiklander } 402043411e5SJens Wiklander 403043411e5SJens Wiklander 4041fca7e26SJens Wiklander #ifndef CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB 4051fca7e26SJens Wiklander #include <crypto/aes-gcm.h> 406d7ac7d0fSJens Wiklander #include <stdlib.h> 4071fca7e26SJens Wiklander 408d7ac7d0fSJens Wiklander TEE_Result crypto_aes_gcm_alloc_ctx(void **ctx_ret) 4091fca7e26SJens Wiklander { 410d7ac7d0fSJens Wiklander struct internal_aes_gcm_ctx *ctx = calloc(1, sizeof(*ctx)); 411d7ac7d0fSJens Wiklander 412d7ac7d0fSJens Wiklander if (!ctx) 413d7ac7d0fSJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 414d7ac7d0fSJens Wiklander 415d7ac7d0fSJens Wiklander *ctx_ret = ctx; 416d7ac7d0fSJens Wiklander return TEE_SUCCESS; 417d7ac7d0fSJens Wiklander } 418d7ac7d0fSJens Wiklander 419d7ac7d0fSJens Wiklander void crypto_aes_gcm_free_ctx(void *ctx) 420d7ac7d0fSJens Wiklander { 421d7ac7d0fSJens Wiklander free(ctx); 422d7ac7d0fSJens Wiklander } 423d7ac7d0fSJens Wiklander 424d7ac7d0fSJens Wiklander void crypto_aes_gcm_copy_state(void *dst_ctx, void *src_ctx) 425d7ac7d0fSJens Wiklander { 426d7ac7d0fSJens Wiklander memcpy(dst_ctx, src_ctx, sizeof(struct internal_aes_gcm_ctx)); 4271fca7e26SJens Wiklander } 4281fca7e26SJens Wiklander 4291fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_init(void *c, TEE_OperationMode mode, 4301fca7e26SJens Wiklander const uint8_t *key, size_t key_len, 4311fca7e26SJens Wiklander const uint8_t *nonce, size_t nonce_len, 4321fca7e26SJens Wiklander size_t tag_len) 4331fca7e26SJens Wiklander { 4341fca7e26SJens Wiklander return internal_aes_gcm_init(c, mode, key, key_len, nonce, nonce_len, 4351fca7e26SJens Wiklander tag_len); 4361fca7e26SJens Wiklander } 4371fca7e26SJens Wiklander 4381fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_update_aad(void *c, const uint8_t *data, size_t len) 4391fca7e26SJens Wiklander { 4401fca7e26SJens Wiklander return internal_aes_gcm_update_aad(c, data, len); 4411fca7e26SJens Wiklander } 4421fca7e26SJens Wiklander 4431fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_update_payload(void *c, TEE_OperationMode m, 4441fca7e26SJens Wiklander const uint8_t *src, size_t len, 4451fca7e26SJens Wiklander uint8_t *dst) 4461fca7e26SJens Wiklander { 4471fca7e26SJens Wiklander return internal_aes_gcm_update_payload(c, m, src, len, dst); 4481fca7e26SJens Wiklander } 4491fca7e26SJens Wiklander 4501fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_enc_final(void *c, const uint8_t *src, size_t len, 4511fca7e26SJens Wiklander uint8_t *dst, uint8_t *tag, size_t *tag_len) 4521fca7e26SJens Wiklander { 4531fca7e26SJens Wiklander return internal_aes_gcm_enc_final(c, src, len, dst, tag, tag_len); 4541fca7e26SJens Wiklander } 4551fca7e26SJens Wiklander 4561fca7e26SJens Wiklander TEE_Result crypto_aes_gcm_dec_final(void *c, const uint8_t *src, size_t len, 4571fca7e26SJens Wiklander uint8_t *dst, const uint8_t *tag, 4581fca7e26SJens Wiklander size_t tag_len) 4591fca7e26SJens Wiklander { 4601fca7e26SJens Wiklander return internal_aes_gcm_dec_final(c, src, len, dst, tag, tag_len); 4611fca7e26SJens Wiklander } 4621fca7e26SJens Wiklander 4631fca7e26SJens Wiklander void crypto_aes_gcm_final(void *c __unused) 4641fca7e26SJens Wiklander { 4651fca7e26SJens Wiklander } 4661fca7e26SJens Wiklander #endif /*!CFG_CRYPTO_AES_GCM_FROM_CRYPTOLIB*/ 467