11495f6c4SClement Faure // SPDX-License-Identifier: BSD-2-Clause
21495f6c4SClement Faure /*
3*116d03abSSahil Malhotra * Copyright 2023-2024 NXP
41495f6c4SClement Faure */
51495f6c4SClement Faure #include <assert.h>
61495f6c4SClement Faure #include <caam_desc_helper.h>
71495f6c4SClement Faure #include <caam_key.h>
81495f6c4SClement Faure #include <caam_status.h>
91495f6c4SClement Faure #include <caam_trace.h>
101495f6c4SClement Faure #include <caam_utils_mem.h>
111495f6c4SClement Faure #include <crypto/crypto.h>
121495f6c4SClement Faure #include <kernel/panic.h>
131495f6c4SClement Faure #include <mm/core_memprot.h>
141495f6c4SClement Faure #include <stdint.h>
151495f6c4SClement Faure #include <string.h>
161495f6c4SClement Faure #include <tee/cache.h>
171495f6c4SClement Faure #include <tee_api_defines.h>
181495f6c4SClement Faure #include <trace.h>
191495f6c4SClement Faure #include <utee_types.h>
201495f6c4SClement Faure
211495f6c4SClement Faure /*
221495f6c4SClement Faure * CAAM Key magic number.
231495f6c4SClement Faure * When the first 32 bits of a key buffer are equal to this value, the buffer
241495f6c4SClement Faure * is a serialized CAAM key structure.
251495f6c4SClement Faure */
261495f6c4SClement Faure #define MAGIC_NUMBER 0xCAAFBFFB
271495f6c4SClement Faure
281495f6c4SClement Faure /*
291495f6c4SClement Faure * Because the CAAM driver relies on this magic number to determine if the key
301495f6c4SClement Faure * is plain text or black, collision can happen. A randomly generated plain text
311495f6c4SClement Faure * key could feature the magic number. That's unlikely but still possible.
321495f6c4SClement Faure *
331495f6c4SClement Faure * Regarding the possibility of collision or forging attack, there are no
341495f6c4SClement Faure * security concerns. Forging and trying to make a plain text key look like a
351495f6c4SClement Faure * black key, won't do much. If the key is forged to look like an ECB Black
361495f6c4SClement Faure * key, the singing operation will output a corrupted result. If the key is
371495f6c4SClement Faure * forged to look like a CCM Black key, the import key will fail (because the
381495f6c4SClement Faure * MAC verification) and no signing operation will be done.
391495f6c4SClement Faure */
401495f6c4SClement Faure
411495f6c4SClement Faure #define BLOB_BKEK_SIZE 32 /* Blob key encryption key size */
421495f6c4SClement Faure #define BLOB_MAC_SIZE 16 /* Blob MAC size */
431495f6c4SClement Faure #define BLOB_PAD_SIZE (BLOB_BKEK_SIZE + BLOB_MAC_SIZE)
441495f6c4SClement Faure
451495f6c4SClement Faure /*
461495f6c4SClement Faure * CAAM Blob key modifier
471495f6c4SClement Faure * Key modifier used to derive Blob-key encryption key (BKEK) from the CAAM
481495f6c4SClement Faure * master key.
491495f6c4SClement Faure *
501495f6c4SClement Faure * A CAAM black key is encrypted using a volatile Job Descriptor key encryption
511495f6c4SClement Faure * key or JDKEK. Black keys are not intended for storage of keys across SoC
521495f6c4SClement Faure * power cycles. The JDKEK is re-generated upon every power cycle (reset,
531495f6c4SClement Faure * suspend/resume ...) or CAAM RNG re-seed.
541495f6c4SClement Faure *
551495f6c4SClement Faure * To retain key across power cycles, the black key must be encapsulated as a
561495f6c4SClement Faure * blob. The blob key encryption key is derived from the CAAM master key which
571495f6c4SClement Faure * makes it non-volatile and can be re-created when the chip powers up again.
581495f6c4SClement Faure */
591495f6c4SClement Faure #define KEY_BLOB_MODIFIER_SIZE 16
60*116d03abSSahil Malhotra #define KEY_BLOB_MODIFIER "NXP_KEY_MODIFIER"
61*116d03abSSahil Malhotra static_assert(sizeof(KEY_BLOB_MODIFIER) >= KEY_BLOB_MODIFIER_SIZE);
62*116d03abSSahil Malhotra static uint8_t *key_blob_modifier;
631495f6c4SClement Faure
641495f6c4SClement Faure /*
651495f6c4SClement Faure * Serialized CAAM key structure format.
661495f6c4SClement Faure *
671495f6c4SClement Faure * If the incoming key buffer is the following:
681495f6c4SClement Faure * | Magic number | key type | key size | key blob buffer |
691495f6c4SClement Faure * The CAAM Key structure will be populated as following:
701495f6c4SClement Faure * struct caamkey {
711495f6c4SClement Faure * .key_type = key type,
721495f6c4SClement Faure * .key_size = key size,
731495f6c4SClement Faure * .is_blob = true,
741495f6c4SClement Faure * .buf = key blob buffer
751495f6c4SClement Faure * }
761495f6c4SClement Faure *
771495f6c4SClement Faure * If the incoming key buffer is the following:
781495f6c4SClement Faure * | Key buffer |
791495f6c4SClement Faure * The CAAM Key structure will be populated as following:
801495f6c4SClement Faure * struct caamkey {
811495f6c4SClement Faure * .key_type = CAAM_KEY_PLAIN_TEXT,
821495f6c4SClement Faure * .key_size = sizeof(Key buffer),
831495f6c4SClement Faure * .is_blob = false,
841495f6c4SClement Faure * .buf = key buffer
851495f6c4SClement Faure * }
861495f6c4SClement Faure */
871495f6c4SClement Faure struct caam_key_serialized {
881495f6c4SClement Faure uint32_t magic_number; /* Magic number */
891495f6c4SClement Faure uint32_t key_type; /* Black key type */
901495f6c4SClement Faure uint32_t sec_size; /* The original plain text key size */
911495f6c4SClement Faure uint8_t key[];
921495f6c4SClement Faure };
931495f6c4SClement Faure
941495f6c4SClement Faure /*
951495f6c4SClement Faure * CAAM key type enumeration to string
961495f6c4SClement Faure */
971495f6c4SClement Faure static const char *const caam_key_type_to_str[] __maybe_unused = {
981495f6c4SClement Faure [CAAM_KEY_PLAIN_TEXT] = "Plain Text",
991495f6c4SClement Faure [CAAM_KEY_BLACK_ECB] = "Black ECB",
1001495f6c4SClement Faure [CAAM_KEY_BLACK_CCM] = "Black CCM",
1011495f6c4SClement Faure };
1021495f6c4SClement Faure
data_to_serialized_key(const uint8_t * data,size_t size)1031495f6c4SClement Faure static struct caam_key_serialized *data_to_serialized_key(const uint8_t *data,
1041495f6c4SClement Faure size_t size)
1051495f6c4SClement Faure {
1061495f6c4SClement Faure assert(data && size);
1071495f6c4SClement Faure assert(size > sizeof(struct caam_key_serialized));
1081495f6c4SClement Faure
1091495f6c4SClement Faure /*
1101495f6c4SClement Faure * It's important to make sure uint8_t and caam_key_serialized{} are
1111495f6c4SClement Faure * actually aligned for performance purpose.
1121495f6c4SClement Faure *
1131495f6c4SClement Faure * A __packed attribute to caam_key_serialized{} could solve the
1141495f6c4SClement Faure * alignment issue but at the cost of un-optimize memory access.
1151495f6c4SClement Faure * To avoid using the __packed attribute, caam_key_serialized{} is
1161495f6c4SClement Faure * defined to be aligned on uint8_t. The following assert checks
1171495f6c4SClement Faure * for this alignment.
1181495f6c4SClement Faure */
1191495f6c4SClement Faure assert(IS_ALIGNED_WITH_TYPE(data, struct caam_key_serialized));
1201495f6c4SClement Faure
1211495f6c4SClement Faure /*
1221495f6c4SClement Faure * The cast to void* instead of struct caam_key_serialized* is needed
1231495f6c4SClement Faure * to avoid the cast alignment compilation warning.
1241495f6c4SClement Faure */
1251495f6c4SClement Faure return (void *)data;
1261495f6c4SClement Faure }
1271495f6c4SClement Faure
1281495f6c4SClement Faure /*
1291495f6c4SClement Faure * Return the CAAM key type of the given key buffer
1301495f6c4SClement Faure *
1311495f6c4SClement Faure * @data Input buffer
1321495f6c4SClement Faure * @size Input buffer size
1331495f6c4SClement Faure */
get_key_type(const uint8_t * data,size_t size)1341495f6c4SClement Faure static enum caam_key_type get_key_type(const uint8_t *data, size_t size)
1351495f6c4SClement Faure {
1361495f6c4SClement Faure struct caam_key_serialized *key = data_to_serialized_key(data, size);
1371495f6c4SClement Faure
1381495f6c4SClement Faure if (key->magic_number != MAGIC_NUMBER)
1391495f6c4SClement Faure return CAAM_KEY_PLAIN_TEXT;
1401495f6c4SClement Faure
1411495f6c4SClement Faure return key->key_type;
1421495f6c4SClement Faure }
1431495f6c4SClement Faure
1441495f6c4SClement Faure /*
1451495f6c4SClement Faure * Return the CAAM key size of the given key buffer
1461495f6c4SClement Faure *
1471495f6c4SClement Faure * @data Input buffer
1481495f6c4SClement Faure * @size Input buffer size
1491495f6c4SClement Faure */
get_key_sec_size(const uint8_t * data,size_t size)1501495f6c4SClement Faure static size_t get_key_sec_size(const uint8_t *data, size_t size)
1511495f6c4SClement Faure {
1521495f6c4SClement Faure struct caam_key_serialized *key = data_to_serialized_key(data, size);
1531495f6c4SClement Faure
1541495f6c4SClement Faure if (key->magic_number != MAGIC_NUMBER)
1551495f6c4SClement Faure return size;
1561495f6c4SClement Faure
1571495f6c4SClement Faure return key->sec_size;
1581495f6c4SClement Faure }
1591495f6c4SClement Faure
1601495f6c4SClement Faure /*
1611495f6c4SClement Faure * Return the CAAM key buffer pointer of the given key buffer
1621495f6c4SClement Faure *
1631495f6c4SClement Faure * @data Input buffer
1641495f6c4SClement Faure * @size Input buffer size
1651495f6c4SClement Faure */
get_key_buf_offset(const uint8_t * data,size_t size)1661495f6c4SClement Faure static unsigned long get_key_buf_offset(const uint8_t *data, size_t size)
1671495f6c4SClement Faure {
1681495f6c4SClement Faure struct caam_key_serialized *key = data_to_serialized_key(data, size);
1691495f6c4SClement Faure
1701495f6c4SClement Faure if (key->magic_number != MAGIC_NUMBER)
1711495f6c4SClement Faure return 0;
1721495f6c4SClement Faure else
1731495f6c4SClement Faure return offsetof(struct caam_key_serialized, key);
1741495f6c4SClement Faure }
1751495f6c4SClement Faure
1761495f6c4SClement Faure /*
1771495f6c4SClement Faure * Return the CAAM key buffer size of the given key buffer
1781495f6c4SClement Faure *
1791495f6c4SClement Faure * @data Input buffer
1801495f6c4SClement Faure * @size Input buffer size
1811495f6c4SClement Faure */
get_key_buf_size(const uint8_t * data,size_t size)1821495f6c4SClement Faure static size_t get_key_buf_size(const uint8_t *data, size_t size)
1831495f6c4SClement Faure {
1841495f6c4SClement Faure struct caam_key_serialized *key = data_to_serialized_key(data, size);
1851495f6c4SClement Faure
1861495f6c4SClement Faure /*
1871495f6c4SClement Faure * In the caam_key_serialized{}, the last element of the structure is
1881495f6c4SClement Faure * a variable-sized buffer.
1891495f6c4SClement Faure */
1901495f6c4SClement Faure return size - sizeof(*key);
1911495f6c4SClement Faure }
1921495f6c4SClement Faure
caam_key_get_alloc_size(const struct caamkey * key)1931495f6c4SClement Faure size_t caam_key_get_alloc_size(const struct caamkey *key)
1941495f6c4SClement Faure {
1951495f6c4SClement Faure if (!key)
1961495f6c4SClement Faure return 0;
1971495f6c4SClement Faure
1981495f6c4SClement Faure /* A blob size is independent from the key encryption algorithm */
1991495f6c4SClement Faure if (key->is_blob)
2001495f6c4SClement Faure return key->sec_size + BLOB_PAD_SIZE;
2011495f6c4SClement Faure
2021495f6c4SClement Faure switch (key->key_type) {
2031495f6c4SClement Faure case CAAM_KEY_PLAIN_TEXT:
2041495f6c4SClement Faure /*
2051495f6c4SClement Faure * If the key is plain text, the allocation size is equal to the
2061495f6c4SClement Faure * key size and no blob operation on this key is possible.
2071495f6c4SClement Faure */
2081495f6c4SClement Faure return key->sec_size;
2091495f6c4SClement Faure case CAAM_KEY_BLACK_ECB:
2101495f6c4SClement Faure /* ECB-black key must be a multiple of 16 bytes */
2111495f6c4SClement Faure return ROUNDUP(key->sec_size, 16);
2121495f6c4SClement Faure case CAAM_KEY_BLACK_CCM:
2131495f6c4SClement Faure /*
2141495f6c4SClement Faure * CCM-black key must be a multiple of 8 bytes. The nonce and
2151495f6c4SClement Faure * ICV add another 12 bytes to the allocation size
2161495f6c4SClement Faure */
2171495f6c4SClement Faure return ROUNDUP(key->sec_size, 8) + BLACK_KEY_NONCE_SIZE +
2181495f6c4SClement Faure BLACK_KEY_ICV_SIZE;
2191495f6c4SClement Faure default:
2201495f6c4SClement Faure return 0;
2211495f6c4SClement Faure }
2221495f6c4SClement Faure }
2231495f6c4SClement Faure
caam_key_dump(const char * trace,const struct caamkey * key)2241495f6c4SClement Faure void caam_key_dump(const char *trace, const struct caamkey *key)
2251495f6c4SClement Faure {
2261495f6c4SClement Faure if (!key || !trace)
2271495f6c4SClement Faure return;
2281495f6c4SClement Faure
2291495f6c4SClement Faure if (key->key_type >= CAAM_KEY_MAX_VALUE)
2301495f6c4SClement Faure return;
2311495f6c4SClement Faure
2321495f6c4SClement Faure KEY_TRACE("%s key_type:%s key_size:%zu is_blob:%s addr:%p",
2331495f6c4SClement Faure caam_key_type_to_str[key->key_type], trace, key->sec_size,
2341495f6c4SClement Faure key->is_blob ? "yes" : "no", key->buf.data);
2351495f6c4SClement Faure
2361495f6c4SClement Faure if (key->buf.data)
2371495f6c4SClement Faure KEY_DUMPBUF("Key data", key->buf.data, key->buf.length);
2381495f6c4SClement Faure }
2391495f6c4SClement Faure
caam_key_alloc(struct caamkey * key)2401495f6c4SClement Faure enum caam_status caam_key_alloc(struct caamkey *key)
2411495f6c4SClement Faure {
2421495f6c4SClement Faure size_t alloc_size = 0;
2431495f6c4SClement Faure
2441495f6c4SClement Faure if (!key)
2451495f6c4SClement Faure return CAAM_BAD_PARAM;
2461495f6c4SClement Faure
2471495f6c4SClement Faure if (key->buf.data) {
2481495f6c4SClement Faure KEY_TRACE("Key already allocated");
2491495f6c4SClement Faure return CAAM_BAD_PARAM;
2501495f6c4SClement Faure }
2511495f6c4SClement Faure
2521495f6c4SClement Faure alloc_size = caam_key_get_alloc_size(key);
2531495f6c4SClement Faure if (!alloc_size)
2541495f6c4SClement Faure return CAAM_FAILURE;
2551495f6c4SClement Faure
2561495f6c4SClement Faure return caam_calloc_align_buf(&key->buf, alloc_size);
2571495f6c4SClement Faure }
2581495f6c4SClement Faure
caam_key_free(struct caamkey * key)2591495f6c4SClement Faure void caam_key_free(struct caamkey *key)
2601495f6c4SClement Faure {
2611495f6c4SClement Faure if (!key)
2621495f6c4SClement Faure return;
2631495f6c4SClement Faure
2641495f6c4SClement Faure caam_free_buf(&key->buf);
2651495f6c4SClement Faure }
2661495f6c4SClement Faure
caam_key_cache_op(enum utee_cache_operation op,const struct caamkey * key)2671495f6c4SClement Faure void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key)
2681495f6c4SClement Faure {
2691495f6c4SClement Faure if (!key)
2701495f6c4SClement Faure return;
2711495f6c4SClement Faure
2721495f6c4SClement Faure if (!key->buf.nocache)
2731495f6c4SClement Faure cache_operation(op, key->buf.data, key->buf.length);
2741495f6c4SClement Faure }
2751495f6c4SClement Faure
2761495f6c4SClement Faure #define BLOB_OP_DESC_ENTRIES 12
caam_key_operation_blob(const struct caamkey * in_key,struct caamkey * out_key)2771495f6c4SClement Faure enum caam_status caam_key_operation_blob(const struct caamkey *in_key,
2781495f6c4SClement Faure struct caamkey *out_key)
2791495f6c4SClement Faure {
2801495f6c4SClement Faure enum caam_status status = CAAM_FAILURE;
2811495f6c4SClement Faure struct caam_jobctx jobctx = { };
2821495f6c4SClement Faure uint32_t opflag = PROT_BLOB_TYPE(BLACK_KEY);
2831495f6c4SClement Faure uint32_t *desc = NULL;
2841495f6c4SClement Faure size_t output_buffer_size = 0;
2851495f6c4SClement Faure size_t input_buffer_size = 0;
2861495f6c4SClement Faure
2871495f6c4SClement Faure assert(in_key && out_key);
2881495f6c4SClement Faure
2891495f6c4SClement Faure KEY_TRACE("Blob %scapsulation of the following key",
2901495f6c4SClement Faure in_key->is_blob ? "de" : "en");
2911495f6c4SClement Faure
2921495f6c4SClement Faure caam_key_dump("Blob input key", in_key);
2931495f6c4SClement Faure
2941495f6c4SClement Faure /* This function blobs or un-blobs */
2951495f6c4SClement Faure if (in_key->is_blob == out_key->is_blob) {
2961495f6c4SClement Faure KEY_TRACE("Only one key must be defined as a blob");
2971495f6c4SClement Faure return CAAM_BAD_PARAM;
2981495f6c4SClement Faure }
2991495f6c4SClement Faure
3001495f6c4SClement Faure /* A black blob cannot take a plain test key as input */
3011495f6c4SClement Faure if (out_key->key_type == CAAM_KEY_PLAIN_TEXT ||
3021495f6c4SClement Faure in_key->key_type == CAAM_KEY_PLAIN_TEXT) {
3031495f6c4SClement Faure KEY_TRACE("A blob in/out operation cannot be plain text");
3041495f6c4SClement Faure return CAAM_BAD_PARAM;
3051495f6c4SClement Faure }
3061495f6c4SClement Faure
3071495f6c4SClement Faure /* The key type must remain the same */
3081495f6c4SClement Faure if (out_key->key_type != in_key->key_type) {
3091495f6c4SClement Faure KEY_TRACE("The in/out keys must have the same key type");
3101495f6c4SClement Faure return CAAM_BAD_PARAM;
3111495f6c4SClement Faure }
3121495f6c4SClement Faure
3131495f6c4SClement Faure /* Define blob operation direction */
3141495f6c4SClement Faure if (out_key->is_blob)
3151495f6c4SClement Faure opflag |= BLOB_ENCAPS;
3161495f6c4SClement Faure else
3171495f6c4SClement Faure opflag |= BLOB_DECAPS;
3181495f6c4SClement Faure
3191495f6c4SClement Faure /* Build OP flags depending on the blob type */
3201495f6c4SClement Faure switch (out_key->key_type) {
3211495f6c4SClement Faure case CAAM_KEY_BLACK_ECB:
3221495f6c4SClement Faure opflag |= PROT_BLOB_INFO(ECB);
3231495f6c4SClement Faure break;
3241495f6c4SClement Faure case CAAM_KEY_BLACK_CCM:
3251495f6c4SClement Faure opflag |= PROT_BLOB_INFO(CCM);
3261495f6c4SClement Faure break;
3271495f6c4SClement Faure default:
3281495f6c4SClement Faure return CAAM_BAD_PARAM;
3291495f6c4SClement Faure }
3301495f6c4SClement Faure
3311495f6c4SClement Faure /* Allocate the descriptor */
3321495f6c4SClement Faure desc = caam_calloc_desc(BLOB_OP_DESC_ENTRIES);
3331495f6c4SClement Faure if (!desc) {
3341495f6c4SClement Faure KEY_TRACE("CAAM Context Descriptor Allocation error");
3351495f6c4SClement Faure return CAAM_OUT_MEMORY;
3361495f6c4SClement Faure }
3371495f6c4SClement Faure
3381495f6c4SClement Faure status = caam_key_alloc(out_key);
3391495f6c4SClement Faure if (status) {
3401495f6c4SClement Faure KEY_TRACE("Key output allocation error");
3411495f6c4SClement Faure goto err;
3421495f6c4SClement Faure }
3431495f6c4SClement Faure
3441495f6c4SClement Faure /* Define input and output buffer size */
3451495f6c4SClement Faure if (out_key->is_blob) {
3461495f6c4SClement Faure /*
3471495f6c4SClement Faure * For a blob operation, the input key size is the original key
3481495f6c4SClement Faure * size of the black key.
3491495f6c4SClement Faure * The output key size is the final blob size.
3501495f6c4SClement Faure */
3511495f6c4SClement Faure input_buffer_size = in_key->sec_size;
3521495f6c4SClement Faure output_buffer_size = out_key->buf.length;
3531495f6c4SClement Faure } else {
3541495f6c4SClement Faure /*
3551495f6c4SClement Faure * For an non-blob operation, the input key size is the original
3561495f6c4SClement Faure * key size of the black key.
3571495f6c4SClement Faure * The output key size is the key security size.
3581495f6c4SClement Faure */
3591495f6c4SClement Faure input_buffer_size = in_key->buf.length;
3601495f6c4SClement Faure output_buffer_size = out_key->sec_size;
3611495f6c4SClement Faure }
3621495f6c4SClement Faure
3631495f6c4SClement Faure /* Create the blob encapsulation/decapsulation descriptor */
3641495f6c4SClement Faure caam_desc_init(desc);
3651495f6c4SClement Faure caam_desc_add_word(desc, DESC_HEADER(0));
3661495f6c4SClement Faure
3671495f6c4SClement Faure /* Load the key modifier */
3681495f6c4SClement Faure caam_desc_add_word(desc,
3691495f6c4SClement Faure LD_NOIMM(CLASS_2, REG_KEY, KEY_BLOB_MODIFIER_SIZE));
3701495f6c4SClement Faure caam_desc_add_ptr(desc, virt_to_phys((void *)key_blob_modifier));
3711495f6c4SClement Faure
3721495f6c4SClement Faure /* Define the Input data sequence */
3731495f6c4SClement Faure caam_desc_add_word(desc, SEQ_IN_PTR(input_buffer_size));
3741495f6c4SClement Faure caam_desc_add_ptr(desc, in_key->buf.paddr);
3751495f6c4SClement Faure
3761495f6c4SClement Faure /* Define the Output data sequence */
3771495f6c4SClement Faure caam_desc_add_word(desc, SEQ_OUT_PTR(output_buffer_size));
3781495f6c4SClement Faure caam_desc_add_ptr(desc, out_key->buf.paddr);
3791495f6c4SClement Faure caam_desc_add_word(desc, opflag);
3801495f6c4SClement Faure
3811495f6c4SClement Faure KEY_DUMPDESC(desc);
3821495f6c4SClement Faure
383*116d03abSSahil Malhotra cache_operation(TEE_CACHECLEAN, key_blob_modifier,
384*116d03abSSahil Malhotra KEY_BLOB_MODIFIER_SIZE);
3851495f6c4SClement Faure caam_key_cache_op(TEE_CACHECLEAN, in_key);
3861495f6c4SClement Faure caam_key_cache_op(TEE_CACHECLEAN, out_key);
3871495f6c4SClement Faure
3881495f6c4SClement Faure jobctx.desc = desc;
3891495f6c4SClement Faure status = caam_jr_enqueue(&jobctx, NULL);
3901495f6c4SClement Faure
3911495f6c4SClement Faure if (status == CAAM_NO_ERROR) {
3921495f6c4SClement Faure KEY_TRACE("CAAM Blob %scapsulation Done",
3931495f6c4SClement Faure out_key->is_blob ? "En" : "De");
3941495f6c4SClement Faure
3951495f6c4SClement Faure caam_key_cache_op(TEE_CACHEINVALIDATE, out_key);
3961495f6c4SClement Faure caam_key_dump("Blob output key", out_key);
3971495f6c4SClement Faure
3981495f6c4SClement Faure goto out;
3991495f6c4SClement Faure } else {
4001495f6c4SClement Faure KEY_TRACE("CAAM Blob Status 0x%08" PRIx32 "", jobctx.status);
4011495f6c4SClement Faure }
4021495f6c4SClement Faure
4031495f6c4SClement Faure err:
4041495f6c4SClement Faure caam_key_free(out_key);
4051495f6c4SClement Faure out:
4061495f6c4SClement Faure caam_free_desc(&desc);
4071495f6c4SClement Faure return status;
4081495f6c4SClement Faure }
4091495f6c4SClement Faure
caam_key_deserialize_from_bin(uint8_t * data,size_t size,struct caamkey * key,size_t sec_size)4101495f6c4SClement Faure enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size,
4111495f6c4SClement Faure struct caamkey *key,
4121495f6c4SClement Faure size_t sec_size)
4131495f6c4SClement Faure {
4141495f6c4SClement Faure enum caam_status status = CAAM_FAILURE;
4151495f6c4SClement Faure struct caamkey blob = { };
4161495f6c4SClement Faure
4171495f6c4SClement Faure assert(data && size && key);
4181495f6c4SClement Faure
4191495f6c4SClement Faure KEY_TRACE("Deserialization binary buffer");
4201495f6c4SClement Faure KEY_DUMPBUF("Deserialize key buffer input", data, size);
4211495f6c4SClement Faure
4221495f6c4SClement Faure /*
4231495f6c4SClement Faure * If a security key size is given, use it. Otherwise, rely on
4241495f6c4SClement Faure * the buffer size.
4251495f6c4SClement Faure * In some case, like ECC keys, the bignum size is less than the
4261495f6c4SClement Faure * security size and it requires the key to be padded with 0's.
4271495f6c4SClement Faure */
4281495f6c4SClement Faure if (sec_size == 0)
4291495f6c4SClement Faure sec_size = get_key_sec_size(data, size);
4301495f6c4SClement Faure
4311495f6c4SClement Faure blob.key_type = get_key_type(data, size);
4321495f6c4SClement Faure blob.sec_size = sec_size;
4331495f6c4SClement Faure blob.is_blob = true;
4341495f6c4SClement Faure
4351495f6c4SClement Faure if (blob.key_type == CAAM_KEY_PLAIN_TEXT) {
4361495f6c4SClement Faure key->sec_size = blob.sec_size;
4371495f6c4SClement Faure key->key_type = blob.key_type;
4381495f6c4SClement Faure key->is_blob = false;
4391495f6c4SClement Faure
4401495f6c4SClement Faure status = caam_key_alloc(key);
4411495f6c4SClement Faure if (status) {
4421495f6c4SClement Faure KEY_TRACE("Key allocation error");
4431495f6c4SClement Faure return status;
4441495f6c4SClement Faure }
4451495f6c4SClement Faure
4461495f6c4SClement Faure /* Some asymmetric keys have leading zeros we must preserve */
4471495f6c4SClement Faure memcpy(key->buf.data + key->buf.length - size, data, size);
4481495f6c4SClement Faure
4491495f6c4SClement Faure return CAAM_NO_ERROR;
4501495f6c4SClement Faure }
4511495f6c4SClement Faure
4521495f6c4SClement Faure status = caam_key_alloc(&blob);
4531495f6c4SClement Faure if (status) {
4541495f6c4SClement Faure KEY_TRACE("Key allocation error");
4551495f6c4SClement Faure return status;
4561495f6c4SClement Faure }
4571495f6c4SClement Faure
4581495f6c4SClement Faure memcpy(blob.buf.data, data + get_key_buf_offset(data, size),
4591495f6c4SClement Faure get_key_buf_size(data, size));
4601495f6c4SClement Faure
4611495f6c4SClement Faure /* Set destination key */
4621495f6c4SClement Faure key->key_type = blob.key_type;
4631495f6c4SClement Faure key->sec_size = blob.sec_size;
4641495f6c4SClement Faure key->is_blob = false;
4651495f6c4SClement Faure
4661495f6c4SClement Faure /* De-blob operation */
4671495f6c4SClement Faure status = caam_key_operation_blob(&blob, key);
4681495f6c4SClement Faure if (status) {
4691495f6c4SClement Faure KEY_TRACE("De-blob operation fail");
4701495f6c4SClement Faure goto out;
4711495f6c4SClement Faure }
4721495f6c4SClement Faure
4731495f6c4SClement Faure KEY_TRACE("Deserialization binary buffer done");
4741495f6c4SClement Faure caam_key_dump("Deserialization output key", key);
4751495f6c4SClement Faure out:
4761495f6c4SClement Faure caam_key_free(&blob);
4771495f6c4SClement Faure return status;
4781495f6c4SClement Faure }
4791495f6c4SClement Faure
caam_key_serialize_to_bin(uint8_t * data,size_t size,const struct caamkey * key)4801495f6c4SClement Faure enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size,
4811495f6c4SClement Faure const struct caamkey *key)
4821495f6c4SClement Faure {
4831495f6c4SClement Faure struct caam_key_serialized key_ser = { };
4841495f6c4SClement Faure struct caamkey blob = { };
4851495f6c4SClement Faure enum caam_status status = CAAM_FAILURE;
4861495f6c4SClement Faure size_t serialized_size = 0;
4871495f6c4SClement Faure
4881495f6c4SClement Faure assert(data && size && key);
4891495f6c4SClement Faure
4901495f6c4SClement Faure caam_key_dump("Serialization input key", key);
4911495f6c4SClement Faure
4921495f6c4SClement Faure /* If the key is plain text, just copy key to buffer */
4931495f6c4SClement Faure if (key->key_type == CAAM_KEY_PLAIN_TEXT) {
4941495f6c4SClement Faure if (size < key->buf.length) {
4951495f6c4SClement Faure KEY_TRACE("Buffer is too short");
4961495f6c4SClement Faure return CAAM_SHORT_BUFFER;
4971495f6c4SClement Faure }
4981495f6c4SClement Faure
4991495f6c4SClement Faure memcpy(data, key->buf.data, key->buf.length);
5001495f6c4SClement Faure
5011495f6c4SClement Faure return CAAM_NO_ERROR;
5021495f6c4SClement Faure }
5031495f6c4SClement Faure
5041495f6c4SClement Faure /* The input key must not be a blob */
5051495f6c4SClement Faure assert(!key->is_blob);
5061495f6c4SClement Faure
5071495f6c4SClement Faure /* Blob the given key for serialization and export */
5081495f6c4SClement Faure blob.is_blob = true;
5091495f6c4SClement Faure blob.sec_size = key->sec_size;
5101495f6c4SClement Faure blob.key_type = key->key_type;
5111495f6c4SClement Faure
5121495f6c4SClement Faure /*
5131495f6c4SClement Faure * Check if the destination is big enough for the black blob buffer and
5141495f6c4SClement Faure * header.
5151495f6c4SClement Faure */
5161495f6c4SClement Faure status = caam_key_serialized_size(&blob, &serialized_size);
5171495f6c4SClement Faure if (status)
5181495f6c4SClement Faure return status;
5191495f6c4SClement Faure
5201495f6c4SClement Faure if (size < serialized_size) {
5211495f6c4SClement Faure KEY_TRACE("Destination buffer is too short %zu < %zu", size,
5221495f6c4SClement Faure serialized_size);
5231495f6c4SClement Faure return CAAM_OUT_MEMORY;
5241495f6c4SClement Faure }
5251495f6c4SClement Faure
5261495f6c4SClement Faure /* Blob the given key */
5271495f6c4SClement Faure status = caam_key_operation_blob(key, &blob);
5281495f6c4SClement Faure if (status) {
5291495f6c4SClement Faure KEY_TRACE("Blob operation fail");
5301495f6c4SClement Faure return status;
5311495f6c4SClement Faure }
5321495f6c4SClement Faure
5331495f6c4SClement Faure /* Copy the header to destination */
5341495f6c4SClement Faure key_ser.magic_number = MAGIC_NUMBER;
5351495f6c4SClement Faure key_ser.key_type = blob.key_type;
5361495f6c4SClement Faure key_ser.sec_size = blob.sec_size;
5371495f6c4SClement Faure memcpy(data, &key_ser, sizeof(key_ser));
5381495f6c4SClement Faure
5391495f6c4SClement Faure /* Copy the key buffer */
5401495f6c4SClement Faure memcpy(data + sizeof(key_ser), blob.buf.data, blob.buf.length);
5411495f6c4SClement Faure
5421495f6c4SClement Faure KEY_DUMPBUF("Key data", data, size);
5431495f6c4SClement Faure
5441495f6c4SClement Faure caam_key_free(&blob);
5451495f6c4SClement Faure
5461495f6c4SClement Faure return status;
5471495f6c4SClement Faure }
5481495f6c4SClement Faure
caam_key_serialized_size(const struct caamkey * key,size_t * size)5491495f6c4SClement Faure enum caam_status caam_key_serialized_size(const struct caamkey *key,
5501495f6c4SClement Faure size_t *size)
5511495f6c4SClement Faure {
5521495f6c4SClement Faure assert(key && size);
5531495f6c4SClement Faure
5541495f6c4SClement Faure /* For a plain text key, the serialized key is identical to the key */
5551495f6c4SClement Faure *size = key->buf.length;
5561495f6c4SClement Faure
5571495f6c4SClement Faure /*
5581495f6c4SClement Faure * For black keys, the serialized key includes the header and must be
5591495f6c4SClement Faure * in a blob format
5601495f6c4SClement Faure */
5611495f6c4SClement Faure if (key->key_type != CAAM_KEY_PLAIN_TEXT) {
5621495f6c4SClement Faure size_t alloc = 0;
5631495f6c4SClement Faure const struct caamkey tmp = {
5641495f6c4SClement Faure .key_type = key->key_type,
5651495f6c4SClement Faure .sec_size = key->sec_size,
5661495f6c4SClement Faure .is_blob = true,
5671495f6c4SClement Faure };
5681495f6c4SClement Faure
5691495f6c4SClement Faure alloc = caam_key_get_alloc_size(&tmp);
5701495f6c4SClement Faure if (!alloc)
5711495f6c4SClement Faure return CAAM_FAILURE;
5721495f6c4SClement Faure
5731495f6c4SClement Faure *size = alloc + sizeof(struct caam_key_serialized);
5741495f6c4SClement Faure }
5751495f6c4SClement Faure
5761495f6c4SClement Faure return CAAM_NO_ERROR;
5771495f6c4SClement Faure }
5781495f6c4SClement Faure
caam_key_deserialize_from_bn(const struct bignum * inkey,struct caamkey * outkey,size_t size_sec)5791495f6c4SClement Faure enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey,
5801495f6c4SClement Faure struct caamkey *outkey,
5811495f6c4SClement Faure size_t size_sec)
5821495f6c4SClement Faure {
5831495f6c4SClement Faure enum caam_status status = CAAM_FAILURE;
5841495f6c4SClement Faure uint8_t *buf = NULL;
5851495f6c4SClement Faure size_t size = 0;
5861495f6c4SClement Faure
5871495f6c4SClement Faure assert(inkey && outkey);
5881495f6c4SClement Faure
5891495f6c4SClement Faure KEY_TRACE("Deserialization bignum");
5901495f6c4SClement Faure
5911495f6c4SClement Faure /* Get bignum size */
5921495f6c4SClement Faure size = crypto_bignum_num_bytes((struct bignum *)inkey);
5931495f6c4SClement Faure
5941495f6c4SClement Faure /* Allocate temporary buffer */
5951495f6c4SClement Faure buf = caam_calloc(size);
5961495f6c4SClement Faure if (!buf)
5971495f6c4SClement Faure return CAAM_OUT_MEMORY;
5981495f6c4SClement Faure
5991495f6c4SClement Faure /* Convert bignum to binary */
6001495f6c4SClement Faure crypto_bignum_bn2bin(inkey, buf);
6011495f6c4SClement Faure
6021495f6c4SClement Faure status = caam_key_deserialize_from_bin(buf, size, outkey, size_sec);
6031495f6c4SClement Faure
6041495f6c4SClement Faure caam_key_dump("Output key", outkey);
6051495f6c4SClement Faure
6061495f6c4SClement Faure caam_free(buf);
6071495f6c4SClement Faure
6081495f6c4SClement Faure return status;
6091495f6c4SClement Faure }
6101495f6c4SClement Faure
caam_key_serialize_to_bn(struct bignum * outkey,const struct caamkey * inkey)6111495f6c4SClement Faure enum caam_status caam_key_serialize_to_bn(struct bignum *outkey,
6121495f6c4SClement Faure const struct caamkey *inkey)
6131495f6c4SClement Faure {
6141495f6c4SClement Faure enum caam_status status = CAAM_FAILURE;
6151495f6c4SClement Faure TEE_Result res = TEE_ERROR_GENERIC;
6161495f6c4SClement Faure uint8_t *buf = NULL;
6171495f6c4SClement Faure size_t size = 0;
6181495f6c4SClement Faure
6191495f6c4SClement Faure assert(inkey && outkey);
6201495f6c4SClement Faure
6211495f6c4SClement Faure KEY_TRACE("Serialization bignum");
6221495f6c4SClement Faure caam_key_dump("Input key", inkey);
6231495f6c4SClement Faure
6241495f6c4SClement Faure status = caam_key_serialized_size(inkey, &size);
6251495f6c4SClement Faure if (status)
6261495f6c4SClement Faure return status;
6271495f6c4SClement Faure
6281495f6c4SClement Faure buf = caam_calloc(size);
6291495f6c4SClement Faure if (!buf)
6301495f6c4SClement Faure return CAAM_OUT_MEMORY;
6311495f6c4SClement Faure
6321495f6c4SClement Faure status = caam_key_serialize_to_bin(buf, size, inkey);
6331495f6c4SClement Faure if (status)
6341495f6c4SClement Faure goto out;
6351495f6c4SClement Faure
6361495f6c4SClement Faure res = crypto_bignum_bin2bn(buf, size, outkey);
6371495f6c4SClement Faure if (res)
6381495f6c4SClement Faure status = CAAM_FAILURE;
6391495f6c4SClement Faure out:
6401495f6c4SClement Faure caam_free(buf);
6411495f6c4SClement Faure
6421495f6c4SClement Faure return status;
6431495f6c4SClement Faure }
6441495f6c4SClement Faure
6451495f6c4SClement Faure #define MAX_DESC_ENTRIES 22
caam_key_black_encapsulation(struct caamkey * key,enum caam_key_type key_type)6461495f6c4SClement Faure enum caam_status caam_key_black_encapsulation(struct caamkey *key,
6471495f6c4SClement Faure enum caam_key_type key_type)
6481495f6c4SClement Faure {
6491495f6c4SClement Faure enum caam_status status = CAAM_FAILURE;
6501495f6c4SClement Faure struct caambuf input_buf = { };
6511495f6c4SClement Faure struct caam_jobctx jobctx = { };
6521495f6c4SClement Faure uint32_t *desc = NULL;
6531495f6c4SClement Faure
6541495f6c4SClement Faure assert(key);
6551495f6c4SClement Faure assert(!key->is_blob && key->key_type == CAAM_KEY_PLAIN_TEXT);
6561495f6c4SClement Faure assert(key_type != CAAM_KEY_PLAIN_TEXT);
6571495f6c4SClement Faure
6581495f6c4SClement Faure KEY_TRACE("Black key encapsulation");
6591495f6c4SClement Faure
6601495f6c4SClement Faure /* Copy input plain text key to temp buffer */
6611495f6c4SClement Faure status = caam_calloc_align_buf(&input_buf, key->buf.length);
6621495f6c4SClement Faure if (status)
6631495f6c4SClement Faure return status;
6641495f6c4SClement Faure
6651495f6c4SClement Faure memcpy(input_buf.data, key->buf.data, key->buf.length);
6661495f6c4SClement Faure cache_operation(TEE_CACHEFLUSH, input_buf.data, input_buf.length);
6671495f6c4SClement Faure
6681495f6c4SClement Faure /* Re-allocate the output key for black format */
6691495f6c4SClement Faure caam_key_free(key);
6701495f6c4SClement Faure key->key_type = key_type;
6711495f6c4SClement Faure
6721495f6c4SClement Faure status = caam_key_alloc(key);
6731495f6c4SClement Faure if (status)
6741495f6c4SClement Faure goto out;
6751495f6c4SClement Faure
6761495f6c4SClement Faure /* Allocate the descriptor */
6771495f6c4SClement Faure desc = caam_calloc_desc(MAX_DESC_ENTRIES);
6781495f6c4SClement Faure if (!desc) {
6791495f6c4SClement Faure KEY_TRACE("Allocation descriptor error");
6801495f6c4SClement Faure status = CAAM_OUT_MEMORY;
6811495f6c4SClement Faure goto out;
6821495f6c4SClement Faure }
6831495f6c4SClement Faure
6841495f6c4SClement Faure caam_key_dump("Input key", key);
6851495f6c4SClement Faure
6861495f6c4SClement Faure caam_desc_init(desc);
6871495f6c4SClement Faure caam_desc_add_word(desc, DESC_HEADER(0));
6881495f6c4SClement Faure caam_desc_add_word(desc, LD_KEY(CLASS_1, PKHA_E, key->sec_size));
6891495f6c4SClement Faure caam_desc_add_ptr(desc, input_buf.paddr);
6901495f6c4SClement Faure
6911495f6c4SClement Faure switch (key->key_type) {
6921495f6c4SClement Faure case CAAM_KEY_BLACK_ECB:
6931495f6c4SClement Faure caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_ECB_JKEK,
6941495f6c4SClement Faure key->sec_size));
6951495f6c4SClement Faure break;
6961495f6c4SClement Faure case CAAM_KEY_BLACK_CCM:
6971495f6c4SClement Faure caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_CCM_JKEK,
6981495f6c4SClement Faure key->sec_size));
6991495f6c4SClement Faure break;
7001495f6c4SClement Faure default:
7011495f6c4SClement Faure status = CAAM_FAILURE;
7021495f6c4SClement Faure goto out;
7031495f6c4SClement Faure }
7041495f6c4SClement Faure
7051495f6c4SClement Faure caam_desc_add_ptr(desc, key->buf.paddr);
7061495f6c4SClement Faure
7071495f6c4SClement Faure KEY_DUMPDESC(desc);
7081495f6c4SClement Faure
7091495f6c4SClement Faure caam_key_cache_op(TEE_CACHEFLUSH, key);
7101495f6c4SClement Faure
7111495f6c4SClement Faure jobctx.desc = desc;
7121495f6c4SClement Faure status = caam_jr_enqueue(&jobctx, NULL);
7131495f6c4SClement Faure if (status != CAAM_NO_ERROR) {
7141495f6c4SClement Faure KEY_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32, status,
7151495f6c4SClement Faure jobctx.status);
7161495f6c4SClement Faure status = CAAM_FAILURE;
7171495f6c4SClement Faure goto out;
7181495f6c4SClement Faure }
7191495f6c4SClement Faure
7201495f6c4SClement Faure caam_key_cache_op(TEE_CACHEINVALIDATE, key);
7211495f6c4SClement Faure
7221495f6c4SClement Faure caam_key_dump("Output Key", key);
7231495f6c4SClement Faure
7241495f6c4SClement Faure out:
7251495f6c4SClement Faure caam_free_buf(&input_buf);
7261495f6c4SClement Faure caam_free_desc(&desc);
7271495f6c4SClement Faure
7281495f6c4SClement Faure return status;
7291495f6c4SClement Faure }
7301495f6c4SClement Faure
caam_key_init(void)7311495f6c4SClement Faure enum caam_status caam_key_init(void)
7321495f6c4SClement Faure {
7331495f6c4SClement Faure size_t alloc_size = 0;
7341495f6c4SClement Faure const struct caamkey key = {
7351495f6c4SClement Faure .key_type = caam_key_default_key_gen_type(),
7361495f6c4SClement Faure .sec_size = 4096, /* Max RSA key size */
7371495f6c4SClement Faure .is_blob = true,
7381495f6c4SClement Faure };
7391495f6c4SClement Faure
7401495f6c4SClement Faure /*
7411495f6c4SClement Faure * Ensure bignum format maximum size is enough to store a black key
7421495f6c4SClement Faure * blob. The largest key is a 4096 bits RSA key pair.
7431495f6c4SClement Faure */
7441495f6c4SClement Faure if (caam_key_serialized_size(&key, &alloc_size))
7451495f6c4SClement Faure return CAAM_FAILURE;
7461495f6c4SClement Faure
7471495f6c4SClement Faure assert(alloc_size <= CFG_CORE_BIGNUM_MAX_BITS);
7481495f6c4SClement Faure
749*116d03abSSahil Malhotra key_blob_modifier = caam_calloc_align(KEY_BLOB_MODIFIER_SIZE);
750*116d03abSSahil Malhotra if (!key_blob_modifier)
751*116d03abSSahil Malhotra return CAAM_FAILURE;
752*116d03abSSahil Malhotra
753*116d03abSSahil Malhotra memcpy(key_blob_modifier, KEY_BLOB_MODIFIER, KEY_BLOB_MODIFIER_SIZE);
754*116d03abSSahil Malhotra
7551495f6c4SClement Faure KEY_TRACE("Max serialized key size %zu", alloc_size);
7561495f6c4SClement Faure
7571495f6c4SClement Faure KEY_TRACE("Default CAAM key generation type %s",
7581495f6c4SClement Faure caam_key_type_to_str[caam_key_default_key_gen_type()]);
7591495f6c4SClement Faure
7601495f6c4SClement Faure return CAAM_NO_ERROR;
7611495f6c4SClement Faure }
762