crypto/fsl: instantiate all rng state handles
Extend the instantiate_rng() function and the corresponding CAAM job
descriptor to instantiate all RNG state handles. This moves the RNG
instantiation code in line with the CAAM kernel driver.
Previously, only the first state handle was instantiated. The second
one was instantiated by the CAAM kernel driver. This works if the
kernel runs in secure mode, but fails in non-secure mode since the
kernel driver uses DEC0 directly instead of over the job ring
interface. Instantiating all RNG state handles in u-boot removes the
need for using DEC0 in the kernel driver, making it possible to use
the CAAM in non-secure mode.
Signed-off-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: York Sun <york.sun@nxp.com>
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index a057798..34bd070 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -444,35 +444,49 @@
#ifndef CONFIG_SPL_BUILD
static int instantiate_rng(uint8_t sec_idx)
{
- struct result op;
u32 *desc;
u32 rdsta_val;
- int ret = 0;
+ int ret = 0, sh_idx, size;
ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
- memset(&op, 0, sizeof(struct result));
-
desc = memalign(ARCH_DMA_MINALIGN, sizeof(uint32_t) * 6);
if (!desc) {
printf("cannot allocate RNG init descriptor memory\n");
return -1;
}
- inline_cnstr_jobdesc_rng_instantiation(desc);
- int size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
- flush_dcache_range((unsigned long)desc,
- (unsigned long)desc + size);
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, this state handle
+ * was initialized by somebody else, so it's left alone.
+ */
+ rdsta_val = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+ if (rdsta_val & (1 << sh_idx))
+ continue;
- ret = run_descriptor_jr_idx(desc, sec_idx);
+ inline_cnstr_jobdesc_rng_instantiation(desc, sh_idx);
+ size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
+ flush_dcache_range((unsigned long)desc,
+ (unsigned long)desc + size);
- if (ret)
- printf("RNG: Instantiation failed with error %x\n", ret);
+ ret = run_descriptor_jr_idx(desc, sec_idx);
- rdsta_val = sec_in32(&rng->rdsta);
- if (op.status || !(rdsta_val & RNG_STATE0_HANDLE_INSTANTIATED))
- return -1;
+ if (ret)
+ printf("RNG: Instantiation failed with error 0x%x\n",
+ ret);
+
+ rdsta_val = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+ if (!(rdsta_val & (1 << sh_idx))) {
+ free(desc);
+ return -1;
+ }
+
+ memset(desc, 0, sizeof(uint32_t) * 6);
+ }
+
+ free(desc);
return ret;
}
@@ -524,14 +538,11 @@
ccsr_sec_t __iomem *sec = (ccsr_sec_t __iomem *)SEC_ADDR(sec_idx);
struct rng4tst __iomem *rng =
(struct rng4tst __iomem *)&sec->rng;
-
- u32 rdsta = sec_in32(&rng->rdsta);
-
- /* Check if RNG state 0 handler is already instantiated */
- if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED)
- return 0;
+ u32 inst_handles;
do {
+ inst_handles = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+
/*
* If either of the SH's were instantiated by somebody else
* then it is assumed that the entropy
@@ -540,8 +551,10 @@
* Also, if a handle was instantiated, do not change
* the TRNG parameters.
*/
- kick_trng(ent_delay, sec_idx);
- ent_delay += 400;
+ if (!inst_handles) {
+ kick_trng(ent_delay, sec_idx);
+ ent_delay += 400;
+ }
/*
* if instantiate_rng(...) fails, the loop will rerun
* and the kick_trng(...) function will modfiy the