The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/cgd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 551c150221c7db99de53d1498e074150


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.