1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2002 Poul-Henning Kamp 5 * Copyright (c) 2002 Networks Associates Technology, Inc. 6 * All rights reserved. 7 * 8 * This software was developed for the FreeBSD Project by Poul-Henning Kamp 9 * and NAI Labs, the Security Research Division of Network Associates, Inc. 10 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 11 * DARPA CHATS research program. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $FreeBSD: stable/11/sbin/gbde/gbde.c 330449 2018-03-05 07:26:05Z eadler $ 35 * 36 * XXX: Future stuff 37 * 38 * Replace the template file options (-i & -f) with command-line variables 39 * "-v property=foo" 40 * 41 * Introduce -e, extra entropy source (XOR with /dev/random) 42 * 43 * Introduce -E, alternate entropy source (instead of /dev/random) 44 * 45 * Introduce -i take IV from keyboard or 46 * 47 * Introduce -I take IV from file/cmd 48 * 49 * Introduce -m/-M store encrypted+encoded masterkey in file 50 * 51 * Introduce -k/-K get pass-phrase part from file/cmd 52 * 53 * Introduce -d add more dest-devices to worklist. 54 * 55 * Add key-option: selfdestruct bit. 56 * 57 * New/changed verbs: 58 * "onetime" attach with onetime nonstored locksector 59 * "key"/"unkey" to blast memory copy of key without orphaning 60 * "nuke" blow away everything attached, crash/halt/power-off if possible. 61 * "blast" destroy all copies of the masterkey 62 * "destroy" destroy one copy of the masterkey 63 * "backup"/"restore" of masterkey sectors. 64 * 65 * Make all verbs work on both attached/detached devices. 66 * 67 */ 68 69#include <sys/types.h> 70#include <sys/queue.h> 71#include <sys/mutex.h> 72#include <md5.h> 73#include <readpassphrase.h> 74#include <string.h> 75#include <stdint.h> 76#include <unistd.h> 77#include <fcntl.h> 78#include <paths.h> 79#include <strings.h> 80#include <stdlib.h> 81#include <err.h> 82#include <stdio.h> 83#include <libutil.h> 84#include <libgeom.h> 85#include <sys/errno.h> 86#include <sys/disk.h> 87#include <sys/stat.h> 88#include <crypto/rijndael/rijndael-api-fst.h> 89#include <crypto/sha2/sha512.h> 90#include <sys/param.h> 91#include <sys/linker.h> 92 93#define GBDEMOD "geom_bde" 94#define KASSERT(foo, bar) do { if(!(foo)) { warn bar ; exit (1); } } while (0) 95 96#include <geom/geom.h> 97#include <geom/bde/g_bde.h> 98 99extern const char template[]; 100 101 102#if 0 103static void 104g_hexdump(void *ptr, int length) 105{ 106 int i, j, k; 107 unsigned char *cp; 108 109 cp = ptr; 110 for (i = 0; i < length; i+= 16) { 111 printf("%04x ", i); 112 for (j = 0; j < 16; j++) { 113 k = i + j; 114 if (k < length) 115 printf(" %02x", cp[k]); 116 else 117 printf(" "); 118 } 119 printf(" |"); 120 for (j = 0; j < 16; j++) { 121 k = i + j; 122 if (k >= length) 123 printf(" "); 124 else if (cp[k] >= ' ' && cp[k] <= '~') 125 printf("%c", cp[k]); 126 else 127 printf("."); 128 } 129 printf("|\n"); 130 } 131} 132#endif 133 134static void __dead2 135usage(void) 136{ 137 138 (void)fprintf(stderr, 139"usage: gbde attach destination [-k keyfile] [-l lockfile] [-p pass-phrase]\n" 140" gbde detach destination\n" 141" gbde init destination [-i] [-f filename] [-K new-keyfile]\n" 142" [-L new-lockfile] [-P new-pass-phrase]\n" 143" gbde setkey destination [-n key]\n" 144" [-k keyfile] [-l lockfile] [-p pass-phrase]\n" 145" [-K new-keyfile] [-L new-lockfile] [-P new-pass-phrase]\n" 146" gbde nuke destination [-n key]\n" 147" [-k keyfile] [-l lockfile] [-p pass-phrase]\n" 148" gbde destroy destination [-k keyfile] [-l lockfile] [-p pass-phrase]\n"); 149 exit(1); 150} 151 152void * 153g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error) 154{ 155 void *p; 156 int fd, i; 157 off_t o2; 158 159 p = malloc(length); 160 if (p == NULL) 161 err(1, "malloc"); 162 fd = *(int *)cp; 163 o2 = lseek(fd, offset, SEEK_SET); 164 if (o2 != offset) 165 err(1, "lseek"); 166 i = read(fd, p, length); 167 if (i != length) 168 err(1, "read"); 169 if (error != NULL) 170 error = 0; 171 return (p); 172} 173 174static void 175random_bits(void *p, u_int len) 176{ 177 static int fdr = -1; 178 int i; 179 180 if (fdr < 0) { 181 fdr = open("/dev/urandom", O_RDONLY); 182 if (fdr < 0) 183 err(1, "/dev/urandom"); 184 } 185 186 i = read(fdr, p, len); 187 if (i != (int)len) 188 err(1, "read from /dev/urandom"); 189} 190 191/* XXX: not nice */ 192static u_char sha2[SHA512_DIGEST_LENGTH]; 193 194static void 195reset_passphrase(struct g_bde_softc *sc) 196{ 197 198 memcpy(sc->sha2, sha2, SHA512_DIGEST_LENGTH); 199} 200 201static void 202setup_passphrase(struct g_bde_softc *sc, int sure, const char *input, 203 const char *keyfile) 204{ 205 char buf1[BUFSIZ + SHA512_DIGEST_LENGTH]; 206 char buf2[BUFSIZ + SHA512_DIGEST_LENGTH]; 207 char *p; 208 int kfd, klen, bpos = 0; 209 210 if (keyfile != NULL) { 211 /* Read up to BUFSIZ bytes from keyfile */ 212 kfd = open(keyfile, O_RDONLY, 0); 213 if (kfd < 0) 214 err(1, "%s", keyfile); 215 klen = read(kfd, buf1, BUFSIZ); 216 if (klen == -1) 217 err(1, "%s", keyfile); 218 close(kfd); 219 220 /* Prepend the passphrase with the hash of the key read */ 221 g_bde_hash_pass(sc, buf1, klen); 222 memcpy(buf1, sc->sha2, SHA512_DIGEST_LENGTH); 223 memcpy(buf2, sc->sha2, SHA512_DIGEST_LENGTH); 224 bpos = SHA512_DIGEST_LENGTH; 225 } 226 227 if (input != NULL) { 228 if (strlen(input) >= BUFSIZ) 229 errx(1, "Passphrase too long"); 230 strcpy(buf1 + bpos, input); 231 232 g_bde_hash_pass(sc, buf1, strlen(buf1 + bpos) + bpos); 233 memcpy(sha2, sc->sha2, SHA512_DIGEST_LENGTH); 234 return; 235 } 236 for (;;) { 237 p = readpassphrase( 238 sure ? "Enter new passphrase:" : "Enter passphrase: ", 239 buf1 + bpos, sizeof buf1 - bpos, 240 RPP_ECHO_OFF | RPP_REQUIRE_TTY); 241 if (p == NULL) 242 err(1, "readpassphrase"); 243 244 if (sure) { 245 p = readpassphrase("Reenter new passphrase: ", 246 buf2 + bpos, sizeof buf2 - bpos, 247 RPP_ECHO_OFF | RPP_REQUIRE_TTY); 248 if (p == NULL) 249 err(1, "readpassphrase"); 250 251 if (strcmp(buf1 + bpos, buf2 + bpos)) { 252 printf("They didn't match.\n"); 253 continue; 254 } 255 } 256 if (strlen(buf1 + bpos) < 3) { 257 printf("Too short passphrase.\n"); 258 continue; 259 } 260 break; 261 } 262 g_bde_hash_pass(sc, buf1, strlen(buf1 + bpos) + bpos); 263 memcpy(sha2, sc->sha2, SHA512_DIGEST_LENGTH); 264} 265 266static void 267encrypt_sector(void *d, int len, int klen, void *key) 268{ 269 keyInstance ki; 270 cipherInstance ci; 271 int error; 272 273 error = rijndael_cipherInit(&ci, MODE_CBC, NULL); 274 if (error <= 0) 275 errx(1, "rijndael_cipherInit=%d", error); 276 error = rijndael_makeKey(&ki, DIR_ENCRYPT, klen, key); 277 if (error <= 0) 278 errx(1, "rijndael_makeKeY=%d", error); 279 error = rijndael_blockEncrypt(&ci, &ki, d, len * 8, d); 280 if (error <= 0) 281 errx(1, "rijndael_blockEncrypt=%d", error); 282} 283 284static void 285cmd_attach(const struct g_bde_softc *sc, const char *dest, const char *lfile) 286{ 287 int ffd; 288 u_char buf[16]; 289 struct gctl_req *r; 290 const char *errstr; 291 292 r = gctl_get_handle(); 293 gctl_ro_param(r, "verb", -1, "create geom"); 294 gctl_ro_param(r, "class", -1, "BDE"); 295 gctl_ro_param(r, "provider", -1, dest); 296 gctl_ro_param(r, "pass", SHA512_DIGEST_LENGTH, sc->sha2); 297 if (lfile != NULL) { 298 ffd = open(lfile, O_RDONLY, 0); 299 if (ffd < 0) 300 err(1, "%s", lfile); 301 read(ffd, buf, 16); 302 gctl_ro_param(r, "key", 16, buf); 303 close(ffd); 304 } 305 errstr = gctl_issue(r); 306 if (errstr != NULL) 307 errx(1, "Attach to %s failed: %s", dest, errstr); 308 309 exit (0); 310} 311 312static void 313cmd_detach(const char *dest) 314{ 315 struct gctl_req *r; 316 const char *errstr; 317 char buf[BUFSIZ]; 318 319 r = gctl_get_handle(); 320 gctl_ro_param(r, "verb", -1, "destroy geom"); 321 gctl_ro_param(r, "class", -1, "BDE"); 322 sprintf(buf, "%s.bde", dest); 323 gctl_ro_param(r, "geom", -1, buf); 324 /* gctl_dump(r, stdout); */ 325 errstr = gctl_issue(r); 326 if (errstr != NULL) 327 errx(1, "Detach of %s failed: %s", dest, errstr); 328 exit (0); 329} 330 331static void 332cmd_open(struct g_bde_softc *sc, int dfd , const char *l_opt, u_int *nkey) 333{ 334 int error; 335 int ffd; 336 u_char keyloc[16]; 337 u_int sectorsize; 338 off_t mediasize; 339 struct stat st; 340 341 error = ioctl(dfd, DIOCGSECTORSIZE, §orsize); 342 if (error) 343 sectorsize = 512; 344 error = ioctl(dfd, DIOCGMEDIASIZE, &mediasize); 345 if (error) { 346 error = fstat(dfd, &st); 347 if (error == 0 && S_ISREG(st.st_mode)) 348 mediasize = st.st_size; 349 else 350 error = ENOENT; 351 } 352 if (error) 353 mediasize = (off_t)-1; 354 if (l_opt != NULL) { 355 ffd = open(l_opt, O_RDONLY, 0); 356 if (ffd < 0) 357 err(1, "%s", l_opt); 358 read(ffd, keyloc, sizeof keyloc); 359 close(ffd); 360 } else { 361 memset(keyloc, 0, sizeof keyloc); 362 } 363 364 error = g_bde_decrypt_lock(sc, sc->sha2, keyloc, mediasize, 365 sectorsize, nkey); 366 if (error == ENOENT) 367 errx(1, "Lock was destroyed."); 368 if (error == ESRCH) 369 errx(1, "Lock was nuked."); 370 if (error == ENOTDIR) 371 errx(1, "Lock not found"); 372 if (error != 0) 373 errx(1, "Error %d decrypting lock", error); 374 if (nkey) 375 printf("Opened with key %u\n", 1 + *nkey); 376 return; 377} 378 379static void 380cmd_nuke(struct g_bde_key *gl, int dfd , int key) 381{ 382 int i; 383 u_char *sbuf; 384 off_t offset, offset2; 385 386 sbuf = malloc(gl->sectorsize); 387 memset(sbuf, 0, gl->sectorsize); 388 offset = (gl->lsector[key] & ~(gl->sectorsize - 1)); 389 offset2 = lseek(dfd, offset, SEEK_SET); 390 if (offset2 != offset) 391 err(1, "lseek"); 392 i = write(dfd, sbuf, gl->sectorsize); 393 free(sbuf); 394 if (i != (int)gl->sectorsize) 395 err(1, "write"); 396 printf("Nuked key %d\n", 1 + key); 397} 398 399static void 400cmd_write(struct g_bde_key *gl, struct g_bde_softc *sc, int dfd , int key, const char *l_opt) 401{ 402 int i, ffd; 403 uint64_t off[2]; 404 u_char keyloc[16]; 405 u_char *sbuf, *q; 406 off_t offset, offset2; 407 408 sbuf = malloc(gl->sectorsize); 409 /* 410 * Find the byte-offset in the lock sector where we will put the lock 411 * data structure. We can put it any random place as long as the 412 * structure fits. 413 */ 414 for(;;) { 415 random_bits(off, sizeof off); 416 off[0] &= (gl->sectorsize - 1); 417 if (off[0] + G_BDE_LOCKSIZE > gl->sectorsize) 418 continue; 419 break; 420 } 421 422 /* Add the sector offset in bytes */ 423 off[0] += (gl->lsector[key] & ~(gl->sectorsize - 1)); 424 gl->lsector[key] = off[0]; 425 426 i = g_bde_keyloc_encrypt(sc->sha2, off[0], off[1], keyloc); 427 if (i) 428 errx(1, "g_bde_keyloc_encrypt()"); 429 if (l_opt != NULL) { 430 ffd = open(l_opt, O_WRONLY | O_CREAT | O_TRUNC, 0600); 431 if (ffd < 0) 432 err(1, "%s", l_opt); 433 write(ffd, keyloc, sizeof keyloc); 434 close(ffd); 435 } else if (gl->flags & GBDE_F_SECT0) { 436 offset2 = lseek(dfd, 0, SEEK_SET); 437 if (offset2 != 0) 438 err(1, "lseek"); 439 i = read(dfd, sbuf, gl->sectorsize); 440 if (i != (int)gl->sectorsize) 441 err(1, "read"); 442 memcpy(sbuf + key * 16, keyloc, sizeof keyloc); 443 offset2 = lseek(dfd, 0, SEEK_SET); 444 if (offset2 != 0) 445 err(1, "lseek"); 446 i = write(dfd, sbuf, gl->sectorsize); 447 if (i != (int)gl->sectorsize) 448 err(1, "write"); 449 } else { 450 errx(1, "No -L option and no space in sector 0 for lockfile"); 451 } 452 453 /* Allocate a sectorbuffer and fill it with random junk */ 454 if (sbuf == NULL) 455 err(1, "malloc"); 456 random_bits(sbuf, gl->sectorsize); 457 458 /* Fill random bits in the spare field */ 459 random_bits(gl->spare, sizeof(gl->spare)); 460 461 /* Encode the structure where we want it */ 462 q = sbuf + (off[0] % gl->sectorsize); 463 i = g_bde_encode_lock(sc->sha2, gl, q); 464 if (i < 0) 465 errx(1, "programming error encoding lock"); 466 467 encrypt_sector(q, G_BDE_LOCKSIZE, 256, sc->sha2 + 16); 468 offset = gl->lsector[key] & ~(gl->sectorsize - 1); 469 offset2 = lseek(dfd, offset, SEEK_SET); 470 if (offset2 != offset) 471 err(1, "lseek"); 472 i = write(dfd, sbuf, gl->sectorsize); 473 if (i != (int)gl->sectorsize) 474 err(1, "write"); 475 free(sbuf); 476#if 0 477 printf("Wrote key %d at %jd\n", key, (intmax_t)offset); 478 printf("s0 = %jd\n", (intmax_t)gl->sector0); 479 printf("sN = %jd\n", (intmax_t)gl->sectorN); 480 printf("l[0] = %jd\n", (intmax_t)gl->lsector[0]); 481 printf("l[1] = %jd\n", (intmax_t)gl->lsector[1]); 482 printf("l[2] = %jd\n", (intmax_t)gl->lsector[2]); 483 printf("l[3] = %jd\n", (intmax_t)gl->lsector[3]); 484 printf("k = %jd\n", (intmax_t)gl->keyoffset); 485 printf("ss = %jd\n", (intmax_t)gl->sectorsize); 486#endif 487} 488 489static void 490cmd_destroy(struct g_bde_key *gl, int nkey) 491{ 492 int i; 493 494 bzero(&gl->sector0, sizeof gl->sector0); 495 bzero(&gl->sectorN, sizeof gl->sectorN); 496 bzero(&gl->keyoffset, sizeof gl->keyoffset); 497 gl->flags &= GBDE_F_SECT0; 498 bzero(gl->mkey, sizeof gl->mkey); 499 for (i = 0; i < G_BDE_MAXKEYS; i++) 500 if (i != nkey) 501 gl->lsector[i] = ~0; 502} 503 504static int 505sorthelp(const void *a, const void *b) 506{ 507 const uint64_t *oa, *ob; 508 509 oa = a; 510 ob = b; 511 if (*oa > *ob) 512 return 1; 513 if (*oa < *ob) 514 return -1; 515 return 0; 516} 517 518static void 519cmd_init(struct g_bde_key *gl, int dfd, const char *f_opt, int i_opt, const char *l_opt) 520{ 521 int i; 522 u_char *buf; 523 unsigned sector_size; 524 uint64_t first_sector; 525 uint64_t last_sector; 526 uint64_t total_sectors; 527 off_t off, off2; 528 unsigned nkeys; 529 const char *p; 530 char *q, cbuf[BUFSIZ]; 531 unsigned u, u2; 532 uint64_t o; 533 properties params; 534 535 bzero(gl, sizeof *gl); 536 if (f_opt != NULL) { 537 i = open(f_opt, O_RDONLY); 538 if (i < 0) 539 err(1, "%s", f_opt); 540 params = properties_read(i); 541 close (i); 542 } else if (i_opt) { 543 /* XXX: Polish */ 544 asprintf(&q, "%stemp.XXXXXXXXXX", _PATH_TMP); 545 if (q == NULL) 546 err(1, "asprintf"); 547 i = mkstemp(q); 548 if (i < 0) 549 err(1, "%s", q); 550 write(i, template, strlen(template)); 551 close (i); 552 p = getenv("EDITOR"); 553 if (p == NULL) 554 p = "vi"; 555 if (snprintf(cbuf, sizeof(cbuf), "%s %s\n", p, q) >= 556 (ssize_t)sizeof(cbuf)) { 557 unlink(q); 558 errx(1, "EDITOR is too long"); 559 } 560 system(cbuf); 561 i = open(q, O_RDONLY); 562 if (i < 0) 563 err(1, "%s", f_opt); 564 params = properties_read(i); 565 close (i); 566 unlink(q); 567 free(q); 568 } else { 569 /* XXX: Hack */ 570 i = open(_PATH_DEVNULL, O_RDONLY); 571 if (i < 0) 572 err(1, "%s", _PATH_DEVNULL); 573 params = properties_read(i); 574 close (i); 575 } 576 577 /* <sector_size> */ 578 p = property_find(params, "sector_size"); 579 i = ioctl(dfd, DIOCGSECTORSIZE, &u); 580 if (p != NULL) { 581 sector_size = strtoul(p, &q, 0); 582 if (!*p || *q) 583 errx(1, "sector_size not a proper number"); 584 } else if (i == 0) { 585 sector_size = u; 586 } else { 587 errx(1, "Missing sector_size property"); 588 } 589 if (sector_size & (sector_size - 1)) 590 errx(1, "sector_size not a power of 2"); 591 if (sector_size < 512) 592 errx(1, "sector_size is smaller than 512"); 593 buf = malloc(sector_size); 594 if (buf == NULL) 595 err(1, "Failed to malloc sector buffer"); 596 gl->sectorsize = sector_size; 597 598 i = ioctl(dfd, DIOCGMEDIASIZE, &off); 599 if (i == 0) { 600 first_sector = 0; 601 total_sectors = off / sector_size; 602 last_sector = total_sectors - 1; 603 } else { 604 first_sector = 0; 605 last_sector = 0; 606 total_sectors = 0; 607 } 608 609 /* <first_sector> */ 610 p = property_find(params, "first_sector"); 611 if (p != NULL) { 612 first_sector = strtoul(p, &q, 0); 613 if (!*p || *q) 614 errx(1, "first_sector not a proper number"); 615 } 616 617 /* <last_sector> */ 618 p = property_find(params, "last_sector"); 619 if (p != NULL) { 620 last_sector = strtoul(p, &q, 0); 621 if (!*p || *q) 622 errx(1, "last_sector not a proper number"); 623 if (last_sector <= first_sector) 624 errx(1, "last_sector not larger than first_sector"); 625 total_sectors = last_sector + 1; 626 } 627 628 /* <total_sectors> */ 629 p = property_find(params, "total_sectors"); 630 if (p != NULL) { 631 total_sectors = strtoul(p, &q, 0); 632 if (!*p || *q) 633 errx(1, "total_sectors not a proper number"); 634 if (last_sector == 0) 635 last_sector = first_sector + total_sectors - 1; 636 } 637 638 if (l_opt == NULL && first_sector != 0) 639 errx(1, "No -L new-lockfile argument and first_sector != 0"); 640 else if (l_opt == NULL) { 641 first_sector++; 642 total_sectors--; 643 gl->flags |= GBDE_F_SECT0; 644 } 645 gl->sector0 = first_sector * gl->sectorsize; 646 647 if (total_sectors != (last_sector - first_sector) + 1) 648 errx(1, "total_sectors disagree with first_sector and last_sector"); 649 if (total_sectors == 0) 650 errx(1, "missing last_sector or total_sectors"); 651 652 gl->sectorN = (last_sector + 1) * gl->sectorsize; 653 654 /* Find a random keyoffset */ 655 random_bits(&o, sizeof o); 656 o %= (gl->sectorN - gl->sector0); 657 o &= ~(gl->sectorsize - 1); 658 gl->keyoffset = o; 659 660 /* <number_of_keys> */ 661 p = property_find(params, "number_of_keys"); 662 if (p != NULL) { 663 nkeys = strtoul(p, &q, 0); 664 if (!*p || *q) 665 errx(1, "number_of_keys not a proper number"); 666 if (nkeys < 1 || nkeys > G_BDE_MAXKEYS) 667 errx(1, "number_of_keys out of range"); 668 } else { 669 nkeys = 4; 670 } 671 for (u = 0; u < nkeys; u++) { 672 for(;;) { 673 do { 674 random_bits(&o, sizeof o); 675 o %= gl->sectorN; 676 o &= ~(gl->sectorsize - 1); 677 } while(o < gl->sector0); 678 for (u2 = 0; u2 < u; u2++) 679 if (o == gl->lsector[u2]) 680 break; 681 if (u2 < u) 682 continue; 683 break; 684 } 685 gl->lsector[u] = o; 686 } 687 for (; u < G_BDE_MAXKEYS; u++) { 688 do 689 random_bits(&o, sizeof o); 690 while (o < gl->sectorN); 691 gl->lsector[u] = o; 692 } 693 qsort(gl->lsector, G_BDE_MAXKEYS, sizeof gl->lsector[0], sorthelp); 694 695 /* Flush sector zero if we use it for lockfile data */ 696 if (gl->flags & GBDE_F_SECT0) { 697 off2 = lseek(dfd, 0, SEEK_SET); 698 if (off2 != 0) 699 err(1, "lseek(2) to sector 0"); 700 random_bits(buf, sector_size); 701 i = write(dfd, buf, sector_size); 702 if (i != (int)sector_size) 703 err(1, "write sector 0"); 704 } 705 706 /* <random_flush> */ 707 p = property_find(params, "random_flush"); 708 if (p != NULL) { 709 off = first_sector * sector_size; 710 off2 = lseek(dfd, off, SEEK_SET); 711 if (off2 != off) 712 err(1, "lseek(2) to first_sector"); 713 off2 = last_sector * sector_size; 714 while (off <= off2) { 715 random_bits(buf, sector_size); 716 i = write(dfd, buf, sector_size); 717 if (i != (int)sector_size) 718 err(1, "write to $device_name"); 719 off += sector_size; 720 } 721 } 722 723 random_bits(gl->mkey, sizeof gl->mkey); 724 random_bits(gl->salt, sizeof gl->salt); 725 726 return; 727} 728 729static enum action { 730 ACT_HUH, 731 ACT_ATTACH, ACT_DETACH, 732 ACT_INIT, ACT_SETKEY, ACT_DESTROY, ACT_NUKE 733} action; 734 735int 736main(int argc, char **argv) 737{ 738 const char *opts; 739 const char *k_opt, *K_opt; 740 const char *l_opt, *L_opt; 741 const char *p_opt, *P_opt; 742 const char *f_opt; 743 char *dest; 744 int i_opt, n_opt, ch, dfd, doopen; 745 u_int nkey; 746 int i; 747 char *q, buf[BUFSIZ]; 748 struct g_bde_key *gl; 749 struct g_bde_softc sc; 750 751 if (argc < 3) 752 usage(); 753 754 if (modfind("g_bde") < 0) { 755 /* need to load the gbde module */ 756 if (kldload(GBDEMOD) < 0 || modfind("g_bde") < 0) 757 err(1, GBDEMOD ": Kernel module not available"); 758 } 759 doopen = 0; 760 if (!strcmp(argv[1], "attach")) { 761 action = ACT_ATTACH; 762 opts = "k:l:p:"; 763 } else if (!strcmp(argv[1], "detach")) { 764 action = ACT_DETACH; 765 opts = ""; 766 } else if (!strcmp(argv[1], "init")) { 767 action = ACT_INIT; 768 doopen = 1; 769 opts = "f:iK:L:P:"; 770 } else if (!strcmp(argv[1], "setkey")) { 771 action = ACT_SETKEY; 772 doopen = 1; 773 opts = "k:K:l:L:n:p:P:"; 774 } else if (!strcmp(argv[1], "destroy")) { 775 action = ACT_DESTROY; 776 doopen = 1; 777 opts = "k:l:p:"; 778 } else if (!strcmp(argv[1], "nuke")) { 779 action = ACT_NUKE; 780 doopen = 1; 781 opts = "k:l:n:p:"; 782 } else { 783 usage(); 784 } 785 argc--; 786 argv++; 787 788 dest = strdup(argv[1]); 789 argc--; 790 argv++; 791 792 p_opt = NULL; 793 P_opt = NULL; 794 k_opt = NULL; 795 K_opt = NULL; 796 l_opt = NULL; 797 L_opt = NULL; 798 f_opt = NULL; 799 n_opt = 0; 800 i_opt = 0; 801 802 while((ch = getopt(argc, argv, opts)) != -1) 803 switch (ch) { 804 case 'f': 805 f_opt = optarg; 806 break; 807 case 'i': 808 i_opt = !i_opt; 809 break; 810 case 'k': 811 k_opt = optarg; 812 break; 813 case 'K': 814 K_opt = optarg; 815 break; 816 case 'l': 817 l_opt = optarg; 818 break; 819 case 'L': 820 L_opt = optarg; 821 break; 822 case 'n': 823 n_opt = strtoul(optarg, &q, 0); 824 if (!*optarg || *q) 825 errx(1, "-n argument not numeric"); 826 if (n_opt < -1 || n_opt > G_BDE_MAXKEYS) 827 errx(1, "-n argument out of range"); 828 break; 829 case 'p': 830 p_opt = optarg; 831 break; 832 case 'P': 833 P_opt = optarg; 834 break; 835 default: 836 usage(); 837 } 838 839 if (doopen) { 840 dfd = open(dest, O_RDWR); 841 if (dfd < 0 && dest[0] != '/') { 842 if (snprintf(buf, sizeof(buf), "%s%s", 843 _PATH_DEV, dest) >= (ssize_t)sizeof(buf)) 844 errno = ENAMETOOLONG; 845 else 846 dfd = open(buf, O_RDWR); 847 } 848 if (dfd < 0) 849 err(1, "%s", dest); 850 } else { 851 if (!memcmp(dest, _PATH_DEV, strlen(_PATH_DEV))) 852 strcpy(dest, dest + strlen(_PATH_DEV)); 853 } 854 855 memset(&sc, 0, sizeof sc); 856 sc.consumer = (void *)&dfd; 857 gl = &sc.key; 858 switch(action) { 859 case ACT_ATTACH: 860 setup_passphrase(&sc, 0, p_opt, k_opt); 861 cmd_attach(&sc, dest, l_opt); 862 break; 863 case ACT_DETACH: 864 cmd_detach(dest); 865 break; 866 case ACT_INIT: 867 cmd_init(gl, dfd, f_opt, i_opt, L_opt); 868 setup_passphrase(&sc, 1, P_opt, K_opt); 869 cmd_write(gl, &sc, dfd, 0, L_opt); 870 break; 871 case ACT_SETKEY: 872 setup_passphrase(&sc, 0, p_opt, k_opt); 873 cmd_open(&sc, dfd, l_opt, &nkey); 874 if (n_opt == 0) 875 n_opt = nkey + 1; 876 setup_passphrase(&sc, 1, P_opt, K_opt); 877 cmd_write(gl, &sc, dfd, n_opt - 1, L_opt); 878 break; 879 case ACT_DESTROY: 880 setup_passphrase(&sc, 0, p_opt, k_opt); 881 cmd_open(&sc, dfd, l_opt, &nkey); 882 cmd_destroy(gl, nkey); 883 reset_passphrase(&sc); 884 cmd_write(gl, &sc, dfd, nkey, l_opt); 885 break; 886 case ACT_NUKE: 887 setup_passphrase(&sc, 0, p_opt, k_opt); 888 cmd_open(&sc, dfd, l_opt, &nkey); 889 if (n_opt == 0) 890 n_opt = nkey + 1; 891 if (n_opt == -1) { 892 for(i = 0; i < G_BDE_MAXKEYS; i++) 893 cmd_nuke(gl, dfd, i); 894 } else { 895 cmd_nuke(gl, dfd, n_opt - 1); 896 } 897 break; 898 default: 899 errx(1, "internal error"); 900 } 901 902 return(0); 903} 904