Skip to content

Commit

Permalink
crypto: mxs-dcp - Fix AES issues
Browse files Browse the repository at this point in the history
The DCP driver does not obey cryptlen, when doing android CTS this
results in passing to hardware input stream lengths which are not
multiple of block size.

Add a check to prevent future erroneous stream lengths from reaching the
hardware and adjust the scatterlist walking code to obey cryptlen.

Also properly copy-out the IV for chaining.

Signed-off-by: Radu Solea <radu.solea@nxp.com>
Signed-off-by: Franck LENORMAND <franck.lenormand@nxp.com>
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Radu Solea authored and Herbert Xu committed Oct 8, 2018
1 parent c709eeb commit fadd7a6
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions drivers/crypto/mxs-dcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -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);
Expand All @@ -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;

Expand All @@ -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)
Expand All @@ -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);
Expand All @@ -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;
Expand Down

0 comments on commit fadd7a6

Please sign in to comment.