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 62static void params_init(struct params *); 63 64static void print_kvpair_cstr(FILE *, int, const char *, const char *); 65static void print_kvpair_string(FILE *, int, const char *, const string_t *); 66static void print_kvpair_int(FILE *, int, const char *, size_t); 67static void print_kvpair_b64(FILE *, int, int, const char *, bits_t *); 68 69static 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 */ 76static 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 87static int crypt_defaults_lookup(const char *); 88 89struct params * 90params_new(void) 91{ 92 struct params *p; 93 94 p = emalloc(sizeof(*p)); 95 params_init(p); 96 return p; 97} 98 99static void 100params_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 113void 114params_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 125struct params * 126params_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 160int 161params_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 193int 194params_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 236struct params * 237params_algorithm(string_t *in) 238{ 239 struct params *p = params_new(); 240 241 p->algorithm = in; 242 return p; 243} 244 245struct params * 246params_ivmeth(string_t *in) 247{ 248 struct params *p = params_new(); 249 250 p->ivmeth = in; 251 return p; 252} 253 254struct params * 255params_keylen(size_t in) 256{ 257 struct params *p = params_new(); 258 259 p->keylen = in; 260 return p; 261} 262 263struct params * 264params_bsize(size_t in) 265{ 266 struct params *p = params_new(); 267 268 p->bsize = in; 269 return p; 270} 271 272struct params * 273params_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 303struct params * 304params_keygen(struct keygen *in) 305{ 306 struct params *p = params_new(); 307 308 p->keygen = in; 309 return p; 310} 311 312struct params * 313params_dep_keygen(struct keygen *in) 314{ 315 struct params *p = params_new(); 316 317 p->dep_keygen = in; 318 return p; 319} 320 321struct keygen * 322keygen_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 343void 344keygen_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 363int 364keygen_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 467struct keygen * 468keygen_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 488int 489keygen_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 */ 539void 540keygen_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 556int 557keygen_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 610int 611keygen_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 648struct keygen * 649keygen_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 696struct keygen * 697keygen_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 726struct keygen * 727keygen_set_method(struct keygen *kg, string_t *in) 728{ 729 730 return keygen_combine(kg, keygen_method(in)); 731} 732 733struct keygen * 734keygen_salt(bits_t *in) 735{ 736 struct keygen *kg = keygen_new(); 737 738 kg->kg_salt = in; 739 return kg; 740} 741 742struct keygen * 743keygen_iterations(size_t in) 744{ 745 struct keygen *kg = keygen_new(); 746 747 kg->kg_iterations = in; 748 return kg; 749} 750 751struct keygen * 752keygen_memory(size_t in) 753{ 754 struct keygen *kg = keygen_new(); 755 756 kg->kg_memory = in; 757 return kg; 758} 759 760struct keygen * 761keygen_parallelism(size_t in) 762{ 763 struct keygen *kg = keygen_new(); 764 765 kg->kg_parallelism = in; 766 return kg; 767} 768 769struct keygen * 770keygen_version(size_t in) 771{ 772 struct keygen *kg = keygen_new(); 773 774 kg->kg_version = in; 775 return kg; 776} 777 778void 779keygen_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 793struct keygen * 794keygen_key(bits_t *in) 795{ 796 struct keygen *kg = keygen_new(); 797 798 kg->kg_key = in; 799 return kg; 800} 801 802struct keygen * 803keygen_cmd(string_t *in) 804{ 805 struct keygen *kg = keygen_new(); 806 807 kg->kg_cmd = in; 808 return kg; 809} 810 811struct keygen * 812keygen_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 832struct params * 833params_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 868struct params * 869params_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 894static void 895spaces(FILE *f, int len) 896{ 897 898 while (len-- > 0) 899 (void)fputc(' ', f); 900} 901 902static void 903print_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 910static void 911print_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 917static void 918print_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 937static void 938print_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 970static void 971print_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 990int 991keygen_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 1044int 1045params_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 1084int 1085params_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 1100static int 1101crypt_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