1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
4 *
5 * Crypto authenc interface implementation to enable HW driver.
6 */
7 #include <assert.h>
8 #include <crypto/crypto.h>
9 #include <crypto/crypto_impl.h>
10 #include <drvcrypt.h>
11 #include <drvcrypt_authenc.h>
12 #include <kernel/panic.h>
13 #include <malloc.h>
14 #include <utee_defines.h>
15 #include <util.h>
16
17 static const struct crypto_authenc_ops authenc_ops;
18
19 /*
20 * Returns the reference to the driver context
21 *
22 * @ctx Reference the API context pointer
23 */
to_authenc_ctx(struct crypto_authenc_ctx * ctx)24 static struct crypto_authenc *to_authenc_ctx(struct crypto_authenc_ctx *ctx)
25 {
26 assert(ctx && ctx->ops == &authenc_ops);
27
28 return container_of(ctx, struct crypto_authenc, authenc_ctx);
29 }
30
31 /*
32 * Free authenc context
33 *
34 * @ctx Reference the API context pointer
35 */
authenc_free_ctx(struct crypto_authenc_ctx * ctx)36 static void authenc_free_ctx(struct crypto_authenc_ctx *ctx)
37 {
38 struct crypto_authenc *authenc = to_authenc_ctx(ctx);
39
40 if (authenc->op && authenc->op->free_ctx)
41 authenc->op->free_ctx(authenc->ctx);
42
43 free(authenc);
44 }
45
46 /*
47 * Copy authenc context
48 *
49 * @dst_ctx [out] Reference the API context pointer destination
50 * @src_ctx Reference the API context pointer source
51 */
authenc_copy_state(struct crypto_authenc_ctx * dst_ctx,struct crypto_authenc_ctx * src_ctx)52 static void authenc_copy_state(struct crypto_authenc_ctx *dst_ctx,
53 struct crypto_authenc_ctx *src_ctx)
54 {
55 struct crypto_authenc *authenc_src = to_authenc_ctx(src_ctx);
56 struct crypto_authenc *authenc_dst = to_authenc_ctx(dst_ctx);
57
58 if (authenc_src->op && authenc_src->op->copy_state)
59 authenc_src->op->copy_state(authenc_dst->ctx, authenc_src->ctx);
60 }
61
62 /*
63 * Initialization of the authenc operation
64 *
65 * @ctx Reference the API context pointer
66 * @mode Operation mode
67 * @key Key
68 * @key_len Length of the key
69 * @nonce Nonce
70 * @nonce_len Length of the nonce
71 * @tag_len Length of the requested tag
72 * @aad_len Length of the associated authenticated data
73 * @payload_len Length of payload
74 */
authenc_init(struct crypto_authenc_ctx * ctx,TEE_OperationMode mode,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)75 static TEE_Result authenc_init(struct crypto_authenc_ctx *ctx,
76 TEE_OperationMode mode, const uint8_t *key,
77 size_t key_len, const uint8_t *nonce,
78 size_t nonce_len, size_t tag_len, size_t aad_len,
79 size_t payload_len)
80 {
81 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
82 struct crypto_authenc *authenc = to_authenc_ctx(ctx);
83
84 if ((!key && key_len) || (!nonce && nonce_len)) {
85 CRYPTO_TRACE("One of the key is not correct");
86 CRYPTO_TRACE("key @%p-%zu bytes", key, key_len);
87 CRYPTO_TRACE("nonce @%p-%zu bytes", nonce, nonce_len);
88 return TEE_ERROR_BAD_PARAMETERS;
89 }
90
91 if (authenc->op && authenc->op->init) {
92 struct drvcrypt_authenc_init dinit = {
93 .ctx = authenc->ctx,
94 .encrypt = (mode == TEE_MODE_ENCRYPT),
95 .key.data = (uint8_t *)key,
96 .key.length = key_len,
97 .nonce.data = (uint8_t *)nonce,
98 .nonce.length = nonce_len,
99 .tag_len = tag_len,
100 .aad_len = aad_len,
101 .payload_len = payload_len,
102 };
103
104 ret = authenc->op->init(&dinit);
105 }
106
107 CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
108 return ret;
109 }
110
111 /*
112 * Update Additional Authenticated Data part of the authenc operation
113 *
114 * @ctx Reference the API context pointer
115 * @data Data to authenticate without encrypt/decrypt (AAD)
116 * @len AAD length in bytes
117 */
authenc_update_aad(struct crypto_authenc_ctx * ctx,const uint8_t * data,size_t len)118 static TEE_Result authenc_update_aad(struct crypto_authenc_ctx *ctx,
119 const uint8_t *data, size_t len)
120 {
121 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
122 struct crypto_authenc *authenc = to_authenc_ctx(ctx);
123
124 if (!data && len) {
125 CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len);
126 return TEE_ERROR_BAD_PARAMETERS;
127 }
128
129 if (authenc->op && authenc->op->update_aad) {
130 struct drvcrypt_authenc_update_aad dupdate = {
131 .ctx = authenc->ctx,
132 .aad.data = (uint8_t *)data,
133 .aad.length = len,
134 };
135
136 ret = authenc->op->update_aad(&dupdate);
137 }
138
139 CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
140 return ret;
141 }
142
143 /*
144 * Update payload part of the authenc operation
145 *
146 * @ctx Reference the API context pointer
147 * @data Data to authenticate and encrypt/decrypt
148 * @len Length of the input data and output result
149 * @dst [out] Output data of the operation
150 */
authenc_update_payload(struct crypto_authenc_ctx * ctx,TEE_OperationMode mode,const uint8_t * data,size_t len,uint8_t * dst)151 static TEE_Result authenc_update_payload(struct crypto_authenc_ctx *ctx,
152 TEE_OperationMode mode,
153 const uint8_t *data,
154 size_t len, uint8_t *dst)
155 {
156 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
157 struct crypto_authenc *authenc = to_authenc_ctx(ctx);
158
159 if (!dst) {
160 CRYPTO_TRACE("Destination buffer error");
161 return TEE_ERROR_BAD_PARAMETERS;
162 }
163
164 if (!data && len) {
165 CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len);
166 return TEE_ERROR_BAD_PARAMETERS;
167 }
168
169 if (authenc->op && authenc->op->update_payload) {
170 struct drvcrypt_authenc_update_payload dupdate = {
171 .ctx = authenc->ctx,
172 .encrypt = (mode == TEE_MODE_ENCRYPT),
173 .src.data = (uint8_t *)data,
174 .src.length = len,
175 .dst.data = dst,
176 .dst.length = len,
177 };
178
179 ret = authenc->op->update_payload(&dupdate);
180 }
181
182 CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
183 return ret;
184 }
185
186 /*
187 * Last block for the authenc encrypt and get tag operation
188 *
189 * @ctx Reference the API context pointer
190 * @data Data to authenticate and encrypt (can be NULL)
191 * @len Length of the input data and output result (can be 0)
192 * @dst [out] Output data of the operation
193 * @tag [out] Output tag of the operation
194 * @tag_len [in/out] in: size of the dst_tag buffer
195 * out: size of the computed tag
196 */
authenc_enc_final(struct crypto_authenc_ctx * ctx,const uint8_t * data,size_t len,uint8_t * dst,uint8_t * tag,size_t * tag_len)197 static TEE_Result authenc_enc_final(struct crypto_authenc_ctx *ctx,
198 const uint8_t *data, size_t len,
199 uint8_t *dst, uint8_t *tag,
200 size_t *tag_len)
201 {
202 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
203 struct crypto_authenc *authenc = to_authenc_ctx(ctx);
204
205 if (!dst && len) {
206 CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len);
207 return TEE_ERROR_BAD_PARAMETERS;
208 }
209
210 if (!data && len) {
211 CRYPTO_TRACE("Bad input @%p-%zu bytes", data, len);
212 return TEE_ERROR_BAD_PARAMETERS;
213 }
214
215 if (authenc->op && authenc->op->enc_final) {
216 struct drvcrypt_authenc_final dfinal = {
217 .ctx = authenc->ctx,
218 .src.data = (uint8_t *)data,
219 .src.length = len,
220 .dst.data = dst,
221 .dst.length = len,
222 .tag.data = tag,
223 .tag.length = *tag_len
224 };
225
226 ret = authenc->op->enc_final(&dfinal);
227 if (ret == TEE_SUCCESS)
228 *tag_len = dfinal.tag.length;
229 }
230
231 CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
232 return ret;
233 }
234
235 /*
236 * Last block for the authenc decrypt and check tag operation
237 *
238 * @ctx Reference the API context pointer
239 * @src_data Data to authenticate and encrypt (can be NULL)
240 * @len Length of the input data and output result (can be 0)
241 * @dst [out] Output data of the operation
242 * @tag Tag to check at end of operation
243 * @tag_len Length of @tag
244 */
authenc_dec_final(struct crypto_authenc_ctx * ctx,const uint8_t * data,size_t len,uint8_t * dst,const uint8_t * tag,size_t tag_len)245 static TEE_Result authenc_dec_final(struct crypto_authenc_ctx *ctx,
246 const uint8_t *data, size_t len,
247 uint8_t *dst, const uint8_t *tag,
248 size_t tag_len)
249 {
250 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
251 struct crypto_authenc *authenc = to_authenc_ctx(ctx);
252
253 if (!dst && len) {
254 CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len);
255 return TEE_ERROR_BAD_PARAMETERS;
256 }
257
258 if (!data && len) {
259 CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len);
260 return TEE_ERROR_BAD_PARAMETERS;
261 }
262
263 if (authenc->op && authenc->op->dec_final) {
264 struct drvcrypt_authenc_final dfinal = {
265 .ctx = authenc->ctx,
266 .src.data = (uint8_t *)data,
267 .src.length = len,
268 .dst.data = dst,
269 .dst.length = len,
270 .tag.data = (uint8_t *)tag,
271 .tag.length = tag_len
272 };
273
274 ret = authenc->op->dec_final(&dfinal);
275 }
276
277 CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
278 return ret;
279 }
280
281 /*
282 * Finalize the authenc operation
283 *
284 * @ctx Reference the API context pointer
285 */
authenc_final(struct crypto_authenc_ctx * ctx)286 static void authenc_final(struct crypto_authenc_ctx *ctx)
287 {
288 struct crypto_authenc *authenc = to_authenc_ctx(ctx);
289
290 if (authenc->op && authenc->op->final)
291 authenc->op->final(authenc->ctx);
292 }
293
294 static const struct crypto_authenc_ops authenc_ops = {
295 .init = authenc_init,
296 .update_aad = authenc_update_aad,
297 .update_payload = authenc_update_payload,
298 .enc_final = authenc_enc_final,
299 .dec_final = authenc_dec_final,
300 .final = authenc_final,
301 .free_ctx = authenc_free_ctx,
302 .copy_state = authenc_copy_state,
303 };
304
drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx ** ctx,uint32_t algo)305 TEE_Result drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx,
306 uint32_t algo)
307 {
308 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
309 struct crypto_authenc *authenc = NULL;
310
311 CRYPTO_TRACE("authenc alloc_ctx algo 0x%" PRIx32, algo);
312
313 assert(ctx);
314
315 authenc = calloc(1, sizeof(*authenc));
316 if (!authenc)
317 return TEE_ERROR_OUT_OF_MEMORY;
318
319 authenc->op = drvcrypt_get_ops(CRYPTO_AUTHENC);
320 if (authenc->op && authenc->op->alloc_ctx)
321 ret = authenc->op->alloc_ctx(&authenc->ctx, algo);
322
323 if (ret != TEE_SUCCESS) {
324 free(authenc);
325 } else {
326 authenc->authenc_ctx.ops = &authenc_ops;
327 *ctx = &authenc->authenc_ctx;
328 }
329
330 CRYPTO_TRACE("authenc alloc_ctx ret 0x%" PRIx32, ret);
331 return ret;
332 }
333