1 /* $OpenBSD: bioctl.c,v 1.158 2024/07/15 05:36:08 jmc Exp $ */ 2 3 /* 4 * Copyright (c) 2004, 2005 Marco Peereboom 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/param.h> /* NODEV */ 31 #include <sys/ioctl.h> 32 #include <sys/dkio.h> 33 #include <sys/stat.h> 34 #include <dev/softraidvar.h> 35 #include <dev/biovar.h> 36 37 #include <errno.h> 38 #include <err.h> 39 #include <fcntl.h> 40 #include <util.h> 41 #include <ctype.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <time.h> 46 #include <unistd.h> 47 #include <limits.h> 48 #include <vis.h> 49 #include <readpassphrase.h> 50 51 struct locator { 52 int channel; 53 int target; 54 int lun; 55 }; 56 57 struct timing { 58 int interval; 59 int start; 60 }; 61 62 static void __dead usage(void); 63 const char *str2locator(const char *, struct locator *); 64 const char *str2patrol(const char *, struct timing *); 65 void bio_status(struct bio_status *); 66 int bio_parse_devlist(char *, dev_t *); 67 void bio_kdf_derive(struct sr_crypto_kdfinfo *, 68 struct sr_crypto_pbkdf *, char *, int); 69 void bio_kdf_generate(struct sr_crypto_kdfinfo *); 70 int bcrypt_pbkdf_autorounds(void); 71 void derive_key(u_int32_t, int, u_int8_t *, size_t, 72 u_int8_t *, size_t, char *, int); 73 74 void bio_inq(char *); 75 void bio_alarm(char *); 76 int bio_getvolbyname(char *); 77 void bio_setstate(char *, int, char *); 78 void bio_setblink(char *, char *, int); 79 void bio_blink(char *, int, int); 80 void bio_createraid(u_int16_t, char *, char *); 81 void bio_deleteraid(char *); 82 void bio_changepass(char *); 83 u_int32_t bio_createflags(char *); 84 char *bio_vis(char *); 85 void bio_diskinq(char *); 86 void bio_patrol(char *); 87 88 int devh = -1; 89 int human; 90 int verbose; 91 u_int32_t cflags = 0; 92 int rflag = -1; /* auto */ 93 char *passfile; 94 95 void *bio_cookie; 96 97 int interactive = 1; 98 99 int 100 main(int argc, char *argv[]) 101 { 102 struct bio_locate bl; 103 u_int64_t func = 0; 104 char *devicename = NULL; 105 char *realname = NULL, *al_arg = NULL; 106 char *bl_arg = NULL, *dev_list = NULL; 107 char *key_disk = NULL; 108 const char *errstr; 109 int ch, blink = 0, changepass = 0, diskinq = 0; 110 int ss_func = 0; 111 u_int16_t cr_level = 0; 112 int biodev = 0; 113 114 if (argc < 2) 115 usage(); 116 117 while ((ch = getopt(argc, argv, "a:b:C:c:dH:hik:l:O:Pp:qr:R:st:u:v")) != 118 -1) { 119 switch (ch) { 120 case 'a': /* alarm */ 121 func |= BIOC_ALARM; 122 al_arg = optarg; 123 break; 124 case 'b': /* blink */ 125 func |= BIOC_BLINK; 126 blink = BIOC_SBBLINK; 127 bl_arg = optarg; 128 break; 129 case 'C': /* creation flags */ 130 cflags = bio_createflags(optarg); 131 break; 132 case 'c': /* create */ 133 func |= BIOC_CREATERAID; 134 if (strcmp(optarg, "1C") == 0) { 135 cr_level = 0x1C; 136 } else if (isdigit((unsigned char)*optarg)) { 137 cr_level = strtonum(optarg, 0, 10, &errstr); 138 if (errstr != NULL) 139 errx(1, "Invalid RAID level"); 140 } else if (strlen(optarg) == 1) { 141 cr_level = *optarg; 142 } else { 143 errx(1, "Invalid RAID level"); 144 } 145 break; 146 case 'd': 147 /* delete volume */ 148 func |= BIOC_DELETERAID; 149 break; 150 case 'u': /* unblink */ 151 func |= BIOC_BLINK; 152 blink = BIOC_SBUNBLINK; 153 bl_arg = optarg; 154 break; 155 case 'H': /* set hotspare */ 156 func |= BIOC_SETSTATE; 157 ss_func = BIOC_SSHOTSPARE; 158 al_arg = optarg; 159 break; 160 case 'h': 161 human = 1; 162 break; 163 case 'i': /* inquiry */ 164 func |= BIOC_INQ; 165 break; 166 case 'k': /* Key disk. */ 167 key_disk = optarg; 168 break; 169 case 'l': /* device list */ 170 func |= BIOC_DEVLIST; 171 dev_list = optarg; 172 break; 173 case 'P': 174 /* Change passphrase. */ 175 changepass = 1; 176 break; 177 case 'p': 178 passfile = optarg; 179 break; 180 case 'r': 181 if (strcmp(optarg, "auto") == 0) { 182 rflag = -1; 183 break; 184 } 185 rflag = strtonum(optarg, 16, 1<<30, &errstr); 186 if (errstr != NULL) 187 errx(1, "number of KDF rounds is %s: %s", 188 errstr, optarg); 189 break; 190 case 'O': 191 /* set a chunk to offline */ 192 func |= BIOC_SETSTATE; 193 ss_func = BIOC_SSOFFLINE; 194 al_arg = optarg; 195 break; 196 case 'R': 197 /* rebuild to provided chunk/CTL */ 198 func |= BIOC_SETSTATE; 199 ss_func = BIOC_SSREBUILD; 200 al_arg = optarg; 201 break; 202 case 's': 203 interactive = 0; 204 break; 205 case 't': /* patrol */ 206 func |= BIOC_PATROL; 207 al_arg = optarg; 208 break; 209 case 'v': 210 verbose = 1; 211 break; 212 case 'q': 213 diskinq = 1; 214 break; 215 default: 216 usage(); 217 /* NOTREACHED */ 218 } 219 } 220 argc -= optind; 221 argv += optind; 222 223 if (argc != 1 || (changepass && func != 0)) 224 usage(); 225 226 if (func == 0) 227 func |= BIOC_INQ; 228 229 devicename = argv[0]; 230 if (devicename == NULL) 231 errx(1, "need device"); 232 233 devh = opendev(devicename, O_RDWR, OPENDEV_PART, &realname); 234 if (devh == -1) { 235 devh = open("/dev/bio", O_RDWR); 236 if (devh == -1) 237 err(1, "Can't open %s", "/dev/bio"); 238 239 memset(&bl, 0, sizeof(bl)); 240 bl.bl_name = devicename; 241 if (ioctl(devh, BIOCLOCATE, &bl) == -1) 242 errx(1, "Can't locate %s device via %s", 243 bl.bl_name, "/dev/bio"); 244 245 bio_cookie = bl.bl_bio.bio_cookie; 246 biodev = 1; 247 devicename = NULL; 248 } 249 250 if (diskinq) { 251 bio_diskinq(devicename); 252 } else if (changepass && !biodev) { 253 bio_changepass(devicename); 254 } else if (func & BIOC_INQ) { 255 bio_inq(devicename); 256 } else if (func == BIOC_ALARM) { 257 bio_alarm(al_arg); 258 } else if (func == BIOC_BLINK) { 259 bio_setblink(devicename, bl_arg, blink); 260 } else if (func == BIOC_PATROL) { 261 bio_patrol(al_arg); 262 } else if (func == BIOC_SETSTATE) { 263 bio_setstate(al_arg, ss_func, argv[0]); 264 } else if (func == BIOC_DELETERAID && !biodev) { 265 bio_deleteraid(devicename); 266 } else if (func & BIOC_CREATERAID || func & BIOC_DEVLIST) { 267 if (!(func & BIOC_CREATERAID)) 268 errx(1, "need -c parameter"); 269 if (!(func & BIOC_DEVLIST)) 270 errx(1, "need -l parameter"); 271 if (!biodev) 272 errx(1, "must use bio device"); 273 bio_createraid(cr_level, dev_list, key_disk); 274 } 275 276 return (0); 277 } 278 279 static void __dead 280 usage(void) 281 { 282 extern char *__progname; 283 284 fprintf(stderr, 285 "usage: %s [-hiqv] [-a alarm-function] " 286 "[-b channel:target[.lun]]\n" 287 "\t[-H channel:target[.lun]] " 288 "[-R chunk | channel:target[.lun]]\n" 289 "\t[-t patrol-function] " 290 "[-u channel:target[.lun]] " 291 "device\n\n" 292 " %s [-dhiPqsv] " 293 "[-C flag[,...]] [-c raidlevel] [-k keydisk]\n" 294 "\t[-l chunk[,...]] " 295 "[-O device | channel:target[.lun]] [-p passfile]\n" 296 "\t[-R chunk | channel:target[.lun]] [-r rounds] " 297 "device\n", __progname, __progname); 298 299 exit(1); 300 } 301 302 const char * 303 str2locator(const char *string, struct locator *location) 304 { 305 const char *errstr; 306 char parse[80], *targ, *lun; 307 308 strlcpy(parse, string, sizeof parse); 309 targ = strchr(parse, ':'); 310 if (targ == NULL) 311 return ("target not specified"); 312 *targ++ = '\0'; 313 314 lun = strchr(targ, '.'); 315 if (lun != NULL) { 316 *lun++ = '\0'; 317 location->lun = strtonum(lun, 0, 256, &errstr); 318 if (errstr) 319 return (errstr); 320 } else 321 location->lun = 0; 322 323 location->target = strtonum(targ, 0, 256, &errstr); 324 if (errstr) 325 return (errstr); 326 location->channel = strtonum(parse, 0, 256, &errstr); 327 if (errstr) 328 return (errstr); 329 return (NULL); 330 } 331 332 const char * 333 str2patrol(const char *string, struct timing *timing) 334 { 335 const char *errstr; 336 char parse[80], *interval = NULL, *start = NULL; 337 338 timing->interval = 0; 339 timing->start = 0; 340 341 strlcpy(parse, string, sizeof parse); 342 343 interval = strchr(parse, '.'); 344 if (interval != NULL) { 345 *interval++ = '\0'; 346 start = strchr(interval, '.'); 347 if (start != NULL) 348 *start++ = '\0'; 349 } 350 if (interval != NULL) { 351 /* -1 == continuously */ 352 timing->interval = strtonum(interval, -1, INT_MAX, &errstr); 353 if (errstr) 354 return (errstr); 355 } 356 if (start != NULL) { 357 timing->start = strtonum(start, 0, INT_MAX, &errstr); 358 if (errstr) 359 return (errstr); 360 } 361 362 return (NULL); 363 } 364 365 void 366 bio_status(struct bio_status *bs) 367 { 368 extern char *__progname; 369 char *prefix; 370 int i; 371 372 if (strlen(bs->bs_controller)) 373 prefix = bs->bs_controller; 374 else 375 prefix = __progname; 376 377 for (i = 0; i < bs->bs_msg_count; i++) 378 fprintf(bs->bs_msgs[i].bm_type == BIO_MSG_INFO ? 379 stdout : stderr, "%s: %s\n", prefix, bs->bs_msgs[i].bm_msg); 380 381 if (bs->bs_status == BIO_STATUS_ERROR) { 382 if (bs->bs_msg_count == 0) 383 errx(1, "unknown error"); 384 else 385 exit(1); 386 } 387 } 388 389 void 390 bio_inq(char *name) 391 { 392 char *status, *cache; 393 char size[64], scsiname[16], volname[32]; 394 char percent[20], seconds[20]; 395 int i, d, volheader, hotspare, unused; 396 char encname[16], serial[32]; 397 struct bioc_inq bi; 398 struct bioc_vol bv; 399 struct bioc_disk bd; 400 401 memset(&bi, 0, sizeof(bi)); 402 403 bi.bi_bio.bio_cookie = bio_cookie; 404 405 if (ioctl(devh, BIOCINQ, &bi) == -1) { 406 if (errno == ENOTTY) 407 bio_diskinq(name); 408 else 409 err(1, "BIOCINQ"); 410 return; 411 } 412 413 bio_status(&bi.bi_bio.bio_status); 414 415 volheader = 0; 416 for (i = 0; i < bi.bi_novol; i++) { 417 memset(&bv, 0, sizeof(bv)); 418 bv.bv_bio.bio_cookie = bio_cookie; 419 bv.bv_volid = i; 420 bv.bv_percent = -1; 421 bv.bv_seconds = 0; 422 423 if (ioctl(devh, BIOCVOL, &bv) == -1) 424 err(1, "BIOCVOL"); 425 426 bio_status(&bv.bv_bio.bio_status); 427 428 if (name && strcmp(name, bv.bv_dev) != 0) 429 continue; 430 431 if (!volheader) { 432 volheader = 1; 433 printf("%-11s %-10s %14s %-8s\n", 434 "Volume", "Status", "Size", "Device"); 435 } 436 437 percent[0] = '\0'; 438 seconds[0] = '\0'; 439 if (bv.bv_percent != -1) 440 snprintf(percent, sizeof percent, 441 " %d%% done", bv.bv_percent); 442 if (bv.bv_seconds) 443 snprintf(seconds, sizeof seconds, 444 " %u seconds", bv.bv_seconds); 445 switch (bv.bv_status) { 446 case BIOC_SVONLINE: 447 status = BIOC_SVONLINE_S; 448 break; 449 case BIOC_SVOFFLINE: 450 status = BIOC_SVOFFLINE_S; 451 break; 452 case BIOC_SVDEGRADED: 453 status = BIOC_SVDEGRADED_S; 454 break; 455 case BIOC_SVBUILDING: 456 status = BIOC_SVBUILDING_S; 457 break; 458 case BIOC_SVREBUILD: 459 status = BIOC_SVREBUILD_S; 460 break; 461 case BIOC_SVSCRUB: 462 status = BIOC_SVSCRUB_S; 463 break; 464 case BIOC_SVINVALID: 465 default: 466 status = BIOC_SVINVALID_S; 467 } 468 switch (bv.bv_cache) { 469 case BIOC_CVWRITEBACK: 470 cache = BIOC_CVWRITEBACK_S; 471 break; 472 case BIOC_CVWRITETHROUGH: 473 cache = BIOC_CVWRITETHROUGH_S; 474 break; 475 case BIOC_CVUNKNOWN: 476 default: 477 cache = BIOC_CVUNKNOWN_S; 478 } 479 480 snprintf(volname, sizeof volname, "%s %u", 481 bi.bi_dev, bv.bv_volid); 482 483 unused = 0; 484 hotspare = 0; 485 if (bv.bv_level == -1 && bv.bv_nodisk == 1) 486 hotspare = 1; 487 else if (bv.bv_level == -2 && bv.bv_nodisk == 1) 488 unused = 1; 489 else { 490 if (human) 491 fmt_scaled(bv.bv_size, size); 492 else 493 snprintf(size, sizeof size, "%14llu", 494 bv.bv_size); 495 printf("%11s %-10s %14s %-7s ", 496 volname, status, size, bv.bv_dev); 497 switch (bv.bv_level) { 498 case 'C': 499 printf("CRYPTO%s%s\n", 500 percent, seconds); 501 break; 502 case 'c': 503 printf("CONCAT%s%s\n", 504 percent, seconds); 505 break; 506 case 0x1C: 507 case 0x1E: 508 printf("RAID%X%s%s %s\n", 509 bv.bv_level, percent, seconds, cache); 510 break; 511 default: 512 printf("RAID%u%s%s %s\n", 513 bv.bv_level, percent, seconds, cache); 514 break; 515 } 516 517 } 518 519 for (d = 0; d < bv.bv_nodisk; d++) { 520 memset(&bd, 0, sizeof(bd)); 521 bd.bd_bio.bio_cookie = bio_cookie; 522 bd.bd_diskid = d; 523 bd.bd_volid = i; 524 bd.bd_patrol.bdp_percent = -1; 525 bd.bd_patrol.bdp_seconds = 0; 526 527 if (ioctl(devh, BIOCDISK, &bd) == -1) 528 err(1, "BIOCDISK"); 529 530 bio_status(&bd.bd_bio.bio_status); 531 532 switch (bd.bd_status) { 533 case BIOC_SDONLINE: 534 status = BIOC_SDONLINE_S; 535 break; 536 case BIOC_SDOFFLINE: 537 status = BIOC_SDOFFLINE_S; 538 break; 539 case BIOC_SDFAILED: 540 status = BIOC_SDFAILED_S; 541 break; 542 case BIOC_SDREBUILD: 543 status = BIOC_SDREBUILD_S; 544 break; 545 case BIOC_SDHOTSPARE: 546 status = BIOC_SDHOTSPARE_S; 547 break; 548 case BIOC_SDUNUSED: 549 status = BIOC_SDUNUSED_S; 550 break; 551 case BIOC_SDSCRUB: 552 status = BIOC_SDSCRUB_S; 553 break; 554 case BIOC_SDINVALID: 555 default: 556 status = BIOC_SDINVALID_S; 557 } 558 559 if (hotspare || unused) 560 ; /* use volname from parent volume */ 561 else 562 snprintf(volname, sizeof volname, " %3u", 563 bd.bd_diskid); 564 565 if (bv.bv_level == 'C' && bd.bd_size == 0) 566 snprintf(size, sizeof size, "%14s", "key disk"); 567 else if (human) 568 fmt_scaled(bd.bd_size, size); 569 else 570 snprintf(size, sizeof size, "%14llu", 571 bd.bd_size); 572 snprintf(scsiname, sizeof scsiname, 573 "%u:%u.%u", 574 bd.bd_channel, bd.bd_target, bd.bd_lun); 575 if (bd.bd_procdev[0]) 576 strlcpy(encname, bd.bd_procdev, sizeof encname); 577 else 578 strlcpy(encname, "noencl", sizeof encname); 579 if (bd.bd_serial[0]) 580 strlcpy(serial, bd.bd_serial, sizeof serial); 581 else 582 strlcpy(serial, "unknown serial", sizeof serial); 583 584 percent[0] = '\0'; 585 seconds[0] = '\0'; 586 if (bd.bd_patrol.bdp_percent != -1) 587 snprintf(percent, sizeof percent, 588 " patrol %d%% done", bd.bd_patrol.bdp_percent); 589 if (bd.bd_patrol.bdp_seconds) 590 snprintf(seconds, sizeof seconds, 591 " %u seconds", bd.bd_patrol.bdp_seconds); 592 593 printf("%11s %-10s %14s %-7s %-6s <%s>\n", 594 volname, status, size, scsiname, encname, 595 bd.bd_vendor); 596 if (verbose) 597 printf("%11s %-10s %14s %-7s %-6s '%s'%s%s\n", 598 "", "", "", "", "", serial, percent, seconds); 599 } 600 } 601 } 602 603 void 604 bio_alarm(char *arg) 605 { 606 struct bioc_alarm ba; 607 608 memset(&ba, 0, sizeof(ba)); 609 ba.ba_bio.bio_cookie = bio_cookie; 610 611 switch (arg[0]) { 612 case 'q': /* silence alarm */ 613 /* FALLTHROUGH */ 614 case 's': 615 ba.ba_opcode = BIOC_SASILENCE; 616 break; 617 618 case 'e': /* enable alarm */ 619 ba.ba_opcode = BIOC_SAENABLE; 620 break; 621 622 case 'd': /* disable alarm */ 623 ba.ba_opcode = BIOC_SADISABLE; 624 break; 625 626 case 't': /* test alarm */ 627 ba.ba_opcode = BIOC_SATEST; 628 break; 629 630 case 'g': /* get alarm state */ 631 ba.ba_opcode = BIOC_GASTATUS; 632 break; 633 634 default: 635 errx(1, "invalid alarm function: %s", arg); 636 } 637 638 if (ioctl(devh, BIOCALARM, &ba) == -1) 639 err(1, "BIOCALARM"); 640 641 bio_status(&ba.ba_bio.bio_status); 642 643 if (arg[0] == 'g') 644 printf("alarm is currently %s\n", 645 ba.ba_status ? "enabled" : "disabled"); 646 } 647 648 int 649 bio_getvolbyname(char *name) 650 { 651 int id = -1, i; 652 struct bioc_inq bi; 653 struct bioc_vol bv; 654 655 memset(&bi, 0, sizeof(bi)); 656 bi.bi_bio.bio_cookie = bio_cookie; 657 if (ioctl(devh, BIOCINQ, &bi) == -1) 658 err(1, "BIOCINQ"); 659 660 bio_status(&bi.bi_bio.bio_status); 661 662 for (i = 0; i < bi.bi_novol; i++) { 663 memset(&bv, 0, sizeof(bv)); 664 bv.bv_bio.bio_cookie = bio_cookie; 665 bv.bv_volid = i; 666 if (ioctl(devh, BIOCVOL, &bv) == -1) 667 err(1, "BIOCVOL"); 668 669 bio_status(&bv.bv_bio.bio_status); 670 671 if (name && strcmp(name, bv.bv_dev) != 0) 672 continue; 673 id = i; 674 break; 675 } 676 677 return (id); 678 } 679 680 void 681 bio_setstate(char *arg, int status, char *devicename) 682 { 683 struct bioc_setstate bs; 684 struct locator location; 685 struct stat sb; 686 const char *errstr; 687 688 memset(&bs, 0, sizeof(bs)); 689 if (stat(arg, &sb) == -1) { 690 /* use CTL */ 691 errstr = str2locator(arg, &location); 692 if (errstr) 693 errx(1, "Target %s: %s", arg, errstr); 694 bs.bs_channel = location.channel; 695 bs.bs_target = location.target; 696 bs.bs_lun = location.lun; 697 } else { 698 /* use other id */ 699 bs.bs_other_id = sb.st_rdev; 700 bs.bs_other_id_type = BIOC_SSOTHER_DEVT; 701 } 702 703 bs.bs_bio.bio_cookie = bio_cookie; 704 bs.bs_status = status; 705 706 if (status != BIOC_SSHOTSPARE) { 707 /* make sure user supplied a sd device */ 708 bs.bs_volid = bio_getvolbyname(devicename); 709 if (bs.bs_volid == -1) 710 errx(1, "invalid device %s", devicename); 711 } 712 713 if (ioctl(devh, BIOCSETSTATE, &bs) == -1) 714 err(1, "BIOCSETSTATE"); 715 716 bio_status(&bs.bs_bio.bio_status); 717 } 718 719 void 720 bio_setblink(char *name, char *arg, int blink) 721 { 722 struct locator location; 723 struct bioc_blink bb; 724 struct bioc_inq bi; 725 struct bioc_vol bv; 726 struct bioc_disk bd; 727 const char *errstr; 728 int v, d, rv; 729 730 errstr = str2locator(arg, &location); 731 if (errstr) 732 errx(1, "Target %s: %s", arg, errstr); 733 734 /* try setting blink on the device directly */ 735 memset(&bb, 0, sizeof(bb)); 736 bb.bb_bio.bio_cookie = bio_cookie; 737 bb.bb_status = blink; 738 bb.bb_target = location.target; 739 bb.bb_channel = location.channel; 740 rv = ioctl(devh, BIOCBLINK, &bb); 741 742 if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_UNKNOWN) 743 return; 744 745 if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_SUCCESS) { 746 bio_status(&bb.bb_bio.bio_status); 747 return; 748 } 749 750 /* if the blink didn't work, try to find something that will */ 751 752 memset(&bi, 0, sizeof(bi)); 753 bi.bi_bio.bio_cookie = bio_cookie; 754 if (ioctl(devh, BIOCINQ, &bi) == -1) 755 err(1, "BIOCINQ"); 756 757 bio_status(&bi.bi_bio.bio_status); 758 759 for (v = 0; v < bi.bi_novol; v++) { 760 memset(&bv, 0, sizeof(bv)); 761 bv.bv_bio.bio_cookie = bio_cookie; 762 bv.bv_volid = v; 763 if (ioctl(devh, BIOCVOL, &bv) == -1) 764 err(1, "BIOCVOL"); 765 766 bio_status(&bv.bv_bio.bio_status); 767 768 if (name && strcmp(name, bv.bv_dev) != 0) 769 continue; 770 771 for (d = 0; d < bv.bv_nodisk; d++) { 772 memset(&bd, 0, sizeof(bd)); 773 bd.bd_bio.bio_cookie = bio_cookie; 774 bd.bd_volid = v; 775 bd.bd_diskid = d; 776 777 if (ioctl(devh, BIOCDISK, &bd) == -1) 778 err(1, "BIOCDISK"); 779 780 bio_status(&bd.bd_bio.bio_status); 781 782 if (bd.bd_channel == location.channel && 783 bd.bd_target == location.target && 784 bd.bd_lun == location.lun) { 785 if (bd.bd_procdev[0] != '\0') 786 bio_blink(bd.bd_procdev, 787 location.target, blink); 788 else 789 warnx("Disk %s is not in an enclosure", 790 arg); 791 return; 792 } 793 } 794 } 795 796 warnx("Disk %s does not exist", arg); 797 } 798 799 void 800 bio_blink(char *enclosure, int target, int blinktype) 801 { 802 int bioh; 803 struct bio_locate bl; 804 struct bioc_blink blink; 805 806 bioh = open("/dev/bio", O_RDWR); 807 if (bioh == -1) 808 err(1, "Can't open %s", "/dev/bio"); 809 810 memset(&bl, 0, sizeof(bl)); 811 bl.bl_name = enclosure; 812 if (ioctl(bioh, BIOCLOCATE, &bl) == -1) 813 errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio"); 814 815 memset(&blink, 0, sizeof(blink)); 816 blink.bb_bio.bio_cookie = bio_cookie; 817 blink.bb_status = blinktype; 818 blink.bb_target = target; 819 820 if (ioctl(bioh, BIOCBLINK, &blink) == -1) 821 err(1, "BIOCBLINK"); 822 823 bio_status(&blink.bb_bio.bio_status); 824 825 close(bioh); 826 } 827 828 void 829 bio_createraid(u_int16_t level, char *dev_list, char *key_disk) 830 { 831 struct bioc_createraid create; 832 struct sr_crypto_kdfinfo kdfinfo; 833 struct sr_crypto_pbkdf kdfhint; 834 struct stat sb; 835 int rv, no_dev, fd; 836 dev_t *dt; 837 u_int16_t min_disks = 0; 838 839 if (!dev_list) 840 errx(1, "no devices specified"); 841 842 dt = calloc(1, BIOC_CRMAXLEN); 843 if (!dt) 844 err(1, "not enough memory for dev_t list"); 845 846 no_dev = bio_parse_devlist(dev_list, dt); 847 848 switch (level) { 849 case 0: 850 min_disks = 2; 851 break; 852 case 1: 853 min_disks = 2; 854 break; 855 case 5: 856 min_disks = 3; 857 break; 858 case 'C': 859 case 0x1C: 860 min_disks = 1; 861 break; 862 case 'c': 863 min_disks = 1; 864 break; 865 default: 866 errx(1, "unsupported RAID level"); 867 } 868 869 if (no_dev < min_disks) 870 errx(1, "not enough disks"); 871 872 /* for crypto raid we only allow one single chunk */ 873 if (level == 'C' && no_dev != min_disks) 874 errx(1, "not exactly one partition"); 875 876 memset(&create, 0, sizeof(create)); 877 create.bc_bio.bio_cookie = bio_cookie; 878 create.bc_level = level; 879 create.bc_dev_list_len = no_dev * sizeof(dev_t); 880 create.bc_dev_list = dt; 881 create.bc_flags = BIOC_SCDEVT | cflags; 882 create.bc_key_disk = NODEV; 883 884 if ((level == 'C' || level == 0x1C) && key_disk == NULL) { 885 886 memset(&kdfinfo, 0, sizeof(kdfinfo)); 887 memset(&kdfhint, 0, sizeof(kdfhint)); 888 889 create.bc_flags |= BIOC_SCNOAUTOASSEMBLE; 890 891 create.bc_opaque = &kdfhint; 892 create.bc_opaque_size = sizeof(kdfhint); 893 create.bc_opaque_flags = BIOC_SOOUT; 894 895 /* try to get KDF hint */ 896 if (ioctl(devh, BIOCCREATERAID, &create) == -1) 897 err(1, "ioctl"); 898 899 bio_status(&create.bc_bio.bio_status); 900 901 if (create.bc_opaque_status == BIOC_SOINOUT_OK) { 902 bio_kdf_derive(&kdfinfo, &kdfhint, "Passphrase: ", 0); 903 memset(&kdfhint, 0, sizeof(kdfhint)); 904 } else { 905 bio_kdf_generate(&kdfinfo); 906 } 907 908 create.bc_opaque = &kdfinfo; 909 create.bc_opaque_size = sizeof(kdfinfo); 910 create.bc_opaque_flags = BIOC_SOIN; 911 912 } else if ((level == 'C' || level == 0x1C) && key_disk != NULL) { 913 914 /* Get device number for key disk. */ 915 fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL); 916 if (fd == -1) 917 err(1, "could not open %s", key_disk); 918 if (fstat(fd, &sb) == -1) { 919 int saved_errno = errno; 920 close(fd); 921 errc(1, saved_errno, "could not stat %s", key_disk); 922 } 923 close(fd); 924 create.bc_key_disk = sb.st_rdev; 925 926 memset(&kdfinfo, 0, sizeof(kdfinfo)); 927 928 kdfinfo.genkdf.len = sizeof(kdfinfo.genkdf); 929 kdfinfo.genkdf.type = SR_CRYPTOKDFT_KEYDISK; 930 kdfinfo.len = sizeof(kdfinfo); 931 kdfinfo.flags = SR_CRYPTOKDF_HINT; 932 933 create.bc_opaque = &kdfinfo; 934 create.bc_opaque_size = sizeof(kdfinfo); 935 create.bc_opaque_flags = BIOC_SOIN; 936 937 } 938 939 rv = ioctl(devh, BIOCCREATERAID, &create); 940 explicit_bzero(&kdfinfo, sizeof(kdfinfo)); 941 if (rv == -1) 942 err(1, "BIOCCREATERAID"); 943 944 bio_status(&create.bc_bio.bio_status); 945 946 free(dt); 947 } 948 949 void 950 bio_kdf_derive(struct sr_crypto_kdfinfo *kdfinfo, struct sr_crypto_pbkdf 951 *kdfhint, char* prompt, int verify) 952 { 953 if (!kdfinfo) 954 errx(1, "invalid KDF info"); 955 if (!kdfhint) 956 errx(1, "invalid KDF hint"); 957 958 if (kdfhint->generic.len != sizeof(*kdfhint)) 959 errx(1, "KDF hint has invalid size"); 960 961 kdfinfo->flags = SR_CRYPTOKDF_KEY; 962 kdfinfo->len = sizeof(*kdfinfo); 963 964 derive_key(kdfhint->generic.type, kdfhint->rounds, 965 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 966 kdfhint->salt, sizeof(kdfhint->salt), 967 prompt, verify); 968 } 969 970 void 971 bio_kdf_generate(struct sr_crypto_kdfinfo *kdfinfo) 972 { 973 if (!kdfinfo) 974 errx(1, "invalid KDF info"); 975 976 if (rflag == -1) 977 rflag = bcrypt_pbkdf_autorounds(); 978 979 kdfinfo->pbkdf.generic.len = sizeof(kdfinfo->pbkdf); 980 kdfinfo->pbkdf.generic.type = SR_CRYPTOKDFT_BCRYPT_PBKDF; 981 kdfinfo->pbkdf.rounds = rflag; 982 983 kdfinfo->flags = SR_CRYPTOKDF_KEY | SR_CRYPTOKDF_HINT; 984 kdfinfo->len = sizeof(*kdfinfo); 985 986 /* generate salt */ 987 arc4random_buf(kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt)); 988 989 derive_key(kdfinfo->pbkdf.generic.type, kdfinfo->pbkdf.rounds, 990 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 991 kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt), 992 "New passphrase: ", interactive); 993 } 994 995 int 996 bio_parse_devlist(char *lst, dev_t *dt) 997 { 998 char *s, *e; 999 u_int32_t sz = 0; 1000 int no_dev = 0, i, x; 1001 struct stat sb; 1002 char dev[PATH_MAX]; 1003 int fd; 1004 1005 if (!lst) 1006 errx(1, "invalid device list"); 1007 1008 s = e = lst; 1009 /* make sure we have a valid device list like /dev/sdNa,/dev/sdNNa */ 1010 while (*e != '\0') { 1011 if (*e == ',') 1012 s = e + 1; 1013 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 1014 /* got one */ 1015 sz = e - s + 1; 1016 strlcpy(dev, s, sz + 1); 1017 fd = opendev(dev, O_RDONLY, OPENDEV_BLCK, NULL); 1018 if (fd == -1) 1019 err(1, "could not open %s", dev); 1020 if (fstat(fd, &sb) == -1) { 1021 int saved_errno = errno; 1022 close(fd); 1023 errc(1, saved_errno, "could not stat %s", dev); 1024 } 1025 close(fd); 1026 dt[no_dev] = sb.st_rdev; 1027 no_dev++; 1028 if (no_dev > (int)(BIOC_CRMAXLEN / sizeof(dev_t))) 1029 errx(1, "too many devices on device list"); 1030 } 1031 e++; 1032 } 1033 1034 for (i = 0; i < no_dev; i++) 1035 for (x = 0; x < no_dev; x++) 1036 if (dt[i] == dt[x] && x != i) 1037 errx(1, "duplicate device in list"); 1038 1039 return (no_dev); 1040 } 1041 1042 u_int32_t 1043 bio_createflags(char *lst) 1044 { 1045 char *s, *e, fs[32]; 1046 u_int32_t sz = 0; 1047 u_int32_t flags = 0; 1048 1049 if (!lst) 1050 errx(1, "invalid flags list"); 1051 1052 s = e = lst; 1053 /* make sure we have a valid flags list like force,noassemeble */ 1054 while (*e != '\0') { 1055 if (*e == ',') 1056 s = e + 1; 1057 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 1058 /* got one */ 1059 sz = e - s + 1; 1060 switch (s[0]) { 1061 case 'f': 1062 flags |= BIOC_SCFORCE; 1063 break; 1064 case 'n': 1065 flags |= BIOC_SCNOAUTOASSEMBLE; 1066 break; 1067 default: 1068 strlcpy(fs, s, sz + 1); 1069 errx(1, "invalid flag %s", fs); 1070 } 1071 } 1072 e++; 1073 } 1074 1075 return (flags); 1076 } 1077 1078 void 1079 bio_deleteraid(char *dev) 1080 { 1081 struct bioc_deleteraid bd; 1082 memset(&bd, 0, sizeof(bd)); 1083 1084 bd.bd_bio.bio_cookie = bio_cookie; 1085 /* XXX make this a dev_t instead of a string */ 1086 strlcpy(bd.bd_dev, dev, sizeof bd.bd_dev); 1087 if (ioctl(devh, BIOCDELETERAID, &bd) == -1) 1088 err(1, "BIOCDELETERAID"); 1089 1090 bio_status(&bd.bd_bio.bio_status); 1091 } 1092 1093 void 1094 bio_changepass(char *dev) 1095 { 1096 struct bioc_discipline bd; 1097 struct sr_crypto_kdfpair kdfpair; 1098 struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2; 1099 struct sr_crypto_pbkdf kdfhint; 1100 int rv; 1101 1102 memset(&bd, 0, sizeof(bd)); 1103 memset(&kdfhint, 0, sizeof(kdfhint)); 1104 memset(&kdfinfo1, 0, sizeof(kdfinfo1)); 1105 memset(&kdfinfo2, 0, sizeof(kdfinfo2)); 1106 1107 /* XXX use dev_t instead of string. */ 1108 strlcpy(bd.bd_dev, dev, sizeof(bd.bd_dev)); 1109 bd.bd_cmd = SR_IOCTL_GET_KDFHINT; 1110 bd.bd_size = sizeof(kdfhint); 1111 bd.bd_data = &kdfhint; 1112 1113 if (ioctl(devh, BIOCDISCIPLINE, &bd) == -1) 1114 err(1, "BIOCDISCIPLINE"); 1115 1116 bio_status(&bd.bd_bio.bio_status); 1117 1118 /* Current passphrase. */ 1119 bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0); 1120 1121 if (rflag == -1) { 1122 rflag = bcrypt_pbkdf_autorounds(); 1123 1124 /* Use previous number of rounds for the same KDF if higher. */ 1125 if (kdfhint.generic.type == SR_CRYPTOKDFT_BCRYPT_PBKDF && 1126 rflag < kdfhint.rounds) 1127 rflag = kdfhint.rounds; 1128 } 1129 1130 /* New passphrase. */ 1131 bio_kdf_generate(&kdfinfo2); 1132 1133 kdfpair.kdfinfo1 = &kdfinfo1; 1134 kdfpair.kdfsize1 = sizeof(kdfinfo1); 1135 kdfpair.kdfinfo2 = &kdfinfo2; 1136 kdfpair.kdfsize2 = sizeof(kdfinfo2); 1137 1138 bd.bd_cmd = SR_IOCTL_CHANGE_PASSPHRASE; 1139 bd.bd_size = sizeof(kdfpair); 1140 bd.bd_data = &kdfpair; 1141 1142 rv = ioctl(devh, BIOCDISCIPLINE, &bd); 1143 1144 memset(&kdfhint, 0, sizeof(kdfhint)); 1145 explicit_bzero(&kdfinfo1, sizeof(kdfinfo1)); 1146 explicit_bzero(&kdfinfo2, sizeof(kdfinfo2)); 1147 1148 if (rv == -1) 1149 err(1, "BIOCDISCIPLINE"); 1150 1151 bio_status(&bd.bd_bio.bio_status); 1152 } 1153 1154 #define BIOCTL_VIS_NBUF 4 1155 #define BIOCTL_VIS_BUFLEN 80 1156 1157 char * 1158 bio_vis(char *s) 1159 { 1160 static char rbuf[BIOCTL_VIS_NBUF][BIOCTL_VIS_BUFLEN]; 1161 static uint idx = 0; 1162 char *buf; 1163 1164 buf = rbuf[idx++]; 1165 if (idx == BIOCTL_VIS_NBUF) 1166 idx = 0; 1167 1168 strnvis(buf, s, BIOCTL_VIS_BUFLEN, VIS_NL|VIS_CSTYLE); 1169 return (buf); 1170 } 1171 1172 void 1173 bio_diskinq(char *sd_dev) 1174 { 1175 struct dk_inquiry di; 1176 1177 if (ioctl(devh, DIOCINQ, &di) == -1) 1178 err(1, "DIOCINQ"); 1179 1180 printf("%s: <%s, %s, %s>, serial %s\n", sd_dev, bio_vis(di.vendor), 1181 bio_vis(di.product), bio_vis(di.revision), bio_vis(di.serial)); 1182 } 1183 1184 void 1185 bio_patrol(char *arg) 1186 { 1187 struct bioc_patrol bp; 1188 struct timing timing; 1189 const char *errstr; 1190 1191 memset(&bp, 0, sizeof(bp)); 1192 bp.bp_bio.bio_cookie = bio_cookie; 1193 1194 switch (arg[0]) { 1195 case 'a': 1196 bp.bp_opcode = BIOC_SPAUTO; 1197 break; 1198 1199 case 'm': 1200 bp.bp_opcode = BIOC_SPMANUAL; 1201 break; 1202 1203 case 'd': 1204 bp.bp_opcode = BIOC_SPDISABLE; 1205 break; 1206 1207 case 'g': /* get patrol state */ 1208 bp.bp_opcode = BIOC_GPSTATUS; 1209 break; 1210 1211 case 's': /* start/stop patrol */ 1212 if (strncmp("sta", arg, 3) == 0) 1213 bp.bp_opcode = BIOC_SPSTART; 1214 else 1215 bp.bp_opcode = BIOC_SPSTOP; 1216 break; 1217 1218 default: 1219 errx(1, "invalid patrol function: %s", arg); 1220 } 1221 1222 switch (arg[0]) { 1223 case 'a': 1224 errstr = str2patrol(arg, &timing); 1225 if (errstr) 1226 errx(1, "Patrol %s: %s", arg, errstr); 1227 bp.bp_autoival = timing.interval; 1228 bp.bp_autonext = timing.start; 1229 break; 1230 } 1231 1232 if (ioctl(devh, BIOCPATROL, &bp) == -1) 1233 err(1, "BIOCPATROL"); 1234 1235 bio_status(&bp.bp_bio.bio_status); 1236 1237 if (arg[0] == 'g') { 1238 const char *mode, *status; 1239 char interval[40]; 1240 1241 interval[0] = '\0'; 1242 1243 switch (bp.bp_mode) { 1244 case BIOC_SPMAUTO: 1245 mode = "auto"; 1246 snprintf(interval, sizeof interval, 1247 " interval=%d next=%d", bp.bp_autoival, 1248 bp.bp_autonext - bp.bp_autonow); 1249 break; 1250 case BIOC_SPMMANUAL: 1251 mode = "manual"; 1252 break; 1253 case BIOC_SPMDISABLED: 1254 mode = "disabled"; 1255 break; 1256 default: 1257 mode = "unknown"; 1258 break; 1259 } 1260 switch (bp.bp_status) { 1261 case BIOC_SPSSTOPPED: 1262 status = "stopped"; 1263 break; 1264 case BIOC_SPSREADY: 1265 status = "ready"; 1266 break; 1267 case BIOC_SPSACTIVE: 1268 status = "active"; 1269 break; 1270 case BIOC_SPSABORTED: 1271 status = "aborted"; 1272 break; 1273 default: 1274 status = "unknown"; 1275 break; 1276 } 1277 printf("patrol mode: %s%s\n", mode, interval); 1278 printf("patrol status: %s\n", status); 1279 } 1280 } 1281 1282 /* 1283 * Measure this system's performance by measuring the time for 100 rounds. 1284 * We are aiming for something that takes around 1s. 1285 */ 1286 int 1287 bcrypt_pbkdf_autorounds(void) 1288 { 1289 struct timespec before, after; 1290 char buf[SR_CRYPTO_MAXKEYBYTES], salt[128]; 1291 int r = 100; 1292 int duration; 1293 1294 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before); 1295 if (bcrypt_pbkdf("testpassword", strlen("testpassword"), 1296 salt, sizeof(salt), buf, sizeof(buf), r) != 0) 1297 errx(1, "bcrypt pbkdf failed"); 1298 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after); 1299 1300 duration = after.tv_sec - before.tv_sec; 1301 duration *= 1000000; 1302 duration += (after.tv_nsec - before.tv_nsec) / 1000; 1303 1304 duration /= r; 1305 r = 1000000 / duration; 1306 1307 if (r < 16) 1308 r = 16; 1309 1310 return r; 1311 } 1312 1313 void 1314 derive_key(u_int32_t type, int rounds, u_int8_t *key, size_t keysz, 1315 u_int8_t *salt, size_t saltsz, char *prompt, int verify) 1316 { 1317 FILE *f; 1318 size_t pl; 1319 struct stat sb; 1320 char passphrase[1024], verifybuf[1024]; 1321 int rpp_flag = RPP_ECHO_OFF; 1322 1323 if (!key) 1324 errx(1, "Invalid key"); 1325 if (!salt) 1326 errx(1, "Invalid salt"); 1327 1328 if (type != SR_CRYPTOKDFT_PKCS5_PBKDF2 && 1329 type != SR_CRYPTOKDFT_BCRYPT_PBKDF) 1330 errx(1, "unknown KDF type %d", type); 1331 1332 if (rounds < (type == SR_CRYPTOKDFT_PKCS5_PBKDF2 ? 1000 : 16)) 1333 errx(1, "number of KDF rounds is too small: %d", rounds); 1334 1335 /* get passphrase */ 1336 if (passfile) { 1337 if ((f = fopen(passfile, "r")) == NULL) 1338 err(1, "invalid passphrase file"); 1339 1340 if (fstat(fileno(f), &sb) == -1) 1341 err(1, "can't stat passphrase file"); 1342 if (sb.st_uid != 0) 1343 errx(1, "passphrase file must be owned by root"); 1344 if ((sb.st_mode & ~S_IFMT) != (S_IRUSR | S_IWUSR)) 1345 errx(1, "passphrase file has the wrong permissions"); 1346 1347 if (fgets(passphrase, sizeof(passphrase), f) == NULL) 1348 err(1, "can't read passphrase file"); 1349 pl = strlen(passphrase); 1350 if (pl > 0 && passphrase[pl - 1] == '\n') 1351 passphrase[pl - 1] = '\0'; 1352 else 1353 errx(1, "invalid passphrase length"); 1354 1355 fclose(f); 1356 } else { 1357 rpp_flag |= interactive ? RPP_REQUIRE_TTY : RPP_STDIN; 1358 1359 retry: 1360 if (readpassphrase(prompt, passphrase, sizeof(passphrase), 1361 rpp_flag) == NULL) 1362 err(1, "unable to read passphrase"); 1363 if (*passphrase == '\0') { 1364 warnx("invalid passphrase length"); 1365 if (interactive) 1366 goto retry; 1367 exit(1); 1368 } 1369 } 1370 1371 if (verify && !passfile) { 1372 /* request user to re-type it */ 1373 if (readpassphrase("Re-type passphrase: ", verifybuf, 1374 sizeof(verifybuf), rpp_flag) == NULL) { 1375 explicit_bzero(passphrase, sizeof(passphrase)); 1376 err(1, "unable to read passphrase"); 1377 } 1378 if ((strlen(passphrase) != strlen(verifybuf)) || 1379 (strcmp(passphrase, verifybuf) != 0)) { 1380 explicit_bzero(passphrase, sizeof(passphrase)); 1381 explicit_bzero(verifybuf, sizeof(verifybuf)); 1382 if (interactive) { 1383 warnx("Passphrases did not match, try again"); 1384 goto retry; 1385 } 1386 errx(1, "Passphrases did not match"); 1387 } 1388 /* forget the re-typed one */ 1389 explicit_bzero(verifybuf, sizeof(verifybuf)); 1390 } 1391 1392 /* derive key from passphrase */ 1393 if (type == SR_CRYPTOKDFT_PKCS5_PBKDF2) { 1394 if (verbose) 1395 printf("Deriving key using PKCS#5 PBKDF2 with %i rounds...\n", 1396 rounds); 1397 if (pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltsz, 1398 key, keysz, rounds) != 0) 1399 errx(1, "pkcs5_pbkdf2 failed"); 1400 } else if (type == SR_CRYPTOKDFT_BCRYPT_PBKDF) { 1401 if (verbose) 1402 printf("Deriving key using bcrypt PBKDF with %i rounds...\n", 1403 rounds); 1404 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, saltsz, 1405 key, keysz, rounds) != 0) 1406 errx(1, "bcrypt_pbkdf failed"); 1407 } else { 1408 errx(1, "unknown KDF type %d", type); 1409 } 1410 1411 /* forget passphrase */ 1412 explicit_bzero(passphrase, sizeof(passphrase)); 1413 } 1414