Skip to content

Commit c709eeb

Browse files
Radu Soleaherbertx
authored andcommitted
crypto: mxs-dcp - Fix SHA null hashes and output length
DCP writes at least 32 bytes in the output buffer instead of hash length as documented. Add intermediate buffer to prevent write out of bounds. When requested to produce null hashes DCP fails to produce valid output. Add software workaround to bypass hardware and return valid output. Signed-off-by: Radu Solea <radu.solea@nxp.com> Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent ea9e756 commit c709eeb

File tree

1 file changed

+37
-10
lines changed

1 file changed

+37
-10
lines changed

drivers/crypto/mxs-dcp.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,24 @@
2828

2929
#define DCP_MAX_CHANS 4
3030
#define DCP_BUF_SZ PAGE_SIZE
31+
#define DCP_SHA_PAY_SZ 64
3132

3233
#define DCP_ALIGNMENT 64
3334

35+
/*
36+
* Null hashes to align with hw behavior on imx6sl and ull
37+
* these are flipped for consistency with hw output
38+
*/
39+
const uint8_t sha1_null_hash[] =
40+
"\x09\x07\xd8\xaf\x90\x18\x60\x95\xef\xbf"
41+
"\x55\x32\x0d\x4b\x6b\x5e\xee\xa3\x39\xda";
42+
43+
const uint8_t sha256_null_hash[] =
44+
"\x55\xb8\x52\x78\x1b\x99\x95\xa4"
45+
"\x4c\x93\x9b\x64\xe4\x41\xae\x27"
46+
"\x24\xb9\x6f\x99\xc8\xf4\xfb\x9a"
47+
"\x14\x1c\xfc\x98\x42\xc4\xb0\xe3";
48+
3449
/* DCP DMA descriptor. */
3550
struct dcp_dma_desc {
3651
uint32_t next_cmd_addr;
@@ -48,6 +63,7 @@ struct dcp_coherent_block {
4863
uint8_t aes_in_buf[DCP_BUF_SZ];
4964
uint8_t aes_out_buf[DCP_BUF_SZ];
5065
uint8_t sha_in_buf[DCP_BUF_SZ];
66+
uint8_t sha_out_buf[DCP_SHA_PAY_SZ];
5167

5268
uint8_t aes_key[2 * AES_KEYSIZE_128];
5369

@@ -513,8 +529,6 @@ static int mxs_dcp_run_sha(struct ahash_request *req)
513529
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
514530
struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
515531
struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
516-
struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
517-
518532
struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
519533

520534
dma_addr_t digest_phys = 0;
@@ -536,20 +550,34 @@ static int mxs_dcp_run_sha(struct ahash_request *req)
536550
desc->payload = 0;
537551
desc->status = 0;
538552

553+
/*
554+
* Align driver with hw behavior when generating null hashes
555+
*/
556+
if (rctx->init && rctx->fini && desc->size == 0) {
557+
struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
558+
const uint8_t *sha_buf =
559+
(actx->alg == MXS_DCP_CONTROL1_HASH_SELECT_SHA1) ?
560+
sha1_null_hash : sha256_null_hash;
561+
memcpy(sdcp->coh->sha_out_buf, sha_buf, halg->digestsize);
562+
ret = 0;
563+
goto done_run;
564+
}
565+
539566
/* Set HASH_TERM bit for last transfer block. */
540567
if (rctx->fini) {
541-
digest_phys = dma_map_single(sdcp->dev, req->result,
542-
halg->digestsize, DMA_FROM_DEVICE);
568+
digest_phys = dma_map_single(sdcp->dev, sdcp->coh->sha_out_buf,
569+
DCP_SHA_PAY_SZ, DMA_FROM_DEVICE);
543570
desc->control0 |= MXS_DCP_CONTROL0_HASH_TERM;
544571
desc->payload = digest_phys;
545572
}
546573

547574
ret = mxs_dcp_start_dma(actx);
548575

549576
if (rctx->fini)
550-
dma_unmap_single(sdcp->dev, digest_phys, halg->digestsize,
577+
dma_unmap_single(sdcp->dev, digest_phys, DCP_SHA_PAY_SZ,
551578
DMA_FROM_DEVICE);
552579

580+
done_run:
553581
dma_unmap_single(sdcp->dev, buf_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
554582

555583
return ret;
@@ -567,6 +595,7 @@ static int dcp_sha_req_to_buf(struct crypto_async_request *arq)
567595
const int nents = sg_nents(req->src);
568596

569597
uint8_t *in_buf = sdcp->coh->sha_in_buf;
598+
uint8_t *out_buf = sdcp->coh->sha_out_buf;
570599

571600
uint8_t *src_buf;
572601

@@ -621,11 +650,9 @@ static int dcp_sha_req_to_buf(struct crypto_async_request *arq)
621650

622651
actx->fill = 0;
623652

624-
/* For some reason, the result is flipped. */
625-
for (i = 0; i < halg->digestsize / 2; i++) {
626-
swap(req->result[i],
627-
req->result[halg->digestsize - i - 1]);
628-
}
653+
/* For some reason the result is flipped */
654+
for (i = 0; i < halg->digestsize; i++)
655+
req->result[i] = out_buf[halg->digestsize - i - 1];
629656
}
630657

631658
return 0;

0 commit comments

Comments
 (0)