1 /* $NetBSD: rk_v1crypto.c,v 1.11 2023/04/24 05:16:01 mrg Exp $ */
2
3 /*-
4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Taylor R. Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * rk_v1crypto -- Rockchip crypto v1 driver
34 *
35 * This is just the RNG for now.
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(1, "$NetBSD: rk_v1crypto.c,v 1.11 2023/04/24 05:16:01 mrg Exp $");
40
41 #include <sys/types.h>
42
43 #include <sys/bus.h>
44 #include <sys/device.h>
45 #include <sys/errno.h>
46 #include <sys/mutex.h>
47 #include <sys/rndsource.h>
48 #include <sys/sysctl.h>
49
50 #include <dev/fdt/fdtvar.h>
51
52 #include <arm/rockchip/rk_v1crypto.h>
53
54 struct rk_v1crypto_softc {
55 device_t sc_dev;
56 bus_space_tag_t sc_bst;
57 bus_space_handle_t sc_bsh;
58 kmutex_t sc_lock;
59 struct krndsource sc_rndsource;
60 struct rk_v1crypto_sysctl {
61 struct sysctllog *cy_log;
62 const struct sysctlnode *cy_root_node;
63 } sc_sysctl;
64 };
65
66 static int rk_v1crypto_match(device_t, cfdata_t, void *);
67 static void rk_v1crypto_attach(device_t, device_t, void *);
68 static int rk_v1crypto_selftest(struct rk_v1crypto_softc *);
69 static void rk_v1crypto_rndsource_attach(struct rk_v1crypto_softc *);
70 static void rk_v1crypto_rng_get(size_t, void *);
71 static void rk_v1crypto_sysctl_attach(struct rk_v1crypto_softc *);
72 static int rk_v1crypto_sysctl_rng(SYSCTLFN_ARGS);
73 static int rk_v1crypto_rng(struct rk_v1crypto_softc *,
74 uint32_t[static RK_V1CRYPTO_TRNG_NOUT]);
75
76 static uint32_t
RKC_READ(struct rk_v1crypto_softc * sc,bus_addr_t reg)77 RKC_READ(struct rk_v1crypto_softc *sc, bus_addr_t reg)
78 {
79 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg);
80 }
81
82 static void
RKC_WRITE(struct rk_v1crypto_softc * sc,bus_addr_t reg,uint32_t v)83 RKC_WRITE(struct rk_v1crypto_softc *sc, bus_addr_t reg, uint32_t v)
84 {
85 bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, v);
86 }
87
88 static inline void
RKC_CTRL(struct rk_v1crypto_softc * sc,uint16_t m,uint16_t v)89 RKC_CTRL(struct rk_v1crypto_softc *sc, uint16_t m, uint16_t v)
90 {
91 uint32_t c = 0;
92
93 c |= __SHIFTIN(m, RK_V1CRYPTO_CTRL_MASK);
94 c |= __SHIFTIN(v, m);
95 RKC_WRITE(sc, RK_V1CRYPTO_CTRL, c);
96 }
97
98 CFATTACH_DECL_NEW(rk_v1crypto, sizeof(struct rk_v1crypto_softc),
99 rk_v1crypto_match, rk_v1crypto_attach, NULL, NULL);
100
101 struct rk_v1crypto_data {
102 int num_clks;
103 const char *const clks[];
104 };
105
106 static const struct rk_v1crypto_data rk3288_crypto_data = {
107 .num_clks = 4,
108 .clks = {"aclk", "hclk", "sclk", "apb_pclk"},
109 };
110
111 static const struct rk_v1crypto_data rk3328_crypto_data = {
112 .num_clks = 3,
113 .clks = {"hclk_master", "hclk_slave", "sclk"},
114 };
115
116 static const struct device_compatible_entry compat_data[] = {
117 { .compat = "rockchip,rk3288-crypto", .data = &rk3288_crypto_data },
118 { .compat = "rockchip,rk3328-crypto", .data = &rk3328_crypto_data },
119 DEVICE_COMPAT_EOL
120 };
121
122 static int
rk_v1crypto_match(device_t parent,cfdata_t cf,void * aux)123 rk_v1crypto_match(device_t parent, cfdata_t cf, void *aux)
124 {
125 const struct fdt_attach_args *const faa = aux;
126
127 return of_compatible_match(faa->faa_phandle, compat_data);
128 }
129
130 static void
rk_v1crypto_attach(device_t parent,device_t self,void * aux)131 rk_v1crypto_attach(device_t parent, device_t self, void *aux)
132 {
133 struct rk_v1crypto_softc *const sc = device_private(self);
134 const struct fdt_attach_args *const faa = aux;
135 bus_addr_t addr;
136 bus_size_t size;
137 const int phandle = faa->faa_phandle;
138 struct fdtbus_reset *rst;
139 unsigned i;
140 uint32_t ctrl;
141 const struct rk_v1crypto_data *config =
142 of_compatible_lookup(phandle, compat_data)->data;
143 const char *const *clks = config->clks;
144
145 fdtbus_clock_assign(phandle);
146
147 sc->sc_dev = self;
148 sc->sc_bst = faa->faa_bst;
149 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTSERIAL);
150
151 /* Get and map device registers. */
152 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
153 aprint_error(": couldn't get registers\n");
154 return;
155 }
156 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
157 aprint_error(": couldn't map registers\n");
158 return;
159 }
160
161 /* Enable the clocks. */
162 for (i = 0; i < config->num_clks; i++) {
163 if (fdtbus_clock_enable(phandle, clks[i], true) != 0) {
164 aprint_error(": couldn't enable %s clock\n", clks[i]);
165 return;
166 }
167 }
168
169 /* Get a reset handle if we need and try to deassert it. */
170 if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL) {
171 if (fdtbus_reset_deassert(rst) != 0) {
172 aprint_error(": couldn't de-assert reset\n");
173 return;
174 }
175 }
176
177 aprint_naive("\n");
178 aprint_normal(": Crypto v1\n");
179
180 /*
181 * Enable ring oscillator to start gathering entropy, and set
182 * up the crypto clock to sample it once every 100 cycles.
183 *
184 * The ring oscillator can run even when the clock is gated or
185 * flush is asserted, and the longer we run it, the less it
186 * will be synchronized with the main clock owing to jitter
187 * ideally from unpredictable thermal noise.
188 */
189 ctrl = RK_V1CRYPTO_TRNG_CTRL_OSC_ENABLE;
190 ctrl |= __SHIFTIN(100, RK_V1CRYPTO_TRNG_CTRL_CYCLES);
191 RKC_WRITE(sc, RK_V1CRYPTO_TRNG_CTRL, ctrl);
192
193 if (rk_v1crypto_selftest(sc))
194 return;
195 rk_v1crypto_rndsource_attach(sc);
196 rk_v1crypto_sysctl_attach(sc);
197 }
198
199 static int
rk_v1crypto_selftest(struct rk_v1crypto_softc * sc)200 rk_v1crypto_selftest(struct rk_v1crypto_softc *sc)
201 {
202 static const uint32_t key[4] = {0};
203 static const uint32_t input[4] = {0};
204 static const uint32_t expected[4] = {
205 0x66e94bd4, 0xef8a2c3b, 0x884cfa59, 0xca342b2e,
206 };
207 uint32_t output[4];
208 uint32_t ctrl;
209 unsigned i, timo;
210
211 /* Program the key and input block. */
212 for (i = 0; i < 4; i++)
213 RKC_WRITE(sc, RK_V1CRYPTO_AES_DIN(i), key[i]);
214 for (i = 0; i < 4; i++)
215 RKC_WRITE(sc, RK_V1CRYPTO_AES_DIN(i), input[i]);
216
217 /*
218 * Set up the AES unit to do AES-128 `ECB' (i.e., just the raw
219 * AES permutation) in the encryption direction.
220 */
221 ctrl = 0;
222 ctrl |= RK_V1CRYPTO_AES_CTRL_KEYCHANGE;
223 ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_MODE_ECB,
224 RK_V1CRYPTO_AES_CTRL_MODE);
225 ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_KEYSIZE_128,
226 RK_V1CRYPTO_AES_CTRL_KEYSIZE);
227 ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_DIR_ENC,
228 RK_V1CRYPTO_AES_CTRL_DIR);
229 RKC_WRITE(sc, RK_V1CRYPTO_AES_CTRL, ctrl);
230
231 /* Kick it off. */
232 RKC_CTRL(sc, RK_V1CRYPTO_CTRL_AES_START, 1);
233
234 /* Wait up to 1ms for it to complete. */
235 timo = 1000;
236 while (RKC_READ(sc, RK_V1CRYPTO_CTRL) & RK_V1CRYPTO_CTRL_AES_START) {
237 if (--timo == 0) {
238 device_printf(sc->sc_dev, "AES self-test timed out\n");
239 return -1;
240 }
241 DELAY(1);
242 }
243
244 /* Read the output. */
245 for (i = 0; i < 4; i++)
246 output[i] = RKC_READ(sc, RK_V1CRYPTO_AES_DOUT(i));
247
248 /* Verify the output. */
249 for (i = 0; i < 4; i++) {
250 if (output[i] != expected[i]) {
251 device_printf(sc->sc_dev, "AES self-test failed\n");
252 return -1;
253 }
254 }
255
256 /* Success! */
257 return 0;
258 }
259
260 static void
rk_v1crypto_rndsource_attach(struct rk_v1crypto_softc * sc)261 rk_v1crypto_rndsource_attach(struct rk_v1crypto_softc *sc)
262 {
263 device_t self = sc->sc_dev;
264
265 rndsource_setcb(&sc->sc_rndsource, rk_v1crypto_rng_get, sc);
266 rnd_attach_source(&sc->sc_rndsource, device_xname(self),
267 RND_TYPE_RNG, RND_FLAG_DEFAULT|RND_FLAG_HASCB);
268 }
269
270 static void
rk_v1crypto_rng_get(size_t nbytes,void * cookie)271 rk_v1crypto_rng_get(size_t nbytes, void *cookie)
272 {
273 struct rk_v1crypto_softc *sc = cookie;
274 device_t self = sc->sc_dev;
275 uint32_t buf[RK_V1CRYPTO_TRNG_NOUT];
276 uint32_t entropybits = NBBY*sizeof(buf)/2; /* be conservative */
277 unsigned n = RK_V1CRYPTO_TRNG_NOUT;
278 int error;
279 size_t nbits = NBBY*nbytes;
280
281 while (nbits) {
282 CTASSERT((RK_V1CRYPTO_TRNG_NOUT % 2) == 0);
283
284 error = rk_v1crypto_rng(sc, buf);
285 if (error) {
286 device_printf(self, "timed out\n");
287 break;
288 }
289 if (consttime_memequal(buf, buf + n/2, sizeof(buf[0]) * n/2)) {
290 device_printf(self, "failed repeated output test\n");
291 break;
292 }
293 rnd_add_data_sync(&sc->sc_rndsource, buf, sizeof buf,
294 entropybits);
295 nbits -= MIN(nbits, MAX(1, entropybits));
296 }
297 explicit_memset(buf, 0, sizeof buf);
298 }
299
300 static void
rk_v1crypto_sysctl_attach(struct rk_v1crypto_softc * sc)301 rk_v1crypto_sysctl_attach(struct rk_v1crypto_softc *sc)
302 {
303 device_t self = sc->sc_dev;
304 struct rk_v1crypto_sysctl *cy = &sc->sc_sysctl;
305 int error;
306
307 /* hw.rkv1cryptoN (node) */
308 error = sysctl_createv(&cy->cy_log, 0, NULL, &cy->cy_root_node,
309 CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(self),
310 SYSCTL_DESCR("rk crypto v1 engine knobs"),
311 NULL, 0, NULL, 0,
312 CTL_HW, CTL_CREATE, CTL_EOL);
313 if (error) {
314 aprint_error_dev(self,
315 "failed to set up sysctl hw.%s: %d\n",
316 device_xname(self), error);
317 return;
318 }
319
320 /* hw.rkv1cryptoN.rng (`struct', 32-byte array) */
321 error = sysctl_createv(&cy->cy_log, 0, &cy->cy_root_node, NULL,
322 CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_STRUCT,
323 "rng", SYSCTL_DESCR("Read up to 32 bytes out of the TRNG"),
324 &rk_v1crypto_sysctl_rng, 0, sc, 0, CTL_CREATE, CTL_EOL);
325 if (error) {
326 aprint_error_dev(self,
327 "failed to set up sysctl hw.%s.rng: %d\n",
328 device_xname(self), error);
329 return;
330 }
331 }
332
333 static int
rk_v1crypto_sysctl_rng(SYSCTLFN_ARGS)334 rk_v1crypto_sysctl_rng(SYSCTLFN_ARGS)
335 {
336 uint32_t buf[RK_V1CRYPTO_TRNG_NOUT];
337 struct sysctlnode node = *rnode;
338 struct rk_v1crypto_softc *sc = node.sysctl_data;
339 size_t size;
340 int error;
341
342 /* If oldp == NULL, the caller wants to learn the size. */
343 if (oldp == NULL) {
344 *oldlenp = sizeof buf;
345 return 0;
346 }
347
348 /* Verify the output buffer size is reasonable. */
349 size = *oldlenp;
350 if (size > sizeof buf) /* size_t, so never negative */
351 return E2BIG;
352 if (size == 0)
353 return 0; /* nothing to do */
354
355 /* Generate data. */
356 error = rk_v1crypto_rng(sc, buf);
357 if (error)
358 return error;
359
360 /* Copy out the data. */
361 node.sysctl_data = buf;
362 node.sysctl_size = size;
363 error = sysctl_lookup(SYSCTLFN_CALL(&node));
364
365 /* Clear the buffer. */
366 explicit_memset(buf, 0, sizeof buf);
367
368 /* Return the sysctl_lookup error, if any. */
369 return error;
370 }
371
372 static int
rk_v1crypto_rng(struct rk_v1crypto_softc * sc,uint32_t buf[static RK_V1CRYPTO_TRNG_NOUT])373 rk_v1crypto_rng(struct rk_v1crypto_softc *sc,
374 uint32_t buf[static RK_V1CRYPTO_TRNG_NOUT])
375 {
376 unsigned i, timo;
377 int error;
378
379 /* Acquire lock to serialize access to TRNG. */
380 mutex_enter(&sc->sc_lock);
381
382 /*
383 * Query TRNG and wait up to 1ms for it to post. Empirically,
384 * this takes around 120us.
385 */
386 RKC_CTRL(sc, RK_V1CRYPTO_CTRL_TRNG_START, 1);
387 timo = 1000;
388 while (RKC_READ(sc, RK_V1CRYPTO_CTRL) & RK_V1CRYPTO_CTRL_TRNG_START) {
389 if (--timo == 0) {
390 error = ETIMEDOUT;
391 goto out;
392 }
393 DELAY(1);
394 }
395
396 /* Read out the data. */
397 for (i = 0; i < RK_V1CRYPTO_TRNG_NOUT; i++)
398 buf[i] = RKC_READ(sc, RK_V1CRYPTO_TRNG_DOUT(i));
399
400 /* Success! */
401 error = 0;
402 out: mutex_exit(&sc->sc_lock);
403 return error;
404 }
405