sun8i_crypto.c revision 1.1 1 /* $NetBSD: sun8i_crypto.c,v 1.1 2019/12/09 04:51:03 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2019 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 * sun8i_crypto -- Allwinner Crypto Engine driver
34 *
35 * The Crypto Engine is documented in Sec. 3.15 of the Allwinner A64
36 * User Manual v1.1, on pp. 230--241. We only use it for the TRNG at
37 * the moment, but in principle it could be wired up with opencrypto(9)
38 * to compute AES, DES, 3DES, MD5, SHA-1, SHA-224, SHA-256, HMAC-SHA1,
39 * HMAC-HA256, RSA, and an undocumented PRNG. It also seems to support
40 * AES keys in SRAM (for some kind of HDMI HDCP stuff?).
41 *
42 * https://linux-sunxi.org/images/b/b4/Allwinner_A64_User_Manual_V1.1.pdf
43 */
44
45 #include <sys/cdefs.h>
46 __KERNEL_RCSID(1, "$NetBSD: sun8i_crypto.c,v 1.1 2019/12/09 04:51:03 riastradh Exp $");
47
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/atomic.h>
51 #include <sys/bus.h>
52 #include <sys/callout.h>
53 #include <sys/conf.h>
54 #include <sys/device.h>
55 #include <sys/kernel.h>
56 #include <sys/kmem.h>
57 #include <sys/mutex.h>
58 #include <sys/rndpool.h>
59 #include <sys/rndsource.h>
60 #include <sys/sysctl.h>
61 #include <sys/workqueue.h>
62
63 #include <dev/fdt/fdtvar.h>
64
65 #include <arm/sunxi/sun8i_crypto.h>
66
67 #define SUN8I_CRYPTO_TIMEOUT hz
68 #define SUN8I_CRYPTO_RNGENTROPY 8 /* estimated bits per bit of entropy */
69 #define SUN8I_CRYPTO_RNGBYTES \
70 (SUN8I_CRYPTO_RNGENTROPY*howmany(RND_POOLBITS, NBBY))
71
72 struct sun8i_crypto_task;
73
74 struct sun8i_crypto_buf {
75 bus_dma_segment_t cb_seg[1];
76 int cb_nsegs;
77 bus_dmamap_t cb_map;
78 void *cb_kva;
79 };
80
81 struct sun8i_crypto_softc {
82 device_t sc_dev;
83 bus_space_tag_t sc_bst;
84 bus_space_handle_t sc_bsh;
85 bus_dma_tag_t sc_dmat;
86 kmutex_t sc_lock;
87 struct sun8i_crypto_chan {
88 struct sun8i_crypto_task *cc_task;
89 unsigned cc_starttime;
90 } sc_chan[SUN8I_CRYPTO_NCHAN];
91 struct callout sc_timeout;
92 struct workqueue *sc_wq;
93 struct work sc_work;
94 void *sc_ih;
95 uint32_t sc_done;
96 uint32_t sc_esr;
97 bool sc_work_pending;
98 struct sun8i_crypto_rng {
99 struct sun8i_crypto_buf cr_buf;
100 struct sun8i_crypto_task *cr_task;
101 struct krndsource cr_rndsource;
102 bool cr_pending;
103 } sc_rng;
104 struct sun8i_crypto_selftest {
105 struct sun8i_crypto_buf cs_in;
106 struct sun8i_crypto_buf cs_key;
107 struct sun8i_crypto_buf cs_out;
108 struct sun8i_crypto_task *cs_task;
109 } sc_selftest;
110 struct sun8i_crypto_sysctl {
111 struct sysctllog *cy_log;
112 const struct sysctlnode *cy_root_node;
113 const struct sysctlnode *cy_trng_node;
114 } sc_sysctl;
115 };
116
117 struct sun8i_crypto_task {
118 bus_dma_segment_t ct_desc_seg[1];
119 int ct_desc_nseg;
120 bus_dmamap_t ct_desc_map;
121 void *ct_desc_kva;
122 struct sun8i_crypto_taskdesc *ct_desc;
123 void (*ct_callback)(struct sun8i_crypto_softc *,
124 struct sun8i_crypto_task *, void *, int);
125 void *ct_cookie;
126 };
127
128 /*
129 * Forward declarations
130 */
131
132 static int sun8i_crypto_match(device_t, cfdata_t, void *);
133 static void sun8i_crypto_attach(device_t, device_t, void *);
134
135 static struct sun8i_crypto_task *
136 sun8i_crypto_task_get(struct sun8i_crypto_softc *,
137 void (*)(struct sun8i_crypto_softc *,
138 struct sun8i_crypto_task *, void *, int),
139 void *);
140 static void sun8i_crypto_task_put(struct sun8i_crypto_softc *,
141 struct sun8i_crypto_task *);
142 static void sun8i_crypto_task_reset(struct sun8i_crypto_task *);
143
144 static void sun8i_crypto_task_set_key(struct sun8i_crypto_task *,
145 bus_dmamap_t);
146 static void sun8i_crypto_task_set_iv(struct sun8i_crypto_task *,
147 bus_dmamap_t);
148 static void sun8i_crypto_task_set_ctr(struct sun8i_crypto_task *,
149 bus_dmamap_t);
150 static void sun8i_crypto_task_set_input(struct sun8i_crypto_task *,
151 bus_dmamap_t);
152 static void sun8i_crypto_task_set_output(struct sun8i_crypto_task *,
153 bus_dmamap_t);
154
155 static void sun8i_crypto_task_scatter(struct sun8i_crypto_adrlen *,
156 bus_dmamap_t);
157
158 static int sun8i_crypto_submit_trng(struct sun8i_crypto_softc *,
159 struct sun8i_crypto_task *, uint32_t);
160 static int sun8i_crypto_submit_aesecb(struct sun8i_crypto_softc *,
161 struct sun8i_crypto_task *, uint32_t, uint32_t, uint32_t);
162 static int sun8i_crypto_submit(struct sun8i_crypto_softc *,
163 struct sun8i_crypto_task *);
164
165 static void sun8i_crypto_timeout(void *);
166 static int sun8i_crypto_intr(void *);
167 static void sun8i_crypto_schedule_worker(struct sun8i_crypto_softc *);
168 static void sun8i_crypto_worker(struct work *, void *);
169 static void sun8i_crypto_chan_done(struct sun8i_crypto_softc *, unsigned,
170 int);
171
172 static int sun8i_crypto_allocbuf(struct sun8i_crypto_softc *, size_t,
173 struct sun8i_crypto_buf *);
174 static void sun8i_crypto_freebuf(struct sun8i_crypto_softc *, size_t,
175 struct sun8i_crypto_buf *);
176
177 static void sun8i_crypto_rng_attach(struct sun8i_crypto_softc *);
178 static void sun8i_crypto_rng_get(size_t, void *);
179 static void sun8i_crypto_rng_done(struct sun8i_crypto_softc *,
180 struct sun8i_crypto_task *, void *, int);
181
182 static void sun8i_crypto_selftest(device_t);
183 static void sun8i_crypto_selftest_done(struct sun8i_crypto_softc *,
184 struct sun8i_crypto_task *, void *, int);
185
186 static void sun8i_crypto_sysctl_attach(struct sun8i_crypto_softc *);
187 static int sun8i_crypto_sysctl_rng(SYSCTLFN_ARGS);
188 static void sun8i_crypto_sysctl_rng_done(struct sun8i_crypto_softc *,
189 struct sun8i_crypto_task *, void *, int);
190
191 /*
192 * Register access
193 */
194
195 static uint32_t
196 sun8i_crypto_read(struct sun8i_crypto_softc *sc, bus_addr_t reg)
197 {
198 return bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg);
199 }
200
201 static void
202 sun8i_crypto_write(struct sun8i_crypto_softc *sc, bus_addr_t reg, uint32_t v)
203 {
204 bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg, v);
205 }
206
207 /*
208 * Autoconf goo
209 */
210
211 CFATTACH_DECL_NEW(sun8i_crypto, sizeof(struct sun8i_crypto_softc),
212 sun8i_crypto_match, sun8i_crypto_attach, NULL, NULL);
213
214 static const struct of_compat_data compat_data[] = {
215 {"allwinner,sun50i-a64-crypto", 0},
216 {NULL}
217 };
218
219 static int
220 sun8i_crypto_match(device_t parent, cfdata_t cf, void *aux)
221 {
222 const struct fdt_attach_args *const faa = aux;
223
224 return of_match_compat_data(faa->faa_phandle, compat_data);
225 }
226
227 static void
228 sun8i_crypto_attach(device_t parent, device_t self, void *aux)
229 {
230 struct sun8i_crypto_softc *const sc = device_private(self);
231 const struct fdt_attach_args *const faa = aux;
232 bus_addr_t addr;
233 bus_size_t size;
234 const int phandle = faa->faa_phandle;
235 char intrstr[128];
236 struct clk *clk;
237 struct fdtbus_reset *rst;
238
239 sc->sc_dev = self;
240 sc->sc_dmat = faa->faa_dmat;
241 sc->sc_bst = faa->faa_bst;
242 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
243 callout_init(&sc->sc_timeout, CALLOUT_MPSAFE);
244 callout_setfunc(&sc->sc_timeout, &sun8i_crypto_timeout, sc);
245 if (workqueue_create(&sc->sc_wq, device_xname(self),
246 &sun8i_crypto_worker, sc, PRI_NONE, IPL_VM, WQ_MPSAFE) != 0) {
247 aprint_error(": couldn't create workqueue\n");
248 return;
249 }
250
251 /* Get and map device registers. */
252 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
253 aprint_error(": couldn't get registers\n");
254 return;
255 }
256 if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
257 aprint_error(": couldn't map registers\n");
258 return;
259 }
260
261 /* Get an interrupt handle. */
262 if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
263 aprint_error(": failed to decode interrupt\n");
264 return;
265 }
266
267 /* Enable the bus clock. */
268 if (fdtbus_clock_enable(phandle, "bus", true) != 0) {
269 aprint_error(": couldn't enable bus clock\n");
270 return;
271 }
272
273 /* Get the module clock and set it to 300 MHz. */
274 if ((clk = fdtbus_clock_get(phandle, "mod")) != NULL) {
275 if (clk_enable(clk) != 0) {
276 aprint_error(": couldn't enable CE clock\n");
277 return;
278 }
279 if (clk_set_rate(clk, 300*1000*1000) != 0) {
280 aprint_error(": couldn't set CE clock to 300MHz\n");
281 return;
282 }
283 }
284
285 /* Get a reset handle if we need and try to deassert it. */
286 if ((rst = fdtbus_reset_get_index(phandle, 0)) != NULL) {
287 if (fdtbus_reset_deassert(rst) != 0) {
288 aprint_error(": couldn't de-assert reset\n");
289 return;
290 }
291 }
292
293 aprint_naive("\n");
294 aprint_normal(": Crypto Engine\n");
295 aprint_debug_dev(self, ": clock freq %d\n", clk_get_rate(clk));
296
297 /* Disable and clear interrupts. */
298 sun8i_crypto_write(sc, SUN8I_CRYPTO_ICR, 0);
299 sun8i_crypto_write(sc, SUN8I_CRYPTO_ISR, 0);
300
301 /* Establish an interrupt handler. */
302 sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_VM, FDT_INTR_MPSAFE,
303 &sun8i_crypto_intr, sc);
304 if (sc->sc_ih == NULL) {
305 aprint_error_dev(self, "failed to establish interrupt on %s\n",
306 intrstr);
307 return;
308 }
309 aprint_normal_dev(self, "interrupting on %s\n", intrstr);
310
311 /* Set up the RNG. */
312 sun8i_crypto_rng_attach(sc);
313
314 /* Attach the sysctl. */
315 sun8i_crypto_sysctl_attach(sc);
316
317 /* Perform self-tests. */
318 config_interrupts(self, sun8i_crypto_selftest);
319 }
320
321 /*
322 * Task allocation
323 */
324
325 static struct sun8i_crypto_task *
326 sun8i_crypto_task_get(struct sun8i_crypto_softc *sc,
327 void (*callback)(struct sun8i_crypto_softc *, struct sun8i_crypto_task *,
328 void *, int),
329 void *cookie)
330 {
331 struct sun8i_crypto_task *task;
332 const size_t desc_size = sizeof(*task->ct_desc);
333 int error;
334
335 task = kmem_zalloc(sizeof(*task), KM_SLEEP);
336
337 /* Allocate DMA-safe memory for the descriptor. */
338 error = bus_dmamem_alloc(sc->sc_dmat, desc_size, 0, 0,
339 task->ct_desc_seg, __arraycount(task->ct_desc_seg),
340 &task->ct_desc_nseg, BUS_DMA_NOWAIT);
341 if (error)
342 goto fail0;
343
344 /* Map the descriptor into kernel virtual address space. */
345 error = bus_dmamem_map(sc->sc_dmat, task->ct_desc_seg,
346 task->ct_desc_nseg, desc_size, &task->ct_desc_kva, BUS_DMA_NOWAIT);
347 if (error)
348 goto fail1;
349 task->ct_desc = task->ct_desc_kva;
350
351 /* Create a map for exposing the descriptor to DMA. */
352 error = bus_dmamap_create(sc->sc_dmat, desc_size, 1, desc_size, 0,
353 BUS_DMA_NOWAIT, &task->ct_desc_map);
354 if (error)
355 goto fail2;
356
357 /* Load the descriptor into the DMA map. */
358 error = bus_dmamap_load(sc->sc_dmat, task->ct_desc_map,
359 task->ct_desc_kva, desc_size, NULL, BUS_DMA_NOWAIT);
360 if (error)
361 goto fail3;
362
363 task->ct_callback = callback;
364 task->ct_cookie = cookie;
365
366 return task;
367
368 fail4: __unused
369 bus_dmamap_unload(sc->sc_dmat, task->ct_desc_map);
370 fail3: bus_dmamap_destroy(sc->sc_dmat, task->ct_desc_map);
371 fail2: bus_dmamem_unmap(sc->sc_dmat, task->ct_desc_kva,
372 sizeof(*task->ct_desc));
373 fail1: bus_dmamem_free(sc->sc_dmat, task->ct_desc_seg, task->ct_desc_nseg);
374 fail0: kmem_free(task, sizeof(*task));
375 return NULL;
376 }
377
378 static void
379 sun8i_crypto_task_put(struct sun8i_crypto_softc *sc,
380 struct sun8i_crypto_task *task)
381 {
382
383 bus_dmamap_unload(sc->sc_dmat, task->ct_desc_map);
384 bus_dmamap_destroy(sc->sc_dmat, task->ct_desc_map);
385 bus_dmamem_unmap(sc->sc_dmat, task->ct_desc_kva,
386 sizeof(*task->ct_desc));
387 bus_dmamem_free(sc->sc_dmat, task->ct_desc_seg, task->ct_desc_nseg);
388 kmem_free(task, sizeof(*task));
389 }
390
391 /*
392 * Task descriptor setup
393 *
394 * WARNING: Task descriptor fields are little-endian, not host-endian.
395 */
396
397 static void
398 sun8i_crypto_task_reset(struct sun8i_crypto_task *task)
399 {
400
401 memset(task->ct_desc, 0, sizeof(*task->ct_desc));
402 }
403
404 static void
405 sun8i_crypto_task_set_key(struct sun8i_crypto_task *task, bus_dmamap_t map)
406 {
407
408 KASSERT(map->dm_nsegs == 1);
409 task->ct_desc->td_keydesc = htole32(map->dm_segs[0].ds_addr);
410 }
411
412 static void __unused /* XXX opencrypto(9) */
413 sun8i_crypto_task_set_iv(struct sun8i_crypto_task *task, bus_dmamap_t map)
414 {
415
416 KASSERT(map->dm_nsegs == 1);
417 task->ct_desc->td_ivdesc = htole32(map->dm_segs[0].ds_addr);
418 }
419
420 static void __unused /* XXX opencrypto(9) */
421 sun8i_crypto_task_set_ctr(struct sun8i_crypto_task *task, bus_dmamap_t map)
422 {
423
424 KASSERT(map->dm_nsegs == 1);
425 task->ct_desc->td_ctrdesc = htole32(map->dm_segs[0].ds_addr);
426 }
427
428 static void
429 sun8i_crypto_task_set_input(struct sun8i_crypto_task *task, bus_dmamap_t map)
430 {
431
432 sun8i_crypto_task_scatter(task->ct_desc->td_src, map);
433 }
434
435 static void
436 sun8i_crypto_task_set_output(struct sun8i_crypto_task *task, bus_dmamap_t map)
437 {
438
439 sun8i_crypto_task_scatter(task->ct_desc->td_dst, map);
440 }
441
442 static void
443 sun8i_crypto_task_scatter(struct sun8i_crypto_adrlen *adrlen, bus_dmamap_t map)
444 {
445 uint32_t total __diagused = 0;
446 unsigned i;
447
448 KASSERT(map->dm_nsegs <= SUN8I_CRYPTO_MAXSEGS);
449 for (i = 0; i < map->dm_nsegs; i++) {
450 KASSERT((map->dm_segs[i].ds_addr % 4) == 0);
451 KASSERT(map->dm_segs[i].ds_addr <= UINT32_MAX);
452 KASSERT(map->dm_segs[i].ds_len <= UINT32_MAX - total);
453 adrlen[i].adr = htole32(map->dm_segs[i].ds_addr);
454 adrlen[i].len = htole32(map->dm_segs[i].ds_len/4);
455 total += map->dm_segs[i].ds_len;
456 }
457
458 /* Verify the remainder are zero. */
459 for (; i < SUN8I_CRYPTO_MAXSEGS; i++) {
460 KASSERT(adrlen[i].adr == 0);
461 KASSERT(adrlen[i].len == 0);
462 }
463
464 /* Verify the total size matches the DMA map. */
465 KASSERT(total == map->dm_mapsize);
466 }
467
468 /*
469 * Task submission
470 *
471 * WARNING: Task descriptor fields are little-endian, not host-endian.
472 */
473
474 static int
475 sun8i_crypto_submit_trng(struct sun8i_crypto_softc *sc,
476 struct sun8i_crypto_task *task, uint32_t datalen)
477 {
478 struct sun8i_crypto_taskdesc *desc = task->ct_desc;
479 uint32_t tdqc = 0;
480 uint32_t total __diagused;
481 unsigned i __diagused;
482
483 /* Data length must be a multiple of 4 because...reasons. */
484 KASSERT((datalen % 4) == 0);
485
486 /* All of the sources should be empty. */
487 for (total = 0, i = 0; i < SUN8I_CRYPTO_MAXSEGS; i++)
488 KASSERT(le32toh(task->ct_desc->td_src[i].len) == 0);
489
490 /* Verify the total output length -- should be datalen/4. */
491 for (total = 0, i = 0; i < SUN8I_CRYPTO_MAXSEGS; i++) {
492 uint32_t len = le32toh(task->ct_desc->td_dst[i].len);
493 KASSERT(len <= UINT32_MAX - total);
494 total += len;
495 }
496 KASSERT(total == datalen/4);
497
498 /* Verify the key, IV, and CTR are unset. */
499 KASSERT(desc->td_keydesc == 0);
500 KASSERT(desc->td_ivdesc == 0);
501 KASSERT(desc->td_ctrdesc == 0);
502
503 /* Set up the task descriptor queue control words. */
504 tdqc |= SUN8I_CRYPTO_TDQC_INTR_EN;
505 tdqc |= __SHIFTIN(SUN8I_CRYPTO_TDQC_METHOD_TRNG,
506 SUN8I_CRYPTO_TDQC_METHOD);
507 desc->td_tdqc = htole32(tdqc);
508 desc->td_tdqs = 0; /* no symmetric crypto */
509 desc->td_tdqa = 0; /* no asymmetric crypto */
510
511 /* Set the data length for the output. */
512 desc->td_datalen = htole32(datalen/4);
513
514 /* Submit! */
515 return sun8i_crypto_submit(sc, task);
516 }
517
518 static int
519 sun8i_crypto_submit_aesecb(struct sun8i_crypto_softc *sc,
520 struct sun8i_crypto_task *task,
521 uint32_t datalen, uint32_t keysize, uint32_t dir)
522 {
523 struct sun8i_crypto_taskdesc *desc = task->ct_desc;
524 uint32_t tdqc = 0, tdqs = 0;
525 uint32_t total __diagused;
526 unsigned i __diagused;
527
528 /*
529 * Data length must be a multiple of 4 because...reasons.
530 *
531 * WARNING: For `AES-CTS' (maybe that means AES-XTS?), datalen
532 * is in units of bytes, not units of words -- but everything
533 * _else_ is in units of words. This routine applies only to
534 * AES-ECB for the self-test.
535 */
536 KASSERT((datalen % 4) == 0);
537
538 /* Verify the total input length -- should be datalen/4. */
539 for (total = 0, i = 0; i < SUN8I_CRYPTO_MAXSEGS; i++) {
540 uint32_t len = le32toh(task->ct_desc->td_src[i].len);
541 KASSERT(len <= UINT32_MAX - total);
542 total += len;
543 }
544 KASSERT(total == datalen/4);
545
546 /* Verify the total output length -- should be datalen/4. */
547 for (total = 0, i = 0; i < SUN8I_CRYPTO_MAXSEGS; i++) {
548 uint32_t len = le32toh(task->ct_desc->td_dst[i].len);
549 KASSERT(len <= UINT32_MAX - total);
550 total += len;
551 }
552 KASSERT(total == datalen/4);
553
554 /* Set up the task descriptor queue control word. */
555 tdqc |= SUN8I_CRYPTO_TDQC_INTR_EN;
556 tdqc |= __SHIFTIN(SUN8I_CRYPTO_TDQC_METHOD_AES,
557 SUN8I_CRYPTO_TDQC_METHOD);
558 desc->td_tdqc = htole32(tdqc);
559
560 /* Set up the symmetric control word. */
561 tdqs |= __SHIFTIN(SUN8I_CRYPTO_TDQS_SKEY_SELECT_SS_KEYx,
562 SUN8I_CRYPTO_TDQS_SKEY_SELECT);
563 tdqs |= __SHIFTIN(SUN8I_CRYPTO_TDQS_OP_MODE_ECB,
564 SUN8I_CRYPTO_TDQS_OP_MODE);
565 tdqs |= __SHIFTIN(SUN8I_CRYPTO_TDQS_AES_KEYSIZE_128,
566 SUN8I_CRYPTO_TDQS_AES_KEYSIZE);
567 desc->td_tdqs = htole32(tdqs);
568
569 desc->td_tdqa = 0; /* no asymmetric crypto */
570
571 /* Set the data length for the output. */
572 desc->td_datalen = htole32(datalen/4);
573
574 /* Submit! */
575 return sun8i_crypto_submit(sc, task);
576 }
577
578 static int
579 sun8i_crypto_submit(struct sun8i_crypto_softc *sc,
580 struct sun8i_crypto_task *task)
581 {
582 unsigned i, retries = 0;
583 uint32_t icr;
584 int error = 0;
585
586 /* One at a time at the device registers, please. */
587 mutex_enter(&sc->sc_lock);
588
589 /* Find a channel. */
590 for (i = 0; i < SUN8I_CRYPTO_NCHAN; i++) {
591 if (sc->sc_chan[i].cc_task == NULL)
592 break;
593 }
594 if (i == SUN8I_CRYPTO_NCHAN) {
595 device_printf(sc->sc_dev, "no free channels\n");
596 error = ERESTART;
597 goto out;
598 }
599
600 /*
601 * Set the channel id. Caller is responsible for setting up
602 * all other parts of the descriptor.
603 */
604 task->ct_desc->td_cid = htole32(i);
605
606 /* Prepare to send the descriptor to the device by DMA. */
607 bus_dmamap_sync(sc->sc_dmat, task->ct_desc_map, 0,
608 sizeof(*task->ct_desc), BUS_DMASYNC_PREWRITE);
609
610 /* Confirm we're ready to go. */
611 if (sun8i_crypto_read(sc, SUN8I_CRYPTO_TLR) & SUN8I_CRYPTO_TLR_LOAD) {
612 device_printf(sc->sc_dev, "TLR not clear\n");
613 error = EIO;
614 goto out;
615 }
616
617 /* Enable interrupts for this channel. */
618 icr = sun8i_crypto_read(sc, SUN8I_CRYPTO_ICR);
619 icr |= __SHIFTIN(SUN8I_CRYPTO_ICR_INTR_EN_CHAN(i),
620 SUN8I_CRYPTO_ICR_INTR_EN);
621 sun8i_crypto_write(sc, SUN8I_CRYPTO_ICR, icr);
622
623 /* Set the task descriptor queue address. */
624 sun8i_crypto_write(sc, SUN8I_CRYPTO_TDQ,
625 task->ct_desc_map->dm_segs[0].ds_addr);
626
627 /* Notify the engine to load it, and wait for acknowledgement. */
628 sun8i_crypto_write(sc, SUN8I_CRYPTO_TLR, SUN8I_CRYPTO_TLR_LOAD);
629 while (sun8i_crypto_read(sc, SUN8I_CRYPTO_TLR) & SUN8I_CRYPTO_TLR_LOAD)
630 {
631 /*
632 * XXX Timeout pulled from arse. Is it even important
633 * to wait here?
634 */
635 if (++retries == 1000) {
636 device_printf(sc->sc_dev, "TLR didn't clear: %08x\n",
637 sun8i_crypto_read(sc, SUN8I_CRYPTO_TLR));
638 /*
639 * Hope it clears eventually; if not, we'll
640 * time out.
641 */
642 break;
643 }
644 DELAY(1);
645 }
646
647 /* Loaded up and ready to go. Start a timer ticking. */
648 sc->sc_chan[i].cc_task = task;
649 sc->sc_chan[i].cc_starttime = atomic_load_relaxed(&hardclock_ticks);
650 callout_schedule(&sc->sc_timeout, SUN8I_CRYPTO_TIMEOUT);
651
652 /* XXX Consider polling if cold to get entropy earlier. */
653
654 out: /* Done! */
655 mutex_exit(&sc->sc_lock);
656 return error;
657 }
658
659 static void
660 sun8i_crypto_timeout(void *cookie)
661 {
662 struct sun8i_crypto_softc *sc = cookie;
663 unsigned i;
664
665 mutex_enter(&sc->sc_lock);
666
667 /* Check whether there are any tasks pending. */
668 for (i = 0; i < SUN8I_CRYPTO_NCHAN; i++) {
669 if (sc->sc_chan[i].cc_task)
670 break;
671 }
672 if (i == SUN8I_CRYPTO_NCHAN)
673 /* None pending, so nothing to do. */
674 goto out;
675
676 /*
677 * Schedule the worker to check for timeouts, and schedule
678 * another timeout in case we need it.
679 */
680 sun8i_crypto_schedule_worker(sc);
681 callout_schedule(&sc->sc_timeout, SUN8I_CRYPTO_TIMEOUT);
682
683 out: mutex_exit(&sc->sc_lock);
684 }
685
686 static int
687 sun8i_crypto_intr(void *cookie)
688 {
689 struct sun8i_crypto_softc *sc = cookie;
690 uint32_t isr, esr;
691
692 mutex_enter(&sc->sc_lock);
693
694 /*
695 * Get and acknowledge the interrupts and error status.
696 *
697 * XXX Data sheet says the error status register is read-only,
698 * but then advises writing 1 to bit x1xx (keysram access error
699 * for AES, SUN8I_CRYPTO_ESR_KEYSRAMERR) to clear it. What do?
700 */
701 isr = sun8i_crypto_read(sc, SUN8I_CRYPTO_ISR);
702 esr = sun8i_crypto_read(sc, SUN8I_CRYPTO_ESR);
703 sun8i_crypto_write(sc, SUN8I_CRYPTO_ISR, isr);
704 sun8i_crypto_write(sc, SUN8I_CRYPTO_ISR, esr);
705
706 /* Start the worker if necessary. */
707 sun8i_crypto_schedule_worker(sc);
708
709 /* Tell the worker what to do. */
710 sc->sc_done |= __SHIFTOUT(isr, SUN8I_CRYPTO_ISR_DONE);
711 sc->sc_esr |= esr;
712
713 mutex_exit(&sc->sc_lock);
714
715 return __SHIFTOUT(isr, SUN8I_CRYPTO_ISR_DONE) != 0;
716 }
717
718 static void
719 sun8i_crypto_schedule_worker(struct sun8i_crypto_softc *sc)
720 {
721
722 KASSERT(mutex_owned(&sc->sc_lock));
723
724 /* Start the worker if necessary. */
725 if (!sc->sc_work_pending) {
726 workqueue_enqueue(sc->sc_wq, &sc->sc_work, NULL);
727 sc->sc_work_pending = true;
728 }
729 }
730
731 static void
732 sun8i_crypto_worker(struct work *wk, void *cookie)
733 {
734 struct sun8i_crypto_softc *sc = cookie;
735 uint32_t done, esr, esr_chan;
736 unsigned i, now;
737 int error;
738
739 /*
740 * Acquire the lock. Note: We will be releasing and
741 * reacquiring it throughout the loop.
742 */
743 mutex_enter(&sc->sc_lock);
744
745 /* Acknowledge the work. */
746 KASSERT(sc->sc_work_pending);
747 sc->sc_work_pending = false;
748
749 /*
750 * Claim the done mask and error status once; we will be
751 * releasing and reacquiring the lock for the callbacks, so
752 * they may change.
753 */
754 done = sc->sc_done;
755 esr = sc->sc_esr;
756 sc->sc_done = 0;
757 sc->sc_esr = 0;
758
759 /* Check the time to determine what's timed out. */
760 now = atomic_load_relaxed(&hardclock_ticks);
761
762 /* Process the channels. */
763 for (i = 0; i < SUN8I_CRYPTO_NCHAN; i++) {
764 if (!ISSET(done, SUN8I_CRYPTO_ISR_DONE_CHAN(i))) {
765 /* Check to see if we have a task that timed out. */
766 if ((sc->sc_chan[i].cc_task != NULL) &&
767 ((now - sc->sc_chan[i].cc_starttime) >=
768 SUN8I_CRYPTO_TIMEOUT))
769 sun8i_crypto_chan_done(sc, i, ETIMEDOUT);
770 continue;
771 }
772 esr_chan = __SHIFTOUT(esr, SUN8I_CRYPTO_ESR_CHAN(i));
773 if (esr_chan & SUN8I_CRYPTO_ESR_CHAN_ALGNOTSUP) {
774 device_printf(sc->sc_dev, "channel %u:"
775 " alg not supported\n", i);
776 error = ENODEV;
777 } else if (esr_chan & SUN8I_CRYPTO_ESR_CHAN_DATALENERR) {
778 device_printf(sc->sc_dev, "channel %u:"
779 " data length error\n", i);
780 error = EIO; /* XXX */
781 } else if (esr_chan & SUN8I_CRYPTO_ESR_CHAN_KEYSRAMERR) {
782 device_printf(sc->sc_dev, "channel %u:"
783 " key sram error\n", i);
784 error = EIO; /* XXX */
785 } else if (esr_chan != 0) {
786 error = EIO; /* generic I/O error */
787 } else {
788 error = 0;
789 }
790
791 /* May release the lock to invoke a callback. */
792 sun8i_crypto_chan_done(sc, i, error);
793 }
794
795 /* All one; release the lock one last time. */
796 mutex_exit(&sc->sc_lock);
797 }
798
799 static void
800 sun8i_crypto_chan_done(struct sun8i_crypto_softc *sc, unsigned i, int error)
801 {
802 struct sun8i_crypto_task *task;
803 uint32_t icr;
804
805 KASSERT(mutex_owned(&sc->sc_lock));
806
807 /* Claim the task if there is one; bail if not. */
808 if ((task = sc->sc_chan[i].cc_task) == NULL) {
809 device_printf(sc->sc_dev, "channel %u: no task but error=%d\n",
810 i, error);
811 return;
812 }
813 sc->sc_chan[i].cc_task = NULL;
814
815 /* Disable interrupts on this channel. */
816 icr = sun8i_crypto_read(sc, SUN8I_CRYPTO_ICR);
817 icr &= ~__SHIFTIN(SUN8I_CRYPTO_ICR_INTR_EN_CHAN(i),
818 SUN8I_CRYPTO_ICR_INTR_EN);
819 sun8i_crypto_write(sc, SUN8I_CRYPTO_ICR, icr);
820
821 /* Finished sending the descriptor to the device by DMA. */
822 bus_dmamap_sync(sc->sc_dmat, task->ct_desc_map, 0,
823 sizeof(*task->ct_desc), BUS_DMASYNC_POSTWRITE);
824
825 /* Temporarily release the lock to invoke the callback. */
826 mutex_exit(&sc->sc_lock);
827 (*task->ct_callback)(sc, task, task->ct_cookie, error);
828 mutex_enter(&sc->sc_lock);
829 }
830
831 /*
832 * DMA buffers
833 */
834
835 static int
836 sun8i_crypto_allocbuf(struct sun8i_crypto_softc *sc, size_t size,
837 struct sun8i_crypto_buf *buf)
838 {
839 int error;
840
841 /* Allocate a DMA-safe buffer. */
842 error = bus_dmamem_alloc(sc->sc_dmat, size, 0, 0, buf->cb_seg,
843 __arraycount(buf->cb_seg), &buf->cb_nsegs, BUS_DMA_WAITOK);
844 if (error)
845 goto fail0;
846
847 /* Map the buffer into kernel virtual address space. */
848 error = bus_dmamem_map(sc->sc_dmat, buf->cb_seg, buf->cb_nsegs,
849 size, &buf->cb_kva, BUS_DMA_WAITOK);
850 if (error)
851 goto fail1;
852
853 /* Create a DMA map for the buffer. */
854 error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
855 BUS_DMA_WAITOK, &buf->cb_map);
856 if (error)
857 goto fail2;
858
859 /* Load the buffer into the DMA map. */
860 error = bus_dmamap_load(sc->sc_dmat, buf->cb_map, buf->cb_kva, size,
861 NULL, BUS_DMA_WAITOK);
862 if (error)
863 goto fail3;
864
865 /* Success! */
866 return 0;
867
868 fail4: __unused
869 bus_dmamap_unload(sc->sc_dmat, buf->cb_map);
870 fail3: bus_dmamap_destroy(sc->sc_dmat, buf->cb_map);
871 fail2: bus_dmamem_unmap(sc->sc_dmat, buf->cb_kva, size);
872 fail1: bus_dmamem_free(sc->sc_dmat, buf->cb_seg, buf->cb_nsegs);
873 fail0: return error;
874 }
875
876 static void
877 sun8i_crypto_freebuf(struct sun8i_crypto_softc *sc, size_t size,
878 struct sun8i_crypto_buf *buf)
879 {
880
881 bus_dmamap_unload(sc->sc_dmat, buf->cb_map);
882 bus_dmamap_destroy(sc->sc_dmat, buf->cb_map);
883 bus_dmamem_unmap(sc->sc_dmat, buf->cb_kva, size);
884 bus_dmamem_free(sc->sc_dmat, buf->cb_seg, buf->cb_nsegs);
885 }
886
887 /*
888 * Crypto Engine - TRNG
889 */
890
891 static void
892 sun8i_crypto_rng_attach(struct sun8i_crypto_softc *sc)
893 {
894 device_t self = sc->sc_dev;
895 struct sun8i_crypto_rng *rng = &sc->sc_rng;
896 int error;
897
898 /* Preallocate a buffer to reuse. */
899 error = sun8i_crypto_allocbuf(sc, SUN8I_CRYPTO_RNGBYTES, &rng->cr_buf);
900 if (error)
901 goto fail0;
902
903 /* Create a task to reuse. */
904 rng->cr_task = sun8i_crypto_task_get(sc, sun8i_crypto_rng_done, rng);
905 if (rng->cr_task == NULL)
906 goto fail1;
907
908 /*
909 * Attach the rndsource. This is _not_ marked as RND_TYPE_RNG
910 * because the output is not uniformly distributed. The bits
911 * are heavily weighted toward 0 or 1, at different times, and
912 * I haven't scienced a satisfactory story out of it yet.
913 */
914 rndsource_setcb(&rng->cr_rndsource, sun8i_crypto_rng_get, sc);
915 rnd_attach_source(&rng->cr_rndsource, device_xname(self),
916 RND_TYPE_UNKNOWN,
917 RND_FLAG_COLLECT_VALUE|RND_FLAG_ESTIMATE_VALUE|RND_FLAG_HASCB);
918
919 /* Success! */
920 return;
921
922 fail2: __unused
923 sun8i_crypto_task_put(sc, rng->cr_task);
924 fail1: sun8i_crypto_freebuf(sc, SUN8I_CRYPTO_RNGBYTES, &rng->cr_buf);
925 fail0: aprint_error_dev(self, "failed to set up RNG, error=%d\n", error);
926 }
927
928 static void
929 sun8i_crypto_rng_get(size_t nbytes, void *cookie)
930 {
931 struct sun8i_crypto_softc *sc = cookie;
932 struct sun8i_crypto_rng *rng = &sc->sc_rng;
933 bool pending;
934 int error;
935
936 /*
937 * Test and set the RNG-pending flag. If it's already in
938 * progress, nothing to do here.
939 */
940 mutex_enter(&sc->sc_lock);
941 pending = rng->cr_pending;
942 rng->cr_pending = true;
943 mutex_exit(&sc->sc_lock);
944 if (pending)
945 return;
946
947 /* Prepare for a DMA read into the buffer. */
948 bus_dmamap_sync(sc->sc_dmat, rng->cr_buf.cb_map,
949 0, SUN8I_CRYPTO_RNGBYTES, BUS_DMASYNC_PREREAD);
950
951 /* Set the task up for TRNG to our buffer. */
952 sun8i_crypto_task_reset(rng->cr_task);
953 sun8i_crypto_task_set_output(rng->cr_task, rng->cr_buf.cb_map);
954
955 /* Submit the TRNG task. */
956 error = sun8i_crypto_submit_trng(sc, rng->cr_task,
957 SUN8I_CRYPTO_RNGBYTES);
958 if (error)
959 goto fail;
960
961 /* All done! */
962 return;
963
964 fail: mutex_enter(&sc->sc_lock);
965 rng->cr_pending = false;
966 mutex_exit(&sc->sc_lock);
967 }
968
969 static void
970 sun8i_crypto_rng_done(struct sun8i_crypto_softc *sc,
971 struct sun8i_crypto_task *task, void *cookie, int error)
972 {
973 struct sun8i_crypto_rng *rng = cookie;
974 uint8_t *buf = rng->cr_buf.cb_kva;
975 uint32_t entropybits;
976
977 KASSERT(rng == &sc->sc_rng);
978
979 /* Finished the DMA read into the buffer. */
980 bus_dmamap_sync(sc->sc_dmat, rng->cr_buf.cb_map,
981 0, SUN8I_CRYPTO_RNGBYTES, BUS_DMASYNC_POSTREAD);
982
983 /* If anything went wrong, forget about it. */
984 if (error)
985 goto out;
986
987 /*
988 * This TRNG has quite low entropy at best. But if it fails a
989 * repeated output test, then assume it's busted.
990 */
991 CTASSERT((SUN8I_CRYPTO_RNGBYTES % SUN8I_CRYPTO_RNGENTROPY) == 0);
992 entropybits = NBBY * (SUN8I_CRYPTO_RNGBYTES/SUN8I_CRYPTO_RNGENTROPY);
993 if (consttime_memequal(buf, buf + SUN8I_CRYPTO_RNGBYTES/2,
994 SUN8I_CRYPTO_RNGBYTES/2)) {
995 device_printf(sc->sc_dev, "failed repeated output test\n");
996 entropybits = 0;
997 }
998
999 /* Success! Enter and erase the data. */
1000 rnd_add_data(&rng->cr_rndsource, buf, SUN8I_CRYPTO_RNGBYTES,
1001 entropybits);
1002 explicit_memset(buf, 0, SUN8I_CRYPTO_RNGBYTES);
1003
1004 out: /* Done -- clear the RNG-pending flag. */
1005 mutex_enter(&sc->sc_lock);
1006 rng->cr_pending = false;
1007 mutex_exit(&sc->sc_lock);
1008 }
1009
1010 /*
1011 * Self-test
1012 */
1013
1014 static uint8_t selftest_input[16];
1015 static uint8_t selftest_key[16];
1016 static uint8_t selftest_output[16] = {
1017 0x66,0xe9,0x4b,0xd4,0xef,0x8a,0x2c,0x3b,
1018 0x88,0x4c,0xfa,0x59,0xca,0x34,0x2b,0x2e,
1019 };
1020
1021 static void
1022 sun8i_crypto_selftest(device_t self)
1023 {
1024 const size_t datalen = sizeof selftest_input;
1025 struct sun8i_crypto_softc *sc = device_private(self);
1026 struct sun8i_crypto_selftest *selftest = &sc->sc_selftest;
1027 int error;
1028
1029 CTASSERT(sizeof selftest_input == sizeof selftest_output);
1030
1031 /* Allocate an input buffer. */
1032 error = sun8i_crypto_allocbuf(sc, sizeof selftest_input,
1033 &selftest->cs_in);
1034 if (error)
1035 goto fail0;
1036
1037 /* Allocate a key buffer. */
1038 error = sun8i_crypto_allocbuf(sc, sizeof selftest_key,
1039 &selftest->cs_key);
1040 if (error)
1041 goto fail1;
1042
1043 /* Allocate an output buffer. */
1044 error = sun8i_crypto_allocbuf(sc, sizeof selftest_output,
1045 &selftest->cs_out);
1046 if (error)
1047 goto fail2;
1048
1049 /* Allocate a task descriptor. */
1050 selftest->cs_task = sun8i_crypto_task_get(sc,
1051 sun8i_crypto_selftest_done, selftest);
1052 if (selftest->cs_task == NULL)
1053 goto fail3;
1054
1055 /* Copy the input and key into their buffers. */
1056 memcpy(selftest->cs_in.cb_kva, selftest_input, sizeof selftest_input);
1057 memcpy(selftest->cs_key.cb_kva, selftest_key, sizeof selftest_key);
1058
1059 /* Prepare for a DMA write from the input and key buffers. */
1060 bus_dmamap_sync(sc->sc_dmat, selftest->cs_in.cb_map, 0,
1061 sizeof selftest_input, BUS_DMASYNC_PREWRITE);
1062 bus_dmamap_sync(sc->sc_dmat, selftest->cs_key.cb_map, 0,
1063 sizeof selftest_key, BUS_DMASYNC_PREWRITE);
1064
1065 /* Prepare for a DMA read into the output buffer. */
1066 bus_dmamap_sync(sc->sc_dmat, selftest->cs_out.cb_map, 0,
1067 sizeof selftest_output, BUS_DMASYNC_PREREAD);
1068
1069 /* Set up the task descriptor. */
1070 sun8i_crypto_task_reset(selftest->cs_task);
1071 sun8i_crypto_task_set_key(selftest->cs_task, selftest->cs_key.cb_map);
1072 sun8i_crypto_task_set_input(selftest->cs_task, selftest->cs_in.cb_map);
1073 sun8i_crypto_task_set_output(selftest->cs_task,
1074 selftest->cs_out.cb_map);
1075
1076 /* Submit the AES-128 ECB task. */
1077 error = sun8i_crypto_submit_aesecb(sc, selftest->cs_task, datalen,
1078 SUN8I_CRYPTO_TDQS_AES_KEYSIZE_128, SUN8I_CRYPTO_TDQC_OP_DIR_ENC);
1079 if (error)
1080 goto fail4;
1081
1082 device_printf(sc->sc_dev, "AES-128 self-test initiated\n");
1083
1084 /* Success! */
1085 return;
1086
1087 fail4: sun8i_crypto_task_put(sc, selftest->cs_task);
1088 fail3: sun8i_crypto_freebuf(sc, sizeof selftest_output, &selftest->cs_out);
1089 fail2: sun8i_crypto_freebuf(sc, sizeof selftest_key, &selftest->cs_key);
1090 fail1: sun8i_crypto_freebuf(sc, sizeof selftest_input, &selftest->cs_in);
1091 fail0: aprint_error_dev(self, "failed to run self-test, error=%d\n", error);
1092 }
1093
1094 static void
1095 sun8i_crypto_selftest_done(struct sun8i_crypto_softc *sc,
1096 struct sun8i_crypto_task *task, void *cookie, int error)
1097 {
1098 struct sun8i_crypto_selftest *selftest = cookie;
1099 unsigned i;
1100 bool ok = true;
1101
1102 KASSERT(selftest == &sc->sc_selftest);
1103
1104 bus_dmamap_sync(sc->sc_dmat, selftest->cs_out.cb_map, 0,
1105 sizeof selftest_output, BUS_DMASYNC_POSTREAD);
1106 bus_dmamap_sync(sc->sc_dmat, selftest->cs_in.cb_map, 0,
1107 sizeof selftest_input, BUS_DMASYNC_POSTWRITE);
1108
1109 if (error) {
1110 device_printf(sc->sc_dev, "self-test error=%d\n", error);
1111 goto out;
1112 }
1113
1114 if (memcmp(selftest_input, selftest->cs_in.cb_kva,
1115 sizeof selftest_input) != 0) {
1116 device_printf(sc->sc_dev, "self-test: input clobbered\n");
1117 printf("expected: ");
1118 for (i = 0; i < sizeof selftest_input; i++)
1119 printf("%02hhx", selftest_input[i]);
1120 printf("\n");
1121 printf("actual: ");
1122 for (i = 0; i < sizeof selftest_input; i++)
1123 printf("%02hhx",
1124 ((const uint8_t *)selftest->cs_in.cb_kva)[i]);
1125 printf("\n");
1126 ok = false;
1127 }
1128
1129 if (memcmp(selftest_key, selftest->cs_key.cb_kva,
1130 sizeof selftest_key) != 0) {
1131 device_printf(sc->sc_dev, "self-test: key clobbered\n");
1132 printf("expected: ");
1133 for (i = 0; i < sizeof selftest_key; i++)
1134 printf("%02hhx", selftest_key[i]);
1135 printf("\n");
1136 printf("actual: ");
1137 for (i = 0; i < sizeof selftest_key; i++)
1138 printf("%02hhx",
1139 ((const uint8_t *)selftest->cs_key.cb_kva)[i]);
1140 printf("\n");
1141 ok = false;
1142 }
1143
1144 if (memcmp(selftest_output, selftest->cs_out.cb_kva,
1145 sizeof selftest_output) != 0) {
1146 device_printf(sc->sc_dev, "self-test: output mismatch\n");
1147 printf("expected: ");
1148 for (i = 0; i < sizeof selftest_output; i++)
1149 printf("%02hhx", selftest_output[i]);
1150 printf("\n");
1151 printf("actual: ");
1152 for (i = 0; i < sizeof selftest_output; i++)
1153 printf("%02hhx",
1154 ((const uint8_t *)selftest->cs_out.cb_kva)[i]);
1155 printf("\n");
1156 ok = false;
1157 }
1158
1159 /* XXX Disable the RNG and other stuff if this fails... */
1160 if (ok)
1161 device_printf(sc->sc_dev, "AES-128 self-test passed\n");
1162
1163 out: sun8i_crypto_task_put(sc, task);
1164 sun8i_crypto_freebuf(sc, sizeof selftest_output, &selftest->cs_out);
1165 sun8i_crypto_freebuf(sc, sizeof selftest_key, &selftest->cs_key);
1166 sun8i_crypto_freebuf(sc, sizeof selftest_input, &selftest->cs_in);
1167 }
1168
1169 /*
1170 * Sysctl for testing
1171 */
1172
1173 struct sun8i_crypto_userreq {
1174 kmutex_t cu_lock;
1175 kcondvar_t cu_cv;
1176 size_t cu_size;
1177 struct sun8i_crypto_buf cu_buf;
1178 struct sun8i_crypto_task *cu_task;
1179 int cu_error;
1180 bool cu_done;
1181 bool cu_cancel;
1182 };
1183
1184 static void
1185 sun8i_crypto_sysctl_attach(struct sun8i_crypto_softc *sc)
1186 {
1187 struct sun8i_crypto_sysctl *cy = &sc->sc_sysctl;
1188 int error;
1189
1190 error = sysctl_createv(&cy->cy_log, 0, NULL, &cy->cy_root_node,
1191 CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(sc->sc_dev),
1192 SYSCTL_DESCR("sun8i crypto engine knobs"),
1193 NULL, 0, NULL, 0,
1194 CTL_HW, CTL_CREATE, CTL_EOL);
1195 if (error) {
1196 aprint_error_dev(sc->sc_dev,
1197 "failed to set up sysctl hw.%s: %d\n",
1198 device_xname(sc->sc_dev), error);
1199 return;
1200 }
1201
1202 sysctl_createv(&cy->cy_log, 0, &cy->cy_root_node, NULL,
1203 CTLFLAG_PERMANENT|CTLFLAG_READONLY|CTLFLAG_PRIVATE, CTLTYPE_STRUCT,
1204 "rng", SYSCTL_DESCR("Read up to 1024 bytes out of the TRNG"),
1205 &sun8i_crypto_sysctl_rng, 0, sc, 0, CTL_CREATE, CTL_EOL);
1206 if (error) {
1207 aprint_error_dev(sc->sc_dev,
1208 "failed to set up sysctl hw.%s.rng: %d\n",
1209 device_xname(sc->sc_dev), error);
1210 return;
1211 }
1212 }
1213
1214 static int
1215 sun8i_crypto_sysctl_rng(SYSCTLFN_ARGS)
1216 {
1217 struct sysctlnode node = *rnode;
1218 struct sun8i_crypto_softc *sc = node.sysctl_data;
1219 struct sun8i_crypto_userreq *req;
1220 size_t size;
1221 int error;
1222
1223 /* If oldp == NULL, the caller wants to learn the size. */
1224 if (oldp == NULL) {
1225 *oldlenp = 1024;
1226 return 0;
1227 }
1228
1229 /* Verify the output buffer size is reasonable. */
1230 size = *oldlenp;
1231 if (size > 1024) /* size_t, so never negative */
1232 return E2BIG;
1233 if (size == 0)
1234 return 0; /* nothing to do */
1235
1236 /* Allocate a request context. */
1237 req = kmem_alloc(sizeof(*req), KM_NOSLEEP);
1238 if (req == NULL)
1239 return ENOMEM;
1240
1241 /* Initialize the request context. */
1242 mutex_init(&req->cu_lock, MUTEX_DEFAULT, IPL_NONE);
1243 cv_init(&req->cu_cv, "sun8isy");
1244 req->cu_size = size;
1245 req->cu_error = EIO;
1246 req->cu_done = false;
1247 req->cu_cancel = false;
1248
1249 /* Allocate a buffer for the RNG output. */
1250 error = sun8i_crypto_allocbuf(sc, size, &req->cu_buf);
1251 if (error)
1252 goto out0;
1253
1254 /* Allocate a task. */
1255 req->cu_task = sun8i_crypto_task_get(sc, sun8i_crypto_sysctl_rng_done,
1256 req);
1257 if (req->cu_task == NULL)
1258 goto out1;
1259
1260 /* Prepare for a DMA read into the buffer. */
1261 bus_dmamap_sync(sc->sc_dmat, req->cu_buf.cb_map, 0, size,
1262 BUS_DMASYNC_PREREAD);
1263
1264 /* Set the task up for TRNG to our buffer. */
1265 sun8i_crypto_task_reset(req->cu_task);
1266 sun8i_crypto_task_set_output(req->cu_task, req->cu_buf.cb_map);
1267
1268 /* Submit the TRNG task. */
1269 error = sun8i_crypto_submit_trng(sc, req->cu_task, size);
1270 if (error)
1271 goto out2;
1272
1273 /* Wait for the request to complete. */
1274 mutex_enter(&req->cu_lock);
1275 while (!req->cu_done) {
1276 error = cv_wait_sig(&req->cu_cv, &req->cu_lock);
1277 if (error) {
1278 /*
1279 * Never mind -- notify the callback that it
1280 * has to clean up after itself.
1281 */
1282 req->cu_cancel = true;
1283 break;
1284 }
1285 }
1286 mutex_exit(&req->cu_lock);
1287
1288 /*
1289 * Return early on error from cv_wait_sig, which means
1290 * interruption; the callback will clean up instead.
1291 */
1292 if (error)
1293 return error;
1294
1295 /* Check for error from the device. */
1296 error = req->cu_error;
1297 if (error)
1298 goto out2;
1299
1300 /* Finished the DMA read into the buffer. */
1301 bus_dmamap_sync(sc->sc_dmat, req->cu_buf.cb_map, 0, req->cu_size,
1302 BUS_DMASYNC_POSTREAD);
1303
1304 /* Copy out the data. */
1305 node.sysctl_data = req->cu_buf.cb_kva;
1306 node.sysctl_size = size;
1307 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1308
1309 /* Clear the buffer. */
1310 explicit_memset(req->cu_buf.cb_kva, 0, size);
1311
1312 out2: sun8i_crypto_task_put(sc, req->cu_task);
1313 out1: sun8i_crypto_freebuf(sc, req->cu_size, &req->cu_buf);
1314 out0: cv_destroy(&req->cu_cv);
1315 mutex_destroy(&req->cu_lock);
1316 return error;
1317 }
1318
1319 static void
1320 sun8i_crypto_sysctl_rng_done(struct sun8i_crypto_softc *sc,
1321 struct sun8i_crypto_task *task, void *cookie, int error)
1322 {
1323 struct sun8i_crypto_userreq *req = cookie;
1324 bool cancel;
1325
1326 /*
1327 * Notify the waiting thread of the error, and find out whether
1328 * that thread cancelled.
1329 */
1330 mutex_enter(&req->cu_lock);
1331 cancel = req->cu_cancel;
1332 req->cu_error = error;
1333 req->cu_done = true;
1334 cv_broadcast(&req->cu_cv);
1335 mutex_exit(&req->cu_lock);
1336
1337 /*
1338 * If it wasn't cancelled, we're done -- the main thread will
1339 * clean up after itself.
1340 */
1341 if (!cancel)
1342 return;
1343
1344 /* Clean up. */
1345 sun8i_crypto_task_put(sc, req->cu_task);
1346 sun8i_crypto_freebuf(sc, req->cu_size, &req->cu_buf);
1347 cv_destroy(&req->cu_cv);
1348 mutex_destroy(&req->cu_lock);
1349 }
1350