diff mbox series

[v3,5/6] crypto/fsl: instantiate the RNG with prediciton resistance

Message ID 20200625121905.4475-6-michael@walle.cc
State Superseded
Delegated to: Priyanka Jain
Headers show
Series crypto/fsl: add RNG support | expand

Commit Message

Michael Walle June 25, 2020, 12:19 p.m. UTC
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>
---
 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(-)

Comments

Heinrich Schuchardt June 27, 2020, 5:32 p.m. UTC | #1
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@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 mbox series

Patch

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];