diff options
author | Franck LENORMAND <franck.lenormand@nxp.com> | 2018-06-21 15:19:07 +0200 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:32:49 +0800 |
commit | 9f91864c2c7d3c4039bc0648721b07689146ba0c (patch) | |
tree | 5e5be6af4aa12cf574f6030a219826f464b07185 /drivers/crypto | |
parent | f06ccb125bbcd3e743d0d0eaabd158c21d3c5361 (diff) |
MLK-18082: crypto: caam: sm: Fix encap/decap function to handle errors
Explicit the use of the ring device to manage the operations related
to DMA.
Some values from DMA functions were not tested hence the issues
were making the descriptor to fail later and make it harder to debug.
Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/caam/sm_store.c | 141 |
1 files changed, 108 insertions, 33 deletions
diff --git a/drivers/crypto/caam/sm_store.c b/drivers/crypto/caam/sm_store.c index 0f105c8b50fa..a3427565d4c1 100644 --- a/drivers/crypto/caam/sm_store.c +++ b/drivers/crypto/caam/sm_store.c @@ -869,21 +869,44 @@ int sm_keystore_slot_export(struct device *dev, u32 unit, u32 slot, u8 keycolor, dma_addr_t keymod_dma, outbuf_dma; u32 dsize, jstat; u32 __iomem *encapdesc = NULL; + struct device *dev_for_dma_op; + + /* Use the ring as device for DMA operations */ + dev_for_dma_op = smpriv->smringdev; /* 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 */ + /* Allocate memory for key modifier compatible with DMA */ 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); + if (!lkeymod) { + retval = (-ENOMEM); + goto exit; + } - outbuf_dma = dma_map_single(dev, outbuf, keylen + BLOB_OVERHEAD, - DMA_FROM_DEVICE); + /* Get DMA address for the key modifier */ + keymod_dma = dma_map_single(dev_for_dma_op, lkeymod, + SECMEM_KEYMOD_LEN, DMA_TO_DEVICE); + if (dma_mapping_error(dev_for_dma_op, keymod_dma)) { + dev_err(dev, "unable to map keymod: %p\n", lkeymod); + retval = (-ENOMEM); + goto free_keymod; + } + + /* Copy the keymod and synchronize the DMA */ + memcpy(lkeymod, keymod, SECMEM_KEYMOD_LEN); + dma_sync_single_for_device(dev_for_dma_op, keymod_dma, + SECMEM_KEYMOD_LEN, DMA_TO_DEVICE); + + /* Get DMA address for the destination */ + outbuf_dma = dma_map_single(dev_for_dma_op, outbuf, + keylen + BLOB_OVERHEAD, DMA_FROM_DEVICE); + if (dma_mapping_error(dev_for_dma_op, outbuf_dma)) { + dev_err(dev, "unable to map outbuf: %p\n", outbuf); + retval = (-ENOMEM); + goto unmap_keymod; + } /* Build the encapsulation job descriptor */ dsize = blob_encap_jobdesc(&encapdesc, keymod_dma, slotphys, outbuf_dma, @@ -891,20 +914,35 @@ int sm_keystore_slot_export(struct device *dev, u32 unit, u32 slot, u8 keycolor, if (!dsize) { dev_err(dev, "can't alloc an encapsulation descriptor\n"); retval = -ENOMEM; - goto out; + goto unmap_outbuf; } + + /* Run the job */ jstat = sm_key_job(dev, encapdesc); - dma_sync_single_for_cpu(dev, outbuf_dma, keylen + BLOB_OVERHEAD, - DMA_FROM_DEVICE); - if (jstat) - retval = -EIO; + if (jstat) { + retval = (-EIO); + goto free_desc; + } -out: - dma_unmap_single(dev, outbuf_dma, keylen + BLOB_OVERHEAD, - DMA_FROM_DEVICE); - dma_unmap_single(dev, keymod_dma, SECMEM_KEYMOD_LEN, DMA_TO_DEVICE); + /* Synchronize the data received */ + dma_sync_single_for_cpu(dev_for_dma_op, outbuf_dma, + keylen + BLOB_OVERHEAD, DMA_FROM_DEVICE); + +free_desc: kfree(encapdesc); +unmap_outbuf: + dma_unmap_single(dev_for_dma_op, outbuf_dma, keylen + BLOB_OVERHEAD, + DMA_FROM_DEVICE); + +unmap_keymod: + dma_unmap_single(dev_for_dma_op, keymod_dma, SECMEM_KEYMOD_LEN, + DMA_TO_DEVICE); + +free_keymod: + kfree(lkeymod); + +exit: return retval; } EXPORT_SYMBOL(sm_keystore_slot_export); @@ -920,23 +958,48 @@ int sm_keystore_slot_import(struct device *dev, u32 unit, u32 slot, u8 keycolor, dma_addr_t keymod_dma, inbuf_dma; u32 dsize, jstat; u32 __iomem *decapdesc = NULL; + struct device *dev_for_dma_op; + + /* Use the ring as device for DMA operations */ + dev_for_dma_op = smpriv->smringdev; /* 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 */ + /* Allocate memory for key modifier compatible with DMA */ lkeymod = kmalloc(SECMEM_KEYMOD_LEN, GFP_KERNEL | GFP_DMA); + if (!lkeymod) { + retval = (-ENOMEM); + goto exit; + } + + /* Get DMA address for the key modifier */ + keymod_dma = dma_map_single(dev_for_dma_op, lkeymod, + SECMEM_KEYMOD_LEN, DMA_TO_DEVICE); + if (dma_mapping_error(dev_for_dma_op, keymod_dma)) { + dev_err(dev, "unable to map keymod: %p\n", lkeymod); + retval = (-ENOMEM); + goto free_keymod; + } + + /* Copy the keymod and synchronize the 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); + dma_sync_single_for_device(dev_for_dma_op, keymod_dma, + SECMEM_KEYMOD_LEN, DMA_TO_DEVICE); + + /* Get DMA address for the input */ + inbuf_dma = dma_map_single(dev_for_dma_op, inbuf, + keylen + BLOB_OVERHEAD, DMA_TO_DEVICE); + if (dma_mapping_error(dev_for_dma_op, inbuf_dma)) { + dev_err(dev, "unable to map inbuf: %p\n", (void *)inbuf_dma); + retval = (-ENOMEM); + goto unmap_keymod; + } - inbuf_dma = dma_map_single(dev, inbuf, keylen + BLOB_OVERHEAD, - DMA_TO_DEVICE); - dma_sync_single_for_device(dev, inbuf_dma, keylen + BLOB_OVERHEAD, - DMA_TO_DEVICE); + /* synchronize the DMA */ + dma_sync_single_for_device(dev_for_dma_op, inbuf_dma, + keylen + BLOB_OVERHEAD, DMA_TO_DEVICE); /* Build the encapsulation job descriptor */ dsize = blob_decap_jobdesc(&decapdesc, keymod_dma, inbuf_dma, slotphys, @@ -944,9 +1007,10 @@ int sm_keystore_slot_import(struct device *dev, u32 unit, u32 slot, u8 keycolor, if (!dsize) { dev_err(dev, "can't alloc a decapsulation descriptor\n"); retval = -ENOMEM; - goto out; + goto unmap_inbuf; } + /* Run the job */ jstat = sm_key_job(dev, decapdesc); /* @@ -955,15 +1019,26 @@ int sm_keystore_slot_import(struct device *dev, u32 unit, u32 slot, u8 keycolor, * meaningful for something like an ICV error on restore, otherwise * the caller is left guessing. */ - if (jstat) - retval = -EIO; + if (jstat) { + retval = (-EIO); + goto free_desc; + } -out: - dma_unmap_single(dev, inbuf_dma, keylen + BLOB_OVERHEAD, - DMA_TO_DEVICE); - dma_unmap_single(dev, keymod_dma, SECMEM_KEYMOD_LEN, DMA_TO_DEVICE); +free_desc: kfree(decapdesc); +unmap_inbuf: + dma_unmap_single(dev_for_dma_op, inbuf_dma, keylen + BLOB_OVERHEAD, + DMA_TO_DEVICE); + +unmap_keymod: + dma_unmap_single(dev_for_dma_op, keymod_dma, SECMEM_KEYMOD_LEN, + DMA_TO_DEVICE); + +free_keymod: + kfree(lkeymod); + +exit: return retval; } EXPORT_SYMBOL(sm_keystore_slot_import); |