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