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