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 			CIPHER_TRACE("Do input %zu bytes, offset %zu",
507 				     size_done, offset);
508 
509 			ret = run_cmac_desc(ctx, &src, NULL, false);
510 		} else {
511 			CIPHER_TRACE("Do saved blockbuf %zu bytes (done = %zu)",
512 				     ctx->blockbuf.filled, size_done);
513 			ret = run_cmac_desc(ctx, NULL, NULL, false);
514 		}
515 
516 		if (ret)
517 			goto end_cmac;
518 	}
519 
520 	if (dupdate->last) {
521 		if (dupdate->src.length - size_inmade) {
522 			size_done = dupdate->src.length - size_inmade;
523 			ret = caam_dmaobj_sgtbuf_build(&src, &size_done, offset,
524 						       ctx->alg->size_block);
525 			if (ret)
526 				goto end_cmac;
527 
528 			if (size_done != dupdate->src.length - size_inmade) {
529 				ret = TEE_ERROR_GENERIC;
530 				goto end_cmac;
531 			}
532 
533 			ret = run_cmac_desc(ctx, &src, &dst, true);
534 		} else {
535 			ret = run_cmac_desc(ctx, NULL, &dst, true);
536 		}
537 
538 		if (!ret)
539 			caam_dmaobj_copy_to_orig(&dst);
540 	}
541 
542 end_cmac_post:
543 	if (size_topost) {
544 		struct caambuf srcbuf = { .data = dupdate->src.data,
545 					  .length = dupdate->src.length };
546 
547 		CIPHER_TRACE("Post %zu of input len %zu made %zu", size_topost,
548 			     srcbuf.length, size_inmade);
549 
550 		retstatus = caam_cpy_block_src(&ctx->blockbuf, &srcbuf,
551 					       size_inmade);
552 		ret = caam_status_to_tee_result(retstatus);
553 	}
554 
555 end_cmac:
556 	caam_dmaobj_free(&src);
557 	caam_dmaobj_free(&dst);
558 
559 	return ret;
560 }
561 
562 /*
563  * Initialization of the CMAC operation.
564  *
565  * @ctx  Operation software context
566  * @key  Input key to compute
567  * @len  Key length
568  */
do_cmac_init(struct crypto_mac_ctx * ctx,const uint8_t * key,size_t len)569 static TEE_Result do_cmac_init(struct crypto_mac_ctx *ctx, const uint8_t *key,
570 			       size_t len)
571 {
572 	TEE_Result ret = TEE_ERROR_GENERIC;
573 	uint8_t *iv_tmp = NULL;
574 	struct drvcrypt_cipher_init dinit = { };
575 	struct crypto_mac *mac = to_mac_ctx(ctx);
576 	struct cipherdata *macdata = mac->ctx;
577 
578 	if (macdata->mode != TEE_CHAIN_MODE_CMAC) {
579 		/* Allocate temporary IV initialize with 0's */
580 		iv_tmp = caam_calloc(macdata->alg->size_ctx);
581 		if (!iv_tmp)
582 			return TEE_ERROR_OUT_OF_MEMORY;
583 	} else {
584 		/*
585 		 * Check if the context register is allocated to free it,
586 		 * because in case of CMAC mode, the context register
587 		 * is allocated during do_update_cmac() operation if
588 		 * necessary.
589 		 */
590 		if (macdata->ctx.data)
591 			caam_free_buf(&macdata->ctx);
592 	}
593 
594 	macdata->countdata = 0;
595 
596 	/* Prepare the initialization data */
597 	dinit.ctx = macdata;
598 	dinit.encrypt = true;
599 	dinit.key1.data = (uint8_t *)key;
600 	dinit.key1.length = len;
601 	dinit.key2.data = NULL;
602 	dinit.key2.length = 0;
603 	dinit.iv.data = iv_tmp;
604 	dinit.iv.length = macdata->alg->size_ctx;
605 	ret = caam_cipher_initialize(&dinit);
606 
607 	caam_free(iv_tmp);
608 
609 	return ret;
610 }
611 
612 /*
613  * Update of the CMAC operation.
614  *
615  * @ctx   Operation software context
616  * @data  Data to encrypt
617  * @len   Data length
618  */
do_cmac_update(struct crypto_mac_ctx * ctx,const uint8_t * data,size_t len)619 static TEE_Result do_cmac_update(struct crypto_mac_ctx *ctx,
620 				 const uint8_t *data, size_t len)
621 {
622 	TEE_Result ret = TEE_ERROR_GENERIC;
623 	struct crypto_mac *mac = to_mac_ctx(ctx);
624 	struct cipherdata *macdata = mac->ctx;
625 	struct drvcrypt_cipher_update dupdate = { };
626 
627 	/* Prepare the update data */
628 	dupdate.ctx = macdata;
629 	dupdate.encrypt = true;
630 	dupdate.last = false;
631 	dupdate.src.data = (uint8_t *)data;
632 	dupdate.src.length = len;
633 	dupdate.dst.data = NULL;
634 	dupdate.dst.length = 0;
635 
636 	ret = macdata->alg->update(&dupdate);
637 
638 	if (!ret && macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5)
639 		macdata->countdata += len;
640 
641 	return ret;
642 }
643 
644 /*
645  * Finalize the CMAC operation
646  *
647  * @ctx     Operation software context
648  * @digest  [out] Digest buffer
649  * @len     Digest buffer length
650  */
do_cmac_final(struct crypto_mac_ctx * ctx,uint8_t * digest,size_t len)651 static TEE_Result do_cmac_final(struct crypto_mac_ctx *ctx, uint8_t *digest,
652 				size_t len)
653 {
654 	TEE_Result ret = TEE_ERROR_GENERIC;
655 	uint8_t *pad_src = NULL;
656 	size_t pad_size = 0;
657 	struct crypto_mac *mac = to_mac_ctx(ctx);
658 	struct cipherdata *macdata = mac->ctx;
659 	struct drvcrypt_cipher_update dupdate = { };
660 
661 	if (macdata->mode == TEE_CHAIN_MODE_CBC_MAC_PKCS5) {
662 		/* Calculate the last block PAD size */
663 		pad_size = macdata->alg->size_block -
664 			   (macdata->countdata % macdata->alg->size_block);
665 		CIPHER_TRACE("Pad size = %zu", pad_size);
666 
667 		if (pad_size) {
668 			/* Need to pad the last block */
669 			pad_src = caam_calloc(pad_size);
670 			if (!pad_src) {
671 				CIPHER_TRACE("Pad src allocation error");
672 				return TEE_ERROR_OUT_OF_MEMORY;
673 			}
674 
675 			memset(pad_src, pad_size, pad_size);
676 		}
677 	}
678 
679 	/* Prepare the update data */
680 	dupdate.ctx = macdata;
681 	dupdate.encrypt = true;
682 	dupdate.last = true;
683 	dupdate.src.data = pad_src;
684 	dupdate.src.length = pad_size;
685 	dupdate.dst.data = digest;
686 	dupdate.dst.length = MIN(len, macdata->alg->size_block);
687 
688 	ret = macdata->alg->update(&dupdate);
689 
690 	caam_free(pad_src);
691 
692 	return ret;
693 }
694 
695 /*
696  * Free the software context
697  *
698  * @ctx    [in/out] Caller context variable
699  */
do_cmac_free(struct crypto_mac_ctx * ctx)700 static void do_cmac_free(struct crypto_mac_ctx *ctx)
701 {
702 	struct crypto_mac *mac = to_mac_ctx(ctx);
703 
704 	caam_cipher_free(mac->ctx);
705 	free(mac);
706 }
707 
708 /*
709  * Copy software CMAC context
710  *
711  * @dst_ctx  [out] Reference the context destination
712  * @src_ctx  Reference the context source
713  */
do_cmac_copy_state(struct crypto_mac_ctx * dst_ctx,struct crypto_mac_ctx * src_ctx)714 static void do_cmac_copy_state(struct crypto_mac_ctx *dst_ctx,
715 			       struct crypto_mac_ctx *src_ctx)
716 {
717 	struct crypto_mac *mac_src = to_mac_ctx(src_ctx);
718 	struct crypto_mac *mac_dst = to_mac_ctx(dst_ctx);
719 	struct cipherdata *macdata_dst = mac_dst->ctx;
720 	struct cipherdata *macdata_src = mac_src->ctx;
721 
722 	caam_cipher_copy_state(macdata_dst, macdata_src);
723 
724 	macdata_dst->countdata = macdata_src->countdata;
725 	macdata_dst->mode = macdata_src->mode;
726 }
727 
728 /*
729  * Registration of the CMAC driver
730  */
731 static const struct crypto_mac_ops cmac_ops = {
732 	.init = do_cmac_init,
733 	.update = do_cmac_update,
734 	.final = do_cmac_final,
735 	.free_ctx = do_cmac_free,
736 	.copy_state = do_cmac_copy_state,
737 };
738 
739 /*
740  * Allocate the software context
741  *
742  * @ctx      [out] Caller context variable
743  * @algo     Algorithm ID
744  */
caam_cmac_allocate(struct crypto_mac_ctx ** ctx,uint32_t algo)745 static TEE_Result caam_cmac_allocate(struct crypto_mac_ctx **ctx, uint32_t algo)
746 {
747 	TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
748 	struct crypto_mac *mac = NULL;
749 	const struct cipheralg *alg = NULL;
750 	struct cipherdata *macdata = NULL;
751 
752 	CIPHER_TRACE("Allocate Context (%p) algo %" PRIx32, ctx, algo);
753 
754 	alg = get_macalgo(algo);
755 	if (!alg) {
756 		CIPHER_TRACE("Algorithm not supported");
757 		return TEE_ERROR_NOT_IMPLEMENTED;
758 	}
759 
760 	mac = calloc(1, sizeof(*mac));
761 	if (!mac)
762 		return TEE_ERROR_OUT_OF_MEMORY;
763 
764 	macdata = caam_calloc(sizeof(*macdata));
765 	if (!macdata) {
766 		CIPHER_TRACE("Allocation MAC data error");
767 		ret = TEE_ERROR_OUT_OF_MEMORY;
768 		goto err;
769 	}
770 
771 	/* Allocate the descriptor */
772 	macdata->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES);
773 	if (!macdata->descriptor) {
774 		CIPHER_TRACE("Allocation descriptor error");
775 		ret = TEE_ERROR_OUT_OF_MEMORY;
776 		goto err;
777 	}
778 
779 	/* Setup the algorithm pointer */
780 	macdata->alg = alg;
781 
782 	/* Initialize the block buffer */
783 	macdata->blockbuf.max = alg->size_block;
784 
785 	/* Keep the MAC mode */
786 	macdata->mode = TEE_ALG_GET_CHAIN_MODE(algo);
787 
788 	mac->mac_ctx.ops = &cmac_ops;
789 	mac->ctx = macdata;
790 
791 	*ctx = &mac->mac_ctx;
792 
793 	return TEE_SUCCESS;
794 
795 err:
796 	if (macdata)
797 		caam_free_desc(&macdata->descriptor);
798 
799 	caam_free(macdata);
800 	free(mac);
801 
802 	return ret;
803 }
804 
805 /*
806  * Initialize the CMAC module
807  *
808  * @ctrl_addr   Controller base address
809  */
caam_cmac_init(vaddr_t ctrl_addr __unused)810 enum caam_status caam_cmac_init(vaddr_t ctrl_addr __unused)
811 {
812 	if (drvcrypt_register(CRYPTO_CMAC, &caam_cmac_allocate))
813 		return CAAM_FAILURE;
814 
815 	return CAAM_NO_ERROR;
816 }
817