1 /* $OpenBSD: bioctl.c,v 1.157 2023/10/07 12:20:10 kn 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" 292 " %s [-dhiPqsv] " 293 "[-C flag[,...]] [-c raidlevel] [-k keydisk]\n" 294 "\t[-l chunk[,...]] " 295 "[-O device | channel:target[.lun]]\n" 296 "\t[-p passfile] [-R chunk | channel:target[.lun]]\n" 297 "\t[-r rounds] " 298 "device\n", __progname, __progname); 299 300 exit(1); 301 } 302 303 const char * 304 str2locator(const char *string, struct locator *location) 305 { 306 const char *errstr; 307 char parse[80], *targ, *lun; 308 309 strlcpy(parse, string, sizeof parse); 310 targ = strchr(parse, ':'); 311 if (targ == NULL) 312 return ("target not specified"); 313 *targ++ = '\0'; 314 315 lun = strchr(targ, '.'); 316 if (lun != NULL) { 317 *lun++ = '\0'; 318 location->lun = strtonum(lun, 0, 256, &errstr); 319 if (errstr) 320 return (errstr); 321 } else 322 location->lun = 0; 323 324 location->target = strtonum(targ, 0, 256, &errstr); 325 if (errstr) 326 return (errstr); 327 location->channel = strtonum(parse, 0, 256, &errstr); 328 if (errstr) 329 return (errstr); 330 return (NULL); 331 } 332 333 const char * 334 str2patrol(const char *string, struct timing *timing) 335 { 336 const char *errstr; 337 char parse[80], *interval = NULL, *start = NULL; 338 339 timing->interval = 0; 340 timing->start = 0; 341 342 strlcpy(parse, string, sizeof parse); 343 344 interval = strchr(parse, '.'); 345 if (interval != NULL) { 346 *interval++ = '\0'; 347 start = strchr(interval, '.'); 348 if (start != NULL) 349 *start++ = '\0'; 350 } 351 if (interval != NULL) { 352 /* -1 == continuously */ 353 timing->interval = strtonum(interval, -1, INT_MAX, &errstr); 354 if (errstr) 355 return (errstr); 356 } 357 if (start != NULL) { 358 timing->start = strtonum(start, 0, INT_MAX, &errstr); 359 if (errstr) 360 return (errstr); 361 } 362 363 return (NULL); 364 } 365 366 void 367 bio_status(struct bio_status *bs) 368 { 369 extern char *__progname; 370 char *prefix; 371 int i; 372 373 if (strlen(bs->bs_controller)) 374 prefix = bs->bs_controller; 375 else 376 prefix = __progname; 377 378 for (i = 0; i < bs->bs_msg_count; i++) 379 fprintf(bs->bs_msgs[i].bm_type == BIO_MSG_INFO ? 380 stdout : stderr, "%s: %s\n", prefix, bs->bs_msgs[i].bm_msg); 381 382 if (bs->bs_status == BIO_STATUS_ERROR) { 383 if (bs->bs_msg_count == 0) 384 errx(1, "unknown error"); 385 else 386 exit(1); 387 } 388 } 389 390 void 391 bio_inq(char *name) 392 { 393 char *status, *cache; 394 char size[64], scsiname[16], volname[32]; 395 char percent[20], seconds[20]; 396 int i, d, volheader, hotspare, unused; 397 char encname[16], serial[32]; 398 struct bioc_inq bi; 399 struct bioc_vol bv; 400 struct bioc_disk bd; 401 402 memset(&bi, 0, sizeof(bi)); 403 404 bi.bi_bio.bio_cookie = bio_cookie; 405 406 if (ioctl(devh, BIOCINQ, &bi) == -1) { 407 if (errno == ENOTTY) 408 bio_diskinq(name); 409 else 410 err(1, "BIOCINQ"); 411 return; 412 } 413 414 bio_status(&bi.bi_bio.bio_status); 415 416 volheader = 0; 417 for (i = 0; i < bi.bi_novol; i++) { 418 memset(&bv, 0, sizeof(bv)); 419 bv.bv_bio.bio_cookie = bio_cookie; 420 bv.bv_volid = i; 421 bv.bv_percent = -1; 422 bv.bv_seconds = 0; 423 424 if (ioctl(devh, BIOCVOL, &bv) == -1) 425 err(1, "BIOCVOL"); 426 427 bio_status(&bv.bv_bio.bio_status); 428 429 if (name && strcmp(name, bv.bv_dev) != 0) 430 continue; 431 432 if (!volheader) { 433 volheader = 1; 434 printf("%-11s %-10s %14s %-8s\n", 435 "Volume", "Status", "Size", "Device"); 436 } 437 438 percent[0] = '\0'; 439 seconds[0] = '\0'; 440 if (bv.bv_percent != -1) 441 snprintf(percent, sizeof percent, 442 " %d%% done", bv.bv_percent); 443 if (bv.bv_seconds) 444 snprintf(seconds, sizeof seconds, 445 " %u seconds", bv.bv_seconds); 446 switch (bv.bv_status) { 447 case BIOC_SVONLINE: 448 status = BIOC_SVONLINE_S; 449 break; 450 case BIOC_SVOFFLINE: 451 status = BIOC_SVOFFLINE_S; 452 break; 453 case BIOC_SVDEGRADED: 454 status = BIOC_SVDEGRADED_S; 455 break; 456 case BIOC_SVBUILDING: 457 status = BIOC_SVBUILDING_S; 458 break; 459 case BIOC_SVREBUILD: 460 status = BIOC_SVREBUILD_S; 461 break; 462 case BIOC_SVSCRUB: 463 status = BIOC_SVSCRUB_S; 464 break; 465 case BIOC_SVINVALID: 466 default: 467 status = BIOC_SVINVALID_S; 468 } 469 switch (bv.bv_cache) { 470 case BIOC_CVWRITEBACK: 471 cache = BIOC_CVWRITEBACK_S; 472 break; 473 case BIOC_CVWRITETHROUGH: 474 cache = BIOC_CVWRITETHROUGH_S; 475 break; 476 case BIOC_CVUNKNOWN: 477 default: 478 cache = BIOC_CVUNKNOWN_S; 479 } 480 481 snprintf(volname, sizeof volname, "%s %u", 482 bi.bi_dev, bv.bv_volid); 483 484 unused = 0; 485 hotspare = 0; 486 if (bv.bv_level == -1 && bv.bv_nodisk == 1) 487 hotspare = 1; 488 else if (bv.bv_level == -2 && bv.bv_nodisk == 1) 489 unused = 1; 490 else { 491 if (human) 492 fmt_scaled(bv.bv_size, size); 493 else 494 snprintf(size, sizeof size, "%14llu", 495 bv.bv_size); 496 printf("%11s %-10s %14s %-7s ", 497 volname, status, size, bv.bv_dev); 498 switch (bv.bv_level) { 499 case 'C': 500 printf("CRYPTO%s%s\n", 501 percent, seconds); 502 break; 503 case 'c': 504 printf("CONCAT%s%s\n", 505 percent, seconds); 506 break; 507 case 0x1C: 508 case 0x1E: 509 printf("RAID%X%s%s %s\n", 510 bv.bv_level, percent, seconds, cache); 511 break; 512 default: 513 printf("RAID%u%s%s %s\n", 514 bv.bv_level, percent, seconds, cache); 515 break; 516 } 517 518 } 519 520 for (d = 0; d < bv.bv_nodisk; d++) { 521 memset(&bd, 0, sizeof(bd)); 522 bd.bd_bio.bio_cookie = bio_cookie; 523 bd.bd_diskid = d; 524 bd.bd_volid = i; 525 bd.bd_patrol.bdp_percent = -1; 526 bd.bd_patrol.bdp_seconds = 0; 527 528 if (ioctl(devh, BIOCDISK, &bd) == -1) 529 err(1, "BIOCDISK"); 530 531 bio_status(&bd.bd_bio.bio_status); 532 533 switch (bd.bd_status) { 534 case BIOC_SDONLINE: 535 status = BIOC_SDONLINE_S; 536 break; 537 case BIOC_SDOFFLINE: 538 status = BIOC_SDOFFLINE_S; 539 break; 540 case BIOC_SDFAILED: 541 status = BIOC_SDFAILED_S; 542 break; 543 case BIOC_SDREBUILD: 544 status = BIOC_SDREBUILD_S; 545 break; 546 case BIOC_SDHOTSPARE: 547 status = BIOC_SDHOTSPARE_S; 548 break; 549 case BIOC_SDUNUSED: 550 status = BIOC_SDUNUSED_S; 551 break; 552 case BIOC_SDSCRUB: 553 status = BIOC_SDSCRUB_S; 554 break; 555 case BIOC_SDINVALID: 556 default: 557 status = BIOC_SDINVALID_S; 558 } 559 560 if (hotspare || unused) 561 ; /* use volname from parent volume */ 562 else 563 snprintf(volname, sizeof volname, " %3u", 564 bd.bd_diskid); 565 566 if (bv.bv_level == 'C' && bd.bd_size == 0) 567 snprintf(size, sizeof size, "%14s", "key disk"); 568 else if (human) 569 fmt_scaled(bd.bd_size, size); 570 else 571 snprintf(size, sizeof size, "%14llu", 572 bd.bd_size); 573 snprintf(scsiname, sizeof scsiname, 574 "%u:%u.%u", 575 bd.bd_channel, bd.bd_target, bd.bd_lun); 576 if (bd.bd_procdev[0]) 577 strlcpy(encname, bd.bd_procdev, sizeof encname); 578 else 579 strlcpy(encname, "noencl", sizeof encname); 580 if (bd.bd_serial[0]) 581 strlcpy(serial, bd.bd_serial, sizeof serial); 582 else 583 strlcpy(serial, "unknown serial", sizeof serial); 584 585 percent[0] = '\0'; 586 seconds[0] = '\0'; 587 if (bd.bd_patrol.bdp_percent != -1) 588 snprintf(percent, sizeof percent, 589 " patrol %d%% done", bd.bd_patrol.bdp_percent); 590 if (bd.bd_patrol.bdp_seconds) 591 snprintf(seconds, sizeof seconds, 592 " %u seconds", bd.bd_patrol.bdp_seconds); 593 594 printf("%11s %-10s %14s %-7s %-6s <%s>\n", 595 volname, status, size, scsiname, encname, 596 bd.bd_vendor); 597 if (verbose) 598 printf("%11s %-10s %14s %-7s %-6s '%s'%s%s\n", 599 "", "", "", "", "", serial, percent, seconds); 600 } 601 } 602 } 603 604 void 605 bio_alarm(char *arg) 606 { 607 struct bioc_alarm ba; 608 609 memset(&ba, 0, sizeof(ba)); 610 ba.ba_bio.bio_cookie = bio_cookie; 611 612 switch (arg[0]) { 613 case 'q': /* silence alarm */ 614 /* FALLTHROUGH */ 615 case 's': 616 ba.ba_opcode = BIOC_SASILENCE; 617 break; 618 619 case 'e': /* enable alarm */ 620 ba.ba_opcode = BIOC_SAENABLE; 621 break; 622 623 case 'd': /* disable alarm */ 624 ba.ba_opcode = BIOC_SADISABLE; 625 break; 626 627 case 't': /* test alarm */ 628 ba.ba_opcode = BIOC_SATEST; 629 break; 630 631 case 'g': /* get alarm state */ 632 ba.ba_opcode = BIOC_GASTATUS; 633 break; 634 635 default: 636 errx(1, "invalid alarm function: %s", arg); 637 } 638 639 if (ioctl(devh, BIOCALARM, &ba) == -1) 640 err(1, "BIOCALARM"); 641 642 bio_status(&ba.ba_bio.bio_status); 643 644 if (arg[0] == 'g') 645 printf("alarm is currently %s\n", 646 ba.ba_status ? "enabled" : "disabled"); 647 } 648 649 int 650 bio_getvolbyname(char *name) 651 { 652 int id = -1, i; 653 struct bioc_inq bi; 654 struct bioc_vol bv; 655 656 memset(&bi, 0, sizeof(bi)); 657 bi.bi_bio.bio_cookie = bio_cookie; 658 if (ioctl(devh, BIOCINQ, &bi) == -1) 659 err(1, "BIOCINQ"); 660 661 bio_status(&bi.bi_bio.bio_status); 662 663 for (i = 0; i < bi.bi_novol; i++) { 664 memset(&bv, 0, sizeof(bv)); 665 bv.bv_bio.bio_cookie = bio_cookie; 666 bv.bv_volid = i; 667 if (ioctl(devh, BIOCVOL, &bv) == -1) 668 err(1, "BIOCVOL"); 669 670 bio_status(&bv.bv_bio.bio_status); 671 672 if (name && strcmp(name, bv.bv_dev) != 0) 673 continue; 674 id = i; 675 break; 676 } 677 678 return (id); 679 } 680 681 void 682 bio_setstate(char *arg, int status, char *devicename) 683 { 684 struct bioc_setstate bs; 685 struct locator location; 686 struct stat sb; 687 const char *errstr; 688 689 memset(&bs, 0, sizeof(bs)); 690 if (stat(arg, &sb) == -1) { 691 /* use CTL */ 692 errstr = str2locator(arg, &location); 693 if (errstr) 694 errx(1, "Target %s: %s", arg, errstr); 695 bs.bs_channel = location.channel; 696 bs.bs_target = location.target; 697 bs.bs_lun = location.lun; 698 } else { 699 /* use other id */ 700 bs.bs_other_id = sb.st_rdev; 701 bs.bs_other_id_type = BIOC_SSOTHER_DEVT; 702 } 703 704 bs.bs_bio.bio_cookie = bio_cookie; 705 bs.bs_status = status; 706 707 if (status != BIOC_SSHOTSPARE) { 708 /* make sure user supplied a sd device */ 709 bs.bs_volid = bio_getvolbyname(devicename); 710 if (bs.bs_volid == -1) 711 errx(1, "invalid device %s", devicename); 712 } 713 714 if (ioctl(devh, BIOCSETSTATE, &bs) == -1) 715 err(1, "BIOCSETSTATE"); 716 717 bio_status(&bs.bs_bio.bio_status); 718 } 719 720 void 721 bio_setblink(char *name, char *arg, int blink) 722 { 723 struct locator location; 724 struct bioc_blink bb; 725 struct bioc_inq bi; 726 struct bioc_vol bv; 727 struct bioc_disk bd; 728 const char *errstr; 729 int v, d, rv; 730 731 errstr = str2locator(arg, &location); 732 if (errstr) 733 errx(1, "Target %s: %s", arg, errstr); 734 735 /* try setting blink on the device directly */ 736 memset(&bb, 0, sizeof(bb)); 737 bb.bb_bio.bio_cookie = bio_cookie; 738 bb.bb_status = blink; 739 bb.bb_target = location.target; 740 bb.bb_channel = location.channel; 741 rv = ioctl(devh, BIOCBLINK, &bb); 742 743 if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_UNKNOWN) 744 return; 745 746 if (rv == 0 && bb.bb_bio.bio_status.bs_status == BIO_STATUS_SUCCESS) { 747 bio_status(&bb.bb_bio.bio_status); 748 return; 749 } 750 751 /* if the blink didn't work, try to find something that will */ 752 753 memset(&bi, 0, sizeof(bi)); 754 bi.bi_bio.bio_cookie = bio_cookie; 755 if (ioctl(devh, BIOCINQ, &bi) == -1) 756 err(1, "BIOCINQ"); 757 758 bio_status(&bi.bi_bio.bio_status); 759 760 for (v = 0; v < bi.bi_novol; v++) { 761 memset(&bv, 0, sizeof(bv)); 762 bv.bv_bio.bio_cookie = bio_cookie; 763 bv.bv_volid = v; 764 if (ioctl(devh, BIOCVOL, &bv) == -1) 765 err(1, "BIOCVOL"); 766 767 bio_status(&bv.bv_bio.bio_status); 768 769 if (name && strcmp(name, bv.bv_dev) != 0) 770 continue; 771 772 for (d = 0; d < bv.bv_nodisk; d++) { 773 memset(&bd, 0, sizeof(bd)); 774 bd.bd_bio.bio_cookie = bio_cookie; 775 bd.bd_volid = v; 776 bd.bd_diskid = d; 777 778 if (ioctl(devh, BIOCDISK, &bd) == -1) 779 err(1, "BIOCDISK"); 780 781 bio_status(&bd.bd_bio.bio_status); 782 783 if (bd.bd_channel == location.channel && 784 bd.bd_target == location.target && 785 bd.bd_lun == location.lun) { 786 if (bd.bd_procdev[0] != '\0') 787 bio_blink(bd.bd_procdev, 788 location.target, blink); 789 else 790 warnx("Disk %s is not in an enclosure", 791 arg); 792 return; 793 } 794 } 795 } 796 797 warnx("Disk %s does not exist", arg); 798 } 799 800 void 801 bio_blink(char *enclosure, int target, int blinktype) 802 { 803 int bioh; 804 struct bio_locate bl; 805 struct bioc_blink blink; 806 807 bioh = open("/dev/bio", O_RDWR); 808 if (bioh == -1) 809 err(1, "Can't open %s", "/dev/bio"); 810 811 memset(&bl, 0, sizeof(bl)); 812 bl.bl_name = enclosure; 813 if (ioctl(bioh, BIOCLOCATE, &bl) == -1) 814 errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio"); 815 816 memset(&blink, 0, sizeof(blink)); 817 blink.bb_bio.bio_cookie = bio_cookie; 818 blink.bb_status = blinktype; 819 blink.bb_target = target; 820 821 if (ioctl(bioh, BIOCBLINK, &blink) == -1) 822 err(1, "BIOCBLINK"); 823 824 bio_status(&blink.bb_bio.bio_status); 825 826 close(bioh); 827 } 828 829 void 830 bio_createraid(u_int16_t level, char *dev_list, char *key_disk) 831 { 832 struct bioc_createraid create; 833 struct sr_crypto_kdfinfo kdfinfo; 834 struct sr_crypto_pbkdf kdfhint; 835 struct stat sb; 836 int rv, no_dev, fd; 837 dev_t *dt; 838 u_int16_t min_disks = 0; 839 840 if (!dev_list) 841 errx(1, "no devices specified"); 842 843 dt = calloc(1, BIOC_CRMAXLEN); 844 if (!dt) 845 err(1, "not enough memory for dev_t list"); 846 847 no_dev = bio_parse_devlist(dev_list, dt); 848 849 switch (level) { 850 case 0: 851 min_disks = 2; 852 break; 853 case 1: 854 min_disks = 2; 855 break; 856 case 5: 857 min_disks = 3; 858 break; 859 case 'C': 860 case 0x1C: 861 min_disks = 1; 862 break; 863 case 'c': 864 min_disks = 1; 865 break; 866 default: 867 errx(1, "unsupported RAID level"); 868 } 869 870 if (no_dev < min_disks) 871 errx(1, "not enough disks"); 872 873 /* for crypto raid we only allow one single chunk */ 874 if (level == 'C' && no_dev != min_disks) 875 errx(1, "not exactly one partition"); 876 877 memset(&create, 0, sizeof(create)); 878 create.bc_bio.bio_cookie = bio_cookie; 879 create.bc_level = level; 880 create.bc_dev_list_len = no_dev * sizeof(dev_t); 881 create.bc_dev_list = dt; 882 create.bc_flags = BIOC_SCDEVT | cflags; 883 create.bc_key_disk = NODEV; 884 885 if ((level == 'C' || level == 0x1C) && key_disk == NULL) { 886 887 memset(&kdfinfo, 0, sizeof(kdfinfo)); 888 memset(&kdfhint, 0, sizeof(kdfhint)); 889 890 create.bc_flags |= BIOC_SCNOAUTOASSEMBLE; 891 892 create.bc_opaque = &kdfhint; 893 create.bc_opaque_size = sizeof(kdfhint); 894 create.bc_opaque_flags = BIOC_SOOUT; 895 896 /* try to get KDF hint */ 897 if (ioctl(devh, BIOCCREATERAID, &create) == -1) 898 err(1, "ioctl"); 899 900 bio_status(&create.bc_bio.bio_status); 901 902 if (create.bc_opaque_status == BIOC_SOINOUT_OK) { 903 bio_kdf_derive(&kdfinfo, &kdfhint, "Passphrase: ", 0); 904 memset(&kdfhint, 0, sizeof(kdfhint)); 905 } else { 906 bio_kdf_generate(&kdfinfo); 907 } 908 909 create.bc_opaque = &kdfinfo; 910 create.bc_opaque_size = sizeof(kdfinfo); 911 create.bc_opaque_flags = BIOC_SOIN; 912 913 } else if ((level == 'C' || level == 0x1C) && key_disk != NULL) { 914 915 /* Get device number for key disk. */ 916 fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL); 917 if (fd == -1) 918 err(1, "could not open %s", key_disk); 919 if (fstat(fd, &sb) == -1) { 920 int saved_errno = errno; 921 close(fd); 922 errc(1, saved_errno, "could not stat %s", key_disk); 923 } 924 close(fd); 925 create.bc_key_disk = sb.st_rdev; 926 927 memset(&kdfinfo, 0, sizeof(kdfinfo)); 928 929 kdfinfo.genkdf.len = sizeof(kdfinfo.genkdf); 930 kdfinfo.genkdf.type = SR_CRYPTOKDFT_KEYDISK; 931 kdfinfo.len = sizeof(kdfinfo); 932 kdfinfo.flags = SR_CRYPTOKDF_HINT; 933 934 create.bc_opaque = &kdfinfo; 935 create.bc_opaque_size = sizeof(kdfinfo); 936 create.bc_opaque_flags = BIOC_SOIN; 937 938 } 939 940 rv = ioctl(devh, BIOCCREATERAID, &create); 941 explicit_bzero(&kdfinfo, sizeof(kdfinfo)); 942 if (rv == -1) 943 err(1, "BIOCCREATERAID"); 944 945 bio_status(&create.bc_bio.bio_status); 946 947 free(dt); 948 } 949 950 void 951 bio_kdf_derive(struct sr_crypto_kdfinfo *kdfinfo, struct sr_crypto_pbkdf 952 *kdfhint, char* prompt, int verify) 953 { 954 if (!kdfinfo) 955 errx(1, "invalid KDF info"); 956 if (!kdfhint) 957 errx(1, "invalid KDF hint"); 958 959 if (kdfhint->generic.len != sizeof(*kdfhint)) 960 errx(1, "KDF hint has invalid size"); 961 962 kdfinfo->flags = SR_CRYPTOKDF_KEY; 963 kdfinfo->len = sizeof(*kdfinfo); 964 965 derive_key(kdfhint->generic.type, kdfhint->rounds, 966 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 967 kdfhint->salt, sizeof(kdfhint->salt), 968 prompt, verify); 969 } 970 971 void 972 bio_kdf_generate(struct sr_crypto_kdfinfo *kdfinfo) 973 { 974 if (!kdfinfo) 975 errx(1, "invalid KDF info"); 976 977 if (rflag == -1) 978 rflag = bcrypt_pbkdf_autorounds(); 979 980 kdfinfo->pbkdf.generic.len = sizeof(kdfinfo->pbkdf); 981 kdfinfo->pbkdf.generic.type = SR_CRYPTOKDFT_BCRYPT_PBKDF; 982 kdfinfo->pbkdf.rounds = rflag; 983 984 kdfinfo->flags = SR_CRYPTOKDF_KEY | SR_CRYPTOKDF_HINT; 985 kdfinfo->len = sizeof(*kdfinfo); 986 987 /* generate salt */ 988 arc4random_buf(kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt)); 989 990 derive_key(kdfinfo->pbkdf.generic.type, kdfinfo->pbkdf.rounds, 991 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 992 kdfinfo->pbkdf.salt, sizeof(kdfinfo->pbkdf.salt), 993 "New passphrase: ", interactive); 994 } 995 996 int 997 bio_parse_devlist(char *lst, dev_t *dt) 998 { 999 char *s, *e; 1000 u_int32_t sz = 0; 1001 int no_dev = 0, i, x; 1002 struct stat sb; 1003 char dev[PATH_MAX]; 1004 int fd; 1005 1006 if (!lst) 1007 errx(1, "invalid device list"); 1008 1009 s = e = lst; 1010 /* make sure we have a valid device list like /dev/sdNa,/dev/sdNNa */ 1011 while (*e != '\0') { 1012 if (*e == ',') 1013 s = e + 1; 1014 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 1015 /* got one */ 1016 sz = e - s + 1; 1017 strlcpy(dev, s, sz + 1); 1018 fd = opendev(dev, O_RDONLY, OPENDEV_BLCK, NULL); 1019 if (fd == -1) 1020 err(1, "could not open %s", dev); 1021 if (fstat(fd, &sb) == -1) { 1022 int saved_errno = errno; 1023 close(fd); 1024 errc(1, saved_errno, "could not stat %s", dev); 1025 } 1026 close(fd); 1027 dt[no_dev] = sb.st_rdev; 1028 no_dev++; 1029 if (no_dev > (int)(BIOC_CRMAXLEN / sizeof(dev_t))) 1030 errx(1, "too many devices on device list"); 1031 } 1032 e++; 1033 } 1034 1035 for (i = 0; i < no_dev; i++) 1036 for (x = 0; x < no_dev; x++) 1037 if (dt[i] == dt[x] && x != i) 1038 errx(1, "duplicate device in list"); 1039 1040 return (no_dev); 1041 } 1042 1043 u_int32_t 1044 bio_createflags(char *lst) 1045 { 1046 char *s, *e, fs[32]; 1047 u_int32_t sz = 0; 1048 u_int32_t flags = 0; 1049 1050 if (!lst) 1051 errx(1, "invalid flags list"); 1052 1053 s = e = lst; 1054 /* make sure we have a valid flags list like force,noassemeble */ 1055 while (*e != '\0') { 1056 if (*e == ',') 1057 s = e + 1; 1058 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 1059 /* got one */ 1060 sz = e - s + 1; 1061 switch (s[0]) { 1062 case 'f': 1063 flags |= BIOC_SCFORCE; 1064 break; 1065 case 'n': 1066 flags |= BIOC_SCNOAUTOASSEMBLE; 1067 break; 1068 default: 1069 strlcpy(fs, s, sz + 1); 1070 errx(1, "invalid flag %s", fs); 1071 } 1072 } 1073 e++; 1074 } 1075 1076 return (flags); 1077 } 1078 1079 void 1080 bio_deleteraid(char *dev) 1081 { 1082 struct bioc_deleteraid bd; 1083 memset(&bd, 0, sizeof(bd)); 1084 1085 bd.bd_bio.bio_cookie = bio_cookie; 1086 /* XXX make this a dev_t instead of a string */ 1087 strlcpy(bd.bd_dev, dev, sizeof bd.bd_dev); 1088 if (ioctl(devh, BIOCDELETERAID, &bd) == -1) 1089 err(1, "BIOCDELETERAID"); 1090 1091 bio_status(&bd.bd_bio.bio_status); 1092 } 1093 1094 void 1095 bio_changepass(char *dev) 1096 { 1097 struct bioc_discipline bd; 1098 struct sr_crypto_kdfpair kdfpair; 1099 struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2; 1100 struct sr_crypto_pbkdf kdfhint; 1101 int rv; 1102 1103 memset(&bd, 0, sizeof(bd)); 1104 memset(&kdfhint, 0, sizeof(kdfhint)); 1105 memset(&kdfinfo1, 0, sizeof(kdfinfo1)); 1106 memset(&kdfinfo2, 0, sizeof(kdfinfo2)); 1107 1108 /* XXX use dev_t instead of string. */ 1109 strlcpy(bd.bd_dev, dev, sizeof(bd.bd_dev)); 1110 bd.bd_cmd = SR_IOCTL_GET_KDFHINT; 1111 bd.bd_size = sizeof(kdfhint); 1112 bd.bd_data = &kdfhint; 1113 1114 if (ioctl(devh, BIOCDISCIPLINE, &bd) == -1) 1115 err(1, "BIOCDISCIPLINE"); 1116 1117 bio_status(&bd.bd_bio.bio_status); 1118 1119 /* Current passphrase. */ 1120 bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0); 1121 1122 if (rflag == -1) { 1123 rflag = bcrypt_pbkdf_autorounds(); 1124 1125 /* Use previous number of rounds for the same KDF if higher. */ 1126 if (kdfhint.generic.type == SR_CRYPTOKDFT_BCRYPT_PBKDF && 1127 rflag < kdfhint.rounds) 1128 rflag = kdfhint.rounds; 1129 } 1130 1131 /* New passphrase. */ 1132 bio_kdf_generate(&kdfinfo2); 1133 1134 kdfpair.kdfinfo1 = &kdfinfo1; 1135 kdfpair.kdfsize1 = sizeof(kdfinfo1); 1136 kdfpair.kdfinfo2 = &kdfinfo2; 1137 kdfpair.kdfsize2 = sizeof(kdfinfo2); 1138 1139 bd.bd_cmd = SR_IOCTL_CHANGE_PASSPHRASE; 1140 bd.bd_size = sizeof(kdfpair); 1141 bd.bd_data = &kdfpair; 1142 1143 rv = ioctl(devh, BIOCDISCIPLINE, &bd); 1144 1145 memset(&kdfhint, 0, sizeof(kdfhint)); 1146 explicit_bzero(&kdfinfo1, sizeof(kdfinfo1)); 1147 explicit_bzero(&kdfinfo2, sizeof(kdfinfo2)); 1148 1149 if (rv == -1) 1150 err(1, "BIOCDISCIPLINE"); 1151 1152 bio_status(&bd.bd_bio.bio_status); 1153 } 1154 1155 #define BIOCTL_VIS_NBUF 4 1156 #define BIOCTL_VIS_BUFLEN 80 1157 1158 char * 1159 bio_vis(char *s) 1160 { 1161 static char rbuf[BIOCTL_VIS_NBUF][BIOCTL_VIS_BUFLEN]; 1162 static uint idx = 0; 1163 char *buf; 1164 1165 buf = rbuf[idx++]; 1166 if (idx == BIOCTL_VIS_NBUF) 1167 idx = 0; 1168 1169 strnvis(buf, s, BIOCTL_VIS_BUFLEN, VIS_NL|VIS_CSTYLE); 1170 return (buf); 1171 } 1172 1173 void 1174 bio_diskinq(char *sd_dev) 1175 { 1176 struct dk_inquiry di; 1177 1178 if (ioctl(devh, DIOCINQ, &di) == -1) 1179 err(1, "DIOCINQ"); 1180 1181 printf("%s: <%s, %s, %s>, serial %s\n", sd_dev, bio_vis(di.vendor), 1182 bio_vis(di.product), bio_vis(di.revision), bio_vis(di.serial)); 1183 } 1184 1185 void 1186 bio_patrol(char *arg) 1187 { 1188 struct bioc_patrol bp; 1189 struct timing timing; 1190 const char *errstr; 1191 1192 memset(&bp, 0, sizeof(bp)); 1193 bp.bp_bio.bio_cookie = bio_cookie; 1194 1195 switch (arg[0]) { 1196 case 'a': 1197 bp.bp_opcode = BIOC_SPAUTO; 1198 break; 1199 1200 case 'm': 1201 bp.bp_opcode = BIOC_SPMANUAL; 1202 break; 1203 1204 case 'd': 1205 bp.bp_opcode = BIOC_SPDISABLE; 1206 break; 1207 1208 case 'g': /* get patrol state */ 1209 bp.bp_opcode = BIOC_GPSTATUS; 1210 break; 1211 1212 case 's': /* start/stop patrol */ 1213 if (strncmp("sta", arg, 3) == 0) 1214 bp.bp_opcode = BIOC_SPSTART; 1215 else 1216 bp.bp_opcode = BIOC_SPSTOP; 1217 break; 1218 1219 default: 1220 errx(1, "invalid patrol function: %s", arg); 1221 } 1222 1223 switch (arg[0]) { 1224 case 'a': 1225 errstr = str2patrol(arg, &timing); 1226 if (errstr) 1227 errx(1, "Patrol %s: %s", arg, errstr); 1228 bp.bp_autoival = timing.interval; 1229 bp.bp_autonext = timing.start; 1230 break; 1231 } 1232 1233 if (ioctl(devh, BIOCPATROL, &bp) == -1) 1234 err(1, "BIOCPATROL"); 1235 1236 bio_status(&bp.bp_bio.bio_status); 1237 1238 if (arg[0] == 'g') { 1239 const char *mode, *status; 1240 char interval[40]; 1241 1242 interval[0] = '\0'; 1243 1244 switch (bp.bp_mode) { 1245 case BIOC_SPMAUTO: 1246 mode = "auto"; 1247 snprintf(interval, sizeof interval, 1248 " interval=%d next=%d", bp.bp_autoival, 1249 bp.bp_autonext - bp.bp_autonow); 1250 break; 1251 case BIOC_SPMMANUAL: 1252 mode = "manual"; 1253 break; 1254 case BIOC_SPMDISABLED: 1255 mode = "disabled"; 1256 break; 1257 default: 1258 mode = "unknown"; 1259 break; 1260 } 1261 switch (bp.bp_status) { 1262 case BIOC_SPSSTOPPED: 1263 status = "stopped"; 1264 break; 1265 case BIOC_SPSREADY: 1266 status = "ready"; 1267 break; 1268 case BIOC_SPSACTIVE: 1269 status = "active"; 1270 break; 1271 case BIOC_SPSABORTED: 1272 status = "aborted"; 1273 break; 1274 default: 1275 status = "unknown"; 1276 break; 1277 } 1278 printf("patrol mode: %s%s\n", mode, interval); 1279 printf("patrol status: %s\n", status); 1280 } 1281 } 1282 1283 /* 1284 * Measure this system's performance by measuring the time for 100 rounds. 1285 * We are aiming for something that takes around 1s. 1286 */ 1287 int 1288 bcrypt_pbkdf_autorounds(void) 1289 { 1290 struct timespec before, after; 1291 char buf[SR_CRYPTO_MAXKEYBYTES], salt[128]; 1292 int r = 100; 1293 int duration; 1294 1295 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before); 1296 if (bcrypt_pbkdf("testpassword", strlen("testpassword"), 1297 salt, sizeof(salt), buf, sizeof(buf), r) != 0) 1298 errx(1, "bcrypt pbkdf failed"); 1299 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after); 1300 1301 duration = after.tv_sec - before.tv_sec; 1302 duration *= 1000000; 1303 duration += (after.tv_nsec - before.tv_nsec) / 1000; 1304 1305 duration /= r; 1306 r = 1000000 / duration; 1307 1308 if (r < 16) 1309 r = 16; 1310 1311 return r; 1312 } 1313 1314 void 1315 derive_key(u_int32_t type, int rounds, u_int8_t *key, size_t keysz, 1316 u_int8_t *salt, size_t saltsz, char *prompt, int verify) 1317 { 1318 FILE *f; 1319 size_t pl; 1320 struct stat sb; 1321 char passphrase[1024], verifybuf[1024]; 1322 int rpp_flag = RPP_ECHO_OFF; 1323 1324 if (!key) 1325 errx(1, "Invalid key"); 1326 if (!salt) 1327 errx(1, "Invalid salt"); 1328 1329 if (type != SR_CRYPTOKDFT_PKCS5_PBKDF2 && 1330 type != SR_CRYPTOKDFT_BCRYPT_PBKDF) 1331 errx(1, "unknown KDF type %d", type); 1332 1333 if (rounds < (type == SR_CRYPTOKDFT_PKCS5_PBKDF2 ? 1000 : 16)) 1334 errx(1, "number of KDF rounds is too small: %d", rounds); 1335 1336 /* get passphrase */ 1337 if (passfile) { 1338 if ((f = fopen(passfile, "r")) == NULL) 1339 err(1, "invalid passphrase file"); 1340 1341 if (fstat(fileno(f), &sb) == -1) 1342 err(1, "can't stat passphrase file"); 1343 if (sb.st_uid != 0) 1344 errx(1, "passphrase file must be owned by root"); 1345 if ((sb.st_mode & ~S_IFMT) != (S_IRUSR | S_IWUSR)) 1346 errx(1, "passphrase file has the wrong permissions"); 1347 1348 if (fgets(passphrase, sizeof(passphrase), f) == NULL) 1349 err(1, "can't read passphrase file"); 1350 pl = strlen(passphrase); 1351 if (pl > 0 && passphrase[pl - 1] == '\n') 1352 passphrase[pl - 1] = '\0'; 1353 else 1354 errx(1, "invalid passphrase length"); 1355 1356 fclose(f); 1357 } else { 1358 rpp_flag |= interactive ? RPP_REQUIRE_TTY : RPP_STDIN; 1359 1360 retry: 1361 if (readpassphrase(prompt, passphrase, sizeof(passphrase), 1362 rpp_flag) == NULL) 1363 err(1, "unable to read passphrase"); 1364 if (*passphrase == '\0') { 1365 warnx("invalid passphrase length"); 1366 if (interactive) 1367 goto retry; 1368 exit(1); 1369 } 1370 } 1371 1372 if (verify && !passfile) { 1373 /* request user to re-type it */ 1374 if (readpassphrase("Re-type passphrase: ", verifybuf, 1375 sizeof(verifybuf), rpp_flag) == NULL) { 1376 explicit_bzero(passphrase, sizeof(passphrase)); 1377 err(1, "unable to read passphrase"); 1378 } 1379 if ((strlen(passphrase) != strlen(verifybuf)) || 1380 (strcmp(passphrase, verifybuf) != 0)) { 1381 explicit_bzero(passphrase, sizeof(passphrase)); 1382 explicit_bzero(verifybuf, sizeof(verifybuf)); 1383 if (interactive) { 1384 warnx("Passphrases did not match, try again"); 1385 goto retry; 1386 } 1387 errx(1, "Passphrases did not match"); 1388 } 1389 /* forget the re-typed one */ 1390 explicit_bzero(verifybuf, sizeof(verifybuf)); 1391 } 1392 1393 /* derive key from passphrase */ 1394 if (type == SR_CRYPTOKDFT_PKCS5_PBKDF2) { 1395 if (verbose) 1396 printf("Deriving key using PKCS#5 PBKDF2 with %i rounds...\n", 1397 rounds); 1398 if (pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltsz, 1399 key, keysz, rounds) != 0) 1400 errx(1, "pkcs5_pbkdf2 failed"); 1401 } else if (type == SR_CRYPTOKDFT_BCRYPT_PBKDF) { 1402 if (verbose) 1403 printf("Deriving key using bcrypt PBKDF with %i rounds...\n", 1404 rounds); 1405 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, saltsz, 1406 key, keysz, rounds) != 0) 1407 errx(1, "bcrypt_pbkdf failed"); 1408 } else { 1409 errx(1, "unknown KDF type %d", type); 1410 } 1411 1412 /* forget passphrase */ 1413 explicit_bzero(passphrase, sizeof(passphrase)); 1414 } 1415