cgd.c revision 1.116.10.4 1 /* $NetBSD: cgd.c,v 1.116.10.4 2021/12/14 19:05:11 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland C. Dowdeswell.
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 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.116.10.4 2021/12/14 19:05:11 martin Exp $");
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/proc.h>
39 #include <sys/errno.h>
40 #include <sys/buf.h>
41 #include <sys/bufq.h>
42 #include <sys/kmem.h>
43 #include <sys/module.h>
44 #include <sys/pool.h>
45 #include <sys/ioctl.h>
46 #include <sys/device.h>
47 #include <sys/disk.h>
48 #include <sys/disklabel.h>
49 #include <sys/fcntl.h>
50 #include <sys/namei.h> /* for pathbuf */
51 #include <sys/vnode.h>
52 #include <sys/conf.h>
53 #include <sys/syslog.h>
54 #include <sys/workqueue.h>
55 #include <sys/cpu.h>
56
57 #include <dev/dkvar.h>
58 #include <dev/cgdvar.h>
59
60 #include <miscfs/specfs/specdev.h> /* for v_rdev */
61
62 #include "ioconf.h"
63
64 struct selftest_params {
65 const char *alg;
66 int blocksize; /* number of bytes */
67 int secsize;
68 daddr_t blkno;
69 int keylen; /* number of bits */
70 int txtlen; /* number of bytes */
71 const uint8_t *key;
72 const uint8_t *ptxt;
73 const uint8_t *ctxt;
74 };
75
76 /* Entry Point Functions */
77
78 static dev_type_open(cgdopen);
79 static dev_type_close(cgdclose);
80 static dev_type_read(cgdread);
81 static dev_type_write(cgdwrite);
82 static dev_type_ioctl(cgdioctl);
83 static dev_type_strategy(cgdstrategy);
84 static dev_type_dump(cgddump);
85 static dev_type_size(cgdsize);
86
87 const struct bdevsw cgd_bdevsw = {
88 .d_open = cgdopen,
89 .d_close = cgdclose,
90 .d_strategy = cgdstrategy,
91 .d_ioctl = cgdioctl,
92 .d_dump = cgddump,
93 .d_psize = cgdsize,
94 .d_discard = nodiscard,
95 .d_flag = D_DISK | D_MPSAFE
96 };
97
98 const struct cdevsw cgd_cdevsw = {
99 .d_open = cgdopen,
100 .d_close = cgdclose,
101 .d_read = cgdread,
102 .d_write = cgdwrite,
103 .d_ioctl = cgdioctl,
104 .d_stop = nostop,
105 .d_tty = notty,
106 .d_poll = nopoll,
107 .d_mmap = nommap,
108 .d_kqfilter = nokqfilter,
109 .d_discard = nodiscard,
110 .d_flag = D_DISK | D_MPSAFE
111 };
112
113 /*
114 * Vector 5 from IEEE 1619/D16 truncated to 64 bytes, blkno 1.
115 */
116 static const uint8_t selftest_aes_xts_256_ptxt[64] = {
117 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
118 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
119 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
120 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
121 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
122 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
123 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
124 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
125 };
126
127 static const uint8_t selftest_aes_xts_256_ctxt[512] = {
128 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe,
129 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f,
130 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60,
131 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5,
132 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d,
133 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce,
134 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b,
135 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb,
136 };
137
138 static const uint8_t selftest_aes_xts_256_key[33] = {
139 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
140 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
141 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
142 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
143 0
144 };
145
146 /*
147 * Vector 11 from IEEE 1619/D16 truncated to 64 bytes, blkno 0xffff.
148 */
149 static const uint8_t selftest_aes_xts_512_ptxt[64] = {
150 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
151 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
152 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
153 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
154 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
155 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
156 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
157 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
158 };
159
160 static const uint8_t selftest_aes_xts_512_ctxt[64] = {
161 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6,
162 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50,
163 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02,
164 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
165 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24,
166 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4,
167 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2,
168 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
169 };
170
171 static const uint8_t selftest_aes_xts_512_key[65] = {
172 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
173 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
174 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
175 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
176 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
177 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
178 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37,
179 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
180 0
181 };
182
183 const struct selftest_params selftests[] = {
184 {
185 .alg = "aes-xts",
186 .blocksize = 16,
187 .secsize = 512,
188 .blkno = 1,
189 .keylen = 256,
190 .txtlen = sizeof(selftest_aes_xts_256_ptxt),
191 .key = selftest_aes_xts_256_key,
192 .ptxt = selftest_aes_xts_256_ptxt,
193 .ctxt = selftest_aes_xts_256_ctxt
194 },
195 {
196 .alg = "aes-xts",
197 .blocksize = 16,
198 .secsize = 512,
199 .blkno = 0xffff,
200 .keylen = 512,
201 .txtlen = sizeof(selftest_aes_xts_512_ptxt),
202 .key = selftest_aes_xts_512_key,
203 .ptxt = selftest_aes_xts_512_ptxt,
204 .ctxt = selftest_aes_xts_512_ctxt
205 }
206 };
207
208 static int cgd_match(device_t, cfdata_t, void *);
209 static void cgd_attach(device_t, device_t, void *);
210 static int cgd_detach(device_t, int);
211 static struct cgd_softc *cgd_spawn(int);
212 static struct cgd_worker *cgd_create_one_worker(void);
213 static void cgd_destroy_one_worker(struct cgd_worker *);
214 static struct cgd_worker *cgd_create_worker(void);
215 static void cgd_destroy_worker(struct cgd_worker *);
216 static int cgd_destroy(device_t);
217
218 /* Internal Functions */
219
220 static int cgd_diskstart(device_t, struct buf *);
221 static void cgd_diskstart2(struct cgd_softc *, struct cgd_xfer *);
222 static void cgdiodone(struct buf *);
223 static void cgd_iodone2(struct cgd_softc *, struct cgd_xfer *);
224 static void cgd_enqueue(struct cgd_softc *, struct cgd_xfer *);
225 static void cgd_process(struct work *, void *);
226 static int cgd_dumpblocks(device_t, void *, daddr_t, int);
227
228 static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
229 static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
230 static int cgd_ioctl_get(dev_t, void *, struct lwp *);
231 static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
232 struct lwp *);
233 static void cgd_cipher(struct cgd_softc *, void *, void *,
234 size_t, daddr_t, size_t, int);
235
236 static struct dkdriver cgddkdriver = {
237 .d_minphys = minphys,
238 .d_open = cgdopen,
239 .d_close = cgdclose,
240 .d_strategy = cgdstrategy,
241 .d_iosize = NULL,
242 .d_diskstart = cgd_diskstart,
243 .d_dumpblocks = cgd_dumpblocks,
244 .d_lastclose = NULL
245 };
246
247 CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
248 cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
249
250 /* DIAGNOSTIC and DEBUG definitions */
251
252 #if defined(CGDDEBUG) && !defined(DEBUG)
253 #define DEBUG
254 #endif
255
256 #ifdef DEBUG
257 int cgddebug = 0;
258
259 #define CGDB_FOLLOW 0x1
260 #define CGDB_IO 0x2
261 #define CGDB_CRYPTO 0x4
262
263 #define IFDEBUG(x,y) if (cgddebug & (x)) y
264 #define DPRINTF(x,y) IFDEBUG(x, printf y)
265 #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
266
267 static void hexprint(const char *, void *, int);
268
269 #else
270 #define IFDEBUG(x,y)
271 #define DPRINTF(x,y)
272 #define DPRINTF_FOLLOW(y)
273 #endif
274
275 #ifdef DIAGNOSTIC
276 #define DIAGPANIC(x) panic x
277 #define DIAGCONDPANIC(x,y) if (x) panic y
278 #else
279 #define DIAGPANIC(x)
280 #define DIAGCONDPANIC(x,y)
281 #endif
282
283 /* Global variables */
284
285 static kmutex_t cgd_spawning_mtx;
286 static kcondvar_t cgd_spawning_cv;
287 static bool cgd_spawning;
288 static struct cgd_worker *cgd_worker;
289 static u_int cgd_refcnt; /* number of users of cgd_worker */
290
291 /* Utility Functions */
292
293 #define CGDUNIT(x) DISKUNIT(x)
294
295 /* The code */
296
297 static int
298 cgd_lock(bool intr)
299 {
300 int error = 0;
301
302 mutex_enter(&cgd_spawning_mtx);
303 while (cgd_spawning) {
304 if (intr)
305 error = cv_wait_sig(&cgd_spawning_cv, &cgd_spawning_mtx);
306 else
307 cv_wait(&cgd_spawning_cv, &cgd_spawning_mtx);
308 }
309 if (error == 0)
310 cgd_spawning = true;
311 mutex_exit(&cgd_spawning_mtx);
312 return error;
313 }
314
315 static void
316 cgd_unlock(void)
317 {
318 mutex_enter(&cgd_spawning_mtx);
319 cgd_spawning = false;
320 cv_broadcast(&cgd_spawning_cv);
321 mutex_exit(&cgd_spawning_mtx);
322 }
323
324 static struct cgd_softc *
325 getcgd_softc(dev_t dev)
326 {
327 return device_lookup_private(&cgd_cd, CGDUNIT(dev));
328 }
329
330 static int
331 cgd_match(device_t self, cfdata_t cfdata, void *aux)
332 {
333
334 return 1;
335 }
336
337 static void
338 cgd_attach(device_t parent, device_t self, void *aux)
339 {
340 struct cgd_softc *sc = device_private(self);
341
342 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
343 cv_init(&sc->sc_cv, "cgdcv");
344 dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
345 disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
346
347 if (!pmf_device_register(self, NULL, NULL))
348 aprint_error_dev(self,
349 "unable to register power management hooks\n");
350 }
351
352
353 static int
354 cgd_detach(device_t self, int flags)
355 {
356 int ret;
357 const int pmask = 1 << RAW_PART;
358 struct cgd_softc *sc = device_private(self);
359 struct dk_softc *dksc = &sc->sc_dksc;
360
361 if (DK_BUSY(dksc, pmask))
362 return EBUSY;
363
364 if (DK_ATTACHED(dksc) &&
365 (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
366 return ret;
367
368 disk_destroy(&dksc->sc_dkdev);
369 cv_destroy(&sc->sc_cv);
370 mutex_destroy(&sc->sc_lock);
371
372 return 0;
373 }
374
375 void
376 cgdattach(int num)
377 {
378 #ifndef _MODULE
379 int error;
380
381 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE);
382 cv_init(&cgd_spawning_cv, "cgspwn");
383
384 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
385 if (error != 0)
386 aprint_error("%s: unable to register cfattach\n",
387 cgd_cd.cd_name);
388 #endif
389 }
390
391 static struct cgd_softc *
392 cgd_spawn(int unit)
393 {
394 cfdata_t cf;
395 struct cgd_worker *cw;
396 struct cgd_softc *sc;
397
398 cf = kmem_alloc(sizeof(*cf), KM_SLEEP);
399 cf->cf_name = cgd_cd.cd_name;
400 cf->cf_atname = cgd_cd.cd_name;
401 cf->cf_unit = unit;
402 cf->cf_fstate = FSTATE_STAR;
403
404 cw = cgd_create_one_worker();
405 if (cw == NULL) {
406 kmem_free(cf, sizeof(*cf));
407 return NULL;
408 }
409
410 sc = device_private(config_attach_pseudo(cf));
411 if (sc == NULL) {
412 cgd_destroy_one_worker(cw);
413 return NULL;
414 }
415
416 sc->sc_worker = cw;
417
418 return sc;
419 }
420
421 static int
422 cgd_destroy(device_t dev)
423 {
424 struct cgd_softc *sc = device_private(dev);
425 struct cgd_worker *cw = sc->sc_worker;
426 cfdata_t cf;
427 int error;
428
429 cf = device_cfdata(dev);
430 error = config_detach(dev, DETACH_QUIET);
431 if (error)
432 return error;
433
434 cgd_destroy_one_worker(cw);
435
436 kmem_free(cf, sizeof(*cf));
437 return 0;
438 }
439
440 static void
441 cgd_busy(struct cgd_softc *sc)
442 {
443
444 mutex_enter(&sc->sc_lock);
445 while (sc->sc_busy)
446 cv_wait(&sc->sc_cv, &sc->sc_lock);
447 sc->sc_busy = true;
448 mutex_exit(&sc->sc_lock);
449 }
450
451 static void
452 cgd_unbusy(struct cgd_softc *sc)
453 {
454
455 mutex_enter(&sc->sc_lock);
456 sc->sc_busy = false;
457 cv_broadcast(&sc->sc_cv);
458 mutex_exit(&sc->sc_lock);
459 }
460
461 static struct cgd_worker *
462 cgd_create_one_worker(void)
463 {
464 KASSERT(cgd_spawning);
465
466 if (cgd_refcnt++ == 0) {
467 KASSERT(cgd_worker == NULL);
468 cgd_worker = cgd_create_worker();
469 }
470
471 KASSERT(cgd_worker != NULL);
472 return cgd_worker;
473 }
474
475 static void
476 cgd_destroy_one_worker(struct cgd_worker *cw)
477 {
478 KASSERT(cgd_spawning);
479 KASSERT(cw == cgd_worker);
480
481 if (--cgd_refcnt == 0) {
482 cgd_destroy_worker(cgd_worker);
483 cgd_worker = NULL;
484 }
485 }
486
487 static struct cgd_worker *
488 cgd_create_worker(void)
489 {
490 struct cgd_worker *cw;
491 struct workqueue *wq;
492 struct pool *cp;
493 int error;
494
495 cw = kmem_alloc(sizeof(struct cgd_worker), KM_SLEEP);
496 cp = kmem_alloc(sizeof(struct pool), KM_SLEEP);
497
498 error = workqueue_create(&wq, "cgd", cgd_process, NULL,
499 PRI_BIO, IPL_BIO, WQ_MPSAFE | WQ_PERCPU);
500 if (error) {
501 kmem_free(cp, sizeof(struct pool));
502 kmem_free(cw, sizeof(struct cgd_worker));
503 return NULL;
504 }
505
506 cw->cw_cpool = cp;
507 cw->cw_wq = wq;
508 pool_init(cw->cw_cpool, sizeof(struct cgd_xfer), 0,
509 0, 0, "cgdcpl", NULL, IPL_BIO);
510
511 mutex_init(&cw->cw_lock, MUTEX_DEFAULT, IPL_BIO);
512
513 return cw;
514 }
515
516 static void
517 cgd_destroy_worker(struct cgd_worker *cw)
518 {
519
520 /*
521 * Wait for all worker threads to complete before destroying
522 * the rest of the cgd_worker.
523 */
524 if (cw->cw_wq)
525 workqueue_destroy(cw->cw_wq);
526
527 mutex_destroy(&cw->cw_lock);
528
529 if (cw->cw_cpool) {
530 pool_destroy(cw->cw_cpool);
531 kmem_free(cw->cw_cpool, sizeof(struct pool));
532 }
533
534 kmem_free(cw, sizeof(struct cgd_worker));
535 }
536
537 static int
538 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
539 {
540 struct cgd_softc *sc;
541 int error;
542
543 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
544
545 error = cgd_lock(true);
546 if (error)
547 return error;
548 sc = getcgd_softc(dev);
549 if (sc == NULL)
550 sc = cgd_spawn(CGDUNIT(dev));
551 cgd_unlock();
552 if (sc == NULL)
553 return ENXIO;
554
555 return dk_open(&sc->sc_dksc, dev, flags, fmt, l);
556 }
557
558 static int
559 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
560 {
561 struct cgd_softc *sc;
562 struct dk_softc *dksc;
563 int error;
564
565 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
566
567 error = cgd_lock(false);
568 if (error)
569 return error;
570 sc = getcgd_softc(dev);
571 if (sc == NULL) {
572 error = ENXIO;
573 goto done;
574 }
575
576 dksc = &sc->sc_dksc;
577 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0)
578 goto done;
579
580 if (!DK_ATTACHED(dksc)) {
581 if ((error = cgd_destroy(sc->sc_dksc.sc_dev)) != 0) {
582 device_printf(dksc->sc_dev,
583 "unable to detach instance\n");
584 goto done;
585 }
586 }
587
588 done:
589 cgd_unlock();
590
591 return error;
592 }
593
594 static void
595 cgdstrategy(struct buf *bp)
596 {
597 struct cgd_softc *sc = getcgd_softc(bp->b_dev);
598
599 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
600 (long)bp->b_bcount));
601
602 /*
603 * Reject unaligned writes.
604 */
605 if (((uintptr_t)bp->b_data & 3) != 0) {
606 bp->b_error = EINVAL;
607 goto bail;
608 }
609
610 dk_strategy(&sc->sc_dksc, bp);
611 return;
612
613 bail:
614 bp->b_resid = bp->b_bcount;
615 biodone(bp);
616 return;
617 }
618
619 static int
620 cgdsize(dev_t dev)
621 {
622 struct cgd_softc *sc = getcgd_softc(dev);
623
624 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
625 if (!sc)
626 return -1;
627 return dk_size(&sc->sc_dksc, dev);
628 }
629
630 /*
631 * cgd_{get,put}data are functions that deal with getting a buffer
632 * for the new encrypted data.
633 * We can no longer have a buffer per device, we need a buffer per
634 * work queue...
635 */
636
637 static void *
638 cgd_getdata(struct cgd_softc *sc, unsigned long size)
639 {
640 void *data = NULL;
641
642 mutex_enter(&sc->sc_lock);
643 if (!sc->sc_data_used) {
644 sc->sc_data_used = true;
645 data = sc->sc_data;
646 }
647 mutex_exit(&sc->sc_lock);
648
649 if (data)
650 return data;
651
652 return kmem_intr_alloc(size, KM_NOSLEEP);
653 }
654
655 static void
656 cgd_putdata(struct cgd_softc *sc, void *data, unsigned long size)
657 {
658
659 if (data == sc->sc_data) {
660 mutex_enter(&sc->sc_lock);
661 sc->sc_data_used = false;
662 mutex_exit(&sc->sc_lock);
663 } else
664 kmem_intr_free(data, size);
665 }
666
667 static int
668 cgd_diskstart(device_t dev, struct buf *bp)
669 {
670 struct cgd_softc *sc = device_private(dev);
671 struct cgd_worker *cw = sc->sc_worker;
672 struct dk_softc *dksc = &sc->sc_dksc;
673 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
674 struct cgd_xfer *cx;
675 struct buf *nbp;
676 void * newaddr;
677 daddr_t bn;
678
679 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
680
681 bn = bp->b_rawblkno;
682
683 /*
684 * We attempt to allocate all of our resources up front, so that
685 * we can fail quickly if they are unavailable.
686 */
687 nbp = getiobuf(sc->sc_tvn, false);
688 if (nbp == NULL)
689 return EAGAIN;
690
691 cx = pool_get(cw->cw_cpool, PR_NOWAIT);
692 if (cx == NULL) {
693 putiobuf(nbp);
694 return EAGAIN;
695 }
696
697 cx->cx_sc = sc;
698 cx->cx_obp = bp;
699 cx->cx_nbp = nbp;
700 cx->cx_srcv = cx->cx_dstv = bp->b_data;
701 cx->cx_blkno = bn;
702 cx->cx_secsize = dg->dg_secsize;
703
704 /*
705 * If we are writing, then we need to encrypt the outgoing
706 * block into a new block of memory.
707 */
708 if ((bp->b_flags & B_READ) == 0) {
709 newaddr = cgd_getdata(sc, bp->b_bcount);
710 if (!newaddr) {
711 pool_put(cw->cw_cpool, cx);
712 putiobuf(nbp);
713 return EAGAIN;
714 }
715
716 cx->cx_dstv = newaddr;
717 cx->cx_len = bp->b_bcount;
718 cx->cx_dir = CGD_CIPHER_ENCRYPT;
719
720 cgd_enqueue(sc, cx);
721 return 0;
722 }
723
724 cgd_diskstart2(sc, cx);
725 return 0;
726 }
727
728 static void
729 cgd_diskstart2(struct cgd_softc *sc, struct cgd_xfer *cx)
730 {
731 struct vnode *vp;
732 struct buf *bp;
733 struct buf *nbp;
734
735 bp = cx->cx_obp;
736 nbp = cx->cx_nbp;
737
738 nbp->b_data = cx->cx_dstv;
739 nbp->b_flags = bp->b_flags;
740 nbp->b_oflags = bp->b_oflags;
741 nbp->b_cflags = bp->b_cflags;
742 nbp->b_iodone = cgdiodone;
743 nbp->b_proc = bp->b_proc;
744 nbp->b_blkno = btodb(cx->cx_blkno * cx->cx_secsize);
745 nbp->b_bcount = bp->b_bcount;
746 nbp->b_private = cx;
747
748 BIO_COPYPRIO(nbp, bp);
749
750 if ((nbp->b_flags & B_READ) == 0) {
751 vp = nbp->b_vp;
752 mutex_enter(vp->v_interlock);
753 vp->v_numoutput++;
754 mutex_exit(vp->v_interlock);
755 }
756 VOP_STRATEGY(sc->sc_tvn, nbp);
757 }
758
759 static void
760 cgdiodone(struct buf *nbp)
761 {
762 struct cgd_xfer *cx = nbp->b_private;
763 struct buf *obp = cx->cx_obp;
764 struct cgd_softc *sc = getcgd_softc(obp->b_dev);
765 struct dk_softc *dksc = &sc->sc_dksc;
766 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
767 daddr_t bn;
768
769 KDASSERT(sc);
770
771 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
772 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
773 obp, obp->b_bcount, obp->b_resid));
774 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
775 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
776 nbp->b_bcount));
777 if (nbp->b_error != 0) {
778 obp->b_error = nbp->b_error;
779 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
780 obp->b_error));
781 }
782
783 /* Perform the decryption if we are reading.
784 *
785 * Note: use the blocknumber from nbp, since it is what
786 * we used to encrypt the blocks.
787 */
788
789 if (nbp->b_flags & B_READ) {
790 bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
791
792 cx->cx_obp = obp;
793 cx->cx_nbp = nbp;
794 cx->cx_dstv = obp->b_data;
795 cx->cx_srcv = obp->b_data;
796 cx->cx_len = obp->b_bcount;
797 cx->cx_blkno = bn;
798 cx->cx_secsize = dg->dg_secsize;
799 cx->cx_dir = CGD_CIPHER_DECRYPT;
800
801 cgd_enqueue(sc, cx);
802 return;
803 }
804
805 cgd_iodone2(sc, cx);
806 }
807
808 static void
809 cgd_iodone2(struct cgd_softc *sc, struct cgd_xfer *cx)
810 {
811 struct cgd_worker *cw = sc->sc_worker;
812 struct buf *obp = cx->cx_obp;
813 struct buf *nbp = cx->cx_nbp;
814 struct dk_softc *dksc = &sc->sc_dksc;
815
816 pool_put(cw->cw_cpool, cx);
817
818 /* If we allocated memory, free it now... */
819 if (nbp->b_data != obp->b_data)
820 cgd_putdata(sc, nbp->b_data, nbp->b_bcount);
821
822 putiobuf(nbp);
823
824 /* Request is complete for whatever reason */
825 obp->b_resid = 0;
826 if (obp->b_error != 0)
827 obp->b_resid = obp->b_bcount;
828
829 dk_done(dksc, obp);
830 dk_start(dksc, NULL);
831 }
832
833 static int
834 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
835 {
836 struct cgd_softc *sc = device_private(dev);
837 struct dk_softc *dksc = &sc->sc_dksc;
838 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
839 size_t nbytes, blksize;
840 void *buf;
841 int error;
842
843 /*
844 * dk_dump gives us units of disklabel sectors. Everything
845 * else in cgd uses units of diskgeom sectors. These had
846 * better agree; otherwise we need to figure out how to convert
847 * between them.
848 */
849 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
850 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
851 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
852 blksize = dg->dg_secsize;
853
854 /*
855 * Compute the number of bytes in this request, which dk_dump
856 * has `helpfully' converted to a number of blocks for us.
857 */
858 nbytes = nblk*blksize;
859
860 /* Try to acquire a buffer to store the ciphertext. */
861 buf = cgd_getdata(sc, nbytes);
862 if (buf == NULL)
863 /* Out of memory: give up. */
864 return ENOMEM;
865
866 /* Encrypt the caller's data into the temporary buffer. */
867 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
868
869 /* Pass it on to the underlying disk device. */
870 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
871
872 /* Release the buffer. */
873 cgd_putdata(sc, buf, nbytes);
874
875 /* Return any error from the underlying disk device. */
876 return error;
877 }
878
879 /* XXX: we should probably put these into dksubr.c, mostly */
880 static int
881 cgdread(dev_t dev, struct uio *uio, int flags)
882 {
883 struct cgd_softc *sc;
884 struct dk_softc *dksc;
885
886 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
887 (unsigned long long)dev, uio, flags));
888 sc = getcgd_softc(dev);
889 if (sc == NULL)
890 return ENXIO;
891 dksc = &sc->sc_dksc;
892 if (!DK_ATTACHED(dksc))
893 return ENXIO;
894 return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
895 }
896
897 /* XXX: we should probably put these into dksubr.c, mostly */
898 static int
899 cgdwrite(dev_t dev, struct uio *uio, int flags)
900 {
901 struct cgd_softc *sc;
902 struct dk_softc *dksc;
903
904 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
905 sc = getcgd_softc(dev);
906 if (sc == NULL)
907 return ENXIO;
908 dksc = &sc->sc_dksc;
909 if (!DK_ATTACHED(dksc))
910 return ENXIO;
911 return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
912 }
913
914 static int
915 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
916 {
917 struct cgd_softc *sc;
918 struct dk_softc *dksc;
919 int part = DISKPART(dev);
920 int pmask = 1 << part;
921 int error;
922
923 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
924 dev, cmd, data, flag, l));
925
926 switch (cmd) {
927 case CGDIOCGET:
928 return cgd_ioctl_get(dev, data, l);
929 case CGDIOCSET:
930 case CGDIOCCLR:
931 if ((flag & FWRITE) == 0)
932 return EBADF;
933 /* FALLTHROUGH */
934 default:
935 sc = getcgd_softc(dev);
936 if (sc == NULL)
937 return ENXIO;
938 dksc = &sc->sc_dksc;
939 break;
940 }
941
942 switch (cmd) {
943 case CGDIOCSET:
944 cgd_busy(sc);
945 if (DK_ATTACHED(dksc))
946 error = EBUSY;
947 else
948 error = cgd_ioctl_set(sc, data, l);
949 cgd_unbusy(sc);
950 break;
951 case CGDIOCCLR:
952 cgd_busy(sc);
953 if (DK_BUSY(&sc->sc_dksc, pmask))
954 error = EBUSY;
955 else
956 error = cgd_ioctl_clr(sc, l);
957 cgd_unbusy(sc);
958 break;
959 case DIOCGCACHE:
960 case DIOCCACHESYNC:
961 cgd_busy(sc);
962 if (!DK_ATTACHED(dksc)) {
963 cgd_unbusy(sc);
964 error = ENOENT;
965 break;
966 }
967 /*
968 * We pass this call down to the underlying disk.
969 */
970 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred);
971 cgd_unbusy(sc);
972 break;
973 case DIOCGSECTORALIGN: {
974 struct disk_sectoralign *dsa = data;
975
976 cgd_busy(sc);
977 if (!DK_ATTACHED(dksc)) {
978 cgd_unbusy(sc);
979 error = ENOENT;
980 break;
981 }
982
983 /* Get the underlying disk's sector alignment. */
984 error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred);
985 if (error) {
986 cgd_unbusy(sc);
987 break;
988 }
989
990 /* Adjust for the disklabel partition if necessary. */
991 if (part != RAW_PART) {
992 struct disklabel *lp = dksc->sc_dkdev.dk_label;
993 daddr_t offset = lp->d_partitions[part].p_offset;
994 uint32_t r = offset % dsa->dsa_alignment;
995
996 if (r < dsa->dsa_firstaligned)
997 dsa->dsa_firstaligned = dsa->dsa_firstaligned
998 - r;
999 else
1000 dsa->dsa_firstaligned = (dsa->dsa_firstaligned
1001 + dsa->dsa_alignment) - r;
1002 }
1003 cgd_unbusy(sc);
1004 break;
1005 }
1006 case DIOCGSTRATEGY:
1007 case DIOCSSTRATEGY:
1008 if (!DK_ATTACHED(dksc)) {
1009 error = ENOENT;
1010 break;
1011 }
1012 /*FALLTHROUGH*/
1013 default:
1014 error = dk_ioctl(dksc, dev, cmd, data, flag, l);
1015 break;
1016 case CGDIOCGET:
1017 KASSERT(0);
1018 error = EINVAL;
1019 }
1020
1021 return error;
1022 }
1023
1024 static int
1025 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
1026 {
1027 struct cgd_softc *sc;
1028
1029 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
1030 dev, blkno, va, (unsigned long)size));
1031 sc = getcgd_softc(dev);
1032 if (sc == NULL)
1033 return ENXIO;
1034 return dk_dump(&sc->sc_dksc, dev, blkno, va, size, DK_DUMP_RECURSIVE);
1035 }
1036
1037 /*
1038 * XXXrcd:
1039 * for now we hardcode the maximum key length.
1040 */
1041 #define MAX_KEYSIZE 1024
1042
1043 static const struct {
1044 const char *n;
1045 int v;
1046 int d;
1047 } encblkno[] = {
1048 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
1049 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
1050 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
1051 };
1052
1053 /* ARGSUSED */
1054 static int
1055 cgd_ioctl_set(struct cgd_softc *sc, void *data, struct lwp *l)
1056 {
1057 struct cgd_ioctl *ci = data;
1058 struct vnode *vp;
1059 int ret;
1060 size_t i;
1061 size_t keybytes; /* key length in bytes */
1062 const char *cp;
1063 struct pathbuf *pb;
1064 char *inbuf;
1065 struct dk_softc *dksc = &sc->sc_dksc;
1066
1067 cp = ci->ci_disk;
1068
1069 ret = pathbuf_copyin(ci->ci_disk, &pb);
1070 if (ret != 0) {
1071 return ret;
1072 }
1073 ret = dk_lookup(pb, l, &vp);
1074 pathbuf_destroy(pb);
1075 if (ret != 0) {
1076 return ret;
1077 }
1078
1079 inbuf = kmem_alloc(MAX_KEYSIZE, KM_SLEEP);
1080
1081 if ((ret = cgdinit(sc, cp, vp, l)) != 0)
1082 goto bail;
1083
1084 (void)memset(inbuf, 0, MAX_KEYSIZE);
1085 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
1086 if (ret)
1087 goto bail;
1088 sc->sc_cfuncs = cryptfuncs_find(inbuf);
1089 if (!sc->sc_cfuncs) {
1090 ret = EINVAL;
1091 goto bail;
1092 }
1093
1094 (void)memset(inbuf, 0, MAX_KEYSIZE);
1095 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
1096 if (ret)
1097 goto bail;
1098
1099 for (i = 0; i < __arraycount(encblkno); i++)
1100 if (strcmp(encblkno[i].n, inbuf) == 0)
1101 break;
1102
1103 if (i == __arraycount(encblkno)) {
1104 ret = EINVAL;
1105 goto bail;
1106 }
1107
1108 keybytes = ci->ci_keylen / 8 + 1;
1109 if (keybytes > MAX_KEYSIZE) {
1110 ret = EINVAL;
1111 goto bail;
1112 }
1113
1114 (void)memset(inbuf, 0, MAX_KEYSIZE);
1115 ret = copyin(ci->ci_key, inbuf, keybytes);
1116 if (ret)
1117 goto bail;
1118
1119 sc->sc_cdata.cf_blocksize = ci->ci_blocksize;
1120 sc->sc_cdata.cf_mode = encblkno[i].v;
1121 sc->sc_cdata.cf_keylen = ci->ci_keylen;
1122 sc->sc_cdata.cf_priv = sc->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
1123 &sc->sc_cdata.cf_blocksize);
1124 if (sc->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
1125 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
1126 sc->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
1127 sc->sc_cdata.cf_priv = NULL;
1128 }
1129
1130 /*
1131 * The blocksize is supposed to be in bytes. Unfortunately originally
1132 * it was expressed in bits. For compatibility we maintain encblkno
1133 * and encblkno8.
1134 */
1135 sc->sc_cdata.cf_blocksize /= encblkno[i].d;
1136 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
1137 if (!sc->sc_cdata.cf_priv) {
1138 ret = EINVAL; /* XXX is this the right error? */
1139 goto bail;
1140 }
1141 kmem_free(inbuf, MAX_KEYSIZE);
1142
1143 bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
1144
1145 sc->sc_data = kmem_alloc(MAXPHYS, KM_SLEEP);
1146 sc->sc_data_used = false;
1147
1148 /* Attach the disk. */
1149 dk_attach(dksc);
1150 disk_attach(&dksc->sc_dkdev);
1151
1152 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
1153
1154 /* Discover wedges on this disk. */
1155 dkwedge_discover(&dksc->sc_dkdev);
1156
1157 return 0;
1158
1159 bail:
1160 kmem_free(inbuf, MAX_KEYSIZE);
1161 (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
1162 return ret;
1163 }
1164
1165 /* ARGSUSED */
1166 static int
1167 cgd_ioctl_clr(struct cgd_softc *sc, struct lwp *l)
1168 {
1169 struct dk_softc *dksc = &sc->sc_dksc;
1170
1171 if (!DK_ATTACHED(dksc))
1172 return ENXIO;
1173
1174 /* Delete all of our wedges. */
1175 dkwedge_delall(&dksc->sc_dkdev);
1176
1177 /* Kill off any queued buffers. */
1178 dk_drain(dksc);
1179 bufq_free(dksc->sc_bufq);
1180
1181 (void)vn_close(sc->sc_tvn, FREAD|FWRITE, l->l_cred);
1182 sc->sc_cfuncs->cf_destroy(sc->sc_cdata.cf_priv);
1183 kmem_free(sc->sc_tpath, sc->sc_tpathlen);
1184 kmem_free(sc->sc_data, MAXPHYS);
1185 sc->sc_data_used = false;
1186 dk_detach(dksc);
1187 disk_detach(&dksc->sc_dkdev);
1188
1189 return 0;
1190 }
1191
1192 static int
1193 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
1194 {
1195 struct cgd_softc *sc;
1196 struct cgd_user *cgu;
1197 int unit, error;
1198
1199 unit = CGDUNIT(dev);
1200 cgu = (struct cgd_user *)data;
1201
1202 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
1203 dev, unit, data, l));
1204
1205 /* XXX, we always return this units data, so if cgu_unit is
1206 * not -1, that field doesn't match the rest
1207 */
1208 if (cgu->cgu_unit == -1)
1209 cgu->cgu_unit = unit;
1210
1211 if (cgu->cgu_unit < 0)
1212 return EINVAL; /* XXX: should this be ENXIO? */
1213
1214 error = cgd_lock(false);
1215 if (error)
1216 return error;
1217
1218 sc = device_lookup_private(&cgd_cd, unit);
1219 if (sc == NULL || !DK_ATTACHED(&sc->sc_dksc)) {
1220 cgu->cgu_dev = 0;
1221 cgu->cgu_alg[0] = '\0';
1222 cgu->cgu_blocksize = 0;
1223 cgu->cgu_mode = 0;
1224 cgu->cgu_keylen = 0;
1225 }
1226 else {
1227 mutex_enter(&sc->sc_lock);
1228 cgu->cgu_dev = sc->sc_tdev;
1229 strncpy(cgu->cgu_alg, sc->sc_cfuncs->cf_name,
1230 sizeof(cgu->cgu_alg));
1231 cgu->cgu_blocksize = sc->sc_cdata.cf_blocksize;
1232 cgu->cgu_mode = sc->sc_cdata.cf_mode;
1233 cgu->cgu_keylen = sc->sc_cdata.cf_keylen;
1234 mutex_exit(&sc->sc_lock);
1235 }
1236
1237 cgd_unlock();
1238 return 0;
1239 }
1240
1241 static int
1242 cgdinit(struct cgd_softc *sc, const char *cpath, struct vnode *vp,
1243 struct lwp *l)
1244 {
1245 struct disk_geom *dg;
1246 int ret;
1247 char *tmppath;
1248 uint64_t psize;
1249 unsigned secsize;
1250 struct dk_softc *dksc = &sc->sc_dksc;
1251
1252 sc->sc_tvn = vp;
1253 sc->sc_tpath = NULL;
1254
1255 tmppath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1256 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &sc->sc_tpathlen);
1257 if (ret)
1258 goto bail;
1259 sc->sc_tpath = kmem_alloc(sc->sc_tpathlen, KM_SLEEP);
1260 memcpy(sc->sc_tpath, tmppath, sc->sc_tpathlen);
1261
1262 sc->sc_tdev = vp->v_rdev;
1263
1264 if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
1265 goto bail;
1266
1267 if (psize == 0) {
1268 ret = ENODEV;
1269 goto bail;
1270 }
1271
1272 /*
1273 * XXX here we should probe the underlying device. If we
1274 * are accessing a partition of type RAW_PART, then
1275 * we should populate our initial geometry with the
1276 * geometry that we discover from the device.
1277 */
1278 dg = &dksc->sc_dkdev.dk_geom;
1279 memset(dg, 0, sizeof(*dg));
1280 dg->dg_secperunit = psize;
1281 dg->dg_secsize = secsize;
1282 dg->dg_ntracks = 1;
1283 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
1284 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
1285
1286 bail:
1287 kmem_free(tmppath, MAXPATHLEN);
1288 if (ret && sc->sc_tpath)
1289 kmem_free(sc->sc_tpath, sc->sc_tpathlen);
1290 return ret;
1291 }
1292
1293 /*
1294 * Our generic cipher entry point. This takes care of the
1295 * IV mode and passes off the work to the specific cipher.
1296 * We implement here the IV method ``encrypted block
1297 * number''.
1298 *
1299 * XXXrcd: for now we rely on our own crypto framework defined
1300 * in dev/cgd_crypto.c. This will change when we
1301 * get a generic kernel crypto framework.
1302 */
1303
1304 static void
1305 blkno2blkno_buf(char *sbuf, daddr_t blkno)
1306 {
1307 int i;
1308
1309 /* Set up the blkno in blkno_buf, here we do not care much
1310 * about the final layout of the information as long as we
1311 * can guarantee that each sector will have a different IV
1312 * and that the endianness of the machine will not affect
1313 * the representation that we have chosen.
1314 *
1315 * We choose this representation, because it does not rely
1316 * on the size of buf (which is the blocksize of the cipher),
1317 * but allows daddr_t to grow without breaking existing
1318 * disks.
1319 *
1320 * Note that blkno2blkno_buf does not take a size as input,
1321 * and hence must be called on a pre-zeroed buffer of length
1322 * greater than or equal to sizeof(daddr_t).
1323 */
1324 for (i=0; i < sizeof(daddr_t); i++) {
1325 *sbuf++ = blkno & 0xff;
1326 blkno >>= 8;
1327 }
1328 }
1329
1330 static struct cpu_info *
1331 cgd_cpu(struct cgd_softc *sc)
1332 {
1333 struct cgd_worker *cw = sc->sc_worker;
1334 struct cpu_info *ci = NULL;
1335 u_int cidx, i;
1336
1337 if (cw->cw_busy == 0) {
1338 cw->cw_last = cpu_index(curcpu());
1339 return NULL;
1340 }
1341
1342 for (i=0, cidx = cw->cw_last+1; i<maxcpus; ++i, ++cidx) {
1343 if (cidx >= maxcpus)
1344 cidx = 0;
1345 ci = cpu_lookup(cidx);
1346 if (ci) {
1347 cw->cw_last = cidx;
1348 break;
1349 }
1350 }
1351
1352 return ci;
1353 }
1354
1355 static void
1356 cgd_enqueue(struct cgd_softc *sc, struct cgd_xfer *cx)
1357 {
1358 struct cgd_worker *cw = sc->sc_worker;
1359 struct cpu_info *ci;
1360
1361 mutex_enter(&cw->cw_lock);
1362 ci = cgd_cpu(sc);
1363 cw->cw_busy++;
1364 mutex_exit(&cw->cw_lock);
1365
1366 workqueue_enqueue(cw->cw_wq, &cx->cx_work, ci);
1367 }
1368
1369 static void
1370 cgd_process(struct work *wk, void *arg)
1371 {
1372 struct cgd_xfer *cx = (struct cgd_xfer *)wk;
1373 struct cgd_softc *sc = cx->cx_sc;
1374 struct cgd_worker *cw = sc->sc_worker;
1375
1376 cgd_cipher(sc, cx->cx_dstv, cx->cx_srcv, cx->cx_len,
1377 cx->cx_blkno, cx->cx_secsize, cx->cx_dir);
1378
1379 if (cx->cx_dir == CGD_CIPHER_ENCRYPT) {
1380 cgd_diskstart2(sc, cx);
1381 } else {
1382 cgd_iodone2(sc, cx);
1383 }
1384
1385 mutex_enter(&cw->cw_lock);
1386 if (cw->cw_busy > 0)
1387 cw->cw_busy--;
1388 mutex_exit(&cw->cw_lock);
1389 }
1390
1391 static void
1392 cgd_cipher(struct cgd_softc *sc, void *dstv, void *srcv,
1393 size_t len, daddr_t blkno, size_t secsize, int dir)
1394 {
1395 char *dst = dstv;
1396 char *src = srcv;
1397 cfunc_cipher_prep *ciprep = sc->sc_cfuncs->cf_cipher_prep;
1398 cfunc_cipher *cipher = sc->sc_cfuncs->cf_cipher;
1399 struct uio dstuio;
1400 struct uio srcuio;
1401 struct iovec dstiov[2];
1402 struct iovec srciov[2];
1403 size_t blocksize = sc->sc_cdata.cf_blocksize;
1404 size_t todo;
1405 char blkno_buf[CGD_MAXBLOCKSIZE], *iv;
1406
1407 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1408
1409 DIAGCONDPANIC(len % blocksize != 0,
1410 ("cgd_cipher: len %% blocksize != 0"));
1411
1412 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1413 DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
1414 ("cgd_cipher: sizeof(daddr_t) > blocksize"));
1415
1416 DIAGCONDPANIC(blocksize > CGD_MAXBLOCKSIZE,
1417 ("cgd_cipher: blocksize > CGD_MAXBLOCKSIZE"));
1418
1419 dstuio.uio_iov = dstiov;
1420 dstuio.uio_iovcnt = 1;
1421
1422 srcuio.uio_iov = srciov;
1423 srcuio.uio_iovcnt = 1;
1424
1425 for (; len > 0; len -= todo) {
1426 todo = MIN(len, secsize);
1427
1428 dstiov[0].iov_base = dst;
1429 srciov[0].iov_base = src;
1430 dstiov[0].iov_len = todo;
1431 srciov[0].iov_len = todo;
1432
1433 memset(blkno_buf, 0x0, blocksize);
1434 blkno2blkno_buf(blkno_buf, blkno);
1435 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1436 blkno_buf, blocksize));
1437
1438 /*
1439 * Compute an initial IV. All ciphers
1440 * can convert blkno_buf in-place.
1441 */
1442 iv = blkno_buf;
1443 ciprep(sc->sc_cdata.cf_priv, iv, blkno_buf, blocksize, dir);
1444 IFDEBUG(CGDB_CRYPTO, hexprint("step 2: iv", iv, blocksize));
1445
1446 cipher(sc->sc_cdata.cf_priv, &dstuio, &srcuio, iv, dir);
1447
1448 dst += todo;
1449 src += todo;
1450 blkno++;
1451 }
1452 }
1453
1454 #ifdef DEBUG
1455 static void
1456 hexprint(const char *start, void *buf, int len)
1457 {
1458 char *c = buf;
1459
1460 DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
1461 printf("%s: len=%06d 0x", start, len);
1462 while (len--)
1463 printf("%02x", (unsigned char) *c++);
1464 }
1465 #endif
1466
1467 static void
1468 selftest(void)
1469 {
1470 struct cgd_softc sc;
1471 void *buf;
1472
1473 printf("running cgd selftest ");
1474
1475 for (size_t i = 0; i < __arraycount(selftests); i++) {
1476 const char *alg = selftests[i].alg;
1477 const uint8_t *key = selftests[i].key;
1478 int keylen = selftests[i].keylen;
1479 int txtlen = selftests[i].txtlen;
1480
1481 printf("%s-%d ", alg, keylen);
1482
1483 memset(&sc, 0, sizeof(sc));
1484
1485 sc.sc_cfuncs = cryptfuncs_find(alg);
1486 if (sc.sc_cfuncs == NULL)
1487 panic("%s not implemented", alg);
1488
1489 sc.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
1490 sc.sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
1491 sc.sc_cdata.cf_keylen = keylen;
1492
1493 sc.sc_cdata.cf_priv = sc.sc_cfuncs->cf_init(keylen,
1494 key, &sc.sc_cdata.cf_blocksize);
1495 if (sc.sc_cdata.cf_priv == NULL)
1496 panic("cf_priv is NULL");
1497 if (sc.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
1498 panic("bad block size %zu", sc.sc_cdata.cf_blocksize);
1499
1500 sc.sc_cdata.cf_blocksize /= 8;
1501
1502 buf = kmem_alloc(txtlen, KM_SLEEP);
1503 memcpy(buf, selftests[i].ptxt, txtlen);
1504
1505 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno,
1506 selftests[i].secsize, CGD_CIPHER_ENCRYPT);
1507 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0)
1508 panic("encryption is broken");
1509
1510 cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno,
1511 selftests[i].secsize, CGD_CIPHER_DECRYPT);
1512 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0)
1513 panic("decryption is broken");
1514
1515 kmem_free(buf, txtlen);
1516 sc.sc_cfuncs->cf_destroy(sc.sc_cdata.cf_priv);
1517 }
1518
1519 printf("done\n");
1520 }
1521
1522 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr,bufq_fcfs");
1523
1524 #ifdef _MODULE
1525 CFDRIVER_DECL(cgd, DV_DISK, NULL);
1526
1527 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1528 #endif
1529
1530 static int
1531 cgd_modcmd(modcmd_t cmd, void *arg)
1532 {
1533 int error = 0;
1534
1535 switch (cmd) {
1536 case MODULE_CMD_INIT:
1537 selftest();
1538 #ifdef _MODULE
1539 mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE);
1540 cv_init(&cgd_spawning_cv, "cgspwn");
1541
1542 error = config_cfdriver_attach(&cgd_cd);
1543 if (error)
1544 break;
1545
1546 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1547 if (error) {
1548 config_cfdriver_detach(&cgd_cd);
1549 aprint_error("%s: unable to register cfattach for"
1550 "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1551 break;
1552 }
1553 /*
1554 * Attach the {b,c}devsw's
1555 */
1556 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1557 &cgd_cdevsw, &cgd_cmajor);
1558
1559 /*
1560 * If devsw_attach fails, remove from autoconf database
1561 */
1562 if (error) {
1563 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1564 config_cfdriver_detach(&cgd_cd);
1565 aprint_error("%s: unable to attach %s devsw, "
1566 "error %d", __func__, cgd_cd.cd_name, error);
1567 break;
1568 }
1569 #endif
1570 break;
1571
1572 case MODULE_CMD_FINI:
1573 #ifdef _MODULE
1574 /*
1575 * Remove {b,c}devsw's
1576 */
1577 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1578
1579 /*
1580 * Now remove device from autoconf database
1581 */
1582 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1583 if (error) {
1584 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1585 &cgd_cdevsw, &cgd_cmajor);
1586 aprint_error("%s: failed to detach %s cfattach, "
1587 "error %d\n", __func__, cgd_cd.cd_name, error);
1588 break;
1589 }
1590 error = config_cfdriver_detach(&cgd_cd);
1591 if (error) {
1592 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1593 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1594 &cgd_cdevsw, &cgd_cmajor);
1595 aprint_error("%s: failed to detach %s cfdriver, "
1596 "error %d\n", __func__, cgd_cd.cd_name, error);
1597 break;
1598 }
1599
1600 cv_destroy(&cgd_spawning_cv);
1601 mutex_destroy(&cgd_spawning_mtx);
1602 #endif
1603 break;
1604
1605 case MODULE_CMD_STAT:
1606 error = ENOTTY;
1607 break;
1608 default:
1609 error = ENOTTY;
1610 break;
1611 }
1612
1613 return error;
1614 }
1615