mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-09-03 10:33:11 +02:00
MLK-9710-11 Add internal key cover and external blob export/import to prototype SM-API
Extended/amended the prototype SM-API with the following functions: - Added key covering (blackening) function in-place to a keyslot - Added export operation to encapsulate data to external memory as a secure memory blob (including descriptor capable of secure memory or general memory blob generation) - Removed in-place blob encapsulation - Added import operation to decapsulate a blob from external memory into secure memory (including descriptor capable of general memory or secure memory content decapsulation) - Removed in-place blob decapsulation [<vicki.milhoan@freescale.com>: Edited to apply to 3.10] Signed-off-by: Steve Cornelius <steve.cornelius@freescale.com> Signed-off-by: Victoria Milhoan <vicki.milhoan@freescale.com> (cherry picked from commit c577769ed0347bb4e3428b5696fb7f209af0a7ad) Signed-off-by: Dan Douglass <dan.douglass@freescale.com> Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
This commit is contained in:
parent
8433c811e9
commit
c7d4f9db10
|
@ -13,6 +13,25 @@
|
|||
#define SM_PERM_WRITE 0x02
|
||||
#define SM_PERM_BLOB 0x03
|
||||
|
||||
/* Define treatment of secure memory vs. general memory blobs */
|
||||
#define SM_SECMEM 0
|
||||
#define SM_GENMEM 1
|
||||
|
||||
/* Define treatment of red/black keys */
|
||||
#define RED_KEY 0
|
||||
#define BLACK_KEY 1
|
||||
|
||||
/* Define key encryption/covering options */
|
||||
#define KEY_COVER_ECB 0 /* cover key in AES-ECB */
|
||||
#define KEY_COVER_CCM 1 /* cover key with AES-CCM */
|
||||
|
||||
/*
|
||||
* Round a key size up to an AES blocksize boundary so to allow for
|
||||
* padding out to a full block
|
||||
*/
|
||||
#define AES_BLOCK_PAD(x) ((x % 16) ? ((x >> 4) + 1) << 4 : x)
|
||||
|
||||
#define BLOB_OVERHEAD (16 + 8) /* BKEK + MAC tag storage in any blob */
|
||||
|
||||
/* Keystore maintenance functions */
|
||||
void sm_init_keystore(struct device *dev);
|
||||
|
@ -30,6 +49,16 @@ extern int sm_keystore_slot_load(struct device *dev, u32 unit, u32 slot,
|
|||
const u8 *key_data, u32 key_length);
|
||||
extern int sm_keystore_slot_read(struct device *dev, u32 unit, u32 slot,
|
||||
u32 key_length, u8 *key_data);
|
||||
extern int sm_keystore_cover_key(struct device *dev, u32 unit, u32 slot,
|
||||
u16 key_length, u8 keyauth);
|
||||
extern int sm_keystore_slot_export(struct device *dev, u32 unit, u32 slot,
|
||||
u8 keycolor, u8 keyauth, u8 *outbuf,
|
||||
u16 keylen, u8 *keymod);
|
||||
extern int sm_keystore_slot_import(struct device *dev, u32 unit, u32 slot,
|
||||
u8 keycolor, u8 keyauth, u8 *inbuf,
|
||||
u16 keylen, u8 *keymod);
|
||||
|
||||
/* Prior functions from legacy API, deprecated */
|
||||
extern int sm_keystore_slot_encapsulate(struct device *dev, u32 unit,
|
||||
u32 inslot, u32 outslot, u16 secretlen,
|
||||
u8 *keymod, u16 keymodlen);
|
||||
|
@ -45,7 +74,8 @@ struct keystore_data_slot_info {
|
|||
|
||||
/* Data structure to hold keystore information */
|
||||
struct keystore_data {
|
||||
void *base_address; /* Base of the Secure Partition */
|
||||
void *base_address; /* Virtual base of secure memory pages */
|
||||
void *phys_address; /* Physical base of secure memory pages */
|
||||
u32 slot_count; /* Number of slots in the keystore */
|
||||
struct keystore_data_slot_info *slot; /* Per-slot information */
|
||||
};
|
||||
|
@ -55,6 +85,7 @@ struct sm_page_descriptor {
|
|||
u16 phys_pagenum; /* may be discontiguous */
|
||||
u16 own_part; /* Owning partition */
|
||||
void *pg_base; /* Calculated virtual address */
|
||||
void *pg_phys; /* Calculated physical address */
|
||||
struct keystore_data *ksdata;
|
||||
};
|
||||
|
||||
|
@ -80,6 +111,7 @@ struct caam_drv_private_sm {
|
|||
int (*slot_alloc)(struct device *dev, u32 unit, u32 size, u32 *slot);
|
||||
int (*slot_dealloc)(struct device *dev, u32 unit, u32 slot);
|
||||
void *(*slot_get_address)(struct device *dev, u32 unit, u32 handle);
|
||||
void *(*slot_get_physical)(struct device *dev, u32 unit, u32 handle);
|
||||
u32 (*slot_get_base)(struct device *dev, u32 unit, u32 handle);
|
||||
u32 (*slot_get_offset)(struct device *dev, u32 unit, u32 handle);
|
||||
u32 (*slot_get_slot_size)(struct device *dev, u32 unit, u32 handle);
|
||||
|
|
|
@ -37,6 +37,9 @@
|
|||
#include "error.h"
|
||||
#include "sm.h"
|
||||
|
||||
#define SECMEM_KEYMOD_LEN 8
|
||||
#define GENMEM_KEYMOD_LEN 16
|
||||
|
||||
#ifdef SM_DEBUG_CONT
|
||||
void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
|
||||
{
|
||||
|
@ -53,28 +56,33 @@ void sm_show_page(struct device *dev, struct sm_page_descriptor *pgdesc)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Construct a secure memory blob encapsulation job descriptor
|
||||
*
|
||||
* - desc pointer to hold new (to be allocated) pointer to the generated
|
||||
* descriptor for later use. Calling thread can kfree the
|
||||
* descriptor after execution.
|
||||
* - keymod Physical pointer to key modifier (contiguous piece).
|
||||
* - keymodsz Size of key modifier in bytes (should normally be 8).
|
||||
* - secretbuf Physical pointer (within an accessible secure memory page)
|
||||
* of the secret to be encapsulated.
|
||||
* - outbuf Physical pointer (within an accessible secure memory page)
|
||||
* of the encapsulated output. This will be larger than the
|
||||
* input secret because of the added encapsulation data.
|
||||
* - secretsz Size of input secret, in bytes.
|
||||
* - auth If nonzero, use AES-CCM for encapsulation, else use ECB
|
||||
*
|
||||
* Note: this uses 32-bit pointers at present
|
||||
*/
|
||||
#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */
|
||||
static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,
|
||||
dma_addr_t secretbuf, dma_addr_t outbuf,
|
||||
u16 secretsz, bool auth)
|
||||
|
||||
/*
|
||||
* 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 physical 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
|
||||
* - keysz size of the plaintext
|
||||
* - auth if a CCM-covered key is required, use KEY_COVER_CCM, else
|
||||
* use KEY_COVER_ECB.
|
||||
*
|
||||
* KEY to key1 from @key_addr LENGTH 16 BYTES;
|
||||
* FIFO STORE from key1[ecb] TO @key_addr LENGTH 16 BYTES;
|
||||
*
|
||||
* Note that this variant uses the JDKEK only; it does not accommodate the
|
||||
* trusted key encryption key at this time.
|
||||
*
|
||||
*/
|
||||
static int blacken_key_jobdesc(u32 **desc, void *key, u16 keysz, bool auth)
|
||||
{
|
||||
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
|
||||
u16 dsize, idx;
|
||||
|
@ -82,26 +90,155 @@ static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,
|
|||
memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));
|
||||
idx = 1;
|
||||
|
||||
/* Load key modifier */
|
||||
tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY |
|
||||
((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) |
|
||||
(keymodsz & LDST_LEN_MASK);
|
||||
/* Load key to class 1 key register */
|
||||
tmpdesc[idx++] = CMD_KEY | CLASS_1 | (keysz & KEY_LENGTH_MASK);
|
||||
tmpdesc[idx++] = (u32)key;
|
||||
|
||||
/* ...and write back out via FIFO store*/
|
||||
tmpdesc[idx] = CMD_FIFO_STORE | CLASS_1 | (keysz & KEY_LENGTH_MASK);
|
||||
|
||||
/* plus account for ECB/CCM option in FIFO_STORE */
|
||||
if (auth == KEY_COVER_ECB)
|
||||
tmpdesc[idx] |= FIFOST_TYPE_KEY_KEK;
|
||||
else
|
||||
tmpdesc[idx] |= FIFOST_TYPE_KEY_CCM_JKEK;
|
||||
|
||||
idx++;
|
||||
tmpdesc[idx++] = (u32)key;
|
||||
|
||||
/* finish off the job header */
|
||||
tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
|
||||
dsize = idx * sizeof(u32);
|
||||
|
||||
/* now allocate execution buffer and coat it with executable */
|
||||
tdesc = kmalloc(dsize, GFP_KERNEL | GFP_DMA);
|
||||
if (tdesc == NULL)
|
||||
return 0;
|
||||
|
||||
memcpy(tdesc, tmpdesc, dsize);
|
||||
*desc = tdesc;
|
||||
|
||||
return dsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* - keymod Physical 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 SM_SECMEM, or 16 bytes long
|
||||
* for a blob of type SM_GENMEM (see blobtype argument).
|
||||
* - secretbuf 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.
|
||||
* - outbuf 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.
|
||||
* - secretsz 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.
|
||||
* - blobtype Determine if encapsulated blob should be a secure memory
|
||||
* blob (SM_SECMEM), with partition data embedded with key
|
||||
* material, or a general memory blob (SM_GENMEM).
|
||||
* - auth If BLACK_KEY source is covered via AES-CCM, specify
|
||||
* KEY_COVER_CCM, else uses AES-ECB (KEY_COVER_ECB).
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Note: this function only generates 32-bit pointers at present, and should
|
||||
* be refactored using a scheme that allows both 32 and 64 bit addressing
|
||||
*/
|
||||
|
||||
static int blob_encap_jobdesc(u32 **desc, dma_addr_t keymod,
|
||||
void *secretbuf, dma_addr_t outbuf,
|
||||
u16 secretsz, u8 keycolor, u8 blobtype, u8 auth)
|
||||
{
|
||||
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
|
||||
u16 dsize, idx;
|
||||
|
||||
memset(tmpdesc, 0, INITIAL_DESCSZ * sizeof(u32));
|
||||
idx = 1;
|
||||
|
||||
/*
|
||||
* 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 (blobtype == SM_SECMEM)
|
||||
tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
|
||||
LDST_SRCDST_BYTE_KEY |
|
||||
((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK)
|
||||
| (8 & LDST_LEN_MASK);
|
||||
else /* is general memory blob */
|
||||
tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
|
||||
LDST_SRCDST_BYTE_KEY | (16 & LDST_LEN_MASK);
|
||||
|
||||
tmpdesc[idx++] = (u32)keymod;
|
||||
|
||||
/* Encapsulate to secure memory */
|
||||
/*
|
||||
* Encapsulation output must include space for blob key encryption
|
||||
* key and MAC tag (32 + 16)
|
||||
*/
|
||||
tmpdesc[idx++] = CMD_SEQ_OUT_PTR | (secretsz + (32 + 16));
|
||||
tmpdesc[idx++] = (u32)outbuf;
|
||||
|
||||
/* Input data, should be somewhere in secure memory */
|
||||
tmpdesc[idx++] = CMD_SEQ_IN_PTR | secretsz;
|
||||
tmpdesc[idx++] = (u32)secretbuf;
|
||||
|
||||
/* Add space for BKEK and MAC tag */
|
||||
tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + (32 + 16));
|
||||
/* Set blob encap, then color */
|
||||
tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB;
|
||||
|
||||
tmpdesc[idx++] = (u32)outbuf;
|
||||
tmpdesc[idx] = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | OP_PCLID_BLOB |
|
||||
OP_PCL_BLOB_PTXT_SECMEM;
|
||||
if (auth)
|
||||
if (blobtype == SM_SECMEM)
|
||||
tmpdesc[idx] |= OP_PCL_BLOB_PTXT_SECMEM;
|
||||
|
||||
if (auth == KEY_COVER_CCM)
|
||||
tmpdesc[idx] |= OP_PCL_BLOB_EKT;
|
||||
|
||||
if (keycolor == BLACK_KEY)
|
||||
tmpdesc[idx] |= OP_PCL_BLOB_BLACK;
|
||||
|
||||
idx++;
|
||||
tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
|
||||
dsize = idx * sizeof(u32);
|
||||
|
@ -116,25 +253,71 @@ static int blob_encap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,
|
|||
}
|
||||
|
||||
/*
|
||||
* Construct a secure memory blob decapsulation job descriptor
|
||||
* Construct a blob decapsulation job descriptor
|
||||
*
|
||||
* - desc pointer to hold new (to be allocated) pointer to the generated
|
||||
* descriptor for later use. Calling thread can kfree the
|
||||
* 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.
|
||||
* - keymod Physical pointer to key modifier (contiguous piece).
|
||||
* - keymodsz Size of key modifier in bytes (should normally be 16).
|
||||
* - blobbuf Physical pointer (within an accessible secure memory page)
|
||||
* of the blob to be decapsulated.
|
||||
* - outbuf Physical pointer (within an accessible secure memory page)
|
||||
* of the decapsulated output.
|
||||
* - secretsz Size of input blob, in bytes.
|
||||
* - auth If nonzero, assume AES-CCM for decapsulation, else use ECB
|
||||
* - keymod Physical 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 SM_SECMEM, or 16 bytes long
|
||||
* for a blob of type SM_GENMEM (see blobtype argument).
|
||||
* - blobbuf Physical pointer (into external memory) of the blob to
|
||||
* be decapsulated. Blob must reside in a contiguous memory
|
||||
* segment.
|
||||
* - outbuf Physical pointer of the decapsulated output, possibly into
|
||||
* a location within a secure memory page. Must be contiguous.
|
||||
* - secretsz Size of encapsulated secret in bytes (not the size of the
|
||||
* input blob).
|
||||
* - keycolor Determines if decapsulated content is encrypted (BLACK_KEY)
|
||||
* or left as plaintext (RED_KEY).
|
||||
* - blobtype Determine if encapsulated blob should be a secure memory
|
||||
* blob (SM_SECMEM), with partition data embedded with key
|
||||
* material, or a general memory blob (SM_GENMEM).
|
||||
* - auth If decapsulation path is specified by BLACK_KEY, then if
|
||||
* AES-CCM is requested for key covering use KEY_COVER_CCM, else
|
||||
* use AES-ECB (KEY_COVER_ECB).
|
||||
*
|
||||
* Note: this uses 32-bit pointers at present
|
||||
* 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
|
||||
*
|
||||
* Note: this function only generates 32-bit pointers at present, and should
|
||||
* be refactored using a scheme that allows both 32 and 64 bit addressing
|
||||
*/
|
||||
static int blob_decap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,
|
||||
dma_addr_t blobbuf, dma_addr_t outbuf,
|
||||
u16 blobsz, bool auth)
|
||||
|
||||
static int blob_decap_jobdesc(u32 **desc, dma_addr_t keymod, dma_addr_t blobbuf,
|
||||
u8 *outbuf, u16 secretsz, u8 keycolor,
|
||||
u8 blobtype, u8 auth)
|
||||
{
|
||||
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
|
||||
u16 dsize, idx;
|
||||
|
@ -143,25 +326,35 @@ static int blob_decap_desc(u32 **desc, dma_addr_t keymod, u16 keymodsz,
|
|||
idx = 1;
|
||||
|
||||
/* Load key modifier */
|
||||
tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB | LDST_SRCDST_BYTE_KEY |
|
||||
((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK) |
|
||||
(keymodsz & LDST_LEN_MASK);
|
||||
if (blobtype == SM_SECMEM)
|
||||
tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
|
||||
LDST_SRCDST_BYTE_KEY |
|
||||
((12 << LDST_OFFSET_SHIFT) & LDST_OFFSET_MASK)
|
||||
| (8 & LDST_LEN_MASK);
|
||||
else /* is general memory blob */
|
||||
tmpdesc[idx++] = CMD_LOAD | LDST_CLASS_2_CCB |
|
||||
LDST_SRCDST_BYTE_KEY | (16 & LDST_LEN_MASK);
|
||||
|
||||
tmpdesc[idx++] = (u32)keymod;
|
||||
|
||||
/* Compensate BKEK + MAC tag */
|
||||
tmpdesc[idx++] = CMD_SEQ_IN_PTR | (blobsz + 32 + 16);
|
||||
|
||||
/* Compensate BKEK + MAC tag over size of encapsulated secret */
|
||||
tmpdesc[idx++] = CMD_SEQ_IN_PTR | (secretsz + 32 + 16);
|
||||
tmpdesc[idx++] = (u32)blobbuf;
|
||||
tmpdesc[idx++] = CMD_SEQ_OUT_PTR | blobsz;
|
||||
tmpdesc[idx++] = CMD_SEQ_OUT_PTR | secretsz;
|
||||
tmpdesc[idx++] = (u32)outbuf;
|
||||
|
||||
/* Decapsulate from secure memory partition to black blob */
|
||||
tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB |
|
||||
OP_PCL_BLOB_PTXT_SECMEM | OP_PCL_BLOB_BLACK;
|
||||
if (auth)
|
||||
tmpdesc[idx] = CMD_OPERATION | OP_TYPE_DECAP_PROTOCOL | OP_PCLID_BLOB;
|
||||
|
||||
if (blobtype == SM_SECMEM)
|
||||
tmpdesc[idx] |= OP_PCL_BLOB_PTXT_SECMEM;
|
||||
|
||||
if (auth == KEY_COVER_CCM)
|
||||
tmpdesc[idx] |= OP_PCL_BLOB_EKT;
|
||||
|
||||
if (keycolor == BLACK_KEY)
|
||||
tmpdesc[idx] |= OP_PCL_BLOB_BLACK;
|
||||
|
||||
idx++;
|
||||
tmpdesc[0] = CMD_DESC_HDR | HDR_ONE | (idx & HDR_DESCLEN_MASK);
|
||||
dsize = idx * sizeof(u32);
|
||||
|
@ -294,6 +487,22 @@ void *slot_get_address(struct device *dev, u32 unit, u32 slot)
|
|||
return ksdata->base_address + slot * smpriv->slot_size;
|
||||
}
|
||||
|
||||
void *slot_get_physical(struct device *dev, u32 unit, u32 slot)
|
||||
{
|
||||
struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
|
||||
struct keystore_data *ksdata = smpriv->pagedesc[unit].ksdata;
|
||||
|
||||
if (slot >= ksdata->slot_count)
|
||||
return NULL;
|
||||
|
||||
#ifdef SM_DEBUG
|
||||
dev_info(dev, "%s: slot %d is 0x%08x\n", __func__, slot,
|
||||
(u32)ksdata->phys_address + slot * smpriv->slot_size);
|
||||
#endif
|
||||
|
||||
return ksdata->phys_address + slot * smpriv->slot_size;
|
||||
}
|
||||
|
||||
u32 slot_get_base(struct device *dev, u32 unit, u32 slot)
|
||||
{
|
||||
struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
|
||||
|
@ -389,6 +598,8 @@ int kso_init_data(struct device *dev, u32 unit)
|
|||
smpriv->pagedesc[unit].ksdata = keystore_data;
|
||||
smpriv->pagedesc[unit].ksdata->base_address =
|
||||
smpriv->pagedesc[unit].pg_base;
|
||||
smpriv->pagedesc[unit].ksdata->phys_address =
|
||||
smpriv->pagedesc[unit].pg_phys;
|
||||
|
||||
retval = 0;
|
||||
|
||||
|
@ -430,6 +641,7 @@ void sm_init_keystore(struct device *dev)
|
|||
smpriv->slot_alloc = slot_alloc;
|
||||
smpriv->slot_dealloc = slot_dealloc;
|
||||
smpriv->slot_get_address = slot_get_address;
|
||||
smpriv->slot_get_physical = slot_get_physical;
|
||||
smpriv->slot_get_base = slot_get_base;
|
||||
smpriv->slot_get_offset = slot_get_offset;
|
||||
smpriv->slot_get_slot_size = slot_get_slot_size;
|
||||
|
@ -580,98 +792,148 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL(sm_keystore_slot_read);
|
||||
|
||||
int sm_keystore_slot_encapsulate(struct device *dev, u32 unit, u32 inslot,
|
||||
u32 outslot, u16 secretlen, u8 *keymod,
|
||||
u16 keymodlen)
|
||||
/*
|
||||
* Blacken a clear key in a slot. Operates "in place".
|
||||
* Limited to class 1 keys at the present time
|
||||
*/
|
||||
int sm_keystore_cover_key(struct device *dev, u32 unit, u32 slot,
|
||||
u16 key_length, u8 keyauth)
|
||||
{
|
||||
struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
|
||||
int retval = 0;
|
||||
u32 slot_length, dsize, jstat;
|
||||
u8 __iomem *slotaddr;
|
||||
void *slotphys;
|
||||
u32 dsize, jstat;
|
||||
u32 __iomem *coverdesc = NULL;
|
||||
|
||||
/* Get the address of the object in the slot */
|
||||
slotaddr = (u8 *)smpriv->slot_get_address(dev, unit, slot);
|
||||
slotphys = (u8 *)smpriv->slot_get_physical(dev, unit, slot);
|
||||
|
||||
dsize = blacken_key_jobdesc(&coverdesc, slotphys, key_length, keyauth);
|
||||
if (!dsize)
|
||||
return -ENOMEM;
|
||||
jstat = sm_key_job(dev, coverdesc);
|
||||
if (jstat)
|
||||
retval = -EIO;
|
||||
|
||||
kfree(coverdesc);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(sm_keystore_cover_key);
|
||||
|
||||
/* Export a black/red key to a blob in external memory */
|
||||
int sm_keystore_slot_export(struct device *dev, u32 unit, u32 slot, u8 keycolor,
|
||||
u8 keyauth, u8 *outbuf, u16 keylen, u8 *keymod)
|
||||
{
|
||||
struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
|
||||
int retval = 0;
|
||||
u8 __iomem *slotaddr, *lkeymod;
|
||||
u8 __iomem *slotphys;
|
||||
dma_addr_t keymod_dma, outbuf_dma;
|
||||
u32 dsize, jstat;
|
||||
u32 __iomem *encapdesc = NULL;
|
||||
u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr;
|
||||
dma_addr_t keymod_dma;
|
||||
|
||||
/* Ensure that the full blob will fit in the key slot */
|
||||
slot_length = smpriv->slot_get_slot_size(dev, unit, outslot);
|
||||
if ((secretlen + 48) > slot_length)
|
||||
goto out;
|
||||
/* Get the base address(es) of the specified slot */
|
||||
slotaddr = (u8 *)smpriv->slot_get_address(dev, unit, slot);
|
||||
slotphys = smpriv->slot_get_physical(dev, unit, slot);
|
||||
|
||||
/* Get the base addresses of both keystore slots */
|
||||
inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot);
|
||||
outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot);
|
||||
/* Build/map/flush the key modifier */
|
||||
lkeymod = kmalloc(SECMEM_KEYMOD_LEN, GFP_KERNEL | GFP_DMA);
|
||||
memcpy(lkeymod, keymod, SECMEM_KEYMOD_LEN);
|
||||
keymod_dma = dma_map_single(dev, lkeymod, SECMEM_KEYMOD_LEN,
|
||||
DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(dev, keymod_dma, SECMEM_KEYMOD_LEN,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
/* Build the key modifier */
|
||||
lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA);
|
||||
memcpy(lkeymod, keymod, keymodlen);
|
||||
keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
|
||||
outbuf_dma = dma_map_single(dev, outbuf,
|
||||
AES_BLOCK_PAD(keylen) + BLOB_OVERHEAD,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
/* Build the encapsulation job descriptor */
|
||||
dsize = blob_encap_desc(&encapdesc, keymod_dma, keymodlen,
|
||||
__pa(inpslotaddr), __pa(outslotaddr),
|
||||
secretlen, 0);
|
||||
dsize = blob_encap_jobdesc(&encapdesc, keymod_dma, slotphys, outbuf_dma,
|
||||
keylen, keycolor, SM_SECMEM, keyauth);
|
||||
if (!dsize) {
|
||||
dev_err(dev, "can't alloc an encap descriptor\n");
|
||||
dev_err(dev, "can't alloc an encapsulation descriptor\n");
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
jstat = sm_key_job(dev, encapdesc);
|
||||
dma_sync_single_for_cpu(dev, outbuf_dma, keylen, DMA_FROM_DEVICE);
|
||||
|
||||
dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
|
||||
kfree(encapdesc);
|
||||
if (jstat)
|
||||
retval = -EIO;
|
||||
|
||||
out:
|
||||
dma_unmap_single(dev, outbuf_dma, AES_BLOCK_PAD(keylen) + BLOB_OVERHEAD,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_unmap_single(dev, keymod_dma, SECMEM_KEYMOD_LEN, DMA_TO_DEVICE);
|
||||
kfree(encapdesc);
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(sm_keystore_slot_encapsulate);
|
||||
EXPORT_SYMBOL(sm_keystore_slot_export);
|
||||
|
||||
int sm_keystore_slot_decapsulate(struct device *dev, u32 unit, u32 inslot,
|
||||
u32 outslot, u16 secretlen, u8 *keymod,
|
||||
u16 keymodlen)
|
||||
/* Import a black/red key from a blob residing in external memory */
|
||||
int sm_keystore_slot_import(struct device *dev, u32 unit, u32 slot, u8 keycolor,
|
||||
u8 keyauth, u8 *inbuf, u16 keylen, u8 *keymod)
|
||||
{
|
||||
struct caam_drv_private_sm *smpriv = dev_get_drvdata(dev);
|
||||
int retval = 0;
|
||||
u32 slot_length, dsize, jstat;
|
||||
u8 __iomem *slotaddr, *lkeymod;
|
||||
u8 __iomem *slotphys;
|
||||
dma_addr_t keymod_dma, inbuf_dma;
|
||||
u32 dsize, jstat;
|
||||
u32 __iomem *decapdesc = NULL;
|
||||
u8 __iomem *lkeymod, *inpslotaddr, *outslotaddr;
|
||||
dma_addr_t keymod_dma;
|
||||
|
||||
/* Ensure that the decap data will fit in the key slot */
|
||||
slot_length = smpriv->slot_get_slot_size(dev, unit, outslot);
|
||||
if (secretlen > slot_length)
|
||||
goto out;
|
||||
/* Get the base address(es) of the specified slot */
|
||||
slotaddr = (u8 *)smpriv->slot_get_address(dev, unit, slot);
|
||||
slotphys = smpriv->slot_get_physical(dev, unit, slot);
|
||||
|
||||
/* Get the base addresses of both keystore slots */
|
||||
inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot);
|
||||
outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot);
|
||||
/* Build/map/flush the key modifier */
|
||||
lkeymod = kmalloc(SECMEM_KEYMOD_LEN, GFP_KERNEL | GFP_DMA);
|
||||
memcpy(lkeymod, keymod, SECMEM_KEYMOD_LEN);
|
||||
keymod_dma = dma_map_single(dev, lkeymod, SECMEM_KEYMOD_LEN,
|
||||
DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(dev, keymod_dma, SECMEM_KEYMOD_LEN,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
/* Build the key modifier */
|
||||
lkeymod = kmalloc(keymodlen, GFP_KERNEL | GFP_DMA);
|
||||
memcpy(lkeymod, keymod, keymodlen);
|
||||
keymod_dma = dma_map_single(dev, lkeymod, keymodlen, DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
|
||||
inbuf_dma = dma_map_single(dev, inbuf,
|
||||
AES_BLOCK_PAD(keylen) + BLOB_OVERHEAD,
|
||||
DMA_TO_DEVICE);
|
||||
dma_sync_single_for_device(dev, inbuf_dma,
|
||||
AES_BLOCK_PAD(keylen) + BLOB_OVERHEAD,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
/* Build the decapsulation job descriptor */
|
||||
dsize = blob_decap_desc(&decapdesc, keymod_dma, keymodlen,
|
||||
__pa(inpslotaddr), __pa(outslotaddr),
|
||||
secretlen, 0);
|
||||
/* Build the encapsulation job descriptor */
|
||||
dsize = blob_decap_jobdesc(&decapdesc, keymod_dma, inbuf_dma, slotphys,
|
||||
keylen, keycolor, SM_SECMEM, keyauth);
|
||||
if (!dsize) {
|
||||
dev_err(dev, "can't alloc a decap descriptor\n");
|
||||
dev_err(dev, "can't alloc a decapsulation descriptor\n");
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
jstat = sm_key_job(dev, decapdesc);
|
||||
|
||||
dma_unmap_single(dev, keymod_dma, keymodlen, DMA_TO_DEVICE);
|
||||
kfree(decapdesc);
|
||||
/*
|
||||
* May want to expand upon error meanings a bit. Any CAAM status
|
||||
* is reported as EIO, but we might want to look for something more
|
||||
* meaningful for something like an ICV error on restore, otherwise
|
||||
* the caller is left guessing.
|
||||
*/
|
||||
if (jstat)
|
||||
retval = -EIO;
|
||||
|
||||
out:
|
||||
dma_unmap_single(dev, inbuf_dma, AES_BLOCK_PAD(keylen) + BLOB_OVERHEAD,
|
||||
DMA_TO_DEVICE);
|
||||
dma_unmap_single(dev, keymod_dma, SECMEM_KEYMOD_LEN, DMA_TO_DEVICE);
|
||||
kfree(decapdesc);
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(sm_keystore_slot_decapsulate);
|
||||
|
||||
EXPORT_SYMBOL(sm_keystore_slot_import);
|
||||
|
||||
/*
|
||||
* Initialization/shutdown subsystem
|
||||
|
@ -782,6 +1044,9 @@ int caam_sm_startup(struct platform_device *pdev)
|
|||
(pgstat & SMCS_PART_SHIFT) >> SMCS_PART_MASK;
|
||||
lpagedesc[page].pg_base = ctrlpriv->sm_base +
|
||||
((smpriv->page_size * page) / sizeof(u32));
|
||||
/* FIXME: get base address from platform property... */
|
||||
lpagedesc[page].pg_phys = (u32 *)0x00100000 +
|
||||
((smpriv->page_size * page) / sizeof(u32));
|
||||
lpagect++;
|
||||
#ifdef SM_DEBUG
|
||||
dev_info(smdev,
|
||||
|
|
Loading…
Reference in New Issue
Block a user