#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)
{
}
#endif
+#define INITIAL_DESCSZ 16 /* size of tmp buffer for descriptor const. */
+
/*
- * Construct a secure memory blob encapsulation job descriptor
+ * 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 hold new (to be allocated) pointer to the generated
- * descriptor for later use. Calling thread can kfree the
+ * - 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 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
+ * - 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.
*
- * 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)
+static int blacken_key_jobdesc(u32 **desc, void *key, u16 keysz, bool auth)
{
u32 *tdesc, tmpdesc[INITIAL_DESCSZ];
u16 dsize, idx;
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);
}
/*
- * 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).
+ *
+ * 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
*
- * Note: this uses 32-bit pointers at present
+ * 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;
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);
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, "slot_get_physical(): slot %d is 0x%08x\n", 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);
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;
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;
}
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:
- return retval;
+ 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 addresses of both keystore slots */
- inpslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, inslot);
- outslotaddr = (u8 *)smpriv->slot_get_address(dev, unit, outslot);
+ /* 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);
+
+ /* 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);
+
+ 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 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);
-
- /* 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:
- return retval;
+ 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
(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,