|
@@ -230,6 +230,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
|
|
|
dma_addr_t dst_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_out_buf,
|
|
|
DCP_BUF_SZ, DMA_FROM_DEVICE);
|
|
|
|
|
|
+ if (actx->fill % AES_BLOCK_SIZE) {
|
|
|
+ dev_err(sdcp->dev, "Invalid block size!\n");
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto aes_done_run;
|
|
|
+ }
|
|
|
+
|
|
|
/* Fill in the DMA descriptor. */
|
|
|
desc->control0 = MXS_DCP_CONTROL0_DECR_SEMAPHORE |
|
|
|
MXS_DCP_CONTROL0_INTERRUPT |
|
|
@@ -259,6 +265,7 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
|
|
|
|
|
|
ret = mxs_dcp_start_dma(actx);
|
|
|
|
|
|
+aes_done_run:
|
|
|
dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128,
|
|
|
DMA_TO_DEVICE);
|
|
|
dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
|
|
@@ -285,13 +292,15 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
|
|
|
|
|
|
uint8_t *out_tmp, *src_buf, *dst_buf = NULL;
|
|
|
uint32_t dst_off = 0;
|
|
|
+ uint32_t last_out_len = 0;
|
|
|
|
|
|
uint8_t *key = sdcp->coh->aes_key;
|
|
|
|
|
|
int ret = 0;
|
|
|
int split = 0;
|
|
|
- unsigned int i, len, clen, rem = 0;
|
|
|
+ unsigned int i, len, clen, rem = 0, tlen = 0;
|
|
|
int init = 0;
|
|
|
+ bool limit_hit = false;
|
|
|
|
|
|
actx->fill = 0;
|
|
|
|
|
@@ -310,6 +319,11 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
|
|
|
for_each_sg(req->src, src, nents, i) {
|
|
|
src_buf = sg_virt(src);
|
|
|
len = sg_dma_len(src);
|
|
|
+ tlen += len;
|
|
|
+ limit_hit = tlen > req->nbytes;
|
|
|
+
|
|
|
+ if (limit_hit)
|
|
|
+ len = req->nbytes - (tlen - len);
|
|
|
|
|
|
do {
|
|
|
if (actx->fill + len > out_off)
|
|
@@ -326,13 +340,15 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
|
|
|
* If we filled the buffer or this is the last SG,
|
|
|
* submit the buffer.
|
|
|
*/
|
|
|
- if (actx->fill == out_off || sg_is_last(src)) {
|
|
|
+ if (actx->fill == out_off || sg_is_last(src) ||
|
|
|
+ limit_hit) {
|
|
|
ret = mxs_dcp_run_aes(actx, req, init);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
init = 0;
|
|
|
|
|
|
out_tmp = out_buf;
|
|
|
+ last_out_len = actx->fill;
|
|
|
while (dst && actx->fill) {
|
|
|
if (!split) {
|
|
|
dst_buf = sg_virt(dst);
|
|
@@ -355,6 +371,19 @@ static int mxs_dcp_aes_block_crypt(struct crypto_async_request *arq)
|
|
|
}
|
|
|
}
|
|
|
} while (len);
|
|
|
+
|
|
|
+ if (limit_hit)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Copy the IV for CBC for chaining */
|
|
|
+ if (!rctx->ecb) {
|
|
|
+ if (rctx->enc)
|
|
|
+ memcpy(req->info, out_buf+(last_out_len-AES_BLOCK_SIZE),
|
|
|
+ AES_BLOCK_SIZE);
|
|
|
+ else
|
|
|
+ memcpy(req->info, in_buf+(last_out_len-AES_BLOCK_SIZE),
|
|
|
+ AES_BLOCK_SIZE);
|
|
|
}
|
|
|
|
|
|
return ret;
|