1 /* $NetBSD: params.c,v 1.28 2015/11/24 14:07:18 christos 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 __RCSID("$NetBSD: params.c,v 1.28 2015/11/24 14:07:18 christos Exp $"); 35 #endif 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/stat.h> 40 41 #include <err.h> 42 #include <errno.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <util.h> 47 48 #include "params.h" 49 #include "pkcs5_pbkdf2.h" 50 #include "utils.h" 51 #include "cgdconfig.h" 52 #include "extern.h" 53 54 static void params_init(struct params *); 55 56 static void print_kvpair_cstr(FILE *, int, const char *, const char *); 57 static void print_kvpair_string(FILE *, int, const char *, const string_t *); 58 static void print_kvpair_int(FILE *, int, const char *, size_t); 59 static void print_kvpair_b64(FILE *, int, int, const char *, bits_t *); 60 61 static void spaces(FILE *, int); 62 63 /* keygen defaults */ 64 #define DEFAULT_SALTLEN 128 65 #define DEFAULT_ITERATION_TIME 2000000 /* 1 second in microseconds */ 66 67 /* crypto defaults functions */ 68 static struct crypto_defaults { 69 char alg[32]; 70 int keylen; 71 } crypto_defaults[] = { 72 { "aes-cbc", 128 }, 73 { "3des-cbc", 192 }, 74 { "blowfish-cbc", 128 } 75 }; 76 77 static int crypt_defaults_lookup(const char *); 78 79 struct params * 80 params_new(void) 81 { 82 struct params *p; 83 84 p = emalloc(sizeof(*p)); 85 params_init(p); 86 return p; 87 } 88 89 static void 90 params_init(struct params *p) 91 { 92 93 p->algorithm = NULL; 94 p->ivmeth = NULL; 95 p->key = NULL; 96 p->keylen = (size_t)-1; 97 p->bsize = (size_t)-1; 98 p->verify_method = VERIFY_UNKNOWN; 99 p->dep_keygen = NULL; 100 p->keygen = NULL; 101 } 102 103 void 104 params_free(struct params *p) 105 { 106 107 if (!p) 108 return; 109 string_free(p->algorithm); 110 string_free(p->ivmeth); 111 keygen_free(p->dep_keygen); 112 keygen_free(p->keygen); 113 } 114 115 struct params * 116 params_combine(struct params *p1, struct params *p2) 117 { 118 struct params *p; 119 120 if (p1) 121 p = p1; 122 else 123 p = params_new(); 124 125 if (!p2) 126 return p; 127 128 if (p2->algorithm) 129 string_assign(&p->algorithm, p2->algorithm); 130 if (p2->ivmeth) 131 string_assign(&p->ivmeth, p2->ivmeth); 132 if (p2->keylen != (size_t)-1) 133 p->keylen = p2->keylen; 134 if (p2->bsize != (size_t)-1) 135 p->bsize = p2->bsize; 136 if (p2->verify_method != VERIFY_UNKNOWN) 137 p->verify_method = p2->verify_method; 138 139 p->dep_keygen = keygen_combine(p->dep_keygen, p2->dep_keygen); 140 keygen_addlist(&p->keygen, p2->keygen); 141 142 /* 143 * at this point we should have moved all allocated data 144 * in p2 into p, so we can free it. 145 */ 146 free(p2); 147 return p; 148 } 149 150 int 151 params_filldefaults(struct params *p) 152 { 153 size_t i; 154 155 if (p->verify_method == VERIFY_UNKNOWN) 156 p->verify_method = VERIFY_NONE; 157 if (!p->ivmeth) 158 p->ivmeth = string_fromcharstar("encblkno1"); 159 if (p->keylen == (size_t)-1) { 160 i = crypt_defaults_lookup(string_tocharstar(p->algorithm)); 161 if (i != (size_t)-1) { 162 p->keylen = crypto_defaults[i].keylen; 163 } else { 164 warnx("could not determine key length for unknown " 165 "algorithm \"%s\"", 166 string_tocharstar(p->algorithm)); 167 return -1; 168 } 169 } 170 return 0; 171 } 172 173 /* 174 * params_verify traverses the parameters and all of the keygen methods 175 * looking for inconsistencies. It outputs warnings on non-fatal errors 176 * such as unknown encryption methods, but returns failure on fatal 177 * conditions such as a PKCS5_PBKDF2 keygen without a salt. It is intended 178 * to run before key generation. 179 */ 180 181 int 182 params_verify(const struct params *p) 183 { 184 static const char *encblkno[] = { 185 "encblkno", "encblkno1", "encblkno8" 186 }; 187 static size_t i; 188 const char *meth; 189 190 if (!p->algorithm) { 191 warnx("unspecified algorithm"); 192 return 0; 193 } 194 /* 195 * we only warn for the encryption method so that it is possible 196 * to use an older cgdconfig(8) with a new kernel that supports 197 * additional crypto algorithms. 198 */ 199 if (crypt_defaults_lookup(string_tocharstar(p->algorithm)) == -1) 200 warnx("unknown algorithm \"%s\"(warning)", 201 string_tocharstar(p->algorithm)); 202 /* same rationale with IV methods. */ 203 if (!p->ivmeth) { 204 warnx("unspecified IV method"); 205 return 0; 206 } 207 208 meth = string_tocharstar(p->ivmeth); 209 for (i = 0; i < __arraycount(encblkno); i++) 210 if (strcmp(encblkno[i], meth) == 0) 211 break; 212 213 if (i == __arraycount(encblkno)) 214 warnx("unknown IV method \"%s\" (warning)", meth); 215 216 if (p->keylen == (size_t)-1) { 217 warnx("unspecified key length"); 218 return 0; 219 } 220 221 return keygen_verify(p->keygen); 222 } 223 224 struct params * 225 params_algorithm(string_t *in) 226 { 227 struct params *p = params_new(); 228 229 p->algorithm = in; 230 return p; 231 } 232 233 struct params * 234 params_ivmeth(string_t *in) 235 { 236 struct params *p = params_new(); 237 238 p->ivmeth = in; 239 return p; 240 } 241 242 struct params * 243 params_keylen(size_t in) 244 { 245 struct params *p = params_new(); 246 247 p->keylen = in; 248 return p; 249 } 250 251 struct params * 252 params_bsize(size_t in) 253 { 254 struct params *p = params_new(); 255 256 p->bsize = in; 257 return p; 258 } 259 260 struct params * 261 params_verify_method(string_t *in) 262 { 263 struct params *p = params_new(); 264 const char *vm = string_tocharstar(in); 265 266 if (!strcmp("none", vm)) 267 p->verify_method = VERIFY_NONE; 268 if (!strcmp("disklabel", vm)) 269 p->verify_method = VERIFY_DISKLABEL; 270 if (!strcmp("ffs", vm)) 271 p->verify_method = VERIFY_FFS; 272 if (!strcmp("re-enter", vm)) 273 p->verify_method = VERIFY_REENTER; 274 if (!strcmp("mbr", vm)) 275 p->verify_method = VERIFY_MBR; 276 if (!strcmp("gpt", vm)) 277 p->verify_method = VERIFY_GPT; 278 279 string_free(in); 280 281 if (p->verify_method == VERIFY_UNKNOWN) 282 warnx("params_setverify_method: unrecognized " 283 "verify method \"%s\"", vm); 284 return p; 285 } 286 287 struct params * 288 params_keygen(struct keygen *in) 289 { 290 struct params *p = params_new(); 291 292 p->keygen = in; 293 return p; 294 } 295 296 struct params * 297 params_dep_keygen(struct keygen *in) 298 { 299 struct params *p = params_new(); 300 301 p->dep_keygen = in; 302 return p; 303 } 304 305 struct keygen * 306 keygen_new(void) 307 { 308 struct keygen *kg; 309 310 kg = emalloc(sizeof(*kg)); 311 kg->kg_method = KEYGEN_UNKNOWN; 312 kg->kg_iterations = (size_t)-1; 313 kg->kg_salt = NULL; 314 kg->kg_key = NULL; 315 kg->kg_cmd = NULL; 316 kg->next = NULL; 317 return kg; 318 } 319 320 void 321 keygen_free(struct keygen *kg) 322 { 323 324 if (!kg) 325 return; 326 bits_free(kg->kg_salt); 327 bits_free(kg->kg_key); 328 string_free(kg->kg_cmd); 329 keygen_free(kg->next); 330 free(kg); 331 } 332 333 /* 334 * keygen_verify traverses the keygen structures and ensures 335 * that the appropriate information is available. 336 */ 337 338 int 339 keygen_verify(const struct keygen *kg) 340 { 341 342 if (!kg) 343 return 1; 344 switch (kg->kg_method) { 345 case KEYGEN_PKCS5_PBKDF2_OLD: 346 if (kg->kg_iterations == (size_t)-1) { 347 warnx("keygen pkcs5_pbkdf2 must provide `iterations'"); 348 return 0; 349 } 350 if (kg->kg_key) 351 warnx("keygen pkcs5_pbkdf2 does not need a `key'"); 352 if (!kg->kg_salt) { 353 warnx("keygen pkcs5_pbkdf2 must provide a salt"); 354 return 0; 355 } 356 if (kg->kg_cmd) 357 warnx("keygen pkcs5_pbkdf2 does not need a `cmd'"); 358 break; 359 case KEYGEN_PKCS5_PBKDF2_SHA1: 360 if (kg->kg_iterations == (size_t)-1) { 361 warnx("keygen pkcs5_pbkdf2/sha1 must provide `iterations'"); 362 return 0; 363 } 364 if (kg->kg_key) 365 warnx("keygen pkcs5_pbkdf2/sha1 does not need a `key'"); 366 if (!kg->kg_salt) { 367 warnx("keygen pkcs5_pbkdf2/sha1 must provide a salt"); 368 return 0; 369 } 370 if (kg->kg_cmd) 371 warnx("keygen pkcs5_pbkdf2/sha1 does not need a `cmd'"); 372 break; 373 case KEYGEN_STOREDKEY: 374 if (kg->kg_iterations != (size_t)-1) 375 warnx("keygen storedkey does not need `iterations'"); 376 if (!kg->kg_key) { 377 warnx("keygen storedkey must provide a key"); 378 return 0; 379 } 380 if (kg->kg_salt) 381 warnx("keygen storedkey does not need `salt'"); 382 if (kg->kg_cmd) 383 warnx("keygen storedkey does not need `cmd'"); 384 break; 385 case KEYGEN_RANDOMKEY: 386 case KEYGEN_URANDOMKEY: 387 if (kg->kg_iterations != (size_t)-1) 388 warnx("keygen [u]randomkey does not need `iterations'"); 389 if (kg->kg_key) 390 warnx("keygen [u]randomkey does not need `key'"); 391 if (kg->kg_salt) 392 warnx("keygen [u]randomkey does not need `salt'"); 393 if (kg->kg_cmd) 394 warnx("keygen [u]randomkey does not need `cmd'"); 395 break; 396 case KEYGEN_SHELL_CMD: 397 if (kg->kg_iterations != (size_t)-1) 398 warnx("keygen shell_cmd does not need `iterations'"); 399 if (kg->kg_key) 400 warnx("keygen shell_cmd does not need `key'"); 401 if (kg->kg_salt) 402 warnx("keygen shell_cmd does not need `salt'"); 403 if (!kg->kg_cmd) { 404 warnx("keygen shell_cmd must provide a `cmd'"); 405 return 0; 406 } 407 break; 408 } 409 return keygen_verify(kg->next); 410 } 411 412 struct keygen * 413 keygen_generate(int method) 414 { 415 struct keygen *kg; 416 417 kg = keygen_new(); 418 if (!kg) 419 return NULL; 420 421 kg->kg_method = method; 422 return kg; 423 } 424 425 /* 426 * keygen_filldefaults walks the keygen list and fills in 427 * default values. The defaults may be either calibrated 428 * or randomly generated so this function is designed to be 429 * called when generating a new parameters file, not when 430 * reading a parameters file. 431 */ 432 433 int 434 keygen_filldefaults(struct keygen *kg, size_t keylen) 435 { 436 437 if (!kg) 438 return 0; 439 switch (kg->kg_method) { 440 case KEYGEN_RANDOMKEY: 441 case KEYGEN_URANDOMKEY: 442 case KEYGEN_SHELL_CMD: 443 break; 444 case KEYGEN_PKCS5_PBKDF2_OLD: 445 case KEYGEN_PKCS5_PBKDF2_SHA1: 446 kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN, 1); 447 kg->kg_iterations = pkcs5_pbkdf2_calibrate(BITS2BYTES(keylen), 448 DEFAULT_ITERATION_TIME); 449 if (kg->kg_iterations < 1) { 450 warnx("could not calibrate pkcs5_pbkdf2"); 451 return -1; 452 } 453 break; 454 case KEYGEN_STOREDKEY: 455 /* Generate a random stored key */ 456 kg->kg_key = bits_getrandombits(keylen, 1); 457 if (!kg->kg_key) { 458 warnx("can't generate random bits for storedkey"); 459 return -1; 460 } 461 break; 462 default: 463 return -1; 464 } 465 466 return keygen_filldefaults(kg->next, keylen); 467 } 468 469 struct keygen * 470 keygen_combine(struct keygen *kg1, struct keygen *kg2) 471 { 472 if (!kg1 && !kg2) 473 return NULL; 474 475 if (!kg1) 476 kg1 = keygen_new(); 477 478 if (!kg2) 479 return kg1; 480 481 if (kg2->kg_method != KEYGEN_UNKNOWN) 482 kg1->kg_method = kg2->kg_method; 483 484 if (kg2->kg_iterations != (size_t)-1 && kg2->kg_iterations > 0) 485 kg1->kg_iterations = kg2->kg_iterations; 486 487 if (kg2->kg_salt) 488 bits_assign(&kg1->kg_salt, kg2->kg_salt); 489 490 if (kg2->kg_key) 491 bits_assign(&kg1->kg_key, kg2->kg_key); 492 493 if (kg2->kg_cmd) 494 string_assign(&kg1->kg_cmd, kg2->kg_cmd); 495 496 return kg1; 497 } 498 499 struct keygen * 500 keygen_method(string_t *in) 501 { 502 struct keygen *kg = keygen_new(); 503 const char *kgm = string_tocharstar(in); 504 505 if (!strcmp("pkcs5_pbkdf2", kgm)) 506 kg->kg_method = KEYGEN_PKCS5_PBKDF2_OLD; 507 if (!strcmp("pkcs5_pbkdf2/sha1", kgm)) 508 kg->kg_method = KEYGEN_PKCS5_PBKDF2_SHA1; 509 if (!strcmp("randomkey", kgm)) 510 kg->kg_method = KEYGEN_RANDOMKEY; 511 if (!strcmp("storedkey", kgm)) 512 kg->kg_method = KEYGEN_STOREDKEY; 513 if (!strcmp("urandomkey", kgm)) 514 kg->kg_method = KEYGEN_URANDOMKEY; 515 if (!strcmp("shell_cmd", kgm)) 516 kg->kg_method = KEYGEN_SHELL_CMD; 517 518 string_free(in); 519 520 if (kg->kg_method == KEYGEN_UNKNOWN) 521 warnx("unrecognized key generation method \"%s\"", kgm); 522 return kg; 523 } 524 525 struct keygen * 526 keygen_set_method(struct keygen *kg, string_t *in) 527 { 528 529 return keygen_combine(kg, keygen_method(in)); 530 } 531 532 struct keygen * 533 keygen_salt(bits_t *in) 534 { 535 struct keygen *kg = keygen_new(); 536 537 kg->kg_salt = in; 538 return kg; 539 } 540 541 struct keygen * 542 keygen_iterations(size_t in) 543 { 544 struct keygen *kg = keygen_new(); 545 546 kg->kg_iterations = in; 547 return kg; 548 } 549 550 void 551 keygen_addlist(struct keygen **l, struct keygen *e) 552 { 553 struct keygen *t; 554 555 if (*l) { 556 t = *l; 557 for (;t->next; t = t->next) 558 ; 559 t->next = e; 560 } else { 561 *l = e; 562 } 563 } 564 565 struct keygen * 566 keygen_key(bits_t *in) 567 { 568 struct keygen *kg = keygen_new(); 569 570 kg->kg_key = in; 571 return kg; 572 } 573 574 struct keygen * 575 keygen_cmd(string_t *in) 576 { 577 struct keygen *kg = keygen_new(); 578 579 kg->kg_cmd = in; 580 return kg; 581 } 582 583 struct params * 584 params_fget(FILE *f) 585 { 586 struct params *p; 587 588 p = cgdparsefile(f); 589 590 if (!p) 591 return NULL; 592 593 /* 594 * We deal with the deprecated keygen structure by prepending it 595 * to the list of keygens, so that the rest of the code does not 596 * have to deal with this backwards compat issue. The deprecated 597 * ``xor_key'' field may be stored in p->dep_keygen->kg_key. If 598 * it exists, we construct a storedkey keygen struct as well. Also, 599 * default the iteration count to 128 as the old code did. 600 */ 601 602 if (p->dep_keygen) { 603 if (p->dep_keygen->kg_iterations == (size_t)-1) 604 p->dep_keygen->kg_iterations = 128; 605 p->dep_keygen->next = p->keygen; 606 if (p->dep_keygen->kg_key) { 607 p->keygen = keygen_generate(KEYGEN_STOREDKEY); 608 p->keygen->kg_key = p->dep_keygen->kg_key; 609 p->dep_keygen->kg_key = NULL; 610 p->keygen->next = p->dep_keygen; 611 } else { 612 p->keygen = p->dep_keygen; 613 } 614 p->dep_keygen = NULL; 615 } 616 return p; 617 } 618 619 struct params * 620 params_cget(const char *fn) 621 { 622 struct params *p; 623 FILE *f; 624 char filename[MAXPATHLEN]; 625 626 if ((f = fopen(fn, "r")) == NULL && fn[0] != '/') { 627 snprintf(filename, sizeof(filename), "%s/%s", 628 CGDCONFIG_DIR, fn); 629 fn = filename; 630 f = fopen(fn, "r"); 631 } 632 633 if (f == NULL) { 634 warn("failed to open params file \"%s\"", fn); 635 return NULL; 636 } 637 p = params_fget(f); 638 (void)fclose(f); 639 return p; 640 } 641 642 #define WRAP_COL 50 643 #define TAB_COL 8 644 645 static void 646 spaces(FILE *f, int len) 647 { 648 649 while (len-- > 0) 650 (void)fputc(' ', f); 651 } 652 653 static void 654 print_kvpair_cstr(FILE *f, int ts, const char *key, const char *val) 655 { 656 657 spaces(f, ts); 658 (void)fprintf(f, "%s %s;\n", key, val); 659 } 660 661 static void 662 print_kvpair_string(FILE *f, int ts, const char *key, const string_t *val) 663 { 664 665 print_kvpair_cstr(f, ts, key, string_tocharstar(val)); 666 } 667 668 static void 669 print_kvpair_int(FILE *f, int ts, const char *key, size_t val) 670 { 671 char *tmp; 672 673 if (!key || val == (size_t)-1) 674 return; 675 676 if (asprintf(&tmp, "%zu", val) == -1) 677 err(1, NULL); 678 print_kvpair_cstr(f, ts, key, tmp); 679 free(tmp); 680 } 681 682 /* 683 * prints out a base64 encoded k-v pair to f. It encodes the length 684 * of the bitstream as a 32bit unsigned integer in network byte order 685 * up front. 686 */ 687 688 static void 689 print_kvpair_b64(FILE *f, int curpos, int ts, const char *key, bits_t *val) 690 { 691 string_t *str; 692 int i; 693 int len; 694 int pos; 695 const char *out; 696 697 if (!key || !val) 698 return; 699 700 str = bits_encode(val); 701 out = string_tocharstar(str); 702 len = strlen(out); 703 704 spaces(f, ts); 705 (void)fprintf(f, "%s ", key); 706 curpos += ts + strlen(key) + 1; 707 ts = curpos; 708 709 for (i=0, pos=curpos; i < len; i++, pos++) { 710 if (pos > WRAP_COL) { 711 (void)fprintf(f, " \\\n"); 712 spaces(f, ts); 713 pos = ts; 714 } 715 (void)fputc(out[i], f); 716 } 717 (void)fprintf(f, ";\n"); 718 string_free(str); 719 } 720 721 int 722 keygen_fput(struct keygen *kg, int ts, FILE *f) 723 { 724 int curpos = 0; 725 726 if (!kg) 727 return 0; 728 (void)fprintf(f, "keygen "); 729 curpos += strlen("keygen "); 730 switch (kg->kg_method) { 731 case KEYGEN_STOREDKEY: 732 (void)fprintf(f, "storedkey "); 733 curpos += strlen("storedkey "); 734 print_kvpair_b64(f, curpos, 0, "key", kg->kg_key); 735 break; 736 case KEYGEN_RANDOMKEY: 737 (void)fprintf(f, "randomkey;\n"); 738 break; 739 case KEYGEN_URANDOMKEY: 740 (void)fprintf(f, "urandomkey;\n"); 741 break; 742 case KEYGEN_PKCS5_PBKDF2_OLD: 743 (void)fprintf(f, "pkcs5_pbkdf2 {\n"); 744 print_kvpair_int(f, ts, "iterations", kg->kg_iterations); 745 print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt); 746 (void)fprintf(f, "};\n"); 747 break; 748 case KEYGEN_PKCS5_PBKDF2_SHA1: 749 (void)fprintf(f, "pkcs5_pbkdf2/sha1 {\n"); 750 print_kvpair_int(f, ts, "iterations", kg->kg_iterations); 751 print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt); 752 (void)fprintf(f, "};\n"); 753 break; 754 default: 755 warnx("keygen_fput: %d not a valid method", kg->kg_method); 756 break; 757 } 758 return keygen_fput(kg->next, ts, f); 759 } 760 761 int 762 params_fput(struct params *p, FILE *f) 763 { 764 int ts = 0; /* tabstop of 0 spaces */ 765 766 print_kvpair_string(f, ts, "algorithm", p->algorithm); 767 print_kvpair_string(f, ts, "iv-method", p->ivmeth); 768 print_kvpair_int(f, ts, "keylength", p->keylen); 769 print_kvpair_int(f, ts, "blocksize", p->bsize); 770 switch (p->verify_method) { 771 case VERIFY_NONE: 772 print_kvpair_cstr(f, ts, "verify_method", "none"); 773 break; 774 case VERIFY_DISKLABEL: 775 print_kvpair_cstr(f, ts, "verify_method", "disklabel"); 776 break; 777 case VERIFY_FFS: 778 print_kvpair_cstr(f, ts, "verify_method", "ffs"); 779 break; 780 case VERIFY_REENTER: 781 print_kvpair_cstr(f, ts, "verify_method", "re-enter"); 782 break; 783 case VERIFY_MBR: 784 print_kvpair_cstr(f, ts, "verify_method", "mbr"); 785 break; 786 case VERIFY_GPT: 787 print_kvpair_cstr(f, ts, "verify_method", "gpt"); 788 break; 789 default: 790 warnx("unsupported verify_method (%d)", p->verify_method); 791 return -1; 792 } 793 return keygen_fput(p->keygen, TAB_COL, f); 794 } 795 796 int 797 params_cput(struct params *p, const char *fn) 798 { 799 FILE *f; 800 801 if (fn && *fn) { 802 if ((f = fopen(fn, "w")) == NULL) { 803 warn("could not open outfile \"%s\"", fn); 804 return -1; 805 } 806 } else { 807 f = stdout; 808 } 809 return params_fput(p, f); 810 } 811 812 static int 813 crypt_defaults_lookup(const char *alg) 814 { 815 unsigned i; 816 817 for (i=0; i < (sizeof(crypto_defaults) / sizeof(crypto_defaults[0])); i++) 818 if (!strcmp(alg, crypto_defaults[i].alg)) 819 return i; 820 821 return -1; 822 } 823