Annotation of src/sys/dev/cgd.c, Revision 1.44.2.1
1.44.2.1! ad 1: /* $NetBSD: cgd.c,v 1.44 2007/03/04 06:01:41 christos 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.44.2.1! ad 40: __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.44 2007/03/04 06:01:41 christos 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.32 christos 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.32 christos 94: struct lwp *);
1.44 christos 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.29 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.29 yamt 180: cs->sc_dksc.sc_dkdev.dk_driver = &cgddkdriver;
1.28 yamt 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.32 christos 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.32 christos 214: return dk_open(di, &cs->sc_dksc, dev, flags, fmt, l);
1.1 elric 215: }
216:
1.18 thorpej 217: static int
1.32 christos 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.32 christos 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.44 christos 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.44 christos 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.44 christos 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.31 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.33 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.33 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.1 elric 367: if (nbp->b_flags & B_ERROR) {
368: obp->b_flags |= B_ERROR;
369: obp->b_error = nbp->b_error ? nbp->b_error : EIO;
370:
371: printf("%s: error %d\n", dksc->sc_xname, obp->b_error);
372: }
373:
1.16 elric 374: /* Perform the decryption if we are reading.
1.1 elric 375: *
376: * Note: use the blocknumber from nbp, since it is what
377: * we used to encrypt the blocks.
378: */
379:
1.16 elric 380: if (nbp->b_flags & B_READ)
1.1 elric 381: cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
382: nbp->b_blkno, DEV_BSIZE, CGD_CIPHER_DECRYPT);
383:
1.16 elric 384: /* If we allocated memory, free it now... */
1.1 elric 385: if (nbp->b_data != obp->b_data)
1.16 elric 386: cgd_putdata(dksc, nbp->b_data);
1.1 elric 387:
1.33 yamt 388: putiobuf(nbp);
1.1 elric 389:
390: /* Request is complete for whatever reason */
391: obp->b_resid = 0;
392: if (obp->b_flags & B_ERROR)
393: obp->b_resid = obp->b_bcount;
1.5 mrg 394: disk_unbusy(&dksc->sc_dkdev, obp->b_bcount - obp->b_resid,
395: (obp->b_flags & B_READ));
1.44.2.1! ad 396: biodone(obp, obp->b_error, obp->b_resid);
1.16 elric 397: dk_iodone(di, dksc);
1.1 elric 398: }
399:
400: /* XXX: we should probably put these into dksubr.c, mostly */
1.18 thorpej 401: static int
1.40 christos 402: cgdread(dev_t dev, struct uio *uio, int flags)
1.1 elric 403: {
404: struct cgd_softc *cs;
405: struct dk_softc *dksc;
406:
407: DPRINTF_FOLLOW(("cgdread(%d, %p, %d)\n", dev, uio, flags));
408: GETCGD_SOFTC(cs, dev);
409: dksc = &cs->sc_dksc;
410: if ((dksc->sc_flags & DKF_INITED) == 0)
411: return ENXIO;
412: return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
413: }
414:
415: /* XXX: we should probably put these into dksubr.c, mostly */
1.18 thorpej 416: static int
1.40 christos 417: cgdwrite(dev_t dev, struct uio *uio, int flags)
1.1 elric 418: {
419: struct cgd_softc *cs;
420: struct dk_softc *dksc;
421:
422: DPRINTF_FOLLOW(("cgdwrite(%d, %p, %d)\n", dev, uio, flags));
423: GETCGD_SOFTC(cs, dev);
424: dksc = &cs->sc_dksc;
425: if ((dksc->sc_flags & DKF_INITED) == 0)
426: return ENXIO;
427: return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
428: }
429:
1.18 thorpej 430: static int
1.44 christos 431: cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.1 elric 432: {
433: struct cgd_softc *cs;
434: struct dk_softc *dksc;
1.29 yamt 435: struct disk *dk;
1.1 elric 436: int ret;
437: int part = DISKPART(dev);
438: int pmask = 1 << part;
439:
440: DPRINTF_FOLLOW(("cgdioctl(%d, %ld, %p, %d, %p)\n",
1.32 christos 441: dev, cmd, data, flag, l));
1.1 elric 442: GETCGD_SOFTC(cs, dev);
443: dksc = &cs->sc_dksc;
1.29 yamt 444: dk = &dksc->sc_dkdev;
1.1 elric 445: switch (cmd) {
446: case CGDIOCSET:
447: case CGDIOCCLR:
448: if ((flag & FWRITE) == 0)
449: return EBADF;
450: }
451:
452: switch (cmd) {
453: case CGDIOCSET:
454: if (dksc->sc_flags & DKF_INITED)
455: ret = EBUSY;
456: else
1.32 christos 457: ret = cgd_ioctl_set(cs, data, l);
1.1 elric 458: break;
459: case CGDIOCCLR:
460: if (!(dksc->sc_flags & DKF_INITED)) {
461: ret = ENXIO;
462: break;
463: }
464: if (DK_BUSY(&cs->sc_dksc, pmask)) {
465: ret = EBUSY;
466: break;
467: }
1.32 christos 468: ret = cgd_ioctl_clr(cs, data, l);
1.1 elric 469: break;
470: default:
1.32 christos 471: ret = dk_ioctl(di, dksc, dev, cmd, data, flag, l);
1.1 elric 472: break;
473: }
474:
475: return ret;
476: }
477:
1.18 thorpej 478: static int
1.44 christos 479: cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
1.1 elric 480: {
481: struct cgd_softc *cs;
482:
1.6 bouyer 483: DPRINTF_FOLLOW(("cgddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va,
1.2 elric 484: (unsigned long)size));
1.1 elric 485: GETCGD_SOFTC(cs, dev);
486: return dk_dump(di, &cs->sc_dksc, dev, blkno, va, size);
487: }
488:
489: /*
490: * XXXrcd:
491: * for now we hardcode the maximum key length.
492: */
493: #define MAX_KEYSIZE 1024
494:
495: /* ARGSUSED */
496: static int
1.32 christos 497: cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
1.1 elric 498: {
499: struct cgd_ioctl *ci = data;
500: struct vnode *vp;
501: int ret;
1.43 cbiere 502: size_t keybytes; /* key length in bytes */
1.27 drochner 503: const char *cp;
1.36 christos 504: char *inbuf;
1.1 elric 505:
506: cp = ci->ci_disk;
1.32 christos 507: if ((ret = dk_lookup(cp, l, &vp)) != 0)
1.1 elric 508: return ret;
509:
1.36 christos 510: inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
511:
1.32 christos 512: if ((ret = cgdinit(cs, cp, vp, l)) != 0)
1.1 elric 513: goto bail;
514:
1.36 christos 515: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.1 elric 516: ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
517: if (ret)
518: goto bail;
519: cs->sc_cfuncs = cryptfuncs_find(inbuf);
520: if (!cs->sc_cfuncs) {
521: ret = EINVAL;
522: goto bail;
523: }
524:
525: /* right now we only support encblkno, so hard-code it */
1.43 cbiere 526: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.36 christos 527: ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
1.1 elric 528: if (ret)
529: goto bail;
530: if (strcmp("encblkno", inbuf)) {
531: ret = EINVAL;
532: goto bail;
533: }
534:
1.15 dan 535: keybytes = ci->ci_keylen / 8 + 1;
536: if (keybytes > MAX_KEYSIZE) {
1.1 elric 537: ret = EINVAL;
538: goto bail;
539: }
1.36 christos 540: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.15 dan 541: ret = copyin(ci->ci_key, inbuf, keybytes);
1.1 elric 542: if (ret)
543: goto bail;
544:
545: cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
546: cs->sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO;
547: cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
548: &cs->sc_cdata.cf_blocksize);
1.36 christos 549: (void)memset(inbuf, 0, MAX_KEYSIZE);
1.1 elric 550: if (!cs->sc_cdata.cf_priv) {
551: printf("cgd: unable to initialize cipher\n");
552: ret = EINVAL; /* XXX is this the right error? */
553: goto bail;
554: }
1.36 christos 555: free(inbuf, M_TEMP);
1.1 elric 556:
1.30 yamt 557: bufq_alloc(&cs->sc_dksc.sc_bufq, "fcfs", 0);
1.16 elric 558:
559: cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
560: cs->sc_data_used = 0;
561:
1.1 elric 562: cs->sc_dksc.sc_flags |= DKF_INITED;
563:
564: /* Attach the disk. */
1.28 yamt 565: pseudo_disk_attach(&cs->sc_dksc.sc_dkdev);
1.1 elric 566:
567: /* Try and read the disklabel. */
568: dk_getdisklabel(di, &cs->sc_dksc, 0 /* XXX ? */);
569:
1.29 yamt 570: /* Discover wedges on this disk. */
571: dkwedge_discover(&cs->sc_dksc.sc_dkdev);
572:
1.1 elric 573: return 0;
574:
575: bail:
1.36 christos 576: free(inbuf, M_TEMP);
1.37 ad 577: (void)vn_close(vp, FREAD|FWRITE, l->l_cred, l);
1.1 elric 578: return ret;
579: }
580:
581: /* ARGSUSED */
582: static int
1.40 christos 583: cgd_ioctl_clr(struct cgd_softc *cs, void *data, struct lwp *l)
1.1 elric 584: {
1.16 elric 585: int s;
586:
1.29 yamt 587: /* Delete all of our wedges. */
588: dkwedge_delall(&cs->sc_dksc.sc_dkdev);
589:
1.16 elric 590: /* Kill off any queued buffers. */
591: s = splbio();
1.30 yamt 592: bufq_drain(cs->sc_dksc.sc_bufq);
1.16 elric 593: splx(s);
1.30 yamt 594: bufq_free(cs->sc_dksc.sc_bufq);
1.1 elric 595:
1.37 ad 596: (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred, l);
1.1 elric 597: cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
598: free(cs->sc_tpath, M_DEVBUF);
1.16 elric 599: free(cs->sc_data, M_DEVBUF);
600: cs->sc_data_used = 0;
1.1 elric 601: cs->sc_dksc.sc_flags &= ~DKF_INITED;
1.28 yamt 602: pseudo_disk_detach(&cs->sc_dksc.sc_dkdev);
1.1 elric 603:
604: return 0;
605: }
606:
607: static int
1.27 drochner 608: cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
1.32 christos 609: struct lwp *l)
1.1 elric 610: {
611: struct dk_geom *pdg;
612: struct partinfo dpart;
613: struct vattr va;
614: size_t size;
615: int maxsecsize = 0;
616: int ret;
1.36 christos 617: char *tmppath;
1.1 elric 618:
619: cs->sc_dksc.sc_size = 0;
620: cs->sc_tvn = vp;
1.36 christos 621: cs->sc_tpath = NULL;
1.1 elric 622:
1.36 christos 623: tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
1.1 elric 624: ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
625: if (ret)
626: goto bail;
627: cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
628: memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
629:
1.37 ad 630: if ((ret = VOP_GETATTR(vp, &va, l->l_cred, l)) != 0)
1.1 elric 631: goto bail;
632:
633: cs->sc_tdev = va.va_rdev;
634:
1.37 ad 635: ret = VOP_IOCTL(vp, DIOCGPART, &dpart, FREAD, l->l_cred, l);
1.1 elric 636: if (ret)
637: goto bail;
638:
639: maxsecsize =
640: ((dpart.disklab->d_secsize > maxsecsize) ?
641: dpart.disklab->d_secsize : maxsecsize);
642: size = dpart.part->p_size;
643:
644: if (!size) {
645: ret = ENODEV;
646: goto bail;
647: }
648:
649: cs->sc_dksc.sc_size = size;
650:
651: /*
652: * XXX here we should probe the underlying device. If we
653: * are accessing a partition of type RAW_PART, then
654: * we should populate our initial geometry with the
655: * geometry that we discover from the device.
656: */
657: pdg = &cs->sc_dksc.sc_geom;
658: pdg->pdg_secsize = DEV_BSIZE;
659: pdg->pdg_ntracks = 1;
660: pdg->pdg_nsectors = 1024 * (1024 / pdg->pdg_secsize);
661: pdg->pdg_ncylinders = cs->sc_dksc.sc_size / pdg->pdg_nsectors;
662:
663: bail:
1.36 christos 664: free(tmppath, M_TEMP);
1.1 elric 665: if (ret && cs->sc_tpath)
666: free(cs->sc_tpath, M_DEVBUF);
667: return ret;
668: }
669:
670: /*
671: * Our generic cipher entry point. This takes care of the
672: * IV mode and passes off the work to the specific cipher.
673: * We implement here the IV method ``encrypted block
674: * number''.
1.22 perry 675: *
1.1 elric 676: * For the encryption case, we accomplish this by setting
677: * up a struct uio where the first iovec of the source is
678: * the blocknumber and the first iovec of the dest is a
679: * sink. We then call the cipher with an IV of zero, and
680: * the right thing happens.
1.22 perry 681: *
1.1 elric 682: * For the decryption case, we use the same basic mechanism
683: * for symmetry, but we encrypt the block number in the
684: * first iovec.
685: *
686: * We mainly do this to avoid requiring the definition of
687: * an ECB mode.
688: *
689: * XXXrcd: for now we rely on our own crypto framework defined
690: * in dev/cgd_crypto.c. This will change when we
691: * get a generic kernel crypto framework.
692: */
693:
694: static void
1.25 xtraeme 695: blkno2blkno_buf(char *sbuf, daddr_t blkno)
1.1 elric 696: {
697: int i;
698:
699: /* Set up the blkno in blkno_buf, here we do not care much
700: * about the final layout of the information as long as we
701: * can guarantee that each sector will have a different IV
702: * and that the endianness of the machine will not affect
703: * the representation that we have chosen.
704: *
705: * We choose this representation, because it does not rely
706: * on the size of buf (which is the blocksize of the cipher),
707: * but allows daddr_t to grow without breaking existing
708: * disks.
709: *
710: * Note that blkno2blkno_buf does not take a size as input,
711: * and hence must be called on a pre-zeroed buffer of length
712: * greater than or equal to sizeof(daddr_t).
713: */
714: for (i=0; i < sizeof(daddr_t); i++) {
1.25 xtraeme 715: *sbuf++ = blkno & 0xff;
1.1 elric 716: blkno >>= 8;
717: }
718: }
719:
720: static void
1.44 christos 721: cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
722: size_t len, daddr_t blkno, size_t secsize, int dir)
1.1 elric 723: {
1.44 christos 724: char *dst = dstv;
725: char *src = srcv;
1.1 elric 726: cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher;
727: struct uio dstuio;
728: struct uio srcuio;
729: struct iovec dstiov[2];
730: struct iovec srciov[2];
1.42 christos 731: size_t blocksize = cs->sc_cdata.cf_blocksize;
1.1 elric 732: char sink[blocksize];
733: char zero_iv[blocksize];
734: char blkno_buf[blocksize];
735:
736: DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
737:
1.22 perry 738: DIAGCONDPANIC(len % blocksize != 0,
1.1 elric 739: ("cgd_cipher: len %% blocksize != 0"));
740:
741: /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
742: DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
743: ("cgd_cipher: sizeof(daddr_t) > blocksize"));
744:
745: memset(zero_iv, 0x0, sizeof(zero_iv));
746:
747: dstuio.uio_iov = dstiov;
748: dstuio.uio_iovcnt = 2;
749:
750: srcuio.uio_iov = srciov;
751: srcuio.uio_iovcnt = 2;
752:
753: dstiov[0].iov_base = sink;
754: dstiov[0].iov_len = blocksize;
755: srciov[0].iov_base = blkno_buf;
756: srciov[0].iov_len = blocksize;
757: dstiov[1].iov_len = secsize;
758: srciov[1].iov_len = secsize;
759:
760: for (; len > 0; len -= secsize) {
761: dstiov[1].iov_base = dst;
762: srciov[1].iov_base = src;
763:
764: memset(blkno_buf, 0x0, sizeof(blkno_buf));
765: blkno2blkno_buf(blkno_buf, blkno);
766: if (dir == CGD_CIPHER_DECRYPT) {
767: dstuio.uio_iovcnt = 1;
768: srcuio.uio_iovcnt = 1;
769: IFDEBUG(CGDB_CRYPTO, hexprint("step 0: blkno_buf",
770: blkno_buf, sizeof(blkno_buf)));
771: cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio,
772: zero_iv, CGD_CIPHER_ENCRYPT);
773: memcpy(blkno_buf, sink, blocksize);
774: dstuio.uio_iovcnt = 2;
775: srcuio.uio_iovcnt = 2;
776: }
777:
778: IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
779: blkno_buf, sizeof(blkno_buf)));
780: cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, zero_iv, dir);
781: IFDEBUG(CGDB_CRYPTO, hexprint("step 2: sink",
782: sink, sizeof(sink)));
783:
784: dst += secsize;
785: src += secsize;
786: blkno++;
787: }
788: }
789:
790: #ifdef DEBUG
791: static void
1.26 drochner 792: hexprint(const char *start, void *buf, int len)
1.1 elric 793: {
794: char *c = buf;
795:
796: DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
797: printf("%s: len=%06d 0x", start, len);
798: while (len--)
1.43 cbiere 799: printf("%02x", (unsigned char) *c++);
1.1 elric 800: }
801: #endif
CVSweb <webmaster@jp.NetBSD.org>