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