Re: [PATCH v6 1/6] crypto: mxs-dcp: Add support for hardware-bound keys
On Thu Mar 7, 2024 at 5:38 PM EET, David Gstir wrote: > DCP (Data Co-Processor) is able to derive private keys for a fused > random seed, which can be referenced by handle but not accessed by > the CPU. Similarly, DCP is able to store arbitrary keys in four > dedicated key slots located in its secure memory area (internal SRAM). > These keys can be used to perform AES encryption. > > Expose these derived keys and key slots through the crypto API via their > handle. The main purpose is to add DCP-backed trusted keys. Other > use cases are possible too (see similar existing paes implementations), > but these should carefully be evaluated as e.g. enabling AF_ALG will > give userspace full access to use keys. In scenarios with untrustworthy > userspace, this will enable en-/decryption oracles. > > Co-developed-by: Richard Weinberger > Signed-off-by: Richard Weinberger > Co-developed-by: David Oberhollenzer > Signed-off-by: David Oberhollenzer > Signed-off-by: David Gstir > Acked-by: Herbert Xu > --- > drivers/crypto/mxs-dcp.c | 104 ++- > include/soc/fsl/dcp.h| 20 > 2 files changed, 113 insertions(+), 11 deletions(-) > create mode 100644 include/soc/fsl/dcp.h > > diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c > index 2b3ebe0db3a6..057d73c370b7 100644 > --- a/drivers/crypto/mxs-dcp.c > +++ b/drivers/crypto/mxs-dcp.c > @@ -15,6 +15,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -101,6 +102,7 @@ struct dcp_async_ctx { > struct crypto_skcipher *fallback; > unsigned intkey_len; > uint8_t key[AES_KEYSIZE_128]; > + boolkey_referenced; > }; > > struct dcp_aes_req_ctx { > @@ -155,6 +157,7 @@ static struct dcp *global_sdcp; > #define MXS_DCP_CONTROL0_HASH_TERM (1 << 13) > #define MXS_DCP_CONTROL0_HASH_INIT (1 << 12) > #define MXS_DCP_CONTROL0_PAYLOAD_KEY (1 << 11) > +#define MXS_DCP_CONTROL0_OTP_KEY (1 << 10) > #define MXS_DCP_CONTROL0_CIPHER_ENCRYPT (1 << 8) > #define MXS_DCP_CONTROL0_CIPHER_INIT (1 << 9) > #define MXS_DCP_CONTROL0_ENABLE_HASH (1 << 6) > @@ -168,6 +171,8 @@ static struct dcp *global_sdcp; > #define MXS_DCP_CONTROL1_CIPHER_MODE_ECB (0 << 4) > #define MXS_DCP_CONTROL1_CIPHER_SELECT_AES128(0 << 0) > > +#define MXS_DCP_CONTROL1_KEY_SELECT_SHIFT8 > + > static int mxs_dcp_start_dma(struct dcp_async_ctx *actx) > { > int dma_err; > @@ -224,13 +229,16 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, > struct dcp *sdcp = global_sdcp; > struct dcp_dma_desc *desc = >coh->desc[actx->chan]; > struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req); > + bool key_referenced = actx->key_referenced; > int ret; > > - key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key, > - 2 * AES_KEYSIZE_128, DMA_TO_DEVICE); > - ret = dma_mapping_error(sdcp->dev, key_phys); > - if (ret) > - return ret; > + if (!key_referenced) { > + key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key, > + 2 * AES_KEYSIZE_128, DMA_TO_DEVICE); > + ret = dma_mapping_error(sdcp->dev, key_phys); > + if (ret) > + return ret; > + } > > src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf, > DCP_BUF_SZ, DMA_TO_DEVICE); > @@ -255,8 +263,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, > MXS_DCP_CONTROL0_INTERRUPT | > MXS_DCP_CONTROL0_ENABLE_CIPHER; > > - /* Payload contains the key. */ > - desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; > + if (key_referenced) > + /* Set OTP key bit to select the key via KEY_SELECT. */ > + desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY; > + else > + /* Payload contains the key. */ > + desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; > > if (rctx->enc) > desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT; > @@ -270,6 +282,9 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, > else > desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_CBC; > > + if (key_referenced) > + desc->control1 |= sdcp->coh->aes_key[0] << > MXS_DCP_CONTROL1_KEY_SELECT_SHIFT; > + > desc->next_cmd_addr = 0; > desc->source = src_phys; > desc->destination = dst_phys; > @@ -284,9 +299,9 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, > err_dst: > dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE); > err_src: > - dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128, > - DMA_TO_DEVICE); > - > + if (!key_referenced) > +
[PATCH v6 1/6] crypto: mxs-dcp: Add support for hardware-bound keys
DCP (Data Co-Processor) is able to derive private keys for a fused random seed, which can be referenced by handle but not accessed by the CPU. Similarly, DCP is able to store arbitrary keys in four dedicated key slots located in its secure memory area (internal SRAM). These keys can be used to perform AES encryption. Expose these derived keys and key slots through the crypto API via their handle. The main purpose is to add DCP-backed trusted keys. Other use cases are possible too (see similar existing paes implementations), but these should carefully be evaluated as e.g. enabling AF_ALG will give userspace full access to use keys. In scenarios with untrustworthy userspace, this will enable en-/decryption oracles. Co-developed-by: Richard Weinberger Signed-off-by: Richard Weinberger Co-developed-by: David Oberhollenzer Signed-off-by: David Oberhollenzer Signed-off-by: David Gstir Acked-by: Herbert Xu --- drivers/crypto/mxs-dcp.c | 104 ++- include/soc/fsl/dcp.h| 20 2 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 include/soc/fsl/dcp.h diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c index 2b3ebe0db3a6..057d73c370b7 100644 --- a/drivers/crypto/mxs-dcp.c +++ b/drivers/crypto/mxs-dcp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -101,6 +102,7 @@ struct dcp_async_ctx { struct crypto_skcipher *fallback; unsigned intkey_len; uint8_t key[AES_KEYSIZE_128]; + boolkey_referenced; }; struct dcp_aes_req_ctx { @@ -155,6 +157,7 @@ static struct dcp *global_sdcp; #define MXS_DCP_CONTROL0_HASH_TERM (1 << 13) #define MXS_DCP_CONTROL0_HASH_INIT (1 << 12) #define MXS_DCP_CONTROL0_PAYLOAD_KEY (1 << 11) +#define MXS_DCP_CONTROL0_OTP_KEY (1 << 10) #define MXS_DCP_CONTROL0_CIPHER_ENCRYPT(1 << 8) #define MXS_DCP_CONTROL0_CIPHER_INIT (1 << 9) #define MXS_DCP_CONTROL0_ENABLE_HASH (1 << 6) @@ -168,6 +171,8 @@ static struct dcp *global_sdcp; #define MXS_DCP_CONTROL1_CIPHER_MODE_ECB (0 << 4) #define MXS_DCP_CONTROL1_CIPHER_SELECT_AES128 (0 << 0) +#define MXS_DCP_CONTROL1_KEY_SELECT_SHIFT 8 + static int mxs_dcp_start_dma(struct dcp_async_ctx *actx) { int dma_err; @@ -224,13 +229,16 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, struct dcp *sdcp = global_sdcp; struct dcp_dma_desc *desc = >coh->desc[actx->chan]; struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req); + bool key_referenced = actx->key_referenced; int ret; - key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key, - 2 * AES_KEYSIZE_128, DMA_TO_DEVICE); - ret = dma_mapping_error(sdcp->dev, key_phys); - if (ret) - return ret; + if (!key_referenced) { + key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key, + 2 * AES_KEYSIZE_128, DMA_TO_DEVICE); + ret = dma_mapping_error(sdcp->dev, key_phys); + if (ret) + return ret; + } src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf, DCP_BUF_SZ, DMA_TO_DEVICE); @@ -255,8 +263,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, MXS_DCP_CONTROL0_INTERRUPT | MXS_DCP_CONTROL0_ENABLE_CIPHER; - /* Payload contains the key. */ - desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; + if (key_referenced) + /* Set OTP key bit to select the key via KEY_SELECT. */ + desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY; + else + /* Payload contains the key. */ + desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; if (rctx->enc) desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT; @@ -270,6 +282,9 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, else desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_CBC; + if (key_referenced) + desc->control1 |= sdcp->coh->aes_key[0] << MXS_DCP_CONTROL1_KEY_SELECT_SHIFT; + desc->next_cmd_addr = 0; desc->source = src_phys; desc->destination = dst_phys; @@ -284,9 +299,9 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx, err_dst: dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE); err_src: - dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128, -DMA_TO_DEVICE); - + if (!key_referenced) + dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128, +DMA_TO_DEVICE); return ret; } @@ -453,7 +468,7 @@ static int mxs_dcp_aes_enqueue(struct