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:
Steve Cornelius 2013-07-23 20:49:29 -07:00 committed by Leonard Crestez
parent 8433c811e9
commit c7d4f9db10
2 changed files with 409 additions and 112 deletions

View File

@ -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);

View File

@ -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,