1 /* $NetBSD: cgd.c,v 1.57 2009/03/14 17:56:47 apb 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.57 2009/03/14 17:56:47 apb 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%"PRIx64"): 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(0x%"PRIx64", %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(0x%"PRIx64", %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(0x%"PRIx64")\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 /* expected to be called at splbio() */ 348 static void 349 cgdiodone(struct buf *nbp) 350 { 351 struct buf *obp = nbp->b_private; 352 struct cgd_softc *cs = getcgd_softc(obp->b_dev); 353 struct dk_softc *dksc = &cs->sc_dksc; 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%"PRIx64", 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 disk_unbusy(&dksc->sc_dkdev, obp->b_bcount - obp->b_resid, 389 (obp->b_flags & B_READ)); 390 biodone(obp); 391 dk_iodone(di, dksc); 392 } 393 394 /* XXX: we should probably put these into dksubr.c, mostly */ 395 static int 396 cgdread(dev_t dev, struct uio *uio, int flags) 397 { 398 struct cgd_softc *cs; 399 struct dk_softc *dksc; 400 401 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n", 402 (unsigned long long)dev, uio, flags)); 403 GETCGD_SOFTC(cs, dev); 404 dksc = &cs->sc_dksc; 405 if ((dksc->sc_flags & DKF_INITED) == 0) 406 return ENXIO; 407 return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio); 408 } 409 410 /* XXX: we should probably put these into dksubr.c, mostly */ 411 static int 412 cgdwrite(dev_t dev, struct uio *uio, int flags) 413 { 414 struct cgd_softc *cs; 415 struct dk_softc *dksc; 416 417 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags)); 418 GETCGD_SOFTC(cs, dev); 419 dksc = &cs->sc_dksc; 420 if ((dksc->sc_flags & DKF_INITED) == 0) 421 return ENXIO; 422 return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio); 423 } 424 425 static int 426 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 427 { 428 struct cgd_softc *cs; 429 struct dk_softc *dksc; 430 struct disk *dk; 431 int ret; 432 int part = DISKPART(dev); 433 int pmask = 1 << part; 434 435 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n", 436 dev, cmd, data, flag, l)); 437 GETCGD_SOFTC(cs, dev); 438 dksc = &cs->sc_dksc; 439 dk = &dksc->sc_dkdev; 440 switch (cmd) { 441 case CGDIOCSET: 442 case CGDIOCCLR: 443 if ((flag & FWRITE) == 0) 444 return EBADF; 445 } 446 447 switch (cmd) { 448 case CGDIOCSET: 449 if (dksc->sc_flags & DKF_INITED) 450 ret = EBUSY; 451 else 452 ret = cgd_ioctl_set(cs, data, l); 453 break; 454 case CGDIOCCLR: 455 if (!(dksc->sc_flags & DKF_INITED)) { 456 ret = ENXIO; 457 break; 458 } 459 if (DK_BUSY(&cs->sc_dksc, pmask)) { 460 ret = EBUSY; 461 break; 462 } 463 ret = cgd_ioctl_clr(cs, data, l); 464 break; 465 466 case DIOCCACHESYNC: 467 /* 468 * XXX Do we really need to care about having a writable 469 * file descriptor here? 470 */ 471 if ((flag & FWRITE) == 0) 472 return (EBADF); 473 474 /* 475 * We pass this call down to the underlying disk. 476 */ 477 ret = VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred); 478 break; 479 480 default: 481 ret = dk_ioctl(di, dksc, dev, cmd, data, flag, l); 482 break; 483 } 484 485 return ret; 486 } 487 488 static int 489 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size) 490 { 491 struct cgd_softc *cs; 492 493 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n", 494 dev, blkno, va, (unsigned long)size)); 495 GETCGD_SOFTC(cs, dev); 496 return dk_dump(di, &cs->sc_dksc, dev, blkno, va, size); 497 } 498 499 /* 500 * XXXrcd: 501 * for now we hardcode the maximum key length. 502 */ 503 #define MAX_KEYSIZE 1024 504 505 static const struct { 506 const char *n; 507 int v; 508 int d; 509 } encblkno[] = { 510 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 511 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 }, 512 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 }, 513 }; 514 515 /* ARGSUSED */ 516 static int 517 cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l) 518 { 519 struct cgd_ioctl *ci = data; 520 struct vnode *vp; 521 int ret; 522 size_t i; 523 size_t keybytes; /* key length in bytes */ 524 const char *cp; 525 char *inbuf; 526 527 cp = ci->ci_disk; 528 if ((ret = dk_lookup(cp, l, &vp, UIO_USERSPACE)) != 0) 529 return ret; 530 531 inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK); 532 533 if ((ret = cgdinit(cs, cp, vp, l)) != 0) 534 goto bail; 535 536 (void)memset(inbuf, 0, MAX_KEYSIZE); 537 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL); 538 if (ret) 539 goto bail; 540 cs->sc_cfuncs = cryptfuncs_find(inbuf); 541 if (!cs->sc_cfuncs) { 542 ret = EINVAL; 543 goto bail; 544 } 545 546 (void)memset(inbuf, 0, MAX_KEYSIZE); 547 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL); 548 if (ret) 549 goto bail; 550 551 for (i = 0; i < __arraycount(encblkno); i++) 552 if (strcmp(encblkno[i].n, inbuf) == 0) 553 break; 554 555 if (i == __arraycount(encblkno)) { 556 ret = EINVAL; 557 goto bail; 558 } 559 560 keybytes = ci->ci_keylen / 8 + 1; 561 if (keybytes > MAX_KEYSIZE) { 562 ret = EINVAL; 563 goto bail; 564 } 565 566 (void)memset(inbuf, 0, MAX_KEYSIZE); 567 ret = copyin(ci->ci_key, inbuf, keybytes); 568 if (ret) 569 goto bail; 570 571 cs->sc_cdata.cf_blocksize = ci->ci_blocksize; 572 cs->sc_cdata.cf_mode = encblkno[i].v; 573 cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, 574 &cs->sc_cdata.cf_blocksize); 575 /* 576 * The blocksize is supposed to be in bytes. Unfortunately originally 577 * it was expressed in bits. For compatibility we maintain encblkno 578 * and encblkno8. 579 */ 580 cs->sc_cdata.cf_blocksize /= encblkno[i].d; 581 (void)memset(inbuf, 0, MAX_KEYSIZE); 582 if (!cs->sc_cdata.cf_priv) { 583 printf("cgd: unable to initialize cipher\n"); 584 ret = EINVAL; /* XXX is this the right error? */ 585 goto bail; 586 } 587 free(inbuf, M_TEMP); 588 589 bufq_alloc(&cs->sc_dksc.sc_bufq, "fcfs", 0); 590 591 cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK); 592 cs->sc_data_used = 0; 593 594 cs->sc_dksc.sc_flags |= DKF_INITED; 595 596 /* Attach the disk. */ 597 disk_attach(&cs->sc_dksc.sc_dkdev); 598 599 /* Try and read the disklabel. */ 600 dk_getdisklabel(di, &cs->sc_dksc, 0 /* XXX ? */); 601 602 /* Discover wedges on this disk. */ 603 dkwedge_discover(&cs->sc_dksc.sc_dkdev); 604 605 return 0; 606 607 bail: 608 free(inbuf, M_TEMP); 609 (void)vn_close(vp, FREAD|FWRITE, l->l_cred); 610 return ret; 611 } 612 613 /* ARGSUSED */ 614 static int 615 cgd_ioctl_clr(struct cgd_softc *cs, void *data, struct lwp *l) 616 { 617 int s; 618 619 /* Delete all of our wedges. */ 620 dkwedge_delall(&cs->sc_dksc.sc_dkdev); 621 622 /* Kill off any queued buffers. */ 623 s = splbio(); 624 bufq_drain(cs->sc_dksc.sc_bufq); 625 splx(s); 626 bufq_free(cs->sc_dksc.sc_bufq); 627 628 (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred); 629 cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv); 630 free(cs->sc_tpath, M_DEVBUF); 631 free(cs->sc_data, M_DEVBUF); 632 cs->sc_data_used = 0; 633 cs->sc_dksc.sc_flags &= ~DKF_INITED; 634 disk_detach(&cs->sc_dksc.sc_dkdev); 635 636 return 0; 637 } 638 639 static int 640 getsize(struct lwp *l, struct vnode *vp, size_t *size) 641 { 642 struct partinfo dpart; 643 struct dkwedge_info dkw; 644 int ret; 645 646 if ((ret = VOP_IOCTL(vp, DIOCGWEDGEINFO, &dkw, FREAD, 647 l->l_cred)) == 0) { 648 *size = dkw.dkw_size; 649 return 0; 650 } 651 652 if ((ret = VOP_IOCTL(vp, DIOCGPART, &dpart, FREAD, l->l_cred)) == 0) { 653 *size = dpart.part->p_size; 654 return 0; 655 } 656 657 return ret; 658 } 659 660 661 static int 662 cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp, 663 struct lwp *l) 664 { 665 struct dk_geom *pdg; 666 struct vattr va; 667 size_t size; 668 int ret; 669 char *tmppath; 670 671 cs->sc_dksc.sc_size = 0; 672 cs->sc_tvn = vp; 673 cs->sc_tpath = NULL; 674 675 tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 676 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen); 677 if (ret) 678 goto bail; 679 cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK); 680 memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen); 681 682 if ((ret = VOP_GETATTR(vp, &va, l->l_cred)) != 0) 683 goto bail; 684 685 cs->sc_tdev = va.va_rdev; 686 687 if ((ret = getsize(l, vp, &size)) != 0) 688 goto bail; 689 690 if (!size) { 691 ret = ENODEV; 692 goto bail; 693 } 694 695 cs->sc_dksc.sc_size = size; 696 697 /* 698 * XXX here we should probe the underlying device. If we 699 * are accessing a partition of type RAW_PART, then 700 * we should populate our initial geometry with the 701 * geometry that we discover from the device. 702 */ 703 pdg = &cs->sc_dksc.sc_geom; 704 pdg->pdg_secsize = DEV_BSIZE; 705 pdg->pdg_ntracks = 1; 706 pdg->pdg_nsectors = 1024 * (1024 / pdg->pdg_secsize); 707 pdg->pdg_ncylinders = cs->sc_dksc.sc_size / pdg->pdg_nsectors; 708 709 bail: 710 free(tmppath, M_TEMP); 711 if (ret && cs->sc_tpath) 712 free(cs->sc_tpath, M_DEVBUF); 713 return ret; 714 } 715 716 /* 717 * Our generic cipher entry point. This takes care of the 718 * IV mode and passes off the work to the specific cipher. 719 * We implement here the IV method ``encrypted block 720 * number''. 721 * 722 * For the encryption case, we accomplish this by setting 723 * up a struct uio where the first iovec of the source is 724 * the blocknumber and the first iovec of the dest is a 725 * sink. We then call the cipher with an IV of zero, and 726 * the right thing happens. 727 * 728 * For the decryption case, we use the same basic mechanism 729 * for symmetry, but we encrypt the block number in the 730 * first iovec. 731 * 732 * We mainly do this to avoid requiring the definition of 733 * an ECB mode. 734 * 735 * XXXrcd: for now we rely on our own crypto framework defined 736 * in dev/cgd_crypto.c. This will change when we 737 * get a generic kernel crypto framework. 738 */ 739 740 static void 741 blkno2blkno_buf(char *sbuf, daddr_t blkno) 742 { 743 int i; 744 745 /* Set up the blkno in blkno_buf, here we do not care much 746 * about the final layout of the information as long as we 747 * can guarantee that each sector will have a different IV 748 * and that the endianness of the machine will not affect 749 * the representation that we have chosen. 750 * 751 * We choose this representation, because it does not rely 752 * on the size of buf (which is the blocksize of the cipher), 753 * but allows daddr_t to grow without breaking existing 754 * disks. 755 * 756 * Note that blkno2blkno_buf does not take a size as input, 757 * and hence must be called on a pre-zeroed buffer of length 758 * greater than or equal to sizeof(daddr_t). 759 */ 760 for (i=0; i < sizeof(daddr_t); i++) { 761 *sbuf++ = blkno & 0xff; 762 blkno >>= 8; 763 } 764 } 765 766 static void 767 cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv, 768 size_t len, daddr_t blkno, size_t secsize, int dir) 769 { 770 char *dst = dstv; 771 char *src = srcv; 772 cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher; 773 struct uio dstuio; 774 struct uio srcuio; 775 struct iovec dstiov[2]; 776 struct iovec srciov[2]; 777 size_t blocksize = cs->sc_cdata.cf_blocksize; 778 char sink[blocksize]; 779 char zero_iv[blocksize]; 780 char blkno_buf[blocksize]; 781 782 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir)); 783 784 DIAGCONDPANIC(len % blocksize != 0, 785 ("cgd_cipher: len %% blocksize != 0")); 786 787 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */ 788 DIAGCONDPANIC(sizeof(daddr_t) > blocksize, 789 ("cgd_cipher: sizeof(daddr_t) > blocksize")); 790 791 memset(zero_iv, 0x0, sizeof(zero_iv)); 792 793 dstuio.uio_iov = dstiov; 794 dstuio.uio_iovcnt = 2; 795 796 srcuio.uio_iov = srciov; 797 srcuio.uio_iovcnt = 2; 798 799 dstiov[0].iov_base = sink; 800 dstiov[0].iov_len = blocksize; 801 srciov[0].iov_base = blkno_buf; 802 srciov[0].iov_len = blocksize; 803 dstiov[1].iov_len = secsize; 804 srciov[1].iov_len = secsize; 805 806 for (; len > 0; len -= secsize) { 807 dstiov[1].iov_base = dst; 808 srciov[1].iov_base = src; 809 810 memset(blkno_buf, 0x0, sizeof(blkno_buf)); 811 blkno2blkno_buf(blkno_buf, blkno); 812 if (dir == CGD_CIPHER_DECRYPT) { 813 dstuio.uio_iovcnt = 1; 814 srcuio.uio_iovcnt = 1; 815 IFDEBUG(CGDB_CRYPTO, hexprint("step 0: blkno_buf", 816 blkno_buf, sizeof(blkno_buf))); 817 cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, 818 zero_iv, CGD_CIPHER_ENCRYPT); 819 memcpy(blkno_buf, sink, blocksize); 820 dstuio.uio_iovcnt = 2; 821 srcuio.uio_iovcnt = 2; 822 } 823 824 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf", 825 blkno_buf, sizeof(blkno_buf))); 826 cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, zero_iv, dir); 827 IFDEBUG(CGDB_CRYPTO, hexprint("step 2: sink", 828 sink, sizeof(sink))); 829 830 dst += secsize; 831 src += secsize; 832 blkno++; 833 } 834 } 835 836 #ifdef DEBUG 837 static void 838 hexprint(const char *start, void *buf, int len) 839 { 840 char *c = buf; 841 842 DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0")); 843 printf("%s: len=%06d 0x", start, len); 844 while (len--) 845 printf("%02x", (unsigned char) *c++); 846 } 847 #endif 848