1 /* $NetBSD: dnssec-keygen.c,v 1.5 2019/04/28 00:01:13 christos Exp $ */ 2 3 /* 4 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 * 13 * Portions Copyright (C) Network Associates, Inc. 14 * 15 * Permission to use, copy, modify, and/or distribute this software for any 16 * purpose with or without fee is hereby granted, provided that the above 17 * copyright notice and this permission notice appear in all copies. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 20 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 22 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 24 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 25 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 */ 27 28 /*! \file */ 29 30 #include <config.h> 31 32 #include <ctype.h> 33 #include <inttypes.h> 34 #include <stdbool.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 38 #include <isc/buffer.h> 39 #include <isc/commandline.h> 40 #include <isc/mem.h> 41 #include <isc/print.h> 42 #include <isc/region.h> 43 #include <isc/string.h> 44 #include <isc/util.h> 45 46 #include <pk11/site.h> 47 48 #include <dns/dnssec.h> 49 #include <dns/fixedname.h> 50 #include <dns/keyvalues.h> 51 #include <dns/log.h> 52 #include <dns/name.h> 53 #include <dns/rdataclass.h> 54 #include <dns/result.h> 55 #include <dns/secalg.h> 56 57 #include <dst/dst.h> 58 59 #if USE_PKCS11 60 #include <pk11/result.h> 61 #endif 62 63 #include "dnssectool.h" 64 65 #define MAX_RSA 4096 /* should be long enough... */ 66 67 const char *program = "dnssec-keygen"; 68 int verbose; 69 70 ISC_PLATFORM_NORETURN_PRE static void 71 usage(void) ISC_PLATFORM_NORETURN_POST; 72 73 static void progress(int p); 74 75 static void 76 usage(void) { 77 fprintf(stderr, "Usage:\n"); 78 fprintf(stderr, " %s [options] name\n\n", program); 79 fprintf(stderr, "Version: %s\n", VERSION); 80 fprintf(stderr, " name: owner of the key\n"); 81 fprintf(stderr, "Options:\n"); 82 fprintf(stderr, " -K <directory>: write keys into directory\n"); 83 fprintf(stderr, " -a <algorithm>:\n"); 84 fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n"); 85 fprintf(stderr, " RSASHA256 | RSASHA512 |\n"); 86 fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n"); 87 fprintf(stderr, " ED25519 | ED448 | DH\n"); 88 fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); 89 fprintf(stderr, " -b <key size in bits>:\n"); 90 fprintf(stderr, " RSASHA1:\t[1024..%d]\n", MAX_RSA); 91 fprintf(stderr, " NSEC3RSASHA1:\t[1024..%d]\n", MAX_RSA); 92 fprintf(stderr, " RSASHA256:\t[1024..%d]\n", MAX_RSA); 93 fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA); 94 fprintf(stderr, " DH:\t\t[128..4096]\n"); 95 fprintf(stderr, " ECDSAP256SHA256:\tignored\n"); 96 fprintf(stderr, " ECDSAP384SHA384:\tignored\n"); 97 fprintf(stderr, " ED25519:\tignored\n"); 98 fprintf(stderr, " ED448:\tignored\n"); 99 fprintf(stderr, " (key size defaults are set according to\n" 100 " algorithm and usage (ZSK or KSK)\n"); 101 fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | " 102 "USER | OTHER\n"); 103 fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n"); 104 fprintf(stderr, " -c <class>: (default: IN)\n"); 105 fprintf(stderr, " -d <digest bits> (0 => max, default)\n"); 106 fprintf(stderr, " -E <engine>:\n"); 107 #if USE_PKCS11 108 fprintf(stderr, " path to PKCS#11 provider library " 109 "(default is %s)\n", PK11_LIB_LOCATION); 110 #else 111 fprintf(stderr, " name of an OpenSSL engine to use\n"); 112 #endif 113 fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n"); 114 fprintf(stderr, " -g <generator>: use specified generator " 115 "(DH only)\n"); 116 fprintf(stderr, " -L <ttl>: default key TTL\n"); 117 fprintf(stderr, " -p <protocol>: (default: 3 [dnssec])\n"); 118 fprintf(stderr, " -s <strength>: strength value this key signs DNS " 119 "records with (default: 0)\n"); 120 fprintf(stderr, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; " 121 "use KEY for SIG(0))\n"); 122 fprintf(stderr, " -t <type>: " 123 "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF " 124 "(default: AUTHCONF)\n"); 125 fprintf(stderr, " -h: print usage and exit\n"); 126 fprintf(stderr, " -m <memory debugging mode>:\n"); 127 fprintf(stderr, " usage | trace | record | size | mctx\n"); 128 fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n"); 129 fprintf(stderr, " -V: print version information\n"); 130 fprintf(stderr, "Timing options:\n"); 131 fprintf(stderr, " -P date/[+-]offset/none: set key publication date " 132 "(default: now)\n"); 133 fprintf(stderr, " -P sync date/[+-]offset/none: set CDS and CDNSKEY " 134 "publication date\n"); 135 fprintf(stderr, " -A date/[+-]offset/none: set key activation date " 136 "(default: now)\n"); 137 fprintf(stderr, " -R date/[+-]offset/none: set key " 138 "revocation date\n"); 139 fprintf(stderr, " -I date/[+-]offset/none: set key " 140 "inactivation date\n"); 141 fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n"); 142 fprintf(stderr, " -D sync date/[+-]offset/none: set CDS and CDNSKEY " 143 "deletion date\n"); 144 145 fprintf(stderr, " -G: generate key only; do not set -P or -A\n"); 146 fprintf(stderr, " -C: generate a backward-compatible key, omitting " 147 "all dates\n"); 148 fprintf(stderr, " -S <key>: generate a successor to an existing " 149 "key\n"); 150 fprintf(stderr, " -i <interval>: prepublication interval for " 151 "successor key " 152 "(default: 30 days)\n"); 153 fprintf(stderr, "Output:\n"); 154 fprintf(stderr, " K<name>+<alg>+<id>.key, " 155 "K<name>+<alg>+<id>.private\n"); 156 157 exit (-1); 158 } 159 160 static void 161 progress(int p) 162 { 163 char c = '*'; 164 165 switch (p) { 166 case 0: 167 c = '.'; 168 break; 169 case 1: 170 c = '+'; 171 break; 172 case 2: 173 c = '*'; 174 break; 175 case 3: 176 c = ' '; 177 break; 178 default: 179 break; 180 } 181 (void) putc(c, stderr); 182 (void) fflush(stderr); 183 } 184 185 int 186 main(int argc, char **argv) { 187 char *algname = NULL, *freeit = NULL; 188 char *nametype = NULL, *type = NULL; 189 char *classname = NULL; 190 char *endp; 191 dst_key_t *key = NULL; 192 dns_fixedname_t fname; 193 dns_name_t *name; 194 uint16_t flags = 0, kskflag = 0, revflag = 0; 195 dns_secalg_t alg; 196 bool conflict = false, null_key = false; 197 bool oldstyle = false; 198 isc_mem_t *mctx = NULL; 199 int ch, generator = 0, param = 0; 200 int protocol = -1, size = -1, signatory = 0; 201 isc_result_t ret; 202 isc_textregion_t r; 203 char filename[255]; 204 const char *directory = NULL; 205 const char *predecessor = NULL; 206 dst_key_t *prevkey = NULL; 207 isc_buffer_t buf; 208 isc_log_t *log = NULL; 209 const char *engine = NULL; 210 dns_rdataclass_t rdclass; 211 int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC; 212 int dbits = 0; 213 dns_ttl_t ttl = 0; 214 bool use_nsec3 = false; 215 isc_stdtime_t publish = 0, activate = 0, revokekey = 0; 216 isc_stdtime_t inactive = 0, deltime = 0; 217 isc_stdtime_t now; 218 int prepub = -1; 219 bool setpub = false, setact = false; 220 bool setrev = false, setinact = false; 221 bool setdel = false, setttl = false; 222 bool unsetpub = false, unsetact = false; 223 bool unsetrev = false, unsetinact = false; 224 bool unsetdel = false; 225 bool genonly = false; 226 bool quiet = false; 227 bool show_progress = false; 228 unsigned char c; 229 isc_stdtime_t syncadd = 0, syncdel = 0; 230 bool setsyncadd = false; 231 bool setsyncdel = false; 232 233 if (argc == 1) 234 usage(); 235 236 #if USE_PKCS11 237 pk11_result_register(); 238 #endif 239 dns_result_register(); 240 241 isc_commandline_errprint = false; 242 243 /* 244 * Process memory debugging argument first. 245 */ 246 #define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:L:m:n:P:p:qR:r:S:s:T:t:" \ 247 "v:V" 248 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { 249 switch (ch) { 250 case 'm': 251 if (strcasecmp(isc_commandline_argument, "record") == 0) 252 isc_mem_debugging |= ISC_MEM_DEBUGRECORD; 253 if (strcasecmp(isc_commandline_argument, "trace") == 0) 254 isc_mem_debugging |= ISC_MEM_DEBUGTRACE; 255 if (strcasecmp(isc_commandline_argument, "usage") == 0) 256 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE; 257 if (strcasecmp(isc_commandline_argument, "size") == 0) 258 isc_mem_debugging |= ISC_MEM_DEBUGSIZE; 259 if (strcasecmp(isc_commandline_argument, "mctx") == 0) 260 isc_mem_debugging |= ISC_MEM_DEBUGCTX; 261 break; 262 default: 263 break; 264 } 265 } 266 isc_commandline_reset = true; 267 268 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); 269 270 isc_stdtime_get(&now); 271 272 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) { 273 switch (ch) { 274 case '3': 275 use_nsec3 = true; 276 break; 277 case 'a': 278 algname = isc_commandline_argument; 279 break; 280 case 'b': 281 size = strtol(isc_commandline_argument, &endp, 10); 282 if (*endp != '\0' || size < 0) 283 fatal("-b requires a non-negative number"); 284 break; 285 case 'C': 286 oldstyle = true; 287 break; 288 case 'c': 289 classname = isc_commandline_argument; 290 break; 291 case 'd': 292 dbits = strtol(isc_commandline_argument, &endp, 10); 293 if (*endp != '\0' || dbits < 0) 294 fatal("-d requires a non-negative number"); 295 break; 296 case 'E': 297 engine = isc_commandline_argument; 298 break; 299 case 'e': 300 fprintf(stderr, 301 "phased-out option -e " 302 "(was 'use (RSA) large exponent')\n"); 303 break; 304 case 'f': 305 c = (unsigned char)(isc_commandline_argument[0]); 306 if (toupper(c) == 'K') 307 kskflag = DNS_KEYFLAG_KSK; 308 else if (toupper(c) == 'R') 309 revflag = DNS_KEYFLAG_REVOKE; 310 else 311 fatal("unknown flag '%s'", 312 isc_commandline_argument); 313 break; 314 case 'g': 315 generator = strtol(isc_commandline_argument, 316 &endp, 10); 317 if (*endp != '\0' || generator <= 0) 318 fatal("-g requires a positive number"); 319 break; 320 case 'K': 321 directory = isc_commandline_argument; 322 ret = try_dir(directory); 323 if (ret != ISC_R_SUCCESS) 324 fatal("cannot open directory %s: %s", 325 directory, isc_result_totext(ret)); 326 break; 327 case 'L': 328 ttl = strtottl(isc_commandline_argument); 329 setttl = true; 330 break; 331 case 'n': 332 nametype = isc_commandline_argument; 333 break; 334 case 'm': 335 break; 336 case 'p': 337 protocol = strtol(isc_commandline_argument, &endp, 10); 338 if (*endp != '\0' || protocol < 0 || protocol > 255) 339 fatal("-p must be followed by a number " 340 "[0..255]"); 341 break; 342 case 'q': 343 quiet = true; 344 break; 345 case 'r': 346 fatal("The -r option has been deprecated.\n" 347 "System random data is always used.\n"); 348 break; 349 case 's': 350 signatory = strtol(isc_commandline_argument, 351 &endp, 10); 352 if (*endp != '\0' || signatory < 0 || signatory > 15) 353 fatal("-s must be followed by a number " 354 "[0..15]"); 355 break; 356 case 'T': 357 if (strcasecmp(isc_commandline_argument, "KEY") == 0) 358 options |= DST_TYPE_KEY; 359 else if (strcasecmp(isc_commandline_argument, 360 "DNSKEY") == 0) 361 /* default behavior */ 362 ; 363 else 364 fatal("unknown type '%s'", 365 isc_commandline_argument); 366 break; 367 case 't': 368 type = isc_commandline_argument; 369 break; 370 case 'v': 371 endp = NULL; 372 verbose = strtol(isc_commandline_argument, &endp, 0); 373 if (*endp != '\0') 374 fatal("-v must be followed by a number"); 375 break; 376 case 'z': 377 /* already the default */ 378 break; 379 case 'G': 380 genonly = true; 381 break; 382 case 'P': 383 /* -Psync ? */ 384 if (isoptarg("sync", argv, usage)) { 385 if (setsyncadd) 386 fatal("-P sync specified more than " 387 "once"); 388 389 syncadd = strtotime(isc_commandline_argument, 390 now, now, &setsyncadd); 391 break; 392 } 393 (void)isoptarg("dnskey", argv, usage); 394 if (setpub || unsetpub) 395 fatal("-P specified more than once"); 396 397 publish = strtotime(isc_commandline_argument, 398 now, now, &setpub); 399 unsetpub = !setpub; 400 break; 401 case 'A': 402 if (setact || unsetact) 403 fatal("-A specified more than once"); 404 405 activate = strtotime(isc_commandline_argument, 406 now, now, &setact); 407 unsetact = !setact; 408 break; 409 case 'R': 410 if (setrev || unsetrev) 411 fatal("-R specified more than once"); 412 413 revokekey = strtotime(isc_commandline_argument, 414 now, now, &setrev); 415 unsetrev = !setrev; 416 break; 417 case 'I': 418 if (setinact || unsetinact) 419 fatal("-I specified more than once"); 420 421 inactive = strtotime(isc_commandline_argument, 422 now, now, &setinact); 423 unsetinact = !setinact; 424 break; 425 case 'D': 426 /* -Dsync ? */ 427 if (isoptarg("sync", argv, usage)) { 428 if (setsyncdel) 429 fatal("-D sync specified more than " 430 "once"); 431 432 syncdel = strtotime(isc_commandline_argument, 433 now, now, &setsyncdel); 434 break; 435 } 436 (void)isoptarg("dnskey", argv, usage); 437 if (setdel || unsetdel) 438 fatal("-D specified more than once"); 439 440 deltime = strtotime(isc_commandline_argument, 441 now, now, &setdel); 442 unsetdel = !setdel; 443 break; 444 case 'S': 445 predecessor = isc_commandline_argument; 446 break; 447 case 'i': 448 prepub = strtottl(isc_commandline_argument); 449 break; 450 case 'F': 451 /* Reserved for FIPS mode */ 452 /* FALLTHROUGH */ 453 case '?': 454 if (isc_commandline_option != '?') 455 fprintf(stderr, "%s: invalid argument -%c\n", 456 program, isc_commandline_option); 457 /* FALLTHROUGH */ 458 case 'h': 459 /* Does not return. */ 460 usage(); 461 462 case 'V': 463 /* Does not return. */ 464 version(program); 465 466 default: 467 fprintf(stderr, "%s: unhandled option -%c\n", 468 program, isc_commandline_option); 469 exit(1); 470 } 471 } 472 473 if (!isatty(0)) 474 quiet = true; 475 476 ret = dst_lib_init(mctx, engine); 477 if (ret != ISC_R_SUCCESS) 478 fatal("could not initialize dst: %s", 479 isc_result_totext(ret)); 480 481 setup_logging(mctx, &log); 482 483 if (predecessor == NULL) { 484 if (prepub == -1) 485 prepub = 0; 486 487 if (argc < isc_commandline_index + 1) 488 fatal("the key name was not specified"); 489 if (argc > isc_commandline_index + 1) 490 fatal("extraneous arguments"); 491 492 name = dns_fixedname_initname(&fname); 493 isc_buffer_init(&buf, argv[isc_commandline_index], 494 strlen(argv[isc_commandline_index])); 495 isc_buffer_add(&buf, strlen(argv[isc_commandline_index])); 496 ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL); 497 if (ret != ISC_R_SUCCESS) 498 fatal("invalid key name %s: %s", 499 argv[isc_commandline_index], 500 isc_result_totext(ret)); 501 502 if (algname == NULL) { 503 fatal("no algorithm specified"); 504 } 505 506 r.base = algname; 507 r.length = strlen(algname); 508 ret = dns_secalg_fromtext(&alg, &r); 509 if (ret != ISC_R_SUCCESS) { 510 fatal("unknown algorithm %s", algname); 511 } 512 if (alg == DST_ALG_DH) { 513 options |= DST_TYPE_KEY; 514 } 515 516 if (!dst_algorithm_supported(alg)) { 517 fatal("unsupported algorithm: %d", alg); 518 } 519 520 if (use_nsec3) { 521 switch (alg) { 522 case DST_ALG_RSASHA1: 523 alg = DST_ALG_NSEC3RSASHA1; 524 break; 525 case DST_ALG_NSEC3RSASHA1: 526 case DST_ALG_RSASHA256: 527 case DST_ALG_RSASHA512: 528 case DST_ALG_ECDSA256: 529 case DST_ALG_ECDSA384: 530 case DST_ALG_ED25519: 531 case DST_ALG_ED448: 532 break; 533 default: 534 fatal("%s is incompatible with NSEC3; " 535 "do not use the -3 option", algname); 536 } 537 } 538 539 if (type != NULL && (options & DST_TYPE_KEY) != 0) { 540 if (strcasecmp(type, "NOAUTH") == 0) { 541 flags |= DNS_KEYTYPE_NOAUTH; 542 } else if (strcasecmp(type, "NOCONF") == 0) { 543 flags |= DNS_KEYTYPE_NOCONF; 544 } else if (strcasecmp(type, "NOAUTHCONF") == 0) { 545 flags |= (DNS_KEYTYPE_NOAUTH | 546 DNS_KEYTYPE_NOCONF); 547 if (size < 0) 548 size = 0; 549 } else if (strcasecmp(type, "AUTHCONF") == 0) { 550 /* nothing */; 551 } else { 552 fatal("invalid type %s", type); 553 } 554 } 555 556 if (size < 0) { 557 switch (alg) { 558 case DST_ALG_RSASHA1: 559 case DST_ALG_NSEC3RSASHA1: 560 case DST_ALG_RSASHA256: 561 case DST_ALG_RSASHA512: 562 if ((kskflag & DNS_KEYFLAG_KSK) != 0) { 563 size = 2048; 564 } else { 565 size = 1024; 566 } 567 if (verbose > 0) { 568 fprintf(stderr, "key size not " 569 "specified; defaulting" 570 " to %d\n", size); 571 } 572 break; 573 case DST_ALG_ECDSA256: 574 case DST_ALG_ECDSA384: 575 case DST_ALG_ED25519: 576 case DST_ALG_ED448: 577 break; 578 default: 579 fatal("key size not specified (-b option)"); 580 } 581 } 582 583 if (!oldstyle && prepub > 0) { 584 if (setpub && setact && (activate - prepub) < publish) 585 fatal("Activation and publication dates " 586 "are closer together than the\n\t" 587 "prepublication interval."); 588 589 if (!setpub && !setact) { 590 setpub = setact = true; 591 publish = now; 592 activate = now + prepub; 593 } else if (setpub && !setact) { 594 setact = true; 595 activate = publish + prepub; 596 } else if (setact && !setpub) { 597 setpub = true; 598 publish = activate - prepub; 599 } 600 601 if ((activate - prepub) < now) 602 fatal("Time until activation is shorter " 603 "than the\n\tprepublication interval."); 604 } 605 } else { 606 char keystr[DST_KEY_FORMATSIZE]; 607 isc_stdtime_t when; 608 int major, minor; 609 610 if (prepub == -1) 611 prepub = (30 * 86400); 612 613 if (algname != NULL) 614 fatal("-S and -a cannot be used together"); 615 if (size >= 0) 616 fatal("-S and -b cannot be used together"); 617 if (nametype != NULL) 618 fatal("-S and -n cannot be used together"); 619 if (type != NULL) 620 fatal("-S and -t cannot be used together"); 621 if (setpub || unsetpub) 622 fatal("-S and -P cannot be used together"); 623 if (setact || unsetact) 624 fatal("-S and -A cannot be used together"); 625 if (use_nsec3) 626 fatal("-S and -3 cannot be used together"); 627 if (oldstyle) 628 fatal("-S and -C cannot be used together"); 629 if (genonly) 630 fatal("-S and -G cannot be used together"); 631 632 ret = dst_key_fromnamedfile(predecessor, directory, 633 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE, 634 mctx, &prevkey); 635 if (ret != ISC_R_SUCCESS) 636 fatal("Invalid keyfile %s: %s", 637 predecessor, isc_result_totext(ret)); 638 if (!dst_key_isprivate(prevkey)) 639 fatal("%s is not a private key", predecessor); 640 641 name = dst_key_name(prevkey); 642 alg = dst_key_alg(prevkey); 643 size = dst_key_size(prevkey); 644 flags = dst_key_flags(prevkey); 645 646 dst_key_format(prevkey, keystr, sizeof(keystr)); 647 dst_key_getprivateformat(prevkey, &major, &minor); 648 if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) 649 fatal("Key %s has incompatible format version %d.%d\n\t" 650 "It is not possible to generate a successor key.", 651 keystr, major, minor); 652 653 ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when); 654 if (ret != ISC_R_SUCCESS) 655 fatal("Key %s has no activation date.\n\t" 656 "You must use dnssec-settime -A to set one " 657 "before generating a successor.", keystr); 658 659 ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate); 660 if (ret != ISC_R_SUCCESS) 661 fatal("Key %s has no inactivation date.\n\t" 662 "You must use dnssec-settime -I to set one " 663 "before generating a successor.", keystr); 664 665 publish = activate - prepub; 666 if (publish < now) 667 fatal("Key %s becomes inactive\n\t" 668 "sooner than the prepublication period " 669 "for the new key ends.\n\t" 670 "Either change the inactivation date with " 671 "dnssec-settime -I,\n\t" 672 "or use the -i option to set a shorter " 673 "prepublication interval.", keystr); 674 675 ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when); 676 if (ret != ISC_R_SUCCESS) 677 fprintf(stderr, "%s: WARNING: Key %s has no removal " 678 "date;\n\t it will remain in the zone " 679 "indefinitely after rollover.\n\t " 680 "You can use dnssec-settime -D to " 681 "change this.\n", program, keystr); 682 683 setpub = setact = true; 684 } 685 686 switch (alg) { 687 case DNS_KEYALG_RSASHA1: 688 case DNS_KEYALG_NSEC3RSASHA1: 689 case DNS_KEYALG_RSASHA256: 690 if (size != 0 && (size < 1024 || size > MAX_RSA)) 691 fatal("RSA key size %d out of range", size); 692 break; 693 case DNS_KEYALG_RSASHA512: 694 if (size != 0 && (size < 1024 || size > MAX_RSA)) 695 fatal("RSA key size %d out of range", size); 696 break; 697 case DNS_KEYALG_DH: 698 if (size != 0 && (size < 128 || size > 4096)) 699 fatal("DH key size %d out of range", size); 700 break; 701 case DST_ALG_ECDSA256: 702 size = 256; 703 break; 704 case DST_ALG_ECDSA384: 705 size = 384; 706 break; 707 case DST_ALG_ED25519: 708 size = 256; 709 break; 710 case DST_ALG_ED448: 711 size = 456; 712 break; 713 } 714 715 if (alg != DNS_KEYALG_DH && generator != 0) 716 fatal("specified DH generator for a non-DH key"); 717 718 if (nametype == NULL) { 719 if ((options & DST_TYPE_KEY) != 0) /* KEY */ 720 fatal("no nametype specified"); 721 flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */ 722 } else if (strcasecmp(nametype, "zone") == 0) 723 flags |= DNS_KEYOWNER_ZONE; 724 else if ((options & DST_TYPE_KEY) != 0) { /* KEY */ 725 if (strcasecmp(nametype, "host") == 0 || 726 strcasecmp(nametype, "entity") == 0) 727 flags |= DNS_KEYOWNER_ENTITY; 728 else if (strcasecmp(nametype, "user") == 0) 729 flags |= DNS_KEYOWNER_USER; 730 else 731 fatal("invalid KEY nametype %s", nametype); 732 } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */ 733 fatal("invalid DNSKEY nametype %s", nametype); 734 735 rdclass = strtoclass(classname); 736 737 if (directory == NULL) 738 directory = "."; 739 740 if ((options & DST_TYPE_KEY) != 0) /* KEY */ 741 flags |= signatory; 742 else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */ 743 flags |= kskflag; 744 flags |= revflag; 745 } 746 747 if (protocol == -1) 748 protocol = DNS_KEYPROTO_DNSSEC; 749 else if ((options & DST_TYPE_KEY) == 0 && 750 protocol != DNS_KEYPROTO_DNSSEC) 751 fatal("invalid DNSKEY protocol: %d", protocol); 752 753 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { 754 if (size > 0) 755 fatal("specified null key with non-zero size"); 756 if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) 757 fatal("specified null key with signing authority"); 758 } 759 760 if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE && 761 alg == DNS_KEYALG_DH) 762 { 763 fatal("a key with algorithm '%s' cannot be a zone key", 764 algname); 765 } 766 767 switch(alg) { 768 case DNS_KEYALG_RSASHA1: 769 case DNS_KEYALG_NSEC3RSASHA1: 770 case DNS_KEYALG_RSASHA256: 771 case DNS_KEYALG_RSASHA512: 772 show_progress = true; 773 break; 774 775 case DNS_KEYALG_DH: 776 param = generator; 777 break; 778 779 case DST_ALG_ECDSA256: 780 case DST_ALG_ECDSA384: 781 case DST_ALG_ED25519: 782 case DST_ALG_ED448: 783 show_progress = true; 784 break; 785 } 786 787 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) 788 null_key = true; 789 790 isc_buffer_init(&buf, filename, sizeof(filename) - 1); 791 792 do { 793 conflict = false; 794 795 if (!quiet && show_progress) { 796 fprintf(stderr, "Generating key pair."); 797 ret = dst_key_generate(name, alg, size, param, flags, 798 protocol, rdclass, mctx, &key, 799 &progress); 800 putc('\n', stderr); 801 fflush(stderr); 802 } else { 803 ret = dst_key_generate(name, alg, size, param, flags, 804 protocol, rdclass, mctx, &key, 805 NULL); 806 } 807 808 if (ret != ISC_R_SUCCESS) { 809 char namestr[DNS_NAME_FORMATSIZE]; 810 char algstr[DNS_SECALG_FORMATSIZE]; 811 dns_name_format(name, namestr, sizeof(namestr)); 812 dns_secalg_format(alg, algstr, sizeof(algstr)); 813 fatal("failed to generate key %s/%s: %s\n", 814 namestr, algstr, isc_result_totext(ret)); 815 /* NOTREACHED */ 816 exit(-1); 817 } 818 819 dst_key_setbits(key, dbits); 820 821 /* 822 * Set key timing metadata (unless using -C) 823 * 824 * Creation date is always set to "now". 825 * 826 * For a new key without an explicit predecessor, publish 827 * and activation dates are set to "now" by default, but 828 * can both be overridden. 829 * 830 * For a successor key, activation is set to match the 831 * predecessor's inactivation date. Publish is set to 30 832 * days earlier than that (XXX: this should be configurable). 833 * If either of the resulting dates are in the past, that's 834 * an error; the inactivation date of the predecessor key 835 * must be updated before a successor key can be created. 836 */ 837 if (!oldstyle) { 838 dst_key_settime(key, DST_TIME_CREATED, now); 839 840 if (genonly && (setpub || setact)) 841 fatal("cannot use -G together with " 842 "-P or -A options"); 843 844 if (setpub) 845 dst_key_settime(key, DST_TIME_PUBLISH, publish); 846 else if (setact && !unsetpub) 847 dst_key_settime(key, DST_TIME_PUBLISH, 848 activate - prepub); 849 else if (!genonly && !unsetpub) 850 dst_key_settime(key, DST_TIME_PUBLISH, now); 851 852 if (setact) 853 dst_key_settime(key, DST_TIME_ACTIVATE, 854 activate); 855 else if (!genonly && !unsetact) 856 dst_key_settime(key, DST_TIME_ACTIVATE, now); 857 858 if (setrev) { 859 if (kskflag == 0) 860 fprintf(stderr, "%s: warning: Key is " 861 "not flagged as a KSK, but -R " 862 "was used. Revoking a ZSK is " 863 "legal, but undefined.\n", 864 program); 865 dst_key_settime(key, DST_TIME_REVOKE, revokekey); 866 } 867 868 if (setinact) 869 dst_key_settime(key, DST_TIME_INACTIVE, 870 inactive); 871 872 if (setdel) { 873 if (setinact && deltime < inactive) 874 fprintf(stderr, "%s: warning: Key is " 875 "scheduled to be deleted " 876 "before it is scheduled to be " 877 "made inactive.\n", 878 program); 879 dst_key_settime(key, DST_TIME_DELETE, deltime); 880 } 881 882 if (setsyncadd) 883 dst_key_settime(key, DST_TIME_SYNCPUBLISH, 884 syncadd); 885 886 if (setsyncdel) 887 dst_key_settime(key, DST_TIME_SYNCDELETE, 888 syncdel); 889 890 } else { 891 if (setpub || setact || setrev || setinact || 892 setdel || unsetpub || unsetact || 893 unsetrev || unsetinact || unsetdel || genonly || 894 setsyncadd || setsyncdel) 895 fatal("cannot use -C together with " 896 "-P, -A, -R, -I, -D, or -G options"); 897 /* 898 * Compatibility mode: Private-key-format 899 * should be set to 1.2. 900 */ 901 dst_key_setprivateformat(key, 1, 2); 902 } 903 904 /* Set the default key TTL */ 905 if (setttl) 906 dst_key_setttl(key, ttl); 907 908 /* 909 * Do not overwrite an existing key, or create a key 910 * if there is a risk of ID collision due to this key 911 * or another key being revoked. 912 */ 913 if (key_collision(key, name, directory, mctx, NULL)) { 914 conflict = true; 915 if (null_key) { 916 dst_key_free(&key); 917 break; 918 } 919 920 if (verbose > 0) { 921 isc_buffer_clear(&buf); 922 ret = dst_key_buildfilename(key, 0, 923 directory, &buf); 924 if (ret == ISC_R_SUCCESS) 925 fprintf(stderr, 926 "%s: %s already exists, or " 927 "might collide with another " 928 "key upon revokation. " 929 "Generating a new key\n", 930 program, filename); 931 } 932 933 dst_key_free(&key); 934 } 935 } while (conflict == true); 936 937 if (conflict) 938 fatal("cannot generate a null key due to possible key ID " 939 "collision"); 940 941 ret = dst_key_tofile(key, options, directory); 942 if (ret != ISC_R_SUCCESS) { 943 char keystr[DST_KEY_FORMATSIZE]; 944 dst_key_format(key, keystr, sizeof(keystr)); 945 fatal("failed to write key %s: %s\n", keystr, 946 isc_result_totext(ret)); 947 } 948 949 isc_buffer_clear(&buf); 950 ret = dst_key_buildfilename(key, 0, NULL, &buf); 951 if (ret != ISC_R_SUCCESS) 952 fatal("dst_key_buildfilename returned: %s\n", 953 isc_result_totext(ret)); 954 printf("%s\n", filename); 955 dst_key_free(&key); 956 if (prevkey != NULL) 957 dst_key_free(&prevkey); 958 959 cleanup_logging(&log); 960 dst_lib_destroy(); 961 dns_name_destroy(); 962 if (verbose > 10) 963 isc_mem_stats(mctx, stdout); 964 isc_mem_destroy(&mctx); 965 966 if (freeit != NULL) 967 free(freeit); 968 969 return (0); 970 } 971