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

crypto: caam - enable prediction resistance in HRWNG

Instantiate CAAM RNG with prediction resistance enabled to improve its
quality (with PR on DRNG is forced to reseed from TRNG every time
random data is generated).

Management Complex firmware with version lower than 10.20.0
doesn't provide prediction resistance support. Consider this
and only instantiate rng when mc f/w version is lower.

Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: Andrei Botila <andrei.botila@nxp.com>
Cc: Chris Healy <cphealy@gmail.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Horia Geantă <horia.geanta@nxp.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Iuliana Prodan <iuliana.prodan@nxp.com>
Cc: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-imx@nxp.com
Reviewed-by: Horia Geantă <horia.geanta@nxp.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Andrey Smirnov and committed by
Herbert Xu
358ba762 0544cb75

+68 -15
+1
drivers/crypto/caam/Kconfig
··· 13 13 depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE 14 14 select SOC_BUS 15 15 select CRYPTO_DEV_FSL_CAAM_COMMON 16 + imply FSL_MC_BUS 16 17 help 17 18 Enables the driver module for Freescale's Cryptographic Accelerator 18 19 and Assurance Module (CAAM), also known as the SEC version 4 (SEC4).
+2 -1
drivers/crypto/caam/caamrng.c
··· 69 69 { 70 70 init_job_desc(desc, 0); /* + 1 cmd_sz */ 71 71 /* Generate random bytes: + 1 cmd_sz */ 72 - append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG); 72 + append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG | 73 + OP_ALG_PR_ON); 73 74 /* Store bytes: + 1 cmd_sz + caam_ptr_sz */ 74 75 append_fifo_store(desc, dst_dma, len, FIFOST_TYPE_RNGSTORE); 75 76
+60 -13
drivers/crypto/caam/ctrl.c
··· 10 10 #include <linux/of_address.h> 11 11 #include <linux/of_irq.h> 12 12 #include <linux/sys_soc.h> 13 + #include <linux/fsl/mc.h> 13 14 14 15 #include "compat.h" 15 16 #include "regs.h" ··· 37 36 init_job_desc(desc, 0); 38 37 39 38 op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | 40 - (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT; 39 + (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT | 40 + OP_ALG_PR_ON; 41 41 42 42 /* INIT RNG in non-test mode */ 43 43 append_operation(desc, op_flags); ··· 280 278 return -ENOMEM; 281 279 282 280 for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) { 281 + const u32 rdsta_if = RDSTA_IF0 << sh_idx; 282 + const u32 rdsta_pr = RDSTA_PR0 << sh_idx; 283 + const u32 rdsta_mask = rdsta_if | rdsta_pr; 283 284 /* 284 285 * If the corresponding bit is set, this state handle 285 286 * was initialized by somebody else, so it's left alone. 286 287 */ 287 - if ((1 << sh_idx) & state_handle_mask) 288 - continue; 288 + if (rdsta_if & state_handle_mask) { 289 + if (rdsta_pr & state_handle_mask) 290 + continue; 291 + 292 + dev_info(ctrldev, 293 + "RNG4 SH%d was previously instantiated without prediction resistance. Tearing it down\n", 294 + sh_idx); 295 + 296 + ret = deinstantiate_rng(ctrldev, rdsta_if); 297 + if (ret) 298 + break; 299 + } 289 300 290 301 /* Create the descriptor for instantiating RNG State Handle */ 291 302 build_instantiation_desc(desc, sh_idx, gen_sk); ··· 318 303 if (ret) 319 304 break; 320 305 321 - rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK; 306 + rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_MASK; 322 307 if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) || 323 - !(rdsta_val & (1 << sh_idx))) { 308 + (rdsta_val & rdsta_mask) != rdsta_mask) { 324 309 ret = -EAGAIN; 325 310 break; 326 311 } ··· 579 564 } 580 565 #endif 581 566 567 + #ifdef CONFIG_FSL_MC_BUS 568 + static bool check_version(struct fsl_mc_version *mc_version, u32 major, 569 + u32 minor, u32 revision) 570 + { 571 + if (mc_version->major > major) 572 + return true; 573 + 574 + if (mc_version->major == major) { 575 + if (mc_version->minor > minor) 576 + return true; 577 + 578 + if (mc_version->minor == minor && 579 + mc_version->revision > revision) 580 + return true; 581 + } 582 + 583 + return false; 584 + } 585 + #endif 586 + 582 587 /* Probe routine for CAAM top (controller) level */ 583 588 static int caam_probe(struct platform_device *pdev) 584 589 { ··· 617 582 u8 rng_vid; 618 583 int pg_size; 619 584 int BLOCK_OFFSET = 0; 585 + bool pr_support = false; 620 586 621 587 ctrlpriv = devm_kzalloc(&pdev->dev, sizeof(*ctrlpriv), GFP_KERNEL); 622 588 if (!ctrlpriv) ··· 703 667 704 668 /* Get the IRQ of the controller (for security violations only) */ 705 669 ctrlpriv->secvio_irq = irq_of_parse_and_map(nprop, 0); 670 + np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-mc"); 671 + ctrlpriv->mc_en = !!np; 672 + of_node_put(np); 673 + 674 + #ifdef CONFIG_FSL_MC_BUS 675 + if (ctrlpriv->mc_en) { 676 + struct fsl_mc_version *mc_version; 677 + 678 + mc_version = fsl_mc_get_version(); 679 + if (mc_version) 680 + pr_support = check_version(mc_version, 10, 20, 0); 681 + else 682 + return -EPROBE_DEFER; 683 + } 684 + #endif 706 685 707 686 /* 708 687 * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel, ··· 725 674 * In case of SoCs with Management Complex, MC f/w performs 726 675 * the configuration. 727 676 */ 728 - np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-mc"); 729 - ctrlpriv->mc_en = !!np; 730 - of_node_put(np); 731 - 732 677 if (!ctrlpriv->mc_en) 733 678 clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, 734 679 MCFGR_AWCACHE_CACH | MCFGR_AWCACHE_BUFF | ··· 831 784 * already instantiated, do RNG instantiation 832 785 * In case of SoCs with Management Complex, RNG is managed by MC f/w. 833 786 */ 834 - if (!ctrlpriv->mc_en && rng_vid >= 4) { 787 + if (!(ctrlpriv->mc_en && pr_support) && rng_vid >= 4) { 835 788 ctrlpriv->rng4_sh_init = 836 789 rd_reg32(&ctrl->r4tst[0].rdsta); 837 790 /* ··· 841 794 * to regenerate these keys before the next POR. 842 795 */ 843 796 gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1; 844 - ctrlpriv->rng4_sh_init &= RDSTA_IFMASK; 797 + ctrlpriv->rng4_sh_init &= RDSTA_MASK; 845 798 do { 846 799 int inst_handles = 847 800 rd_reg32(&ctrl->r4tst[0].rdsta) & 848 - RDSTA_IFMASK; 801 + RDSTA_MASK; 849 802 /* 850 803 * If either SH were instantiated by somebody else 851 804 * (e.g. u-boot) then it is assumed that the entropy ··· 885 838 * Set handles init'ed by this module as the complement of the 886 839 * already initialized ones 887 840 */ 888 - ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK; 841 + ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_MASK; 889 842 890 843 /* Enable RDB bit so that RNG works faster */ 891 844 clrsetbits_32(&ctrl->scfgr, 0, SCFGR_RDBENABLE);
+2
drivers/crypto/caam/desc.h
··· 1254 1254 #define OP_ALG_ICV_OFF (0 << OP_ALG_ICV_SHIFT) 1255 1255 #define OP_ALG_ICV_ON (1 << OP_ALG_ICV_SHIFT) 1256 1256 1257 + #define OP_ALG_PR_ON BIT(1) 1258 + 1257 1259 #define OP_ALG_DIR_SHIFT 0 1258 1260 #define OP_ALG_DIR_MASK 1 1259 1261 #define OP_ALG_DECRYPT 0
+3 -1
drivers/crypto/caam/regs.h
··· 524 524 u32 rsvd1[40]; 525 525 #define RDSTA_SKVT 0x80000000 526 526 #define RDSTA_SKVN 0x40000000 527 + #define RDSTA_PR0 BIT(4) 528 + #define RDSTA_PR1 BIT(5) 527 529 #define RDSTA_IF0 0x00000001 528 530 #define RDSTA_IF1 0x00000002 529 - #define RDSTA_IFMASK (RDSTA_IF1 | RDSTA_IF0) 531 + #define RDSTA_MASK (RDSTA_PR1 | RDSTA_PR0 | RDSTA_IF1 | RDSTA_IF0) 530 532 u32 rdsta; 531 533 u32 rsvd2[15]; 532 534 };