From b4fefe7b6e638815ea88b235187ab7abd5f148c3 Mon Sep 17 00:00:00 2001 From: Lucian Cristian Date: Sun, 1 Oct 2017 18:29:22 +0300 Subject: [PATCH] sunxi: backport support for Allwinner Security System PRNG Signed-off-by: Lucian Cristian --- target/linux/sunxi/cortexa7/config-default | 1 + target/linux/sunxi/cortexa8/config-default | 1 + ...-ss_support_the_Security_System_PRNG.patch | 206 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 target/linux/sunxi/patches-4.9/0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch diff --git a/target/linux/sunxi/cortexa7/config-default b/target/linux/sunxi/cortexa7/config-default index fe974c1033..14912981d6 100644 --- a/target/linux/sunxi/cortexa7/config-default +++ b/target/linux/sunxi/cortexa7/config-default @@ -1,4 +1,5 @@ CONFIG_DWMAC_SUN8I=y +CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y # CONFIG_MACH_SUN4I is not set # CONFIG_MACH_SUN5I is not set # CONFIG_PINCTRL_GR8 is not set diff --git a/target/linux/sunxi/cortexa8/config-default b/target/linux/sunxi/cortexa8/config-default index fa40deb6f8..93e48956ee 100644 --- a/target/linux/sunxi/cortexa8/config-default +++ b/target/linux/sunxi/cortexa8/config-default @@ -1,6 +1,7 @@ # CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set # CONFIG_ARM_ERRATA_643719 is not set # CONFIG_ARM_LPAE is not set +CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y # CONFIG_MACH_SUN6I is not set # CONFIG_MACH_SUN7I is not set # CONFIG_MACH_SUN8I is not set diff --git a/target/linux/sunxi/patches-4.9/0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch b/target/linux/sunxi/patches-4.9/0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch new file mode 100644 index 0000000000..f2bac1fde0 --- /dev/null +++ b/target/linux/sunxi/patches-4.9/0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch @@ -0,0 +1,206 @@ +From b8ae5c7387ad075ee61e8c8774ce2bca46bc9236 Mon Sep 17 00:00:00 2001 +From: Corentin LABBE +Date: Mon, 3 Jul 2017 20:48:48 +0200 +Subject: crypto: sun4i-ss - support the Security System PRNG + +The Security System has a PRNG, this patch adds support for it via +crypto_rng. + +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +--- + drivers/crypto/Kconfig | 8 +++++ + drivers/crypto/sunxi-ss/Makefile | 1 + + drivers/crypto/sunxi-ss/sun4i-ss-core.c | 30 ++++++++++++++++++ + drivers/crypto/sunxi-ss/sun4i-ss-prng.c | 56 +++++++++++++++++++++++++++++++++ + drivers/crypto/sunxi-ss/sun4i-ss.h | 11 +++++++ + 5 files changed, 106 insertions(+) + create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-prng.c + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -538,6 +538,14 @@ config CRYPTO_DEV_SUN4I_SS + To compile this driver as a module, choose M here: the module + will be called sun4i-ss. + ++config CRYPTO_DEV_SUN4I_SS_PRNG ++ bool "Support for Allwinner Security System PRNG" ++ depends on CRYPTO_DEV_SUN4I_SS ++ select CRYPTO_RNG ++ help ++ Select this option if you want to provide kernel-side support for ++ the Pseudo-Random Number Generator found in the Security System. ++ + config CRYPTO_DEV_ROCKCHIP + tristate "Rockchip's Cryptographic Engine driver" + depends on OF && ARCH_ROCKCHIP +--- a/drivers/crypto/sunxi-ss/Makefile ++++ b/drivers/crypto/sunxi-ss/Makefile +@@ -1,2 +1,3 @@ + obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o + sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o ++sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o +--- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c +@@ -214,6 +214,23 @@ static struct sun4i_ss_alg_template ss_a + } + } + }, ++#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG ++{ ++ .type = CRYPTO_ALG_TYPE_RNG, ++ .alg.rng = { ++ .base = { ++ .cra_name = "stdrng", ++ .cra_driver_name = "sun4i_ss_rng", ++ .cra_priority = 300, ++ .cra_ctxsize = 0, ++ .cra_module = THIS_MODULE, ++ }, ++ .generate = sun4i_ss_prng_generate, ++ .seed = sun4i_ss_prng_seed, ++ .seedsize = SS_SEED_LEN / BITS_PER_BYTE, ++ } ++}, ++#endif + }; + + static int sun4i_ss_probe(struct platform_device *pdev) +@@ -356,6 +373,13 @@ static int sun4i_ss_probe(struct platfor + goto error_alg; + } + break; ++ case CRYPTO_ALG_TYPE_RNG: ++ err = crypto_register_rng(&ss_algs[i].alg.rng); ++ if (err) { ++ dev_err(ss->dev, "Fail to register %s\n", ++ ss_algs[i].alg.rng.base.cra_name); ++ } ++ break; + } + } + platform_set_drvdata(pdev, ss); +@@ -370,6 +394,9 @@ error_alg: + case CRYPTO_ALG_TYPE_AHASH: + crypto_unregister_ahash(&ss_algs[i].alg.hash); + break; ++ case CRYPTO_ALG_TYPE_RNG: ++ crypto_unregister_rng(&ss_algs[i].alg.rng); ++ break; + } + } + if (ss->reset) +@@ -394,6 +421,9 @@ static int sun4i_ss_remove(struct platfo + case CRYPTO_ALG_TYPE_AHASH: + crypto_unregister_ahash(&ss_algs[i].alg.hash); + break; ++ case CRYPTO_ALG_TYPE_RNG: ++ crypto_unregister_rng(&ss_algs[i].alg.rng); ++ break; + } + } + +--- /dev/null ++++ b/drivers/crypto/sunxi-ss/sun4i-ss-prng.c +@@ -0,0 +1,56 @@ ++#include "sun4i-ss.h" ++ ++int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, ++ unsigned int slen) ++{ ++ struct sun4i_ss_alg_template *algt; ++ struct rng_alg *alg = crypto_rng_alg(tfm); ++ ++ algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); ++ memcpy(algt->ss->seed, seed, slen); ++ ++ return 0; ++} ++ ++int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, ++ unsigned int slen, u8 *dst, unsigned int dlen) ++{ ++ struct sun4i_ss_alg_template *algt; ++ struct rng_alg *alg = crypto_rng_alg(tfm); ++ int i; ++ u32 v; ++ u32 *data = (u32 *)dst; ++ const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED; ++ size_t len; ++ struct sun4i_ss_ctx *ss; ++ unsigned int todo = (dlen / 4) * 4; ++ ++ algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); ++ ss = algt->ss; ++ ++ spin_lock(&ss->slock); ++ ++ writel(mode, ss->base + SS_CTL); ++ ++ while (todo > 0) { ++ /* write the seed */ ++ for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) ++ writel(ss->seed[i], ss->base + SS_KEY0 + i * 4); ++ ++ /* Read the random data */ ++ len = min_t(size_t, SS_DATA_LEN / BITS_PER_BYTE, todo); ++ readsl(ss->base + SS_TXFIFO, data, len / 4); ++ data += len / 4; ++ todo -= len; ++ ++ /* Update the seed */ ++ for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) { ++ v = readl(ss->base + SS_KEY0 + i * 4); ++ ss->seed[i] = v; ++ } ++ } ++ ++ writel(0, ss->base + SS_CTL); ++ spin_unlock(&ss->slock); ++ return dlen; ++} +--- a/drivers/crypto/sunxi-ss/sun4i-ss.h ++++ b/drivers/crypto/sunxi-ss/sun4i-ss.h +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #define SS_CTL 0x00 + #define SS_KEY0 0x04 +@@ -125,6 +126,9 @@ + #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) + #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) + ++#define SS_SEED_LEN 192 ++#define SS_DATA_LEN 160 ++ + struct sun4i_ss_ctx { + void __iomem *base; + int irq; +@@ -134,6 +138,9 @@ struct sun4i_ss_ctx { + struct device *dev; + struct resource *res; + spinlock_t slock; /* control the use of the device */ ++#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG ++ u32 seed[SS_SEED_LEN / BITS_PER_LONG]; ++#endif + }; + + struct sun4i_ss_alg_template { +@@ -142,6 +149,7 @@ struct sun4i_ss_alg_template { + union { + struct crypto_alg crypto; + struct ahash_alg hash; ++ struct rng_alg rng; + } alg; + struct sun4i_ss_ctx *ss; + }; +@@ -199,3 +207,6 @@ int sun4i_ss_des_setkey(struct crypto_ab + unsigned int keylen); + int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen); ++int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, ++ unsigned int slen, u8 *dst, unsigned int dlen); ++int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);