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