Skip to content

Commit 3d16af0

Browse files
iokilljarkkojs
authored andcommitted
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 <[email protected]> Signed-off-by: Richard Weinberger <[email protected]> Co-developed-by: David Oberhollenzer <[email protected]> Signed-off-by: David Oberhollenzer <[email protected]> Signed-off-by: David Gstir <[email protected]> Acked-by: Herbert Xu <[email protected]> Reviewed-by: Jarkko Sakkinen <[email protected]> Signed-off-by: Jarkko Sakkinen <[email protected]>
1 parent 45db3ab commit 3d16af0

File tree

2 files changed

+113
-11
lines changed

2 files changed

+113
-11
lines changed

drivers/crypto/mxs-dcp.c

Lines changed: 93 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/platform_device.h>
1616
#include <linux/stmp_device.h>
1717
#include <linux/clk.h>
18+
#include <soc/fsl/dcp.h>
1819

1920
#include <crypto/aes.h>
2021
#include <crypto/sha1.h>
@@ -101,6 +102,7 @@ struct dcp_async_ctx {
101102
struct crypto_skcipher *fallback;
102103
unsigned int key_len;
103104
uint8_t key[AES_KEYSIZE_128];
105+
bool key_referenced;
104106
};
105107

106108
struct dcp_aes_req_ctx {
@@ -155,6 +157,7 @@ static struct dcp *global_sdcp;
155157
#define MXS_DCP_CONTROL0_HASH_TERM (1 << 13)
156158
#define MXS_DCP_CONTROL0_HASH_INIT (1 << 12)
157159
#define MXS_DCP_CONTROL0_PAYLOAD_KEY (1 << 11)
160+
#define MXS_DCP_CONTROL0_OTP_KEY (1 << 10)
158161
#define MXS_DCP_CONTROL0_CIPHER_ENCRYPT (1 << 8)
159162
#define MXS_DCP_CONTROL0_CIPHER_INIT (1 << 9)
160163
#define MXS_DCP_CONTROL0_ENABLE_HASH (1 << 6)
@@ -168,6 +171,8 @@ static struct dcp *global_sdcp;
168171
#define MXS_DCP_CONTROL1_CIPHER_MODE_ECB (0 << 4)
169172
#define MXS_DCP_CONTROL1_CIPHER_SELECT_AES128 (0 << 0)
170173

174+
#define MXS_DCP_CONTROL1_KEY_SELECT_SHIFT 8
175+
171176
static int mxs_dcp_start_dma(struct dcp_async_ctx *actx)
172177
{
173178
int dma_err;
@@ -224,13 +229,16 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
224229
struct dcp *sdcp = global_sdcp;
225230
struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
226231
struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req);
232+
bool key_referenced = actx->key_referenced;
227233
int ret;
228234

229-
key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
230-
2 * AES_KEYSIZE_128, DMA_TO_DEVICE);
231-
ret = dma_mapping_error(sdcp->dev, key_phys);
232-
if (ret)
233-
return ret;
235+
if (!key_referenced) {
236+
key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
237+
2 * AES_KEYSIZE_128, DMA_TO_DEVICE);
238+
ret = dma_mapping_error(sdcp->dev, key_phys);
239+
if (ret)
240+
return ret;
241+
}
234242

235243
src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf,
236244
DCP_BUF_SZ, DMA_TO_DEVICE);
@@ -255,8 +263,12 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
255263
MXS_DCP_CONTROL0_INTERRUPT |
256264
MXS_DCP_CONTROL0_ENABLE_CIPHER;
257265

258-
/* Payload contains the key. */
259-
desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY;
266+
if (key_referenced)
267+
/* Set OTP key bit to select the key via KEY_SELECT. */
268+
desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY;
269+
else
270+
/* Payload contains the key. */
271+
desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY;
260272

261273
if (rctx->enc)
262274
desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT;
@@ -270,6 +282,9 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
270282
else
271283
desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_CBC;
272284

285+
if (key_referenced)
286+
desc->control1 |= sdcp->coh->aes_key[0] << MXS_DCP_CONTROL1_KEY_SELECT_SHIFT;
287+
273288
desc->next_cmd_addr = 0;
274289
desc->source = src_phys;
275290
desc->destination = dst_phys;
@@ -284,9 +299,9 @@ static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
284299
err_dst:
285300
dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
286301
err_src:
287-
dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128,
288-
DMA_TO_DEVICE);
289-
302+
if (!key_referenced)
303+
dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128,
304+
DMA_TO_DEVICE);
290305
return ret;
291306
}
292307

@@ -453,7 +468,7 @@ static int mxs_dcp_aes_enqueue(struct skcipher_request *req, int enc, int ecb)
453468
struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req);
454469
int ret;
455470

456-
if (unlikely(actx->key_len != AES_KEYSIZE_128))
471+
if (unlikely(actx->key_len != AES_KEYSIZE_128 && !actx->key_referenced))
457472
return mxs_dcp_block_fallback(req, enc);
458473

