1
0
Fork 0
alistair23-linux/drivers/crypto/caam/caamkeyblob_desc.c

447 lines
17 KiB
C

// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/*
* Shared descriptors for CAAM black key
* and blob encapsulation/decapsulation
*
* Copyright 2018-2020 NXP
*/
#include "caamkeyblob_desc.h"
/* Size of tmp buffer for descriptor const. */
#define INITIAL_DESCSZ 64
/*
* Construct a black key conversion job descriptor
*
* This function constructs a job descriptor capable of performing
* a key blackening operation on a plaintext secure memory resident object.
*
* @desc : Pointer to a pointer to the descriptor generated by this
* function. Caller will be responsible to kfree() this
* descriptor after execution.
* @key : Pointer to the plaintext, which will also hold
* the result. Since encryption occurs in place, caller must
* ensure that the space is large enough to accommodate the
* blackened key
* @key_len : Size of the plaintext
* @black_key : DMA address of the black key obtained from hardware
* @black_key_len : Size of the black key
* @key_enc : Encrypted Key Type (AES-ECB or AES-CCM)
* @trusted_key : Trusted Key (use Job Descriptor Key Encryption Key (JDKEK)
* or Trusted Descriptor Key Encryption Key (TDKEK) to
* decrypt the key to be loaded into a Key Register).
*
* Return : '0' on success, error code otherwise
*/
int cnstr_desc_black_key(u32 **desc, char *key, size_t key_len,
dma_addr_t black_key, size_t black_key_len,
u8 key_enc, u8 trusted_key)
{
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
u16 dsize;
u32 bk_store;
u32 key_length_for_desc = key_len;
/* Trusted key not supported */
if (trusted_key != UNTRUSTED_KEY)
return -ENOTSUPP;
memset(tmpdesc, 0, sizeof(tmpdesc));
init_job_desc(tmpdesc, 0);
/*
* KEY commands seems limited to 32 bytes, so we should use the load
* command instead which can load up to 64 bytes.
* The size must also be loaded.
*
* TODO: The KEY command indicate it should be able to load key bigger
* than 32bytes but it doesn't work in practice
*
* TODO: The LOAD command indicate it should be able to load up to 96
* byte keys it doesn't work in practice and is limited to 64 bytes
*/
/* Load key to class 1 key register */
append_load_as_imm(tmpdesc, (void *)key, key_length_for_desc,
LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_KEY);
/* Load the size of the key */
append_load_imm_u32(tmpdesc, key_length_for_desc, LDST_CLASS_1_CCB |
LDST_IMM | LDST_SRCDST_WORD_KEYSZ_REG);
/* ...and write back out via FIFO store*/
bk_store = CLASS_1;
if (key_enc == KEY_COVER_ECB)
bk_store |= FIFOST_TYPE_KEY_KEK;
else
bk_store |= FIFOST_TYPE_KEY_CCM_JKEK;
/* Save the key as black key in memory */
append_fifo_store(tmpdesc, black_key, black_key_len, bk_store);
dsize = desc_bytes(&tmpdesc);
/* Now allocate execution buffer and coat it with executable */
tdesc = kmemdup(tmpdesc, dsize, GFP_KERNEL | GFP_DMA);
if (!tdesc)
return -ENOMEM;
*desc = tdesc;
print_hex_dump_debug("black key desc@" __stringify(__LINE__) ":",
DUMP_PREFIX_ADDRESS, 16, 4, *desc,
desc_bytes(*desc), 1);
return 0;
}
EXPORT_SYMBOL(cnstr_desc_black_key);
/*
* Construct a black key using RNG job descriptor
*
* This function constructs a job descriptor capable of performing
* a key blackening operation on RNG generated.
*
* @desc : Pointer to a pointer to the descriptor generated by this
* function. Caller will be responsible to kfree() this
* descriptor after execution.
* @key_len : Size of the random plaintext
* @black_key : DMA address of the black key obtained from hardware
* @black_key_len : Size of the black key
* @key_enc : Encrypted Key Type (AES-ECB or AES-CCM)
* @trusted_key : Trusted Key (use Job Descriptor Key Encryption Key (JDKEK)
* or Trusted Descriptor Key Encryption Key (TDKEK) to
* decrypt the key to be loaded into a Key Register).
*
* Return : '0' on success, error code otherwise
*/
int cnstr_desc_random_black_key(u32 **desc, size_t key_len,
dma_addr_t black_key, size_t black_key_len,
u8 key_enc, u8 trusted_key)
{
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
u16 dsize;
u32 bk_store;
memset(tmpdesc, 0, sizeof(tmpdesc));
init_job_desc(tmpdesc, 0);
/* Prepare RNG */
append_operation(tmpdesc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
/* Generate RNG and left it in output data fifo */
append_cmd(tmpdesc, CMD_FIFO_STORE | FIFOST_TYPE_RNGFIFO | key_len);
/* Copy RNG from outfifo to class 1 Key register */
append_move(tmpdesc, MOVE_SRC_OUTFIFO | MOVE_DEST_CLASS1KEY |
MOVE_WAITCOMP | (key_len & MOVE_LEN_MASK));
/* Write the size of the key moved */
append_load_imm_u32(tmpdesc, key_len, LDST_CLASS_1_CCB |
LDST_SRCDST_WORD_KEYSZ_REG | LDST_IMM);
bk_store = CLASS_1;
if (key_enc == KEY_COVER_ECB)
bk_store |= FIFOST_TYPE_KEY_KEK;
else
bk_store |= FIFOST_TYPE_KEY_CCM_JKEK;
/* Fifo store to save the key as black key in memory */
append_fifo_store(tmpdesc, black_key, black_key_len, bk_store);
dsize = desc_bytes(&tmpdesc);
/* Now allocate execution buffer and coat it with executable */
tdesc = kmemdup(tmpdesc, dsize, GFP_KERNEL | GFP_DMA);
if (!tdesc)
return -ENOMEM;
*desc = tdesc;
print_hex_dump_debug("black key random desc@" __stringify(__LINE__) ":",
DUMP_PREFIX_ADDRESS, 16, 4, *desc,
desc_bytes(*desc), 1);
return 0;
}
EXPORT_SYMBOL(cnstr_desc_random_black_key);
/*
* Construct a blob encapsulation job descriptor
*
* This function dynamically constructs a blob encapsulation job descriptor
* from the following arguments:
*
* @desc : Pointer to a pointer to the descriptor generated by this
* function. Caller will be responsible to kfree() this
* descriptor after execution.
* @black_key : Physical pointer to a secret, normally a black or red key,
* possibly residing within an accessible secure memory page,
* of the secret to be encapsulated to an output blob.
* @black_key_len : Size of input secret, in bytes. This is limited to 65536
* less the size of blob overhead, since the length embeds
* into DECO pointer in/out instructions.
* @keycolor : Determines if the source data is covered (black key) or
* plaintext (red key). RED_KEY or BLACK_KEY are defined in
* for this purpose.
* @key_enc : If BLACK_KEY source is covered via AES-CCM, specify
* KEY_COVER_CCM, else uses AES-ECB (KEY_COVER_ECB).
* @trusted_key : Trusted Key (use Job Descriptor Key Encryption Key (JDKEK)
* or Trusted Descriptor Key Encryption Key (TDKEK) to
* decrypt the key to be loaded into a Key Register).
* @mem_type : Determine if encapsulated blob should be a secure memory
* blob (DATA_SECMEM), with partition data embedded with key
* material, or a general memory blob (DATA_GENMEM).
* @key_mod : Pointer to a key modifier, which must reside in a
* contiguous piece of memory. Modifier will be assumed to be
* 8 bytes long for a blob of type DATA_SECMEM, or 16 bytes
* long for a blob of type DATA_GENMEM
* @key_mod_len : Modifier length is 8 bytes long for a blob of type
* DATA_SECMEM, or 16 bytes long for a blob of type DATA_GENMEM
* @blob : Physical pointer to the destination buffer to receive the
* encapsulated output. This buffer will need to be 48 bytes
* larger than the input because of the added encapsulation
* data. The generated descriptor will account for the
* increase in size, but the caller must also account for
* this increase in the buffer allocator.
* @blob_len : Size of the destination buffer to receive the
* encapsulated output.
* Return : '0' on success, error code otherwise
*
* Upon completion, desc points to a buffer containing a CAAM job
* descriptor which encapsulates data into an externally-storable blob
* suitable for use across power cycles.
*
* This is an example of a black key encapsulation job into a general memory
* blob. Notice the 16-byte key modifier in the LOAD instruction. Also note
* the output 48 bytes longer than the input:
*
* [00] B0800008 jobhdr: stidx=0 len=8
* [01] 14400010 ld: ccb2-key len=16 offs=0
* [02] 08144891 ptr->@0x08144891
* [03] F800003A seqoutptr: len=58
* [04] 01000000 out_ptr->@0x01000000
* [05] F000000A seqinptr: len=10
* [06] 09745090 in_ptr->@0x09745090
* [07] 870D0004 operation: encap blob reg=memory, black, format=normal
*
* This is an example of a red key encapsulation job for storing a red key
* into a secure memory blob. Note the 8 byte modifier on the 12 byte offset
* in the LOAD instruction; this accounts for blob permission storage:
*
* [00] B0800008 jobhdr: stidx=0 len=8
* [01] 14400C08 ld: ccb2-key len=8 offs=12
* [02] 087D0784 ptr->@0x087d0784
* [03] F8000050 seqoutptr: len=80
* [04] 09251BB2 out_ptr->@0x09251bb2
* [05] F0000020 seqinptr: len=32
* [06] 40000F31 in_ptr->@0x40000f31
* [07] 870D0008 operation: encap blob reg=memory, red, sec_mem,
* format=normal
*/
int cnstr_desc_blob_encap(u32 **desc, dma_addr_t black_key,
size_t key_len, u8 keycolor, u8 key_enc,
u8 trusted_key, u8 mem_type, const void *key_mod,
size_t key_mod_len, dma_addr_t blob, size_t blob_len)
{
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
u16 dsize;
u32 bk_store;
/* Trusted key not supported */
if (trusted_key != UNTRUSTED_KEY)
return -ENOTSUPP;
memset(tmpdesc, 0, sizeof(tmpdesc));
init_job_desc(tmpdesc, 0);
/*
* Key modifier works differently for secure/general memory blobs
* This accounts for the permission/protection data encapsulated
* within the blob if a secure memory blob is requested
*/
if (mem_type == DATA_SECMEM)
append_load_as_imm(tmpdesc, key_mod, key_mod_len,
LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY |
((12 << LDST_OFFSET_SHIFT) &
LDST_OFFSET_MASK));
else /* is general memory blob */
append_load_as_imm(tmpdesc, key_mod, key_mod_len,
LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY);
/* Input data, should be somewhere in secure memory */
append_seq_in_ptr_intlen(tmpdesc, black_key, key_len, 0);
/*
* Encapsulation output must include space for blob key encryption
* key and MAC tag
*/
append_seq_out_ptr_intlen(tmpdesc, blob, CCM_BLACK_KEY_SIZE(key_len) +
BLOB_OVERHEAD, 0);
bk_store = OP_PCLID_BLOB;
if (mem_type == DATA_SECMEM)
bk_store |= OP_PCL_BLOB_PTXT_SECMEM;
if (key_enc == KEY_COVER_CCM)
bk_store |= OP_PCL_BLOB_EKT;
/* An input black key cannot be stored in a red blob */
if (keycolor == BLACK_KEY)
bk_store |= OP_PCL_BLOB_BLACK;
/* Set blob encap, then color */
append_operation(tmpdesc, OP_TYPE_ENCAP_PROTOCOL | bk_store);
dsize = desc_bytes(&tmpdesc);
tdesc = kmemdup(tmpdesc, dsize, GFP_KERNEL | GFP_DMA);
if (!tdesc)
return -ENOMEM;
*desc = tdesc;
print_hex_dump_debug("blob encap desc@" __stringify(__LINE__) ":",
DUMP_PREFIX_ADDRESS, 16, 4, *desc,
desc_bytes(*desc), 1);
return 0;
}
EXPORT_SYMBOL(cnstr_desc_blob_encap);
/*
* Construct a blob decapsulation job descriptor
*
* This function dynamically constructs a blob decapsulation job descriptor
* from the following arguments:
*
* @desc : Pointer to a pointer to the descriptor generated by this
* function. Caller will be responsible to kfree() this
* descriptor after execution.
* @blob : Physical pointer (into external memory) of the blob to
* be decapsulated. Blob must reside in a contiguous memory
* segment.
* @blob_len : Size of the blob buffer to be decapsulated.
* @key_mod : Pointer to a key modifier, which must reside in a
* contiguous piece of memory. Modifier will be assumed to be
* 8 bytes long for a blob of type DATA_SECMEM, or 16 bytes
* long for a blob of type DATA_GENMEM
* @key_mod_len : Modifier length is 8 bytes long for a blob of type
* DATA_SECMEM, or 16 bytes long for a blob of type DATA_GENMEM
* @black_key : Physical pointer of the decapsulated output, possibly into
* a location within a secure memory page. Must be contiguous.
* @black_key_len : Size of encapsulated secret in bytes (not the size of the
* input blob).
* @keycolor : Determines if the source data is covered (black key) or
* plaintext (red key). RED_KEY or BLACK_KEY are defined in
* for this purpose.
* @key_enc : If BLACK_KEY source is covered via AES-CCM, specify
* KEY_COVER_CCM, else uses AES-ECB (KEY_COVER_ECB).
* @trusted_key : Trusted Key (use Job Descriptor Key Encryption Key (JDKEK)
* or Trusted Descriptor Key Encryption Key (TDKEK) to
* decrypt the key to be loaded into a Key Register).
* @mem_type : Determine if encapsulated blob should be a secure memory
* blob (DATA_SECMEM), with partition data embedded with key
* material, or a general memory blob (DATA_GENMEM).
* Return : '0' on success, error code otherwise
*
* Upon completion, desc points to a buffer containing a CAAM job descriptor
* that decapsulates a key blob from external memory into a black (encrypted)
* key or red (plaintext) content.
*
* This is an example of a black key decapsulation job from a general memory
* blob. Notice the 16-byte key modifier in the LOAD instruction.
*
* [00] B0800008 jobhdr: stidx=0 len=8
* [01] 14400010 ld: ccb2-key len=16 offs=0
* [02] 08A63B7F ptr->@0x08a63b7f
* [03] F8000010 seqoutptr: len=16
* [04] 01000000 out_ptr->@0x01000000
* [05] F000003A seqinptr: len=58
* [06] 01000010 in_ptr->@0x01000010
* [07] 860D0004 operation: decap blob reg=memory, black, format=normal
*
* This is an example of a red key decapsulation job for restoring a red key
* from a secure memory blob. Note the 8 byte modifier on the 12 byte offset
* in the LOAD instruction:
*
* [00] B0800008 jobhdr: stidx=0 len=8
* [01] 14400C08 ld: ccb2-key len=8 offs=12
* [02] 01000000 ptr->@0x01000000
* [03] F8000020 seqoutptr: len=32
* [04] 400000E6 out_ptr->@0x400000e6
* [05] F0000050 seqinptr: len=80
* [06] 08F0C0EA in_ptr->@0x08f0c0ea
* [07] 860D0008 operation: decap blob reg=memory, red, sec_mem,
* format=normal
*/
int cnstr_desc_blob_decap(u32 **desc, dma_addr_t blob, size_t blob_len,
const void *key_mod, size_t key_mod_len,
dma_addr_t black_key, size_t plaintext_len,
u8 keycolor, u8 key_enc, u8 trusted_key, u8 mem_type)
{
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
u16 dsize;
u32 bk_store;
/* Trusted key not supported */
if (trusted_key != UNTRUSTED_KEY)
return -ENOTSUPP;
memset(tmpdesc, 0, sizeof(tmpdesc));
init_job_desc(tmpdesc, 0);
/* Load key modifier */
if (mem_type == DATA_SECMEM)
append_load_as_imm(tmpdesc, key_mod, key_mod_len,
LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY |
((12 << LDST_OFFSET_SHIFT) &
LDST_OFFSET_MASK));
else /* is general memory blob */
append_load_as_imm(tmpdesc, key_mod, key_mod_len,
LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY);
/* Compensate blob header + MAC tag over size of encapsulated secret */
append_seq_in_ptr_intlen(tmpdesc, blob, plaintext_len + BLOB_OVERHEAD,
0);
append_seq_out_ptr_intlen(tmpdesc, black_key, plaintext_len, 0);
/* Decapsulate from secure memory partition to black blob */
bk_store = OP_PCLID_BLOB;
if (mem_type == DATA_SECMEM)
bk_store |= OP_PCL_BLOB_PTXT_SECMEM;
if (key_enc == KEY_COVER_CCM)
bk_store |= OP_PCL_BLOB_EKT;
/* An input black key cannot be stored in a red blob */
if (keycolor == BLACK_KEY)
bk_store |= OP_PCL_BLOB_BLACK;
/* Set blob encap, then color */
append_operation(tmpdesc, OP_TYPE_DECAP_PROTOCOL | bk_store);
dsize = desc_bytes(&tmpdesc);
tdesc = kmemdup(tmpdesc, dsize, GFP_KERNEL | GFP_DMA);
if (!tdesc)
return -ENOMEM;
*desc = tdesc;
print_hex_dump_debug("blob decap desc@" __stringify(__LINE__) ":",
DUMP_PREFIX_ADDRESS, 16, 4, *desc,
desc_bytes(*desc), 1);
return 0;
}
EXPORT_SYMBOL(cnstr_desc_blob_decap);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("NXP CAAM Black Key and Blob descriptors");
MODULE_AUTHOR("NXP Semiconductors");