1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014-2019, Linaro Limited
4 */
5
6 #include <assert.h>
7 #include <crypto/crypto.h>
8 #include <crypto/crypto_impl.h>
9 #include <stdlib.h>
10 #include <string_ext.h>
11 #include <string.h>
12 #include <tee_api_types.h>
13 #include <tomcrypt_private.h>
14 #include <util.h>
15
16 #define TEE_GCM_TAG_MAX_LENGTH 16
17
18 struct tee_gcm_state {
19 struct crypto_authenc_ctx aectx;
20 gcm_state ctx; /* the gcm state as defined by LTC */
21 size_t tag_len; /* tag length */
22 };
23
24 static const struct crypto_authenc_ops aes_gcm_ops;
25
to_tee_gcm_state(struct crypto_authenc_ctx * aectx)26 static struct tee_gcm_state *to_tee_gcm_state(struct crypto_authenc_ctx *aectx)
27 {
28 assert(aectx && aectx->ops == &aes_gcm_ops);
29
30 return container_of(aectx, struct tee_gcm_state, aectx);
31 }
32
crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx ** ctx_ret)33 TEE_Result crypto_aes_gcm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret)
34 {
35 struct tee_gcm_state *ctx = calloc(1, sizeof(*ctx));
36
37 if (!ctx)
38 return TEE_ERROR_OUT_OF_MEMORY;
39 ctx->aectx.ops = &aes_gcm_ops;
40
41 *ctx_ret = &ctx->aectx;
42
43 return TEE_SUCCESS;
44 }
45
crypto_aes_gcm_free_ctx(struct crypto_authenc_ctx * aectx)46 static void crypto_aes_gcm_free_ctx(struct crypto_authenc_ctx *aectx)
47 {
48 free(to_tee_gcm_state(aectx));
49 }
50
crypto_aes_gcm_copy_state(struct crypto_authenc_ctx * dst_aectx,struct crypto_authenc_ctx * src_aectx)51 static void crypto_aes_gcm_copy_state(struct crypto_authenc_ctx *dst_aectx,
52 struct crypto_authenc_ctx *src_aectx)
53 {
54 struct tee_gcm_state *dst_ctx = to_tee_gcm_state(dst_aectx);
55 struct tee_gcm_state *src_ctx = to_tee_gcm_state(src_aectx);
56
57 dst_ctx->ctx = src_ctx->ctx;
58 dst_ctx->tag_len = src_ctx->tag_len;
59 }
60
crypto_aes_gcm_init(struct crypto_authenc_ctx * aectx,TEE_OperationMode mode __unused,const uint8_t * key,size_t key_len,const uint8_t * nonce,size_t nonce_len,size_t tag_len,size_t aad_len __unused,size_t payload_len __unused)61 static TEE_Result crypto_aes_gcm_init(struct crypto_authenc_ctx *aectx,
62 TEE_OperationMode mode __unused,
63 const uint8_t *key, size_t key_len,
64 const uint8_t *nonce, size_t nonce_len,
65 size_t tag_len, size_t aad_len __unused,
66 size_t payload_len __unused)
67 {
68 int ltc_res = 0;
69 int ltc_cipherindex = find_cipher("aes");
70 struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
71
72 if (ltc_cipherindex < 0)
73 return TEE_ERROR_NOT_SUPPORTED;
74
75 /* reset the state */
76 memset(&gcm->ctx, 0, sizeof(gcm->ctx));
77 gcm->tag_len = tag_len;
78
79 ltc_res = gcm_init(&gcm->ctx, ltc_cipherindex, key, key_len);
80 if (ltc_res != CRYPT_OK)
81 return TEE_ERROR_BAD_STATE;
82
83 /* Add the IV */
84 ltc_res = gcm_add_iv(&gcm->ctx, nonce, nonce_len);
85 if (ltc_res != CRYPT_OK)
86 return TEE_ERROR_BAD_STATE;
87
88 return TEE_SUCCESS;
89 }
90
crypto_aes_gcm_update_aad(struct crypto_authenc_ctx * aectx,const uint8_t * data,size_t len)91 static TEE_Result crypto_aes_gcm_update_aad(struct crypto_authenc_ctx *aectx,
92 const uint8_t *data, size_t len)
93 {
94 struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
95 int ltc_res = 0;
96
97 /* Add the AAD (note: aad can be NULL if aadlen == 0) */
98 ltc_res = gcm_add_aad(&gcm->ctx, data, len);
99 if (ltc_res != CRYPT_OK)
100 return TEE_ERROR_BAD_STATE;
101
102 return TEE_SUCCESS;
103 }
104
105 static TEE_Result
crypto_aes_gcm_update_payload(struct crypto_authenc_ctx * aectx,TEE_OperationMode mode,const uint8_t * src_data,size_t len,uint8_t * dst_data)106 crypto_aes_gcm_update_payload(struct crypto_authenc_ctx *aectx,
107 TEE_OperationMode mode, const uint8_t *src_data,
108 size_t len, uint8_t *dst_data)
109 {
110 TEE_Result res = TEE_SUCCESS;
111 int ltc_res = 0;
112 int dir = 0;
113 struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
114 unsigned char *pt = NULL;
115 unsigned char *ct = NULL;
116
117 if (mode == TEE_MODE_ENCRYPT) {
118 pt = (unsigned char *)src_data;
119 ct = dst_data;
120 dir = GCM_ENCRYPT;
121 } else {
122 pt = dst_data;
123 ct = (unsigned char *)src_data;
124 dir = GCM_DECRYPT;
125 }
126
127 /* aad is optional ==> add one without length */
128 if (gcm->ctx.mode == LTC_GCM_MODE_IV) {
129 res = crypto_aes_gcm_update_aad(aectx, NULL, 0);
130 if (res != TEE_SUCCESS)
131 return res;
132 }
133
134 /* process the data */
135 ltc_res = gcm_process(&gcm->ctx, pt, len, ct, dir);
136 if (ltc_res != CRYPT_OK)
137 return TEE_ERROR_BAD_STATE;
138
139 return TEE_SUCCESS;
140 }
141
crypto_aes_gcm_enc_final(struct crypto_authenc_ctx * aectx,const uint8_t * src_data,size_t len,uint8_t * dst_data,uint8_t * dst_tag,size_t * dst_tag_len)142 static TEE_Result crypto_aes_gcm_enc_final(struct crypto_authenc_ctx *aectx,
143 const uint8_t *src_data, size_t len,
144 uint8_t *dst_data, uint8_t *dst_tag,
145 size_t *dst_tag_len)
146 {
147 TEE_Result res = TEE_SUCCESS;
148 struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
149 int ltc_res = 0;
150
151 /* Finalize the remaining buffer */
152 res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data,
153 len, dst_data);
154 if (res != TEE_SUCCESS)
155 return res;
156
157 /* Check the tag length */
158 if (*dst_tag_len < gcm->tag_len) {
159 *dst_tag_len = gcm->tag_len;
160 return TEE_ERROR_SHORT_BUFFER;
161 }
162 *dst_tag_len = gcm->tag_len;
163
164 /* Compute the tag */
165 ltc_res = gcm_done(&gcm->ctx, dst_tag, (unsigned long *)dst_tag_len);
166 if (ltc_res != CRYPT_OK)
167 return TEE_ERROR_BAD_STATE;
168
169 return TEE_SUCCESS;
170 }
171
crypto_aes_gcm_dec_final(struct crypto_authenc_ctx * aectx,const uint8_t * src_data,size_t len,uint8_t * dst_data,const uint8_t * tag,size_t tag_len)172 static TEE_Result crypto_aes_gcm_dec_final(struct crypto_authenc_ctx *aectx,
173 const uint8_t *src_data, size_t len,
174 uint8_t *dst_data,
175 const uint8_t *tag, size_t tag_len)
176 {
177 TEE_Result res = TEE_ERROR_BAD_STATE;
178 struct tee_gcm_state *gcm = to_tee_gcm_state(aectx);
179 int ltc_res = 0;
180 uint8_t dst_tag[TEE_GCM_TAG_MAX_LENGTH] = { 0 };
181 unsigned long ltc_tag_len = tag_len;
182
183 if (tag_len == 0)
184 return TEE_ERROR_SHORT_BUFFER;
185 if (tag_len > TEE_GCM_TAG_MAX_LENGTH)
186 return TEE_ERROR_BAD_STATE;
187
188 /* Process the last buffer, if any */
189 res = crypto_aes_gcm_update_payload(aectx, TEE_MODE_DECRYPT, src_data,
190 len, dst_data);
191 if (res != TEE_SUCCESS)
192 return res;
193
194 /* Finalize the authentication */
195 ltc_res = gcm_done(&gcm->ctx, dst_tag, <c_tag_len);
196 if (ltc_res != CRYPT_OK)
197 return TEE_ERROR_BAD_STATE;
198
199 if (consttime_memcmp(dst_tag, tag, tag_len) != 0)
200 res = TEE_ERROR_MAC_INVALID;
201 else
202 res = TEE_SUCCESS;
203 return res;
204 }
205
crypto_aes_gcm_final(struct crypto_authenc_ctx * aectx)206 static void crypto_aes_gcm_final(struct crypto_authenc_ctx *aectx)
207 {
208 gcm_reset(&to_tee_gcm_state(aectx)->ctx);
209 }
210
211 static const struct crypto_authenc_ops aes_gcm_ops = {
212 .init = crypto_aes_gcm_init,
213 .update_aad = crypto_aes_gcm_update_aad,
214 .update_payload = crypto_aes_gcm_update_payload,
215 .enc_final = crypto_aes_gcm_enc_final,
216 .dec_final = crypto_aes_gcm_dec_final,
217 .final = crypto_aes_gcm_final,
218 .free_ctx = crypto_aes_gcm_free_ctx,
219 .copy_state = crypto_aes_gcm_copy_state,
220 };
221