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