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