summaryrefslogtreecommitdiffstats
path: root/drivers/crypto/fsl/jr.c
diff options
context:
space:
mode:
authorRuchika Gupta <ruchika.gupta@freescale.com>2014-10-07 15:46:20 +0530
committerYork Sun <yorksun@freescale.com>2014-10-16 14:20:40 -0700
commitc5de15cbc8a8c87ae9f104e958ee6a374a145724 (patch)
tree3981bd4ef5f6933afe89f126cc16886d459fa8aa /drivers/crypto/fsl/jr.c
parent7cad2e38d61e27ea59fb7944f7e647e97ef292d3 (diff)
downloadtalos-obmc-uboot-c5de15cbc8a8c87ae9f104e958ee6a374a145724.tar.gz
talos-obmc-uboot-c5de15cbc8a8c87ae9f104e958ee6a374a145724.zip
crypto/fsl: Add command for encapsulating/decapsulating blobs
Freescale's SEC block has built-in Blob Protocol which provides a method for protecting user-defined data across system power cycles. SEC block protects data in a data structure called a Blob, which provides both confidentiality and integrity protection. Encapsulating data as a blob Each time that the Blob Protocol is used to protect data, a different randomly generated key is used to encrypt the data. This random key is itself encrypted using a key which is derived from SoC's non volatile secret key and a 16 bit Key identifier. The resulting encrypted key along with encrypted data is called a blob. The non volatile secure key is available for use only during secure boot. During decapsulation, the reverse process is performed to get back the original data. Commands added -------------- blob enc - encapsulating data as a cryptgraphic blob blob dec - decapsulating cryptgraphic blob to get the data Commands Syntax --------------- blob enc src dst len km Encapsulate and create blob of data $len bytes long at address $src and store the result at address $dst. $km is the 16 byte key modifier is also required for generation/use as key for cryptographic operation. Key modifier should be 16 byte long. blob dec src dst len km Decapsulate the blob of data at address $src and store result of $len byte at addr $dst. $km is the 16 byte key modifier is also required for generation/use as key for cryptographic operation. Key modifier should be 16 byte long. Signed-off-by: Ruchika Gupta <ruchika.gupta@freescale.com> Reviewed-by: York Sun <yorksun@freescale.com>
Diffstat (limited to 'drivers/crypto/fsl/jr.c')
-rw-r--r--drivers/crypto/fsl/jr.c127
1 files changed, 126 insertions, 1 deletions
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index a107e6afcb..29681e18a6 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -10,6 +10,7 @@
#include <malloc.h>
#include "fsl_sec.h"
#include "jr.h"
+#include "jobdesc.h"
#define CIRC_CNT(head, tail, size) (((head) - (tail)) & (size - 1))
#define CIRC_SPACE(head, tail, size) CIRC_CNT((tail), (head) + 1, (size))
@@ -319,6 +320,120 @@ int sec_reset(void)
return 0;
}
+static int instantiate_rng(void)
+{
+ struct result op;
+ u32 *desc;
+ u32 rdsta_val;
+ int ret = 0;
+ ccsr_sec_t __iomem *sec =
+ (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ struct rng4tst __iomem *rng =
+ (struct rng4tst __iomem *)&sec->rng;
+
+ memset(&op, 0, sizeof(struct result));
+
+ desc = malloc(sizeof(int) * 6);
+ if (!desc) {
+ printf("cannot allocate RNG init descriptor memory\n");
+ return -1;
+ }
+
+ inline_cnstr_jobdesc_rng_instantiation(desc);
+ ret = run_descriptor_jr(desc);
+
+ if (ret)
+ printf("RNG: Instantiation failed with error %x\n", ret);
+
+ rdsta_val = sec_in32(&rng->rdsta);
+ if (op.status || !(rdsta_val & RNG_STATE0_HANDLE_INSTANTIATED))
+ return -1;
+
+ return ret;
+}
+
+static u8 get_rng_vid(void)
+{
+ ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
+ u32 cha_vid = sec_in32(&sec->chavid_ls);
+
+ return (cha_vid & SEC_CHAVID_RNG_LS_MASK) >> SEC_CHAVID_LS_RNG_SHIFT;
+}
+
+/*
+ * By default, the TRNG runs for 200 clocks per sample;
+ * 1200 clocks per sample generates better entropy.
+ */
+static void kick_trng(int ent_delay)
+{
+ ccsr_sec_t __iomem *sec =
+ (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ struct rng4tst __iomem *rng =
+ (struct rng4tst __iomem *)&sec->rng;
+ u32 val;
+
+ /* put RNG4 into program mode */
+ sec_setbits32(&rng->rtmctl, RTMCTL_PRGM);
+ /* rtsdctl bits 0-15 contain "Entropy Delay, which defines the
+ * length (in system clocks) of each Entropy sample taken
+ * */
+ val = sec_in32(&rng->rtsdctl);
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+ (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
+ sec_out32(&rng->rtsdctl, val);
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
+ sec_out32(&rng->rtfreqmin, ent_delay >> 2);
+ /* max. freq. count, equal to 8 times the entropy sample length */
+ sec_out32(&rng->rtfreqmax, ent_delay << 3);
+ /* put RNG4 into run mode */
+ sec_clrbits32(&rng->rtmctl, RTMCTL_PRGM);
+}
+
+static int rng_init(void)
+{
+ int ret, ent_delay = RTSDCTL_ENT_DLY_MIN;
+ ccsr_sec_t __iomem *sec =
+ (ccsr_sec_t __iomem *)CONFIG_SYS_FSL_SEC_ADDR;
+ 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;
+
+ do {
+ /*
+ * If either of the SH's were instantiated by somebody else
+ * then it is assumed that the entropy
+ * parameters are properly set and thus the function
+ * setting these (kick_trng(...)) is skipped.
+ * Also, if a handle was instantiated, do not change
+ * the TRNG parameters.
+ */
+ kick_trng(ent_delay);
+ ent_delay += 400;
+ /*
+ * if instantiate_rng(...) fails, the loop will rerun
+ * and the kick_trng(...) function will modfiy the
+ * upper and lower limits of the entropy sampling
+ * interval, leading to a sucessful initialization of
+ * the RNG.
+ */
+ ret = instantiate_rng();
+ } while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+ if (ret) {
+ printf("RNG: Failed to instantiate RNG\n");
+ return ret;
+ }
+
+ /* Enable RDB bit so that RNG works faster */
+ sec_setbits32(&sec->scfgr, SEC_SCFGR_RDBENABLE);
+
+ return ret;
+}
+
int sec_init(void)
{
int ret = 0;
@@ -330,8 +445,18 @@ int sec_init(void)
sec_out32(&sec->mcfgr, mcr | 1 << MCFGR_PS_SHIFT);
#endif
ret = jr_init();
- if (ret < 0)
+ if (ret < 0) {
+ printf("SEC initialization failed\n");
return -1;
+ }
+
+ if (get_rng_vid() >= 4) {
+ if (rng_init() < 0) {
+ printf("RNG instantiation failed\n");
+ return -1;
+ }
+ printf("SEC: RNG instantiated\n");
+ }
return ret;
}
OpenPOWER on IntegriCloud