crypto/fsl: instantiate all rng state handles
authorLukas Auer <lukas.auer@aisec.fraunhofer.de>
Thu, 25 Jan 2018 13:11:17 +0000 (14:11 +0100)
committerYork Sun <york.sun@nxp.com>
Fri, 9 Feb 2018 16:34:34 +0000 (08:34 -0800)
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>
drivers/crypto/fsl/jobdesc.c
drivers/crypto/fsl/jobdesc.h
drivers/crypto/fsl/jr.c
drivers/crypto/fsl/jr.h
include/fsl_sec.h

index 375ff9d0e38fec807bc69c9fb1f560d77d10de75..aadf8511014d144979f03e355463cbc0f3ca02bb 100644 (file)
@@ -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*/
index 112404c74d638efa64465081363df607b98964e6..75c9424c4a881c1cbc23318185ffefb76b5af275 100644 (file)
@@ -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,
index a05779826fe466bf98489a6c8726923f37040b28..34bd070426b73913bf82a0c647fb7c9c281c4f15 100644 (file)
@@ -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
index 8aab4c988dabd1f9ae4587aab83025ffc7cf6fe4..ef515e74f8c72d8345af29aa2396c2b3d806eeed 100644 (file)
@@ -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;
index a2f5f5a5f1a3d4a434667f05a621aa80ab180dc2..4cbdb2d65a0cb2d6a7a398ebbf0b0e98745a7740 100644 (file)
@@ -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];
 };