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