cgd.c revision 1.108.2.19 1 /* $NetBSD: cgd.c,v 1.108.2.19 2016/11/04 14:49:08 pgoyette 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.108.2.19 2016/11/04 14:49:08 pgoyette 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/malloc.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/localcount.h>
55
56 #include <dev/dkvar.h>
57 #include <dev/cgdvar.h>
58
59 #include <miscfs/specfs/specdev.h> /* for v_rdev */
60
61 #include "ioconf.h"
62
63 /* Entry Point Functions */
64
65 static dev_type_open(cgdopen);
66 static dev_type_close(cgdclose);
67 static dev_type_read(cgdread);
68 static dev_type_write(cgdwrite);
69 static dev_type_ioctl(cgdioctl);
70 static dev_type_strategy(cgdstrategy);
71 static dev_type_dump(cgddump);
72 static dev_type_size(cgdsize);
73
74 const struct bdevsw cgd_bdevsw = {
75 DEVSW_MODULE_INIT
76 .d_open = cgdopen,
77 .d_close = cgdclose,
78 .d_strategy = cgdstrategy,
79 .d_ioctl = cgdioctl,
80 .d_dump = cgddump,
81 .d_psize = cgdsize,
82 .d_discard = nodiscard,
83 .d_flag = D_DISK
84 };
85
86 const struct cdevsw cgd_cdevsw = {
87 DEVSW_MODULE_INIT
88 .d_open = cgdopen,
89 .d_close = cgdclose,
90 .d_read = cgdread,
91 .d_write = cgdwrite,
92 .d_ioctl = cgdioctl,
93 .d_stop = nostop,
94 .d_tty = notty,
95 .d_poll = nopoll,
96 .d_mmap = nommap,
97 .d_kqfilter = nokqfilter,
98 .d_discard = nodiscard,
99 .d_flag = D_DISK
100 };
101
102 static int cgd_match(device_t, cfdata_t, void *);
103 static void cgd_attach(device_t, device_t, void *);
104 static int cgd_detach(device_t, int);
105 static struct cgd_softc *cgd_spawn(int, device_t *);
106 static int cgd_destroy(device_t);
107
108 /* Internal Functions */
109
110 static int cgd_diskstart(device_t, struct buf *);
111 static void cgdiodone(struct buf *);
112 static int cgd_dumpblocks(device_t, void *, daddr_t, int);
113
114 static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
115 static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
116 static int cgd_ioctl_get(dev_t, void *, struct lwp *);
117 static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
118 struct lwp *);
119 static void cgd_cipher(struct cgd_softc *, void *, void *,
120 size_t, daddr_t, size_t, int);
121
122 static struct dkdriver cgddkdriver = {
123 .d_minphys = minphys,
124 .d_open = cgdopen,
125 .d_close = cgdclose,
126 .d_strategy = cgdstrategy,
127 .d_iosize = NULL,
128 .d_diskstart = cgd_diskstart,
129 .d_dumpblocks = cgd_dumpblocks,
130 .d_lastclose = NULL
131 };
132
133 CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
134 cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
135 extern struct cfdriver cgd_cd;
136
137 /* DIAGNOSTIC and DEBUG definitions */
138
139 #if defined(CGDDEBUG) && !defined(DEBUG)
140 #define DEBUG
141 #endif
142
143 #ifdef DEBUG
144 int cgddebug = 0;
145
146 #define CGDB_FOLLOW 0x1
147 #define CGDB_IO 0x2
148 #define CGDB_CRYPTO 0x4
149
150 #define IFDEBUG(x,y) if (cgddebug & (x)) y
151 #define DPRINTF(x,y) IFDEBUG(x, printf y)
152 #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
153
154 static void hexprint(const char *, void *, int);
155
156 #else
157 #define IFDEBUG(x,y)
158 #define DPRINTF(x,y)
159 #define DPRINTF_FOLLOW(y)
160 #endif
161
162 #ifdef DIAGNOSTIC
163 #define DIAGPANIC(x) panic x
164 #define DIAGCONDPANIC(x,y) if (x) panic y
165 #else
166 #define DIAGPANIC(x)
167 #define DIAGCONDPANIC(x,y)
168 #endif
169
170 /* Global variables */
171
172 /* Utility Functions */
173
174 #define CGDUNIT(x) DISKUNIT(x)
175 #define GETCGD_SOFTC(_cs, x, _dv) \
176 if (((_cs) = getcgd_softc(x, &_dv)) == NULL) { \
177 return ENXIO; \
178 }
179
180 /* The code */
181
182 /*
183 * Lookup the device and return it's softc. If the device doesn't
184 * exist, spawn it.
185 *
186 * In either case, the device is "acquired", and must be "released"
187 * by the caller after it is finished with the softc.
188 */
189 static struct cgd_softc *
190 getcgd_softc(dev_t dev, device_t *self)
191 {
192 int unit = CGDUNIT(dev);
193 struct cgd_softc *sc;
194
195 DPRINTF_FOLLOW(("getcgd_softc(0x%"PRIx64"): unit = %d\n", dev, unit));
196
197 *self = device_lookup_acquire(&cgd_cd, unit);
198
199 if (*self == NULL) {
200 sc = cgd_spawn(unit, self);
201 } else {
202 sc = device_private(*self);
203 }
204
205 return sc;
206 }
207
208 static int
209 cgd_match(device_t self, cfdata_t cfdata, void *aux)
210 {
211
212 return 1;
213 }
214
215 static void
216 cgd_attach(device_t parent, device_t self, void *aux)
217 {
218 struct cgd_softc *sc;
219
220 sc = device_private(self);
221
222 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
223 dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
224 disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
225
226 if (!pmf_device_register(self, NULL, NULL))
227 aprint_error_dev(self,
228 "unable to register power management hooks\n");
229 }
230
231
232 /*
233 * The caller must hold a reference to the device's localcount. the
234 * reference is released if the device is available for detach.
235 */
236 static int
237 cgd_detach(device_t self, int flags)
238 {
239 int ret;
240 const int pmask = 1 << RAW_PART;
241 struct cgd_softc *sc = device_private(self);
242 struct dk_softc *dksc = &sc->sc_dksc;
243
244 if (DK_BUSY(dksc, pmask))
245 return EBUSY;
246
247 if (DK_ATTACHED(dksc) &&
248 (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
249 return ret;
250
251 disk_destroy(&dksc->sc_dkdev);
252 mutex_destroy(&sc->sc_lock);
253
254 device_release(self);
255 return 0;
256 }
257
258 void
259 cgdattach(int num)
260 {
261 int error;
262
263 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
264 if (error != 0)
265 aprint_error("%s: unable to register cfattach\n",
266 cgd_cd.cd_name);
267 }
268
269 static struct cgd_softc *
270 cgd_spawn(int unit, device_t *self)
271 {
272 cfdata_t cf;
273 struct cgd_softc *sc;
274
275 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
276 cf->cf_name = cgd_cd.cd_name;
277 cf->cf_atname = cgd_cd.cd_name;
278 cf->cf_unit = unit;
279 cf->cf_fstate = FSTATE_STAR;
280
281 if (config_attach_pseudo(cf) == NULL)
282 return NULL;
283
284 *self = device_lookup_acquire(&cgd_cd, unit);
285 if (self == NULL)
286 return NULL;
287 else {
288 /*
289 * Note that we return while still holding a reference
290 * to the device!
291 */
292 sc = device_private(*self);
293 return sc;
294 }
295 }
296
297 static int
298 cgd_destroy(device_t dev)
299 {
300 int error;
301 cfdata_t cf;
302
303 cf = device_cfdata(dev);
304 error = config_detach(dev, DETACH_QUIET);
305 if (error == 0)
306 free(cf, M_DEVBUF);
307
308 return error;
309 }
310
311 static int
312 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
313 {
314 device_t self;
315 int error;
316 struct cgd_softc *cs;
317
318 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
319 GETCGD_SOFTC(cs, dev, self);
320 error = dk_open(&cs->sc_dksc, dev, flags, fmt, l);
321 device_release(self);
322 return error;
323 }
324
325 static int
326 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
327 {
328 int error;
329 device_t self;
330 struct cgd_softc *cs;
331 struct dk_softc *dksc;
332
333 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
334 GETCGD_SOFTC(cs, dev, self);
335 dksc = &cs->sc_dksc;
336 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0) {
337 device_release(self);
338 return error;
339 }
340
341 if (!DK_ATTACHED(dksc)) {
342 if ((error = cgd_destroy(cs->sc_dksc.sc_dev)) != 0) {
343 aprint_error_dev(dksc->sc_dev,
344 "unable to detach instance\n");
345 return error;
346 }
347 } else
348 device_release(self);
349 return 0;
350 }
351
352 static void
353 cgdstrategy(struct buf *bp)
354 {
355 device_t self;
356 struct cgd_softc *cs = getcgd_softc(bp->b_dev, &self);
357 struct dk_softc *dksc = &cs->sc_dksc;
358 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
359
360 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
361 (long)bp->b_bcount));
362
363 cs = getcgd_softc(bp->b_dev);
364 if (!cs) {
365 bp->b_error = ENXIO;
366 goto bail;
367 }
368
369 /*
370 * Reject unaligned writes.
371 */
372 if (((uintptr_t)bp->b_data & 3) != 0) {
373 bp->b_error = EINVAL;
374 bp->b_resid = bp->b_bcount;
375 biodone(bp);
376 device_release(self);
377 return;
378 }
379
380 dk_strategy(&cs->sc_dksc, bp);
381 device_release(self);
382 return;
383
384 bail:
385 bp->b_resid = bp->b_bcount;
386 biodone(bp);
387 return;
388 }
389
390 static int
391 cgdsize(dev_t dev)
392 {
393 int retval;
394 device_t self;
395 struct cgd_softc *cs = getcgd_softc(dev, &self);
396
397 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
398 if (!cs)
399 retval = -1;
400 else
401 retval = dk_size(&cs->sc_dksc, dev);
402
403 device_release(self);
404 return retval;
405 }
406
407 /*
408 * cgd_{get,put}data are functions that deal with getting a buffer
409 * for the new encrypted data. We have a buffer per device so that
410 * we can ensure that we can always have a transaction in flight.
411 * We use this buffer first so that we have one less piece of
412 * malloc'ed data at any given point.
413 */
414
415 static void *
416 cgd_getdata(struct dk_softc *dksc, unsigned long size)
417 {
418 struct cgd_softc *cs = (struct cgd_softc *)dksc;
419 void * data = NULL;
420
421 mutex_enter(&cs->sc_lock);
422 if (cs->sc_data_used == 0) {
423 cs->sc_data_used = 1;
424 data = cs->sc_data;
425 }
426 mutex_exit(&cs->sc_lock);
427
428 if (data)
429 return data;
430
431 return malloc(size, M_DEVBUF, M_NOWAIT);
432 }
433
434 static void
435 cgd_putdata(struct dk_softc *dksc, void *data)
436 {
437 struct cgd_softc *cs = (struct cgd_softc *)dksc;
438
439 if (data == cs->sc_data) {
440 mutex_enter(&cs->sc_lock);
441 cs->sc_data_used = 0;
442 mutex_exit(&cs->sc_lock);
443 } else {
444 free(data, M_DEVBUF);
445 }
446 }
447
448 static int
449 cgd_diskstart(device_t dev, struct buf *bp)
450 {
451 struct cgd_softc *cs = device_private(dev);
452 struct dk_softc *dksc = &cs->sc_dksc;
453 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
454 struct buf *nbp;
455 void * addr;
456 void * newaddr;
457 daddr_t bn;
458 struct vnode *vp;
459
460 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
461
462 bn = bp->b_rawblkno;
463
464 /*
465 * We attempt to allocate all of our resources up front, so that
466 * we can fail quickly if they are unavailable.
467 */
468 nbp = getiobuf(cs->sc_tvn, false);
469 if (nbp == NULL)
470 return EAGAIN;
471
472 /*
473 * If we are writing, then we need to encrypt the outgoing
474 * block into a new block of memory.
475 */
476 newaddr = addr = bp->b_data;
477 if ((bp->b_flags & B_READ) == 0) {
478 newaddr = cgd_getdata(dksc, bp->b_bcount);
479 if (!newaddr) {
480 putiobuf(nbp);
481 return EAGAIN;
482 }
483 cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
484 dg->dg_secsize, CGD_CIPHER_ENCRYPT);
485 }
486
487 nbp->b_data = newaddr;
488 nbp->b_flags = bp->b_flags;
489 nbp->b_oflags = bp->b_oflags;
490 nbp->b_cflags = bp->b_cflags;
491 nbp->b_iodone = cgdiodone;
492 nbp->b_proc = bp->b_proc;
493 nbp->b_blkno = btodb(bn * dg->dg_secsize);
494 nbp->b_bcount = bp->b_bcount;
495 nbp->b_private = bp;
496
497 BIO_COPYPRIO(nbp, bp);
498
499 if ((nbp->b_flags & B_READ) == 0) {
500 vp = nbp->b_vp;
501 mutex_enter(vp->v_interlock);
502 vp->v_numoutput++;
503 mutex_exit(vp->v_interlock);
504 }
505 VOP_STRATEGY(cs->sc_tvn, nbp);
506
507 return 0;
508 }
509
510 static void
511 cgdiodone(struct buf *nbp)
512 {
513 device_t self;
514 struct buf *obp = nbp->b_private;
515 struct cgd_softc *cs = getcgd_softc(obp->b_dev, &self);
516 struct dk_softc *dksc = &cs->sc_dksc;
517 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
518 daddr_t bn;
519
520 KDASSERT(cs);
521
522 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
523 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
524 obp, obp->b_bcount, obp->b_resid));
525 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
526 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
527 nbp->b_bcount));
528 if (nbp->b_error != 0) {
529 obp->b_error = nbp->b_error;
530 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
531 obp->b_error));
532 }
533
534 /* Perform the decryption if we are reading.
535 *
536 * Note: use the blocknumber from nbp, since it is what
537 * we used to encrypt the blocks.
538 */
539
540 if (nbp->b_flags & B_READ) {
541 bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
542 cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
543 bn, dg->dg_secsize, CGD_CIPHER_DECRYPT);
544 }
545
546 /* If we allocated memory, free it now... */
547 if (nbp->b_data != obp->b_data)
548 cgd_putdata(dksc, nbp->b_data);
549
550 putiobuf(nbp);
551
552 /* Request is complete for whatever reason */
553 obp->b_resid = 0;
554 if (obp->b_error != 0)
555 obp->b_resid = obp->b_bcount;
556
557 dk_done(dksc, obp);
558 device_release(self);
559
560 dk_start(dksc, NULL);
561 }
562
563 static int
564 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
565 {
566 struct cgd_softc *sc = device_private(dev);
567 struct dk_softc *dksc = &sc->sc_dksc;
568 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
569 size_t nbytes, blksize;
570 void *buf;
571 int error;
572
573 /*
574 * dk_dump gives us units of disklabel sectors. Everything
575 * else in cgd uses units of diskgeom sectors. These had
576 * better agree; otherwise we need to figure out how to convert
577 * between them.
578 */
579 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
580 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
581 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
582 blksize = dg->dg_secsize;
583
584 /*
585 * Compute the number of bytes in this request, which dk_dump
586 * has `helpfully' converted to a number of blocks for us.
587 */
588 nbytes = nblk*blksize;
589
590 /* Try to acquire a buffer to store the ciphertext. */
591 buf = cgd_getdata(dksc, nbytes);
592 if (buf == NULL)
593 /* Out of memory: give up. */
594 return ENOMEM;
595
596 /* Encrypt the caller's data into the temporary buffer. */
597 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
598
599 /* Pass it on to the underlying disk device. */
600 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
601
602 /* Release the buffer. */
603 cgd_putdata(dksc, buf);
604
605 /* Return any error from the underlying disk device. */
606 return error;
607 }
608
609 /* XXX: we should probably put these into dksubr.c, mostly */
610 static int
611 cgdread(dev_t dev, struct uio *uio, int flags)
612 {
613 device_t self;
614 int error;
615 struct cgd_softc *cs;
616 struct dk_softc *dksc;
617
618 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
619 (unsigned long long)dev, uio, flags));
620 GETCGD_SOFTC(cs, dev, self);
621 dksc = &cs->sc_dksc;
622 if (!DK_ATTACHED(dksc)) {
623 device_release(self);
624 return ENXIO;
625 }
626 error = physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
627 device_release(self);
628 return error;
629 }
630
631 /* XXX: we should probably put these into dksubr.c, mostly */
632 static int
633 cgdwrite(dev_t dev, struct uio *uio, int flags)
634 {
635 device_t self;
636 int error;
637 struct cgd_softc *cs;
638 struct dk_softc *dksc;
639
640 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
641 GETCGD_SOFTC(cs, dev, self);
642 dksc = &cs->sc_dksc;
643 if (!DK_ATTACHED(dksc)) {
644 device_release(self);
645 return ENXIO;
646 }
647 error = physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
648 device_release(self);
649 return error;
650 }
651
652 static int
653 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
654 {
655 device_t self;
656 struct cgd_softc *cs;
657 struct dk_softc *dksc;
658 int part = DISKPART(dev);
659 int pmask = 1 << part;
660 int error = 0;
661
662 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
663 dev, cmd, data, flag, l));
664
665 switch (cmd) {
666 case CGDIOCGET:
667 return cgd_ioctl_get(dev, data, l);
668 case CGDIOCSET:
669 case CGDIOCCLR:
670 if ((flag & FWRITE) == 0)
671 return EBADF;
672 /* FALLTHROUGH */
673 default:
674 GETCGD_SOFTC(cs, dev, self);
675 dksc = &cs->sc_dksc;
676 break;
677 }
678
679 switch (cmd) {
680 case CGDIOCSET:
681 if (DK_ATTACHED(dksc))
682 error = EBUSY;
683 else
684 error = cgd_ioctl_set(cs, data, l);
685 break;
686 case CGDIOCCLR:
687 if (DK_BUSY(&cs->sc_dksc, pmask))
688 error = EBUSY;
689 else
690 error = cgd_ioctl_clr(cs, l);
691 break;
692 case DIOCCACHESYNC:
693 /*
694 * XXX Do we really need to care about having a writable
695 * file descriptor here?
696 */
697 if ((flag & FWRITE) == 0)
698 error = (EBADF);
699
700 /*
701 * We pass this call down to the underlying disk.
702 */
703 else
704 error = VOP_IOCTL(cs->sc_tvn, cmd, data, flag,
705 l->l_cred);
706 break;
707 case DIOCGSTRATEGY:
708 case DIOCSSTRATEGY:
709 if (!DK_ATTACHED(dksc)) {
710 error = ENOENT;
711 break;
712 }
713 /*FALLTHROUGH*/
714 default:
715 error = dk_ioctl(dksc, dev, cmd, data, flag, l);
716 break;
717 case CGDIOCGET:
718 KASSERT(0);
719 error = EINVAL;
720 break;
721 }
722 device_release(self);
723 return error;
724 }
725
726 static int
727 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
728 {
729 device_t self;
730 int error;
731 struct cgd_softc *cs;
732
733 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
734 dev, blkno, va, (unsigned long)size));
735 GETCGD_SOFTC(cs, dev, self);
736 error = dk_dump(&cs->sc_dksc, dev, blkno, va, size);
737 device_release(self);
738 return error;
739 }
740
741 /*
742 * XXXrcd:
743 * for now we hardcode the maximum key length.
744 */
745 #define MAX_KEYSIZE 1024
746
747 static const struct {
748 const char *n;
749 int v;
750 int d;
751 } encblkno[] = {
752 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
753 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
754 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
755 };
756
757 /* ARGSUSED */
758 static int
759 cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
760 {
761 struct cgd_ioctl *ci = data;
762 struct vnode *vp;
763 int ret;
764 size_t i;
765 size_t keybytes; /* key length in bytes */
766 const char *cp;
767 struct pathbuf *pb;
768 char *inbuf;
769 struct dk_softc *dksc = &cs->sc_dksc;
770
771 cp = ci->ci_disk;
772
773 ret = pathbuf_copyin(ci->ci_disk, &pb);
774 if (ret != 0) {
775 return ret;
776 }
777 ret = dk_lookup(pb, l, &vp);
778 pathbuf_destroy(pb);
779 if (ret != 0) {
780 return ret;
781 }
782
783 inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
784
785 if ((ret = cgdinit(cs, cp, vp, l)) != 0)
786 goto bail;
787
788 (void)memset(inbuf, 0, MAX_KEYSIZE);
789 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
790 if (ret)
791 goto bail;
792 cs->sc_cfuncs = cryptfuncs_find(inbuf);
793 if (!cs->sc_cfuncs) {
794 ret = EINVAL;
795 goto bail;
796 }
797
798 (void)memset(inbuf, 0, MAX_KEYSIZE);
799 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
800 if (ret)
801 goto bail;
802
803 for (i = 0; i < __arraycount(encblkno); i++)
804 if (strcmp(encblkno[i].n, inbuf) == 0)
805 break;
806
807 if (i == __arraycount(encblkno)) {
808 ret = EINVAL;
809 goto bail;
810 }
811
812 keybytes = ci->ci_keylen / 8 + 1;
813 if (keybytes > MAX_KEYSIZE) {
814 ret = EINVAL;
815 goto bail;
816 }
817
818 (void)memset(inbuf, 0, MAX_KEYSIZE);
819 ret = copyin(ci->ci_key, inbuf, keybytes);
820 if (ret)
821 goto bail;
822
823 cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
824 cs->sc_cdata.cf_mode = encblkno[i].v;
825 cs->sc_cdata.cf_keylen = ci->ci_keylen;
826 cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
827 &cs->sc_cdata.cf_blocksize);
828 if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
829 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
830 cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
831 cs->sc_cdata.cf_priv = NULL;
832 }
833
834 /*
835 * The blocksize is supposed to be in bytes. Unfortunately originally
836 * it was expressed in bits. For compatibility we maintain encblkno
837 * and encblkno8.
838 */
839 cs->sc_cdata.cf_blocksize /= encblkno[i].d;
840 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
841 if (!cs->sc_cdata.cf_priv) {
842 ret = EINVAL; /* XXX is this the right error? */
843 goto bail;
844 }
845 free(inbuf, M_TEMP);
846
847 bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
848
849 cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
850 cs->sc_data_used = 0;
851
852 /* Attach the disk. */
853 dk_attach(dksc);
854 disk_attach(&dksc->sc_dkdev);
855
856 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
857
858 /* Discover wedges on this disk. */
859 dkwedge_discover(&dksc->sc_dkdev);
860
861 return 0;
862
863 bail:
864 free(inbuf, M_TEMP);
865 (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
866 return ret;
867 }
868
869 /* ARGSUSED */
870 static int
871 cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
872 {
873 struct dk_softc *dksc = &cs->sc_dksc;
874
875 if (!DK_ATTACHED(dksc))
876 return ENXIO;
877
878 /* Delete all of our wedges. */
879 dkwedge_delall(&dksc->sc_dkdev);
880
881 /* Kill off any queued buffers. */
882 dk_drain(dksc);
883 bufq_free(dksc->sc_bufq);
884
885 (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
886 cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
887 free(cs->sc_tpath, M_DEVBUF);
888 free(cs->sc_data, M_DEVBUF);
889 cs->sc_data_used = 0;
890 dk_detach(dksc);
891 disk_detach(&dksc->sc_dkdev);
892
893 return 0;
894 }
895
896 static int
897 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
898 {
899 device_t self;
900 struct cgd_softc *cs = getcgd_softc(dev, &self);
901 struct cgd_user *cgu;
902 int unit;
903 struct dk_softc *dksc = &cs->sc_dksc;
904
905 unit = CGDUNIT(dev);
906 cgu = (struct cgd_user *)data;
907
908 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
909 dev, unit, data, l));
910
911 if (cgu->cgu_unit == -1)
912 cgu->cgu_unit = unit;
913
914 if (cgu->cgu_unit < 0) {
915 device_release(self);
916 return EINVAL; /* XXX: should this be ENXIO? */
917 }
918
919 /*
920 * XXX This appears to be redundant, given the initialization
921 * XXX when it was declared. Leave it for now, but don't
922 * XXX take an extra reference to the device!
923 */
924 cs = device_lookup_private(&cgd_cd, unit);
925 if (cs == NULL || !DK_ATTACHED(dksc)) {
926 cgu->cgu_dev = 0;
927 cgu->cgu_alg[0] = '\0';
928 cgu->cgu_blocksize = 0;
929 cgu->cgu_mode = 0;
930 cgu->cgu_keylen = 0;
931 }
932 else {
933 cgu->cgu_dev = cs->sc_tdev;
934 strlcpy(cgu->cgu_alg, cs->sc_cfuncs->cf_name,
935 sizeof(cgu->cgu_alg));
936 cgu->cgu_blocksize = cs->sc_cdata.cf_blocksize;
937 cgu->cgu_mode = cs->sc_cdata.cf_mode;
938 cgu->cgu_keylen = cs->sc_cdata.cf_keylen;
939 }
940 device_release(self);
941 return 0;
942 }
943
944 static int
945 cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
946 struct lwp *l)
947 {
948 struct disk_geom *dg;
949 int ret;
950 char *tmppath;
951 uint64_t psize;
952 unsigned secsize;
953 struct dk_softc *dksc = &cs->sc_dksc;
954
955 cs->sc_tvn = vp;
956 cs->sc_tpath = NULL;
957
958 tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
959 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
960 if (ret)
961 goto bail;
962 cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
963 memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
964
965 cs->sc_tdev = vp->v_rdev;
966
967 if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
968 goto bail;
969
970 if (psize == 0) {
971 ret = ENODEV;
972 goto bail;
973 }
974
975 /*
976 * XXX here we should probe the underlying device. If we
977 * are accessing a partition of type RAW_PART, then
978 * we should populate our initial geometry with the
979 * geometry that we discover from the device.
980 */
981 dg = &dksc->sc_dkdev.dk_geom;
982 memset(dg, 0, sizeof(*dg));
983 dg->dg_secperunit = psize;
984 dg->dg_secsize = secsize;
985 dg->dg_ntracks = 1;
986 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
987 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
988
989 bail:
990 free(tmppath, M_TEMP);
991 if (ret && cs->sc_tpath)
992 free(cs->sc_tpath, M_DEVBUF);
993 return ret;
994 }
995
996 /*
997 * Our generic cipher entry point. This takes care of the
998 * IV mode and passes off the work to the specific cipher.
999 * We implement here the IV method ``encrypted block
1000 * number''.
1001 *
1002 * For the encryption case, we accomplish this by setting
1003 * up a struct uio where the first iovec of the source is
1004 * the blocknumber and the first iovec of the dest is a
1005 * sink. We then call the cipher with an IV of zero, and
1006 * the right thing happens.
1007 *
1008 * For the decryption case, we use the same basic mechanism
1009 * for symmetry, but we encrypt the block number in the
1010 * first iovec.
1011 *
1012 * We mainly do this to avoid requiring the definition of
1013 * an ECB mode.
1014 *
1015 * XXXrcd: for now we rely on our own crypto framework defined
1016 * in dev/cgd_crypto.c. This will change when we
1017 * get a generic kernel crypto framework.
1018 */
1019
1020 static void
1021 blkno2blkno_buf(char *sbuf, daddr_t blkno)
1022 {
1023 int i;
1024
1025 /* Set up the blkno in blkno_buf, here we do not care much
1026 * about the final layout of the information as long as we
1027 * can guarantee that each sector will have a different IV
1028 * and that the endianness of the machine will not affect
1029 * the representation that we have chosen.
1030 *
1031 * We choose this representation, because it does not rely
1032 * on the size of buf (which is the blocksize of the cipher),
1033 * but allows daddr_t to grow without breaking existing
1034 * disks.
1035 *
1036 * Note that blkno2blkno_buf does not take a size as input,
1037 * and hence must be called on a pre-zeroed buffer of length
1038 * greater than or equal to sizeof(daddr_t).
1039 */
1040 for (i=0; i < sizeof(daddr_t); i++) {
1041 *sbuf++ = blkno & 0xff;
1042 blkno >>= 8;
1043 }
1044 }
1045
1046 static void
1047 cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
1048 size_t len, daddr_t blkno, size_t secsize, int dir)
1049 {
1050 char *dst = dstv;
1051 char *src = srcv;
1052 cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher;
1053 struct uio dstuio;
1054 struct uio srcuio;
1055 struct iovec dstiov[2];
1056 struct iovec srciov[2];
1057 size_t blocksize = cs->sc_cdata.cf_blocksize;
1058 size_t todo;
1059 char sink[CGD_MAXBLOCKSIZE];
1060 char zero_iv[CGD_MAXBLOCKSIZE];
1061 char blkno_buf[CGD_MAXBLOCKSIZE];
1062
1063 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1064
1065 DIAGCONDPANIC(len % blocksize != 0,
1066 ("cgd_cipher: len %% blocksize != 0"));
1067
1068 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1069 DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
1070 ("cgd_cipher: sizeof(daddr_t) > blocksize"));
1071
1072 memset(zero_iv, 0x0, blocksize);
1073
1074 dstuio.uio_iov = dstiov;
1075 dstuio.uio_iovcnt = 2;
1076
1077 srcuio.uio_iov = srciov;
1078 srcuio.uio_iovcnt = 2;
1079
1080 dstiov[0].iov_base = sink;
1081 dstiov[0].iov_len = blocksize;
1082 srciov[0].iov_base = blkno_buf;
1083 srciov[0].iov_len = blocksize;
1084
1085 for (; len > 0; len -= todo) {
1086 todo = MIN(len, secsize);
1087
1088 dstiov[1].iov_base = dst;
1089 srciov[1].iov_base = src;
1090 dstiov[1].iov_len = todo;
1091 srciov[1].iov_len = todo;
1092
1093 memset(blkno_buf, 0x0, blocksize);
1094 blkno2blkno_buf(blkno_buf, blkno);
1095 if (dir == CGD_CIPHER_DECRYPT) {
1096 dstuio.uio_iovcnt = 1;
1097 srcuio.uio_iovcnt = 1;
1098 IFDEBUG(CGDB_CRYPTO, hexprint("step 0: blkno_buf",
1099 blkno_buf, blocksize));
1100 cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio,
1101 zero_iv, CGD_CIPHER_ENCRYPT);
1102 memcpy(blkno_buf, sink, blocksize);
1103 dstuio.uio_iovcnt = 2;
1104 srcuio.uio_iovcnt = 2;
1105 }
1106
1107 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1108 blkno_buf, blocksize));
1109 cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, zero_iv, dir);
1110 IFDEBUG(CGDB_CRYPTO, hexprint("step 2: sink",
1111 sink, blocksize));
1112
1113 dst += todo;
1114 src += todo;
1115 blkno++;
1116 }
1117 }
1118
1119 #ifdef DEBUG
1120 static void
1121 hexprint(const char *start, void *buf, int len)
1122 {
1123 char *c = buf;
1124
1125 DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
1126 printf("%s: len=%06d 0x", start, len);
1127 while (len--)
1128 printf("%02x", (unsigned char) *c++);
1129 }
1130 #endif
1131
1132 MODULE(MODULE_CLASS_DRIVER, cgd, "dk_subr");
1133
1134 #ifdef _MODULE
1135 CFDRIVER_DECL(cgd, DV_DISK, NULL);
1136
1137 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1138 #endif
1139
1140 static int
1141 cgd_modcmd(modcmd_t cmd, void *arg)
1142 {
1143 int error = 0;
1144
1145 switch (cmd) {
1146 case MODULE_CMD_INIT:
1147 #ifdef _MODULE
1148 error = config_cfdriver_attach(&cgd_cd);
1149 if (error)
1150 break;
1151
1152 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1153 if (error) {
1154 config_cfdriver_detach(&cgd_cd);
1155 aprint_error("%s: unable to register cfattach for "
1156 "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1157 break;
1158 }
1159 /*
1160 * Attach the {b,c}devsw's
1161 */
1162 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1163 &cgd_cdevsw, &cgd_cmajor);
1164
1165 /*
1166 * If devsw_attach fails, remove from autoconf database
1167 */
1168 if (error) {
1169 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1170 config_cfdriver_detach(&cgd_cd);
1171 aprint_error("%s: unable to attach %s devsw, "
1172 "error %d", __func__, cgd_cd.cd_name, error);
1173 break;
1174 }
1175 #endif
1176 break;
1177
1178 case MODULE_CMD_FINI:
1179 #ifdef _MODULE
1180 /*
1181 * Remove {b,c}devsw's
1182 */
1183 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1184
1185 /*
1186 * Now remove device from autoconf database
1187 */
1188 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1189 if (error) {
1190 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1191 &cgd_cdevsw, &cgd_cmajor);
1192 aprint_error("%s: failed to detach %s cfattach, "
1193 "error %d\n", __func__, cgd_cd.cd_name, error);
1194 break;
1195 }
1196 error = config_cfdriver_detach(&cgd_cd);
1197 if (error) {
1198 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1199 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1200 &cgd_cdevsw, &cgd_cmajor);
1201 aprint_error("%s: failed to detach %s cfdriver, "
1202 "error %d\n", __func__, cgd_cd.cd_name, error);
1203 break;
1204 }
1205 #endif
1206 break;
1207
1208 case MODULE_CMD_STAT:
1209 error = ENOTTY;
1210 break;
1211 default:
1212 error = ENOTTY;
1213 break;
1214 }
1215
1216 return error;
1217 }
1218