Annotation of src/sys/dev/cgd.c, Revision 1.27.2.4
1.27.2.4! yamt 1: /* $NetBSD: cgd.c,v 1.27.2.3 2007/02/26 09:09:53 yamt Exp $ */
1.1 elric 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: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: #include <sys/cdefs.h>
1.27.2.4! yamt 40: __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.27.2.3 2007/02/26 09:09:53 yamt Exp $");
1.1 elric 41:
42: #include <sys/types.h>
43: #include <sys/param.h>
44: #include <sys/systm.h>
45: #include <sys/proc.h>
46: #include <sys/errno.h>
47: #include <sys/buf.h>
1.21 yamt 48: #include <sys/bufq.h>
1.1 elric 49: #include <sys/malloc.h>
50: #include <sys/pool.h>
51: #include <sys/ioctl.h>
52: #include <sys/device.h>
53: #include <sys/disk.h>
54: #include <sys/disklabel.h>
55: #include <sys/fcntl.h>
56: #include <sys/vnode.h>
57: #include <sys/lock.h>
58: #include <sys/conf.h>
59:
60: #include <dev/dkvar.h>
61: #include <dev/cgdvar.h>
62:
63: /* Entry Point Functions */
64:
65: void cgdattach(int);
66:
1.18 thorpej 67: static dev_type_open(cgdopen);
68: static dev_type_close(cgdclose);
69: static dev_type_read(cgdread);
70: static dev_type_write(cgdwrite);
71: static dev_type_ioctl(cgdioctl);
72: static dev_type_strategy(cgdstrategy);
73: static dev_type_dump(cgddump);
74: static dev_type_size(cgdsize);
1.1 elric 75:
76: const struct bdevsw cgd_bdevsw = {
77: cgdopen, cgdclose, cgdstrategy, cgdioctl,
78: cgddump, cgdsize, D_DISK
79: };
80:
81: const struct cdevsw cgd_cdevsw = {
82: cgdopen, cgdclose, cgdread, cgdwrite, cgdioctl,
1.4 jdolecek 83: nostop, notty, nopoll, nommap, nokqfilter, D_DISK
1.1 elric 84: };
85:
86: /* Internal Functions */
87:
1.16 elric 88: static int cgdstart(struct dk_softc *, struct buf *);
1.1 elric 89: static void cgdiodone(struct buf *);
90:
1.27.2.1 yamt 91: static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
92: static int cgd_ioctl_clr(struct cgd_softc *, void *, struct lwp *);
1.27 drochner 93: static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
1.27.2.1 yamt 94: struct lwp *);
1.27.2.4! yamt 95: static void cgd_cipher(struct cgd_softc *, void *, void *,
1.1 elric 96: size_t, daddr_t, size_t, int);
97:
98: /* Pseudo-disk Interface */
99:
100: static struct dk_intf the_dkintf = {
101: DTYPE_CGD,
102: "cgd",
103: cgdopen,
104: cgdclose,
105: cgdstrategy,
106: cgdstart,
107: };
108: static struct dk_intf *di = &the_dkintf;
109:
1.27.2.1 yamt 110: static struct dkdriver cgddkdriver = {
111: .d_strategy = cgdstrategy,
112: .d_minphys = minphys,
113: };
114:
1.1 elric 115: /* DIAGNOSTIC and DEBUG definitions */
116:
117: #if defined(CGDDEBUG) && !defined(DEBUG)
118: #define DEBUG
119: #endif
120:
121: #ifdef DEBUG
122: int cgddebug = 0;
123:
124: #define CGDB_FOLLOW 0x1
125: #define CGDB_IO 0x2
126: #define CGDB_CRYPTO 0x4
127:
128: #define IFDEBUG(x,y) if (cgddebug & (x)) y
129: #define DPRINTF(x,y) IFDEBUG(x, printf y)
130: #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
131:
1.26 drochner 132: static void hexprint(const char *, void *, int);
1.1 elric 133:
134: #else
135: #define IFDEBUG(x,y)
136: #define DPRINTF(x,y)
137: #define DPRINTF_FOLLOW(y)
138: #endif
139:
140: #ifdef DIAGNOSTIC
1.22 perry 141: #define DIAGPANIC(x) panic x
1.1 elric 142: #define DIAGCONDPANIC(x,y) if (x) panic y
143: #else
144: #define DIAGPANIC(x)
145: #define DIAGCONDPANIC(x,y)
146: #endif
147:
148: /* Global variables */
149:
150: struct cgd_softc *cgd_softc;
151: int numcgd = 0;
152:
153: /* Utility Functions */
154:
155: #define CGDUNIT(x) DISKUNIT(x)
156: #define GETCGD_SOFTC(_cs, x) if (!((_cs) = getcgd_softc(x))) return ENXIO
157:
158: static struct cgd_softc *
159: getcgd_softc(dev_t dev)
160: {
161: int unit = CGDUNIT(dev);
162:
163: DPRINTF_FOLLOW(("getcgd_softc(0x%x): unit = %d\n", dev, unit));
164: if (unit >= numcgd)
165: return NULL;
166: return &cgd_softc[unit];
167: }
168:
169: /* The code */
170:
171: static void
172: cgdsoftc_init(struct cgd_softc *cs, int num)
173: {
1.25 xtraeme 174: char sbuf[DK_XNAME_SIZE];
1.1 elric 175:
176: memset(cs, 0x0, sizeof(*cs));
1.25 xtraeme 177: snprintf(sbuf, DK_XNAME_SIZE, "cgd%d", num);
1.16 elric 178: simple_lock_init(&cs->sc_slock);
1.25 xtraeme 179: dk_sc_init(&cs->sc_dksc, cs, sbuf);
1.27.2.1 yamt 180: cs->sc_dksc.sc_dkdev.dk_driver = &cgddkdriver;
181: pseudo_disk_init(&cs->sc_dksc.sc_dkdev);
1.1 elric 182: }
183:
184: void
185: cgdattach(int num)
186: {
187: int i;
188:
189: DPRINTF_FOLLOW(("cgdattach(%d)\n", num));
190: if (num <= 0) {
191: DIAGPANIC(("cgdattach: count <= 0"));
192: return;
193: }
194:
1.10 agc 195: cgd_softc = (void *)malloc(num * sizeof(*cgd_softc), M_DEVBUF, M_NOWAIT);
196: if (!cgd_softc) {
1.1 elric 197: printf("WARNING: unable to malloc(9) memory for crypt disks\n");
198: DIAGPANIC(("cgdattach: cannot malloc(9) enough memory"));
199: return;
200: }
201:
202: numcgd = num;
203: for (i=0; i<num; i++)
204: cgdsoftc_init(&cgd_softc[i], i);
205: }
206:
1.18 thorpej 207: static int
1.27.2.1 yamt 208: cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
1.1 elric 209: {
210: struct cgd_softc *cs;
211:
212: DPRINTF_FOLLOW(("cgdopen(%d, %d)\n", dev, flags));
213: GETCGD_SOFTC(cs, dev);
1.27.2.1 yamt 214: return dk_open(di, &cs->sc_dksc, dev, flags, fmt, l);
1.1 elric 215: }
216:
1.18 thorpej 217: static int
1.27.2.1 yamt 218: cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
1.1 elric 219: {
220: struct cgd_softc *cs;
221:
222: DPRINTF_FOLLOW(("cgdclose(%d, %d)\n", dev, flags));
223: GETCGD_SOFTC(cs, dev);
1.27.2.1 yamt 224: return dk_close(di, &cs->sc_dksc, dev, flags, fmt, l);
1.1 elric 225: }
226:
1.18 thorpej 227: static void
1.1 elric 228: cgdstrategy(struct buf *bp)
229: {
230: struct cgd_softc *cs = getcgd_softc(bp->b_dev);
231:
232: DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
233: (long)bp->b_bcount));
234: /* XXXrcd: Should we test for (cs != NULL)? */
235: dk_strategy(di, &cs->sc_dksc, bp);
236: return;
237: }
238:
1.18 thorpej 239: static int
1.1 elric 240: cgdsize(dev_t dev)
241: {
242: struct cgd_softc *cs = getcgd_softc(dev);
243:
244: DPRINTF_FOLLOW(("cgdsize(%d)\n", dev));
245: if (!cs)
246: return -1;
247: return dk_size(di, &cs->sc_dksc, dev);
248: }
249:
1.16 elric 250: /*
251: * cgd_{get,put}data are functions that deal with getting a buffer
252: * for the new encrypted data. We have a buffer per device so that
253: * we can ensure that we can always have a transaction in flight.
254: * We use this buffer first so that we have one less piece of
255: * malloc'ed data at any given point.
256: */
257:
258: static void *
259: cgd_getdata(struct dk_softc *dksc, unsigned long size)
260: {
261: struct cgd_softc *cs =dksc->sc_osc;
1.27.2.4! yamt 262: void * data = NULL;
1.16 elric 263:
264: simple_lock(&cs->sc_slock);
265: if (cs->sc_data_used == 0) {
266: cs->sc_data_used = 1;
267: data = cs->sc_data;
268: }
269: simple_unlock(&cs->sc_slock);
270:
271: if (data)
272: return data;
273:
274: return malloc(size, M_DEVBUF, M_NOWAIT);
275: }
276:
1.1 elric 277: static void
1.27.2.4! yamt 278: cgd_putdata(struct dk_softc *dksc, void *data)
1.16 elric 279: {
280: struct cgd_softc *cs =dksc->sc_osc;
281:
282: if (data == cs->sc_data) {
283: simple_lock(&cs->sc_slock);
284: cs->sc_data_used = 0;
285: simple_unlock(&cs->sc_slock);
286: } else {
287: free(data, M_DEVBUF);
288: }
289: }
290:
291: static int
1.1 elric 292: cgdstart(struct dk_softc *dksc, struct buf *bp)
293: {
294: struct cgd_softc *cs = dksc->sc_osc;
1.17 dbj 295: struct buf *nbp;
1.27.2.4! yamt 296: void * addr;
! 297: void * newaddr;
1.1 elric 298: daddr_t bn;
299:
300: DPRINTF_FOLLOW(("cgdstart(%p, %p)\n", dksc, bp));
301: disk_busy(&dksc->sc_dkdev); /* XXX: put in dksubr.c */
302:
1.27.2.1 yamt 303: bn = bp->b_rawblkno;
1.1 elric 304:
305: /*
1.16 elric 306: * We attempt to allocate all of our resources up front, so that
307: * we can fail quickly if they are unavailable.
308: */
1.22 perry 309:
1.27.2.1 yamt 310: nbp = getiobuf_nowait();
1.17 dbj 311: if (nbp == NULL) {
1.16 elric 312: disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
313: return -1;
314: }
315:
316: /*
1.1 elric 317: * If we are writing, then we need to encrypt the outgoing
1.16 elric 318: * block into a new block of memory. If we fail, then we
319: * return an error and let the dksubr framework deal with it.
1.1 elric 320: */
321: newaddr = addr = bp->b_data;
322: if ((bp->b_flags & B_READ) == 0) {
1.16 elric 323: newaddr = cgd_getdata(dksc, bp->b_bcount);
324: if (!newaddr) {
1.27.2.1 yamt 325: putiobuf(nbp);
1.16 elric 326: disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
327: return -1;
328: }
1.1 elric 329: cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
330: DEV_BSIZE, CGD_CIPHER_ENCRYPT);
331: }
332:
1.17 dbj 333: nbp->b_data = newaddr;
334: nbp->b_flags = bp->b_flags | B_CALL;
335: nbp->b_iodone = cgdiodone;
336: nbp->b_proc = bp->b_proc;
337: nbp->b_blkno = bn;
338: nbp->b_vp = cs->sc_tvn;
339: nbp->b_bcount = bp->b_bcount;
340: nbp->b_private = bp;
341:
342: BIO_COPYPRIO(nbp, bp);
343:
344: if ((nbp->b_flags & B_READ) == 0) {
345: V_INCR_NUMOUTPUT(nbp->b_vp);
346: }
347: VOP_STRATEGY(cs->sc_tvn, nbp);
1.16 elric 348: return 0;
1.1 elric 349: }
350:
1.17 dbj 351: /* expected to be called at splbio() */
1.18 thorpej 352: static void
1.17 dbj 353: cgdiodone(struct buf *nbp)
1.1 elric 354: {
1.17 dbj 355: struct buf *obp = nbp->b_private;
356: struct cgd_softc *cs = getcgd_softc(obp->b_dev);
1.1 elric 357: struct dk_softc *dksc = &cs->sc_dksc;
1.22 perry 358:
1.17 dbj 359: KDASSERT(cs);
1.1 elric 360:
1.17 dbj 361: DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
1.20 yamt 362: DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
1.1 elric 363: obp, obp->b_bcount, obp->b_resid));
1.20 yamt 364: DPRINTF(CGDB_IO, (" dev 0x%x, nbp %p bn %" PRId64 " addr %p bcnt %d\n",
1.17 dbj 365: nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
366: nbp->b_bcount));
1.27.2.4! yamt 367: if (nbp->b_error != 0) {
! 368: obp->b_error = nbp->b_error;
1.1 elric 369: printf("%s: error %d\n", dksc->sc_xname, obp->b_error);
370: }
371:
1.16 elric 372: /* Perform the decryption if we are reading.
1.1 elric 373: *
374: * Note: use the blocknumber from nbp, since it is what
375: * we used to encrypt the blocks.
376: */
377:
1.16 elric 378: if (nbp->b_flags & B_READ)
1.1 elric 379: cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
380: nbp->b_blkno, DEV_BSIZE, CGD_CIPHER_DECRYPT);
381:
1.16 elric 382: /* If we allocated memory, free it now... */
1.1 elric 383: if (nbp->b_data != obp->b_data)
1.16 elric 384: cgd_putdata(dksc, nbp->b_data);
1.1 elric 385:
1.27.2.1 yamt 386: putiobuf(nbp);
1.1 elric 387:
388: /* Request is complete for whatever reason */
389: obp->b_resid = 0;
1.27.2.4! yamt 390: if (obp->b_error != 0)
1.1 elric 391: obp->b_resid = obp->b_bcount;
1.5 mrg 392: disk_unbusy(&dksc->sc_dkdev, obp->b_bcount - obp->b_resid,
393: (obp->b_flags & B_READ));
1.1 elric 394: biodone(obp);
1.16 elric 395: dk_iodone(di, dksc);
1.1 elric 396: }
397:
398: /* XXX: we should probably put these into dksubr.c, mostly */
1.18 thorpej 399: static int
1.1 elric 400: cgdread(dev_t dev, struct uio *uio, int flags)
401: {
402: struct cgd_softc *cs;
403: struct dk_softc *dksc;
404:
405: DPRINTF_FOLLOW(("cgdread(%d, %p, %d)\n", dev, uio, flags));
406: GETCGD_SOFTC(cs, dev);
407: dksc = &cs->sc_dksc;
408: if ((dksc->sc_flags & DKF_INITED) == 0)
409: return ENXIO;
410: return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
411: }
412:
413: /* XXX: we should probably put these into dksubr.c, mostly */
1.18 thorpej 414: static int
1.1 elric 415: cgdwrite(dev_t dev, struct uio *uio, int flags)
416: {
417: struct cgd_softc *cs;
418: struct dk_softc *dksc;
419:
420: DPRINTF_FOLLOW(("cgdwrite(%d, %p, %d)\n", dev, uio, flags));
421: GETCGD_SOFTC(cs, dev);
422: dksc = &cs->sc_dksc;
423: if ((dksc->sc_flags & DKF_INITED) == 0)
424: return ENXIO;
425: return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
426: }
427:
1.18 thorpej 428: static int
1.27.2.4! yamt 429: cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.1 elric 430: {
431: struct cgd_softc *cs;
432: struct dk_softc *dksc;
1.27.2.1 yamt 433: struct disk *dk;
1.1 elric 434: int ret;
435: int part = DISKPART(dev);
436: int pmask = 1 << part;
437:
438: DPRINTF_FOLLOW(("cgdioctl(%d, %ld, %p, %d, %p)\n",
1.27.2.1 yamt 439: dev, cmd, data, flag, l));
1.1 elric 440: GETCGD_SOFTC(cs, dev);
441: dksc = &cs->sc_dksc;
1.27.2.1 yamt 442: dk = &dksc->sc_dkdev;
1.1 elric 443: switch (cmd) {
444: case CGDIOCSET:
445: case CGDIOCCLR:
446: if ((flag & FWRITE) == 0)
447: return EBADF;
448: }
449:
450: switch (cmd) {
451: case CGDIOCSET:
452: if (dksc->sc_flags & DKF_INITED)
453: ret = EBUSY;
454: else
1.27.2.1 yamt 455: ret = cgd_ioctl_set(cs, data, l);
1.1 elric 456: break;
457: case CGDIOCCLR:
458: if (!(dksc->sc_flags & DKF_INITED)) {
459: ret = ENXIO;
460: break;
461: }
462: if (DK_BUSY(&cs->sc_dksc, pmask)) {
463: ret = EBUSY;
464: break;
465: }
1.27.2.1 yamt 466: ret = cgd_ioctl_clr(cs, data, l);
1.1 elric 467: break;
468: default:
1.27.2.1 yamt 469: ret = dk_ioctl(di, dksc, dev, cmd, data, flag, l);
1.1 elric 470: break;
471: }
472:
473: return ret;
474: }
475:
1.18 thorpej 476: static int
1.27.2.4! yamt 477: cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
1.1 elric 478: {
479: struct cgd_softc *cs;
480:
1.6 bouyer 481: DPRINTF_FOLLOW(("cgddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va,
1.2 elric 482: (unsigned long)size));
1.1 elric 483: GETCGD_SOFTC(cs, dev);
484: return dk_dump(di, &cs->sc_dksc, dev, blkno, va, size);
485: }
486:
487: /*
488: * XXXrcd:
489: * for now we hardcode the maximum key length.
490: */
491: #define MAX_KEYSIZE 1024
492:
493: /* ARGSUSED */
494: static int
1.27.2.1 yamt 495: cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
1.1 elric 496: {
497: struct cgd_ioctl *ci = data;
498: struct vnode *vp;
499: int ret;
1.27.2.3 yamt 500: size_t keybytes; /* key length in bytes */
1.27 drochner 501: const char *cp;
1.27.2.1 yamt 502: char *inbuf;
1.1 elric 503:
504: cp = ci->ci_disk;
1.27.2.4! yamt 505: if ((ret = dk_lookup(cp, l, &vp, UIO_USERSPACE)) != 0)
1.1 elric 506: return ret;
507:
1.27.2.1 yamt 508: inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
509:
510: if ((ret = cgdinit(cs, cp, vp, l)) != 0)
1.1 elric 511: goto bail;
512:
1.27.2.1 yamt 513: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.1 elric 514: ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
515: if (ret)
516: goto bail;
517: cs->sc_cfuncs = cryptfuncs_find(inbuf);
518: if (!cs->sc_cfuncs) {
519: ret = EINVAL;
520: goto bail;
521: }
522:
523: /* right now we only support encblkno, so hard-code it */
1.27.2.3 yamt 524: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.27.2.1 yamt 525: ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
1.1 elric 526: if (ret)
527: goto bail;
528: if (strcmp("encblkno", inbuf)) {
529: ret = EINVAL;
530: goto bail;
531: }
532:
1.15 dan 533: keybytes = ci->ci_keylen / 8 + 1;
534: if (keybytes > MAX_KEYSIZE) {
1.1 elric 535: ret = EINVAL;
536: goto bail;
537: }
1.27.2.1 yamt 538: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.15 dan 539: ret = copyin(ci->ci_key, inbuf, keybytes);
1.1 elric 540: if (ret)
541: goto bail;
542:
543: cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
544: cs->sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO;
545: cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
546: &cs->sc_cdata.cf_blocksize);
1.27.2.1 yamt 547: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.1 elric 548: if (!cs->sc_cdata.cf_priv) {
549: printf("cgd: unable to initialize cipher\n");
550: ret = EINVAL; /* XXX is this the right error? */
551: goto bail;
552: }
1.27.2.1 yamt 553: free(inbuf, M_TEMP);
1.1 elric 554:
1.27.2.1 yamt 555: bufq_alloc(&cs->sc_dksc.sc_bufq, "fcfs", 0);
1.16 elric 556:
557: cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
558: cs->sc_data_used = 0;
559:
1.1 elric 560: cs->sc_dksc.sc_flags |= DKF_INITED;
561:
562: /* Attach the disk. */
1.27.2.1 yamt 563: pseudo_disk_attach(&cs->sc_dksc.sc_dkdev);
1.1 elric 564:
565: /* Try and read the disklabel. */
566: dk_getdisklabel(di, &cs->sc_dksc, 0 /* XXX ? */);
567:
1.27.2.1 yamt 568: /* Discover wedges on this disk. */
569: dkwedge_discover(&cs->sc_dksc.sc_dkdev);
570:
1.1 elric 571: return 0;
572:
573: bail:
1.27.2.1 yamt 574: free(inbuf, M_TEMP);
1.27.2.2 yamt 575: (void)vn_close(vp, FREAD|FWRITE, l->l_cred, l);
1.1 elric 576: return ret;
577: }
578:
579: /* ARGSUSED */
580: static int
1.27.2.1 yamt 581: cgd_ioctl_clr(struct cgd_softc *cs, void *data, struct lwp *l)
1.1 elric 582: {
1.16 elric 583: int s;
584:
1.27.2.1 yamt 585: /* Delete all of our wedges. */
586: dkwedge_delall(&cs->sc_dksc.sc_dkdev);
587:
1.16 elric 588: /* Kill off any queued buffers. */
589: s = splbio();
1.27.2.1 yamt 590: bufq_drain(cs->sc_dksc.sc_bufq);
1.16 elric 591: splx(s);
1.27.2.1 yamt 592: bufq_free(cs->sc_dksc.sc_bufq);
1.1 elric 593:
1.27.2.2 yamt 594: (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred, l);
1.1 elric 595: cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
596: free(cs->sc_tpath, M_DEVBUF);
1.16 elric 597: free(cs->sc_data, M_DEVBUF);
598: cs->sc_data_used = 0;
1.1 elric 599: cs->sc_dksc.sc_flags &= ~DKF_INITED;
1.27.2.1 yamt 600: pseudo_disk_detach(&cs->sc_dksc.sc_dkdev);
1.1 elric 601:
602: return 0;
603: }
604:
605: static int
1.27 drochner 606: cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
1.27.2.1 yamt 607: struct lwp *l)
1.1 elric 608: {
609: struct dk_geom *pdg;
610: struct partinfo dpart;
611: struct vattr va;
612: size_t size;
613: int maxsecsize = 0;
614: int ret;
1.27.2.1 yamt 615: char *tmppath;
1.1 elric 616:
617: cs->sc_dksc.sc_size = 0;
618: cs->sc_tvn = vp;
1.27.2.1 yamt 619: cs->sc_tpath = NULL;
1.1 elric 620:
1.27.2.1 yamt 621: tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1.1 elric 622: ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
623: if (ret)
624: goto bail;
625: cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
626: memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
627:
1.27.2.2 yamt 628: if ((ret = VOP_GETATTR(vp, &va, l->l_cred, l)) != 0)
1.1 elric 629: goto bail;
630:
631: cs->sc_tdev = va.va_rdev;
632:
1.27.2.2 yamt 633: ret = VOP_IOCTL(vp, DIOCGPART, &dpart, FREAD, l->l_cred, l);
1.1 elric 634: if (ret)
635: goto bail;
636:
637: maxsecsize =
638: ((dpart.disklab->d_secsize > maxsecsize) ?
639: dpart.disklab->d_secsize : maxsecsize);
640: size = dpart.part->p_size;
641:
642: if (!size) {
643: ret = ENODEV;
644: goto bail;
645: }
646:
647: cs->sc_dksc.sc_size = size;
648:
649: /*
650: * XXX here we should probe the underlying device. If we
651: * are accessing a partition of type RAW_PART, then
652: * we should populate our initial geometry with the
653: * geometry that we discover from the device.
654: */
655: pdg = &cs->sc_dksc.sc_geom;
656: pdg->pdg_secsize = DEV_BSIZE;
657: pdg->pdg_ntracks = 1;
658: pdg->pdg_nsectors = 1024 * (1024 / pdg->pdg_secsize);
659: pdg->pdg_ncylinders = cs->sc_dksc.sc_size / pdg->pdg_nsectors;
660:
661: bail:
1.27.2.1 yamt 662: free(tmppath, M_TEMP);
1.1 elric 663: if (ret && cs->sc_tpath)
664: free(cs->sc_tpath, M_DEVBUF);
665: return ret;
666: }
667:
668: /*
669: * Our generic cipher entry point. This takes care of the
670: * IV mode and passes off the work to the specific cipher.
671: * We implement here the IV method ``encrypted block
672: * number''.
1.22 perry 673: *
1.1 elric 674: * For the encryption case, we accomplish this by setting
675: * up a struct uio where the first iovec of the source is
676: * the blocknumber and the first iovec of the dest is a
677: * sink. We then call the cipher with an IV of zero, and
678: * the right thing happens.
1.22 perry 679: *
1.1 elric 680: * For the decryption case, we use the same basic mechanism
681: * for symmetry, but we encrypt the block number in the
682: * first iovec.
683: *
684: * We mainly do this to avoid requiring the definition of
685: * an ECB mode.
686: *
687: * XXXrcd: for now we rely on our own crypto framework defined
688: * in dev/cgd_crypto.c. This will change when we
689: * get a generic kernel crypto framework.
690: */
691:
692: static void
1.25 xtraeme 693: blkno2blkno_buf(char *sbuf, daddr_t blkno)
1.1 elric 694: {
695: int i;
696:
697: /* Set up the blkno in blkno_buf, here we do not care much
698: * about the final layout of the information as long as we
699: * can guarantee that each sector will have a different IV
700: * and that the endianness of the machine will not affect
701: * the representation that we have chosen.
702: *
703: * We choose this representation, because it does not rely
704: * on the size of buf (which is the blocksize of the cipher),
705: * but allows daddr_t to grow without breaking existing
706: * disks.
707: *
708: * Note that blkno2blkno_buf does not take a size as input,
709: * and hence must be called on a pre-zeroed buffer of length
710: * greater than or equal to sizeof(daddr_t).
711: */
712: for (i=0; i < sizeof(daddr_t); i++) {
1.25 xtraeme 713: *sbuf++ = blkno & 0xff;
1.1 elric 714: blkno >>= 8;
715: }
716: }
717:
718: static void
1.27.2.4! yamt 719: cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
! 720: size_t len, daddr_t blkno, size_t secsize, int dir)
1.1 elric 721: {
1.27.2.4! yamt 722: char *dst = dstv;
! 723: char *src = srcv;
1.1 elric 724: cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher;
725: struct uio dstuio;
726: struct uio srcuio;
727: struct iovec dstiov[2];
728: struct iovec srciov[2];
1.27.2.2 yamt 729: size_t blocksize = cs->sc_cdata.cf_blocksize;
1.1 elric 730: char sink[blocksize];
731: char zero_iv[blocksize];
732: char blkno_buf[blocksize];
733:
734: DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
735:
1.22 perry 736: DIAGCONDPANIC(len % blocksize != 0,
1.1 elric 737: ("cgd_cipher: len %% blocksize != 0"));
738:
739: /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
740: DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
741: ("cgd_cipher: sizeof(daddr_t) > blocksize"));
742:
743: memset(zero_iv, 0x0, sizeof(zero_iv));
744:
745: dstuio.uio_iov = dstiov;
746: dstuio.uio_iovcnt = 2;
747:
748: srcuio.uio_iov = srciov;
749: srcuio.uio_iovcnt = 2;
750:
751: dstiov[0].iov_base = sink;
752: dstiov[0].iov_len = blocksize;
753: srciov[0].iov_base = blkno_buf;
754: srciov[0].iov_len = blocksize;
755: dstiov[1].iov_len = secsize;
756: srciov[1].iov_len = secsize;
757:
758: for (; len > 0; len -= secsize) {
759: dstiov[1].iov_base = dst;
760: srciov[1].iov_base = src;
761:
762: memset(blkno_buf, 0x0, sizeof(blkno_buf));
763: blkno2blkno_buf(blkno_buf, blkno);
764: if (dir == CGD_CIPHER_DECRYPT) {
765: dstuio.uio_iovcnt = 1;
766: srcuio.uio_iovcnt = 1;
767: IFDEBUG(CGDB_CRYPTO, hexprint("step 0: blkno_buf",
768: blkno_buf, sizeof(blkno_buf)));
769: cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio,
770: zero_iv, CGD_CIPHER_ENCRYPT);
771: memcpy(blkno_buf, sink, blocksize);
772: dstuio.uio_iovcnt = 2;
773: srcuio.uio_iovcnt = 2;
774: }
775:
776: IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
777: blkno_buf, sizeof(blkno_buf)));
778: cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, zero_iv, dir);
779: IFDEBUG(CGDB_CRYPTO, hexprint("step 2: sink",
780: sink, sizeof(sink)));
781:
782: dst += secsize;
783: src += secsize;
784: blkno++;
785: }
786: }
787:
788: #ifdef DEBUG
789: static void
1.26 drochner 790: hexprint(const char *start, void *buf, int len)
1.1 elric 791: {
792: char *c = buf;
793:
794: DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
795: printf("%s: len=%06d 0x", start, len);
796: while (len--)
1.27.2.3 yamt 797: printf("%02x", (unsigned char) *c++);
1.1 elric 798: }
799: #endif
CVSweb <webmaster@jp.NetBSD.org>