1 From b8ae5c7387ad075ee61e8c8774ce2bca46bc9236 Mon Sep 17 00:00:00 2001
2 From: Corentin LABBE <clabbe.montjoie@gmail.com>
3 Date: Mon, 3 Jul 2017 20:48:48 +0200
4 Subject: crypto: sun4i-ss - support the Security System PRNG
6 The Security System has a PRNG, this patch adds support for it via
9 Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
10 Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
12 drivers/crypto/Kconfig | 8 +++++
13 drivers/crypto/sunxi-ss/Makefile | 1 +
14 drivers/crypto/sunxi-ss/sun4i-ss-core.c | 30 ++++++++++++++++++
15 drivers/crypto/sunxi-ss/sun4i-ss-prng.c | 56 +++++++++++++++++++++++++++++++++
16 drivers/crypto/sunxi-ss/sun4i-ss.h | 11 +++++++
17 5 files changed, 106 insertions(+)
18 create mode 100644 drivers/crypto/sunxi-ss/sun4i-ss-prng.c
20 --- a/drivers/crypto/Kconfig
21 +++ b/drivers/crypto/Kconfig
22 @@ -538,6 +538,14 @@ config CRYPTO_DEV_SUN4I_SS
23 To compile this driver as a module, choose M here: the module
24 will be called sun4i-ss.
26 +config CRYPTO_DEV_SUN4I_SS_PRNG
27 + bool "Support for Allwinner Security System PRNG"
28 + depends on CRYPTO_DEV_SUN4I_SS
31 + Select this option if you want to provide kernel-side support for
32 + the Pseudo-Random Number Generator found in the Security System.
34 config CRYPTO_DEV_ROCKCHIP
35 tristate "Rockchip's Cryptographic Engine driver"
36 depends on OF && ARCH_ROCKCHIP
37 --- a/drivers/crypto/sunxi-ss/Makefile
38 +++ b/drivers/crypto/sunxi-ss/Makefile
40 obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o
41 sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o
42 +sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o
43 --- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c
44 +++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
45 @@ -214,6 +214,23 @@ static struct sun4i_ss_alg_template ss_a
49 +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
51 + .type = CRYPTO_ALG_TYPE_RNG,
54 + .cra_name = "stdrng",
55 + .cra_driver_name = "sun4i_ss_rng",
56 + .cra_priority = 300,
58 + .cra_module = THIS_MODULE,
60 + .generate = sun4i_ss_prng_generate,
61 + .seed = sun4i_ss_prng_seed,
62 + .seedsize = SS_SEED_LEN / BITS_PER_BYTE,
68 static int sun4i_ss_probe(struct platform_device *pdev)
69 @@ -356,6 +373,13 @@ static int sun4i_ss_probe(struct platfor
73 + case CRYPTO_ALG_TYPE_RNG:
74 + err = crypto_register_rng(&ss_algs[i].alg.rng);
76 + dev_err(ss->dev, "Fail to register %s\n",
77 + ss_algs[i].alg.rng.base.cra_name);
82 platform_set_drvdata(pdev, ss);
83 @@ -370,6 +394,9 @@ error_alg:
84 case CRYPTO_ALG_TYPE_AHASH:
85 crypto_unregister_ahash(&ss_algs[i].alg.hash);
87 + case CRYPTO_ALG_TYPE_RNG:
88 + crypto_unregister_rng(&ss_algs[i].alg.rng);
93 @@ -394,6 +421,9 @@ static int sun4i_ss_remove(struct platfo
94 case CRYPTO_ALG_TYPE_AHASH:
95 crypto_unregister_ahash(&ss_algs[i].alg.hash);
97 + case CRYPTO_ALG_TYPE_RNG:
98 + crypto_unregister_rng(&ss_algs[i].alg.rng);
104 +++ b/drivers/crypto/sunxi-ss/sun4i-ss-prng.c
106 +#include "sun4i-ss.h"
108 +int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
111 + struct sun4i_ss_alg_template *algt;
112 + struct rng_alg *alg = crypto_rng_alg(tfm);
114 + algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
115 + memcpy(algt->ss->seed, seed, slen);
120 +int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
121 + unsigned int slen, u8 *dst, unsigned int dlen)
123 + struct sun4i_ss_alg_template *algt;
124 + struct rng_alg *alg = crypto_rng_alg(tfm);
127 + u32 *data = (u32 *)dst;
128 + const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED;
130 + struct sun4i_ss_ctx *ss;
131 + unsigned int todo = (dlen / 4) * 4;
133 + algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
136 + spin_lock(&ss->slock);
138 + writel(mode, ss->base + SS_CTL);
141 + /* write the seed */
142 + for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++)
143 + writel(ss->seed[i], ss->base + SS_KEY0 + i * 4);
145 + /* Read the random data */
146 + len = min_t(size_t, SS_DATA_LEN / BITS_PER_BYTE, todo);
147 + readsl(ss->base + SS_TXFIFO, data, len / 4);
151 + /* Update the seed */
152 + for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) {
153 + v = readl(ss->base + SS_KEY0 + i * 4);
158 + writel(0, ss->base + SS_CTL);
159 + spin_unlock(&ss->slock);
162 --- a/drivers/crypto/sunxi-ss/sun4i-ss.h
163 +++ b/drivers/crypto/sunxi-ss/sun4i-ss.h
165 #include <crypto/aes.h>
166 #include <crypto/des.h>
167 #include <crypto/internal/rng.h>
168 +#include <crypto/rng.h>
173 #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2)
174 #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0)
176 +#define SS_SEED_LEN 192
177 +#define SS_DATA_LEN 160
179 struct sun4i_ss_ctx {
182 @@ -134,6 +138,9 @@ struct sun4i_ss_ctx {
184 struct resource *res;
185 spinlock_t slock; /* control the use of the device */
186 +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
187 + u32 seed[SS_SEED_LEN / BITS_PER_LONG];
191 struct sun4i_ss_alg_template {
192 @@ -142,6 +149,7 @@ struct sun4i_ss_alg_template {
194 struct crypto_alg crypto;
195 struct ahash_alg hash;
196 + struct rng_alg rng;
198 struct sun4i_ss_ctx *ss;
200 @@ -199,3 +207,6 @@ int sun4i_ss_des_setkey(struct crypto_ab
201 unsigned int keylen);
202 int sun4i_ss_des3_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
203 unsigned int keylen);
204 +int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
205 + unsigned int slen, u8 *dst, unsigned int dlen);
206 +int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);