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