00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <config.h>
00035
00036 #include <ctype.h>
00037 #include <stdlib.h>
00038 #include <unistd.h>
00039
00040 #include <isc/buffer.h>
00041 #include <isc/commandline.h>
00042 #include <isc/entropy.h>
00043 #include <isc/mem.h>
00044 #include <isc/region.h>
00045 #include <isc/string.h>
00046 #include <isc/util.h>
00047
00048 #include <dns/dnssec.h>
00049 #include <dns/fixedname.h>
00050 #include <dns/keyvalues.h>
00051 #include <dns/log.h>
00052 #include <dns/name.h>
00053 #include <dns/rdataclass.h>
00054 #include <dns/result.h>
00055 #include <dns/secalg.h>
00056
00057 #include <dst/dst.h>
00058
00059 #ifdef PKCS11CRYPTO
00060 #include <pk11/result.h>
00061 #endif
00062
00063 #include "dnssectool.h"
00064
00065 #define MAX_RSA 4096
00066
00067 const char *program = "dnssec-keygen";
00068 int verbose;
00069
00070 #define DEFAULT_ALGORITHM "RSASHA1"
00071 #define DEFAULT_NSEC3_ALGORITHM "NSEC3RSASHA1"
00072
00073 ISC_PLATFORM_NORETURN_PRE static void
00074 usage(void) ISC_PLATFORM_NORETURN_POST;
00075
00076 static void progress(int p);
00077
00078 static void
00079 usage(void) {
00080 fprintf(stderr, "Usage:\n");
00081 fprintf(stderr, " %s [options] name\n\n", program);
00082 fprintf(stderr, "Version: %s\n", VERSION);
00083 fprintf(stderr, " name: owner of the key\n");
00084 fprintf(stderr, "Options:\n");
00085 fprintf(stderr, " -K <directory>: write keys into directory\n");
00086 fprintf(stderr, " -a <algorithm>:\n");
00087 fprintf(stderr, " RSA | RSAMD5 | DSA | RSASHA1 | NSEC3RSASHA1"
00088 " | NSEC3DSA |\n");
00089 fprintf(stderr, " RSASHA256 | RSASHA512 | ECCGOST |\n");
00090 fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n");
00091 fprintf(stderr, " DH | HMAC-MD5 | HMAC-SHA1 | HMAC-SHA224 | "
00092 "HMAC-SHA256 | \n");
00093 fprintf(stderr, " HMAC-SHA384 | HMAC-SHA512\n");
00094 fprintf(stderr, " (default: RSASHA1, or "
00095 "NSEC3RSASHA1 if using -3)\n");
00096 fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
00097 fprintf(stderr, " -b <key size in bits>:\n");
00098 fprintf(stderr, " RSAMD5:\t[512..%d]\n", MAX_RSA);
00099 fprintf(stderr, " RSASHA1:\t[512..%d]\n", MAX_RSA);
00100 fprintf(stderr, " NSEC3RSASHA1:\t[512..%d]\n", MAX_RSA);
00101 fprintf(stderr, " RSASHA256:\t[512..%d]\n", MAX_RSA);
00102 fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA);
00103 fprintf(stderr, " DH:\t\t[128..4096]\n");
00104 fprintf(stderr, " DSA:\t\t[512..1024] and divisible by 64\n");
00105 fprintf(stderr, " NSEC3DSA:\t[512..1024] and divisible "
00106 "by 64\n");
00107 fprintf(stderr, " ECCGOST:\tignored\n");
00108 fprintf(stderr, " ECDSAP256SHA256:\tignored\n");
00109 fprintf(stderr, " ECDSAP384SHA384:\tignored\n");
00110 fprintf(stderr, " HMAC-MD5:\t[1..512]\n");
00111 fprintf(stderr, " HMAC-SHA1:\t[1..160]\n");
00112 fprintf(stderr, " HMAC-SHA224:\t[1..224]\n");
00113 fprintf(stderr, " HMAC-SHA256:\t[1..256]\n");
00114 fprintf(stderr, " HMAC-SHA384:\t[1..384]\n");
00115 fprintf(stderr, " HMAC-SHA512:\t[1..512]\n");
00116 fprintf(stderr, " (if using the default algorithm, key size\n"
00117 " defaults to 2048 for KSK, or 1024 for all "
00118 "others)\n");
00119 fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | "
00120 "USER | OTHER\n");
00121 fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
00122 fprintf(stderr, " -c <class>: (default: IN)\n");
00123 fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
00124 fprintf(stderr, " -E <engine>:\n");
00125 #if defined(PKCS11CRYPTO)
00126 fprintf(stderr, " path to PKCS#11 provider library "
00127 "(default is %s)\n", PK11_LIB_LOCATION);
00128 #elif defined(USE_PKCS11)
00129 fprintf(stderr, " name of an OpenSSL engine to use "
00130 "(default is \"pkcs11\")\n");
00131 #else
00132 fprintf(stderr, " name of an OpenSSL engine to use\n");
00133 #endif
00134 fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n");
00135 fprintf(stderr, " -g <generator>: use specified generator "
00136 "(DH only)\n");
00137 fprintf(stderr, " -L <ttl>: default key TTL\n");
00138 fprintf(stderr, " -p <protocol>: (default: 3 [dnssec])\n");
00139 fprintf(stderr, " -r <randomdev>: a file containing random data\n");
00140 fprintf(stderr, " -s <strength>: strength value this key signs DNS "
00141 "records with (default: 0)\n");
00142 fprintf(stderr, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; "
00143 "use KEY for SIG(0))\n");
00144 fprintf(stderr, " -t <type>: "
00145 "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
00146 "(default: AUTHCONF)\n");
00147 fprintf(stderr, " -h: print usage and exit\n");
00148 fprintf(stderr, " -m <memory debugging mode>:\n");
00149 fprintf(stderr, " usage | trace | record | size | mctx\n");
00150 fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n");
00151 fprintf(stderr, " -V: print version information\n");
00152 fprintf(stderr, "Timing options:\n");
00153 fprintf(stderr, " -P date/[+-]offset/none: set key publication date "
00154 "(default: now)\n");
00155 fprintf(stderr, " -A date/[+-]offset/none: set key activation date "
00156 "(default: now)\n");
00157 fprintf(stderr, " -R date/[+-]offset/none: set key "
00158 "revocation date\n");
00159 fprintf(stderr, " -I date/[+-]offset/none: set key "
00160 "inactivation date\n");
00161 fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n");
00162 fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
00163 fprintf(stderr, " -C: generate a backward-compatible key, omitting "
00164 "all dates\n");
00165 fprintf(stderr, " -S <key>: generate a successor to an existing "
00166 "key\n");
00167 fprintf(stderr, " -i <interval>: prepublication interval for "
00168 "successor key "
00169 "(default: 30 days)\n");
00170 fprintf(stderr, "Output:\n");
00171 fprintf(stderr, " K<name>+<alg>+<id>.key, "
00172 "K<name>+<alg>+<id>.private\n");
00173
00174 exit (-1);
00175 }
00176
00177 static isc_boolean_t
00178 dsa_size_ok(int size) {
00179 return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0));
00180 }
00181
00182 static void
00183 progress(int p)
00184 {
00185 char c = '*';
00186
00187 switch (p) {
00188 case 0:
00189 c = '.';
00190 break;
00191 case 1:
00192 c = '+';
00193 break;
00194 case 2:
00195 c = '*';
00196 break;
00197 case 3:
00198 c = ' ';
00199 break;
00200 default:
00201 break;
00202 }
00203 (void) putc(c, stderr);
00204 (void) fflush(stderr);
00205 }
00206
00207 int
00208 main(int argc, char **argv) {
00209 char *algname = NULL, *freeit = NULL;
00210 char *nametype = NULL, *type = NULL;
00211 char *classname = NULL;
00212 char *endp;
00213 dst_key_t *key = NULL;
00214 dns_fixedname_t fname;
00215 dns_name_t *name;
00216 isc_uint16_t flags = 0, kskflag = 0, revflag = 0;
00217 dns_secalg_t alg;
00218 isc_boolean_t conflict = ISC_FALSE, null_key = ISC_FALSE;
00219 isc_boolean_t oldstyle = ISC_FALSE;
00220 isc_mem_t *mctx = NULL;
00221 int ch, generator = 0, param = 0;
00222 int protocol = -1, size = -1, signatory = 0;
00223 isc_result_t ret;
00224 isc_textregion_t r;
00225 char filename[255];
00226 const char *directory = NULL;
00227 const char *predecessor = NULL;
00228 dst_key_t *prevkey = NULL;
00229 isc_buffer_t buf;
00230 isc_log_t *log = NULL;
00231 isc_entropy_t *ectx = NULL;
00232 #ifdef USE_PKCS11
00233 const char *engine = PKCS11_ENGINE;
00234 #else
00235 const char *engine = NULL;
00236 #endif
00237 dns_rdataclass_t rdclass;
00238 int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
00239 int dbits = 0;
00240 dns_ttl_t ttl = 0;
00241 isc_boolean_t use_default = ISC_FALSE, use_nsec3 = ISC_FALSE;
00242 isc_stdtime_t publish = 0, activate = 0, revokekey = 0;
00243 isc_stdtime_t inactive = 0, delete = 0;
00244 isc_stdtime_t now;
00245 int prepub = -1;
00246 isc_boolean_t setpub = ISC_FALSE, setact = ISC_FALSE;
00247 isc_boolean_t setrev = ISC_FALSE, setinact = ISC_FALSE;
00248 isc_boolean_t setdel = ISC_FALSE, setttl = ISC_FALSE;
00249 isc_boolean_t unsetpub = ISC_FALSE, unsetact = ISC_FALSE;
00250 isc_boolean_t unsetrev = ISC_FALSE, unsetinact = ISC_FALSE;
00251 isc_boolean_t unsetdel = ISC_FALSE;
00252 isc_boolean_t genonly = ISC_FALSE;
00253 isc_boolean_t quiet = ISC_FALSE;
00254 isc_boolean_t show_progress = ISC_FALSE;
00255 unsigned char c;
00256
00257 if (argc == 1)
00258 usage();
00259
00260 #ifdef PKCS11CRYPTO
00261 pk11_result_register();
00262 #endif
00263 dns_result_register();
00264
00265 isc_commandline_errprint = ISC_FALSE;
00266
00267
00268
00269
00270 #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:" \
00271 "v:V"
00272 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
00273 switch (ch) {
00274 case 'm':
00275 if (strcasecmp(isc_commandline_argument, "record") == 0)
00276 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
00277 if (strcasecmp(isc_commandline_argument, "trace") == 0)
00278 isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
00279 if (strcasecmp(isc_commandline_argument, "usage") == 0)
00280 isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
00281 if (strcasecmp(isc_commandline_argument, "size") == 0)
00282 isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
00283 if (strcasecmp(isc_commandline_argument, "mctx") == 0)
00284 isc_mem_debugging |= ISC_MEM_DEBUGCTX;
00285 break;
00286 default:
00287 break;
00288 }
00289 }
00290 isc_commandline_reset = ISC_TRUE;
00291
00292 RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
00293
00294 isc_stdtime_get(&now);
00295
00296 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
00297 switch (ch) {
00298 case '3':
00299 use_nsec3 = ISC_TRUE;
00300 break;
00301 case 'a':
00302 algname = isc_commandline_argument;
00303 break;
00304 case 'b':
00305 size = strtol(isc_commandline_argument, &endp, 10);
00306 if (*endp != '\0' || size < 0)
00307 fatal("-b requires a non-negative number");
00308 break;
00309 case 'C':
00310 oldstyle = ISC_TRUE;
00311 break;
00312 case 'c':
00313 classname = isc_commandline_argument;
00314 break;
00315 case 'd':
00316 dbits = strtol(isc_commandline_argument, &endp, 10);
00317 if (*endp != '\0' || dbits < 0)
00318 fatal("-d requires a non-negative number");
00319 break;
00320 case 'E':
00321 engine = isc_commandline_argument;
00322 break;
00323 case 'e':
00324 fprintf(stderr,
00325 "phased-out option -e "
00326 "(was 'use (RSA) large exponent)\n");
00327 break;
00328 case 'f':
00329 c = (unsigned char)(isc_commandline_argument[0]);
00330 if (toupper(c) == 'K')
00331 kskflag = DNS_KEYFLAG_KSK;
00332 else if (toupper(c) == 'R')
00333 revflag = DNS_KEYFLAG_REVOKE;
00334 else
00335 fatal("unknown flag '%s'",
00336 isc_commandline_argument);
00337 break;
00338 case 'g':
00339 generator = strtol(isc_commandline_argument,
00340 &endp, 10);
00341 if (*endp != '\0' || generator <= 0)
00342 fatal("-g requires a positive number");
00343 break;
00344 case 'K':
00345 directory = isc_commandline_argument;
00346 ret = try_dir(directory);
00347 if (ret != ISC_R_SUCCESS)
00348 fatal("cannot open directory %s: %s",
00349 directory, isc_result_totext(ret));
00350 break;
00351 case 'k':
00352 fatal("The -k option has been deprecated.\n"
00353 "To generate a key-signing key, use -f KSK.\n"
00354 "To generate a key with TYPE=KEY, use -T KEY.\n");
00355 break;
00356 case 'L':
00357 ttl = strtottl(isc_commandline_argument);
00358 setttl = ISC_TRUE;
00359 break;
00360 case 'n':
00361 nametype = isc_commandline_argument;
00362 break;
00363 case 'm':
00364 break;
00365 case 'p':
00366 protocol = strtol(isc_commandline_argument, &endp, 10);
00367 if (*endp != '\0' || protocol < 0 || protocol > 255)
00368 fatal("-p must be followed by a number "
00369 "[0..255]");
00370 break;
00371 case 'q':
00372 quiet = ISC_TRUE;
00373 break;
00374 case 'r':
00375 setup_entropy(mctx, isc_commandline_argument, &ectx);
00376 break;
00377 case 's':
00378 signatory = strtol(isc_commandline_argument,
00379 &endp, 10);
00380 if (*endp != '\0' || signatory < 0 || signatory > 15)
00381 fatal("-s must be followed by a number "
00382 "[0..15]");
00383 break;
00384 case 'T':
00385 if (strcasecmp(isc_commandline_argument, "KEY") == 0)
00386 options |= DST_TYPE_KEY;
00387 else if (strcasecmp(isc_commandline_argument,
00388 "DNSKEY") == 0)
00389
00390 ;
00391 else
00392 fatal("unknown type '%s'",
00393 isc_commandline_argument);
00394 break;
00395 case 't':
00396 type = isc_commandline_argument;
00397 break;
00398 case 'v':
00399 endp = NULL;
00400 verbose = strtol(isc_commandline_argument, &endp, 0);
00401 if (*endp != '\0')
00402 fatal("-v must be followed by a number");
00403 break;
00404 case 'z':
00405
00406 break;
00407 case 'G':
00408 genonly = ISC_TRUE;
00409 break;
00410 case 'P':
00411 if (setpub || unsetpub)
00412 fatal("-P specified more than once");
00413
00414 publish = strtotime(isc_commandline_argument,
00415 now, now, &setpub);
00416 unsetpub = !setpub;
00417 break;
00418 case 'A':
00419 if (setact || unsetact)
00420 fatal("-A specified more than once");
00421
00422 activate = strtotime(isc_commandline_argument,
00423 now, now, &setact);
00424 unsetact = !setact;
00425 break;
00426 case 'R':
00427 if (setrev || unsetrev)
00428 fatal("-R specified more than once");
00429
00430 revokekey = strtotime(isc_commandline_argument,
00431 now, now, &setrev);
00432 unsetrev = !setrev;
00433 break;
00434 case 'I':
00435 if (setinact || unsetinact)
00436 fatal("-I specified more than once");
00437
00438 inactive = strtotime(isc_commandline_argument,
00439 now, now, &setinact);
00440 unsetinact = !setinact;
00441 break;
00442 case 'D':
00443 if (setdel || unsetdel)
00444 fatal("-D specified more than once");
00445
00446 delete = strtotime(isc_commandline_argument,
00447 now, now, &setdel);
00448 unsetdel = !setdel;
00449 break;
00450 case 'S':
00451 predecessor = isc_commandline_argument;
00452 break;
00453 case 'i':
00454 prepub = strtottl(isc_commandline_argument);
00455 break;
00456 case 'F':
00457
00458
00459 case '?':
00460 if (isc_commandline_option != '?')
00461 fprintf(stderr, "%s: invalid argument -%c\n",
00462 program, isc_commandline_option);
00463
00464 case 'h':
00465
00466 usage();
00467
00468 case 'V':
00469
00470 version(program);
00471
00472 default:
00473 fprintf(stderr, "%s: unhandled option -%c\n",
00474 program, isc_commandline_option);
00475 exit(1);
00476 }
00477 }
00478
00479 if (!isatty(0))
00480 quiet = ISC_TRUE;
00481
00482 if (ectx == NULL)
00483 setup_entropy(mctx, NULL, &ectx);
00484 ret = dst_lib_init2(mctx, ectx, engine,
00485 ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
00486 if (ret != ISC_R_SUCCESS)
00487 fatal("could not initialize dst: %s",
00488 isc_result_totext(ret));
00489
00490 setup_logging(mctx, &log);
00491
00492 if (predecessor == NULL) {
00493 if (prepub == -1)
00494 prepub = 0;
00495
00496 if (argc < isc_commandline_index + 1)
00497 fatal("the key name was not specified");
00498 if (argc > isc_commandline_index + 1)
00499 fatal("extraneous arguments");
00500
00501 dns_fixedname_init(&fname);
00502 name = dns_fixedname_name(&fname);
00503 isc_buffer_init(&buf, argv[isc_commandline_index],
00504 strlen(argv[isc_commandline_index]));
00505 isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
00506 ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
00507 if (ret != ISC_R_SUCCESS)
00508 fatal("invalid key name %s: %s",
00509 argv[isc_commandline_index],
00510 isc_result_totext(ret));
00511
00512 if (algname == NULL) {
00513 use_default = ISC_TRUE;
00514 if (use_nsec3)
00515 algname = strdup(DEFAULT_NSEC3_ALGORITHM);
00516 else
00517 algname = strdup(DEFAULT_ALGORITHM);
00518 if (algname == NULL)
00519 fatal("strdup failed");
00520 freeit = algname;
00521 if (verbose > 0)
00522 fprintf(stderr, "no algorithm specified; "
00523 "defaulting to %s\n", algname);
00524 }
00525
00526 if (strcasecmp(algname, "RSA") == 0) {
00527 fprintf(stderr, "The use of RSA (RSAMD5) is not "
00528 "recommended.\nIf you still wish to "
00529 "use RSA (RSAMD5) please specify "
00530 "\"-a RSAMD5\"\n");
00531 INSIST(freeit == NULL);
00532 return (1);
00533 } else if (strcasecmp(algname, "HMAC-MD5") == 0)
00534 alg = DST_ALG_HMACMD5;
00535 else if (strcasecmp(algname, "HMAC-SHA1") == 0)
00536 alg = DST_ALG_HMACSHA1;
00537 else if (strcasecmp(algname, "HMAC-SHA224") == 0)
00538 alg = DST_ALG_HMACSHA224;
00539 else if (strcasecmp(algname, "HMAC-SHA256") == 0)
00540 alg = DST_ALG_HMACSHA256;
00541 else if (strcasecmp(algname, "HMAC-SHA384") == 0)
00542 alg = DST_ALG_HMACSHA384;
00543 else if (strcasecmp(algname, "HMAC-SHA512") == 0)
00544 alg = DST_ALG_HMACSHA512;
00545 else {
00546 r.base = algname;
00547 r.length = strlen(algname);
00548 ret = dns_secalg_fromtext(&alg, &r);
00549 if (ret != ISC_R_SUCCESS)
00550 fatal("unknown algorithm %s", algname);
00551 if (alg == DST_ALG_DH)
00552 options |= DST_TYPE_KEY;
00553 }
00554
00555 if (!dst_algorithm_supported(alg))
00556 fatal("unsupported algorithm: %d", alg);
00557
00558 if (use_nsec3 &&
00559 alg != DST_ALG_NSEC3DSA && alg != DST_ALG_NSEC3RSASHA1 &&
00560 alg != DST_ALG_RSASHA256 && alg!= DST_ALG_RSASHA512 &&
00561 alg != DST_ALG_ECCGOST &&
00562 alg != DST_ALG_ECDSA256 && alg != DST_ALG_ECDSA384) {
00563 fatal("%s is incompatible with NSEC3; "
00564 "do not use the -3 option", algname);
00565 }
00566
00567 if (type != NULL && (options & DST_TYPE_KEY) != 0) {
00568 if (strcasecmp(type, "NOAUTH") == 0)
00569 flags |= DNS_KEYTYPE_NOAUTH;
00570 else if (strcasecmp(type, "NOCONF") == 0)
00571 flags |= DNS_KEYTYPE_NOCONF;
00572 else if (strcasecmp(type, "NOAUTHCONF") == 0) {
00573 flags |= (DNS_KEYTYPE_NOAUTH |
00574 DNS_KEYTYPE_NOCONF);
00575 if (size < 0)
00576 size = 0;
00577 }
00578 else if (strcasecmp(type, "AUTHCONF") == 0)
00579 ;
00580 else
00581 fatal("invalid type %s", type);
00582 }
00583
00584 if (size < 0) {
00585 if (use_default) {
00586 if ((kskflag & DNS_KEYFLAG_KSK) != 0)
00587 size = 2048;
00588 else
00589 size = 1024;
00590 if (verbose > 0)
00591 fprintf(stderr, "key size not "
00592 "specified; defaulting"
00593 " to %d\n", size);
00594 } else if (alg != DST_ALG_ECCGOST &&
00595 alg != DST_ALG_ECDSA256 &&
00596 alg != DST_ALG_ECDSA384)
00597 fatal("key size not specified (-b option)");
00598 }
00599
00600 if (!oldstyle && prepub > 0) {
00601 if (setpub && setact && (activate - prepub) < publish)
00602 fatal("Activation and publication dates "
00603 "are closer together than the\n\t"
00604 "prepublication interval.");
00605
00606 if (!setpub && !setact) {
00607 setpub = setact = ISC_TRUE;
00608 publish = now;
00609 activate = now + prepub;
00610 } else if (setpub && !setact) {
00611 setact = ISC_TRUE;
00612 activate = publish + prepub;
00613 } else if (setact && !setpub) {
00614 setpub = ISC_TRUE;
00615 publish = activate - prepub;
00616 }
00617
00618 if ((activate - prepub) < now)
00619 fatal("Time until activation is shorter "
00620 "than the\n\tprepublication interval.");
00621 }
00622 } else {
00623 char keystr[DST_KEY_FORMATSIZE];
00624 isc_stdtime_t when;
00625 int major, minor;
00626
00627 if (prepub == -1)
00628 prepub = (30 * 86400);
00629
00630 if (algname != NULL)
00631 fatal("-S and -a cannot be used together");
00632 if (size >= 0)
00633 fatal("-S and -b cannot be used together");
00634 if (nametype != NULL)
00635 fatal("-S and -n cannot be used together");
00636 if (type != NULL)
00637 fatal("-S and -t cannot be used together");
00638 if (setpub || unsetpub)
00639 fatal("-S and -P cannot be used together");
00640 if (setact || unsetact)
00641 fatal("-S and -A cannot be used together");
00642 if (use_nsec3)
00643 fatal("-S and -3 cannot be used together");
00644 if (oldstyle)
00645 fatal("-S and -C cannot be used together");
00646 if (genonly)
00647 fatal("-S and -G cannot be used together");
00648
00649 ret = dst_key_fromnamedfile(predecessor, directory,
00650 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
00651 mctx, &prevkey);
00652 if (ret != ISC_R_SUCCESS)
00653 fatal("Invalid keyfile %s: %s",
00654 predecessor, isc_result_totext(ret));
00655 if (!dst_key_isprivate(prevkey))
00656 fatal("%s is not a private key", predecessor);
00657
00658 name = dst_key_name(prevkey);
00659 alg = dst_key_alg(prevkey);
00660 size = dst_key_size(prevkey);
00661 flags = dst_key_flags(prevkey);
00662
00663 dst_key_format(prevkey, keystr, sizeof(keystr));
00664 dst_key_getprivateformat(prevkey, &major, &minor);
00665 if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
00666 fatal("Key %s has incompatible format version %d.%d\n\t"
00667 "It is not possible to generate a successor key.",
00668 keystr, major, minor);
00669
00670 ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
00671 if (ret != ISC_R_SUCCESS)
00672 fatal("Key %s has no activation date.\n\t"
00673 "You must use dnssec-settime -A to set one "
00674 "before generating a successor.", keystr);
00675
00676 ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate);
00677 if (ret != ISC_R_SUCCESS)
00678 fatal("Key %s has no inactivation date.\n\t"
00679 "You must use dnssec-settime -I to set one "
00680 "before generating a successor.", keystr);
00681
00682 publish = activate - prepub;
00683 if (publish < now)
00684 fatal("Key %s becomes inactive\n\t"
00685 "sooner than the prepublication period "
00686 "for the new key ends.\n\t"
00687 "Either change the inactivation date with "
00688 "dnssec-settime -I,\n\t"
00689 "or use the -i option to set a shorter "
00690 "prepublication interval.", keystr);
00691
00692 ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
00693 if (ret != ISC_R_SUCCESS)
00694 fprintf(stderr, "%s: WARNING: Key %s has no removal "
00695 "date;\n\t it will remain in the zone "
00696 "indefinitely after rollover.\n\t "
00697 "You can use dnssec-settime -D to "
00698 "change this.\n", program, keystr);
00699
00700 setpub = setact = ISC_TRUE;
00701 }
00702
00703 switch (alg) {
00704 case DNS_KEYALG_RSAMD5:
00705 case DNS_KEYALG_RSASHA1:
00706 case DNS_KEYALG_NSEC3RSASHA1:
00707 case DNS_KEYALG_RSASHA256:
00708 if (size != 0 && (size < 512 || size > MAX_RSA))
00709 fatal("RSA key size %d out of range", size);
00710 break;
00711 case DNS_KEYALG_RSASHA512:
00712 if (size != 0 && (size < 1024 || size > MAX_RSA))
00713 fatal("RSA key size %d out of range", size);
00714 break;
00715 case DNS_KEYALG_DH:
00716 if (size != 0 && (size < 128 || size > 4096))
00717 fatal("DH key size %d out of range", size);
00718 break;
00719 case DNS_KEYALG_DSA:
00720 case DNS_KEYALG_NSEC3DSA:
00721 if (size != 0 && !dsa_size_ok(size))
00722 fatal("invalid DSS key size: %d", size);
00723 break;
00724 case DST_ALG_ECCGOST:
00725 size = 256;
00726 break;
00727 case DST_ALG_ECDSA256:
00728 size = 256;
00729 break;
00730 case DST_ALG_ECDSA384:
00731 size = 384;
00732 break;
00733 case DST_ALG_HMACMD5:
00734 options |= DST_TYPE_KEY;
00735 if (size < 1 || size > 512)
00736 fatal("HMAC-MD5 key size %d out of range", size);
00737 if (dbits != 0 && (dbits < 80 || dbits > 128))
00738 fatal("HMAC-MD5 digest bits %d out of range", dbits);
00739 if ((dbits % 8) != 0)
00740 fatal("HMAC-MD5 digest bits %d not divisible by 8",
00741 dbits);
00742 break;
00743 case DST_ALG_HMACSHA1:
00744 options |= DST_TYPE_KEY;
00745 if (size < 1 || size > 160)
00746 fatal("HMAC-SHA1 key size %d out of range", size);
00747 if (dbits != 0 && (dbits < 80 || dbits > 160))
00748 fatal("HMAC-SHA1 digest bits %d out of range", dbits);
00749 if ((dbits % 8) != 0)
00750 fatal("HMAC-SHA1 digest bits %d not divisible by 8",
00751 dbits);
00752 break;
00753 case DST_ALG_HMACSHA224:
00754 options |= DST_TYPE_KEY;
00755 if (size < 1 || size > 224)
00756 fatal("HMAC-SHA224 key size %d out of range", size);
00757 if (dbits != 0 && (dbits < 112 || dbits > 224))
00758 fatal("HMAC-SHA224 digest bits %d out of range", dbits);
00759 if ((dbits % 8) != 0)
00760 fatal("HMAC-SHA224 digest bits %d not divisible by 8",
00761 dbits);
00762 break;
00763 case DST_ALG_HMACSHA256:
00764 options |= DST_TYPE_KEY;
00765 if (size < 1 || size > 256)
00766 fatal("HMAC-SHA256 key size %d out of range", size);
00767 if (dbits != 0 && (dbits < 128 || dbits > 256))
00768 fatal("HMAC-SHA256 digest bits %d out of range", dbits);
00769 if ((dbits % 8) != 0)
00770 fatal("HMAC-SHA256 digest bits %d not divisible by 8",
00771 dbits);
00772 break;
00773 case DST_ALG_HMACSHA384:
00774 options |= DST_TYPE_KEY;
00775 if (size < 1 || size > 384)
00776 fatal("HMAC-384 key size %d out of range", size);
00777 if (dbits != 0 && (dbits < 192 || dbits > 384))
00778 fatal("HMAC-SHA384 digest bits %d out of range", dbits);
00779 if ((dbits % 8) != 0)
00780 fatal("HMAC-SHA384 digest bits %d not divisible by 8",
00781 dbits);
00782 break;
00783 case DST_ALG_HMACSHA512:
00784 options |= DST_TYPE_KEY;
00785 if (size < 1 || size > 512)
00786 fatal("HMAC-SHA512 key size %d out of range", size);
00787 if (dbits != 0 && (dbits < 256 || dbits > 512))
00788 fatal("HMAC-SHA512 digest bits %d out of range", dbits);
00789 if ((dbits % 8) != 0)
00790 fatal("HMAC-SHA512 digest bits %d not divisible by 8",
00791 dbits);
00792 break;
00793 }
00794
00795 if (alg != DNS_KEYALG_DH && generator != 0)
00796 fatal("specified DH generator for a non-DH key");
00797
00798 if (nametype == NULL) {
00799 if ((options & DST_TYPE_KEY) != 0)
00800 fatal("no nametype specified");
00801 flags |= DNS_KEYOWNER_ZONE;
00802 } else if (strcasecmp(nametype, "zone") == 0)
00803 flags |= DNS_KEYOWNER_ZONE;
00804 else if ((options & DST_TYPE_KEY) != 0) {
00805 if (strcasecmp(nametype, "host") == 0 ||
00806 strcasecmp(nametype, "entity") == 0)
00807 flags |= DNS_KEYOWNER_ENTITY;
00808 else if (strcasecmp(nametype, "user") == 0)
00809 flags |= DNS_KEYOWNER_USER;
00810 else
00811 fatal("invalid KEY nametype %s", nametype);
00812 } else if (strcasecmp(nametype, "other") != 0)
00813 fatal("invalid DNSKEY nametype %s", nametype);
00814
00815 rdclass = strtoclass(classname);
00816
00817 if (directory == NULL)
00818 directory = ".";
00819
00820 if ((options & DST_TYPE_KEY) != 0)
00821 flags |= signatory;
00822 else if ((flags & DNS_KEYOWNER_ZONE) != 0) {
00823 flags |= kskflag;
00824 flags |= revflag;
00825 }
00826
00827 if (protocol == -1)
00828 protocol = DNS_KEYPROTO_DNSSEC;
00829 else if ((options & DST_TYPE_KEY) == 0 &&
00830 protocol != DNS_KEYPROTO_DNSSEC)
00831 fatal("invalid DNSKEY protocol: %d", protocol);
00832
00833 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
00834 if (size > 0)
00835 fatal("specified null key with non-zero size");
00836 if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
00837 fatal("specified null key with signing authority");
00838 }
00839
00840 if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
00841 (alg == DNS_KEYALG_DH || alg == DST_ALG_HMACMD5 ||
00842 alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 ||
00843 alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 ||
00844 alg == DST_ALG_HMACSHA512))
00845 fatal("a key with algorithm '%s' cannot be a zone key",
00846 algname);
00847
00848 switch(alg) {
00849 case DNS_KEYALG_RSAMD5:
00850 case DNS_KEYALG_RSASHA1:
00851 case DNS_KEYALG_NSEC3RSASHA1:
00852 case DNS_KEYALG_RSASHA256:
00853 case DNS_KEYALG_RSASHA512:
00854 show_progress = ISC_TRUE;
00855 break;
00856
00857 case DNS_KEYALG_DH:
00858 param = generator;
00859 break;
00860
00861 case DNS_KEYALG_DSA:
00862 case DNS_KEYALG_NSEC3DSA:
00863 case DST_ALG_ECCGOST:
00864 case DST_ALG_ECDSA256:
00865 case DST_ALG_ECDSA384:
00866 show_progress = ISC_TRUE;
00867
00868
00869 case DST_ALG_HMACMD5:
00870 case DST_ALG_HMACSHA1:
00871 case DST_ALG_HMACSHA224:
00872 case DST_ALG_HMACSHA256:
00873 case DST_ALG_HMACSHA384:
00874 case DST_ALG_HMACSHA512:
00875 param = 0;
00876 break;
00877 }
00878
00879 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
00880 null_key = ISC_TRUE;
00881
00882 isc_buffer_init(&buf, filename, sizeof(filename) - 1);
00883
00884 do {
00885 conflict = ISC_FALSE;
00886
00887 if (!quiet && show_progress) {
00888 fprintf(stderr, "Generating key pair.");
00889 ret = dst_key_generate2(name, alg, size, param, flags,
00890 protocol, rdclass, mctx, &key,
00891 &progress);
00892 putc('\n', stderr);
00893 fflush(stderr);
00894 } else {
00895 ret = dst_key_generate2(name, alg, size, param, flags,
00896 protocol, rdclass, mctx, &key,
00897 NULL);
00898 }
00899
00900 isc_entropy_stopcallbacksources(ectx);
00901
00902 if (ret != ISC_R_SUCCESS) {
00903 char namestr[DNS_NAME_FORMATSIZE];
00904 char algstr[DNS_SECALG_FORMATSIZE];
00905 dns_name_format(name, namestr, sizeof(namestr));
00906 dns_secalg_format(alg, algstr, sizeof(algstr));
00907 fatal("failed to generate key %s/%s: %s\n",
00908 namestr, algstr, isc_result_totext(ret));
00909
00910 exit(-1);
00911 }
00912
00913 dst_key_setbits(key, dbits);
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 if (!oldstyle) {
00932 dst_key_settime(key, DST_TIME_CREATED, now);
00933
00934 if (genonly && (setpub || setact))
00935 fatal("cannot use -G together with "
00936 "-P or -A options");
00937
00938 if (setpub)
00939 dst_key_settime(key, DST_TIME_PUBLISH, publish);
00940 else if (setact && !unsetpub)
00941 dst_key_settime(key, DST_TIME_PUBLISH,
00942 activate - prepub);
00943 else if (!genonly && !unsetpub)
00944 dst_key_settime(key, DST_TIME_PUBLISH, now);
00945
00946 if (setact)
00947 dst_key_settime(key, DST_TIME_ACTIVATE,
00948 activate);
00949 else if (!genonly && !unsetact)
00950 dst_key_settime(key, DST_TIME_ACTIVATE, now);
00951
00952 if (setrev) {
00953 if (kskflag == 0)
00954 fprintf(stderr, "%s: warning: Key is "
00955 "not flagged as a KSK, but -R "
00956 "was used. Revoking a ZSK is "
00957 "legal, but undefined.\n",
00958 program);
00959 dst_key_settime(key, DST_TIME_REVOKE, revokekey);
00960 }
00961
00962 if (setinact)
00963 dst_key_settime(key, DST_TIME_INACTIVE,
00964 inactive);
00965
00966 if (setdel) {
00967 if (setinact && delete < inactive)
00968 fprintf(stderr, "%s: warning: Key is "
00969 "scheduled to be deleted "
00970 "before it is scheduled to be "
00971 "made inactive.\n",
00972 program);
00973 dst_key_settime(key, DST_TIME_DELETE, delete);
00974 }
00975 } else {
00976 if (setpub || setact || setrev || setinact ||
00977 setdel || unsetpub || unsetact ||
00978 unsetrev || unsetinact || unsetdel || genonly)
00979 fatal("cannot use -C together with "
00980 "-P, -A, -R, -I, -D, or -G options");
00981
00982
00983
00984
00985 dst_key_setprivateformat(key, 1, 2);
00986 }
00987
00988
00989 if (setttl)
00990 dst_key_setttl(key, ttl);
00991
00992
00993
00994
00995
00996
00997 if (key_collision(key, name, directory, mctx, NULL)) {
00998 conflict = ISC_TRUE;
00999 if (null_key) {
01000 dst_key_free(&key);
01001 break;
01002 }
01003
01004 if (verbose > 0) {
01005 isc_buffer_clear(&buf);
01006 ret = dst_key_buildfilename(key, 0,
01007 directory, &buf);
01008 if (ret == ISC_R_SUCCESS)
01009 fprintf(stderr,
01010 "%s: %s already exists, or "
01011 "might collide with another "
01012 "key upon revokation. "
01013 "Generating a new key\n",
01014 program, filename);
01015 }
01016
01017 dst_key_free(&key);
01018 }
01019 } while (conflict == ISC_TRUE);
01020
01021 if (conflict)
01022 fatal("cannot generate a null key due to possible key ID "
01023 "collision");
01024
01025 ret = dst_key_tofile(key, options, directory);
01026 if (ret != ISC_R_SUCCESS) {
01027 char keystr[DST_KEY_FORMATSIZE];
01028 dst_key_format(key, keystr, sizeof(keystr));
01029 fatal("failed to write key %s: %s\n", keystr,
01030 isc_result_totext(ret));
01031 }
01032
01033 isc_buffer_clear(&buf);
01034 ret = dst_key_buildfilename(key, 0, NULL, &buf);
01035 if (ret != ISC_R_SUCCESS)
01036 fatal("dst_key_buildfilename returned: %s\n",
01037 isc_result_totext(ret));
01038 printf("%s\n", filename);
01039 dst_key_free(&key);
01040 if (prevkey != NULL)
01041 dst_key_free(&prevkey);
01042
01043 cleanup_logging(&log);
01044 cleanup_entropy(&ectx);
01045 dst_lib_destroy();
01046 dns_name_destroy();
01047 if (verbose > 10)
01048 isc_mem_stats(mctx, stdout);
01049 isc_mem_destroy(&mctx);
01050
01051 if (freeit != NULL)
01052 free(freeit);
01053
01054 return (0);
01055 }