xref: /optee_os/core/drivers/crypto/caam/caam_key.c (revision 209c34dc03563af70f1e406f304008495dae7a5e)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2023 NXP
4  */
5 #include <assert.h>
6 #include <caam_desc_helper.h>
7 #include <caam_key.h>
8 #include <caam_status.h>
9 #include <caam_trace.h>
10 #include <caam_utils_mem.h>
11 #include <crypto/crypto.h>
12 #include <kernel/panic.h>
13 #include <mm/core_memprot.h>
14 #include <stdint.h>
15 #include <string.h>
16 #include <tee/cache.h>
17 #include <tee_api_defines.h>
18 #include <trace.h>
19 #include <utee_types.h>
20 
21 /*
22  * CAAM Key magic number.
23  * When the first 32 bits of a key buffer are equal to this value, the buffer
24  * is a serialized CAAM key structure.
25  */
26 #define MAGIC_NUMBER 0xCAAFBFFB
27 
28 /*
29  * Because the CAAM driver relies on this magic number to determine if the key
30  * is plain text or black, collision can happen. A randomly generated plain text
31  * key could feature the magic number. That's unlikely but still possible.
32  *
33  * Regarding the possibility of collision or forging attack, there are no
34  * security concerns. Forging and trying to make a plain text key look like a
35  * black key, won't do much. If the key is forged to look like an ECB Black
36  * key, the singing operation will output a corrupted result. If the key is
37  * forged to look like a CCM Black key, the import key will fail (because the
38  * MAC verification) and no signing operation will be done.
39  */
40 
41 #define BLOB_BKEK_SIZE	     32 /* Blob key encryption key size */
42 #define BLOB_MAC_SIZE	     16 /* Blob MAC size */
43 #define BLOB_PAD_SIZE	     (BLOB_BKEK_SIZE + BLOB_MAC_SIZE)
44 
45 /*
46  * CAAM Blob key modifier
47  * Key modifier used to derive Blob-key encryption key (BKEK) from the CAAM
48  * master key.
49  *
50  * A CAAM black key is encrypted using a volatile Job Descriptor key encryption
51  * key or JDKEK. Black keys are not intended for storage of keys across SoC
52  * power cycles. The JDKEK is re-generated upon every power cycle (reset,
53  * suspend/resume ...) or CAAM RNG re-seed.
54  *
55  * To retain key across power cycles, the black key must be encapsulated as a
56  * blob. The blob key encryption key is derived from the CAAM master key which
57  * makes it non-volatile and can be re-created when the chip powers up again.
58  */
59 #define KEY_BLOB_MODIFIER_SIZE 16
60 static const uint8_t key_blob_modifier[KEY_BLOB_MODIFIER_SIZE] =
61 	"NXP_OPTEE_BLOB";
62 
63 /*
64  * Serialized CAAM key structure format.
65  *
66  * If the incoming key buffer is the following:
67  *	| Magic number | key type | key size | key blob buffer |
68  * The CAAM Key structure will be populated as following:
69  * struct caamkey {
70  *	.key_type = key type,
71  *	.key_size = key size,
72  *	.is_blob = true,
73  *	.buf = key blob buffer
74  * }
75  *
76  * If the incoming key buffer is the following:
77  *	| Key buffer |
78  * The CAAM Key structure will be populated as following:
79  * struct caamkey {
80  *	.key_type = CAAM_KEY_PLAIN_TEXT,
81  *	.key_size = sizeof(Key buffer),
82  *	.is_blob = false,
83  *	.buf = key buffer
84  * }
85  */
86 struct caam_key_serialized {
87 	uint32_t magic_number; /* Magic number */
88 	uint32_t key_type; /* Black key type */
89 	uint32_t sec_size; /* The original plain text key size */
90 	uint8_t key[];
91 };
92 
93 /*
94  * CAAM key type enumeration to string
95  */
96 static const char *const caam_key_type_to_str[] __maybe_unused = {
97 	[CAAM_KEY_PLAIN_TEXT] = "Plain Text",
98 	[CAAM_KEY_BLACK_ECB] = "Black ECB",
99 	[CAAM_KEY_BLACK_CCM] = "Black CCM",
100 };
101 
102 static struct caam_key_serialized *data_to_serialized_key(const uint8_t *data,
103 							  size_t size)
104 {
105 	assert(data && size);
106 	assert(size > sizeof(struct caam_key_serialized));
107 
108 	/*
109 	 * It's important to make sure uint8_t and caam_key_serialized{} are
110 	 * actually aligned for performance purpose.
111 	 *
112 	 * A __packed attribute to caam_key_serialized{} could solve the
113 	 * alignment issue but at the cost of un-optimize memory access.
114 	 * To avoid using the __packed attribute, caam_key_serialized{} is
115 	 * defined to be aligned on uint8_t. The following assert checks
116 	 * for this alignment.
117 	 */
118 	assert(IS_ALIGNED_WITH_TYPE(data, struct caam_key_serialized));
119 
120 	/*
121 	 * The cast to void* instead of struct caam_key_serialized* is needed
122 	 * to avoid the cast alignment compilation warning.
123 	 */
124 	return (void *)data;
125 }
126 
127 /*
128  * Return the CAAM key type of the given key buffer
129  *
130  * @data	Input buffer
131  * @size	Input buffer size
132  */
133 static enum caam_key_type get_key_type(const uint8_t *data, size_t size)
134 {
135 	struct caam_key_serialized *key = data_to_serialized_key(data, size);
136 
137 	if (key->magic_number != MAGIC_NUMBER)
138 		return CAAM_KEY_PLAIN_TEXT;
139 
140 	return key->key_type;
141 }
142 
143 /*
144  * Return the CAAM key size of the given key buffer
145  *
146  * @data	Input buffer
147  * @size	Input buffer size
148  */
149 static size_t get_key_sec_size(const uint8_t *data, size_t size)
150 {
151 	struct caam_key_serialized *key = data_to_serialized_key(data, size);
152 
153 	if (key->magic_number != MAGIC_NUMBER)
154 		return size;
155 
156 	return key->sec_size;
157 }
158 
159 /*
160  * Return the CAAM key buffer pointer of the given key buffer
161  *
162  * @data	Input buffer
163  * @size	Input buffer size
164  */
165 static unsigned long get_key_buf_offset(const uint8_t *data, size_t size)
166 {
167 	struct caam_key_serialized *key = data_to_serialized_key(data, size);
168 
169 	if (key->magic_number != MAGIC_NUMBER)
170 		return 0;
171 	else
172 		return offsetof(struct caam_key_serialized, key);
173 }
174 
175 /*
176  * Return the CAAM key buffer size of the given key buffer
177  *
178  * @data	Input buffer
179  * @size	Input buffer size
180  */
181 static size_t get_key_buf_size(const uint8_t *data, size_t size)
182 {
183 	struct caam_key_serialized *key = data_to_serialized_key(data, size);
184 
185 	/*
186 	 * In the caam_key_serialized{}, the last element of the structure is
187 	 * a variable-sized buffer.
188 	 */
189 	return size - sizeof(*key);
190 }
191 
192 size_t caam_key_get_alloc_size(const struct caamkey *key)
193 {
194 	if (!key)
195 		return 0;
196 
197 	/* A blob size is independent from the key encryption algorithm */
198 	if (key->is_blob)
199 		return key->sec_size + BLOB_PAD_SIZE;
200 
201 	switch (key->key_type) {
202 	case CAAM_KEY_PLAIN_TEXT:
203 		/*
204 		 * If the key is plain text, the allocation size is equal to the
205 		 * key size and no blob operation on this key is possible.
206 		 */
207 		return key->sec_size;
208 	case CAAM_KEY_BLACK_ECB:
209 		/* ECB-black key must be a multiple of 16 bytes */
210 		return ROUNDUP(key->sec_size, 16);
211 	case CAAM_KEY_BLACK_CCM:
212 		/*
213 		 * CCM-black key must be a multiple of 8 bytes. The nonce and
214 		 * ICV add another 12 bytes to the allocation size
215 		 */
216 		return ROUNDUP(key->sec_size, 8) + BLACK_KEY_NONCE_SIZE +
217 		       BLACK_KEY_ICV_SIZE;
218 	default:
219 		return 0;
220 	}
221 }
222 
223 void caam_key_dump(const char *trace, const struct caamkey *key)
224 {
225 	if (!key || !trace)
226 		return;
227 
228 	if (key->key_type >= CAAM_KEY_MAX_VALUE)
229 		return;
230 
231 	KEY_TRACE("%s key_type:%s key_size:%zu is_blob:%s addr:%p",
232 		  caam_key_type_to_str[key->key_type], trace, key->sec_size,
233 		  key->is_blob ? "yes" : "no", key->buf.data);
234 
235 	if (key->buf.data)
236 		KEY_DUMPBUF("Key data", key->buf.data, key->buf.length);
237 }
238 
239 enum caam_status caam_key_alloc(struct caamkey *key)
240 {
241 	size_t alloc_size = 0;
242 
243 	if (!key)
244 		return CAAM_BAD_PARAM;
245 
246 	if (key->buf.data) {
247 		KEY_TRACE("Key already allocated");
248 		return CAAM_BAD_PARAM;
249 	}
250 
251 	alloc_size = caam_key_get_alloc_size(key);
252 	if (!alloc_size)
253 		return CAAM_FAILURE;
254 
255 	return caam_calloc_align_buf(&key->buf, alloc_size);
256 }
257 
258 void caam_key_free(struct caamkey *key)
259 {
260 	if (!key)
261 		return;
262 
263 	caam_free_buf(&key->buf);
264 }
265 
266 void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key)
267 {
268 	if (!key)
269 		return;
270 
271 	if (!key->buf.nocache)
272 		cache_operation(op, key->buf.data, key->buf.length);
273 }
274 
275 #define BLOB_OP_DESC_ENTRIES 12
276 enum caam_status caam_key_operation_blob(const struct caamkey *in_key,
277 					 struct caamkey *out_key)
278 {
279 	enum caam_status status = CAAM_FAILURE;
280 	struct caam_jobctx jobctx = { };
281 	uint32_t opflag = PROT_BLOB_TYPE(BLACK_KEY);
282 	uint32_t *desc = NULL;
283 	size_t output_buffer_size = 0;
284 	size_t input_buffer_size = 0;
285 
286 	assert(in_key && out_key);
287 
288 	KEY_TRACE("Blob %scapsulation of the following key",
289 		  in_key->is_blob ? "de" : "en");
290 
291 	caam_key_dump("Blob input key", in_key);
292 
293 	/* This function blobs or un-blobs */
294 	if (in_key->is_blob == out_key->is_blob) {
295 		KEY_TRACE("Only one key must be defined as a blob");
296 		return CAAM_BAD_PARAM;
297 	}
298 
299 	/* A black blob cannot take a plain test key as input */
300 	if (out_key->key_type == CAAM_KEY_PLAIN_TEXT ||
301 	    in_key->key_type == CAAM_KEY_PLAIN_TEXT) {
302 		KEY_TRACE("A blob in/out operation cannot be plain text");
303 		return CAAM_BAD_PARAM;
304 	}
305 
306 	/* The key type must remain the same */
307 	if (out_key->key_type != in_key->key_type) {
308 		KEY_TRACE("The in/out keys must have the same key type");
309 		return CAAM_BAD_PARAM;
310 	}
311 
312 	/* Define blob operation direction */
313 	if (out_key->is_blob)
314 		opflag |= BLOB_ENCAPS;
315 	else
316 		opflag |= BLOB_DECAPS;
317 
318 	/* Build OP flags depending on the blob type */
319 	switch (out_key->key_type) {
320 	case CAAM_KEY_BLACK_ECB:
321 		opflag |= PROT_BLOB_INFO(ECB);
322 		break;
323 	case CAAM_KEY_BLACK_CCM:
324 		opflag |= PROT_BLOB_INFO(CCM);
325 		break;
326 	default:
327 		return CAAM_BAD_PARAM;
328 	}
329 
330 	/* Allocate the descriptor */
331 	desc = caam_calloc_desc(BLOB_OP_DESC_ENTRIES);
332 	if (!desc) {
333 		KEY_TRACE("CAAM Context Descriptor Allocation error");
334 		return CAAM_OUT_MEMORY;
335 	}
336 
337 	status = caam_key_alloc(out_key);
338 	if (status) {
339 		KEY_TRACE("Key output allocation error");
340 		goto err;
341 	}
342 
343 	/* Define input and output buffer size */
344 	if (out_key->is_blob) {
345 		/*
346 		 * For a blob operation, the input key size is the original key
347 		 * size of the black key.
348 		 * The output key size is the final blob size.
349 		 */
350 		input_buffer_size = in_key->sec_size;
351 		output_buffer_size = out_key->buf.length;
352 	} else {
353 		/*
354 		 * For an non-blob operation, the input key size is the original
355 		 * key size of the black key.
356 		 * The output key size is the key security size.
357 		 */
358 		input_buffer_size = in_key->buf.length;
359 		output_buffer_size = out_key->sec_size;
360 	}
361 
362 	/* Create the blob encapsulation/decapsulation descriptor */
363 	caam_desc_init(desc);
364 	caam_desc_add_word(desc, DESC_HEADER(0));
365 
366 	/* Load the key modifier */
367 	caam_desc_add_word(desc,
368 			   LD_NOIMM(CLASS_2, REG_KEY, KEY_BLOB_MODIFIER_SIZE));
369 	caam_desc_add_ptr(desc, virt_to_phys((void *)key_blob_modifier));
370 
371 	/* Define the Input data sequence */
372 	caam_desc_add_word(desc, SEQ_IN_PTR(input_buffer_size));
373 	caam_desc_add_ptr(desc, in_key->buf.paddr);
374 
375 	/* Define the Output data sequence */
376 	caam_desc_add_word(desc, SEQ_OUT_PTR(output_buffer_size));
377 	caam_desc_add_ptr(desc, out_key->buf.paddr);
378 	caam_desc_add_word(desc, opflag);
379 
380 	KEY_DUMPDESC(desc);
381 
382 	caam_key_cache_op(TEE_CACHECLEAN, in_key);
383 	caam_key_cache_op(TEE_CACHECLEAN, out_key);
384 
385 	jobctx.desc = desc;
386 	status = caam_jr_enqueue(&jobctx, NULL);
387 
388 	if (status == CAAM_NO_ERROR) {
389 		KEY_TRACE("CAAM Blob %scapsulation Done",
390 			  out_key->is_blob ? "En" : "De");
391 
392 		caam_key_cache_op(TEE_CACHEINVALIDATE, out_key);
393 		caam_key_dump("Blob output key", out_key);
394 
395 		goto out;
396 	} else {
397 		KEY_TRACE("CAAM Blob Status 0x%08" PRIx32 "", jobctx.status);
398 	}
399 
400 err:
401 	caam_key_free(out_key);
402 out:
403 	caam_free_desc(&desc);
404 	return status;
405 }
406 
407 enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size,
408 					       struct caamkey *key,
409 					       size_t sec_size)
410 {
411 	enum caam_status status = CAAM_FAILURE;
412 	struct caamkey blob = { };
413 
414 	assert(data && size && key);
415 
416 	KEY_TRACE("Deserialization binary buffer");
417 	KEY_DUMPBUF("Deserialize key buffer input", data, size);
418 
419 	/*
420 	 * If a security key size is given, use it. Otherwise, rely on
421 	 * the buffer size.
422 	 * In some case, like ECC keys, the bignum size is less than the
423 	 * security size and it requires the key to be padded with 0's.
424 	 */
425 	if (sec_size == 0)
426 		sec_size = get_key_sec_size(data, size);
427 
428 	blob.key_type = get_key_type(data, size);
429 	blob.sec_size = sec_size;
430 	blob.is_blob = true;
431 
432 	if (blob.key_type == CAAM_KEY_PLAIN_TEXT) {
433 		key->sec_size = blob.sec_size;
434 		key->key_type = blob.key_type;
435 		key->is_blob = false;
436 
437 		status = caam_key_alloc(key);
438 		if (status) {
439 			KEY_TRACE("Key allocation error");
440 			return status;
441 		}
442 
443 		/* Some asymmetric keys have leading zeros we must preserve */
444 		memcpy(key->buf.data + key->buf.length - size, data, size);
445 
446 		return CAAM_NO_ERROR;
447 	}
448 
449 	status = caam_key_alloc(&blob);
450 	if (status) {
451 		KEY_TRACE("Key allocation error");
452 		return status;
453 	}
454 
455 	memcpy(blob.buf.data, data + get_key_buf_offset(data, size),
456 	       get_key_buf_size(data, size));
457 
458 	/* Set destination key */
459 	key->key_type = blob.key_type;
460 	key->sec_size = blob.sec_size;
461 	key->is_blob = false;
462 
463 	/* De-blob operation */
464 	status = caam_key_operation_blob(&blob, key);
465 	if (status) {
466 		KEY_TRACE("De-blob operation fail");
467 		goto out;
468 	}
469 
470 	KEY_TRACE("Deserialization binary buffer done");
471 	caam_key_dump("Deserialization output key", key);
472 out:
473 	caam_key_free(&blob);
474 	return status;
475 }
476 
477 enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size,
478 					   const struct caamkey *key)
479 {
480 	struct caam_key_serialized key_ser = { };
481 	struct caamkey blob = { };
482 	enum caam_status status = CAAM_FAILURE;
483 	size_t serialized_size = 0;
484 
485 	assert(data && size && key);
486 
487 	caam_key_dump("Serialization input key", key);
488 
489 	/* If the key is plain text, just copy key to buffer */
490 	if (key->key_type == CAAM_KEY_PLAIN_TEXT) {
491 		if (size < key->buf.length) {
492 			KEY_TRACE("Buffer is too short");
493 			return CAAM_SHORT_BUFFER;
494 		}
495 
496 		memcpy(data, key->buf.data, key->buf.length);
497 
498 		return CAAM_NO_ERROR;
499 	}
500 
501 	/* The input key must not be a blob */
502 	assert(!key->is_blob);
503 
504 	/* Blob the given key for serialization and export */
505 	blob.is_blob = true;
506 	blob.sec_size = key->sec_size;
507 	blob.key_type = key->key_type;
508 
509 	/*
510 	 * Check if the destination is big enough for the black blob buffer and
511 	 * header.
512 	 */
513 	status = caam_key_serialized_size(&blob, &serialized_size);
514 	if (status)
515 		return status;
516 
517 	if (size < serialized_size) {
518 		KEY_TRACE("Destination buffer is too short %zu < %zu", size,
519 			  serialized_size);
520 		return CAAM_OUT_MEMORY;
521 	}
522 
523 	/* Blob the given key */
524 	status = caam_key_operation_blob(key, &blob);
525 	if (status) {
526 		KEY_TRACE("Blob operation fail");
527 		return status;
528 	}
529 
530 	/* Copy the header to destination */
531 	key_ser.magic_number = MAGIC_NUMBER;
532 	key_ser.key_type = blob.key_type;
533 	key_ser.sec_size = blob.sec_size;
534 	memcpy(data, &key_ser, sizeof(key_ser));
535 
536 	/* Copy the key buffer */
537 	memcpy(data + sizeof(key_ser), blob.buf.data, blob.buf.length);
538 
539 	KEY_DUMPBUF("Key data", data, size);
540 
541 	caam_key_free(&blob);
542 
543 	return status;
544 }
545 
546 enum caam_status caam_key_serialized_size(const struct caamkey *key,
547 					  size_t *size)
548 {
549 	assert(key && size);
550 
551 	/* For a plain text key, the serialized key is identical to the key */
552 	*size = key->buf.length;
553 
554 	/*
555 	 * For black keys, the serialized key includes the header and must be
556 	 * in a blob format
557 	 */
558 	if (key->key_type != CAAM_KEY_PLAIN_TEXT) {
559 		size_t alloc = 0;
560 		const struct caamkey tmp = {
561 			.key_type = key->key_type,
562 			.sec_size = key->sec_size,
563 			.is_blob = true,
564 		};
565 
566 		alloc = caam_key_get_alloc_size(&tmp);
567 		if (!alloc)
568 			return CAAM_FAILURE;
569 
570 		*size = alloc + sizeof(struct caam_key_serialized);
571 	}
572 
573 	return CAAM_NO_ERROR;
574 }
575 
576 enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey,
577 					      struct caamkey *outkey,
578 					      size_t size_sec)
579 {
580 	enum caam_status status = CAAM_FAILURE;
581 	uint8_t *buf = NULL;
582 	size_t size = 0;
583 
584 	assert(inkey && outkey);
585 
586 	KEY_TRACE("Deserialization bignum");
587 
588 	/* Get bignum size */
589 	size = crypto_bignum_num_bytes((struct bignum *)inkey);
590 
591 	/* Allocate temporary buffer */
592 	buf = caam_calloc(size);
593 	if (!buf)
594 		return CAAM_OUT_MEMORY;
595 
596 	/* Convert bignum to binary */
597 	crypto_bignum_bn2bin(inkey, buf);
598 
599 	status = caam_key_deserialize_from_bin(buf, size, outkey, size_sec);
600 
601 	caam_key_dump("Output key", outkey);
602 
603 	caam_free(buf);
604 
605 	return status;
606 }
607 
608 enum caam_status caam_key_serialize_to_bn(struct bignum *outkey,
609 					  const struct caamkey *inkey)
610 {
611 	enum caam_status status = CAAM_FAILURE;
612 	TEE_Result res = TEE_ERROR_GENERIC;
613 	uint8_t *buf = NULL;
614 	size_t size = 0;
615 
616 	assert(inkey && outkey);
617 
618 	KEY_TRACE("Serialization bignum");
619 	caam_key_dump("Input key", inkey);
620 
621 	status = caam_key_serialized_size(inkey, &size);
622 	if (status)
623 		return status;
624 
625 	buf = caam_calloc(size);
626 	if (!buf)
627 		return CAAM_OUT_MEMORY;
628 
629 	status = caam_key_serialize_to_bin(buf, size, inkey);
630 	if (status)
631 		goto out;
632 
633 	res = crypto_bignum_bin2bn(buf, size, outkey);
634 	if (res)
635 		status = CAAM_FAILURE;
636 out:
637 	caam_free(buf);
638 
639 	return status;
640 }
641 
642 #define MAX_DESC_ENTRIES 22
643 enum caam_status caam_key_black_encapsulation(struct caamkey *key,
644 					      enum caam_key_type key_type)
645 {
646 	enum caam_status status = CAAM_FAILURE;
647 	struct caambuf input_buf = { };
648 	struct caam_jobctx jobctx = { };
649 	uint32_t *desc = NULL;
650 
651 	assert(key);
652 	assert(!key->is_blob && key->key_type == CAAM_KEY_PLAIN_TEXT);
653 	assert(key_type != CAAM_KEY_PLAIN_TEXT);
654 
655 	KEY_TRACE("Black key encapsulation");
656 
657 	/* Copy input plain text key to temp buffer */
658 	status = caam_calloc_align_buf(&input_buf, key->buf.length);
659 	if (status)
660 		return status;
661 
662 	memcpy(input_buf.data, key->buf.data, key->buf.length);
663 	cache_operation(TEE_CACHEFLUSH, input_buf.data, input_buf.length);
664 
665 	/* Re-allocate the output key for black format */
666 	caam_key_free(key);
667 	key->key_type = key_type;
668 
669 	status = caam_key_alloc(key);
670 	if (status)
671 		goto out;
672 
673 	/* Allocate the descriptor */
674 	desc = caam_calloc_desc(MAX_DESC_ENTRIES);
675 	if (!desc) {
676 		KEY_TRACE("Allocation descriptor error");
677 		status = CAAM_OUT_MEMORY;
678 		goto out;
679 	}
680 
681 	caam_key_dump("Input key", key);
682 
683 	caam_desc_init(desc);
684 	caam_desc_add_word(desc, DESC_HEADER(0));
685 	caam_desc_add_word(desc, LD_KEY(CLASS_1, PKHA_E, key->sec_size));
686 	caam_desc_add_ptr(desc, input_buf.paddr);
687 
688 	switch (key->key_type) {
689 	case CAAM_KEY_BLACK_ECB:
690 		caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_ECB_JKEK,
691 						 key->sec_size));
692 		break;
693 	case CAAM_KEY_BLACK_CCM:
694 		caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_CCM_JKEK,
695 						 key->sec_size));
696 		break;
697 	default:
698 		status = CAAM_FAILURE;
699 		goto out;
700 	}
701 
702 	caam_desc_add_ptr(desc, key->buf.paddr);
703 
704 	KEY_DUMPDESC(desc);
705 
706 	caam_key_cache_op(TEE_CACHEFLUSH, key);
707 
708 	jobctx.desc = desc;
709 	status = caam_jr_enqueue(&jobctx, NULL);
710 	if (status != CAAM_NO_ERROR) {
711 		KEY_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32, status,
712 			  jobctx.status);
713 		status = CAAM_FAILURE;
714 		goto out;
715 	}
716 
717 	caam_key_cache_op(TEE_CACHEINVALIDATE, key);
718 
719 	caam_key_dump("Output Key", key);
720 
721 out:
722 	caam_free_buf(&input_buf);
723 	caam_free_desc(&desc);
724 
725 	return status;
726 }
727 
728 enum caam_status caam_key_init(void)
729 {
730 	size_t alloc_size = 0;
731 	const struct caamkey key = {
732 		.key_type = caam_key_default_key_gen_type(),
733 		.sec_size = 4096, /* Max RSA key size */
734 		.is_blob = true,
735 	};
736 
737 	/*
738 	 * Ensure bignum format maximum size is enough to store a black key
739 	 * blob. The largest key is a 4096 bits RSA key pair.
740 	 */
741 	if (caam_key_serialized_size(&key, &alloc_size))
742 		return CAAM_FAILURE;
743 
744 	assert(alloc_size <= CFG_CORE_BIGNUM_MAX_BITS);
745 
746 	KEY_TRACE("Max serialized key size %zu", alloc_size);
747 
748 	KEY_TRACE("Default CAAM key generation type %s",
749 		  caam_key_type_to_str[caam_key_default_key_gen_type()]);
750 
751 	return CAAM_NO_ERROR;
752 }
753