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