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