diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c index 375ff9d..aadf851 100644 --- a/drivers/crypto/fsl/jobdesc.c +++ b/drivers/crypto/fsl/jobdesc.c @@ -257,7 +257,7 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr, * Descriptor to instantiate RNG State Handle 0 in normal mode and * load the JDKEK, TDKEK and TDSK registers */ -void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc) +void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc, int handle) { u32 *jump_cmd; @@ -265,21 +265,24 @@ void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc) /* INIT RNG in non-test mode */ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | - OP_ALG_AS_INIT); - - /* wait for done */ - jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1); - set_jump_tgt_here(desc, jump_cmd); - - /* - * load 1 to clear written reg: - * resets the done interrrupt and returns the RNG to idle. - */ - append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW); - - /* generate secure keys (non-test) */ - append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | - OP_ALG_RNG4_SK); + (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT); + + /* For SH0, Secure Keys must be generated as well */ + if (handle == 0) { + /* wait for done */ + jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1); + set_jump_tgt_here(desc, jump_cmd); + + /* + * load 1 to clear written reg: + * resets the done interrupt and returns the RNG to idle. + */ + append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW); + + /* generate secure keys (non-test) */ + append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | + OP_ALG_RNG4_SK); + } } /* Change key size to bytes form bits in calling function*/ diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h index 112404c..75c9424 100644 --- a/drivers/crypto/fsl/jobdesc.h +++ b/drivers/crypto/fsl/jobdesc.h @@ -40,7 +40,7 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr, uint8_t *enc_blob, uint8_t *plain_txt, uint32_t out_sz); -void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc); +void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc, int handle); void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, struct pk_in_params *pkin, uint8_t *out, 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 @@ int sec_reset(void) #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; + + 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); - ret = run_descriptor_jr_idx(desc, sec_idx); + ret = run_descriptor_jr_idx(desc, sec_idx); - if (ret) - printf("RNG: Instantiation failed with error %x\n", ret); + if (ret) + printf("RNG: Instantiation failed with error 0x%x\n", + ret); - rdsta_val = sec_in32(&rng->rdsta); - if (op.status || !(rdsta_val & RNG_STATE0_HANDLE_INSTANTIATED)) - return -1; + 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 @@ static int rng_init(uint8_t sec_idx) 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 @@ static int rng_init(uint8_t sec_idx) * 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 diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h index 8aab4c9..ef515e7 100644 --- a/drivers/crypto/fsl/jr.h +++ b/drivers/crypto/fsl/jr.h @@ -41,6 +41,8 @@ #define JQ_DEQ_TO_ERR -2 #define JQ_ENQ_ERR -3 +#define RNG4_MAX_HANDLES 2 + struct op_ring { phys_addr_t desc; uint32_t status; diff --git a/include/fsl_sec.h b/include/fsl_sec.h index a2f5f5a..4cbdb2d 100644 --- a/include/fsl_sec.h +++ b/include/fsl_sec.h @@ -67,6 +67,9 @@ struct rng4tst { }; u32 rsvd1[40]; #define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001 +#define RNG_STATE1_HANDLE_INSTANTIATED 0x00000002 +#define RNG_STATE_HANDLE_MASK \ + (RNG_STATE0_HANDLE_INSTANTIATED | RNG_STATE1_HANDLE_INSTANTIATED) u32 rdsta; /*RNG DRNG Status Register*/ u32 rsvd2[15]; };