xref: /optee_os/core/crypto/aes-gcm-sw.c (revision 11fa71b9ddb429088f325cfda430183003ccd1db)
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 
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 
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 
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 	for (n = 0; n < num_blocks; n++)
47 		ghash_update_block(state,
48 				   (uint8_t *)data + n * TEE_AES_BLOCK_SIZE);
49 }
50 
51 static void encrypt_block(struct internal_aes_gcm_state *state,
52 			  const struct internal_aes_gcm_key *enc_key,
53 			  const uint64_t src[2], uint64_t dst[2])
54 {
55 	void *buf_cryp = state->buf_cryp;
56 
57 	internal_aes_gcm_xor_block(buf_cryp, src);
58 	internal_aes_gcm_ghash_update(state, buf_cryp, NULL, 0);
59 	memcpy(dst, buf_cryp, sizeof(state->buf_cryp));
60 
61 	crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data),
62 			     enc_key->rounds, state->ctr, state->buf_cryp);
63 	internal_aes_gcm_inc_ctr(state);
64 }
65 
66 static void encrypt_pl(struct internal_aes_gcm_state *state,
67 		       const struct internal_aes_gcm_key *ek,
68 		       const uint8_t *src, size_t num_blocks, uint8_t *dst)
69 {
70 	size_t n = 0;
71 
72 	if (ALIGNMENT_IS_OK(src, uint64_t)) {
73 		for (n = 0; n < num_blocks; n++) {
74 			const void *s = src + n * TEE_AES_BLOCK_SIZE;
75 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
76 
77 			encrypt_block(state, ek, s, d);
78 		}
79 	} else {
80 		for (n = 0; n < num_blocks; n++) {
81 			uint64_t tmp[2] = { 0 };
82 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
83 
84 			memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp));
85 			encrypt_block(state, ek, tmp, d);
86 		}
87 	}
88 }
89 
90 static void decrypt_block(struct internal_aes_gcm_state *state,
91 			  const struct internal_aes_gcm_key *enc_key,
92 			  const uint64_t src[2], uint64_t dst[2])
93 {
94 	void *buf_cryp = state->buf_cryp;
95 
96 	crypto_aes_enc_block(enc_key->data, sizeof(enc_key->data),
97 			     enc_key->rounds, state->ctr, buf_cryp);
98 	internal_aes_gcm_inc_ctr(state);
99 
100 	internal_aes_gcm_xor_block(buf_cryp, src);
101 	internal_aes_gcm_ghash_update(state, src, NULL, 0);
102 	memcpy(dst, buf_cryp, sizeof(state->buf_cryp));
103 }
104 
105 static void decrypt_pl(struct internal_aes_gcm_state *state,
106 		       const struct internal_aes_gcm_key *ek,
107 		       const uint8_t *src, size_t num_blocks, uint8_t *dst)
108 {
109 	size_t n = 0;
110 
111 	if (ALIGNMENT_IS_OK(src, uint64_t)) {
112 		for (n = 0; n < num_blocks; n++) {
113 			const void *s = src + n * TEE_AES_BLOCK_SIZE;
114 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
115 
116 			decrypt_block(state, ek, s, d);
117 		}
118 	} else {
119 		for (n = 0; n < num_blocks; n++) {
120 			uint64_t tmp[2] = { 0 };
121 			void *d = dst + n * TEE_AES_BLOCK_SIZE;
122 
123 			memcpy(tmp, src + n * TEE_AES_BLOCK_SIZE, sizeof(tmp));
124 			decrypt_block(state, ek, tmp, d);
125 		}
126 	}
127 }
128 
129 void
130 internal_aes_gcm_update_payload_blocks(struct internal_aes_gcm_state *state,
131 				       const struct internal_aes_gcm_key *ek,
132 				       TEE_OperationMode m, const void *src,
133 				       size_t num_blocks, void *dst)
134 {
135 	assert(!state->buf_pos && num_blocks);
136 
137 	if (m == TEE_MODE_ENCRYPT)
138 		encrypt_pl(state, ek, src, num_blocks, dst);
139 	else
140 		decrypt_pl(state, ek, src, num_blocks, dst);
141 }
142