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