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