1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <ctype.h>
17 #include <inttypes.h>
18 #include <stdbool.h>
19 #include <stdlib.h>
20
21 #include <isc/buffer.h>
22 #include <isc/commandline.h>
23 #include <isc/mem.h>
24 #include <isc/print.h>
25 #include <isc/region.h>
26 #include <isc/string.h>
27 #include <isc/util.h>
28
29 #include <pk11/site.h>
30
31 #include <dns/dnssec.h>
32 #include <dns/fixedname.h>
33 #include <dns/keyvalues.h>
34 #include <dns/log.h>
35 #include <dns/name.h>
36 #include <dns/rdataclass.h>
37 #include <dns/result.h>
38 #include <dns/secalg.h>
39
40 #include <dst/dst.h>
41
42 #if USE_PKCS11
43 #include <pk11/result.h>
44 #endif /* if USE_PKCS11 */
45
46 #include "dnssectool.h"
47
48 #define MAX_RSA 4096 /* should be long enough... */
49
50 const char *program = "dnssec-keyfromlabel";
51
52 ISC_PLATFORM_NORETURN_PRE static void
53 usage(void) ISC_PLATFORM_NORETURN_POST;
54
55 static void
usage(void)56 usage(void) {
57 fprintf(stderr, "Usage:\n");
58 fprintf(stderr, " %s -l label [options] name\n\n", program);
59 fprintf(stderr, "Version: %s\n", VERSION);
60 fprintf(stderr, "Required options:\n");
61 fprintf(stderr, " -l label: label of the key pair\n");
62 fprintf(stderr, " name: owner of the key\n");
63 fprintf(stderr, "Other options:\n");
64 fprintf(stderr, " -a algorithm: \n"
65 " DH | RSASHA1 |\n"
66 " NSEC3RSASHA1 |\n"
67 " RSASHA256 | RSASHA512 |\n"
68 " ECDSAP256SHA256 | ECDSAP384SHA384 |\n"
69 " ED25519 | ED448\n");
70 fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
71 fprintf(stderr, " -c class (default: IN)\n");
72 fprintf(stderr, " -E <engine>:\n");
73 #if USE_PKCS11
74 fprintf(stderr,
75 " path to PKCS#11 provider library "
76 "(default is %s)\n",
77 PK11_LIB_LOCATION);
78 #else /* if USE_PKCS11 */
79 fprintf(stderr, " name of an OpenSSL engine to use\n");
80 #endif /* if USE_PKCS11 */
81 fprintf(stderr, " -f keyflag: KSK | REVOKE\n");
82 fprintf(stderr, " -K directory: directory in which to place "
83 "key files\n");
84 fprintf(stderr, " -k: generate a TYPE=KEY key\n");
85 fprintf(stderr, " -L ttl: default key TTL\n");
86 fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | "
87 "OTHER\n");
88 fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
89 fprintf(stderr, " -p protocol: default: 3 [dnssec]\n");
90 fprintf(stderr, " -t type: "
91 "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
92 "(default: AUTHCONF)\n");
93 fprintf(stderr, " -y: permit keys that might collide\n");
94 fprintf(stderr, " -v verbose level\n");
95 fprintf(stderr, " -V: print version information\n");
96 fprintf(stderr, "Date options:\n");
97 fprintf(stderr, " -P date/[+-]offset: set key publication date\n");
98 fprintf(stderr, " -P sync date/[+-]offset: set CDS and CDNSKEY "
99 "publication date\n");
100 fprintf(stderr, " -A date/[+-]offset: set key activation date\n");
101 fprintf(stderr, " -R date/[+-]offset: set key revocation date\n");
102 fprintf(stderr, " -I date/[+-]offset: set key inactivation date\n");
103 fprintf(stderr, " -D date/[+-]offset: set key deletion date\n");
104 fprintf(stderr, " -D sync date/[+-]offset: set CDS and CDNSKEY "
105 "deletion date\n");
106 fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
107 fprintf(stderr, " -C: generate a backward-compatible key, omitting"
108 " all dates\n");
109 fprintf(stderr, " -S <key>: generate a successor to an existing "
110 "key\n");
111 fprintf(stderr, " -i <interval>: prepublication interval for "
112 "successor key "
113 "(default: 30 days)\n");
114 fprintf(stderr, "Output:\n");
115 fprintf(stderr, " K<name>+<alg>+<id>.key, "
116 "K<name>+<alg>+<id>.private\n");
117
118 exit(-1);
119 }
120
121 int
main(int argc,char ** argv)122 main(int argc, char **argv) {
123 char *algname = NULL, *freeit = NULL;
124 char *nametype = NULL, *type = NULL;
125 const char *directory = NULL;
126 const char *predecessor = NULL;
127 dst_key_t *prevkey = NULL;
128 const char *engine = NULL;
129 char *classname = NULL;
130 char *endp;
131 dst_key_t *key = NULL;
132 dns_fixedname_t fname;
133 dns_name_t *name;
134 uint16_t flags = 0, kskflag = 0, revflag = 0;
135 dns_secalg_t alg;
136 bool oldstyle = false;
137 isc_mem_t *mctx = NULL;
138 int ch;
139 int protocol = -1, signatory = 0;
140 isc_result_t ret;
141 isc_textregion_t r;
142 char filename[255];
143 isc_buffer_t buf;
144 isc_log_t *log = NULL;
145 dns_rdataclass_t rdclass;
146 int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
147 char *label = NULL;
148 dns_ttl_t ttl = 0;
149 isc_stdtime_t publish = 0, activate = 0, revoke = 0;
150 isc_stdtime_t inactive = 0, deltime = 0;
151 isc_stdtime_t now;
152 int prepub = -1;
153 bool setpub = false, setact = false;
154 bool setrev = false, setinact = false;
155 bool setdel = false, setttl = false;
156 bool unsetpub = false, unsetact = false;
157 bool unsetrev = false, unsetinact = false;
158 bool unsetdel = false;
159 bool genonly = false;
160 bool use_nsec3 = false;
161 bool avoid_collisions = true;
162 bool exact;
163 unsigned char c;
164 isc_stdtime_t syncadd = 0, syncdel = 0;
165 bool unsetsyncadd = false, setsyncadd = false;
166 bool unsetsyncdel = false, setsyncdel = false;
167
168 if (argc == 1) {
169 usage();
170 }
171
172 isc_mem_create(&mctx);
173
174 #if USE_PKCS11
175 pk11_result_register();
176 #endif /* if USE_PKCS11 */
177 dns_result_register();
178
179 isc_commandline_errprint = false;
180
181 isc_stdtime_get(&now);
182
183 #define CMDLINE_FLAGS "3A:a:Cc:D:E:Ff:GhI:i:kK:L:l:n:P:p:R:S:t:v:Vy"
184 while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
185 switch (ch) {
186 case '3':
187 use_nsec3 = true;
188 break;
189 case 'a':
190 algname = isc_commandline_argument;
191 break;
192 case 'C':
193 oldstyle = true;
194 break;
195 case 'c':
196 classname = isc_commandline_argument;
197 break;
198 case 'E':
199 engine = isc_commandline_argument;
200 break;
201 case 'f':
202 c = (unsigned char)(isc_commandline_argument[0]);
203 if (toupper(c) == 'K') {
204 kskflag = DNS_KEYFLAG_KSK;
205 } else if (toupper(c) == 'R') {
206 revflag = DNS_KEYFLAG_REVOKE;
207 } else {
208 fatal("unknown flag '%s'",
209 isc_commandline_argument);
210 }
211 break;
212 case 'K':
213 directory = isc_commandline_argument;
214 ret = try_dir(directory);
215 if (ret != ISC_R_SUCCESS) {
216 fatal("cannot open directory %s: %s", directory,
217 isc_result_totext(ret));
218 }
219 break;
220 case 'k':
221 options |= DST_TYPE_KEY;
222 break;
223 case 'L':
224 ttl = strtottl(isc_commandline_argument);
225 setttl = true;
226 break;
227 case 'l':
228 label = isc_mem_strdup(mctx, isc_commandline_argument);
229 break;
230 case 'n':
231 nametype = isc_commandline_argument;
232 break;
233 case 'p':
234 protocol = strtol(isc_commandline_argument, &endp, 10);
235 if (*endp != '\0' || protocol < 0 || protocol > 255) {
236 fatal("-p must be followed by a number "
237 "[0..255]");
238 }
239 break;
240 case 't':
241 type = isc_commandline_argument;
242 break;
243 case 'v':
244 verbose = strtol(isc_commandline_argument, &endp, 0);
245 if (*endp != '\0') {
246 fatal("-v must be followed by a number");
247 }
248 break;
249 case 'y':
250 avoid_collisions = false;
251 break;
252 case 'G':
253 genonly = true;
254 break;
255 case 'P':
256 /* -Psync ? */
257 if (isoptarg("sync", argv, usage)) {
258 if (unsetsyncadd || setsyncadd) {
259 fatal("-P sync specified more than "
260 "once");
261 }
262
263 syncadd = strtotime(isc_commandline_argument,
264 now, now, &setsyncadd);
265 unsetsyncadd = !setsyncadd;
266 break;
267 }
268 /* -Pdnskey ? */
269 (void)isoptarg("dnskey", argv, usage);
270 if (setpub || unsetpub) {
271 fatal("-P specified more than once");
272 }
273
274 publish = strtotime(isc_commandline_argument, now, now,
275 &setpub);
276 unsetpub = !setpub;
277 break;
278 case 'A':
279 if (setact || unsetact) {
280 fatal("-A specified more than once");
281 }
282
283 activate = strtotime(isc_commandline_argument, now, now,
284 &setact);
285 unsetact = !setact;
286 break;
287 case 'R':
288 if (setrev || unsetrev) {
289 fatal("-R specified more than once");
290 }
291
292 revoke = strtotime(isc_commandline_argument, now, now,
293 &setrev);
294 unsetrev = !setrev;
295 break;
296 case 'I':
297 if (setinact || unsetinact) {
298 fatal("-I specified more than once");
299 }
300
301 inactive = strtotime(isc_commandline_argument, now, now,
302 &setinact);
303 unsetinact = !setinact;
304 break;
305 case 'D':
306 /* -Dsync ? */
307 if (isoptarg("sync", argv, usage)) {
308 if (unsetsyncdel || setsyncdel) {
309 fatal("-D sync specified more than "
310 "once");
311 }
312
313 syncdel = strtotime(isc_commandline_argument,
314 now, now, &setsyncdel);
315 unsetsyncdel = !setsyncdel;
316 break;
317 }
318 /* -Ddnskey ? */
319 (void)isoptarg("dnskey", argv, usage);
320 if (setdel || unsetdel) {
321 fatal("-D specified more than once");
322 }
323
324 deltime = strtotime(isc_commandline_argument, now, now,
325 &setdel);
326 unsetdel = !setdel;
327 break;
328 case 'S':
329 predecessor = isc_commandline_argument;
330 break;
331 case 'i':
332 prepub = strtottl(isc_commandline_argument);
333 break;
334 case 'F':
335 /* Reserved for FIPS mode */
336 /* FALLTHROUGH */
337 case '?':
338 if (isc_commandline_option != '?') {
339 fprintf(stderr, "%s: invalid argument -%c\n",
340 program, isc_commandline_option);
341 }
342 /* FALLTHROUGH */
343 case 'h':
344 /* Does not return. */
345 usage();
346
347 case 'V':
348 /* Does not return. */
349 version(program);
350
351 default:
352 fprintf(stderr, "%s: unhandled option -%c\n", program,
353 isc_commandline_option);
354 exit(1);
355 }
356 }
357
358 ret = dst_lib_init(mctx, engine);
359 if (ret != ISC_R_SUCCESS) {
360 fatal("could not initialize dst: %s", isc_result_totext(ret));
361 }
362
363 setup_logging(mctx, &log);
364
365 if (predecessor == NULL) {
366 if (label == NULL) {
367 fatal("the key label was not specified");
368 }
369 if (argc < isc_commandline_index + 1) {
370 fatal("the key name was not specified");
371 }
372 if (argc > isc_commandline_index + 1) {
373 fatal("extraneous arguments");
374 }
375
376 name = dns_fixedname_initname(&fname);
377 isc_buffer_init(&buf, argv[isc_commandline_index],
378 strlen(argv[isc_commandline_index]));
379 isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
380 ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
381 if (ret != ISC_R_SUCCESS) {
382 fatal("invalid key name %s: %s",
383 argv[isc_commandline_index],
384 isc_result_totext(ret));
385 }
386
387 if (strchr(label, ':') == NULL) {
388 char *l;
389 int len;
390
391 len = strlen(label) + 8;
392 l = isc_mem_allocate(mctx, len);
393 snprintf(l, len, "pkcs11:%s", label);
394 isc_mem_free(mctx, label);
395 label = l;
396 }
397
398 if (algname == NULL) {
399 fatal("no algorithm specified");
400 }
401
402 r.base = algname;
403 r.length = strlen(algname);
404 ret = dns_secalg_fromtext(&alg, &r);
405 if (ret != ISC_R_SUCCESS) {
406 fatal("unknown algorithm %s", algname);
407 }
408 if (alg == DST_ALG_DH) {
409 options |= DST_TYPE_KEY;
410 }
411
412 if (use_nsec3) {
413 switch (alg) {
414 case DST_ALG_RSASHA1:
415 alg = DST_ALG_NSEC3RSASHA1;
416 break;
417 case DST_ALG_NSEC3RSASHA1:
418 case DST_ALG_RSASHA256:
419 case DST_ALG_RSASHA512:
420 case DST_ALG_ECDSA256:
421 case DST_ALG_ECDSA384:
422 case DST_ALG_ED25519:
423 case DST_ALG_ED448:
424 break;
425 default:
426 fatal("%s is incompatible with NSEC3; "
427 "do not use the -3 option",
428 algname);
429 }
430 }
431
432 if (type != NULL && (options & DST_TYPE_KEY) != 0) {
433 if (strcasecmp(type, "NOAUTH") == 0) {
434 flags |= DNS_KEYTYPE_NOAUTH;
435 } else if (strcasecmp(type, "NOCONF") == 0) {
436 flags |= DNS_KEYTYPE_NOCONF;
437 } else if (strcasecmp(type, "NOAUTHCONF") == 0) {
438 flags |= (DNS_KEYTYPE_NOAUTH |
439 DNS_KEYTYPE_NOCONF);
440 } else if (strcasecmp(type, "AUTHCONF") == 0) {
441 /* nothing */
442 } else {
443 fatal("invalid type %s", type);
444 }
445 }
446
447 if (!oldstyle && prepub > 0) {
448 if (setpub && setact && (activate - prepub) < publish) {
449 fatal("Activation and publication dates "
450 "are closer together than the\n\t"
451 "prepublication interval.");
452 }
453
454 if (!setpub && !setact) {
455 setpub = setact = true;
456 publish = now;
457 activate = now + prepub;
458 } else if (setpub && !setact) {
459 setact = true;
460 activate = publish + prepub;
461 } else if (setact && !setpub) {
462 setpub = true;
463 publish = activate - prepub;
464 }
465
466 if ((activate - prepub) < now) {
467 fatal("Time until activation is shorter "
468 "than the\n\tprepublication interval.");
469 }
470 }
471 } else {
472 char keystr[DST_KEY_FORMATSIZE];
473 isc_stdtime_t when;
474 int major, minor;
475
476 if (prepub == -1) {
477 prepub = (30 * 86400);
478 }
479
480 if (algname != NULL) {
481 fatal("-S and -a cannot be used together");
482 }
483 if (nametype != NULL) {
484 fatal("-S and -n cannot be used together");
485 }
486 if (type != NULL) {
487 fatal("-S and -t cannot be used together");
488 }
489 if (setpub || unsetpub) {
490 fatal("-S and -P cannot be used together");
491 }
492 if (setact || unsetact) {
493 fatal("-S and -A cannot be used together");
494 }
495 if (use_nsec3) {
496 fatal("-S and -3 cannot be used together");
497 }
498 if (oldstyle) {
499 fatal("-S and -C cannot be used together");
500 }
501 if (genonly) {
502 fatal("-S and -G cannot be used together");
503 }
504
505 ret = dst_key_fromnamedfile(predecessor, directory,
506 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
507 mctx, &prevkey);
508 if (ret != ISC_R_SUCCESS) {
509 fatal("Invalid keyfile %s: %s", predecessor,
510 isc_result_totext(ret));
511 }
512 if (!dst_key_isprivate(prevkey)) {
513 fatal("%s is not a private key", predecessor);
514 }
515
516 name = dst_key_name(prevkey);
517 alg = dst_key_alg(prevkey);
518 flags = dst_key_flags(prevkey);
519
520 dst_key_format(prevkey, keystr, sizeof(keystr));
521 dst_key_getprivateformat(prevkey, &major, &minor);
522 if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
523 fatal("Key %s has incompatible format version %d.%d\n\t"
524 "It is not possible to generate a successor key.",
525 keystr, major, minor);
526 }
527
528 ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
529 if (ret != ISC_R_SUCCESS) {
530 fatal("Key %s has no activation date.\n\t"
531 "You must use dnssec-settime -A to set one "
532 "before generating a successor.",
533 keystr);
534 }
535
536 ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE, &activate);
537 if (ret != ISC_R_SUCCESS) {
538 fatal("Key %s has no inactivation date.\n\t"
539 "You must use dnssec-settime -I to set one "
540 "before generating a successor.",
541 keystr);
542 }
543
544 publish = activate - prepub;
545 if (publish < now) {
546 fatal("Key %s becomes inactive\n\t"
547 "sooner than the prepublication period "
548 "for the new key ends.\n\t"
549 "Either change the inactivation date with "
550 "dnssec-settime -I,\n\t"
551 "or use the -i option to set a shorter "
552 "prepublication interval.",
553 keystr);
554 }
555
556 ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
557 if (ret != ISC_R_SUCCESS) {
558 fprintf(stderr,
559 "%s: WARNING: Key %s has no removal "
560 "date;\n\t it will remain in the zone "
561 "indefinitely after rollover.\n\t "
562 "You can use dnssec-settime -D to "
563 "change this.\n",
564 program, keystr);
565 }
566
567 setpub = setact = true;
568 }
569
570 if (nametype == NULL) {
571 if ((options & DST_TYPE_KEY) != 0) { /* KEY */
572 fatal("no nametype specified");
573 }
574 flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
575 } else if (strcasecmp(nametype, "zone") == 0) {
576 flags |= DNS_KEYOWNER_ZONE;
577 } else if ((options & DST_TYPE_KEY) != 0) { /* KEY */
578 if (strcasecmp(nametype, "host") == 0 ||
579 strcasecmp(nametype, "entity") == 0) {
580 flags |= DNS_KEYOWNER_ENTITY;
581 } else if (strcasecmp(nametype, "user") == 0) {
582 flags |= DNS_KEYOWNER_USER;
583 } else {
584 fatal("invalid KEY nametype %s", nametype);
585 }
586 } else if (strcasecmp(nametype, "other") != 0) { /* DNSKEY */
587 fatal("invalid DNSKEY nametype %s", nametype);
588 }
589
590 rdclass = strtoclass(classname);
591
592 if (directory == NULL) {
593 directory = ".";
594 }
595
596 if ((options & DST_TYPE_KEY) != 0) { /* KEY */
597 flags |= signatory;
598 } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */
599 flags |= kskflag;
600 flags |= revflag;
601 }
602
603 if (protocol == -1) {
604 protocol = DNS_KEYPROTO_DNSSEC;
605 } else if ((options & DST_TYPE_KEY) == 0 &&
606 protocol != DNS_KEYPROTO_DNSSEC) {
607 fatal("invalid DNSKEY protocol: %d", protocol);
608 }
609
610 if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
611 if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) {
612 fatal("specified null key with signing authority");
613 }
614 }
615
616 if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
617 alg == DNS_KEYALG_DH)
618 {
619 fatal("a key with algorithm '%s' cannot be a zone key",
620 algname);
621 }
622
623 isc_buffer_init(&buf, filename, sizeof(filename) - 1);
624
625 /* associate the key */
626 ret = dst_key_fromlabel(name, alg, flags, protocol, rdclass,
627 #if USE_PKCS11
628 "pkcs11",
629 #else /* if USE_PKCS11 */
630 engine,
631 #endif /* if USE_PKCS11 */
632 label, NULL, mctx, &key);
633
634 if (ret != ISC_R_SUCCESS) {
635 char namestr[DNS_NAME_FORMATSIZE];
636 char algstr[DNS_SECALG_FORMATSIZE];
637 dns_name_format(name, namestr, sizeof(namestr));
638 dns_secalg_format(alg, algstr, sizeof(algstr));
639 fatal("failed to get key %s/%s: %s", namestr, algstr,
640 isc_result_totext(ret));
641 /* NOTREACHED */
642 exit(-1);
643 }
644
645 /*
646 * Set key timing metadata (unless using -C)
647 *
648 * Publish and activation dates are set to "now" by default, but
649 * can be overridden. Creation date is always set to "now".
650 */
651 if (!oldstyle) {
652 dst_key_settime(key, DST_TIME_CREATED, now);
653
654 if (genonly && (setpub || setact)) {
655 fatal("cannot use -G together with -P or -A options");
656 }
657
658 if (setpub) {
659 dst_key_settime(key, DST_TIME_PUBLISH, publish);
660 } else if (setact) {
661 dst_key_settime(key, DST_TIME_PUBLISH, activate);
662 } else if (!genonly && !unsetpub) {
663 dst_key_settime(key, DST_TIME_PUBLISH, now);
664 }
665
666 if (setact) {
667 dst_key_settime(key, DST_TIME_ACTIVATE, activate);
668 } else if (!genonly && !unsetact) {
669 dst_key_settime(key, DST_TIME_ACTIVATE, now);
670 }
671
672 if (setrev) {
673 if (kskflag == 0) {
674 fprintf(stderr,
675 "%s: warning: Key is "
676 "not flagged as a KSK, but -R "
677 "was used. Revoking a ZSK is "
678 "legal, but undefined.\n",
679 program);
680 }
681 dst_key_settime(key, DST_TIME_REVOKE, revoke);
682 }
683
684 if (setinact) {
685 dst_key_settime(key, DST_TIME_INACTIVE, inactive);
686 }
687
688 if (setdel) {
689 dst_key_settime(key, DST_TIME_DELETE, deltime);
690 }
691 if (setsyncadd) {
692 dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncadd);
693 }
694 if (setsyncdel) {
695 dst_key_settime(key, DST_TIME_SYNCDELETE, syncdel);
696 }
697 } else {
698 if (setpub || setact || setrev || setinact || setdel ||
699 unsetpub || unsetact || unsetrev || unsetinact ||
700 unsetdel || genonly || setsyncadd || setsyncdel)
701 {
702 fatal("cannot use -C together with "
703 "-P, -A, -R, -I, -D, or -G options");
704 }
705 /*
706 * Compatibility mode: Private-key-format
707 * should be set to 1.2.
708 */
709 dst_key_setprivateformat(key, 1, 2);
710 }
711
712 /* Set default key TTL */
713 if (setttl) {
714 dst_key_setttl(key, ttl);
715 }
716
717 /*
718 * Do not overwrite an existing key. Warn LOUDLY if there
719 * is a risk of ID collision due to this key or another key
720 * being revoked.
721 */
722 if (key_collision(key, name, directory, mctx, &exact)) {
723 isc_buffer_clear(&buf);
724 ret = dst_key_buildfilename(key, 0, directory, &buf);
725 if (ret != ISC_R_SUCCESS) {
726 fatal("dst_key_buildfilename returned: %s\n",
727 isc_result_totext(ret));
728 }
729 if (exact) {
730 fatal("%s: %s already exists\n", program, filename);
731 }
732
733 if (avoid_collisions) {
734 fatal("%s: %s could collide with another key upon "
735 "revokation\n",
736 program, filename);
737 }
738
739 fprintf(stderr,
740 "%s: WARNING: Key %s could collide with "
741 "another key upon revokation. If you plan "
742 "to revoke keys, destroy this key and "
743 "generate a different one.\n",
744 program, filename);
745 }
746
747 ret = dst_key_tofile(key, options, directory);
748 if (ret != ISC_R_SUCCESS) {
749 char keystr[DST_KEY_FORMATSIZE];
750 dst_key_format(key, keystr, sizeof(keystr));
751 fatal("failed to write key %s: %s\n", keystr,
752 isc_result_totext(ret));
753 }
754
755 isc_buffer_clear(&buf);
756 ret = dst_key_buildfilename(key, 0, NULL, &buf);
757 if (ret != ISC_R_SUCCESS) {
758 fatal("dst_key_buildfilename returned: %s\n",
759 isc_result_totext(ret));
760 }
761 printf("%s\n", filename);
762 dst_key_free(&key);
763 if (prevkey != NULL) {
764 dst_key_free(&prevkey);
765 }
766
767 cleanup_logging(&log);
768 dst_lib_destroy();
769 if (verbose > 10) {
770 isc_mem_stats(mctx, stdout);
771 }
772 isc_mem_free(mctx, label);
773 isc_mem_destroy(&mctx);
774
775 if (freeit != NULL) {
776 free(freeit);
777 }
778
779 return (0);
780 }
781