1 /* $NetBSD: cgdconfig.c,v 1.61 2022/11/17 06:40:38 chs Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Roland C. Dowdeswell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 2002, 2003\ 35 The NetBSD Foundation, Inc. All rights reserved."); 36 __RCSID("$NetBSD: cgdconfig.c,v 1.61 2022/11/17 06:40:38 chs Exp $"); 37 #endif 38 39 #ifdef HAVE_ARGON2 40 #include <argon2.h> 41 #endif 42 #include <assert.h> 43 #include <err.h> 44 #include <errno.h> 45 #include <fcntl.h> 46 #include <libgen.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <string.h> 50 #include <unistd.h> 51 #include <util.h> 52 #include <paths.h> 53 #include <dirent.h> 54 55 /* base64 gunk */ 56 #include <netinet/in.h> 57 #include <arpa/nameser.h> 58 #include <resolv.h> 59 60 #include <sys/ioctl.h> 61 #include <sys/stat.h> 62 #include <sys/bootblock.h> 63 #include <sys/disklabel.h> 64 #include <sys/disklabel_gpt.h> 65 #include <sys/mman.h> 66 #include <sys/param.h> 67 #include <sys/resource.h> 68 #include <sys/statvfs.h> 69 #include <sys/bitops.h> 70 #include <sys/queue.h> 71 72 #include <dev/cgdvar.h> 73 74 #include <ufs/ffs/fs.h> 75 76 #include "params.h" 77 #include "pkcs5_pbkdf2.h" 78 #include "utils.h" 79 #include "cgdconfig.h" 80 #include "prog_ops.h" 81 #include "hkdf_hmac_sha256.h" 82 83 #define CGDCONFIG_CFILE CGDCONFIG_DIR "/cgd.conf" 84 85 enum action { 86 ACTION_DEFAULT, /* default -> configure */ 87 ACTION_CONFIGURE, /* configure, with paramsfile */ 88 ACTION_UNCONFIGURE, /* unconfigure */ 89 ACTION_GENERATE, /* generate a paramsfile */ 90 ACTION_GENERATE_CONVERT, /* generate a ``dup'' paramsfile */ 91 ACTION_CONFIGALL, /* configure all from config file */ 92 ACTION_UNCONFIGALL, /* unconfigure all from config file */ 93 ACTION_CONFIGSTDIN, /* configure, key from stdin */ 94 ACTION_LIST, /* list configured devices */ 95 ACTION_PRINTKEY, /* print key to stdout */ 96 ACTION_PRINTALLKEYS, /* print all keys to stdout */ 97 }; 98 99 /* if nflag is set, do not configure/unconfigure the cgd's */ 100 101 int nflag = 0; 102 103 /* if Sflag is set, generate shared keys */ 104 105 int Sflag = 0; 106 107 /* if pflag is set to PFLAG_STDIN read from stdin rather than getpass(3) */ 108 109 #define PFLAG_GETPASS 0x01 110 #define PFLAG_GETPASS_ECHO 0x02 111 #define PFLAG_GETPASS_MASK 0x03 112 #define PFLAG_STDIN 0x04 113 int pflag = PFLAG_GETPASS; 114 115 /* 116 * When configuring all cgds, save a cache of shared keys for key 117 * derivation. If the _first_ verification with a shared key fails, we 118 * chuck it and start over; if _subsequent_ verifications fail, we 119 * assume the disk is wrong and give up on it immediately. 120 */ 121 122 struct sharedkey { 123 int alg; 124 string_t *id; 125 bits_t *key; 126 LIST_ENTRY(sharedkey) list; 127 SLIST_ENTRY(sharedkey) used; 128 int verified; 129 }; 130 LIST_HEAD(, sharedkey) sharedkeys; 131 SLIST_HEAD(sharedkeyhits, sharedkey); 132 133 static int configure(int, char **, struct params *, int); 134 static int configure_stdin(struct params *, int argc, char **); 135 static int generate(struct params *, int, char **, const char *, 136 const char *); 137 static int generate_convert(struct params *, int, char **, const char *, 138 const char *); 139 static int unconfigure(int, char **, struct params *, int); 140 static int do_all(const char *, int, char **, 141 int (*)(int, char **, struct params *, int)); 142 static int do_list(int, char **); 143 static int printkey(const char *, const char *, const char *, ...) 144 __printflike(3,4); 145 static int printkey1(int, char **, struct params *, int); 146 static int do_printkey(int, char **); 147 148 #define CONFIG_FLAGS_FROMALL 1 /* called from configure_all() */ 149 #define CONFIG_FLAGS_FROMMAIN 2 /* called from main() */ 150 151 static int configure_params(int, const char *, const char *, 152 struct params *); 153 static void eliminate_cores(void); 154 static bits_t *getkey(const char *, struct keygen *, size_t, 155 struct sharedkeyhits *); 156 static bits_t *getkey_storedkey(const char *, struct keygen *, size_t); 157 static bits_t *getkey_randomkey(const char *, struct keygen *, size_t, int); 158 #ifdef HAVE_ARGON2 159 static bits_t *getkey_argon2id(const char *, struct keygen *, size_t); 160 #endif 161 static bits_t *getkey_pkcs5_pbkdf2(const char *, struct keygen *, size_t, 162 int); 163 static bits_t *getkey_shell_cmd(const char *, struct keygen *, size_t); 164 static char *maybe_getpass(char *); 165 static int opendisk_werror(const char *, char *, size_t); 166 static int unconfigure_fd(int); 167 static int verify(struct params *, int); 168 static int verify_disklabel(int); 169 static int verify_ffs(int); 170 static int verify_reenter(struct params *); 171 static int verify_mbr(int); 172 static int verify_gpt(int); 173 174 __dead static void usage(void); 175 176 /* Verbose Framework */ 177 unsigned verbose = 0; 178 179 #define VERBOSE(x,y) if (verbose >= x) y 180 #define VPRINTF(x,y) if (verbose >= x) (void)printf y 181 182 static void 183 usage(void) 184 { 185 186 (void)fprintf(stderr, "usage: %s [-enpv] [-V vmeth] cgd dev " 187 "[paramsfile]\n", getprogname()); 188 (void)fprintf(stderr, " %s -C [-enpv] [-f configfile]\n", 189 getprogname()); 190 (void)fprintf(stderr, " %s -G [-enpSv] [-i ivmeth] [-k kgmeth] " 191 "[-P paramsfile] [-o outfile] paramsfile\n", getprogname()); 192 (void)fprintf(stderr, " %s -g [-Sv] [-i ivmeth] [-k kgmeth] " 193 "[-P paramsfile] [-o outfile] alg [keylen]\n", getprogname()); 194 (void)fprintf(stderr, " %s -l [-v[v]] [cgd]\n", getprogname()); 195 (void)fprintf(stderr, " %s -s [-nv] [-i ivmeth] cgd dev alg " 196 "[keylen]\n", getprogname()); 197 (void)fprintf(stderr, " %s -t paramsfile\n", getprogname()); 198 (void)fprintf(stderr, " %s -T [-f configfile]\n", getprogname()); 199 (void)fprintf(stderr, " %s -U [-nv] [-f configfile]\n", 200 getprogname()); 201 (void)fprintf(stderr, " %s -u [-nv] cgd\n", getprogname()); 202 exit(EXIT_FAILURE); 203 } 204 205 static int 206 parse_size_t(const char *s, size_t *l) 207 { 208 char *endptr; 209 long v; 210 211 errno = 0; 212 v = strtol(s, &endptr, 10); 213 if ((v == LONG_MIN || v == LONG_MAX) && errno) 214 return -1; 215 if (v < INT_MIN || v > INT_MAX) { 216 errno = ERANGE; 217 return -1; 218 } 219 if (endptr == s) { 220 errno = EINVAL; 221 return -1; 222 } 223 *l = (size_t)v; 224 return 0; 225 } 226 227 static void 228 set_action(enum action *action, enum action value) 229 { 230 if (*action != ACTION_DEFAULT) 231 usage(); 232 *action = value; 233 } 234 235 int 236 main(int argc, char **argv) 237 { 238 struct params *p; 239 struct params *tp; 240 struct keygen *kg; 241 enum action action = ACTION_DEFAULT; 242 int ch; 243 const char *cfile = NULL; 244 const char *outfile = NULL; 245 const char *Pfile = NULL; 246 247 setprogname(*argv); 248 if (hkdf_hmac_sha256_selftest()) 249 err(EXIT_FAILURE, "Crypto self-test failed"); 250 eliminate_cores(); 251 if (mlockall(MCL_FUTURE)) 252 err(EXIT_FAILURE, "Can't lock memory"); 253 p = params_new(); 254 kg = NULL; 255 256 while ((ch = getopt(argc, argv, "CGP:STUV:b:ef:gi:k:lno:sptuv")) != -1) 257 switch (ch) { 258 case 'C': 259 set_action(&action, ACTION_CONFIGALL); 260 break; 261 case 'G': 262 set_action(&action, ACTION_GENERATE_CONVERT); 263 break; 264 case 'P': 265 if (Pfile) 266 usage(); 267 Pfile = estrdup(optarg); 268 break; 269 case 'S': 270 Sflag = 1; 271 break; 272 case 'T': 273 set_action(&action, ACTION_PRINTALLKEYS); 274 break; 275 case 'U': 276 set_action(&action, ACTION_UNCONFIGALL); 277 break; 278 case 'V': 279 tp = params_verify_method(string_fromcharstar(optarg)); 280 if (!tp) 281 usage(); 282 p = params_combine(p, tp); 283 break; 284 case 'b': 285 { 286 size_t size; 287 288 if (parse_size_t(optarg, &size) == -1) 289 usage(); 290 tp = params_bsize(size); 291 if (!tp) 292 usage(); 293 p = params_combine(p, tp); 294 } 295 break; 296 case 'e': 297 pflag = PFLAG_GETPASS_ECHO; 298 break; 299 case 'f': 300 if (cfile) 301 usage(); 302 cfile = estrdup(optarg); 303 break; 304 case 'g': 305 set_action(&action, ACTION_GENERATE); 306 break; 307 case 'i': 308 tp = params_ivmeth(string_fromcharstar(optarg)); 309 p = params_combine(p, tp); 310 break; 311 case 'k': 312 kg = keygen_method(string_fromcharstar(optarg)); 313 if (!kg) 314 usage(); 315 keygen_addlist(&p->keygen, kg); 316 break; 317 case 'l': 318 set_action(&action, ACTION_LIST); 319 break; 320 case 'n': 321 nflag = 1; 322 break; 323 case 'o': 324 if (outfile) 325 usage(); 326 outfile = estrdup(optarg); 327 break; 328 case 'p': 329 pflag = PFLAG_STDIN; 330 break; 331 case 's': 332 set_action(&action, ACTION_CONFIGSTDIN); 333 break; 334 case 't': 335 set_action(&action, ACTION_PRINTKEY); 336 break; 337 case 'u': 338 set_action(&action, ACTION_UNCONFIGURE); 339 break; 340 case 'v': 341 verbose++; 342 break; 343 default: 344 usage(); 345 /* NOTREACHED */ 346 } 347 348 argc -= optind; 349 argv += optind; 350 351 if (!outfile) 352 outfile = ""; 353 if (!cfile) 354 cfile = ""; 355 356 if (prog_init && prog_init() == -1) 357 err(1, "init failed"); 358 359 /* validate the consistency of the arguments */ 360 if (Pfile != NULL && 361 action != ACTION_GENERATE && 362 action != ACTION_GENERATE_CONVERT) { 363 warnx("-P is only for use with -g/-G action"); 364 usage(); 365 } 366 if (Pfile != NULL && !Sflag) { 367 warnx("-P only makes sense with -S flag"); 368 } 369 if (Sflag && 370 action != ACTION_GENERATE && 371 action != ACTION_GENERATE_CONVERT) { 372 warnx("-S is only for use with -g/-G action"); 373 usage(); 374 } 375 376 switch (action) { 377 case ACTION_DEFAULT: /* ACTION_CONFIGURE is the default */ 378 case ACTION_CONFIGURE: 379 return configure(argc, argv, p, CONFIG_FLAGS_FROMMAIN); 380 case ACTION_UNCONFIGURE: 381 return unconfigure(argc, argv, NULL, CONFIG_FLAGS_FROMMAIN); 382 case ACTION_GENERATE: 383 return generate(p, argc, argv, outfile, Pfile); 384 case ACTION_GENERATE_CONVERT: 385 return generate_convert(p, argc, argv, outfile, Pfile); 386 case ACTION_CONFIGALL: 387 return do_all(cfile, argc, argv, configure); 388 case ACTION_UNCONFIGALL: 389 return do_all(cfile, argc, argv, unconfigure); 390 case ACTION_CONFIGSTDIN: 391 return configure_stdin(p, argc, argv); 392 case ACTION_LIST: 393 return do_list(argc, argv); 394 case ACTION_PRINTKEY: 395 return do_printkey(argc, argv); 396 case ACTION_PRINTALLKEYS: 397 return do_all(cfile, argc, argv, printkey1); 398 default: 399 errx(EXIT_FAILURE, "undefined action"); 400 /* NOTREACHED */ 401 } 402 } 403 404 static bits_t * 405 getsubkey_hkdf_hmac_sha256(bits_t *key, bits_t *info, size_t subkeylen) 406 { 407 bits_t *ret = NULL; 408 uint8_t *tmp; 409 410 tmp = emalloc(BITS2BYTES(subkeylen)); 411 if (hkdf_hmac_sha256(tmp, BITS2BYTES(subkeylen), 412 bits_getbuf(key), BITS2BYTES(bits_len(key)), 413 bits_getbuf(info), BITS2BYTES(bits_len(info)))) { 414 warnx("failed to derive HKDF-HMAC-SHA256 subkey"); 415 goto out; 416 } 417 418 ret = bits_new(tmp, subkeylen); 419 420 out: free(tmp); 421 return ret; 422 } 423 424 static bits_t * 425 getsubkey(int alg, bits_t *key, bits_t *info, size_t subkeylen) 426 { 427 428 switch (alg) { 429 case SHARED_ALG_HKDF_HMAC_SHA256: 430 return getsubkey_hkdf_hmac_sha256(key, info, subkeylen); 431 default: 432 warnx("unrecognised shared key derivation method %d", alg); 433 return NULL; 434 } 435 } 436 437 static bits_t * 438 getkey(const char *dev, struct keygen *kg, size_t len0, 439 struct sharedkeyhits *skh) 440 { 441 bits_t *ret = NULL; 442 bits_t *tmp; 443 444 VPRINTF(3, ("getkey(\"%s\", %p, %zu) called\n", dev, kg, len0)); 445 for (; kg; kg=kg->next) { 446 struct sharedkey *sk = NULL; 447 size_t len = len0; 448 449 /* 450 * If shared, determine the shared key's length and 451 * probe the cache of shared keys. 452 */ 453 if (kg->kg_sharedid) { 454 const char *id = string_tocharstar(kg->kg_sharedid); 455 456 len = kg->kg_sharedlen; 457 LIST_FOREACH(sk, &sharedkeys, list) { 458 if (kg->kg_sharedalg == sk->alg && 459 kg->kg_sharedlen == bits_len(sk->key) && 460 strcmp(id, string_tocharstar(sk->id)) == 0) 461 break; 462 } 463 if (sk) { 464 tmp = sk->key; 465 goto derive; 466 } 467 } 468 469 switch (kg->kg_method) { 470 case KEYGEN_STOREDKEY: 471 tmp = getkey_storedkey(dev, kg, len); 472 break; 473 case KEYGEN_RANDOMKEY: 474 tmp = getkey_randomkey(dev, kg, len, 1); 475 break; 476 case KEYGEN_URANDOMKEY: 477 tmp = getkey_randomkey(dev, kg, len, 0); 478 break; 479 #ifdef HAVE_ARGON2 480 case KEYGEN_ARGON2ID: 481 tmp = getkey_argon2id(dev, kg, len); 482 break; 483 #endif 484 case KEYGEN_PKCS5_PBKDF2_SHA1: 485 tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 0); 486 break; 487 /* provide backwards compatibility for old config files */ 488 case KEYGEN_PKCS5_PBKDF2_OLD: 489 tmp = getkey_pkcs5_pbkdf2(dev, kg, len, 1); 490 break; 491 case KEYGEN_SHELL_CMD: 492 tmp = getkey_shell_cmd(dev, kg, len); 493 break; 494 default: 495 warnx("unrecognised keygen method %d in getkey()", 496 kg->kg_method); 497 if (ret) 498 bits_free(ret); 499 return NULL; 500 } 501 502 /* 503 * If shared, cache the key. 504 */ 505 if (kg->kg_sharedid) { 506 assert(sk == NULL); 507 sk = ecalloc(1, sizeof(*sk)); 508 sk->alg = kg->kg_sharedalg; 509 sk->id = string_dup(kg->kg_sharedid); 510 sk->key = tmp; 511 LIST_INSERT_HEAD(&sharedkeys, sk, list); 512 sk->verified = 0; 513 } 514 515 derive: if (kg->kg_sharedid) { 516 assert(sk != NULL); 517 /* 518 * tmp holds the master key, owned by the 519 * struct sharedkey record; replace it by the 520 * derived subkey. 521 */ 522 tmp = getsubkey(kg->kg_sharedalg, tmp, 523 kg->kg_sharedinfo, len0); 524 if (tmp == NULL) { 525 if (ret) 526 bits_free(ret); 527 return NULL; 528 } 529 if (skh) 530 SLIST_INSERT_HEAD(skh, sk, used); 531 } 532 if (ret) 533 ret = bits_xor_d(tmp, ret); 534 else 535 ret = tmp; 536 } 537 538 return ret; 539 } 540 541 /*ARGSUSED*/ 542 static bits_t * 543 getkey_storedkey(const char *target, struct keygen *kg, size_t keylen) 544 { 545 return bits_dup(kg->kg_key); 546 } 547 548 /*ARGSUSED*/ 549 static bits_t * 550 getkey_randomkey(const char *target, struct keygen *kg, size_t keylen, int hard) 551 { 552 return bits_getrandombits(keylen, hard); 553 } 554 555 static char * 556 maybe_getpass(char *prompt) 557 { 558 char buf[1024]; 559 char *p = NULL; 560 char *tmp, *pass; 561 562 switch (pflag) { 563 case PFLAG_GETPASS: 564 p = getpass_r(prompt, buf, sizeof(buf)); 565 break; 566 567 case PFLAG_GETPASS_ECHO: 568 p = getpassfd(prompt, buf, sizeof(buf), NULL, 569 GETPASS_ECHO|GETPASS_ECHO_NL|GETPASS_NEED_TTY, 0); 570 break; 571 572 case PFLAG_STDIN: 573 p = fgets(buf, sizeof(buf), stdin); 574 if (p) { 575 tmp = strchr(p, '\n'); 576 if (tmp) 577 *tmp = '\0'; 578 } 579 break; 580 581 default: 582 errx(EXIT_FAILURE, "pflag set inappropriately?"); 583 } 584 585 if (!p) 586 err(EXIT_FAILURE, "failed to read passphrase"); 587 588 pass = estrdup(p); 589 explicit_memset(buf, 0, sizeof(buf)); 590 591 return pass; 592 } 593 594 /*ARGSUSED*/ 595 /* 596 * XXX take, and pass through, a compat flag that indicates whether we 597 * provide backwards compatibility with a previous bug. The previous 598 * behaviour is indicated by the keygen method pkcs5_pbkdf2, and a 599 * non-zero compat flag. The new default, and correct keygen method is 600 * called pcks5_pbkdf2/sha1. When the old method is removed, so will 601 * be the compat argument. 602 */ 603 static bits_t * 604 getkey_pkcs5_pbkdf2(const char *target, struct keygen *kg, size_t keylen, 605 int compat) 606 { 607 bits_t *ret; 608 char *passp; 609 char buf[1024]; 610 u_int8_t *tmp; 611 612 snprintf(buf, sizeof(buf), "%s's passphrase%s:", target, 613 pflag & PFLAG_GETPASS_ECHO ? " (echo)" : ""); 614 passp = maybe_getpass(buf); 615 if (pkcs5_pbkdf2(&tmp, BITS2BYTES(keylen), (uint8_t *)passp, 616 strlen(passp), 617 bits_getbuf(kg->kg_salt), BITS2BYTES(bits_len(kg->kg_salt)), 618 kg->kg_iterations, compat)) { 619 warnx("failed to generate PKCS#5 PBKDF2 key"); 620 return NULL; 621 } 622 623 ret = bits_new(tmp, keylen); 624 kg->kg_key = bits_dup(ret); 625 explicit_memset(passp, 0, strlen(passp)); 626 free(passp); 627 free(tmp); 628 return ret; 629 } 630 631 #ifdef HAVE_ARGON2 632 static bits_t * 633 getkey_argon2id(const char *target, struct keygen *kg, size_t keylen) 634 { 635 bits_t *ret; 636 char *passp; 637 char buf[1024]; 638 uint8_t raw[256]; 639 int err; 640 641 snprintf(buf, sizeof(buf), "%s's passphrase%s:", target, 642 pflag & PFLAG_GETPASS_ECHO ? " (echo)" : ""); 643 passp = maybe_getpass(buf); 644 if ((err = argon2_hash(kg->kg_iterations, kg->kg_memory, 645 kg->kg_parallelism, 646 passp, strlen(passp), 647 bits_getbuf(kg->kg_salt), 648 BITS2BYTES(bits_len(kg->kg_salt)), 649 raw, sizeof(raw), 650 NULL, 0, 651 Argon2_id, kg->kg_version)) != ARGON2_OK) { 652 warnx("failed to generate Argon2id key, error code %d", err); 653 return NULL; 654 } 655 656 ret = bits_new(raw, keylen); 657 kg->kg_key = bits_dup(ret); 658 explicit_memset(passp, 0, strlen(passp)); 659 explicit_memset(raw, 0, sizeof(raw)); 660 free(passp); 661 return ret; 662 } 663 #endif 664 665 /*ARGSUSED*/ 666 static bits_t * 667 getkey_shell_cmd(const char *target, struct keygen *kg, size_t keylen) 668 { 669 FILE *f; 670 bits_t *ret; 671 int status; 672 673 if ((f = popen(string_tocharstar(kg->kg_cmd), "r")) == NULL) 674 errx(1, "command failed"); 675 if ((ret = bits_fget(f, keylen)) == NULL) 676 errx(1, "command output too short"); 677 if ((status = pclose(f)) != 0) 678 err(1, "command failed with status %d", status); 679 680 return ret; 681 } 682 683 /*ARGSUSED*/ 684 static int 685 unconfigure(int argc, char **argv, struct params *inparams, int flags) 686 { 687 int fd; 688 int ret; 689 char buf[MAXPATHLEN] = ""; 690 691 /* only complain about additional arguments, if called from main() */ 692 if (flags == CONFIG_FLAGS_FROMMAIN && argc != 1) 693 usage(); 694 695 /* if called from do_all(), then ensure that 2 or 3 args exist */ 696 if (flags == CONFIG_FLAGS_FROMALL && (argc < 2 || argc > 3)) 697 return -1; 698 699 fd = opendisk1(*argv, O_RDWR, buf, sizeof(buf), 1, prog_open); 700 if (fd == -1) { 701 int saved_errno = errno; 702 703 warn("can't open cgd \"%s\", \"%s\"", *argv, buf); 704 705 /* this isn't fatal with nflag != 0 */ 706 if (!nflag) 707 return saved_errno; 708 } 709 710 VPRINTF(1, ("%s (%s): clearing\n", *argv, buf)); 711 712 if (nflag) 713 return 0; 714 715 ret = unconfigure_fd(fd); 716 (void)prog_close(fd); 717 return ret; 718 } 719 720 static int 721 unconfigure_fd(int fd) 722 { 723 struct cgd_ioctl ci; 724 725 if (prog_ioctl(fd, CGDIOCCLR, &ci) == -1) { 726 warn("ioctl"); 727 return -1; 728 } 729 730 return 0; 731 } 732 733 /*ARGSUSED*/ 734 static int 735 configure(int argc, char **argv, struct params *inparams, int flags) 736 { 737 struct params *p; 738 struct keygen *kg; 739 int fd; 740 int loop = 0; 741 int ret; 742 char cgdname[PATH_MAX]; 743 char devicename[PATH_MAX]; 744 const char *dev = NULL; /* XXX: gcc */ 745 746 if (argc < 2 || argc > 3) { 747 /* print usage and exit, only if called from main() */ 748 if (flags == CONFIG_FLAGS_FROMMAIN) { 749 warnx("wrong number of args"); 750 usage(); 751 } 752 return -1; 753 } 754 755 if (( 756 fd = opendisk1(*argv, O_RDWR, cgdname, sizeof(cgdname), 1, prog_open) 757 ) != -1) { 758 struct cgd_user cgu; 759 760 cgu.cgu_unit = -1; 761 if (prog_ioctl(fd, CGDIOCGET, &cgu) != -1 && cgu.cgu_dev != 0) { 762 warnx("device %s already in use", *argv); 763 prog_close(fd); 764 return -1; 765 } 766 prog_close(fd); 767 } 768 769 dev = getfsspecname(devicename, sizeof(devicename), argv[1]); 770 if (dev == NULL) { 771 warnx("getfsspecname failed: %s", devicename); 772 return -1; 773 } 774 775 if (argc == 2) { 776 char pfile[MAXPATHLEN]; 777 778 /* make string writable for basename */ 779 strlcpy(pfile, dev, sizeof(pfile)); 780 p = params_cget(basename(pfile)); 781 } else 782 p = params_cget(argv[2]); 783 784 if (!p) 785 return -1; 786 787 /* 788 * over-ride with command line specifications and fill in default 789 * values. 790 */ 791 792 p = params_combine(p, inparams); 793 ret = params_filldefaults(p); 794 if (ret) { 795 params_free(p); 796 return ret; 797 } 798 799 if (!params_verify(p)) { 800 warnx("params invalid"); 801 return -1; 802 } 803 804 /* 805 * loop over configuring the disk and checking to see if it 806 * verifies properly. We open and close the disk device each 807 * time, because if the user passes us the block device we 808 * need to flush the buffer cache. 809 * 810 * We only loop if one of the verification methods prompts for 811 * a password. 812 */ 813 814 for (kg = p->keygen; 815 (pflag & PFLAG_GETPASS_MASK) && kg; 816 kg = kg->next) 817 if (kg->kg_method == KEYGEN_ARGON2ID || 818 kg->kg_method == KEYGEN_PKCS5_PBKDF2_SHA1 || 819 kg->kg_method == KEYGEN_PKCS5_PBKDF2_OLD) { 820 loop = 1; 821 break; 822 } 823 824 for (;;) { 825 struct sharedkeyhits skh; 826 struct sharedkey *sk, *sk1; 827 int all_verified; 828 829 SLIST_INIT(&skh); 830 831 fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname)); 832 if (fd == -1) 833 return -1; 834 835 if (p->key) 836 bits_free(p->key); 837 838 p->key = getkey(argv[1], p->keygen, p->keylen, &skh); 839 if (!p->key) 840 goto bail_err; 841 842 ret = configure_params(fd, cgdname, dev, p); 843 if (ret) 844 goto bail_err; 845 846 ret = verify(p, fd); 847 if (ret == -1) { 848 (void)unconfigure_fd(fd); 849 goto bail_err; 850 } 851 if (ret == 0) { /* success */ 852 SLIST_FOREACH(sk, &skh, used) 853 sk->verified = 1; 854 break; 855 } 856 857 (void)unconfigure_fd(fd); 858 (void)prog_close(fd); 859 860 /* 861 * For shared keys: If the shared keys were all 862 * verified already, assume something is wrong with the 863 * disk and give up. If not, flush the cache of the 864 * ones that have not been verified in case we can try 865 * again with passphrase re-entry. 866 */ 867 if (!SLIST_EMPTY(&skh)) { 868 all_verified = 1; 869 SLIST_FOREACH_SAFE(sk, &skh, used, sk1) { 870 all_verified &= sk->verified; 871 if (!sk->verified) { 872 LIST_REMOVE(sk, list); 873 free(sk); 874 } 875 } 876 if (all_verified) 877 loop = 0; 878 } 879 880 if (!loop) { 881 warnx("verification failed permanently"); 882 goto bail_err; 883 } 884 885 warnx("verification failed, please reenter passphrase"); 886 } 887 888 params_free(p); 889 (void)prog_close(fd); 890 return 0; 891 892 bail_err:; 893 params_free(p); 894 (void)prog_close(fd); 895 return -1; 896 } 897 898 static int 899 configure_stdin(struct params *p, int argc, char **argv) 900 { 901 int fd; 902 int ret; 903 char cgdname[PATH_MAX]; 904 char devicename[PATH_MAX]; 905 const char *dev; 906 907 if (argc < 3 || argc > 4) 908 usage(); 909 910 dev = getfsspecname(devicename, sizeof(devicename), argv[1]); 911 if (dev == NULL) { 912 warnx("getfsspecname failed: %s", devicename); 913 return -1; 914 } 915 916 p->algorithm = string_fromcharstar(argv[2]); 917 if (argc > 3) { 918 size_t keylen; 919 920 if (parse_size_t(argv[3], &keylen) == -1) { 921 warn("failed to parse key length"); 922 return -1; 923 } 924 p->keylen = keylen; 925 } 926 927 ret = params_filldefaults(p); 928 if (ret) 929 return ret; 930 931 fd = opendisk_werror(argv[0], cgdname, sizeof(cgdname)); 932 if (fd == -1) 933 return -1; 934 935 p->key = bits_fget(stdin, p->keylen); 936 if (!p->key) { 937 warnx("failed to read key from stdin"); 938 return -1; 939 } 940 941 return configure_params(fd, cgdname, dev, p); 942 } 943 944 static int 945 opendisk_werror(const char *cgd, char *buf, size_t buflen) 946 { 947 int fd; 948 949 VPRINTF(3, ("opendisk_werror(%s, %s, %zu) called.\n", cgd,buf,buflen)); 950 951 /* sanity */ 952 if (!cgd || !buf) 953 return -1; 954 955 if (nflag) { 956 if (strlcpy(buf, cgd, buflen) >= buflen) 957 return -1; 958 return 0; 959 } 960 961 fd = opendisk1(cgd, O_RDWR, buf, buflen, 0, prog_open); 962 if (fd == -1) 963 warnx("can't open cgd \"%s\", \"%s\"", cgd, buf); 964 965 return fd; 966 } 967 968 static int 969 configure_params(int fd, const char *cgd, const char *dev, struct params *p) 970 { 971 struct cgd_ioctl ci; 972 973 /* sanity */ 974 if (!cgd || !dev) 975 return -1; 976 977 (void)memset(&ci, 0x0, sizeof(ci)); 978 ci.ci_disk = dev; 979 ci.ci_alg = string_tocharstar(p->algorithm); 980 ci.ci_ivmethod = string_tocharstar(p->ivmeth); 981 ci.ci_key = bits_getbuf(p->key); 982 ci.ci_keylen = p->keylen; 983 ci.ci_blocksize = p->bsize; 984 985 VPRINTF(1, (" with alg %s keylen %zu blocksize %zu ivmethod %s\n", 986 string_tocharstar(p->algorithm), p->keylen, p->bsize, 987 string_tocharstar(p->ivmeth))); 988 VPRINTF(2, ("key: ")); 989 VERBOSE(2, bits_fprint(stdout, p->key)); 990 VPRINTF(2, ("\n")); 991 992 if (nflag) 993 return 0; 994 995 if (prog_ioctl(fd, CGDIOCSET, &ci) == -1) { 996 int saved_errno = errno; 997 warn("ioctl"); 998 return saved_errno; 999 } 1000 1001 return 0; 1002 } 1003 1004 /* 1005 * verify returns 0 for success, -1 for unrecoverable error, or 1 for retry. 1006 */ 1007 1008 #define SCANSIZE 8192 1009 1010 static int 1011 verify(struct params *p, int fd) 1012 { 1013 1014 switch (p->verify_method) { 1015 case VERIFY_NONE: 1016 return 0; 1017 case VERIFY_DISKLABEL: 1018 return verify_disklabel(fd); 1019 case VERIFY_FFS: 1020 return verify_ffs(fd); 1021 case VERIFY_REENTER: 1022 return verify_reenter(p); 1023 case VERIFY_MBR: 1024 return verify_mbr(fd); 1025 case VERIFY_GPT: 1026 return verify_gpt(fd); 1027 default: 1028 warnx("unimplemented verification method"); 1029 return -1; 1030 } 1031 } 1032 1033 static int 1034 verify_disklabel(int fd) 1035 { 1036 struct disklabel l; 1037 ssize_t ret; 1038 char buf[SCANSIZE]; 1039 1040 /* 1041 * we simply scan the first few blocks for a disklabel, ignoring 1042 * any MBR/filecore sorts of logic. MSDOS and RiscOS can't read 1043 * a cgd, anyway, so it is unlikely that there will be non-native 1044 * partition information. 1045 */ 1046 1047 ret = prog_pread(fd, buf, SCANSIZE, 0); 1048 if (ret < 0) { 1049 warn("can't read disklabel area"); 1050 return -1; 1051 } 1052 1053 /* now scan for the disklabel */ 1054 1055 return disklabel_scan(&l, buf, (size_t)ret); 1056 } 1057 1058 static int 1059 verify_mbr(int fd) 1060 { 1061 struct mbr_sector mbr; 1062 ssize_t ret; 1063 char buf[SCANSIZE]; 1064 1065 /* 1066 * we read the first blocks to avoid sector size issues and 1067 * verify the MBR in the beginning 1068 */ 1069 1070 ret = prog_pread(fd, buf, SCANSIZE, 0); 1071 if (ret < 0) { 1072 warn("can't read mbr area"); 1073 return -1; 1074 } 1075 1076 memcpy(&mbr, buf, sizeof(mbr)); 1077 if (le16toh(mbr.mbr_magic) != MBR_MAGIC) 1078 return 1; 1079 1080 return 0; 1081 } 1082 1083 static uint32_t crc32_tab[] = { 1084 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 1085 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 1086 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 1087 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 1088 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 1089 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 1090 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 1091 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 1092 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 1093 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 1094 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 1095 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 1096 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 1097 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 1098 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 1099 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 1100 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 1101 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 1102 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 1103 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 1104 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 1105 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 1106 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 1107 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 1108 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 1109 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 1110 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 1111 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 1112 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 1113 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 1114 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 1115 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 1116 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 1117 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 1118 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 1119 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 1120 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 1121 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 1122 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 1123 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 1124 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 1125 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 1126 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 1127 }; 1128 1129 static uint32_t 1130 crc32(const void *buf, size_t size) 1131 { 1132 const uint8_t *p; 1133 uint32_t crc; 1134 1135 p = buf; 1136 crc = ~0U; 1137 1138 while (size--) 1139 crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 1140 1141 return crc ^ ~0U; 1142 } 1143 1144 static int 1145 verify_gpt(int fd) 1146 { 1147 struct gpt_hdr hdr; 1148 ssize_t ret; 1149 char buf[SCANSIZE]; 1150 unsigned blksize; 1151 size_t off; 1152 1153 /* 1154 * we read the first blocks to avoid sector size issues and 1155 * verify the GPT header. 1156 */ 1157 1158 ret = prog_pread(fd, buf, SCANSIZE, 0); 1159 if (ret < 0) { 1160 warn("can't read gpt area"); 1161 return -1; 1162 } 1163 1164 ret = 1; 1165 for (blksize = DEV_BSIZE; 1166 (off = (blksize * GPT_HDR_BLKNO)) <= SCANSIZE - sizeof(hdr); 1167 blksize <<= 1) { 1168 1169 memcpy(&hdr, &buf[off], sizeof(hdr)); 1170 if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) == 0 1171 && le32toh(hdr.hdr_revision) == GPT_HDR_REVISION 1172 && le32toh(hdr.hdr_size) == GPT_HDR_SIZE) { 1173 1174 hdr.hdr_crc_self = 0; 1175 if (crc32(&hdr, sizeof(hdr))) { 1176 ret = 0; 1177 break; 1178 } 1179 } 1180 } 1181 1182 return ret; 1183 } 1184 1185 static off_t sblock_try[] = SBLOCKSEARCH; 1186 1187 static int 1188 verify_ffs(int fd) 1189 { 1190 size_t i; 1191 1192 for (i = 0; sblock_try[i] != -1; i++) { 1193 union { 1194 char buf[SBLOCKSIZE]; 1195 struct fs fs; 1196 } u; 1197 ssize_t ret; 1198 1199 ret = prog_pread(fd, &u, sizeof(u), sblock_try[i]); 1200 if (ret < 0) { 1201 warn("pread"); 1202 break; 1203 } else if ((size_t)ret < sizeof(u)) { 1204 warnx("pread: incomplete block"); 1205 break; 1206 } 1207 switch (u.fs.fs_magic) { 1208 case FS_UFS1_MAGIC: 1209 case FS_UFS2_MAGIC: 1210 case FS_UFS2EA_MAGIC: 1211 case FS_UFS1_MAGIC_SWAPPED: 1212 case FS_UFS2_MAGIC_SWAPPED: 1213 case FS_UFS2EA_MAGIC_SWAPPED: 1214 return 0; 1215 default: 1216 continue; 1217 } 1218 } 1219 1220 return 1; /* failure */ 1221 } 1222 1223 static int 1224 verify_reenter(struct params *p) 1225 { 1226 struct keygen *kg; 1227 bits_t *orig_key, *key = NULL; 1228 int ret; 1229 1230 ret = 0; 1231 for (kg = p->keygen; kg && !ret; kg = kg->next) { 1232 if (kg->kg_method != KEYGEN_ARGON2ID && 1233 kg->kg_method != KEYGEN_PKCS5_PBKDF2_SHA1 && 1234 kg->kg_method != KEYGEN_PKCS5_PBKDF2_OLD) 1235 continue; 1236 1237 orig_key = kg->kg_key; 1238 kg->kg_key = NULL; 1239 1240 switch (kg->kg_method) { 1241 #ifdef HAVE_ARGON2 1242 case KEYGEN_ARGON2ID: 1243 key = getkey_argon2id("re-enter device", kg, 1244 bits_len(orig_key)); 1245 break; 1246 #endif 1247 case KEYGEN_PKCS5_PBKDF2_SHA1: 1248 key = getkey_pkcs5_pbkdf2("re-enter device", kg, 1249 bits_len(orig_key), 0); 1250 break; 1251 case KEYGEN_PKCS5_PBKDF2_OLD: 1252 key = getkey_pkcs5_pbkdf2("re-enter device", kg, 1253 bits_len(orig_key), 1); 1254 break; 1255 default: 1256 warnx("unsupported keygen method"); 1257 kg->kg_key = orig_key; 1258 return -1; 1259 } 1260 1261 ret = !bits_match(key, orig_key); 1262 1263 bits_free(key); 1264 bits_free(kg->kg_key); 1265 kg->kg_key = orig_key; 1266 } 1267 1268 return ret; 1269 } 1270 1271 static int 1272 generate(struct params *p, int argc, char **argv, const char *outfile, 1273 const char *Pfile) 1274 { 1275 int ret; 1276 1277 if (argc < 1 || argc > 2) 1278 usage(); 1279 1280 p->algorithm = string_fromcharstar(argv[0]); 1281 if (argc > 1) { 1282 size_t keylen; 1283 1284 if (parse_size_t(argv[1], &keylen) == -1) { 1285 warn("Failed to parse key length"); 1286 return -1; 1287 } 1288 p->keylen = keylen; 1289 } 1290 1291 ret = params_filldefaults(p); 1292 if (ret) 1293 return ret; 1294 1295 if (Pfile) { 1296 struct params *pp; 1297 1298 pp = params_cget(Pfile); 1299 if (pp == NULL) 1300 return -1; 1301 if (!params_verify(pp)) { 1302 params_free(pp); 1303 warnx("invalid parameters file \"%s\"", Pfile); 1304 return -1; 1305 } 1306 p = params_combine(pp, p); 1307 keygen_stripstored(&p->keygen); 1308 if (!p->keygen) { 1309 warnx("no keygen in parameters file \"%s\"", Pfile); 1310 return -1; 1311 } 1312 } else { 1313 if (!p->keygen) { 1314 p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1); 1315 if (!p->keygen) 1316 return -1; 1317 } 1318 1319 if (keygen_filldefaults(p->keygen, p->keylen)) { 1320 warnx("Failed to generate defaults for keygen"); 1321 return -1; 1322 } 1323 } 1324 1325 if (Sflag) { 1326 if (Pfile) 1327 ret = keygen_tweakshared(p->keygen); 1328 else 1329 ret = keygen_makeshared(p->keygen); 1330 if (ret) 1331 return ret; 1332 } 1333 1334 if (!params_verify(p)) { 1335 warnx("invalid parameters generated"); 1336 return -1; 1337 } 1338 1339 return params_cput(p, outfile); 1340 } 1341 1342 static int 1343 generate_convert(struct params *p, int argc, char **argv, const char *outfile, 1344 const char *Pfile) 1345 { 1346 struct params *oldp; 1347 struct keygen *kg; 1348 int ret; 1349 1350 if (argc != 1) 1351 usage(); 1352 1353 oldp = params_cget(*argv); 1354 if (!oldp) 1355 return -1; 1356 1357 /* for sanity, we ensure that none of the keygens are randomkey */ 1358 for (kg=p->keygen; kg; kg=kg->next) 1359 if ((kg->kg_method == KEYGEN_RANDOMKEY) || 1360 (kg->kg_method == KEYGEN_URANDOMKEY)) { 1361 warnx("can't preserve randomly generated key"); 1362 goto bail; 1363 } 1364 for (kg=oldp->keygen; kg; kg=kg->next) 1365 if ((kg->kg_method == KEYGEN_RANDOMKEY) || 1366 (kg->kg_method == KEYGEN_URANDOMKEY)) { 1367 warnx("can't preserve randomly generated key"); 1368 goto bail; 1369 } 1370 1371 if (!params_verify(oldp)) { 1372 warnx("invalid old parameters file \"%s\"", *argv); 1373 return -1; 1374 } 1375 1376 oldp->key = getkey("old file", oldp->keygen, oldp->keylen, NULL); 1377 1378 /* we copy across the non-keygen info, here. */ 1379 1380 string_free(p->algorithm); 1381 string_free(p->ivmeth); 1382 1383 p->algorithm = string_dup(oldp->algorithm); 1384 p->ivmeth = string_dup(oldp->ivmeth); 1385 p->keylen = oldp->keylen; 1386 p->bsize = oldp->bsize; 1387 if (p->verify_method == VERIFY_UNKNOWN) 1388 p->verify_method = oldp->verify_method; 1389 1390 params_free(oldp); 1391 1392 if (Pfile) { 1393 struct params *pp; 1394 1395 pp = params_cget(Pfile); 1396 if (pp == NULL) 1397 return -1; 1398 if (!params_verify(pp)) { 1399 params_free(pp); 1400 warnx("invalid parameters file \"%s\"", Pfile); 1401 return -1; 1402 } 1403 p = params_combine(pp, p); 1404 keygen_stripstored(&p->keygen); 1405 if (!p->keygen) { 1406 warnx("no keygen in parameters file \"%s\"", Pfile); 1407 return -1; 1408 } 1409 } else { 1410 if (!p->keygen) { 1411 p->keygen = keygen_generate(KEYGEN_PKCS5_PBKDF2_SHA1); 1412 if (!p->keygen) 1413 return -1; 1414 } 1415 (void)params_filldefaults(p); 1416 (void)keygen_filldefaults(p->keygen, p->keylen); 1417 } 1418 1419 if (Sflag) { 1420 if (Pfile) 1421 ret = keygen_tweakshared(p->keygen); 1422 else 1423 ret = keygen_makeshared(p->keygen); 1424 if (ret) 1425 return ret; 1426 } 1427 1428 p->key = getkey("new file", p->keygen, p->keylen, NULL); 1429 1430 kg = keygen_generate(KEYGEN_STOREDKEY); 1431 kg->kg_key = bits_xor(p->key, oldp->key); 1432 keygen_addlist(&p->keygen, kg); 1433 1434 if (!params_verify(p)) { 1435 warnx("can't generate new parameters file"); 1436 return -1; 1437 } 1438 1439 return params_cput(p, outfile); 1440 bail:; 1441 params_free(oldp); 1442 return -1; 1443 } 1444 1445 static int 1446 /*ARGSUSED*/ 1447 do_all(const char *cfile, int argc, char **argv, 1448 int (*conf)(int, char **, struct params *, int)) 1449 { 1450 FILE *f; 1451 size_t len; 1452 size_t lineno; 1453 int my_argc; 1454 int ret; 1455 const char *fn; 1456 char *line; 1457 char **my_argv; 1458 1459 if (argc > 0) 1460 usage(); 1461 1462 if (!cfile[0]) 1463 fn = CGDCONFIG_CFILE; 1464 else 1465 fn = cfile; 1466 1467 f = fopen(fn, "r"); 1468 if (f == NULL) { 1469 warn("could not open config file \"%s\"", fn); 1470 return -1; 1471 } 1472 1473 ret = 0; 1474 lineno = 0; 1475 for (;;) { 1476 line = fparseln(f, &len, &lineno, "\\\\#", FPARSELN_UNESCALL); 1477 if (!line) 1478 break; 1479 if (!*line) 1480 continue; 1481 1482 my_argv = words(line, &my_argc); 1483 ret = conf(my_argc, my_argv, NULL, CONFIG_FLAGS_FROMALL); 1484 if (ret) { 1485 warnx("action failed on \"%s\" line %lu", fn, 1486 (u_long)lineno); 1487 break; 1488 } 1489 words_free(my_argv, my_argc); 1490 } 1491 return ret; 1492 } 1493 1494 static const char * 1495 iv_method(int mode) 1496 { 1497 1498 switch (mode) { 1499 case CGD_CIPHER_CBC_ENCBLKNO8: 1500 return "encblkno8"; 1501 case CGD_CIPHER_CBC_ENCBLKNO1: 1502 return "encblkno1"; 1503 default: 1504 return "unknown"; 1505 } 1506 } 1507 1508 1509 static void 1510 show(const char *dev) { 1511 char path[64]; 1512 struct cgd_user cgu; 1513 int fd; 1514 1515 fd = opendisk(dev, O_RDONLY, path, sizeof(path), 0); 1516 if (fd == -1) { 1517 warn("open: %s", dev); 1518 return; 1519 } 1520 1521 cgu.cgu_unit = -1; 1522 if (prog_ioctl(fd, CGDIOCGET, &cgu) == -1) { 1523 close(fd); 1524 err(1, "CGDIOCGET"); 1525 } 1526 1527 printf("%s: ", dev); 1528 1529 if (cgu.cgu_dev == 0) { 1530 printf("not in use"); 1531 goto out; 1532 } 1533 1534 dev = devname(cgu.cgu_dev, S_IFBLK); 1535 if (dev != NULL) 1536 printf("%s ", dev); 1537 else 1538 printf("dev %llu,%llu ", (unsigned long long)major(cgu.cgu_dev), 1539 (unsigned long long)minor(cgu.cgu_dev)); 1540 1541 if (verbose) 1542 printf("%s ", cgu.cgu_alg); 1543 if (verbose > 1) { 1544 printf("keylen %d ", cgu.cgu_keylen); 1545 printf("blksize %zd ", cgu.cgu_blocksize); 1546 printf("%s ", iv_method(cgu.cgu_mode)); 1547 } 1548 1549 out:; 1550 putchar('\n'); 1551 close(fd); 1552 } 1553 1554 static int 1555 do_list(int argc, char **argv) 1556 { 1557 1558 if (argc != 0 && argc != 1) 1559 usage(); 1560 1561 if (argc) { 1562 show(argv[0]); 1563 return 0; 1564 } 1565 1566 DIR *dirp; 1567 struct dirent *dp; 1568 __BITMAP_TYPE(, uint32_t, 65536) bm; 1569 1570 __BITMAP_ZERO(&bm); 1571 1572 if ((dirp = opendir(_PATH_DEV)) == NULL) 1573 err(1, "opendir: %s", _PATH_DEV); 1574 1575 while ((dp = readdir(dirp)) != NULL) { 1576 char *ep; 1577 if (strncmp(dp->d_name, "rcgd", 4) != 0) 1578 continue; 1579 errno = 0; 1580 int n = (int)strtol(dp->d_name + 4, &ep, 0); 1581 if (ep == dp->d_name + 4 || errno != 0) { 1582 warnx("bad name %s", dp->d_name); 1583 continue; 1584 } 1585 *ep = '\0'; 1586 if (__BITMAP_ISSET(n, &bm)) 1587 continue; 1588 __BITMAP_SET(n, &bm); 1589 show(dp->d_name + 1); 1590 } 1591 1592 closedir(dirp); 1593 return 0; 1594 } 1595 1596 static int 1597 printkey(const char *dev, const char *paramsfile, const char *fmt, ...) 1598 { 1599 va_list va; 1600 struct params *p; 1601 const uint8_t *raw; 1602 size_t nbits, nbytes; 1603 size_t nb64; 1604 char *b64; 1605 int ret; 1606 1607 p = params_cget(paramsfile); 1608 if (p == NULL) 1609 return -1; 1610 if (!params_verify(p)) { 1611 warnx("invalid parameters file \"%s\"", paramsfile); 1612 return -1; 1613 } 1614 p->key = getkey(dev, p->keygen, p->keylen, NULL); 1615 raw = bits_getbuf(p->key); 1616 nbits = bits_len(p->key); 1617 assert(nbits <= INT_MAX - 7); 1618 nbytes = BITS2BYTES(nbits); 1619 assert(nbytes <= 3*(INT_MAX/4) - 2); 1620 1621 nb64 = 4*((nbytes + 2)/3); 1622 b64 = emalloc(nb64 + 2); 1623 ret = __b64_ntop(raw, nbytes, b64, nb64 + 1); 1624 assert(ret == (int)nb64); 1625 b64[nb64] = '\n'; 1626 b64[nb64 + 1] = '\0'; 1627 1628 va_start(va, fmt); 1629 vprintf(fmt, va); 1630 va_end(va); 1631 if (fwrite(b64, nb64 + 1, 1, stdout) != 1) 1632 err(1, "fwrite"); 1633 fflush(stdout); 1634 return ferror(stdout); 1635 } 1636 1637 static int 1638 printkey1(int argc, char **argv, struct params *inparams, int flags) 1639 { 1640 char devicename[PATH_MAX], paramsfilebuf[PATH_MAX]; 1641 const char *dev, *paramsfile; 1642 1643 assert(flags == CONFIG_FLAGS_FROMALL); 1644 1645 if (argc < 2 || argc > 3) 1646 return -1; 1647 1648 dev = getfsspecname(devicename, sizeof(devicename), argv[1]); 1649 if (dev == NULL) { 1650 warnx("getfsspecname failed: %s", devicename); 1651 return -1; 1652 } 1653 1654 if (argc == 2) { 1655 strlcpy(paramsfilebuf, dev, sizeof(paramsfilebuf)); 1656 paramsfile = basename(paramsfilebuf); 1657 } else { 1658 paramsfile = argv[2]; 1659 } 1660 1661 return printkey(dev, paramsfile, "%s: ", dev); 1662 } 1663 1664 static int 1665 do_printkey(int argc, char **argv) 1666 { 1667 1668 if (argc != 1) 1669 usage(); 1670 return printkey("key", argv[0], ""); 1671 } 1672 1673 static void 1674 eliminate_cores(void) 1675 { 1676 struct rlimit rlp; 1677 1678 rlp.rlim_cur = 0; 1679 rlp.rlim_max = 0; 1680 if (setrlimit(RLIMIT_CORE, &rlp) == -1) 1681 err(EXIT_FAILURE, "Can't disable cores"); 1682 } 1683