459474
rctx->enc = enc;
@@ -500,6 +515,7 @@ static int mxs_dcp_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
500515
* there can still be an operation in progress.
501516
*/
502517
actx->key_len = len;
518+
actx->key_referenced = false;
503519
if (len == AES_KEYSIZE_128) {
504520
memcpy(actx->key, key, len);
505521
return 0;
@@ -516,6 +532,32 @@ static int mxs_dcp_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
516532
return crypto_skcipher_setkey(actx->fallback, key, len);
517533
}
518534

535+
static int mxs_dcp_aes_setrefkey(struct crypto_skcipher *tfm, const u8 *key,
536+
unsigned int len)
537+
{
538+
struct dcp_async_ctx *actx = crypto_skcipher_ctx(tfm);
539+
540+
if (len != DCP_PAES_KEYSIZE)
541+
return -EINVAL;
542+
543+
switch (key[0]) {
544+
case DCP_PAES_KEY_SLOT0:
545+
case DCP_PAES_KEY_SLOT1:
546+
case DCP_PAES_KEY_SLOT2:
547+
case DCP_PAES_KEY_SLOT3:
548+
case DCP_PAES_KEY_UNIQUE:
549+
case DCP_PAES_KEY_OTP:
550+
memcpy(actx->key, key, len);
551+
actx->key_len = len;
552+
actx->key_referenced = true;
553+
break;
554+
default:
555+
return -EINVAL;
556+
}
557+
558+
return 0;
559+
}
560+
519561
static int mxs_dcp_aes_fallback_init_tfm(struct crypto_skcipher *tfm)
520562
{
521563
const char *name = crypto_tfm_alg_name(crypto_skcipher_tfm(tfm));
@@ -539,6 +581,13 @@ static void mxs_dcp_aes_fallback_exit_tfm(struct crypto_skcipher *tfm)
539581
crypto_free_skcipher(actx->fallback);
540582
}
541583

584+
static int mxs_dcp_paes_init_tfm(struct crypto_skcipher *tfm)
585+
{
586+
crypto_skcipher_set_reqsize(tfm, sizeof(struct dcp_aes_req_ctx));
587+
588+
return 0;
589+
}
590+
542591
/*
543592
* Hashing (SHA1/SHA256)
544593
*/
@@ -889,6 +938,39 @@ static struct skcipher_alg dcp_aes_algs[] = {
889938
.ivsize = AES_BLOCK_SIZE,
890939
.init = mxs_dcp_aes_fallback_init_tfm,
891940
.exit = mxs_dcp_aes_fallback_exit_tfm,
941+
}, {
942+
.base.cra_name = "ecb(paes)",
943+
.base.cra_driver_name = "ecb-paes-dcp",
944+
.base.cra_priority = 401,
945+
.base.cra_alignmask = 15,
946+
.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_INTERNAL,
947+
.base.cra_blocksize = AES_BLOCK_SIZE,
948+
.base.cra_ctxsize = sizeof(struct dcp_async_ctx),
949+
.base.cra_module = THIS_MODULE,
950+
951+
.min_keysize = DCP_PAES_KEYSIZE,
952+
.max_keysize = DCP_PAES_KEYSIZE,
953+
.setkey = mxs_dcp_aes_setrefkey,
954+
.encrypt = mxs_dcp_aes_ecb_encrypt,
955+
.decrypt = mxs_dcp_aes_ecb_decrypt,
956+
.init = mxs_dcp_paes_init_tfm,
957+
}, {
958+
.base.cra_name = "cbc(paes)",
959+
.base.cra_driver_name = "cbc-paes-dcp",
960+
.base.cra_priority = 401,
961+
.base.cra_alignmask = 15,
962+
.base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_INTERNAL,
963+
.base.cra_blocksize = AES_BLOCK_SIZE,
964+
.base.cra_ctxsize = sizeof(struct dcp_async_ctx),
965+
.base.cra_module = THIS_MODULE,
966+
967+
.min_keysize = DCP_PAES_KEYSIZE,
968+
.max_keysize = DCP_PAES_KEYSIZE,
969+
.setkey = mxs_dcp_aes_setrefkey,
970+
.encrypt = mxs_dcp_aes_cbc_encrypt,
971+
.decrypt = mxs_dcp_aes_cbc_decrypt,
972+
.ivsize = AES_BLOCK_SIZE,
973+
.init = mxs_dcp_paes_init_tfm,
892974
},
893975
};
894976

include/soc/fsl/dcp.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2021 sigma star gmbh
4+
*
5+
* Specifies paes key slot handles for NXP's DCP (Data Co-Processor) to be used
6+
* with the crypto_skcipher_setkey().
7+
*/
8+
9+
#ifndef MXS_DCP_H
10+
#define MXS_DCP_H
11+
12+
#define DCP_PAES_KEYSIZE 1
13+
#define DCP_PAES_KEY_SLOT0 0x00
14+
#define DCP_PAES_KEY_SLOT1 0x01
15+
#define DCP_PAES_KEY_SLOT2 0x02
16+
#define DCP_PAES_KEY_SLOT3 0x03
17+
#define DCP_PAES_KEY_UNIQUE 0xfe
18+
#define DCP_PAES_KEY_OTP 0xff
19+
20+
#endif /* MXS_DCP_H */

0 commit comments

Comments
 (0)