1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2021 NXP
4 *
5 * Implementation of CMAC functions
6 */
7 #include <caam_cipher.h>
8 #include <caam_common.h>
9 #include <caam_jr.h>
10 #include <caam_utils_mem.h>
11 #include <caam_utils_status.h>
12 #include <drvcrypt_mac.h>
13 #include <mm/core_memprot.h>
14 #include <string.h>
15 #include <tee/cache.h>
16 #include <utee_defines.h>
17
18 #include "local.h"
19
20 static TEE_Result do_update_mac(struct drvcrypt_cipher_update *dupdate);
21 static TEE_Result do_update_cmac(struct drvcrypt_cipher_update *dupdate);
22
23 /*
24 * Constant definitions of AES MAC algorithms
25 */
26 static const struct cipheralg aes_cbc_mac_alg = {
27 .type = OP_ALGO(AES) | ALGO_AAI(AES_CBC),
28 .size_block = TEE_AES_BLOCK_SIZE,
29 .size_ctx = 2 * sizeof(uint64_t),
30 .ctx_offset = 0,
31 .require_key = NEED_KEY1 | NEED_IV,
32 .def_key = {
33 .min = 16,
34 .max = 32,
35 .mod = 8
36 },
37 .update = do_update_mac,
38 };
39
40 static const struct cipheralg aes_cmac_alg = {
41 .type = OP_ALGO(AES) | ALGO_AAI(AES_CMAC),
42 .size_block = TEE_AES_BLOCK_SIZE,
43 .size_ctx = 4 * sizeof(uint64_t),
44 .ctx_offset = 0,
45 .require_key = NEED_KEY1,
46 .def_key = {
47 .min = 16,
48 .max = 32,
49 .mod = 8
50 },
51 .update = do_update_cmac,
52 };
53
54 /*
55 * Constant definitions of DES MAC algorithm
56 */
57 static const struct cipheralg des_mac_alg = {
58 .type = OP_ALGO(DES) | ALGO_AAI(DES_CBC),
59 .size_block = TEE_DES_BLOCK_SIZE,
60 .size_ctx = sizeof(uint64_t),
61 .ctx_offset = 0,
62 .require_key = NEED_KEY1 | NEED_IV,
63 .def_key = {
64 .min = 8,
65 .max = 8,
66 .mod = 8
67 },
68 .update = do_update_mac,
69 };
70
71 /*
72 * Constant definitions of DES3 MAC algorithm
73 */
74 static const struct cipheralg des3_mac_alg = {
75 .type = OP_ALGO(3DES) | ALGO_AAI(DES_CBC),
76 .size_block = TEE_DES_BLOCK_SIZE,
77 .size_ctx = sizeof(uint64_t),
78 .ctx_offset = 0,
79 .require_key = NEED_KEY1 | NEED_IV,
80 .def_key = {
81 .min = 16,
82 .max = 24,
83 .mod = 8
84 },
85 .update = do_update_mac,
86 };
87
88 static const struct crypto_mac_ops cmac_ops;
89
90 /*
91 * Format the MAC context to keep the reference to the operation driver
92 */
93 struct crypto_mac {
94 struct crypto_mac_ctx mac_ctx; /* Crypto MAC API context */
95 struct cipherdata *ctx; /* CMAC context */
96 };
97
98 /*
99 * Returns the reference to the driver context
100 *
101 * @ctx API context
102 */
to_mac_ctx(struct crypto_mac_ctx * ctx)103 static struct crypto_mac *to_mac_ctx(struct crypto_mac_ctx *ctx)
104 {
105 assert(ctx && ctx->ops == &cmac_ops);
106
107 return container_of(ctx, struct crypto_mac, mac_ctx);
108 }
109
110 /*
111 * Checks if the algorithm @algo is supported and returns the
112 * local algorithm entry in the corresponding cipher array.
113 *
114 * @algo Algorithm ID
115 */
get_macalgo(uint32_t algo)116 static const struct cipheralg *get_macalgo(uint32_t algo)
117 {
118 switch (algo) {
119 case TEE_ALG_AES_CBC_MAC_NOPAD:
120 case TEE_ALG_AES_CBC_MAC_PKCS5:
121 return &aes_cbc_mac_alg;
122 case TEE_ALG_AES_CMAC:
123 return &aes_cmac_alg;
124 case TEE_ALG_DES_CBC_MAC_NOPAD:
125 case TEE_ALG_DES_CBC_MAC_PKCS5:
126 return &des_mac_alg;
127 case TEE_ALG_DES3_CBC_MAC_NOPAD:
128 case TEE_ALG_DES3_CBC_MAC_PKCS5:
129 return &des3_mac_alg;
130 default:
131 return NULL;
132 }
133 }
134
135 /*
136 * MAC update of the cipher operation of complete block except
137 * if last block. Last block can be partial block.
138 *
139 * @dupdate Data update object
140 */
do_update_mac(struct drvcrypt_cipher_update * dupdate)141 static TEE_Result do_update_mac(struct drvcrypt_cipher_update *dupdate)
142 {
143 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
144 enum caam_status retstatus = CAAM_FAILURE;
145 struct cipherdata *ctx = dupdate->ctx;
146 struct caamdmaobj src = { };
147 struct caamdmaobj dst = { };
148 size_t full_size = 0;
149 size_t size_topost = 0;
150 size_t size_todo = 0;
151 size_t size_done = 0;
152 size_t size_inmade = 0;
153 size_t offset = 0;
154
155 CIPHER_TRACE("Length=%zu - %s", dupdate->src.length,
156 ctx->encrypt ? "Encrypt" : "Decrypt");
157
158 /* Calculate the total data to be handled */
159 full_size = ctx->blockbuf.filled + dupdate->src.length;
160 if (full_size < ctx->alg->size_block) {
161 size_topost = dupdate->src.length;
162 } else {
163 size_topost = full_size % ctx->alg->size_block;
164 size_inmade = dupdate->src.length - size_topost;
165 /* Total size that is a cipher block multiple */
166 size_todo = full_size - size_topost;
167 }
168
169 CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", full_size,
170 size_topost, size_todo);
171
172 if (!size_todo) {
173 /*
174 * There is no complete block to do:
175 * - either input size + already saved data < block size
176 * - or no input data and this is the last block
177 */
178 if (dupdate->last)
179 memcpy(dupdate->dst.data, ctx->ctx.data,
180 MIN(dupdate->dst.length, ctx->alg->size_ctx));
181
182 ret = TEE_SUCCESS;
183 goto end_mac_post;
184 }
185
186 if (dupdate->src.length) {
187 ret = caam_dmaobj_init_input(&src, dupdate->src.data,
188 dupdate->src.length);
189 if (ret)
190 goto end_mac;
191
192 ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block);
193 if (ret)
194 goto end_mac;
195 }
196
197 if (dupdate->last) {
198 ret = caam_dmaobj_output_sgtbuf(&dst, dupdate->dst.data,
199 dupdate->dst.length,
200 dupdate->dst.length);
201 if (ret)
202 goto end_mac;
203
204 /* Remove a block of data to do the last block */
205 if (size_todo > ctx->alg->size_block)
206 size_todo -= ctx->alg->size_block;
207 else
208 size_todo = 0;
209 }
210
211 /* Check if there is some data saved to complete the buffer */
212 if (ctx->blockbuf.filled) {
213 ret = caam_dmaobj_add_first_block(&src, &ctx->blockbuf);
214 if (ret)
215 goto end_mac;
216 ctx->blockbuf.filled = 0;
217 }
218
219 size_done = ctx->alg->size_block;
220 for (offset = 0; size_todo;
221 offset += size_done, size_todo -= size_done) {
222 CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done,
223 offset);
224
225 ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset,
226 ctx->alg->size_block);
227 if (ret)
228 goto end_mac;
229
230 if (size_done != ctx->alg->size_block) {
231 ret = TEE_ERROR_GENERIC;
232 goto end_mac;
233 }
234
235 retstatus = caam_cipher_block(ctx, true, NEED_KEY1, true, &src,
236 NULL);
237
238 if (retstatus != CAAM_NO_ERROR) {
239 ret = caam_status_to_tee_result(retstatus);
240 goto end_mac;
241 }
242 }
243
244 if (dupdate->last) {
245 CIPHER_TRACE("Do input %zu bytes, offset %zu", size_done,
246 offset);
247
248 ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset,
249 ctx->alg->size_block);
250 if (ret)
251 goto end_mac;
252
253 if (size_done != ctx->alg->size_block) {
254 ret = TEE_ERROR_GENERIC;
255 goto end_mac;
256 }
257
258 retstatus = caam_cipher_block(ctx, true, NEED_KEY1, true, &src,
259 &dst);
260
261 if (retstatus == CAAM_NO_ERROR)
262 caam_dmaobj_copy_to_orig(&dst);
263
264 ret = caam_status_to_tee_result(retstatus);
265 }
266
267 end_mac_post:
268 if (size_topost) {
269 struct caambuf cpysrc = {
270 .data = dupdate->src.data,
271 .length = dupdate->src.length
272 };
273
274 CIPHER_TRACE("Save input data %zu bytes of %zu (%zu)",
275 size_topost, dupdate->src.length, size_inmade);
276
277 retstatus = caam_cpy_block_src(&ctx->blockbuf, &cpysrc,
278 size_inmade);
279 ret = caam_status_to_tee_result(retstatus);
280 }
281
282 end_mac:
283 caam_dmaobj_free(&src);
284 caam_dmaobj_free(&dst);
285
286 return ret;
287 }
288
289 /*
290 * Build and run the CMAC descriptor (AES only)
291 *
292 * @ctx Cipher Data context
293 * @src Input data
294 * @dstbuf [out] Output data if last block
295 * @last Last block flag
296 */
run_cmac_desc(struct cipherdata * ctx,struct caamdmaobj * src,struct caamdmaobj * dst,bool last)297 static TEE_Result run_cmac_desc(struct cipherdata *ctx, struct caamdmaobj *src,
298 struct caamdmaobj *dst, bool last)
299 {
300 TEE_Result ret = TEE_ERROR_GENERIC;
301 enum caam_status retstatus = CAAM_FAILURE;
302 struct caam_jobctx jobctx = { };
303 uint32_t *desc = NULL;
304
305 desc = ctx->descriptor;
306 caam_desc_init(desc);
307 caam_desc_add_word(desc, DESC_HEADER(0));
308
309 if (ctx->alg->require_key & NEED_KEY1) {
310 /* Build the descriptor */
311 caam_desc_add_word(desc, LD_KEY_PLAIN(CLASS_1, REG,
312 ctx->key1.length));
313 caam_desc_add_ptr(desc, ctx->key1.paddr);
314 }
315
316 /* If context already allocated, this is an update */
317 if (ctx->ctx.length) {
318 CIPHER_TRACE("%s operation", last ? "Final" : "Update");
319 caam_desc_add_word(desc, LD_NOIMM_OFF(CLASS_1, REG_CTX,
320 ctx->ctx.length,
321 ctx->alg->ctx_offset));
322 caam_desc_add_ptr(desc, ctx->ctx.paddr);
323 if (last)
324 caam_desc_add_word(desc,
325 CIPHER_FINAL(ctx->alg->type, true));
326 else
327 caam_desc_add_word(desc,
328 CIPHER_UPDATE(ctx->alg->type, true));
329 } else if (last) {
330 CIPHER_TRACE("Init/Final operation");
331
332 caam_desc_add_word(desc,
333 CIPHER_INITFINAL(ctx->alg->type, true));
334 } else {
335 CIPHER_TRACE("Init operation");
336
337 caam_desc_add_word(desc, CIPHER_INIT(ctx->alg->type, true));
338 if (!ctx->ctx.data) {
339 retstatus = caam_alloc_align_buf(&ctx->ctx,
340 ctx->alg->size_ctx);
341 if (retstatus != CAAM_NO_ERROR)
342 return TEE_ERROR_OUT_OF_MEMORY;
343 }
344 }
345
346 /* Check first if there is some pending data from previous updates */
347 if (ctx->blockbuf.filled) {
348 /* Add the temporary buffer */
349 if (src)
350 caam_desc_add_word(desc,
351 FIFO_LD_EXT(CLASS_1, MSG, NOACTION));
352 else
353 caam_desc_add_word(desc,
354 FIFO_LD_EXT(CLASS_1, MSG, LAST_C1));
355
356 caam_desc_add_ptr(desc, ctx->blockbuf.buf.paddr);
357 caam_desc_add_word(desc, ctx->blockbuf.filled);
358
359 /* Clean the circular buffer data to be loaded */
360 cache_operation(TEE_CACHECLEAN, ctx->blockbuf.buf.data,
361 ctx->blockbuf.filled);
362 }
363
364 if (src) {
365 caam_desc_fifo_load(desc, src, CLASS_1, MSG, LAST_C1);
366 caam_dmaobj_cache_push(src);
367 } else {
368 if (last && !ctx->blockbuf.filled) {
369 /*
370 * Add the input data of 0 bytes to start
371 * algorithm by setting the input data size
372 */
373 caam_desc_add_word(desc,
374 FIFO_LD(CLASS_1, MSG, LAST_C1, 0));
375 caam_desc_add_ptr(desc, 0);
376 }
377 }
378
379 ctx->blockbuf.filled = 0;
380
381 if (last) {
382 caam_desc_store(desc, dst, CLASS_1, REG_CTX);
383 caam_dmaobj_cache_push(dst);
384 } else {
385 /* Store the context */
386 caam_desc_add_word(desc, ST_NOIMM_OFF(CLASS_1, REG_CTX,
387 ctx->ctx.length,
388 ctx->alg->ctx_offset));
389 caam_desc_add_ptr(desc, ctx->ctx.paddr);
390 }
391
392 CIPHER_DUMPDESC(desc);
393
394 /* Invalidate Context register */
395 if (ctx->ctx.length)
396 cache_operation(TEE_CACHEINVALIDATE, ctx->ctx.data,
397 ctx->ctx.length);
398
399 jobctx.desc = desc;
400 retstatus = caam_jr_enqueue(&jobctx, NULL);
401
402 if (retstatus == CAAM_NO_ERROR) {
403 ret = TEE_SUCCESS;
404 } else {
405 CIPHER_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
406 ret = job_status_to_tee_result(jobctx.status);
407 }
408
409 return ret;
410 }
411
412 /*
413 * Update of the CMAC operation of complete block except
414 * if last block. Last block can be a partial block.
415 *
416 * @dupdate Data update object
417 */
do_update_cmac(struct drvcrypt_cipher_update * dupdate)418 static TEE_Result do_update_cmac(struct drvcrypt_cipher_update *dupdate)
419 {
420 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
421 enum caam_status retstatus = CAAM_FAILURE;
422 struct cipherdata *ctx = dupdate->ctx;
423 size_t full_size = 0;
424 size_t size_topost = 0;
425 size_t size_todo = 0;
426 size_t size_inmade = 0;
427 size_t size_done = 0;
428 size_t offset = 0;
429 struct caamdmaobj src = { };
430 struct caamdmaobj dst = { };
431
432 CIPHER_TRACE("Length=%zu - %s", dupdate->src.length,
433 dupdate->encrypt ? "Encrypt" : "Decrypt");
434
435 /* Calculate the total data to be handled */
436 full_size = ctx->blockbuf.filled + dupdate->src.length;
437 if (!dupdate->last) {
438 /*
439 * In case there is no data to save and because it's
440 * not the final operation, ensure that a block of data
441 * is kept for the final operation.
442 */
443 if (full_size <= ctx->alg->size_block) {
444 size_topost = dupdate->src.length;
445 goto end_cmac_post;
446 }
447
448 size_topost = full_size % ctx->alg->size_block;
449
450 if (!size_topost)
451 size_topost = ctx->alg->size_block;
452
453 size_inmade = dupdate->src.length - size_topost;
454 size_todo = full_size - size_topost;
455 } else {
456 ret = caam_dmaobj_output_sgtbuf(&dst, dupdate->dst.data,
457 dupdate->dst.length,
458 dupdate->dst.length);
459 if (ret)
460 goto end_cmac;
461
462 /*
463 * If there more than one block to do, keep the last
464 * block to build the CMAC output.
465 */
466 if (full_size > ctx->alg->size_block) {
467 size_todo = full_size - ctx->alg->size_block;
468 size_inmade = size_todo - ctx->blockbuf.filled;
469 }
470 }
471
472 if (size_inmade) {
473 ret = caam_dmaobj_init_input(&src, dupdate->src.data,
474 size_inmade);
475 if (ret)
476 goto end_cmac;
477
478 ret = caam_dmaobj_prepare(&src, NULL, ctx->alg->size_block);
479 if (ret)
480 goto end_cmac;
481 }
482
483 CIPHER_TRACE("FullSize %zu - posted %zu - todo %zu", full_size,
484 size_topost, size_todo);
485
486 for (offset = 0; size_todo;
487 offset += size_done, size_todo -= size_done) {
488 /*
489 * At least one block is to be done.
490 * At first iteration, we can have less than one block
491 * data available from previous update operation which
492 * was not block modulus.
493 * Remove the previous saved data (blockbuf) from the data to
494 * take from input data.
495 * Next iteration, blockbuf will be empty.
496 */
497 size_todo -= ctx->blockbuf.filled;
498 size_done = size_todo;
499
500 if (size_inmade) {
501 ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset,
502 ctx->alg->size_block);
503 if (ret)
504 goto end_cmac;
505
506 /*
507 * Need to re-adjust the length of the data if the
508 * posted data block is not empty and the SGT/Buffer
509 * is part of the full input data to do.
510 */
511 if (ctx->blockbuf.filled && size_done < size_todo) {
512 size_done -= ctx->blockbuf.filled;
513 src.sgtbuf.length = size_done;
514 }
515 CIPHER_TRACE("Do input %zu bytes, offset %zu",
516 size_done, offset);
517
518 ret = run_cmac_desc(ctx, &src, NULL, false);
519 } else {
520 CIPHER_TRACE("Do saved blockbuf %zu bytes (done = %zu)",
521 ctx->blockbuf.filled, size_done);
522 ret = run_cmac_desc(ctx, NULL, NULL, false);
523 }
524
525 if (ret)
526 goto end_cmac;
527 }
528
529 if (dupdate->last) {
530 if (dupdate->src.length - size_inmade) {
531 size_done = dupdate->src.length - size_inmade;
532 ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset,
533 ctx->alg->size_block);
534 if (ret)
535 goto end_cmac;
536
537 if (size_done != dupdate->src.length - size_inmade) {
538 ret = TEE_ERROR_GENERIC;
539 goto end_cmac;
540 }
541
542 ret = run_cmac_desc(ctx, &src, &dst, true);
543 } else {
544 ret = run_cmac_desc(ctx, NULL, &dst, true);
545 }
546
547 if (!ret)
548 caam_dmaobj_copy_to_orig(&dst);
549 }
550
551 end_cmac_post:
552 if (size_topost) {
553 struct caambuf srcbuf = { .data = dupdate->src.data,
554 .length = dupdate->src.length };
555
556 CIPHER_TRACE("Post %zu of input len %zu made %zu", size_topost,
557 srcbuf.length, size_inmade);
558
559 retstatus = caam_cpy_block_src(&ctx->blockbuf, &srcbuf,
560 size_inmade);
561 ret = caam_status_to_tee_result(retstatus);
562 }
563
564 end_cmac:
565 caam_dmaobj_free(&src);
566 caam_dmaobj_free(&dst);
567
568 return ret;
569 }
570
571 /*
572 * Initialization of the CMAC operation.
573 *
574 * @ctx Operation software context
575 * @key Input key to compute
576 * @len Key length
577 */
do_cmac_init(struct crypto_mac_ctx * ctx,const uint8_t * key,size_t len)578 static TEE_Result do_cmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key,
579 size_t len)
580 {
581 TEE_Result ret = TEE_ERROR_GENERIC;
582 uint8_t *iv_tmp = NULL;
583 struct drvcrypt_cipher_init dinit = { };
584 struct crypto_mac *mac = to_mac_ctx(ctx);
585 struct cipherdata *macdata = mac->ctx;
586
587 if (macdata->mode != TEE_CHAIN_MODE_CMAC) {
588 /* Allocate temporary IV initialize with 0's */
589 iv_tmp = caam_calloc(macdata->alg->size_ctx);
590 if (!iv_tmp)
591 return TEE_ERROR_OUT_OF_MEMORY;
592 } else {
593 /*
594 * Check if the context register is allocated to free it,
595 * because in case of CMAC mode, the context register
596 * is allocated during do_update_cmac() operation if
597 * necessary.
598 */
599 if (macdata->ctx.data)
600 caam_free_buf(&macdata->ctx);
601 }
602
603 macdata->countdata = 0;
604
605 /* Prepare the initialization data */
606 dinit.ctx = macdata;
607 dinit.encrypt = true;
608 dinit.key1.data = (uint8_t *)key;
609 dinit.key1.length = len;
610 dinit.key2.data = NULL;
611 dinit.key2.length = 0;
612 dinit.iv.data = iv_tmp;
613 dinit.iv.length = macdata->alg->size_ctx;
614 ret = caam_cipher_initialize(&dinit);
615
616 caam_free(iv_tmp);
617
618 return ret;
619 }
620
621 /*
622 * Update of the CMAC operation.
623 *
624 * @ctx Operation software context
625 * @data Data to encrypt
626 * @len Data length
627 */
do_cmac_update(struct crypto_mac_ctx * ctx,const uint8_t * data,size_t len)628 static TEE_Result do_cmac_update(struct crypto_mac_ctx *ctx,
629 const uint8_t *data, size_t len)
630 {
631 TEE_Result ret = TEE_ERROR_GENERIC;
632 struct crypto_mac *mac = to_mac_ctx(ctx);
633 struct cipherdata *macdata = mac->ctx;
634 struct drvcrypt_cipher_update dupdate = { };
635
636 /* Prepare the update data */
637 dupdate.ctx = macdata;
638 dupdate.encrypt = true;
639 dupdate.last = false;
640 dupdate.src.data = (uint8_t *)data;
641 dupdate.src.length = len;
642 dupdate.dst.data = NULL;
643 dupdate.dst.length = 0;
644
645 ret = macdata->alg->update(&dupdate);
646
647 if (!ret && macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5)
648 macdata->countdata += len;
649
650 return ret;
651 }
652
653 /*
654 * Finalize the CMAC operation
655 *
656 * @ctx Operation software context
657 * @digest [out] Digest buffer
658 * @len Digest buffer length
659 */
do_cmac_final(struct crypto_mac_ctx * ctx,uint8_t * digest,size_t len)660 static TEE_Result do_cmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest,
661 size_t len)
662 {
663 TEE_Result ret = TEE_ERROR_GENERIC;
664 uint8_t *pad_src = NULL;
665 size_t pad_size = 0;
666 struct crypto_mac *mac = to_mac_ctx(ctx);
667 struct cipherdata *macdata = mac->ctx;
668 struct drvcrypt_cipher_update dupdate = { };
669
670 if (macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5) {
671 /* Calculate the last block PAD size */
672 pad_size = macdata->alg->size_block -
673 (macdata->countdata % macdata->alg->size_block);
674 CIPHER_TRACE("Pad size = %zu", pad_size);
675
676 if (pad_size) {
677 /* Need to pad the last block */
678 pad_src = caam_calloc(pad_size);
679 if (!pad_src) {
680 CIPHER_TRACE("Pad src allocation error");
681 return TEE_ERROR_OUT_OF_MEMORY;
682 }
683
684 memset(pad_src, pad_size, pad_size);
685 }
686 }
687
688 /* Prepare the update data */
689 dupdate.ctx = macdata;
690 dupdate.encrypt = true;
691 dupdate.last = true;
692 dupdate.src.data = pad_src;
693 dupdate.src.length = pad_size;
694 dupdate.dst.data = digest;
695 dupdate.dst.length = MIN(len, macdata->alg->size_block);
696
697 ret = macdata->alg->update(&dupdate);
698
699 caam_free(pad_src);
700
701 return ret;
702 }
703
704 /*
705 * Free the software context
706 *
707 * @ctx [in/out] Caller context variable
708 */
do_cmac_free(struct crypto_mac_ctx * ctx)709 static void do_cmac_free(struct crypto_mac_ctx *ctx)
710 {
711 struct crypto_mac *mac = to_mac_ctx(ctx);
712
713 caam_cipher_free(mac->ctx);
714 free(mac);
715 }
716
717 /*
718 * Copy software CMAC context
719 *
720 * @dst_ctx [out] Reference the context destination
721 * @src_ctx Reference the context source
722 */
do_cmac_copy_state(struct crypto_mac_ctx * dst_ctx,struct crypto_mac_ctx * src_ctx)723 static void do_cmac_copy_state(struct crypto_mac_ctx *dst_ctx,
724 struct crypto_mac_ctx *src_ctx)
725 {
726 struct crypto_mac *mac_src = to_mac_ctx(src_ctx);
727 struct crypto_mac *mac_dst = to_mac_ctx(dst_ctx);
728 struct cipherdata *macdata_dst = mac_dst->ctx;
729 struct cipherdata *macdata_src = mac_src->ctx;
730
731 caam_cipher_copy_state(macdata_dst, macdata_src);
732
733 macdata_dst->countdata = macdata_src->countdata;
734 macdata_dst->mode = macdata_src->mode;
735 }
736
737 /*
738 * Registration of the CMAC driver
739 */
740 static const struct crypto_mac_ops cmac_ops = {
741 .init = do_cmac_init,
742 .update = do_cmac_update,
743 .final = do_cmac_final,
744 .free_ctx = do_cmac_free,
745 .copy_state = do_cmac_copy_state,
746 };
747
748 /*
749 * Allocate the software context
750 *
751 * @ctx [out] Caller context variable
752 * @algo Algorithm ID
753 */
caam_cmac_allocate(struct crypto_mac_ctx ** ctx,uint32_t algo)754 static TEE_Result caam_cmac_allocate(struct crypto_mac_ctx **ctx, uint32_t algo)
755 {
756 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
757 struct crypto_mac *mac = NULL;
758 const struct cipheralg *alg = NULL;
759 struct cipherdata *macdata = NULL;
760
761 CIPHER_TRACE("Allocate Context (%p) algo %" PRIx32, ctx, algo);
762
763 alg = get_macalgo(algo);
764 if (!alg) {
765 CIPHER_TRACE("Algorithm not supported");
766 return TEE_ERROR_NOT_IMPLEMENTED;
767 }
768
769 mac = calloc(1, sizeof(*mac));
770 if (!mac)
771 return TEE_ERROR_OUT_OF_MEMORY;
772
773 macdata = caam_calloc(sizeof(*macdata));
774 if (!macdata) {
775 CIPHER_TRACE("Allocation MAC data error");
776 ret = TEE_ERROR_OUT_OF_MEMORY;
777 goto err;
778 }
779
780 /* Allocate the descriptor */
781 macdata->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES);
782 if (!macdata->descriptor) {
783 CIPHER_TRACE("Allocation descriptor error");
784 ret = TEE_ERROR_OUT_OF_MEMORY;
785 goto err;
786 }
787
788 /* Setup the algorithm pointer */
789 macdata->alg = alg;
790
791 /* Initialize the block buffer */
792 macdata->blockbuf.max = alg->size_block;
793
794 /* Keep the MAC mode */
795 macdata->mode = TEE_ALG_GET_CHAIN_MODE(algo);
796
797 mac->mac_ctx.ops = &cmac_ops;
798 mac->ctx = macdata;
799
800 *ctx = &mac->mac_ctx;
801
802 return TEE_SUCCESS;
803
804 err:
805 if (macdata)
806 caam_free_desc(&macdata->descriptor);
807
808 caam_free(macdata);
809 free(mac);
810
811 return ret;
812 }
813
814 /*
815 * Initialize the CMAC module
816 *
817 * @ctrl_addr Controller base address
818 */
caam_cmac_init(vaddr_t ctrl_addr __unused)819 enum caam_status caam_cmac_init(vaddr_t ctrl_addr __unused)
820 {
821 if (drvcrypt_register(CRYPTO_CMAC, &caam_cmac_allocate))
822 return CAAM_FAILURE;
823
824 return CAAM_NO_ERROR;
825 }
826