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