1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 21fca7e26SJens Wiklander /* 3b314df1fSJens Wiklander * Copyright (c) 2017-2020, Linaro Limited 41fca7e26SJens Wiklander */ 51fca7e26SJens Wiklander 661b4cd9cSJens Wiklander #include <assert.h> 761b4cd9cSJens Wiklander #include <crypto/crypto.h> 81fca7e26SJens Wiklander #include <crypto/internal_aes-gcm.h> 91fca7e26SJens Wiklander #include <string.h> 101fca7e26SJens Wiklander #include <tee_api_types.h> 111fca7e26SJens Wiklander #include <types_ext.h> 121fca7e26SJens Wiklander 13b314df1fSJens Wiklander void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state, 1454af8d67SJens Wiklander const struct internal_aes_gcm_key *ek) 151fca7e26SJens Wiklander { 16b8c186b5SJens Wiklander #ifdef CFG_AES_GCM_TABLE_BASED 17b314df1fSJens Wiklander internal_aes_gcm_ghash_gen_tbl(&state->ghash_key, ek); 18b8c186b5SJens Wiklander #else 194f6d7160SJens Wiklander crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds, 204f6d7160SJens Wiklander state->ctr, state->ghash_key.hash_subkey); 21b8c186b5SJens Wiklander #endif 221fca7e26SJens Wiklander } 231fca7e26SJens Wiklander 24b314df1fSJens Wiklander static void ghash_update_block(struct internal_aes_gcm_state *state, 25b314df1fSJens Wiklander const void *data) 26b314df1fSJens Wiklander { 27b314df1fSJens Wiklander void *y = state->hash_state; 28b314df1fSJens Wiklander 29b314df1fSJens Wiklander internal_aes_gcm_xor_block(y, data); 30b314df1fSJens Wiklander #ifdef CFG_AES_GCM_TABLE_BASED 31b314df1fSJens Wiklander internal_aes_gcm_ghash_mult_tbl(&state->ghash_key, y, y); 32b314df1fSJens Wiklander #else 33b314df1fSJens Wiklander internal_aes_gcm_gfmul(state->ghash_key.hash_subkey, y, y); 34b314df1fSJens Wiklander #endif 35b314df1fSJens Wiklander } 36b314df1fSJens Wiklander 37b314df1fSJens Wiklander void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state, 38b8c186b5SJens Wiklander const void *head, const void *data, 39b8c186b5SJens Wiklander size_t num_blocks) 40b8c186b5SJens Wiklander { 41b314df1fSJens Wiklander size_t n = 0; 42b8c186b5SJens Wiklander 43b8c186b5SJens Wiklander if (head) 44b314df1fSJens Wiklander ghash_update_block(state, head); 45b8c186b5SJens Wiklander 46*b2b27623SSander Visser if (data) 47b8c186b5SJens Wiklander for (n = 0; n < num_blocks; n++) 48b314df1fSJens Wiklander ghash_update_block(state, 49*b2b27623SSander Visser (const uint8_t *)data + 50*b2b27623SSander Visser n * TEE_AES_BLOCK_SIZE); 51b8c186b5SJens Wiklander } 5280f47278SJens Wiklander 5380f47278SJens Wiklander static void encrypt_block(struct internal_aes_gcm_state *state, 5480f47278SJens Wiklander const struct internal_aes_gcm_key *enc_key, 5580f47278SJens Wiklander const uint64_t src[2], uint64_t dst[2]) 5680f47278SJens Wiklander { 5780f47278SJens Wiklander void *buf_cryp = state->buf_cryp; 5880f47278SJens Wiklander 5980f47278SJens Wiklander internal_aes_gcm_xor_block(buf_cryp, src); 6080f47278SJens Wiklander internal_aes_gcm_ghash_update(state, buf_cryp, NULL, 0); 6180f47278SJens Wiklander memcpy(dst, buf_cryp, sizeof(state->buf_cryp)); 6280f47278SJens Wiklander 6380f47278SJens Wiklander crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), 6480f47278SJens Wiklander enc_key->rounds, state->ctr, state->buf_cryp); 6580f47278SJens Wiklander internal_aes_gcm_inc_ctr(state); 6680f47278SJens Wiklander } 6780f47278SJens Wiklander 6880f47278SJens Wiklander static void encrypt_pl(struct internal_aes_gcm_state *state, 6980f47278SJens Wiklander const struct internal_aes_gcm_key *ek, 7080f47278SJens Wiklander const uint8_t *src, size_t num_blocks, uint8_t *dst) 7180f47278SJens Wiklander { 7280f47278SJens Wiklander size_t n = 0; 7380f47278SJens Wiklander 7480f47278SJens Wiklander if (ALIGNMENT_IS_OK(src, uint64_t)) { 7580f47278SJens Wiklander for (n = 0; n < num_blocks; n++) { 7680f47278SJens Wiklander const void *s = src + n * TEE_AES_BLOCK_SIZE; 7780f47278SJens Wiklander void *d = dst + n * TEE_AES_BLOCK_SIZE; 7880f47278SJens Wiklander 7980f47278SJens Wiklander encrypt_block(state, ek, s, d); 8080f47278SJens Wiklander } 8180f47278SJens Wiklander } else { 8280f47278SJens Wiklander for (n = 0; n < num_blocks; n++) { 8380f47278SJens Wiklander uint64_t tmp[2] = { 0 }; 8480f47278SJens Wiklander void *d = dst + n * TEE_AES_BLOCK_SIZE; 8580f47278SJens Wiklander 8680f47278SJens Wiklander memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp)); 8780f47278SJens Wiklander encrypt_block(state, ek, tmp, d); 8880f47278SJens Wiklander } 8980f47278SJens Wiklander } 9080f47278SJens Wiklander } 9180f47278SJens Wiklander 9280f47278SJens Wiklander static void decrypt_block(struct internal_aes_gcm_state *state, 9380f47278SJens Wiklander const struct internal_aes_gcm_key *enc_key, 9480f47278SJens Wiklander const uint64_t src[2], uint64_t dst[2]) 9580f47278SJens Wiklander { 9680f47278SJens Wiklander void *buf_cryp = state->buf_cryp; 9780f47278SJens Wiklander 9880f47278SJens Wiklander crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data), 9980f47278SJens Wiklander enc_key->rounds, state->ctr, buf_cryp); 10080f47278SJens Wiklander internal_aes_gcm_inc_ctr(state); 10180f47278SJens Wiklander 10280f47278SJens Wiklander internal_aes_gcm_xor_block(buf_cryp, src); 10380f47278SJens Wiklander internal_aes_gcm_ghash_update(state, src, NULL, 0); 10480f47278SJens Wiklander memcpy(dst, buf_cryp, sizeof(state->buf_cryp)); 10580f47278SJens Wiklander } 10680f47278SJens Wiklander 10780f47278SJens Wiklander static void decrypt_pl(struct internal_aes_gcm_state *state, 10880f47278SJens Wiklander const struct internal_aes_gcm_key *ek, 10980f47278SJens Wiklander const uint8_t *src, size_t num_blocks, uint8_t *dst) 11080f47278SJens Wiklander { 11180f47278SJens Wiklander size_t n = 0; 11280f47278SJens Wiklander 11380f47278SJens Wiklander if (ALIGNMENT_IS_OK(src, uint64_t)) { 11480f47278SJens Wiklander for (n = 0; n < num_blocks; n++) { 11580f47278SJens Wiklander const void *s = src + n * TEE_AES_BLOCK_SIZE; 11680f47278SJens Wiklander void *d = dst + n * TEE_AES_BLOCK_SIZE; 11780f47278SJens Wiklander 11880f47278SJens Wiklander decrypt_block(state, ek, s, d); 11980f47278SJens Wiklander } 12080f47278SJens Wiklander } else { 12180f47278SJens Wiklander for (n = 0; n < num_blocks; n++) { 12280f47278SJens Wiklander uint64_t tmp[2] = { 0 }; 12380f47278SJens Wiklander void *d = dst + n * TEE_AES_BLOCK_SIZE; 12480f47278SJens Wiklander 12580f47278SJens Wiklander memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp)); 12680f47278SJens Wiklander decrypt_block(state, ek, tmp, d); 12780f47278SJens Wiklander } 12880f47278SJens Wiklander } 12980f47278SJens Wiklander } 13080f47278SJens Wiklander 13180f47278SJens Wiklander void 13280f47278SJens Wiklander internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state, 13380f47278SJens Wiklander const struct internal_aes_gcm_key *ek, 13480f47278SJens Wiklander TEE_OperationMode m, const void *src, 13580f47278SJens Wiklander size_t num_blocks, void *dst) 13680f47278SJens Wiklander { 13780f47278SJens Wiklander assert(!state->buf_pos && num_blocks); 13880f47278SJens Wiklander 13980f47278SJens Wiklander if (m == TEE_MODE_ENCRYPT) 14080f47278SJens Wiklander encrypt_pl(state, ek, src, num_blocks, dst); 14180f47278SJens Wiklander else 14280f47278SJens Wiklander decrypt_pl(state, ek, src, num_blocks, dst); 14380f47278SJens Wiklander } 144