Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <richard@nod.at>
Signed-off-by: Richard Weinberger <richard@nod.at>
Co-developed-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Signed-off-by: David Gstir <david@sigma-star.at>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>

authored by

David Gstir and committed by
Jarkko Sakkinen
3d16af0b 45db3ab7

+113 -11
+93 -11
drivers/crypto/mxs-dcp.c
··· 15 15 #include <linux/platform_device.h> 16 16 #include <linux/stmp_device.h> 17 17 #include <linux/clk.h> 18 + #include <soc/fsl/dcp.h> 18 19 19 20 #include <crypto/aes.h> 20 21 #include <crypto/sha1.h> ··· 102 101 struct crypto_skcipher *fallback; 103 102 unsigned int key_len; 104 103 uint8_t key[AES_KEYSIZE_128]; 104 + bool key_referenced; 105 105 }; 106 106 107 107 struct dcp_aes_req_ctx { ··· 157 155 #define MXS_DCP_CONTROL0_HASH_TERM (1 << 13) 158 156 #define MXS_DCP_CONTROL0_HASH_INIT (1 << 12) 159 157 #define MXS_DCP_CONTROL0_PAYLOAD_KEY (1 << 11) 158 + #define MXS_DCP_CONTROL0_OTP_KEY (1 << 10) 160 159 #define MXS_DCP_CONTROL0_CIPHER_ENCRYPT (1 << 8) 161 160 #define MXS_DCP_CONTROL0_CIPHER_INIT (1 << 9) 162 161 #define MXS_DCP_CONTROL0_ENABLE_HASH (1 << 6) ··· 170 167 #define MXS_DCP_CONTROL1_CIPHER_MODE_CBC (1 << 4) 171 168 #define MXS_DCP_CONTROL1_CIPHER_MODE_ECB (0 << 4) 172 169 #define MXS_DCP_CONTROL1_CIPHER_SELECT_AES128 (0 << 0) 170 + 171 + #define MXS_DCP_CONTROL1_KEY_SELECT_SHIFT 8 173 172 174 173 static int mxs_dcp_start_dma(struct dcp_async_ctx *actx) 175 174 { ··· 229 224 struct dcp *sdcp = global_sdcp; 230 225 struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan]; 231 226 struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req); 227 + bool key_referenced = actx->key_referenced; 232 228 int ret; 233 229 234 - key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key, 235 - 2 * AES_KEYSIZE_128, DMA_TO_DEVICE); 236 - ret = dma_mapping_error(sdcp->dev, key_phys); 237 - if (ret) 238 - return ret; 230 + if (!key_referenced) { 231 + key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key, 232 + 2 * AES_KEYSIZE_128, DMA_TO_DEVICE); 233 + ret = dma_mapping_error(sdcp->dev, key_phys); 234 + if (ret) 235 + return ret; 236 + } 239 237 240 238 src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf, 241 239 DCP_BUF_SZ, DMA_TO_DEVICE); ··· 263 255 MXS_DCP_CONTROL0_INTERRUPT | 264 256 MXS_DCP_CONTROL0_ENABLE_CIPHER; 265 257 266 - /* Payload contains the key. */ 267 - desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; 258 + if (key_referenced) 259 + /* Set OTP key bit to select the key via KEY_SELECT. */ 260 + desc->control0 |= MXS_DCP_CONTROL0_OTP_KEY; 261 + else 262 + /* Payload contains the key. */ 263 + desc->control0 |= MXS_DCP_CONTROL0_PAYLOAD_KEY; 268 264 269 265 if (rctx->enc) 270 266 desc->control0 |= MXS_DCP_CONTROL0_CIPHER_ENCRYPT; ··· 281 269 desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_ECB; 282 270 else 283 271 desc->control1 |= MXS_DCP_CONTROL1_CIPHER_MODE_CBC; 272 + 273 + if (key_referenced) 274 + desc->control1 |= sdcp->coh->aes_key[0] << MXS_DCP_CONTROL1_KEY_SELECT_SHIFT; 284 275 285 276 desc->next_cmd_addr = 0; 286 277 desc->source = src_phys; ··· 299 284 err_dst: 300 285 dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE); 301 286 err_src: 302 - dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128, 303 - DMA_TO_DEVICE); 304 - 287 + if (!key_referenced) 288 + dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128, 289 + DMA_TO_DEVICE); 305 290 return ret; 306 291 } 307 292 ··· 468 453 struct dcp_aes_req_ctx *rctx = skcipher_request_ctx(req); 469 454 int ret; 470 455 471 - if (unlikely(actx->key_len != AES_KEYSIZE_128)) 456 + if (unlikely(actx->key_len != AES_KEYSIZE_128 && !actx->key_referenced)) 472 457 return mxs_dcp_block_fallback(req, enc); 473 458 474 459 rctx->enc = enc; ··· 515 500 * there can still be an operation in progress. 516 501 */ 517 502 actx->key_len = len; 503 + actx->key_referenced = false; 518 504 if (len == AES_KEYSIZE_128) { 519 505 memcpy(actx->key, key, len); 520 506 return 0; ··· 530 514 crypto_skcipher_set_flags(actx->fallback, 531 515 tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); 532 516 return crypto_skcipher_setkey(actx->fallback, key, len); 517 + } 518 + 519 + static int mxs_dcp_aes_setrefkey(struct crypto_skcipher *tfm, const u8 *key, 520 + unsigned int len) 521 + { 522 + struct dcp_async_ctx *actx = crypto_skcipher_ctx(tfm); 523 + 524 + if (len != DCP_PAES_KEYSIZE) 525 + return -EINVAL; 526 + 527 + switch (key[0]) { 528 + case DCP_PAES_KEY_SLOT0: 529 + case DCP_PAES_KEY_SLOT1: 530 + case DCP_PAES_KEY_SLOT2: 531 + case DCP_PAES_KEY_SLOT3: 532 + case DCP_PAES_KEY_UNIQUE: 533 + case DCP_PAES_KEY_OTP: 534 + memcpy(actx->key, key, len); 535 + actx->key_len = len; 536 + actx->key_referenced = true; 537 + break; 538 + default: 539 + return -EINVAL; 540 + } 541 + 542 + return 0; 533 543 } 534 544 535 545 static int mxs_dcp_aes_fallback_init_tfm(struct crypto_skcipher *tfm) ··· 579 537 struct dcp_async_ctx *actx = crypto_skcipher_ctx(tfm); 580 538 581 539 crypto_free_skcipher(actx->fallback); 540 + } 541 + 542 + static int mxs_dcp_paes_init_tfm(struct crypto_skcipher *tfm) 543 + { 544 + crypto_skcipher_set_reqsize(tfm, sizeof(struct dcp_aes_req_ctx)); 545 + 546 + return 0; 582 547 } 583 548 584 549 /* ··· 938 889 .ivsize = AES_BLOCK_SIZE, 939 890 .init = mxs_dcp_aes_fallback_init_tfm, 940 891 .exit = mxs_dcp_aes_fallback_exit_tfm, 892 + }, { 893 + .base.cra_name = "ecb(paes)", 894 + .base.cra_driver_name = "ecb-paes-dcp", 895 + .base.cra_priority = 401, 896 + .base.cra_alignmask = 15, 897 + .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_INTERNAL, 898 + .base.cra_blocksize = AES_BLOCK_SIZE, 899 + .base.cra_ctxsize = sizeof(struct dcp_async_ctx), 900 + .base.cra_module = THIS_MODULE, 901 + 902 + .min_keysize = DCP_PAES_KEYSIZE, 903 + .max_keysize = DCP_PAES_KEYSIZE, 904 + .setkey = mxs_dcp_aes_setrefkey, 905 + .encrypt = mxs_dcp_aes_ecb_encrypt, 906 + .decrypt = mxs_dcp_aes_ecb_decrypt, 907 + .init = mxs_dcp_paes_init_tfm, 908 + }, { 909 + .base.cra_name = "cbc(paes)", 910 + .base.cra_driver_name = "cbc-paes-dcp", 911 + .base.cra_priority = 401, 912 + .base.cra_alignmask = 15, 913 + .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_INTERNAL, 914 + .base.cra_blocksize = AES_BLOCK_SIZE, 915 + .base.cra_ctxsize = sizeof(struct dcp_async_ctx), 916 + .base.cra_module = THIS_MODULE, 917 + 918 + .min_keysize = DCP_PAES_KEYSIZE, 919 + .max_keysize = DCP_PAES_KEYSIZE, 920 + .setkey = mxs_dcp_aes_setrefkey, 921 + .encrypt = mxs_dcp_aes_cbc_encrypt, 922 + .decrypt = mxs_dcp_aes_cbc_decrypt, 923 + .ivsize = AES_BLOCK_SIZE, 924 + .init = mxs_dcp_paes_init_tfm, 941 925 }, 942 926 }; 943 927
+20
include/soc/fsl/dcp.h
··· 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 */