sunxi: backport support for Allwinner Security System PRNG
[openwrt/staging/mkresin.git] / target / linux / sunxi / patches-4.9 / 0054-crypto-sun4i-ss_support_the_Security_System_PRNG.patch
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
5
6 The Security System has a PRNG, this patch adds support for it via
7 crypto_rng.
8
9 Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
10 Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
11 ---
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
19
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.
25
26 +config CRYPTO_DEV_SUN4I_SS_PRNG
27 + bool "Support for Allwinner Security System PRNG"
28 + depends on CRYPTO_DEV_SUN4I_SS
29 + select CRYPTO_RNG
30 + help
31 + Select this option if you want to provide kernel-side support for
32 + the Pseudo-Random Number Generator found in the Security System.
33 +
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
39 @@ -1,2 +1,3 @@
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
46 }
47 }
48 },
49 +#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
50 +{
51 + .type = CRYPTO_ALG_TYPE_RNG,
52 + .alg.rng = {
53 + .base = {
54 + .cra_name = "stdrng",
55 + .cra_driver_name = "sun4i_ss_rng",
56 + .cra_priority = 300,
57 + .cra_ctxsize = 0,
58 + .cra_module = THIS_MODULE,
59 + },
60 + .generate = sun4i_ss_prng_generate,
61 + .seed = sun4i_ss_prng_seed,
62 + .seedsize = SS_SEED_LEN / BITS_PER_BYTE,
63 + }
64 +},
65 +#endif
66 };
67
68 static int sun4i_ss_probe(struct platform_device *pdev)
69 @@ -356,6 +373,13 @@ static int sun4i_ss_probe(struct platfor
70 goto error_alg;
71 }
72 break;
73 + case CRYPTO_ALG_TYPE_RNG:
74 + err = crypto_register_rng(&ss_algs[i].alg.rng);
75 + if (err) {
76 + dev_err(ss->dev, "Fail to register %s\n",
77 + ss_algs[i].alg.rng.base.cra_name);
78 + }
79 + break;
80 }
81 }
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);
86 break;
87 + case CRYPTO_ALG_TYPE_RNG:
88 + crypto_unregister_rng(&ss_algs[i].alg.rng);
89 + break;
90 }
91 }
92 if (ss->reset)
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);
96 break;
97 + case CRYPTO_ALG_TYPE_RNG:
98 + crypto_unregister_rng(&ss_algs[i].alg.rng);
99 + break;
100 }
101 }
102
103 --- /dev/null
104 +++ b/drivers/crypto/sunxi-ss/sun4i-ss-prng.c
105 @@ -0,0 +1,56 @@
106 +#include "sun4i-ss.h"
107 +
108 +int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
109 + unsigned int slen)
110 +{
111 + struct sun4i_ss_alg_template *algt;
112 + struct rng_alg *alg = crypto_rng_alg(tfm);
113 +
114 + algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
115 + memcpy(algt->ss->seed, seed, slen);
116 +
117 + return 0;
118 +}
119 +
120 +int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
121 + unsigned int slen, u8 *dst, unsigned int dlen)
122 +{
123 + struct sun4i_ss_alg_template *algt;
124 + struct rng_alg *alg = crypto_rng_alg(tfm);
125 + int i;
126 + u32 v;
127 + u32 *data = (u32 *)dst;
128 + const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED;
129 + size_t len;
130 + struct sun4i_ss_ctx *ss;
131 + unsigned int todo = (dlen / 4) * 4;
132 +
133 + algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
134 + ss = algt->ss;
135 +
136 + spin_lock(&ss->slock);
137 +
138 + writel(mode, ss->base + SS_CTL);
139 +
140 + while (todo > 0) {
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);
144 +
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);
148 + data += len / 4;
149 + todo -= len;
150 +
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);
154 + ss->seed[i] = v;
155 + }
156 + }
157 +
158 + writel(0, ss->base + SS_CTL);
159 + spin_unlock(&ss->slock);
160 + return dlen;
161 +}
162 --- a/drivers/crypto/sunxi-ss/sun4i-ss.h
163 +++ b/drivers/crypto/sunxi-ss/sun4i-ss.h
164 @@ -30,6 +30,7 @@
165 #include <crypto/aes.h>
166 #include <crypto/des.h>
167 #include <crypto/internal/rng.h>
168 +#include <crypto/rng.h>
169
170 #define SS_CTL 0x00
171 #define SS_KEY0 0x04
172 @@ -125,6 +126,9 @@
173 #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2)
174 #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0)
175
176 +#define SS_SEED_LEN 192
177 +#define SS_DATA_LEN 160
178 +
179 struct sun4i_ss_ctx {
180 void __iomem *base;
181 int irq;
182 @@ -134,6 +138,9 @@ struct sun4i_ss_ctx {
183 struct device *dev;
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];
188 +#endif
189 };
190
191 struct sun4i_ss_alg_template {
192 @@ -142,6 +149,7 @@ struct sun4i_ss_alg_template {
193 union {
194 struct crypto_alg crypto;
195 struct ahash_alg hash;
196 + struct rng_alg rng;
197 } alg;
198 struct sun4i_ss_ctx *ss;
199 };
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);