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
internal_aes_gcm_set_key(struct internal_aes_gcm_state * state,const struct internal_aes_gcm_key * ek)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
ghash_update_block(struct internal_aes_gcm_state * state,const void * data)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
internal_aes_gcm_ghash_update(struct internal_aes_gcm_state * state,const void * head,const void * data,size_t num_blocks)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
46b2b27623SSander Visser if (data)
47b8c186b5SJens Wiklander for (n = 0; n < num_blocks; n++)
48b314df1fSJens Wiklander ghash_update_block(state,
49b2b27623SSander Visser (const uint8_t *)data +
50b2b27623SSander Visser n * TEE_AES_BLOCK_SIZE);
51b8c186b5SJens Wiklander }
5280f47278SJens Wiklander
encrypt_block(struct internal_aes_gcm_state * state,const struct internal_aes_gcm_key * enc_key,const uint64_t src[2],uint64_t dst[2])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
encrypt_pl(struct internal_aes_gcm_state * state,const struct internal_aes_gcm_key * ek,const uint8_t * src,size_t num_blocks,uint8_t * dst)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
74*be501eb1SJorge Ramirez-Ortiz if (IS_ALIGNED_WITH_TYPE(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
decrypt_block(struct internal_aes_gcm_state * state,const struct internal_aes_gcm_key * enc_key,const uint64_t src[2],uint64_t dst[2])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
decrypt_pl(struct internal_aes_gcm_state * state,const struct internal_aes_gcm_key * ek,const uint8_t * src,size_t num_blocks,uint8_t * dst)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
113*be501eb1SJorge Ramirez-Ortiz if (IS_ALIGNED_WITH_TYPE(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
internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state * state,const struct internal_aes_gcm_key * ek,TEE_OperationMode m,const void * src,size_t num_blocks,void * dst)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