1 /* $OpenBSD: bioctl.c,v 1.103 2011/08/01 08:23:52 matthieu 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/ioctl.h> 31 #include <sys/dkio.h> 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <dev/biovar.h> 36 #include <dev/softraidvar.h> 37 38 #include <errno.h> 39 #include <err.h> 40 #include <fcntl.h> 41 #include <util.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <unistd.h> 46 #include <ctype.h> 47 #include <vis.h> 48 #include <readpassphrase.h> 49 50 #include "pbkdf2.h" 51 52 struct locator { 53 int channel; 54 int target; 55 int lun; 56 }; 57 58 void usage(void); 59 const char *str2locator(const char *, struct locator *); 60 void cleanup(void); 61 int bio_parse_devlist(char *, dev_t *); 62 void bio_kdf_derive(struct sr_crypto_kdfinfo *, 63 struct sr_crypto_kdf_pbkdf2 *, char *, int); 64 void bio_kdf_generate(struct sr_crypto_kdfinfo *); 65 void derive_key_pkcs(int, u_int8_t *, size_t, u_int8_t *, 66 size_t, char *, int); 67 68 void bio_inq(char *); 69 void bio_alarm(char *); 70 int bio_getvolbyname(char *); 71 void bio_setstate(char *, int, char *); 72 void bio_setblink(char *, char *, int); 73 void bio_blink(char *, int, int); 74 struct sr_aoe_config *create_aoe(u_int16_t, char *); 75 void bio_createraid(u_int16_t, char *, char *); 76 void bio_deleteraid(char *); 77 void bio_changepass(char *); 78 u_int32_t bio_createflags(char *); 79 char *bio_vis(char *); 80 void bio_diskinq(char *); 81 82 int devh = -1; 83 int human; 84 int verbose; 85 u_int32_t cflags = 0; 86 int rflag = 8192; 87 char *password; 88 89 struct bio_locate bl; 90 int rpp_flag = RPP_REQUIRE_TTY; 91 92 int 93 main(int argc, char *argv[]) 94 { 95 extern char *optarg; 96 u_int64_t func = 0; 97 /* u_int64_t subfunc = 0; */ 98 char *devicename = NULL; 99 char *realname = NULL, *al_arg = NULL; 100 char *bl_arg = NULL, *dev_list = NULL; 101 char *key_disk = NULL; 102 const char *errstr; 103 int ch, rv, blink = 0, changepass = 0, diskinq = 0; 104 int ss_func = 0; 105 u_int16_t cr_level = 0; 106 int biodev = 0; 107 108 if (argc < 2) 109 usage(); 110 111 while ((ch = getopt(argc, argv, "a:b:C:c:dH:hik:l:Pp:qr:R:svu:")) != 112 -1) { 113 switch (ch) { 114 case 'a': /* alarm */ 115 func |= BIOC_ALARM; 116 al_arg = optarg; 117 break; 118 case 'b': /* blink */ 119 func |= BIOC_BLINK; 120 blink = BIOC_SBBLINK; 121 bl_arg = optarg; 122 break; 123 case 'C': /* creation flags */ 124 cflags = bio_createflags(optarg); 125 break; 126 case 'c': /* create */ 127 func |= BIOC_CREATERAID; 128 if (isdigit(*optarg)) { 129 cr_level = strtonum(optarg, 0, 10, &errstr); 130 if (errstr != NULL) 131 errx(1, "Invalid RAID level"); 132 } else 133 cr_level = *optarg; 134 break; 135 case 'd': 136 /* delete volume */ 137 func |= BIOC_DELETERAID; 138 break; 139 case 'u': /* unblink */ 140 func |= BIOC_BLINK; 141 blink = BIOC_SBUNBLINK; 142 bl_arg = optarg; 143 break; 144 case 'H': /* set hotspare */ 145 func |= BIOC_SETSTATE; 146 ss_func = BIOC_SSHOTSPARE; 147 al_arg = optarg; 148 break; 149 case 'h': 150 human = 1; 151 break; 152 case 'i': /* inquiry */ 153 func |= BIOC_INQ; 154 break; 155 case 'k': /* Key disk. */ 156 key_disk = optarg; 157 break; 158 case 'l': /* device list */ 159 func |= BIOC_DEVLIST; 160 dev_list = optarg; 161 break; 162 case 'P': 163 /* Change passphrase. */ 164 changepass = 1; 165 break; 166 case 'p': 167 password = optarg; 168 break; 169 case 'r': 170 rflag = strtonum(optarg, 1000, 1<<30, &errstr); 171 if (errstr != NULL) 172 errx(1, "Number of rounds is %s: %s", 173 errstr, optarg); 174 break; 175 case 'R': 176 /* rebuild to provided chunk/CTL */ 177 func |= BIOC_SETSTATE; 178 ss_func = BIOC_SSREBUILD; 179 al_arg = optarg; 180 break; 181 case 's': 182 rpp_flag = RPP_STDIN; 183 break; 184 case 'v': 185 verbose = 1; 186 break; 187 case 'q': 188 diskinq = 1; 189 break; 190 default: 191 usage(); 192 /* NOTREACHED */ 193 } 194 } 195 argc -= optind; 196 argv += optind; 197 198 if (argc != 1 || (changepass && func != 0)) 199 usage(); 200 201 if (func == 0) 202 func |= BIOC_INQ; 203 204 devicename = argv[0]; 205 if (devicename == NULL) 206 errx(1, "need device"); 207 208 devh = opendev(devicename, O_RDWR, OPENDEV_PART, &realname); 209 if (devh == -1) { 210 devh = open("/dev/bio", O_RDWR); 211 if (devh == -1) 212 err(1, "Can't open %s", "/dev/bio"); 213 214 bl.bl_name = devicename; 215 rv = ioctl(devh, BIOCLOCATE, &bl); 216 if (rv == -1) 217 errx(1, "Can't locate %s device via %s", 218 bl.bl_name, "/dev/bio"); 219 biodev = 1; 220 devicename = NULL; 221 } 222 223 if (diskinq) { 224 bio_diskinq(devicename); 225 } else if (changepass && !biodev) { 226 bio_changepass(devicename); 227 } else if (func & BIOC_INQ) { 228 bio_inq(devicename); 229 } else if (func == BIOC_ALARM) { 230 bio_alarm(al_arg); 231 } else if (func == BIOC_BLINK) { 232 bio_setblink(devicename, bl_arg, blink); 233 } else if (func == BIOC_SETSTATE) { 234 bio_setstate(al_arg, ss_func, argv[0]); 235 } else if (func == BIOC_DELETERAID && !biodev) { 236 bio_deleteraid(devicename); 237 } else if (func & BIOC_CREATERAID || func & BIOC_DEVLIST) { 238 if (!(func & BIOC_CREATERAID)) 239 errx(1, "need -c parameter"); 240 if (!(func & BIOC_DEVLIST)) 241 errx(1, "need -l parameter"); 242 if (!biodev) 243 errx(1, "must use bio device"); 244 bio_createraid(cr_level, dev_list, key_disk); 245 } 246 247 return (0); 248 } 249 250 void 251 usage(void) 252 { 253 extern char *__progname; 254 255 fprintf(stderr, 256 "usage: %s [-hiqv] [-a alarm-function] " 257 "[-b channel:target[.lun]]\n" 258 "\t[-H channel:target[.lun]] " 259 "[-R device | channel:target[.lun]]\n" 260 "\t[-u channel:target[.lun]] " 261 "device\n" 262 " %s [-dhiPqsv] " 263 "[-C flag[,flag,...]] [-c raidlevel] [-k keydisk]\n" 264 "\t[-l special[,special,...]] [-p passfile]\n" 265 "\t[-R device | channel:target[.lun]] [-r rounds] " 266 "device\n", __progname, __progname); 267 268 exit(1); 269 } 270 271 const char * 272 str2locator(const char *string, struct locator *location) 273 { 274 const char *errstr; 275 char parse[80], *targ, *lun; 276 277 strlcpy(parse, string, sizeof parse); 278 targ = strchr(parse, ':'); 279 if (targ == NULL) 280 return ("target not specified"); 281 *targ++ = '\0'; 282 283 lun = strchr(targ, '.'); 284 if (lun != NULL) { 285 *lun++ = '\0'; 286 location->lun = strtonum(lun, 0, 256, &errstr); 287 if (errstr) 288 return (errstr); 289 } else 290 location->lun = 0; 291 292 location->target = strtonum(targ, 0, 256, &errstr); 293 if (errstr) 294 return (errstr); 295 location->channel = strtonum(parse, 0, 256, &errstr); 296 if (errstr) 297 return (errstr); 298 return (NULL); 299 } 300 301 void 302 bio_inq(char *name) 303 { 304 char *status, size[64], scsiname[16], volname[32]; 305 char percent[10], seconds[20]; 306 int rv, i, d, volheader, hotspare, unused; 307 char encname[16], serial[32]; 308 struct bioc_disk bd; 309 struct bioc_inq bi; 310 struct bioc_vol bv; 311 312 memset(&bi, 0, sizeof(bi)); 313 314 bi.bi_cookie = bl.bl_cookie; 315 316 rv = ioctl(devh, BIOCINQ, &bi); 317 if (rv == -1) { 318 if (errno == ENOTTY) 319 bio_diskinq(name); 320 else 321 err(1, "BIOCINQ"); 322 return; 323 } 324 325 volheader = 0; 326 for (i = 0; i < bi.bi_novol; i++) { 327 memset(&bv, 0, sizeof(bv)); 328 bv.bv_cookie = bl.bl_cookie; 329 bv.bv_volid = i; 330 bv.bv_percent = -1; 331 bv.bv_seconds = 0; 332 333 rv = ioctl(devh, BIOCVOL, &bv); 334 if (rv == -1) 335 err(1, "BIOCVOL"); 336 337 if (name && strcmp(name, bv.bv_dev) != 0) 338 continue; 339 340 if (!volheader) { 341 volheader = 1; 342 printf("%-11s %-10s %14s %-8s\n", 343 "Volume", "Status", "Size", "Device"); 344 } 345 346 percent[0] = '\0'; 347 seconds[0] = '\0'; 348 if (bv.bv_percent != -1) 349 snprintf(percent, sizeof percent, 350 " %d%% done", bv.bv_percent); 351 if (bv.bv_seconds) 352 snprintf(seconds, sizeof seconds, 353 " %u seconds", bv.bv_seconds); 354 switch (bv.bv_status) { 355 case BIOC_SVONLINE: 356 status = BIOC_SVONLINE_S; 357 break; 358 case BIOC_SVOFFLINE: 359 status = BIOC_SVOFFLINE_S; 360 break; 361 case BIOC_SVDEGRADED: 362 status = BIOC_SVDEGRADED_S; 363 break; 364 case BIOC_SVBUILDING: 365 status = BIOC_SVBUILDING_S; 366 break; 367 case BIOC_SVREBUILD: 368 status = BIOC_SVREBUILD_S; 369 break; 370 case BIOC_SVSCRUB: 371 status = BIOC_SVSCRUB_S; 372 break; 373 case BIOC_SVINVALID: 374 default: 375 status = BIOC_SVINVALID_S; 376 } 377 378 snprintf(volname, sizeof volname, "%s %u", 379 bi.bi_dev, bv.bv_volid); 380 381 unused = 0; 382 hotspare = 0; 383 if (bv.bv_level == -1 && bv.bv_nodisk == 1) 384 hotspare = 1; 385 else if (bv.bv_level == -2 && bv.bv_nodisk == 1) 386 unused = 1; 387 else { 388 if (human) 389 fmt_scaled(bv.bv_size, size); 390 else 391 snprintf(size, sizeof size, "%14llu", 392 bv.bv_size); 393 switch (bv.bv_level) { 394 case 'C': 395 printf("%11s %-10s %14s %-7s CRYPTO%s%s\n", 396 volname, status, size, bv.bv_dev, 397 percent, seconds); 398 break; 399 default: 400 printf("%11s %-10s %14s %-7s RAID%u%s%s\n", 401 volname, status, size, bv.bv_dev, 402 bv.bv_level, percent, seconds); 403 break; 404 } 405 406 } 407 408 for (d = 0; d < bv.bv_nodisk; d++) { 409 memset(&bd, 0, sizeof(bd)); 410 bd.bd_cookie = bl.bl_cookie; 411 bd.bd_diskid = d; 412 bd.bd_volid = i; 413 414 rv = ioctl(devh, BIOCDISK, &bd); 415 if (rv == -1) 416 err(1, "BIOCDISK"); 417 418 switch (bd.bd_status) { 419 case BIOC_SDONLINE: 420 status = BIOC_SDONLINE_S; 421 break; 422 case BIOC_SDOFFLINE: 423 status = BIOC_SDOFFLINE_S; 424 break; 425 case BIOC_SDFAILED: 426 status = BIOC_SDFAILED_S; 427 break; 428 case BIOC_SDREBUILD: 429 status = BIOC_SDREBUILD_S; 430 break; 431 case BIOC_SDHOTSPARE: 432 status = BIOC_SDHOTSPARE_S; 433 break; 434 case BIOC_SDUNUSED: 435 status = BIOC_SDUNUSED_S; 436 break; 437 case BIOC_SDSCRUB: 438 status = BIOC_SDSCRUB_S; 439 break; 440 case BIOC_SDINVALID: 441 default: 442 status = BIOC_SDINVALID_S; 443 } 444 445 if (hotspare || unused) 446 ; /* use volname from parent volume */ 447 else 448 snprintf(volname, sizeof volname, " %3u", 449 bd.bd_diskid); 450 451 if (bv.bv_level == 'C' && bd.bd_size == 0) 452 snprintf(size, sizeof size, "%14s", "key disk"); 453 else if (human) 454 fmt_scaled(bd.bd_size, size); 455 else 456 snprintf(size, sizeof size, "%14llu", 457 bd.bd_size); 458 snprintf(scsiname, sizeof scsiname, 459 "%u:%u.%u", 460 bd.bd_channel, bd.bd_target, bd.bd_lun); 461 if (bd.bd_procdev[0]) 462 strlcpy(encname, bd.bd_procdev, sizeof encname); 463 else 464 strlcpy(encname, "noencl", sizeof encname); 465 if (bd.bd_serial[0]) 466 strlcpy(serial, bd.bd_serial, sizeof serial); 467 else 468 strlcpy(serial, "unknown serial", sizeof serial); 469 470 printf("%11s %-10s %14s %-7s %-6s <%s>\n", 471 volname, status, size, scsiname, encname, 472 bd.bd_vendor); 473 if (verbose) 474 printf("%7s %-10s %14s %-7s %-6s '%s'\n", 475 "", "", "", "", "", serial); 476 } 477 } 478 } 479 480 void 481 bio_alarm(char *arg) 482 { 483 int rv; 484 struct bioc_alarm ba; 485 486 ba.ba_cookie = bl.bl_cookie; 487 488 switch (arg[0]) { 489 case 'q': /* silence alarm */ 490 /* FALLTHROUGH */ 491 case 's': 492 ba.ba_opcode = BIOC_SASILENCE; 493 break; 494 495 case 'e': /* enable alarm */ 496 ba.ba_opcode = BIOC_SAENABLE; 497 break; 498 499 case 'd': /* disable alarm */ 500 ba.ba_opcode = BIOC_SADISABLE; 501 break; 502 503 case 't': /* test alarm */ 504 ba.ba_opcode = BIOC_SATEST; 505 break; 506 507 case 'g': /* get alarm state */ 508 ba.ba_opcode = BIOC_GASTATUS; 509 break; 510 511 default: 512 errx(1, "invalid alarm function: %s", arg); 513 } 514 515 rv = ioctl(devh, BIOCALARM, &ba); 516 if (rv == -1) 517 err(1, "BIOCALARM"); 518 519 if (arg[0] == 'g') { 520 printf("alarm is currently %s\n", 521 ba.ba_status ? "enabled" : "disabled"); 522 523 } 524 } 525 526 int 527 bio_getvolbyname(char *name) 528 { 529 int id = -1, i, rv; 530 struct bioc_inq bi; 531 struct bioc_vol bv; 532 533 memset(&bi, 0, sizeof(bi)); 534 bi.bi_cookie = bl.bl_cookie; 535 rv = ioctl(devh, BIOCINQ, &bi); 536 if (rv == -1) 537 err(1, "BIOCINQ"); 538 539 for (i = 0; i < bi.bi_novol; i++) { 540 memset(&bv, 0, sizeof(bv)); 541 bv.bv_cookie = bl.bl_cookie; 542 bv.bv_volid = i; 543 rv = ioctl(devh, BIOCVOL, &bv); 544 if (rv == -1) 545 err(1, "BIOCVOL"); 546 547 if (name && strcmp(name, bv.bv_dev) != 0) 548 continue; 549 id = i; 550 break; 551 } 552 553 return (id); 554 } 555 556 void 557 bio_setstate(char *arg, int status, char *devicename) 558 { 559 struct bioc_setstate bs; 560 struct locator location; 561 struct stat sb; 562 const char *errstr; 563 int rv; 564 565 memset(&bs, 0, sizeof(bs)); 566 if (stat(arg, &sb) == -1) { 567 /* use CTL */ 568 errstr = str2locator(arg, &location); 569 if (errstr) 570 errx(1, "Target %s: %s", arg, errstr); 571 bs.bs_channel = location.channel; 572 bs.bs_target = location.target; 573 bs.bs_lun = location.lun; 574 } else { 575 /* use other id */ 576 bs.bs_other_id = sb.st_rdev; 577 bs.bs_other_id_type = BIOC_SSOTHER_DEVT; 578 } 579 580 bs.bs_cookie = bl.bl_cookie; 581 bs.bs_status = status; 582 583 if (status != BIOC_SSHOTSPARE) { 584 /* make sure user supplied a sd device */ 585 bs.bs_volid = bio_getvolbyname(devicename); 586 if (bs.bs_volid == -1) 587 errx(1, "invalid device %s", devicename); 588 } 589 590 rv = ioctl(devh, BIOCSETSTATE, &bs); 591 if (rv == -1) 592 err(1, "BIOCSETSTATE"); 593 } 594 595 void 596 bio_setblink(char *name, char *arg, int blink) 597 { 598 struct locator location; 599 struct bioc_inq bi; 600 struct bioc_vol bv; 601 struct bioc_disk bd; 602 struct bioc_blink bb; 603 const char *errstr; 604 int v, d, rv; 605 606 errstr = str2locator(arg, &location); 607 if (errstr) 608 errx(1, "Target %s: %s", arg, errstr); 609 610 /* try setting blink on the device directly */ 611 memset(&bb, 0, sizeof(bb)); 612 bb.bb_cookie = bl.bl_cookie; 613 bb.bb_status = blink; 614 bb.bb_target = location.target; 615 bb.bb_channel = location.channel; 616 rv = ioctl(devh, BIOCBLINK, &bb); 617 if (rv == 0) 618 return; 619 620 /* if the blink didn't work, try to find something that will */ 621 622 memset(&bi, 0, sizeof(bi)); 623 bi.bi_cookie = bl.bl_cookie; 624 rv = ioctl(devh, BIOCINQ, &bi); 625 if (rv == -1) 626 err(1, "BIOCINQ"); 627 628 for (v = 0; v < bi.bi_novol; v++) { 629 memset(&bv, 0, sizeof(bv)); 630 bv.bv_cookie = bl.bl_cookie; 631 bv.bv_volid = v; 632 rv = ioctl(devh, BIOCVOL, &bv); 633 if (rv == -1) 634 err(1, "BIOCVOL"); 635 636 if (name && strcmp(name, bv.bv_dev) != 0) 637 continue; 638 639 for (d = 0; d < bv.bv_nodisk; d++) { 640 memset(&bd, 0, sizeof(bd)); 641 bd.bd_cookie = bl.bl_cookie; 642 bd.bd_volid = v; 643 bd.bd_diskid = d; 644 645 rv = ioctl(devh, BIOCDISK, &bd); 646 if (rv == -1) 647 err(1, "BIOCDISK"); 648 649 if (bd.bd_channel == location.channel && 650 bd.bd_target == location.target && 651 bd.bd_lun == location.lun) { 652 if (bd.bd_procdev[0] != '\0') { 653 bio_blink(bd.bd_procdev, 654 location.target, blink); 655 } else 656 warnx("Disk %s is not in an enclosure", arg); 657 return; 658 } 659 } 660 } 661 662 warnx("Disk %s does not exist", arg); 663 return; 664 } 665 666 void 667 bio_blink(char *enclosure, int target, int blinktype) 668 { 669 int bioh; 670 struct bio_locate bio; 671 struct bioc_blink blink; 672 int rv; 673 674 bioh = open("/dev/bio", O_RDWR); 675 if (bioh == -1) 676 err(1, "Can't open %s", "/dev/bio"); 677 678 bio.bl_name = enclosure; 679 rv = ioctl(bioh, BIOCLOCATE, &bio); 680 if (rv == -1) 681 errx(1, "Can't locate %s device via %s", enclosure, "/dev/bio"); 682 683 memset(&blink, 0, sizeof(blink)); 684 blink.bb_cookie = bio.bl_cookie; 685 blink.bb_status = blinktype; 686 blink.bb_target = target; 687 688 rv = ioctl(bioh, BIOCBLINK, &blink); 689 if (rv == -1) 690 err(1, "BIOCBLINK"); 691 692 close(bioh); 693 } 694 695 struct sr_aoe_config * 696 create_aoe(u_int16_t level, char *dev_list) 697 { 698 static struct sr_aoe_config sac; 699 char *nic; 700 char *dsteaddr; 701 char *shelf; 702 char *slot; 703 struct ether_addr *eaddr; 704 const char *errstr; 705 706 nic = dsteaddr = slot = shelf = 0; 707 708 memset(&sac, 0, sizeof(sac)); 709 nic = dev_list; 710 dsteaddr = strchr(nic, ','); 711 if (!dsteaddr) 712 goto invalid; 713 *dsteaddr++ = '\0'; 714 shelf = strchr(dsteaddr, ','); 715 if (!shelf) 716 goto invalid; 717 *shelf++ = '\0'; 718 slot = strchr(shelf, ','); 719 if (!slot) 720 goto invalid; 721 *slot++ = '\0'; 722 strlcpy(sac.nic, nic, sizeof(sac.nic)); 723 eaddr = ether_aton(dsteaddr); 724 if (!eaddr) 725 goto invalid; 726 sac.dsteaddr = *eaddr; 727 sac.shelf = htons(strtonum(shelf, 0, 0xfffe, &errstr)); 728 if (errstr) 729 goto invalid; 730 sac.slot = strtonum(slot, 0, 0xfe, &errstr); 731 if (errstr) 732 goto invalid; 733 734 return &sac; 735 invalid: 736 errx(1, "invalid AOE dev list: use nic,dsteaddr,shelf,slot"); 737 } 738 739 void 740 bio_createraid(u_int16_t level, char *dev_list, char *key_disk) 741 { 742 struct bioc_createraid create; 743 struct sr_crypto_kdfinfo kdfinfo; 744 struct sr_crypto_kdf_pbkdf2 kdfhint; 745 struct sr_aoe_config *sac; 746 struct stat sb; 747 int rv, no_dev, fd; 748 dev_t *dt; 749 u_int16_t min_disks = 0; 750 751 if (!dev_list) 752 errx(1, "no devices specified"); 753 754 if (level == 'a') { 755 sac = create_aoe(level, dev_list); 756 no_dev = 0; 757 dt = NULL; 758 } else { 759 dt = (dev_t *)malloc(BIOC_CRMAXLEN); 760 if (!dt) 761 err(1, "not enough memory for dev_t list"); 762 memset(dt, 0, BIOC_CRMAXLEN); 763 764 no_dev = bio_parse_devlist(dev_list, dt); 765 } 766 767 switch (level) { 768 case 0: 769 min_disks = 2; 770 break; 771 case 1: 772 min_disks = 2; 773 break; 774 case 4: 775 case 5: 776 min_disks = 3; 777 break; 778 case 'C': 779 min_disks = 1; 780 break; 781 case 'c': 782 min_disks = 1; 783 break; 784 case 'a': 785 break; 786 default: 787 errx(1, "unsupported raid level"); 788 } 789 790 if (no_dev < min_disks) 791 errx(1, "not enough disks"); 792 793 /* for crypto raid we only allow one single chunk */ 794 if (level == 'C' && no_dev != min_disks) 795 errx(1, "not exactly one partition"); 796 797 memset(&create, 0, sizeof(create)); 798 create.bc_cookie = bl.bl_cookie; 799 create.bc_level = level; 800 create.bc_dev_list_len = no_dev * sizeof(dev_t); 801 create.bc_dev_list = dt; 802 create.bc_flags = BIOC_SCDEVT | cflags; 803 create.bc_key_disk = NODEV; 804 805 if (level == 'a') { 806 create.bc_opaque = sac; 807 create.bc_opaque_size = sizeof(*sac); 808 create.bc_opaque_flags = BIOC_SOIN; 809 } else if (level == 'C' && key_disk == NULL) { 810 811 memset(&kdfinfo, 0, sizeof(kdfinfo)); 812 memset(&kdfhint, 0, sizeof(kdfhint)); 813 814 create.bc_flags |= BIOC_SCNOAUTOASSEMBLE; 815 816 create.bc_opaque = &kdfhint; 817 create.bc_opaque_size = sizeof(kdfhint); 818 create.bc_opaque_flags = BIOC_SOOUT; 819 820 /* try to get KDF hint */ 821 if (ioctl(devh, BIOCCREATERAID, &create) == -1) 822 err(1, "ioctl"); 823 824 if (create.bc_opaque_status == BIOC_SOINOUT_OK) { 825 bio_kdf_derive(&kdfinfo, &kdfhint, "Passphrase: ", 0); 826 memset(&kdfhint, 0, sizeof(kdfhint)); 827 } else { 828 bio_kdf_generate(&kdfinfo); 829 } 830 831 create.bc_opaque = &kdfinfo; 832 create.bc_opaque_size = sizeof(kdfinfo); 833 create.bc_opaque_flags = BIOC_SOIN; 834 835 } else if (level == 'C' && key_disk != NULL) { 836 837 /* Get device number for key disk. */ 838 fd = opendev(key_disk, O_RDONLY, OPENDEV_BLCK, NULL); 839 if (fd == -1) 840 err(1, "could not open %s", key_disk); 841 if (fstat(fd, &sb) == -1) { 842 close(fd); 843 err(1, "could not stat %s", key_disk); 844 } 845 close(fd); 846 create.bc_key_disk = sb.st_rdev; 847 848 memset(&kdfinfo, 0, sizeof(kdfinfo)); 849 850 kdfinfo.genkdf.len = sizeof(kdfinfo.genkdf); 851 kdfinfo.genkdf.type = SR_CRYPTOKDFT_KEYDISK; 852 kdfinfo.len = sizeof(kdfinfo); 853 kdfinfo.flags = SR_CRYPTOKDF_HINT; 854 855 create.bc_opaque = &kdfinfo; 856 create.bc_opaque_size = sizeof(kdfinfo); 857 create.bc_opaque_flags = BIOC_SOIN; 858 859 } 860 861 rv = ioctl(devh, BIOCCREATERAID, &create); 862 memset(&kdfinfo, 0, sizeof(kdfinfo)); 863 memset(&create, 0, sizeof(create)); 864 if (rv == -1) { 865 if (errno == EPERM) 866 errx(1, "Incorrect passphrase"); 867 err(1, "BIOCCREATERAID"); 868 } 869 870 free(dt); 871 } 872 873 void 874 bio_kdf_derive(struct sr_crypto_kdfinfo *kdfinfo, struct sr_crypto_kdf_pbkdf2 875 *kdfhint, char* prompt, int verify) 876 { 877 if (!kdfinfo) 878 errx(1, "invalid KDF info"); 879 if (!kdfhint) 880 errx(1, "invalid KDF hint"); 881 882 if (kdfhint->len != sizeof(*kdfhint)) 883 errx(1, "KDF hint has invalid size"); 884 if (kdfhint->type != SR_CRYPTOKDFT_PBKDF2) 885 errx(1, "unknown KDF type %d", kdfhint->type); 886 if (kdfhint->rounds < 1000) 887 errx(1, "number of KDF rounds too low: %d", kdfhint->rounds); 888 889 kdfinfo->flags = SR_CRYPTOKDF_KEY; 890 kdfinfo->len = sizeof(*kdfinfo); 891 892 derive_key_pkcs(kdfhint->rounds, 893 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 894 kdfhint->salt, sizeof(kdfhint->salt), prompt, verify); 895 } 896 897 void 898 bio_kdf_generate(struct sr_crypto_kdfinfo *kdfinfo) 899 { 900 if (!kdfinfo) 901 errx(1, "invalid KDF info"); 902 903 kdfinfo->pbkdf2.len = sizeof(kdfinfo->pbkdf2); 904 kdfinfo->pbkdf2.type = SR_CRYPTOKDFT_PBKDF2; 905 kdfinfo->pbkdf2.rounds = rflag; 906 kdfinfo->len = sizeof(*kdfinfo); 907 kdfinfo->flags = SR_CRYPTOKDF_KEY | SR_CRYPTOKDF_HINT; 908 909 /* generate salt */ 910 arc4random_buf(kdfinfo->pbkdf2.salt, sizeof(kdfinfo->pbkdf2.salt)); 911 912 derive_key_pkcs(kdfinfo->pbkdf2.rounds, 913 kdfinfo->maskkey, sizeof(kdfinfo->maskkey), 914 kdfinfo->pbkdf2.salt, sizeof(kdfinfo->pbkdf2.salt), 915 "New passphrase: ", 1); 916 } 917 918 int 919 bio_parse_devlist(char *lst, dev_t *dt) 920 { 921 char *s, *e; 922 u_int32_t sz = 0; 923 int no_dev = 0, i, x; 924 struct stat sb; 925 char dev[MAXPATHLEN]; 926 int fd; 927 928 if (!lst) 929 errx(1, "invalid device list"); 930 931 s = e = lst; 932 /* make sure we have a valid device list like /dev/sdNa,/dev/sdNNa */ 933 while (*e != '\0') { 934 if (*e == ',') 935 s = e + 1; 936 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 937 /* got one */ 938 sz = e - s + 1; 939 strlcpy(dev, s, sz + 1); 940 fd = opendev(dev, O_RDONLY, OPENDEV_BLCK, NULL); 941 if (fd == -1) 942 err(1, "could not open %s", dev); 943 if (fstat(fd, &sb) == -1) { 944 close(fd); 945 err(1, "could not stat %s", dev); 946 } 947 close(fd); 948 dt[no_dev] = sb.st_rdev; 949 no_dev++; 950 if (no_dev > (int)(BIOC_CRMAXLEN / sizeof(dev_t))) 951 errx(1, "too many devices on device list"); 952 } 953 e++; 954 } 955 956 for (i = 0; i < no_dev; i++) 957 for (x = 0; x < no_dev; x++) 958 if (dt[i] == dt[x] && x != i) 959 errx(1, "duplicate device in list"); 960 961 return (no_dev); 962 } 963 964 u_int32_t 965 bio_createflags(char *lst) 966 { 967 char *s, *e, fs[32]; 968 u_int32_t sz = 0; 969 u_int32_t flags = 0; 970 971 if (!lst) 972 errx(1, "invalid flags list"); 973 974 s = e = lst; 975 /* make sure we have a valid flags list like force,noassemeble */ 976 while (*e != '\0') { 977 if (*e == ',') 978 s = e + 1; 979 else if (*(e + 1) == '\0' || *(e + 1) == ',') { 980 /* got one */ 981 sz = e - s + 1; 982 switch (s[0]) { 983 case 'f': 984 flags |= BIOC_SCFORCE; 985 break; 986 case 'n': 987 flags |= BIOC_SCNOAUTOASSEMBLE; 988 break; 989 default: 990 strlcpy(fs, s, sz + 1); 991 errx(1, "invalid flag %s", fs); 992 } 993 } 994 e++; 995 } 996 997 return (flags); 998 } 999 1000 void 1001 bio_deleteraid(char *dev) 1002 { 1003 struct bioc_deleteraid bd; 1004 memset(&bd, 0, sizeof(bd)); 1005 1006 bd.bd_cookie = bd.bd_cookie; 1007 /* XXX make this a dev_t instead of a string */ 1008 strlcpy(bd.bd_dev, dev, sizeof bd.bd_dev); 1009 if (ioctl(devh, BIOCDELETERAID, &bd)) 1010 errx(1, "delete volume %s failed", dev); 1011 } 1012 1013 void 1014 bio_changepass(char *dev) 1015 { 1016 struct bioc_discipline bd; 1017 struct sr_crypto_kdfpair kdfpair; 1018 struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2; 1019 struct sr_crypto_kdf_pbkdf2 kdfhint; 1020 int rv; 1021 1022 memset(&bd, 0, sizeof(bd)); 1023 memset(&kdfhint, 0, sizeof(kdfhint)); 1024 memset(&kdfinfo1, 0, sizeof(kdfinfo1)); 1025 memset(&kdfinfo2, 0, sizeof(kdfinfo2)); 1026 1027 /* XXX use dev_t instead of string. */ 1028 strlcpy(bd.bd_dev, dev, sizeof(bd.bd_dev)); 1029 bd.bd_cmd = SR_IOCTL_GET_KDFHINT; 1030 bd.bd_size = sizeof(kdfhint); 1031 bd.bd_data = &kdfhint; 1032 1033 if (ioctl(devh, BIOCDISCIPLINE, &bd)) 1034 errx(1, "%s: failed to get KDF hint", dev); 1035 1036 /* Current passphrase. */ 1037 bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0); 1038 1039 /* New passphrase. */ 1040 bio_kdf_derive(&kdfinfo2, &kdfhint, "New passphrase: ", 1); 1041 1042 kdfpair.kdfinfo1 = &kdfinfo1; 1043 kdfpair.kdfsize1 = sizeof(kdfinfo1); 1044 kdfpair.kdfinfo2 = &kdfinfo2; 1045 kdfpair.kdfsize2 = sizeof(kdfinfo2); 1046 1047 bd.bd_cmd = SR_IOCTL_CHANGE_PASSPHRASE; 1048 bd.bd_size = sizeof(kdfpair); 1049 bd.bd_data = &kdfpair; 1050 1051 rv = ioctl(devh, BIOCDISCIPLINE, &bd); 1052 1053 memset(&kdfhint, 0, sizeof(kdfhint)); 1054 memset(&kdfinfo1, 0, sizeof(kdfinfo1)); 1055 memset(&kdfinfo2, 0, sizeof(kdfinfo2)); 1056 1057 if (rv) { 1058 if (errno == EPERM) 1059 errx(1, "%s: incorrect passphrase", dev); 1060 else 1061 errx(1, "%s: failed to change passphrase", dev); 1062 } 1063 } 1064 1065 #define BIOCTL_VIS_NBUF 4 1066 #define BIOCTL_VIS_BUFLEN 80 1067 1068 char * 1069 bio_vis(char *s) 1070 { 1071 static char rbuf[BIOCTL_VIS_NBUF][BIOCTL_VIS_BUFLEN]; 1072 static uint idx = 0; 1073 char *buf; 1074 1075 buf = rbuf[idx++]; 1076 if (idx == BIOCTL_VIS_NBUF) 1077 idx = 0; 1078 1079 strnvis(buf, s, BIOCTL_VIS_BUFLEN, VIS_NL|VIS_CSTYLE); 1080 return (buf); 1081 } 1082 1083 void 1084 bio_diskinq(char *sd_dev) 1085 { 1086 struct dk_inquiry di; 1087 1088 if (ioctl(devh, DIOCINQ, &di) == -1) 1089 err(1, "DIOCINQ"); 1090 1091 printf("%s: <%s, %s, %s>, serial %s\n", sd_dev, bio_vis(di.vendor), 1092 bio_vis(di.product), bio_vis(di.revision), bio_vis(di.serial)); 1093 } 1094 1095 void 1096 derive_key_pkcs(int rounds, u_int8_t *key, size_t keysz, u_int8_t *salt, 1097 size_t saltsz, char *prompt, int verify) 1098 { 1099 FILE *f; 1100 size_t pl; 1101 struct stat sb; 1102 char passphrase[1024], verifybuf[1024]; 1103 1104 if (!key) 1105 errx(1, "Invalid key"); 1106 if (!salt) 1107 errx(1, "Invalid salt"); 1108 if (rounds < 1000) 1109 errx(1, "Too few rounds: %d", rounds); 1110 1111 /* get passphrase */ 1112 if (password && verify) 1113 errx(1, "can't specify passphrase file during initial " 1114 "creation of crypto volume"); 1115 if (password) { 1116 if ((f = fopen(password, "r")) == NULL) 1117 err(1, "invalid passphrase file"); 1118 1119 if (fstat(fileno(f), &sb) == -1) 1120 err(1, "can't stat passphrase file"); 1121 if (sb.st_uid != 0) 1122 errx(1, "passphrase file must be owned by root"); 1123 if ((sb.st_mode & ~S_IFMT) != (S_IRUSR | S_IWUSR)) 1124 errx(1, "passphrase file has the wrong permissions"); 1125 1126 if (fgets(passphrase, sizeof(passphrase), f) == NULL) 1127 err(1, "can't read passphrase file"); 1128 pl = strlen(passphrase); 1129 if (pl > 0 && passphrase[pl - 1] == '\n') 1130 passphrase[pl - 1] = '\0'; 1131 else 1132 errx(1, "invalid passphrase length"); 1133 1134 fclose(f); 1135 } else { 1136 if (readpassphrase(prompt, passphrase, sizeof(passphrase), 1137 rpp_flag) == NULL) 1138 errx(1, "unable to read passphrase"); 1139 } 1140 1141 if (verify) { 1142 /* request user to re-type it */ 1143 if (readpassphrase("Re-type passphrase: ", verifybuf, 1144 sizeof(verifybuf), rpp_flag) == NULL) { 1145 memset(passphrase, 0, sizeof(passphrase)); 1146 errx(1, "unable to read passphrase"); 1147 } 1148 if ((strlen(passphrase) != strlen(verifybuf)) || 1149 (strcmp(passphrase, verifybuf) != 0)) { 1150 memset(passphrase, 0, sizeof(passphrase)); 1151 memset(verifybuf, 0, sizeof(verifybuf)); 1152 errx(1, "Passphrases did not match"); 1153 } 1154 /* forget the re-typed one */ 1155 memset(verifybuf, 0, strlen(verifybuf)); 1156 } 1157 1158 /* derive key from passphrase */ 1159 if (pkcs5_pbkdf2(passphrase, strlen(passphrase), salt, saltsz, 1160 key, keysz, rounds) != 0) 1161 errx(1, "pbkdf2 failed"); 1162 1163 /* forget passphrase */ 1164 memset(passphrase, 0, sizeof(passphrase)); 1165 1166 return; 1167 } 1168