[BACK]Return to cgd.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev

Annotation of src/sys/dev/cgd.c, Revision 1.108.2.17

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

CVSweb <webmaster@jp.NetBSD.org>