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