Message ID | 20200625121905.4475-6-michael@walle.cc |
---|---|
State | Superseded |
Headers | show |
Series | crypto/fsl: add RNG support | expand |
On 6/25/20 2:19 PM, Michael Walle wrote: > If it is already instantiated tear it down first and then reinstanciate > it again with prediction resistance. > > Signed-off-by: Michael Walle <michael at walle.cc> > --- > drivers/crypto/fsl/desc.h | 2 ++ > drivers/crypto/fsl/jobdesc.c | 12 ++++++- > drivers/crypto/fsl/jobdesc.h | 2 ++ > drivers/crypto/fsl/jr.c | 67 ++++++++++++++++++++++++++++++++---- > include/fsl_sec.h | 7 ++-- > 5 files changed, 79 insertions(+), 11 deletions(-) > > diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h > index 11ad506829..3589e6ea02 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 6102e9c06b..d9554c550b 100644 > --- a/drivers/crypto/fsl/jobdesc.c > +++ b/drivers/crypto/fsl/jobdesc.c > @@ -266,7 +266,8 @@ void inline_cnstr_jobdesc_rng_instantiation(u32 *desc, int handle, int do_sk) > > /* 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 @@ void inline_cnstr_jobdesc_rng_instantiation(u32 *desc, int handle, int do_sk) > } > } > > +/* 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 14b2a119d7..5185ddd535 100644 > --- a/drivers/crypto/fsl/jobdesc.h > +++ b/drivers/crypto/fsl/jobdesc.h > @@ -41,6 +41,8 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr, > > 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 42865a6cd7..00a3244b18 100644 > --- a/drivers/crypto/fsl/jr.c > +++ b/drivers/crypto/fsl/jr.c > @@ -9,6 +9,7 @@ > #include <cpu_func.h> > #include <log.h> > #include <malloc.h> > +#include <memalign.h> > #include "fsl_sec.h" > #include "jr.h" > #include "jobdesc.h" > @@ -446,6 +447,51 @@ int sec_reset(void) > 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 = sizeof(u32) * 2; > + > + desc = malloc_cache_aligned(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); flush_dcache_range() tests that start and stop address are multiples of CONFIG_SYS_CACHELINE_SIZE (= ARCH_DMA_MINALIGN on ARM). See check_cache_range(start, stop). So you should use ALIGN(desc_size, ARCH_DMA_MINALIGN) instead of desc_size. Best regards Heinrich > + > + 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 @@ static int instantiate_rng(u8 sec_idx, int gen_sk) > * 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 @@ static int instantiate_rng(u8 sec_idx, int gen_sk) > 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 @@ static int rng_init(uint8_t sec_idx) > > 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 > diff --git a/include/fsl_sec.h b/include/fsl_sec.h > index 64b8751f2d..1c6f1eb23e 100644 > --- a/include/fsl_sec.h > +++ b/include/fsl_sec.h > @@ -65,10 +65,9 @@ struct rng4tst { > u32 rtfreqcnt; /* PRGM=0: freq. count register */ > }; > 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) > +#define RDSTA_IF(idx) (0x00000001 << (idx)) > +#define RDSTA_PR(idx) (0x00000010 << (idx)) > +#define RDSTA_MASK (RDSTA_PR(1) | RDSTA_PR(0) | RDSTA_IF(1) | RDSTA_IF(0)) > #define RDSTA_SKVN 0x40000000 > u32 rdsta; /*RNG DRNG Status Register*/ > u32 rsvd2[15]; >
diff --git a/drivers/crypto/fsl/desc.h b/drivers/crypto/fsl/desc.h index 11ad506829..3589e6ea02 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 6102e9c06b..d9554c550b 100644 --- a/drivers/crypto/fsl/jobdesc.c +++ b/drivers/crypto/fsl/jobdesc.c @@ -266,7 +266,8 @@ void inline_cnstr_jobdesc_rng_instantiation(u32 *desc, int handle, int do_sk) /* 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 @@ void inline_cnstr_jobdesc_rng_instantiation(u32 *desc, int handle, int do_sk) } } +/* 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 14b2a119d7..5185ddd535 100644 --- a/drivers/crypto/fsl/jobdesc.h +++ b/drivers/crypto/fsl/jobdesc.h @@ -41,6 +41,8 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr, 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 42865a6cd7..00a3244b18 100644 --- a/drivers/crypto/fsl/jr.c +++ b/drivers/crypto/fsl/jr.c @@ -9,6 +9,7 @@ #include <cpu_func.h> #include <log.h> #include <malloc.h> +#include <memalign.h> #include "fsl_sec.h" #include "jr.h" #include "jobdesc.h" @@ -446,6 +447,51 @@ int sec_reset(void) 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 = sizeof(u32) * 2; + + desc = malloc_cache_aligned(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 @@ static int instantiate_rng(u8 sec_idx, int gen_sk) * 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 @@ static int instantiate_rng(u8 sec_idx, int gen_sk) 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 @@ static int rng_init(uint8_t sec_idx) 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 diff --git a/include/fsl_sec.h b/include/fsl_sec.h index 64b8751f2d..1c6f1eb23e 100644 --- a/include/fsl_sec.h +++ b/include/fsl_sec.h @@ -65,10 +65,9 @@ struct rng4tst { u32 rtfreqcnt; /* PRGM=0: freq. count register */ }; 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) +#define RDSTA_IF(idx) (0x00000001 << (idx)) +#define RDSTA_PR(idx) (0x00000010 << (idx)) +#define RDSTA_MASK (RDSTA_PR(1) | RDSTA_PR(0) | RDSTA_IF(1) | RDSTA_IF(0)) #define RDSTA_SKVN 0x40000000 u32 rdsta; /*RNG DRNG Status Register*/ u32 rsvd2[15];
If it is already instantiated tear it down first and then reinstanciate it again with prediction resistance. Signed-off-by: Michael Walle <michael at walle.cc> --- drivers/crypto/fsl/desc.h | 2 ++ drivers/crypto/fsl/jobdesc.c | 12 ++++++- drivers/crypto/fsl/jobdesc.h | 2 ++ drivers/crypto/fsl/jr.c | 67 ++++++++++++++++++++++++++++++++---- include/fsl_sec.h | 7 ++-- 5 files changed, 79 insertions(+), 11 deletions(-)