xref: /netbsd-src/sys/arch/arm/rockchip/rk_v1crypto.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /*	$NetBSD: rk_v1crypto.c,v 1.7 2021/01/27 03:10:19 thorpej 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.7 2021/01/27 03:10:19 thorpej 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
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
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
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 static const struct device_compatible_entry compat_data[] = {
102 	{ .compat = "rockchip,rk3288-crypto" },
103 	DEVICE_COMPAT_EOL
104 };
105 
106 static int
107 rk_v1crypto_match(device_t parent, cfdata_t cf, void *aux)
108 {
109 	const struct fdt_attach_args *const faa = aux;
110 
111 	return of_compatible_match(faa->faa_phandle, compat_data);
112 }
113 
114 static void
115 rk_v1crypto_attach(device_t parent, device_t self, void *aux)
116 {
117 	static const char *const clks[] = {"aclk", "hclk", "sclk", "apb_pclk"};
118 	struct rk_v1crypto_softc *const sc = device_private(self);
119 	const struct fdt_attach_args *const faa = aux;
120 	bus_addr_t addr;
121 	bus_size_t size;
122 	const int phandle = faa->faa_phandle;
123 	struct fdtbus_reset *rst;
124 	unsigned i;
125 	uint32_t ctrl;
126 
127 	fdtbus_clock_assign(phandle);
128 
129 	sc->sc_dev = self;
130 	sc->sc_bst = faa->faa_bst;
131 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
132 
133 	/* Get and map device registers.  */
134 	if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
135 		aprint_error(": couldn't get registers\n");
136 		return;
137 	}
138 	if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
139 		aprint_error(": couldn't map registers\n");
140 		return;
141 	}
142 
143 	/* Enable the clocks.  */
144 	for (i = 0; i < __arraycount(clks); i++) {
145 		if (fdtbus_clock_enable(phandle, clks[i], true) != 0) {
146 			aprint_error(": couldn't enable %s clock\n", clks[i]);
147 			return;
148 		}
149 	}
150 
151 	/* Get a reset handle if we need and try to deassert it.  */
152 	if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL) {
153 		if (fdtbus_reset_deassert(rst) != 0) {
154 			aprint_error(": couldn't de-assert reset\n");
155 			return;
156 		}
157 	}
158 
159 	aprint_naive("\n");
160 	aprint_normal(": Crypto v1\n");
161 
162 	/*
163 	 * Enable ring oscillator to start gathering entropy, and set
164 	 * up the crypto clock to sample it once every 100 cycles.
165 	 *
166 	 * The ring oscillator can run even when the clock is gated or
167 	 * flush is asserted, and the longer we run it, the less it
168 	 * will be synchronized with the main clock owing to jitter
169 	 * ideally from unpredictable thermal noise.
170 	 */
171 	ctrl = RK_V1CRYPTO_TRNG_CTRL_OSC_ENABLE;
172 	ctrl |= __SHIFTIN(100, RK_V1CRYPTO_TRNG_CTRL_CYCLES);
173 	RKC_WRITE(sc, RK_V1CRYPTO_TRNG_CTRL, ctrl);
174 
175 	if (rk_v1crypto_selftest(sc))
176 		return;
177 	rk_v1crypto_rndsource_attach(sc);
178 	rk_v1crypto_sysctl_attach(sc);
179 }
180 
181 static int
182 rk_v1crypto_selftest(struct rk_v1crypto_softc *sc)
183 {
184 	static const uint32_t key[4] = {0};
185 	static const uint32_t input[4] = {0};
186 	static const uint32_t expected[4] = {
187 		0x66e94bd4, 0xef8a2c3b, 0x884cfa59, 0xca342b2e,
188 	};
189 	uint32_t output[4];
190 	uint32_t ctrl;
191 	unsigned i, timo;
192 
193 	/* Program the key and input block.  */
194 	for (i = 0; i < 4; i++)
195 		RKC_WRITE(sc, RK_V1CRYPTO_AES_DIN(i), key[i]);
196 	for (i = 0; i < 4; i++)
197 		RKC_WRITE(sc, RK_V1CRYPTO_AES_DIN(i), input[i]);
198 
199 	/*
200 	 * Set up the AES unit to do AES-128 `ECB' (i.e., just the raw
201 	 * AES permutation) in the encryption direction.
202 	 */
203 	ctrl = 0;
204 	ctrl |= RK_V1CRYPTO_AES_CTRL_KEYCHANGE;
205 	ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_MODE_ECB,
206 	    RK_V1CRYPTO_AES_CTRL_MODE);
207 	ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_KEYSIZE_128,
208 	    RK_V1CRYPTO_AES_CTRL_KEYSIZE);
209 	ctrl |= __SHIFTIN(RK_V1CRYPTO_AES_CTRL_DIR_ENC,
210 	    RK_V1CRYPTO_AES_CTRL_DIR);
211 	RKC_WRITE(sc, RK_V1CRYPTO_AES_CTRL, ctrl);
212 
213 	/* Kick it off.  */
214 	RKC_CTRL(sc, RK_V1CRYPTO_CTRL_AES_START, 1);
215 
216 	/* Wait up to 1ms for it to complete.  */
217 	timo = 1000;
218 	while (RKC_READ(sc, RK_V1CRYPTO_CTRL) & RK_V1CRYPTO_CTRL_AES_START) {
219 		if (--timo == 0) {
220 			device_printf(sc->sc_dev, "AES self-test timed out\n");
221 			return -1;
222 		}
223 		DELAY(1);
224 	}
225 
226 	/* Read the output.  */
227 	for (i = 0; i < 4; i++)
228 		output[i] = RKC_READ(sc, RK_V1CRYPTO_AES_DOUT(i));
229 
230 	/* Verify the output.  */
231 	for (i = 0; i < 4; i++) {
232 		if (output[i] != expected[i]) {
233 			device_printf(sc->sc_dev, "AES self-test failed\n");
234 			return -1;
235 		}
236 	}
237 
238 	/* Success!  */
239 	return 0;
240 }
241 
242 static void
243 rk_v1crypto_rndsource_attach(struct rk_v1crypto_softc *sc)
244 {
245 	device_t self = sc->sc_dev;
246 
247 	rndsource_setcb(&sc->sc_rndsource, rk_v1crypto_rng_get, sc);
248 	rnd_attach_source(&sc->sc_rndsource, device_xname(self),
249 	    RND_TYPE_RNG, RND_FLAG_DEFAULT|RND_FLAG_HASCB);
250 }
251 
252 static void
253 rk_v1crypto_rng_get(size_t nbytes, void *cookie)
254 {
255 	struct rk_v1crypto_softc *sc = cookie;
256 	device_t self = sc->sc_dev;
257 	uint32_t buf[RK_V1CRYPTO_TRNG_NOUT];
258 	uint32_t entropybits = NBBY*sizeof(buf)/2; /* be conservative */
259 	unsigned n = RK_V1CRYPTO_TRNG_NOUT;
260 	int error;
261 	size_t nbits = NBBY*nbytes;
262 
263 	while (nbits) {
264 		CTASSERT((RK_V1CRYPTO_TRNG_NOUT % 2) == 0);
265 
266 		error = rk_v1crypto_rng(sc, buf);
267 		if (error) {
268 			device_printf(self, "timed out\n");
269 			break;
270 		}
271 		if (consttime_memequal(buf, buf + n/2, n/2)) {
272 			device_printf(self, "failed repeated output test\n");
273 			break;
274 		}
275 		rnd_add_data_sync(&sc->sc_rndsource, buf, sizeof buf,
276 		    entropybits);
277 		nbits -= MIN(nbits, MAX(1, entropybits));
278 	}
279 	explicit_memset(buf, 0, sizeof buf);
280 }
281 
282 static void
283 rk_v1crypto_sysctl_attach(struct rk_v1crypto_softc *sc)
284 {
285 	device_t self = sc->sc_dev;
286 	struct rk_v1crypto_sysctl *cy = &sc->sc_sysctl;
287 	int error;
288 
289 	/* hw.rkv1cryptoN (node) */
290 	error = sysctl_createv(&cy->cy_log, 0, NULL, &cy->cy_root_node,
291 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(self),
292 	    SYSCTL_DESCR("rk crypto v1 engine knobs"),
293 	    NULL, 0, NULL, 0,
294 	    CTL_HW, CTL_CREATE, CTL_EOL);
295 	if (error) {
296 		aprint_error_dev(self,
297 		    "failed to set up sysctl hw.%s: %d\n",
298 		    device_xname(self), error);
299 		return;
300 	}
301 
302 	/* hw.rkv1cryptoN.rng (`struct', 32-byte array) */
303 	sysctl_createv(&cy->cy_log, 0, &cy->cy_root_node, NULL,
304 	    CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_STRUCT,
305 	    "rng", SYSCTL_DESCR("Read up to 32 bytes out of the TRNG"),
306 	    &rk_v1crypto_sysctl_rng, 0, sc, 0, CTL_CREATE, CTL_EOL);
307 	if (error) {
308 		aprint_error_dev(self,
309 		    "failed to set up sysctl hw.%s.rng: %d\n",
310 		    device_xname(self), error);
311 		return;
312 	}
313 }
314 
315 static int
316 rk_v1crypto_sysctl_rng(SYSCTLFN_ARGS)
317 {
318 	uint32_t buf[RK_V1CRYPTO_TRNG_NOUT];
319 	struct sysctlnode node = *rnode;
320 	struct rk_v1crypto_softc *sc = node.sysctl_data;
321 	size_t size;
322 	int error;
323 
324 	/* If oldp == NULL, the caller wants to learn the size.  */
325 	if (oldp == NULL) {
326 		*oldlenp = sizeof buf;
327 		return 0;
328 	}
329 
330 	/* Verify the output buffer size is reasonable.  */
331 	size = *oldlenp;
332 	if (size > sizeof buf)	/* size_t, so never negative */
333 		return E2BIG;
334 	if (size == 0)
335 		return 0;	/* nothing to do */
336 
337 	/* Generate data.  */
338 	error = rk_v1crypto_rng(sc, buf);
339 	if (error)
340 		return error;
341 
342 	/* Copy out the data.  */
343 	node.sysctl_data = buf;
344 	node.sysctl_size = size;
345 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
346 
347 	/* Clear the buffer.  */
348 	explicit_memset(buf, 0, sizeof buf);
349 
350 	/* Return the sysctl_lookup error, if any.  */
351 	return error;
352 }
353 
354 static int
355 rk_v1crypto_rng(struct rk_v1crypto_softc *sc,
356     uint32_t buf[static RK_V1CRYPTO_TRNG_NOUT])
357 {
358 	unsigned i, timo;
359 	int error;
360 
361 	/* Acquire lock to serialize access to TRNG.  */
362 	mutex_enter(&sc->sc_lock);
363 
364 	/*
365 	 * Query TRNG and wait up to 1ms for it to post.  Empirically,
366 	 * this takes around 120us.
367 	 */
368 	RKC_CTRL(sc, RK_V1CRYPTO_CTRL_TRNG_START, 1);
369 	timo = 1000;
370 	while (RKC_READ(sc, RK_V1CRYPTO_CTRL) & RK_V1CRYPTO_CTRL_TRNG_START) {
371 		if (--timo == 0) {
372 			error = ETIMEDOUT;
373 			goto out;
374 		}
375 		DELAY(1);
376 	}
377 
378 	/* Read out the data.  */
379 	for (i = 0; i < RK_V1CRYPTO_TRNG_NOUT; i++)
380 		buf[i] = RKC_READ(sc, RK_V1CRYPTO_TRNG_DOUT(i));
381 
382 	/* Success!  */
383 	error = 0;
384 out:	mutex_exit(&sc->sc_lock);
385 	return error;
386 }
387