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