1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2017-2020, Linaro Limited
4 */
5
6 #include <assert.h>
7 #include <crypto/crypto.h>
8 #include <crypto/internal_aes-gcm.h>
9 #include <string.h>
10 #include <tee_api_types.h>
11 #include <types_ext.h>
12
internal_aes_gcm_set_key(struct internal_aes_gcm_state * state,const struct internal_aes_gcm_key * ek)13 void internal_aes_gcm_set_key(struct internal_aes_gcm_state *state,
14 const struct internal_aes_gcm_key *ek)
15 {
16 #ifdef CFG_AES_GCM_TABLE_BASED
17 internal_aes_gcm_ghash_gen_tbl(&state->ghash_key, ek);
18 #else
19 crypto_aes_enc_block(ek->data, sizeof(ek->data), ek->rounds,
20 state->ctr, state->ghash_key.hash_subkey);
21 #endif
22 }
23
ghash_update_block(struct internal_aes_gcm_state * state,const void * data)24 static void ghash_update_block(struct internal_aes_gcm_state *state,
25 const void *data)
26 {
27 void *y = state->hash_state;
28
29 internal_aes_gcm_xor_block(y, data);
30 #ifdef CFG_AES_GCM_TABLE_BASED
31 internal_aes_gcm_ghash_mult_tbl(&state->ghash_key, y, y);
32 #else
33 internal_aes_gcm_gfmul(state->ghash_key.hash_subkey, y, y);
34 #endif
35 }
36
internal_aes_gcm_ghash_update(struct internal_aes_gcm_state * state,const void * head,const void * data,size_t num_blocks)37 void internal_aes_gcm_ghash_update(struct internal_aes_gcm_state *state,
38 const void *head, const void *data,
39 size_t num_blocks)
40 {
41 size_t n = 0;
42
43 if (head)
44 ghash_update_block(state, head);
45
46 if (data)
47 for (n = 0; n < num_blocks; n++)
48 ghash_update_block(state,
49 (const uint8_t *)data +
50 n * TEE_AES_BLOCK_SIZE);
51 }
52
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])53 static void encrypt_block(struct internal_aes_gcm_state *state,
54 const struct internal_aes_gcm_key *enc_key,
55 const uint64_t src[2], uint64_t dst[2])
56 {
57 void *buf_cryp = state->buf_cryp;
58
59 internal_aes_gcm_xor_block(buf_cryp, src);
60 internal_aes_gcm_ghash_update(state, buf_cryp, NULL, 0);
61 memcpy(dst, buf_cryp, sizeof(state->buf_cryp));
62
63 crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data),
64 enc_key->rounds, state->ctr, state->buf_cryp);
65 internal_aes_gcm_inc_ctr(state);
66 }
67
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)68 static void encrypt_pl(struct internal_aes_gcm_state *state,
69 const struct internal_aes_gcm_key *ek,
70 const uint8_t *src, size_t num_blocks, uint8_t *dst)
71 {
72 size_t n = 0;
73
74 if (IS_ALIGNED_WITH_TYPE(src, uint64_t)) {
75 for (n = 0; n < num_blocks; n++) {
76 const void *s = src + n * TEE_AES_BLOCK_SIZE;
77 void *d = dst + n * TEE_AES_BLOCK_SIZE;
78
79 encrypt_block(state, ek, s, d);
80 }
81 } else {
82 for (n = 0; n < num_blocks; n++) {
83 uint64_t tmp[2] = { 0 };
84 void *d = dst + n * TEE_AES_BLOCK_SIZE;
85
86 memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp));
87 encrypt_block(state, ek, tmp, d);
88 }
89 }
90 }
91
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])92 static void decrypt_block(struct internal_aes_gcm_state *state,
93 const struct internal_aes_gcm_key *enc_key,
94 const uint64_t src[2], uint64_t dst[2])
95 {
96 void *buf_cryp = state->buf_cryp;
97
98 crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data),
99 enc_key->rounds, state->ctr, buf_cryp);
100 internal_aes_gcm_inc_ctr(state);
101
102 internal_aes_gcm_xor_block(buf_cryp, src);
103 internal_aes_gcm_ghash_update(state, src, NULL, 0);
104 memcpy(dst, buf_cryp, sizeof(state->buf_cryp));
105 }
106
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)107 static void decrypt_pl(struct internal_aes_gcm_state *state,
108 const struct internal_aes_gcm_key *ek,
109 const uint8_t *src, size_t num_blocks, uint8_t *dst)
110 {
111 size_t n = 0;
112
113 if (IS_ALIGNED_WITH_TYPE(src, uint64_t)) {
114 for (n = 0; n < num_blocks; n++) {
115 const void *s = src + n * TEE_AES_BLOCK_SIZE;
116 void *d = dst + n * TEE_AES_BLOCK_SIZE;
117
118 decrypt_block(state, ek, s, d);
119 }
120 } else {
121 for (n = 0; n < num_blocks; n++) {
122 uint64_t tmp[2] = { 0 };
123 void *d = dst + n * TEE_AES_BLOCK_SIZE;
124
125 memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp));
126 decrypt_block(state, ek, tmp, d);
127 }
128 }
129 }
130
131 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)132 internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state,
133 const struct internal_aes_gcm_key *ek,
134 TEE_OperationMode m, const void *src,
135 size_t num_blocks, void *dst)
136 {
137 assert(!state->buf_pos && num_blocks);
138
139 if (m == TEE_MODE_ENCRYPT)
140 encrypt_pl(state, ek, src, num_blocks, dst);
141 else
142 decrypt_pl(state, ek, src, num_blocks, dst);
143 }
144