[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.117

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

CVSweb <webmaster@jp.NetBSD.org>