crypto/fsl: instantiate the RNG with prediciton resistance
If it is already instantiated tear it down first and then reinstanciate
it again with prediction resistance.
Signed-off-by: Michael Walle <michael@walle.cc>
Reviewed-by: Priyanka Jain <priyanka.jain@nxp.com>
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h
index 11ad506..3589e6e 100644
--- a/drivers/crypto/fsl/desc.h
+++ b/drivers/crypto/fsl/desc.h
@@ -520,6 +520,8 @@
#define OP_ALG_ICV_OFF (0 << OP_ALG_ICV_SHIFT)
#define OP_ALG_ICV_ON (1 << OP_ALG_ICV_SHIFT)
+#define OP_ALG_PR_ON 0x02
+
#define OP_ALG_DIR_SHIFT 0
#define OP_ALG_DIR_MASK 1
#define OP_ALG_DECRYPT 0
diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c
index c30ea88..a888758 100644
--- a/drivers/crypto/fsl/jobdesc.c
+++ b/drivers/crypto/fsl/jobdesc.c
@@ -266,7 +266,8 @@
/* INIT RNG in non-test mode */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT);
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT |
+ OP_ALG_PR_ON);
/* For SH0, Secure Keys must be generated as well */
if (!handle && do_sk) {
@@ -286,6 +287,15 @@
}
}
+/* Descriptor for deinstantiation of the RNG block. */
+void inline_cnstr_jobdesc_rng_deinstantiation(u32 *desc, int handle)
+{
+ init_job_desc(desc, 0);
+
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
+}
+
/* Change key size to bytes form bits in calling function*/
void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
struct pk_in_params *pkin, uint8_t *out,
diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h
index 14b2a11..5185ddd 100644
--- a/drivers/crypto/fsl/jobdesc.h
+++ b/drivers/crypto/fsl/jobdesc.h
@@ -41,6 +41,8 @@
void inline_cnstr_jobdesc_rng_instantiation(u32 *desc, int handle, int do_sk);
+void inline_cnstr_jobdesc_rng_deinstantiation(u32 *desc, int handle);
+
void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
struct pk_in_params *pkin, uint8_t *out,
uint32_t out_siz);
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 42865a6..c5802f7 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <cpu_func.h>
+#include <linux/kernel.h>
#include <log.h>
#include <malloc.h>
#include "fsl_sec.h"
@@ -446,6 +447,51 @@
return sec_reset_idx(0);
}
#ifndef CONFIG_SPL_BUILD
+static int deinstantiate_rng(u8 sec_idx, int state_handle_mask)
+{
+ u32 *desc;
+ int sh_idx, ret = 0;
+ int desc_size = ALIGN(sizeof(u32) * 2, ARCH_DMA_MINALIGN);
+
+ desc = memalign(ARCH_DMA_MINALIGN, desc_size);
+ if (!desc) {
+ debug("cannot allocate RNG init descriptor memory\n");
+ return -ENOMEM;
+ }
+
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, then it means the state
+ * handle was initialized by us, and thus it needs to be
+ * deinitialized as well
+ */
+
+ if (state_handle_mask & RDSTA_IF(sh_idx)) {
+ /*
+ * Create the descriptor for deinstantating this state
+ * handle.
+ */
+ inline_cnstr_jobdesc_rng_deinstantiation(desc, sh_idx);
+ flush_dcache_range((unsigned long)desc,
+ (unsigned long)desc + desc_size);
+
+ ret = run_descriptor_jr_idx(desc, sec_idx);
+ if (ret) {
+ printf("SEC%u: RNG4 SH%d deinstantiation failed with error 0x%x\n",
+ sec_idx, sh_idx, ret);
+ ret = -EIO;
+ break;
+ }
+
+ printf("SEC%u: Deinstantiated RNG4 SH%d\n",
+ sec_idx, sh_idx);
+ }
+ }
+
+ free(desc);
+ return ret;
+}
+
static int instantiate_rng(u8 sec_idx, int gen_sk)
{
u32 *desc;
@@ -466,9 +512,18 @@
* 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;
+ rdsta_val = sec_in32(&rng->rdsta);
+ if (rdsta_val & (RDSTA_IF(sh_idx))) {
+ if (rdsta_val & RDSTA_PR(sh_idx))
+ continue;
+
+ printf("SEC%u: RNG4 SH%d was instantiated w/o prediction resistance. Tearing it down\n",
+ sec_idx, sh_idx);
+
+ ret = deinstantiate_rng(sec_idx, RDSTA_IF(sh_idx));
+ if (ret)
+ break;
+ }
inline_cnstr_jobdesc_rng_instantiation(desc, sh_idx, gen_sk);
size = roundup(sizeof(uint32_t) * 6, ARCH_DMA_MINALIGN);
@@ -481,8 +536,8 @@
printf("SEC%u: RNG4 SH%d instantiation failed with error 0x%x\n",
sec_idx, sh_idx, ret);
- rdsta_val = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
- if (!(rdsta_val & (1 << sh_idx))) {
+ rdsta_val = sec_in32(&rng->rdsta);
+ if (!(rdsta_val & RDSTA_IF(sh_idx))) {
free(desc);
return -1;
}
@@ -554,7 +609,7 @@
gen_sk = !(sec_in32(&rng->rdsta) & RDSTA_SKVN);
do {
- inst_handles = sec_in32(&rng->rdsta) & RNG_STATE_HANDLE_MASK;
+ inst_handles = sec_in32(&rng->rdsta) & RDSTA_MASK;
/*
* If either of the SH's were instantiated by somebody else