1 /* $NetBSD: params.c,v 1.6 2003/04/10 05:45:29 elric 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifndef lint 41 __RCSID("$NetBSD: params.c,v 1.6 2003/04/10 05:45:29 elric Exp $"); 42 #endif 43 44 #include <sys/types.h> 45 46 #include <err.h> 47 #include <errno.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 52 #include "params.h" 53 #include "pkcs5_pbkdf2.h" 54 #include "utils.h" 55 56 /* from cgdparse.y */ 57 struct params *cgdparsefile(FILE *); 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 *, int); 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 milliseconds */ 71 72 /* crypto defaults functions */ 73 struct crypto_defaults { 74 char alg[32]; 75 int keylen; 76 } crypto_defaults[] = { 77 { "aes-cbc", 128 }, 78 { "3des-cbc", 192 }, 79 { "blowfish-cbc", 128 } 80 }; 81 82 static int crypt_defaults_lookup(const char *); 83 84 struct params * 85 params_new(void) 86 { 87 struct params *p; 88 89 p = malloc(sizeof(*p)); 90 params_init(p); 91 return p; 92 } 93 94 static void 95 params_init(struct params *p) 96 { 97 98 p->algorithm = NULL; 99 p->ivmeth = NULL; 100 p->key = NULL; 101 p->keylen = -1; 102 p->bsize = -1; 103 p->verify_method = VERIFY_UNKNOWN; 104 p->dep_keygen = NULL; 105 p->keygen = NULL; 106 } 107 108 void 109 params_free(struct params *p) 110 { 111 112 if (!p) 113 return; 114 string_free(p->algorithm); 115 string_free(p->ivmeth); 116 keygen_free(p->dep_keygen); 117 keygen_free(p->keygen); 118 } 119 120 struct params * 121 params_combine(struct params *p1, struct params *p2) 122 { 123 struct params *p; 124 125 if (p1) 126 p = p1; 127 else 128 p = params_new(); 129 130 if (!p2) 131 return p; 132 133 if (p2->algorithm) 134 string_assign(&p->algorithm, p2->algorithm); 135 if (p2->ivmeth) 136 string_assign(&p->ivmeth, p2->ivmeth); 137 if (p2->keylen != -1) 138 p->keylen = p2->keylen; 139 if (p2->bsize != -1) 140 p->bsize = p2->bsize; 141 if (p2->verify_method != VERIFY_UNKNOWN) 142 p->verify_method = p2->verify_method; 143 144 p->dep_keygen = keygen_combine(p->dep_keygen, p2->dep_keygen); 145 keygen_addlist(&p->keygen, p2->keygen); 146 147 /* 148 * at this point we should have moved all allocated data 149 * in p2 into p, so we can free it. 150 */ 151 free(p2); 152 return p; 153 } 154 155 int 156 params_filldefaults(struct params *p) 157 { 158 int i; 159 160 if (p->verify_method == VERIFY_UNKNOWN) 161 p->verify_method = VERIFY_NONE; 162 if (!p->ivmeth) 163 p->ivmeth = string_fromcharstar("encblkno"); 164 if (p->keylen == -1) { 165 i = crypt_defaults_lookup(string_tocharstar(p->algorithm)); 166 if (i != -1) { 167 p->keylen = crypto_defaults[i].keylen; 168 } else { 169 warnx("could not determine key length for unknown " 170 "algorithm \"%s\"", 171 string_tocharstar(p->algorithm)); 172 return -1; 173 } 174 } 175 return 0; 176 } 177 178 /* 179 * params_verify traverses the parameters and all of the keygen methods 180 * looking for inconsistencies. It outputs warnings on non-fatal errors 181 * such as unknown encryption methods, but returns failure on fatal 182 * conditions such as a PKCS5_PBKDF2 keygen without a salt. It is intended 183 * to run before key generation. 184 */ 185 186 int 187 params_verify(const struct params *p) 188 { 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 if (strcmp("encblkno", string_tocharstar(p->ivmeth))) 208 warnx("unknown IV method \"%s\" (warning)", 209 string_tocharstar(p->ivmeth)); 210 if (p->keylen == -1) { 211 warnx("unspecified key length"); 212 return 0; 213 } 214 215 return keygen_verify(p->keygen); 216 } 217 218 struct params * 219 params_algorithm(string_t *in) 220 { 221 struct params *p = params_new(); 222 223 p->algorithm = in; 224 return p; 225 } 226 227 struct params * 228 params_ivmeth(string_t *in) 229 { 230 struct params *p = params_new(); 231 232 p->ivmeth = in; 233 return p; 234 } 235 236 struct params * 237 params_keylen(int in) 238 { 239 struct params *p = params_new(); 240 241 p->keylen = in; 242 return p; 243 } 244 245 struct params * 246 params_bsize(int in) 247 { 248 struct params *p = params_new(); 249 250 p->bsize = in; 251 return p; 252 } 253 254 struct params * 255 params_verify_method(string_t *in) 256 { 257 struct params *p = params_new(); 258 const char *vm = string_tocharstar(in); 259 260 if (!strcmp("none", vm)) 261 p->verify_method = VERIFY_NONE; 262 if (!strcmp("disklabel", vm)) 263 p->verify_method = VERIFY_DISKLABEL; 264 if (!strcmp("ffs", vm)) 265 p->verify_method = VERIFY_FFS; 266 267 string_free(in); 268 269 if (p->verify_method == VERIFY_UNKNOWN) 270 fprintf(stderr, "params_setverify_method: unrecognized " 271 "verify method \"%s\"\n", vm); 272 return p; 273 } 274 275 struct params * 276 params_keygen(struct keygen *in) 277 { 278 struct params *p = params_new(); 279 280 p->keygen = in; 281 return p; 282 } 283 284 struct params * 285 params_dep_keygen(struct keygen *in) 286 { 287 struct params *p = params_new(); 288 289 p->dep_keygen = in; 290 return p; 291 } 292 293 struct keygen * 294 keygen_new(void) 295 { 296 struct keygen *kg; 297 298 kg = malloc(sizeof(*kg)); 299 if (!kg) 300 return NULL; 301 kg->kg_method = KEYGEN_UNKNOWN; 302 kg->kg_iterations = -1; 303 kg->kg_salt = NULL; 304 kg->kg_key = NULL; 305 kg->next = NULL; 306 return kg; 307 } 308 309 void 310 keygen_free(struct keygen *kg) 311 { 312 313 if (!kg) 314 return; 315 bits_free(kg->kg_salt); 316 bits_free(kg->kg_key); 317 keygen_free(kg->next); 318 free(kg); 319 } 320 321 /* 322 * keygen_verify traverses the keygen structures and ensures 323 * that the appropriate information is available. 324 */ 325 326 int 327 keygen_verify(const struct keygen *kg) 328 { 329 330 if (!kg) 331 return 1; 332 switch (kg->kg_method) { 333 case KEYGEN_PKCS5_PBKDF2: 334 if (kg->kg_iterations == -1) { 335 warnx("keygen pkcs5_pbkdf2 must provide `iterations'"); 336 return 0; 337 } 338 if (kg->kg_key) 339 warnx("keygen pkcs5_pbkdf2 does not need a `key'"); 340 if (!kg->kg_salt) { 341 warnx("keygen pkcs5_pbkdf2 must provide a salt"); 342 return 0; 343 } 344 break; 345 case KEYGEN_STOREDKEY: 346 if (kg->kg_iterations != -1) 347 warnx("keygen storedkey does not need `iterations'"); 348 if (!kg->kg_key) { 349 warnx("keygen storedkey must provide a key"); 350 return 0; 351 } 352 if (kg->kg_salt) 353 warnx("keygen storedkey does not need `salt'"); 354 break; 355 case KEYGEN_RANDOMKEY: 356 if (kg->kg_iterations != -1) 357 warnx("keygen randomkey does not need `iterations'"); 358 if (kg->kg_key) 359 warnx("keygen randomkey does not need `key'"); 360 if (kg->kg_salt) 361 warnx("keygen randomkey does not need `salt'"); 362 break; 363 } 364 return keygen_verify(kg->next); 365 } 366 367 struct keygen * 368 keygen_generate(int method) 369 { 370 struct keygen *kg; 371 372 kg = keygen_new(); 373 if (!kg) 374 return NULL; 375 376 kg->kg_method = method; 377 return kg; 378 } 379 380 /* 381 * keygen_filldefaults walks the keygen list and fills in 382 * default values. The defaults may be either calibrated 383 * or randomly generated so this function is designed to be 384 * called when generating a new parameters file, not when 385 * reading a parameters file. 386 */ 387 388 int 389 keygen_filldefaults(struct keygen *kg, int keylen) 390 { 391 392 if (!kg) 393 return 0; 394 switch (kg->kg_method) { 395 case KEYGEN_RANDOMKEY: 396 break; 397 case KEYGEN_PKCS5_PBKDF2: 398 kg->kg_salt = bits_getrandombits(DEFAULT_SALTLEN); 399 kg->kg_iterations = 400 pkcs5_pbkdf2_calibrate(keylen, DEFAULT_ITERATION_TIME); 401 if (kg->kg_iterations < 1) { 402 fprintf(stderr, "%s: could not calibrate " 403 "pkcs5_pbkdf2\n", getprogname()); 404 return -1; 405 } 406 break; 407 case KEYGEN_STOREDKEY: 408 /* Generate a random stored key */ 409 kg->kg_key = bits_getrandombits(keylen); 410 if (!kg->kg_key) { 411 warnx("can't generate random bits for storedkey"); 412 return -1; 413 } 414 break; 415 default: 416 return -1; 417 } 418 419 return keygen_filldefaults(kg->next, keylen); 420 } 421 422 struct keygen * 423 keygen_combine(struct keygen *kg1, struct keygen *kg2) 424 { 425 struct keygen *kg; 426 427 if (!kg1 && !kg2) 428 return NULL; 429 430 if (kg1) 431 kg = kg1; 432 else 433 kg = keygen_new(); 434 435 if (!kg2) 436 return kg; 437 438 if (kg2->kg_method != KEYGEN_UNKNOWN) 439 kg->kg_method = kg2->kg_method; 440 if (kg2->kg_iterations > 0) 441 kg->kg_iterations = kg2->kg_iterations; 442 if (kg2->kg_salt) 443 bits_assign(&kg->kg_salt, kg2->kg_salt); 444 if (kg2->kg_key) 445 bits_assign(&kg->kg_key, kg2->kg_key); 446 return kg; 447 } 448 449 struct keygen * 450 keygen_method(string_t *in) 451 { 452 struct keygen *kg = keygen_new(); 453 const char *kgm = string_tocharstar(in); 454 455 if (!strcmp("pkcs5_pbkdf2", kgm)) 456 kg->kg_method = KEYGEN_PKCS5_PBKDF2; 457 if (!strcmp("randomkey", kgm)) 458 kg->kg_method = KEYGEN_RANDOMKEY; 459 if (!strcmp("storedkey", kgm)) 460 kg->kg_method = KEYGEN_STOREDKEY; 461 462 string_free(in); 463 464 if (kg->kg_method == KEYGEN_UNKNOWN) 465 fprintf(stderr, "unrecognized key generation method " 466 "\"%s\"\n", kgm); 467 return kg; 468 } 469 470 struct keygen * 471 keygen_set_method(struct keygen *kg, string_t *in) 472 { 473 474 return keygen_combine(kg, keygen_method(in)); 475 } 476 477 struct keygen * 478 keygen_salt(bits_t *in) 479 { 480 struct keygen *kg = keygen_new(); 481 482 kg->kg_salt = in; 483 return kg; 484 } 485 486 struct keygen * 487 keygen_iterations(int in) 488 { 489 struct keygen *kg = keygen_new(); 490 491 kg->kg_iterations = in; 492 return kg; 493 } 494 495 void 496 keygen_addlist(struct keygen **l, struct keygen *e) 497 { 498 struct keygen *t; 499 500 if (*l) { 501 t = *l; 502 for (;t->next; t = t->next) 503 ; 504 t->next = e; 505 } else { 506 *l = e; 507 } 508 } 509 510 struct keygen * 511 keygen_key(bits_t *in) 512 { 513 struct keygen *kg = keygen_new(); 514 515 kg->kg_key = in; 516 return kg; 517 } 518 519 struct params * 520 params_fget(FILE *f) 521 { 522 struct params *p; 523 524 p = cgdparsefile(f); 525 526 if (!p) 527 return NULL; 528 529 /* 530 * We deal with the deprecated keygen structure by prepending it 531 * to the list of keygens, so that the rest of the code does not 532 * have to deal with this backwards compat issue. The deprecated 533 * ``xor_key'' field may be stored in p->dep_keygen->kg_key. If 534 * it exists, we construct a storedkey keygen struct as well. Also, 535 * default the iteration count to 128 as the old code did. 536 */ 537 538 if (p->dep_keygen) { 539 if (p->dep_keygen->kg_iterations == -1) 540 p->dep_keygen->kg_iterations = 128; 541 p->dep_keygen->next = p->keygen; 542 if (p->dep_keygen->kg_key) { 543 p->keygen = keygen_generate(KEYGEN_STOREDKEY); 544 p->keygen->kg_key = p->dep_keygen->kg_key; 545 p->dep_keygen->kg_key = NULL; 546 p->keygen->next = p->dep_keygen; 547 } else { 548 p->keygen = p->dep_keygen; 549 } 550 p->dep_keygen = NULL; 551 } 552 return p; 553 } 554 555 struct params * 556 params_cget(const char *fn) 557 { 558 struct params *p; 559 FILE *f; 560 561 f = fopen(fn, "r"); 562 if (!f) { 563 fprintf(stderr, "failed to open params file \"%s\": %s\n", 564 fn, strerror(errno)); 565 return NULL; 566 } 567 p = params_fget(f); 568 fclose(f); 569 return p; 570 } 571 572 #define WRAP_COL 50 573 #define TAB_COL 8 574 575 static void 576 spaces(FILE *f, int len) 577 { 578 579 while (len-- > 0) 580 fputc(' ', f); 581 } 582 583 static void 584 print_kvpair_cstr(FILE *f, int ts, const char *key, const char *val) 585 { 586 587 spaces(f, ts); 588 fprintf(f, "%s %s;\n", key, val); 589 } 590 591 static void 592 print_kvpair_string(FILE *f, int ts, const char *key, const string_t *val) 593 { 594 595 print_kvpair_cstr(f, ts, key, string_tocharstar(val)); 596 } 597 598 static void 599 print_kvpair_int(FILE *f, int ts, const char *key, int val) 600 { 601 char *tmp; 602 603 if (!key || val == -1) 604 return; 605 606 asprintf(&tmp, "%d", val); 607 print_kvpair_cstr(f, ts, key, tmp); 608 free(tmp); 609 } 610 611 /* 612 * prints out a base64 encoded k-v pair to f. It encodes the length 613 * of the bitstream as a 32bit unsigned integer in network byte order 614 * up front. 615 */ 616 617 static void 618 print_kvpair_b64(FILE *f, int curpos, int ts, const char *key, bits_t *val) 619 { 620 string_t *str; 621 int i; 622 int len; 623 int pos; 624 const char *out; 625 626 if (!key || !val) 627 return; 628 629 str = bits_encode(val); 630 out = string_tocharstar(str); 631 len = strlen(out); 632 633 spaces(f, ts); 634 fprintf(f, "%s ", key); 635 curpos += ts + strlen(key) + 1; 636 ts = curpos; 637 638 for (i=0, pos=curpos; i < len; i++, pos++) { 639 if (pos > WRAP_COL) { 640 fprintf(f, " \\\n"); 641 spaces(f, ts); 642 pos = ts; 643 } 644 fputc(out[i], f); 645 } 646 fprintf(f, ";\n"); 647 string_free(str); 648 } 649 650 int 651 keygen_fput(struct keygen *kg, int ts, FILE *f) 652 { 653 int curpos = 0; 654 655 if (!kg) 656 return 0; 657 fprintf(f, "keygen "); 658 curpos += strlen("keygen "); 659 switch (kg->kg_method) { 660 case KEYGEN_STOREDKEY: 661 fprintf(f, "storedkey "); 662 curpos += strlen("storedkey "); 663 print_kvpair_b64(f, curpos, 0, "key", kg->kg_key); 664 break; 665 case KEYGEN_RANDOMKEY: 666 fprintf(f, "randomkey;\n"); 667 break; 668 case KEYGEN_PKCS5_PBKDF2: 669 fprintf(f, "pkcs5_pbkdf2 {\n"); 670 print_kvpair_int(f, ts, "iterations", kg->kg_iterations); 671 print_kvpair_b64(f, 0, ts, "salt", kg->kg_salt); 672 fprintf(f, "};\n"); 673 break; 674 default: 675 fprintf(stderr, "keygen_fput: %d not a valid method\n", 676 kg->kg_method); 677 break; 678 } 679 return keygen_fput(kg->next, ts, f); 680 } 681 682 int 683 params_fput(struct params *p, FILE *f) 684 { 685 int ts = 0; /* tabstop of 0 spaces */ 686 687 print_kvpair_string(f, ts, "algorithm", p->algorithm); 688 print_kvpair_string(f, ts, "iv-method", p->ivmeth); 689 print_kvpair_int(f, ts, "keylength", p->keylen); 690 print_kvpair_int(f, ts, "blocksize", p->bsize); 691 switch (p->verify_method) { 692 case VERIFY_NONE: 693 print_kvpair_cstr(f, ts, "verify_method", "none"); 694 break; 695 case VERIFY_DISKLABEL: 696 print_kvpair_cstr(f, ts, "verify_method", "disklabel"); 697 break; 698 case VERIFY_FFS: 699 print_kvpair_cstr(f, ts, "verify_method", "ffs"); 700 break; 701 default: 702 fprintf(stderr, "unsupported verify_method (%d)\n", 703 p->verify_method); 704 return -1; 705 } 706 keygen_fput(p->keygen, TAB_COL, f); 707 return 0; 708 } 709 710 int 711 params_cput(struct params *p, const char *fn) 712 { 713 FILE *f; 714 715 if (fn && *fn) { 716 f = fopen(fn, "w"); 717 if (!f) { 718 fprintf(stderr, "could not open outfile \"%s\": %s\n", 719 fn, strerror(errno)); 720 perror("fopen"); 721 return -1; 722 } 723 } else { 724 f = stdout; 725 } 726 return params_fput(p, f); 727 } 728 729 static int 730 crypt_defaults_lookup(const char *alg) 731 { 732 int i; 733 734 for (i=0; i < sizeof(crypto_defaults); i++) 735 if (!strcmp(alg, crypto_defaults[i].alg)) 736 break; 737 738 if (i >= sizeof(crypto_defaults)) 739 return -1; 740 else 741 return i; 742 } 743