1*4ac1c27eSchristos /* $NetBSD: dnssec-keygen.c,v 1.10 2023/01/25 21:43:23 christos Exp $ */
2e2b1b9c0Schristos
3e2b1b9c0Schristos /*
4e2b1b9c0Schristos * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5e2b1b9c0Schristos *
6c0b5d9fbSchristos * SPDX-License-Identifier: MPL-2.0
7c0b5d9fbSchristos *
8e2b1b9c0Schristos * This Source Code Form is subject to the terms of the Mozilla Public
9e2b1b9c0Schristos * License, v. 2.0. If a copy of the MPL was not distributed with this
1073584a28Schristos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11e2b1b9c0Schristos *
12e2b1b9c0Schristos * See the COPYRIGHT file distributed with this work for additional
13e2b1b9c0Schristos * information regarding copyright ownership.
14e2b1b9c0Schristos *
15e2b1b9c0Schristos * Portions Copyright (C) Network Associates, Inc.
16e2b1b9c0Schristos *
17e2b1b9c0Schristos * Permission to use, copy, modify, and/or distribute this software for any
18e2b1b9c0Schristos * purpose with or without fee is hereby granted, provided that the above
19e2b1b9c0Schristos * copyright notice and this permission notice appear in all copies.
20e2b1b9c0Schristos *
21e2b1b9c0Schristos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
22e2b1b9c0Schristos * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
23e2b1b9c0Schristos * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
24e2b1b9c0Schristos * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25e2b1b9c0Schristos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
26e2b1b9c0Schristos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
27e2b1b9c0Schristos * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28e2b1b9c0Schristos */
29e2b1b9c0Schristos
30e2b1b9c0Schristos /*! \file */
31e2b1b9c0Schristos
32e2b1b9c0Schristos #include <ctype.h>
33f2e20987Schristos #include <inttypes.h>
34f2e20987Schristos #include <stdbool.h>
35e2b1b9c0Schristos #include <stdlib.h>
36e2b1b9c0Schristos #include <unistd.h>
37e2b1b9c0Schristos
38e2b1b9c0Schristos #include <isc/buffer.h>
39e2b1b9c0Schristos #include <isc/commandline.h>
40e2b1b9c0Schristos #include <isc/mem.h>
41e2b1b9c0Schristos #include <isc/print.h>
42e2b1b9c0Schristos #include <isc/region.h>
43e2b1b9c0Schristos #include <isc/string.h>
44e2b1b9c0Schristos #include <isc/util.h>
45e2b1b9c0Schristos
46e2b1b9c0Schristos #include <pk11/site.h>
47e2b1b9c0Schristos
48e2b1b9c0Schristos #include <dns/dnssec.h>
49e2b1b9c0Schristos #include <dns/fixedname.h>
509742fdb4Schristos #include <dns/kasp.h>
51e2b1b9c0Schristos #include <dns/keyvalues.h>
52e2b1b9c0Schristos #include <dns/log.h>
53e2b1b9c0Schristos #include <dns/name.h>
54e2b1b9c0Schristos #include <dns/rdataclass.h>
55e2b1b9c0Schristos #include <dns/result.h>
56e2b1b9c0Schristos #include <dns/secalg.h>
57e2b1b9c0Schristos
58e2b1b9c0Schristos #include <dst/dst.h>
59e2b1b9c0Schristos
609742fdb4Schristos #include <isccfg/cfg.h>
619742fdb4Schristos #include <isccfg/grammar.h>
629742fdb4Schristos #include <isccfg/kaspconf.h>
639742fdb4Schristos #include <isccfg/namedconf.h>
649742fdb4Schristos
65f2e20987Schristos #if USE_PKCS11
66e2b1b9c0Schristos #include <pk11/result.h>
679742fdb4Schristos #endif /* if USE_PKCS11 */
68e2b1b9c0Schristos
69e2b1b9c0Schristos #include "dnssectool.h"
70e2b1b9c0Schristos
71e2b1b9c0Schristos #define MAX_RSA 4096 /* should be long enough... */
72e2b1b9c0Schristos
73e2b1b9c0Schristos const char *program = "dnssec-keygen";
749742fdb4Schristos
759742fdb4Schristos isc_log_t *lctx = NULL;
76e2b1b9c0Schristos
77e2b1b9c0Schristos ISC_PLATFORM_NORETURN_PRE static void
78e2b1b9c0Schristos usage(void) ISC_PLATFORM_NORETURN_POST;
79e2b1b9c0Schristos
809742fdb4Schristos static void
819742fdb4Schristos progress(int p);
829742fdb4Schristos
839742fdb4Schristos struct keygen_ctx {
849742fdb4Schristos const char *predecessor;
859742fdb4Schristos const char *policy;
869742fdb4Schristos const char *configfile;
879742fdb4Schristos const char *directory;
889742fdb4Schristos char *algname;
899742fdb4Schristos char *nametype;
909742fdb4Schristos char *type;
919742fdb4Schristos int generator;
929742fdb4Schristos int protocol;
939742fdb4Schristos int size;
949742fdb4Schristos int signatory;
959742fdb4Schristos dns_rdataclass_t rdclass;
969742fdb4Schristos int options;
979742fdb4Schristos int dbits;
989742fdb4Schristos dns_ttl_t ttl;
999742fdb4Schristos uint16_t kskflag;
1009742fdb4Schristos uint16_t revflag;
1019742fdb4Schristos dns_secalg_t alg;
1029742fdb4Schristos /* timing data */
1039742fdb4Schristos int prepub;
1049742fdb4Schristos isc_stdtime_t now;
1059742fdb4Schristos isc_stdtime_t publish;
1069742fdb4Schristos isc_stdtime_t activate;
1079742fdb4Schristos isc_stdtime_t inactive;
1089742fdb4Schristos isc_stdtime_t revokekey;
1099742fdb4Schristos isc_stdtime_t deltime;
1109742fdb4Schristos isc_stdtime_t syncadd;
1119742fdb4Schristos isc_stdtime_t syncdel;
1129742fdb4Schristos bool setpub;
1139742fdb4Schristos bool setact;
1149742fdb4Schristos bool setinact;
1159742fdb4Schristos bool setrev;
1169742fdb4Schristos bool setdel;
1179742fdb4Schristos bool setsyncadd;
1189742fdb4Schristos bool setsyncdel;
1199742fdb4Schristos bool unsetpub;
1209742fdb4Schristos bool unsetact;
1219742fdb4Schristos bool unsetinact;
1229742fdb4Schristos bool unsetrev;
1239742fdb4Schristos bool unsetdel;
1249742fdb4Schristos /* how to generate the key */
1259742fdb4Schristos bool setttl;
1269742fdb4Schristos bool use_nsec3;
1279742fdb4Schristos bool genonly;
1289742fdb4Schristos bool showprogress;
1299742fdb4Schristos bool quiet;
1309742fdb4Schristos bool oldstyle;
1319742fdb4Schristos /* state */
1329742fdb4Schristos time_t lifetime;
1339742fdb4Schristos bool ksk;
1349742fdb4Schristos bool zsk;
1359742fdb4Schristos };
1369742fdb4Schristos
1379742fdb4Schristos typedef struct keygen_ctx keygen_ctx_t;
138e2b1b9c0Schristos
139e2b1b9c0Schristos static void
usage(void)140e2b1b9c0Schristos usage(void) {
141e2b1b9c0Schristos fprintf(stderr, "Usage:\n");
142e2b1b9c0Schristos fprintf(stderr, " %s [options] name\n\n", program);
143e2b1b9c0Schristos fprintf(stderr, "Version: %s\n", VERSION);
144e2b1b9c0Schristos fprintf(stderr, " name: owner of the key\n");
145e2b1b9c0Schristos fprintf(stderr, "Options:\n");
146e2b1b9c0Schristos fprintf(stderr, " -K <directory>: write keys into directory\n");
1479742fdb4Schristos fprintf(stderr, " -k <policy>: generate keys for dnssec-policy\n");
1489742fdb4Schristos fprintf(stderr, " -l <file>: configuration file with dnssec-policy "
1499742fdb4Schristos "statement\n");
150e2b1b9c0Schristos fprintf(stderr, " -a <algorithm>:\n");
151cc2e102bSchristos fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n");
152f2e20987Schristos fprintf(stderr, " RSASHA256 | RSASHA512 |\n");
153e2b1b9c0Schristos fprintf(stderr, " ECDSAP256SHA256 | ECDSAP384SHA384 |\n");
154f2e20987Schristos fprintf(stderr, " ED25519 | ED448 | DH\n");
155e2b1b9c0Schristos fprintf(stderr, " -3: use NSEC3-capable algorithm\n");
156e2b1b9c0Schristos fprintf(stderr, " -b <key size in bits>:\n");
157e2b1b9c0Schristos fprintf(stderr, " RSASHA1:\t[1024..%d]\n", MAX_RSA);
158e2b1b9c0Schristos fprintf(stderr, " NSEC3RSASHA1:\t[1024..%d]\n", MAX_RSA);
159e2b1b9c0Schristos fprintf(stderr, " RSASHA256:\t[1024..%d]\n", MAX_RSA);
160e2b1b9c0Schristos fprintf(stderr, " RSASHA512:\t[1024..%d]\n", MAX_RSA);
161e2b1b9c0Schristos fprintf(stderr, " DH:\t\t[128..4096]\n");
162e2b1b9c0Schristos fprintf(stderr, " ECDSAP256SHA256:\tignored\n");
163e2b1b9c0Schristos fprintf(stderr, " ECDSAP384SHA384:\tignored\n");
164e2b1b9c0Schristos fprintf(stderr, " ED25519:\tignored\n");
165e2b1b9c0Schristos fprintf(stderr, " ED448:\tignored\n");
166e2b1b9c0Schristos fprintf(stderr, " (key size defaults are set according to\n"
167e2b1b9c0Schristos " algorithm and usage (ZSK or KSK)\n");
168e2b1b9c0Schristos fprintf(stderr, " -n <nametype>: ZONE | HOST | ENTITY | "
169e2b1b9c0Schristos "USER | OTHER\n");
170e2b1b9c0Schristos fprintf(stderr, " (DNSKEY generation defaults to ZONE)\n");
171e2b1b9c0Schristos fprintf(stderr, " -c <class>: (default: IN)\n");
172e2b1b9c0Schristos fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
173e2b1b9c0Schristos fprintf(stderr, " -E <engine>:\n");
174f2e20987Schristos #if USE_PKCS11
1759742fdb4Schristos fprintf(stderr,
1769742fdb4Schristos " path to PKCS#11 provider library "
1779742fdb4Schristos "(default is %s)\n",
1789742fdb4Schristos PK11_LIB_LOCATION);
1799742fdb4Schristos #else /* if USE_PKCS11 */
180e2b1b9c0Schristos fprintf(stderr, " name of an OpenSSL engine to use\n");
1819742fdb4Schristos #endif /* if USE_PKCS11 */
182e2b1b9c0Schristos fprintf(stderr, " -f <keyflag>: KSK | REVOKE\n");
183e2b1b9c0Schristos fprintf(stderr, " -g <generator>: use specified generator "
184e2b1b9c0Schristos "(DH only)\n");
185e2b1b9c0Schristos fprintf(stderr, " -L <ttl>: default key TTL\n");
186e2b1b9c0Schristos fprintf(stderr, " -p <protocol>: (default: 3 [dnssec])\n");
187e2b1b9c0Schristos fprintf(stderr, " -s <strength>: strength value this key signs DNS "
188e2b1b9c0Schristos "records with (default: 0)\n");
189e2b1b9c0Schristos fprintf(stderr, " -T <rrtype>: DNSKEY | KEY (default: DNSKEY; "
190e2b1b9c0Schristos "use KEY for SIG(0))\n");
191e2b1b9c0Schristos fprintf(stderr, " -t <type>: "
192e2b1b9c0Schristos "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
193e2b1b9c0Schristos "(default: AUTHCONF)\n");
194e2b1b9c0Schristos fprintf(stderr, " -h: print usage and exit\n");
195e2b1b9c0Schristos fprintf(stderr, " -m <memory debugging mode>:\n");
196e2b1b9c0Schristos fprintf(stderr, " usage | trace | record | size | mctx\n");
197e2b1b9c0Schristos fprintf(stderr, " -v <level>: set verbosity level (0 - 10)\n");
198e2b1b9c0Schristos fprintf(stderr, " -V: print version information\n");
199e2b1b9c0Schristos fprintf(stderr, "Timing options:\n");
200e2b1b9c0Schristos fprintf(stderr, " -P date/[+-]offset/none: set key publication date "
201e2b1b9c0Schristos "(default: now)\n");
202e2b1b9c0Schristos fprintf(stderr, " -P sync date/[+-]offset/none: set CDS and CDNSKEY "
203e2b1b9c0Schristos "publication date\n");
204e2b1b9c0Schristos fprintf(stderr, " -A date/[+-]offset/none: set key activation date "
205e2b1b9c0Schristos "(default: now)\n");
206e2b1b9c0Schristos fprintf(stderr, " -R date/[+-]offset/none: set key "
207e2b1b9c0Schristos "revocation date\n");
208e2b1b9c0Schristos fprintf(stderr, " -I date/[+-]offset/none: set key "
209e2b1b9c0Schristos "inactivation date\n");
210e2b1b9c0Schristos fprintf(stderr, " -D date/[+-]offset/none: set key deletion date\n");
211e2b1b9c0Schristos fprintf(stderr, " -D sync date/[+-]offset/none: set CDS and CDNSKEY "
212e2b1b9c0Schristos "deletion date\n");
213e2b1b9c0Schristos
214e2b1b9c0Schristos fprintf(stderr, " -G: generate key only; do not set -P or -A\n");
215e2b1b9c0Schristos fprintf(stderr, " -C: generate a backward-compatible key, omitting "
216e2b1b9c0Schristos "all dates\n");
217e2b1b9c0Schristos fprintf(stderr, " -S <key>: generate a successor to an existing "
218e2b1b9c0Schristos "key\n");
219e2b1b9c0Schristos fprintf(stderr, " -i <interval>: prepublication interval for "
220e2b1b9c0Schristos "successor key "
221e2b1b9c0Schristos "(default: 30 days)\n");
222e2b1b9c0Schristos fprintf(stderr, "Output:\n");
223e2b1b9c0Schristos fprintf(stderr, " K<name>+<alg>+<id>.key, "
224e2b1b9c0Schristos "K<name>+<alg>+<id>.private\n");
225e2b1b9c0Schristos
226e2b1b9c0Schristos exit(-1);
227e2b1b9c0Schristos }
228e2b1b9c0Schristos
229e2b1b9c0Schristos static void
progress(int p)2309742fdb4Schristos progress(int p) {
231e2b1b9c0Schristos char c = '*';
232e2b1b9c0Schristos
233e2b1b9c0Schristos switch (p) {
234e2b1b9c0Schristos case 0:
235e2b1b9c0Schristos c = '.';
236e2b1b9c0Schristos break;
237e2b1b9c0Schristos case 1:
238e2b1b9c0Schristos c = '+';
239e2b1b9c0Schristos break;
240e2b1b9c0Schristos case 2:
241e2b1b9c0Schristos c = '*';
242e2b1b9c0Schristos break;
243e2b1b9c0Schristos case 3:
244e2b1b9c0Schristos c = ' ';
245e2b1b9c0Schristos break;
246e2b1b9c0Schristos default:
247e2b1b9c0Schristos break;
248e2b1b9c0Schristos }
249e2b1b9c0Schristos (void)putc(c, stderr);
250e2b1b9c0Schristos (void)fflush(stderr);
251e2b1b9c0Schristos }
252e2b1b9c0Schristos
2539742fdb4Schristos static void
kasp_from_conf(cfg_obj_t * config,isc_mem_t * mctx,const char * name,dns_kasp_t ** kaspp)2549742fdb4Schristos kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
2559742fdb4Schristos dns_kasp_t **kaspp) {
2569742fdb4Schristos const cfg_listelt_t *element;
2579742fdb4Schristos const cfg_obj_t *kasps = NULL;
2589742fdb4Schristos dns_kasp_t *kasp = NULL, *kasp_next;
2599742fdb4Schristos isc_result_t result = ISC_R_NOTFOUND;
2609742fdb4Schristos dns_kasplist_t kasplist;
261e2b1b9c0Schristos
2629742fdb4Schristos ISC_LIST_INIT(kasplist);
263e2b1b9c0Schristos
2649742fdb4Schristos (void)cfg_map_get(config, "dnssec-policy", &kasps);
2659742fdb4Schristos for (element = cfg_list_first(kasps); element != NULL;
2669742fdb4Schristos element = cfg_list_next(element))
2679742fdb4Schristos {
2689742fdb4Schristos cfg_obj_t *kconfig = cfg_listelt_value(element);
2699742fdb4Schristos kasp = NULL;
2709742fdb4Schristos if (strcmp(cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
271*4ac1c27eSchristos name) != 0)
272*4ac1c27eSchristos {
2739742fdb4Schristos continue;
2749742fdb4Schristos }
275e2b1b9c0Schristos
27673584a28Schristos result = cfg_kasp_fromconfig(kconfig, NULL, mctx, lctx,
27773584a28Schristos &kasplist, &kasp);
2789742fdb4Schristos if (result != ISC_R_SUCCESS) {
2799742fdb4Schristos fatal("failed to configure dnssec-policy '%s': %s",
2809742fdb4Schristos cfg_obj_asstring(cfg_tuple_get(kconfig, "name")),
2819742fdb4Schristos isc_result_totext(result));
2829742fdb4Schristos }
2839742fdb4Schristos INSIST(kasp != NULL);
2849742fdb4Schristos dns_kasp_freeze(kasp);
2859742fdb4Schristos break;
2869742fdb4Schristos }
2879742fdb4Schristos
2889742fdb4Schristos *kaspp = kasp;
289e2b1b9c0Schristos
290e2b1b9c0Schristos /*
29173584a28Schristos * Cleanup kasp list.
292e2b1b9c0Schristos */
2939742fdb4Schristos for (kasp = ISC_LIST_HEAD(kasplist); kasp != NULL; kasp = kasp_next) {
2949742fdb4Schristos kasp_next = ISC_LIST_NEXT(kasp, link);
2959742fdb4Schristos ISC_LIST_UNLINK(kasplist, kasp, link);
2969742fdb4Schristos dns_kasp_detach(&kasp);
297e2b1b9c0Schristos }
298e2b1b9c0Schristos }
299e2b1b9c0Schristos
3009742fdb4Schristos static void
keygen(keygen_ctx_t * ctx,isc_mem_t * mctx,int argc,char ** argv)3019742fdb4Schristos keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) {
3029742fdb4Schristos char filename[255];
3039742fdb4Schristos char algstr[DNS_SECALG_FORMATSIZE];
3049742fdb4Schristos uint16_t flags = 0;
3059742fdb4Schristos int param = 0;
3069742fdb4Schristos bool null_key = false;
3079742fdb4Schristos bool conflict = false;
3089742fdb4Schristos bool show_progress = false;
3099742fdb4Schristos isc_buffer_t buf;
3109742fdb4Schristos dns_name_t *name;
3119742fdb4Schristos dns_fixedname_t fname;
3129742fdb4Schristos isc_result_t ret;
3139742fdb4Schristos dst_key_t *key = NULL;
3149742fdb4Schristos dst_key_t *prevkey = NULL;
315e2b1b9c0Schristos
3169742fdb4Schristos UNUSED(argc);
317e2b1b9c0Schristos
3189742fdb4Schristos dns_secalg_format(ctx->alg, algstr, sizeof(algstr));
319e2b1b9c0Schristos
3209742fdb4Schristos if (ctx->predecessor == NULL) {
3219742fdb4Schristos if (ctx->prepub == -1) {
3229742fdb4Schristos ctx->prepub = 0;
3239742fdb4Schristos }
324e2b1b9c0Schristos
325e2b1b9c0Schristos name = dns_fixedname_initname(&fname);
326e2b1b9c0Schristos isc_buffer_init(&buf, argv[isc_commandline_index],
327e2b1b9c0Schristos strlen(argv[isc_commandline_index]));
328e2b1b9c0Schristos isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
329e2b1b9c0Schristos ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
3309742fdb4Schristos if (ret != ISC_R_SUCCESS) {
331e2b1b9c0Schristos fatal("invalid key name %s: %s",
332e2b1b9c0Schristos argv[isc_commandline_index],
333e2b1b9c0Schristos isc_result_totext(ret));
334e2b1b9c0Schristos }
335e2b1b9c0Schristos
3369742fdb4Schristos if (!dst_algorithm_supported(ctx->alg)) {
3379742fdb4Schristos fatal("unsupported algorithm: %s", algstr);
338e2b1b9c0Schristos }
339e2b1b9c0Schristos
3409742fdb4Schristos if (ctx->alg == DST_ALG_DH) {
3419742fdb4Schristos ctx->options |= DST_TYPE_KEY;
342f2e20987Schristos }
343e2b1b9c0Schristos
3449742fdb4Schristos if (ctx->use_nsec3) {
3459742fdb4Schristos switch (ctx->alg) {
346e2b1b9c0Schristos case DST_ALG_RSASHA1:
3479742fdb4Schristos ctx->alg = DST_ALG_NSEC3RSASHA1;
348e2b1b9c0Schristos break;
349e2b1b9c0Schristos case DST_ALG_NSEC3RSASHA1:
350e2b1b9c0Schristos case DST_ALG_RSASHA256:
351e2b1b9c0Schristos case DST_ALG_RSASHA512:
352e2b1b9c0Schristos case DST_ALG_ECDSA256:
353e2b1b9c0Schristos case DST_ALG_ECDSA384:
354e2b1b9c0Schristos case DST_ALG_ED25519:
355e2b1b9c0Schristos case DST_ALG_ED448:
356e2b1b9c0Schristos break;
357e2b1b9c0Schristos default:
3589742fdb4Schristos fatal("algorithm %s is incompatible with NSEC3"
3599742fdb4Schristos ", do not use the -3 option",
3609742fdb4Schristos algstr);
361e2b1b9c0Schristos }
362e2b1b9c0Schristos }
363e2b1b9c0Schristos
3649742fdb4Schristos if (ctx->type != NULL && (ctx->options & DST_TYPE_KEY) != 0) {
3659742fdb4Schristos if (strcasecmp(ctx->type, "NOAUTH") == 0) {
366e2b1b9c0Schristos flags |= DNS_KEYTYPE_NOAUTH;
3679742fdb4Schristos } else if (strcasecmp(ctx->type, "NOCONF") == 0) {
368e2b1b9c0Schristos flags |= DNS_KEYTYPE_NOCONF;
3699742fdb4Schristos } else if (strcasecmp(ctx->type, "NOAUTHCONF") == 0) {
370e2b1b9c0Schristos flags |= (DNS_KEYTYPE_NOAUTH |
371e2b1b9c0Schristos DNS_KEYTYPE_NOCONF);
3729742fdb4Schristos if (ctx->size < 0) {
3739742fdb4Schristos ctx->size = 0;
3749742fdb4Schristos }
3759742fdb4Schristos } else if (strcasecmp(ctx->type, "AUTHCONF") == 0) {
3769742fdb4Schristos /* nothing */
377f2e20987Schristos } else {
3789742fdb4Schristos fatal("invalid type %s", ctx->type);
379e2b1b9c0Schristos }
380f2e20987Schristos }
381e2b1b9c0Schristos
3829742fdb4Schristos if (ctx->size < 0) {
3839742fdb4Schristos switch (ctx->alg) {
384e2b1b9c0Schristos case DST_ALG_RSASHA1:
385e2b1b9c0Schristos case DST_ALG_NSEC3RSASHA1:
386e2b1b9c0Schristos case DST_ALG_RSASHA256:
387e2b1b9c0Schristos case DST_ALG_RSASHA512:
3889742fdb4Schristos ctx->size = 2048;
389e2b1b9c0Schristos if (verbose > 0) {
3909742fdb4Schristos fprintf(stderr,
3919742fdb4Schristos "key size not "
392e2b1b9c0Schristos "specified; defaulting"
3939742fdb4Schristos " to %d\n",
3949742fdb4Schristos ctx->size);
395e2b1b9c0Schristos }
396e2b1b9c0Schristos break;
397e2b1b9c0Schristos case DST_ALG_ECDSA256:
398e2b1b9c0Schristos case DST_ALG_ECDSA384:
399e2b1b9c0Schristos case DST_ALG_ED25519:
400e2b1b9c0Schristos case DST_ALG_ED448:
401e2b1b9c0Schristos break;
402e2b1b9c0Schristos default:
403e2b1b9c0Schristos fatal("key size not specified (-b option)");
404e2b1b9c0Schristos }
405e2b1b9c0Schristos }
406e2b1b9c0Schristos
4079742fdb4Schristos if (!ctx->oldstyle && ctx->prepub > 0) {
4089742fdb4Schristos if (ctx->setpub && ctx->setact &&
409*4ac1c27eSchristos (ctx->activate - ctx->prepub) < ctx->publish)
410*4ac1c27eSchristos {
411e2b1b9c0Schristos fatal("Activation and publication dates "
412e2b1b9c0Schristos "are closer together than the\n\t"
413e2b1b9c0Schristos "prepublication interval.");
414e2b1b9c0Schristos }
415e2b1b9c0Schristos
4169742fdb4Schristos if (!ctx->setpub && !ctx->setact) {
4179742fdb4Schristos ctx->setpub = ctx->setact = true;
4189742fdb4Schristos ctx->publish = ctx->now;
4199742fdb4Schristos ctx->activate = ctx->now + ctx->prepub;
4209742fdb4Schristos } else if (ctx->setpub && !ctx->setact) {
4219742fdb4Schristos ctx->setact = true;
4229742fdb4Schristos ctx->activate = ctx->publish + ctx->prepub;
4239742fdb4Schristos } else if (ctx->setact && !ctx->setpub) {
4249742fdb4Schristos ctx->setpub = true;
4259742fdb4Schristos ctx->publish = ctx->activate - ctx->prepub;
4269742fdb4Schristos }
4279742fdb4Schristos
4289742fdb4Schristos if ((ctx->activate - ctx->prepub) < ctx->now) {
429e2b1b9c0Schristos fatal("Time until activation is shorter "
430e2b1b9c0Schristos "than the\n\tprepublication interval.");
431e2b1b9c0Schristos }
4329742fdb4Schristos }
433e2b1b9c0Schristos } else {
434e2b1b9c0Schristos char keystr[DST_KEY_FORMATSIZE];
435e2b1b9c0Schristos isc_stdtime_t when;
436e2b1b9c0Schristos int major, minor;
437e2b1b9c0Schristos
4389742fdb4Schristos if (ctx->prepub == -1) {
4399742fdb4Schristos ctx->prepub = (30 * 86400);
4409742fdb4Schristos }
441e2b1b9c0Schristos
4429742fdb4Schristos if (ctx->alg != 0) {
443e2b1b9c0Schristos fatal("-S and -a cannot be used together");
4449742fdb4Schristos }
4459742fdb4Schristos if (ctx->size >= 0) {
446e2b1b9c0Schristos fatal("-S and -b cannot be used together");
4479742fdb4Schristos }
4489742fdb4Schristos if (ctx->nametype != NULL) {
449e2b1b9c0Schristos fatal("-S and -n cannot be used together");
4509742fdb4Schristos }
4519742fdb4Schristos if (ctx->type != NULL) {
452e2b1b9c0Schristos fatal("-S and -t cannot be used together");
4539742fdb4Schristos }
4549742fdb4Schristos if (ctx->setpub || ctx->unsetpub) {
455e2b1b9c0Schristos fatal("-S and -P cannot be used together");
4569742fdb4Schristos }
4579742fdb4Schristos if (ctx->setact || ctx->unsetact) {
458e2b1b9c0Schristos fatal("-S and -A cannot be used together");
4599742fdb4Schristos }
4609742fdb4Schristos if (ctx->use_nsec3) {
461e2b1b9c0Schristos fatal("-S and -3 cannot be used together");
4629742fdb4Schristos }
4639742fdb4Schristos if (ctx->oldstyle) {
464e2b1b9c0Schristos fatal("-S and -C cannot be used together");
4659742fdb4Schristos }
4669742fdb4Schristos if (ctx->genonly) {
467e2b1b9c0Schristos fatal("-S and -G cannot be used together");
4689742fdb4Schristos }
469e2b1b9c0Schristos
4709742fdb4Schristos ret = dst_key_fromnamedfile(
4719742fdb4Schristos ctx->predecessor, ctx->directory,
4729742fdb4Schristos (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE),
473e2b1b9c0Schristos mctx, &prevkey);
4749742fdb4Schristos if (ret != ISC_R_SUCCESS) {
4759742fdb4Schristos fatal("Invalid keyfile %s: %s", ctx->predecessor,
4769742fdb4Schristos isc_result_totext(ret));
4779742fdb4Schristos }
4789742fdb4Schristos if (!dst_key_isprivate(prevkey)) {
4799742fdb4Schristos fatal("%s is not a private key", ctx->predecessor);
4809742fdb4Schristos }
481e2b1b9c0Schristos
482e2b1b9c0Schristos name = dst_key_name(prevkey);
4839742fdb4Schristos ctx->alg = dst_key_alg(prevkey);
4849742fdb4Schristos ctx->size = dst_key_size(prevkey);
485e2b1b9c0Schristos flags = dst_key_flags(prevkey);
486e2b1b9c0Schristos
487e2b1b9c0Schristos dst_key_format(prevkey, keystr, sizeof(keystr));
488e2b1b9c0Schristos dst_key_getprivateformat(prevkey, &major, &minor);
4899742fdb4Schristos if (major != DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) {
490e2b1b9c0Schristos fatal("Key %s has incompatible format version %d.%d\n\t"
491e2b1b9c0Schristos "It is not possible to generate a successor key.",
492e2b1b9c0Schristos keystr, major, minor);
4939742fdb4Schristos }
494e2b1b9c0Schristos
495e2b1b9c0Schristos ret = dst_key_gettime(prevkey, DST_TIME_ACTIVATE, &when);
4969742fdb4Schristos if (ret != ISC_R_SUCCESS) {
497e2b1b9c0Schristos fatal("Key %s has no activation date.\n\t"
498e2b1b9c0Schristos "You must use dnssec-settime -A to set one "
4999742fdb4Schristos "before generating a successor.",
5009742fdb4Schristos keystr);
5019742fdb4Schristos }
502e2b1b9c0Schristos
5039742fdb4Schristos ret = dst_key_gettime(prevkey, DST_TIME_INACTIVE,
5049742fdb4Schristos &ctx->activate);
5059742fdb4Schristos if (ret != ISC_R_SUCCESS) {
506e2b1b9c0Schristos fatal("Key %s has no inactivation date.\n\t"
507e2b1b9c0Schristos "You must use dnssec-settime -I to set one "
5089742fdb4Schristos "before generating a successor.",
5099742fdb4Schristos keystr);
5109742fdb4Schristos }
511e2b1b9c0Schristos
5129742fdb4Schristos ctx->publish = ctx->activate - ctx->prepub;
5139742fdb4Schristos if (ctx->publish < ctx->now) {
514e2b1b9c0Schristos fatal("Key %s becomes inactive\n\t"
515e2b1b9c0Schristos "sooner than the prepublication period "
516e2b1b9c0Schristos "for the new key ends.\n\t"
517e2b1b9c0Schristos "Either change the inactivation date with "
518e2b1b9c0Schristos "dnssec-settime -I,\n\t"
519e2b1b9c0Schristos "or use the -i option to set a shorter "
5209742fdb4Schristos "prepublication interval.",
5219742fdb4Schristos keystr);
5229742fdb4Schristos }
523e2b1b9c0Schristos
524e2b1b9c0Schristos ret = dst_key_gettime(prevkey, DST_TIME_DELETE, &when);
5259742fdb4Schristos if (ret != ISC_R_SUCCESS) {
5269742fdb4Schristos fprintf(stderr,
5279742fdb4Schristos "%s: WARNING: Key %s has no removal "
528e2b1b9c0Schristos "date;\n\t it will remain in the zone "
529e2b1b9c0Schristos "indefinitely after rollover.\n\t "
530e2b1b9c0Schristos "You can use dnssec-settime -D to "
5319742fdb4Schristos "change this.\n",
5329742fdb4Schristos program, keystr);
533e2b1b9c0Schristos }
534e2b1b9c0Schristos
5359742fdb4Schristos ctx->setpub = ctx->setact = true;
5369742fdb4Schristos }
5379742fdb4Schristos
5389742fdb4Schristos switch (ctx->alg) {
539e2b1b9c0Schristos case DNS_KEYALG_RSASHA1:
540e2b1b9c0Schristos case DNS_KEYALG_NSEC3RSASHA1:
541e2b1b9c0Schristos case DNS_KEYALG_RSASHA256:
5429742fdb4Schristos if (ctx->size != 0 && (ctx->size < 1024 || ctx->size > MAX_RSA))
5439742fdb4Schristos {
5449742fdb4Schristos fatal("RSA key size %d out of range", ctx->size);
5459742fdb4Schristos }
546e2b1b9c0Schristos break;
547e2b1b9c0Schristos case DNS_KEYALG_RSASHA512:
5489742fdb4Schristos if (ctx->size != 0 && (ctx->size < 1024 || ctx->size > MAX_RSA))
5499742fdb4Schristos {
5509742fdb4Schristos fatal("RSA key size %d out of range", ctx->size);
5519742fdb4Schristos }
552e2b1b9c0Schristos break;
553e2b1b9c0Schristos case DNS_KEYALG_DH:
5549742fdb4Schristos if (ctx->size != 0 && (ctx->size < 128 || ctx->size > 4096)) {
5559742fdb4Schristos fatal("DH key size %d out of range", ctx->size);
5569742fdb4Schristos }
557e2b1b9c0Schristos break;
558e2b1b9c0Schristos case DST_ALG_ECDSA256:
5599742fdb4Schristos ctx->size = 256;
560e2b1b9c0Schristos break;
561e2b1b9c0Schristos case DST_ALG_ECDSA384:
5629742fdb4Schristos ctx->size = 384;
563e2b1b9c0Schristos break;
564e2b1b9c0Schristos case DST_ALG_ED25519:
5659742fdb4Schristos ctx->size = 256;
566e2b1b9c0Schristos break;
567e2b1b9c0Schristos case DST_ALG_ED448:
5689742fdb4Schristos ctx->size = 456;
569e2b1b9c0Schristos break;
570e2b1b9c0Schristos }
571e2b1b9c0Schristos
5729742fdb4Schristos if (ctx->alg != DNS_KEYALG_DH && ctx->generator != 0) {
573e2b1b9c0Schristos fatal("specified DH generator for a non-DH key");
574e2b1b9c0Schristos }
575e2b1b9c0Schristos
5769742fdb4Schristos if (ctx->nametype == NULL) {
5779742fdb4Schristos if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
5789742fdb4Schristos fatal("no nametype specified");
5799742fdb4Schristos }
5809742fdb4Schristos flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
5819742fdb4Schristos } else if (strcasecmp(ctx->nametype, "zone") == 0) {
5829742fdb4Schristos flags |= DNS_KEYOWNER_ZONE;
5839742fdb4Schristos } else if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
5849742fdb4Schristos if (strcasecmp(ctx->nametype, "host") == 0 ||
5859742fdb4Schristos strcasecmp(ctx->nametype, "entity") == 0)
5869742fdb4Schristos {
5879742fdb4Schristos flags |= DNS_KEYOWNER_ENTITY;
5889742fdb4Schristos } else if (strcasecmp(ctx->nametype, "user") == 0) {
5899742fdb4Schristos flags |= DNS_KEYOWNER_USER;
5909742fdb4Schristos } else {
5919742fdb4Schristos fatal("invalid KEY nametype %s", ctx->nametype);
5929742fdb4Schristos }
5939742fdb4Schristos } else if (strcasecmp(ctx->nametype, "other") != 0) { /* DNSKEY */
5949742fdb4Schristos fatal("invalid DNSKEY nametype %s", ctx->nametype);
5959742fdb4Schristos }
5969742fdb4Schristos
5979742fdb4Schristos if (ctx->directory == NULL) {
5989742fdb4Schristos ctx->directory = ".";
5999742fdb4Schristos }
6009742fdb4Schristos
6019742fdb4Schristos if ((ctx->options & DST_TYPE_KEY) != 0) { /* KEY */
6029742fdb4Schristos flags |= ctx->signatory;
6039742fdb4Schristos } else if ((flags & DNS_KEYOWNER_ZONE) != 0) { /* DNSKEY */
6049742fdb4Schristos flags |= ctx->kskflag;
6059742fdb4Schristos flags |= ctx->revflag;
6069742fdb4Schristos }
6079742fdb4Schristos
6089742fdb4Schristos if (ctx->protocol == -1) {
6099742fdb4Schristos ctx->protocol = DNS_KEYPROTO_DNSSEC;
6109742fdb4Schristos } else if ((ctx->options & DST_TYPE_KEY) == 0 &&
6119742fdb4Schristos ctx->protocol != DNS_KEYPROTO_DNSSEC)
6129742fdb4Schristos {
6139742fdb4Schristos fatal("invalid DNSKEY protocol: %d", ctx->protocol);
6149742fdb4Schristos }
615e2b1b9c0Schristos
616e2b1b9c0Schristos if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
6179742fdb4Schristos if (ctx->size > 0) {
618e2b1b9c0Schristos fatal("specified null key with non-zero size");
6199742fdb4Schristos }
6209742fdb4Schristos if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0) {
621e2b1b9c0Schristos fatal("specified null key with signing authority");
622e2b1b9c0Schristos }
6239742fdb4Schristos }
624e2b1b9c0Schristos
625e2b1b9c0Schristos if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
6269742fdb4Schristos ctx->alg == DNS_KEYALG_DH)
627f2e20987Schristos {
6289742fdb4Schristos fatal("a key with algorithm %s cannot be a zone key", algstr);
629f2e20987Schristos }
630e2b1b9c0Schristos
6319742fdb4Schristos switch (ctx->alg) {
632e2b1b9c0Schristos case DNS_KEYALG_RSASHA1:
633e2b1b9c0Schristos case DNS_KEYALG_NSEC3RSASHA1:
634e2b1b9c0Schristos case DNS_KEYALG_RSASHA256:
635e2b1b9c0Schristos case DNS_KEYALG_RSASHA512:
636f2e20987Schristos show_progress = true;
637e2b1b9c0Schristos break;
638e2b1b9c0Schristos
639e2b1b9c0Schristos case DNS_KEYALG_DH:
6409742fdb4Schristos param = ctx->generator;
641e2b1b9c0Schristos break;
642e2b1b9c0Schristos
643e2b1b9c0Schristos case DST_ALG_ECDSA256:
644e2b1b9c0Schristos case DST_ALG_ECDSA384:
645e2b1b9c0Schristos case DST_ALG_ED25519:
646e2b1b9c0Schristos case DST_ALG_ED448:
647f2e20987Schristos show_progress = true;
648e2b1b9c0Schristos break;
649e2b1b9c0Schristos }
650e2b1b9c0Schristos
6519742fdb4Schristos if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
652f2e20987Schristos null_key = true;
6539742fdb4Schristos }
654e2b1b9c0Schristos
655e2b1b9c0Schristos isc_buffer_init(&buf, filename, sizeof(filename) - 1);
656e2b1b9c0Schristos
657e2b1b9c0Schristos do {
658f2e20987Schristos conflict = false;
659e2b1b9c0Schristos
6609742fdb4Schristos if (!ctx->quiet && show_progress) {
661e2b1b9c0Schristos fprintf(stderr, "Generating key pair.");
6629742fdb4Schristos ret = dst_key_generate(name, ctx->alg, ctx->size, param,
6639742fdb4Schristos flags, ctx->protocol,
6649742fdb4Schristos ctx->rdclass, mctx, &key,
665e2b1b9c0Schristos &progress);
666e2b1b9c0Schristos putc('\n', stderr);
667e2b1b9c0Schristos fflush(stderr);
668e2b1b9c0Schristos } else {
6699742fdb4Schristos ret = dst_key_generate(name, ctx->alg, ctx->size, param,
6709742fdb4Schristos flags, ctx->protocol,
6719742fdb4Schristos ctx->rdclass, mctx, &key, NULL);
672e2b1b9c0Schristos }
673e2b1b9c0Schristos
674e2b1b9c0Schristos if (ret != ISC_R_SUCCESS) {
675e2b1b9c0Schristos char namestr[DNS_NAME_FORMATSIZE];
676e2b1b9c0Schristos dns_name_format(name, namestr, sizeof(namestr));
6779742fdb4Schristos fatal("failed to generate key %s/%s: %s\n", namestr,
6789742fdb4Schristos algstr, isc_result_totext(ret));
679e2b1b9c0Schristos }
680e2b1b9c0Schristos
6819742fdb4Schristos dst_key_setbits(key, ctx->dbits);
682e2b1b9c0Schristos
683e2b1b9c0Schristos /*
684e2b1b9c0Schristos * Set key timing metadata (unless using -C)
685e2b1b9c0Schristos *
686e2b1b9c0Schristos * Creation date is always set to "now".
687e2b1b9c0Schristos *
688e2b1b9c0Schristos * For a new key without an explicit predecessor, publish
689e2b1b9c0Schristos * and activation dates are set to "now" by default, but
690e2b1b9c0Schristos * can both be overridden.
691e2b1b9c0Schristos *
692e2b1b9c0Schristos * For a successor key, activation is set to match the
693e2b1b9c0Schristos * predecessor's inactivation date. Publish is set to 30
694e2b1b9c0Schristos * days earlier than that (XXX: this should be configurable).
695e2b1b9c0Schristos * If either of the resulting dates are in the past, that's
696e2b1b9c0Schristos * an error; the inactivation date of the predecessor key
697e2b1b9c0Schristos * must be updated before a successor key can be created.
698e2b1b9c0Schristos */
6999742fdb4Schristos if (!ctx->oldstyle) {
7009742fdb4Schristos dst_key_settime(key, DST_TIME_CREATED, ctx->now);
701e2b1b9c0Schristos
7029742fdb4Schristos if (ctx->genonly && (ctx->setpub || ctx->setact)) {
703e2b1b9c0Schristos fatal("cannot use -G together with "
704e2b1b9c0Schristos "-P or -A options");
7059742fdb4Schristos }
706e2b1b9c0Schristos
7079742fdb4Schristos if (ctx->setpub) {
708e2b1b9c0Schristos dst_key_settime(key, DST_TIME_PUBLISH,
7099742fdb4Schristos ctx->publish);
7109742fdb4Schristos } else if (ctx->setact && !ctx->unsetpub) {
7119742fdb4Schristos dst_key_settime(key, DST_TIME_PUBLISH,
7129742fdb4Schristos ctx->activate - ctx->prepub);
7139742fdb4Schristos } else if (!ctx->genonly && !ctx->unsetpub) {
7149742fdb4Schristos dst_key_settime(key, DST_TIME_PUBLISH,
7159742fdb4Schristos ctx->now);
7169742fdb4Schristos }
717e2b1b9c0Schristos
7189742fdb4Schristos if (ctx->setact) {
719e2b1b9c0Schristos dst_key_settime(key, DST_TIME_ACTIVATE,
7209742fdb4Schristos ctx->activate);
7219742fdb4Schristos } else if (!ctx->genonly && !ctx->unsetact) {
7229742fdb4Schristos dst_key_settime(key, DST_TIME_ACTIVATE,
7239742fdb4Schristos ctx->now);
7249742fdb4Schristos }
725e2b1b9c0Schristos
7269742fdb4Schristos if (ctx->setrev) {
7279742fdb4Schristos if (ctx->kskflag == 0) {
7289742fdb4Schristos fprintf(stderr,
7299742fdb4Schristos "%s: warning: Key is "
730e2b1b9c0Schristos "not flagged as a KSK, but -R "
731e2b1b9c0Schristos "was used. Revoking a ZSK is "
732e2b1b9c0Schristos "legal, but undefined.\n",
733e2b1b9c0Schristos program);
7349742fdb4Schristos }
7359742fdb4Schristos dst_key_settime(key, DST_TIME_REVOKE,
7369742fdb4Schristos ctx->revokekey);
737e2b1b9c0Schristos }
738e2b1b9c0Schristos
7399742fdb4Schristos if (ctx->setinact) {
740e2b1b9c0Schristos dst_key_settime(key, DST_TIME_INACTIVE,
7419742fdb4Schristos ctx->inactive);
7429742fdb4Schristos }
743e2b1b9c0Schristos
7449742fdb4Schristos if (ctx->setdel) {
7459742fdb4Schristos if (ctx->setinact &&
746*4ac1c27eSchristos ctx->deltime < ctx->inactive)
747*4ac1c27eSchristos {
7489742fdb4Schristos fprintf(stderr,
7499742fdb4Schristos "%s: warning: Key is "
750e2b1b9c0Schristos "scheduled to be deleted "
751e2b1b9c0Schristos "before it is scheduled to be "
752e2b1b9c0Schristos "made inactive.\n",
753e2b1b9c0Schristos program);
7549742fdb4Schristos }
7559742fdb4Schristos dst_key_settime(key, DST_TIME_DELETE,
7569742fdb4Schristos ctx->deltime);
757e2b1b9c0Schristos }
758e2b1b9c0Schristos
7599742fdb4Schristos if (ctx->setsyncadd) {
760e2b1b9c0Schristos dst_key_settime(key, DST_TIME_SYNCPUBLISH,
7619742fdb4Schristos ctx->syncadd);
7629742fdb4Schristos }
763e2b1b9c0Schristos
7649742fdb4Schristos if (ctx->setsyncdel) {
765e2b1b9c0Schristos dst_key_settime(key, DST_TIME_SYNCDELETE,
7669742fdb4Schristos ctx->syncdel);
7679742fdb4Schristos }
768e2b1b9c0Schristos } else {
7699742fdb4Schristos if (ctx->setpub || ctx->setact || ctx->setrev ||
7709742fdb4Schristos ctx->setinact || ctx->setdel || ctx->unsetpub ||
7719742fdb4Schristos ctx->unsetact || ctx->unsetrev || ctx->unsetinact ||
7729742fdb4Schristos ctx->unsetdel || ctx->genonly || ctx->setsyncadd ||
7739742fdb4Schristos ctx->setsyncdel)
7749742fdb4Schristos {
775e2b1b9c0Schristos fatal("cannot use -C together with "
776e2b1b9c0Schristos "-P, -A, -R, -I, -D, or -G options");
7779742fdb4Schristos }
778e2b1b9c0Schristos /*
779e2b1b9c0Schristos * Compatibility mode: Private-key-format
780e2b1b9c0Schristos * should be set to 1.2.
781e2b1b9c0Schristos */
782e2b1b9c0Schristos dst_key_setprivateformat(key, 1, 2);
783e2b1b9c0Schristos }
784e2b1b9c0Schristos
785e2b1b9c0Schristos /* Set the default key TTL */
7869742fdb4Schristos if (ctx->setttl) {
7879742fdb4Schristos dst_key_setttl(key, ctx->ttl);
7889742fdb4Schristos }
7899742fdb4Schristos
7909742fdb4Schristos /* Set dnssec-policy related metadata */
79173584a28Schristos if (ctx->policy != NULL) {
7929742fdb4Schristos dst_key_setnum(key, DST_NUM_LIFETIME, ctx->lifetime);
7939742fdb4Schristos dst_key_setbool(key, DST_BOOL_KSK, ctx->ksk);
7949742fdb4Schristos dst_key_setbool(key, DST_BOOL_ZSK, ctx->zsk);
7959742fdb4Schristos }
796e2b1b9c0Schristos
797e2b1b9c0Schristos /*
798e2b1b9c0Schristos * Do not overwrite an existing key, or create a key
799e2b1b9c0Schristos * if there is a risk of ID collision due to this key
800e2b1b9c0Schristos * or another key being revoked.
801e2b1b9c0Schristos */
8029742fdb4Schristos if (key_collision(key, name, ctx->directory, mctx, NULL)) {
803f2e20987Schristos conflict = true;
804e2b1b9c0Schristos if (null_key) {
805e2b1b9c0Schristos dst_key_free(&key);
806e2b1b9c0Schristos break;
807e2b1b9c0Schristos }
808e2b1b9c0Schristos
809e2b1b9c0Schristos if (verbose > 0) {
810e2b1b9c0Schristos isc_buffer_clear(&buf);
8119742fdb4Schristos ret = dst_key_buildfilename(
8129742fdb4Schristos key, 0, ctx->directory, &buf);
8139742fdb4Schristos if (ret == ISC_R_SUCCESS) {
814e2b1b9c0Schristos fprintf(stderr,
815e2b1b9c0Schristos "%s: %s already exists, or "
816e2b1b9c0Schristos "might collide with another "
817e2b1b9c0Schristos "key upon revokation. "
818e2b1b9c0Schristos "Generating a new key\n",
819e2b1b9c0Schristos program, filename);
820e2b1b9c0Schristos }
8219742fdb4Schristos }
822e2b1b9c0Schristos
823e2b1b9c0Schristos dst_key_free(&key);
824e2b1b9c0Schristos }
825803e9293Schristos } while (conflict);
826e2b1b9c0Schristos
8279742fdb4Schristos if (conflict) {
828e2b1b9c0Schristos fatal("cannot generate a null key due to possible key ID "
829e2b1b9c0Schristos "collision");
8309742fdb4Schristos }
831e2b1b9c0Schristos
8329742fdb4Schristos if (ctx->predecessor != NULL && prevkey != NULL) {
8339742fdb4Schristos dst_key_setnum(prevkey, DST_NUM_SUCCESSOR, dst_key_id(key));
8349742fdb4Schristos dst_key_setnum(key, DST_NUM_PREDECESSOR, dst_key_id(prevkey));
8359742fdb4Schristos
8369742fdb4Schristos ret = dst_key_tofile(prevkey, ctx->options, ctx->directory);
8379742fdb4Schristos if (ret != ISC_R_SUCCESS) {
8389742fdb4Schristos char keystr[DST_KEY_FORMATSIZE];
8399742fdb4Schristos dst_key_format(prevkey, keystr, sizeof(keystr));
8409742fdb4Schristos fatal("failed to update predecessor %s: %s\n", keystr,
8419742fdb4Schristos isc_result_totext(ret));
8429742fdb4Schristos }
8439742fdb4Schristos }
8449742fdb4Schristos
8459742fdb4Schristos ret = dst_key_tofile(key, ctx->options, ctx->directory);
846e2b1b9c0Schristos if (ret != ISC_R_SUCCESS) {
847e2b1b9c0Schristos char keystr[DST_KEY_FORMATSIZE];
848e2b1b9c0Schristos dst_key_format(key, keystr, sizeof(keystr));
849e2b1b9c0Schristos fatal("failed to write key %s: %s\n", keystr,
850e2b1b9c0Schristos isc_result_totext(ret));
851e2b1b9c0Schristos }
852e2b1b9c0Schristos
853e2b1b9c0Schristos isc_buffer_clear(&buf);
854e2b1b9c0Schristos ret = dst_key_buildfilename(key, 0, NULL, &buf);
8559742fdb4Schristos if (ret != ISC_R_SUCCESS) {
856e2b1b9c0Schristos fatal("dst_key_buildfilename returned: %s\n",
857e2b1b9c0Schristos isc_result_totext(ret));
8589742fdb4Schristos }
859e2b1b9c0Schristos printf("%s\n", filename);
860e2b1b9c0Schristos
8619742fdb4Schristos dst_key_free(&key);
8629742fdb4Schristos if (prevkey != NULL) {
8639742fdb4Schristos dst_key_free(&prevkey);
8649742fdb4Schristos }
8659742fdb4Schristos }
8669742fdb4Schristos
8679742fdb4Schristos int
main(int argc,char ** argv)8689742fdb4Schristos main(int argc, char **argv) {
8699742fdb4Schristos char *algname = NULL, *freeit = NULL;
8709742fdb4Schristos char *classname = NULL;
8719742fdb4Schristos char *endp;
8729742fdb4Schristos isc_mem_t *mctx = NULL;
8739742fdb4Schristos isc_result_t ret;
8749742fdb4Schristos isc_textregion_t r;
8759742fdb4Schristos const char *engine = NULL;
8769742fdb4Schristos unsigned char c;
8779742fdb4Schristos int ch;
8789742fdb4Schristos
8799742fdb4Schristos keygen_ctx_t ctx = {
8809742fdb4Schristos .options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC,
8819742fdb4Schristos .prepub = -1,
8829742fdb4Schristos .protocol = -1,
8839742fdb4Schristos .size = -1,
8849742fdb4Schristos };
8859742fdb4Schristos
8869742fdb4Schristos if (argc == 1) {
8879742fdb4Schristos usage();
8889742fdb4Schristos }
8899742fdb4Schristos
8909742fdb4Schristos #if USE_PKCS11
8919742fdb4Schristos pk11_result_register();
8929742fdb4Schristos #endif /* if USE_PKCS11 */
8939742fdb4Schristos dns_result_register();
8949742fdb4Schristos
8959742fdb4Schristos isc_commandline_errprint = false;
8969742fdb4Schristos
8979742fdb4Schristos /*
8989742fdb4Schristos * Process memory debugging argument first.
8999742fdb4Schristos */
9009742fdb4Schristos #define CMDLINE_FLAGS \
9019742fdb4Schristos "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:k:L:l:m:n:P:p:qR:r:S:s:" \
9029742fdb4Schristos "T:t:v:V"
9039742fdb4Schristos while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
9049742fdb4Schristos switch (ch) {
9059742fdb4Schristos case 'm':
9069742fdb4Schristos if (strcasecmp(isc_commandline_argument, "record") == 0)
9079742fdb4Schristos {
9089742fdb4Schristos isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
9099742fdb4Schristos }
9109742fdb4Schristos if (strcasecmp(isc_commandline_argument, "trace") == 0)
9119742fdb4Schristos {
9129742fdb4Schristos isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
9139742fdb4Schristos }
9149742fdb4Schristos if (strcasecmp(isc_commandline_argument, "usage") == 0)
9159742fdb4Schristos {
9169742fdb4Schristos isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
9179742fdb4Schristos }
9189742fdb4Schristos if (strcasecmp(isc_commandline_argument, "size") == 0) {
9199742fdb4Schristos isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
9209742fdb4Schristos }
9219742fdb4Schristos if (strcasecmp(isc_commandline_argument, "mctx") == 0) {
9229742fdb4Schristos isc_mem_debugging |= ISC_MEM_DEBUGCTX;
9239742fdb4Schristos }
9249742fdb4Schristos break;
9259742fdb4Schristos default:
9269742fdb4Schristos break;
9279742fdb4Schristos }
9289742fdb4Schristos }
9299742fdb4Schristos isc_commandline_reset = true;
9309742fdb4Schristos
9319742fdb4Schristos isc_mem_create(&mctx);
9329742fdb4Schristos isc_stdtime_get(&ctx.now);
9339742fdb4Schristos
9349742fdb4Schristos while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
9359742fdb4Schristos switch (ch) {
9369742fdb4Schristos case '3':
9379742fdb4Schristos ctx.use_nsec3 = true;
9389742fdb4Schristos break;
9399742fdb4Schristos case 'a':
9409742fdb4Schristos algname = isc_commandline_argument;
9419742fdb4Schristos break;
9429742fdb4Schristos case 'b':
9439742fdb4Schristos ctx.size = strtol(isc_commandline_argument, &endp, 10);
9449742fdb4Schristos if (*endp != '\0' || ctx.size < 0) {
9459742fdb4Schristos fatal("-b requires a non-negative number");
9469742fdb4Schristos }
9479742fdb4Schristos break;
9489742fdb4Schristos case 'C':
9499742fdb4Schristos ctx.oldstyle = true;
9509742fdb4Schristos break;
9519742fdb4Schristos case 'c':
9529742fdb4Schristos classname = isc_commandline_argument;
9539742fdb4Schristos break;
9549742fdb4Schristos case 'd':
9559742fdb4Schristos ctx.dbits = strtol(isc_commandline_argument, &endp, 10);
9569742fdb4Schristos if (*endp != '\0' || ctx.dbits < 0) {
9579742fdb4Schristos fatal("-d requires a non-negative number");
9589742fdb4Schristos }
9599742fdb4Schristos break;
9609742fdb4Schristos case 'E':
9619742fdb4Schristos engine = isc_commandline_argument;
9629742fdb4Schristos break;
9639742fdb4Schristos case 'e':
9649742fdb4Schristos fprintf(stderr, "phased-out option -e "
9659742fdb4Schristos "(was 'use (RSA) large exponent')\n");
9669742fdb4Schristos break;
9679742fdb4Schristos case 'f':
9689742fdb4Schristos c = (unsigned char)(isc_commandline_argument[0]);
9699742fdb4Schristos if (toupper(c) == 'K') {
9709742fdb4Schristos ctx.kskflag = DNS_KEYFLAG_KSK;
9719742fdb4Schristos } else if (toupper(c) == 'R') {
9729742fdb4Schristos ctx.revflag = DNS_KEYFLAG_REVOKE;
9739742fdb4Schristos } else {
9749742fdb4Schristos fatal("unknown flag '%s'",
9759742fdb4Schristos isc_commandline_argument);
9769742fdb4Schristos }
9779742fdb4Schristos break;
9789742fdb4Schristos case 'g':
9799742fdb4Schristos ctx.generator = strtol(isc_commandline_argument, &endp,
9809742fdb4Schristos 10);
9819742fdb4Schristos if (*endp != '\0' || ctx.generator <= 0) {
9829742fdb4Schristos fatal("-g requires a positive number");
9839742fdb4Schristos }
9849742fdb4Schristos break;
9859742fdb4Schristos case 'K':
9869742fdb4Schristos ctx.directory = isc_commandline_argument;
9879742fdb4Schristos ret = try_dir(ctx.directory);
9889742fdb4Schristos if (ret != ISC_R_SUCCESS) {
9899742fdb4Schristos fatal("cannot open directory %s: %s",
9909742fdb4Schristos ctx.directory, isc_result_totext(ret));
9919742fdb4Schristos }
9929742fdb4Schristos break;
9939742fdb4Schristos case 'k':
9949742fdb4Schristos ctx.policy = isc_commandline_argument;
9959742fdb4Schristos break;
9969742fdb4Schristos case 'L':
9979742fdb4Schristos ctx.ttl = strtottl(isc_commandline_argument);
9989742fdb4Schristos ctx.setttl = true;
9999742fdb4Schristos break;
10009742fdb4Schristos case 'l':
10019742fdb4Schristos ctx.configfile = isc_commandline_argument;
10029742fdb4Schristos break;
10039742fdb4Schristos case 'n':
10049742fdb4Schristos ctx.nametype = isc_commandline_argument;
10059742fdb4Schristos break;
10069742fdb4Schristos case 'm':
10079742fdb4Schristos break;
10089742fdb4Schristos case 'p':
10099742fdb4Schristos ctx.protocol = strtol(isc_commandline_argument, &endp,
10109742fdb4Schristos 10);
10119742fdb4Schristos if (*endp != '\0' || ctx.protocol < 0 ||
1012*4ac1c27eSchristos ctx.protocol > 255)
1013*4ac1c27eSchristos {
10149742fdb4Schristos fatal("-p must be followed by a number "
10159742fdb4Schristos "[0..255]");
10169742fdb4Schristos }
10179742fdb4Schristos break;
10189742fdb4Schristos case 'q':
10199742fdb4Schristos ctx.quiet = true;
10209742fdb4Schristos break;
10219742fdb4Schristos case 'r':
10229742fdb4Schristos fatal("The -r option has been deprecated.\n"
10239742fdb4Schristos "System random data is always used.\n");
10249742fdb4Schristos break;
10259742fdb4Schristos case 's':
10269742fdb4Schristos ctx.signatory = strtol(isc_commandline_argument, &endp,
10279742fdb4Schristos 10);
10289742fdb4Schristos if (*endp != '\0' || ctx.signatory < 0 ||
1029*4ac1c27eSchristos ctx.signatory > 15)
1030*4ac1c27eSchristos {
10319742fdb4Schristos fatal("-s must be followed by a number "
10329742fdb4Schristos "[0..15]");
10339742fdb4Schristos }
10349742fdb4Schristos break;
10359742fdb4Schristos case 'T':
10369742fdb4Schristos if (strcasecmp(isc_commandline_argument, "KEY") == 0) {
10379742fdb4Schristos ctx.options |= DST_TYPE_KEY;
10389742fdb4Schristos } else if (strcasecmp(isc_commandline_argument,
10399742fdb4Schristos "DNSKE"
10409742fdb4Schristos "Y") == 0)
10419742fdb4Schristos {
10429742fdb4Schristos /* default behavior */
10439742fdb4Schristos } else {
10449742fdb4Schristos fatal("unknown type '%s'",
10459742fdb4Schristos isc_commandline_argument);
10469742fdb4Schristos }
10479742fdb4Schristos break;
10489742fdb4Schristos case 't':
10499742fdb4Schristos ctx.type = isc_commandline_argument;
10509742fdb4Schristos break;
10519742fdb4Schristos case 'v':
10529742fdb4Schristos endp = NULL;
10539742fdb4Schristos verbose = strtol(isc_commandline_argument, &endp, 0);
10549742fdb4Schristos if (*endp != '\0') {
10559742fdb4Schristos fatal("-v must be followed by a number");
10569742fdb4Schristos }
10579742fdb4Schristos break;
10589742fdb4Schristos case 'G':
10599742fdb4Schristos ctx.genonly = true;
10609742fdb4Schristos break;
10619742fdb4Schristos case 'P':
10629742fdb4Schristos /* -Psync ? */
10639742fdb4Schristos if (isoptarg("sync", argv, usage)) {
10649742fdb4Schristos if (ctx.setsyncadd) {
10659742fdb4Schristos fatal("-P sync specified more than "
10669742fdb4Schristos "once");
10679742fdb4Schristos }
10689742fdb4Schristos
10699742fdb4Schristos ctx.syncadd = strtotime(
10709742fdb4Schristos isc_commandline_argument, ctx.now,
10719742fdb4Schristos ctx.now, &ctx.setsyncadd);
10729742fdb4Schristos break;
10739742fdb4Schristos }
10749742fdb4Schristos (void)isoptarg("dnskey", argv, usage);
10759742fdb4Schristos if (ctx.setpub || ctx.unsetpub) {
10769742fdb4Schristos fatal("-P specified more than once");
10779742fdb4Schristos }
10789742fdb4Schristos
10799742fdb4Schristos ctx.publish = strtotime(isc_commandline_argument,
10809742fdb4Schristos ctx.now, ctx.now, &ctx.setpub);
10819742fdb4Schristos ctx.unsetpub = !ctx.setpub;
10829742fdb4Schristos break;
10839742fdb4Schristos case 'A':
10849742fdb4Schristos if (ctx.setact || ctx.unsetact) {
10859742fdb4Schristos fatal("-A specified more than once");
10869742fdb4Schristos }
10879742fdb4Schristos
10889742fdb4Schristos ctx.activate = strtotime(isc_commandline_argument,
10899742fdb4Schristos ctx.now, ctx.now, &ctx.setact);
10909742fdb4Schristos ctx.unsetact = !ctx.setact;
10919742fdb4Schristos break;
10929742fdb4Schristos case 'R':
10939742fdb4Schristos if (ctx.setrev || ctx.unsetrev) {
10949742fdb4Schristos fatal("-R specified more than once");
10959742fdb4Schristos }
10969742fdb4Schristos
10979742fdb4Schristos ctx.revokekey = strtotime(isc_commandline_argument,
10989742fdb4Schristos ctx.now, ctx.now,
10999742fdb4Schristos &ctx.setrev);
11009742fdb4Schristos ctx.unsetrev = !ctx.setrev;
11019742fdb4Schristos break;
11029742fdb4Schristos case 'I':
11039742fdb4Schristos if (ctx.setinact || ctx.unsetinact) {
11049742fdb4Schristos fatal("-I specified more than once");
11059742fdb4Schristos }
11069742fdb4Schristos
11079742fdb4Schristos ctx.inactive = strtotime(isc_commandline_argument,
11089742fdb4Schristos ctx.now, ctx.now,
11099742fdb4Schristos &ctx.setinact);
11109742fdb4Schristos ctx.unsetinact = !ctx.setinact;
11119742fdb4Schristos break;
11129742fdb4Schristos case 'D':
11139742fdb4Schristos /* -Dsync ? */
11149742fdb4Schristos if (isoptarg("sync", argv, usage)) {
11159742fdb4Schristos if (ctx.setsyncdel) {
11169742fdb4Schristos fatal("-D sync specified more than "
11179742fdb4Schristos "once");
11189742fdb4Schristos }
11199742fdb4Schristos
11209742fdb4Schristos ctx.syncdel = strtotime(
11219742fdb4Schristos isc_commandline_argument, ctx.now,
11229742fdb4Schristos ctx.now, &ctx.setsyncdel);
11239742fdb4Schristos break;
11249742fdb4Schristos }
11259742fdb4Schristos (void)isoptarg("dnskey", argv, usage);
11269742fdb4Schristos if (ctx.setdel || ctx.unsetdel) {
11279742fdb4Schristos fatal("-D specified more than once");
11289742fdb4Schristos }
11299742fdb4Schristos
11309742fdb4Schristos ctx.deltime = strtotime(isc_commandline_argument,
11319742fdb4Schristos ctx.now, ctx.now, &ctx.setdel);
11329742fdb4Schristos ctx.unsetdel = !ctx.setdel;
11339742fdb4Schristos break;
11349742fdb4Schristos case 'S':
11359742fdb4Schristos ctx.predecessor = isc_commandline_argument;
11369742fdb4Schristos break;
11379742fdb4Schristos case 'i':
11389742fdb4Schristos ctx.prepub = strtottl(isc_commandline_argument);
11399742fdb4Schristos break;
11409742fdb4Schristos case 'F':
11419742fdb4Schristos /* Reserved for FIPS mode */
1142c0b5d9fbSchristos FALLTHROUGH;
11439742fdb4Schristos case '?':
11449742fdb4Schristos if (isc_commandline_option != '?') {
11459742fdb4Schristos fprintf(stderr, "%s: invalid argument -%c\n",
11469742fdb4Schristos program, isc_commandline_option);
11479742fdb4Schristos }
1148c0b5d9fbSchristos FALLTHROUGH;
11499742fdb4Schristos case 'h':
11509742fdb4Schristos /* Does not return. */
11519742fdb4Schristos usage();
11529742fdb4Schristos
11539742fdb4Schristos case 'V':
11549742fdb4Schristos /* Does not return. */
11559742fdb4Schristos version(program);
11569742fdb4Schristos
11579742fdb4Schristos default:
11589742fdb4Schristos fprintf(stderr, "%s: unhandled option -%c\n", program,
11599742fdb4Schristos isc_commandline_option);
11609742fdb4Schristos exit(1);
11619742fdb4Schristos }
11629742fdb4Schristos }
11639742fdb4Schristos
11649742fdb4Schristos if (!isatty(0)) {
11659742fdb4Schristos ctx.quiet = true;
11669742fdb4Schristos }
11679742fdb4Schristos
11689742fdb4Schristos ret = dst_lib_init(mctx, engine);
11699742fdb4Schristos if (ret != ISC_R_SUCCESS) {
11709742fdb4Schristos fatal("could not initialize dst: %s", isc_result_totext(ret));
11719742fdb4Schristos }
11729742fdb4Schristos
11739742fdb4Schristos setup_logging(mctx, &lctx);
11749742fdb4Schristos
11759742fdb4Schristos ctx.rdclass = strtoclass(classname);
11769742fdb4Schristos
11779742fdb4Schristos if (ctx.configfile == NULL || ctx.configfile[0] == '\0') {
11789742fdb4Schristos ctx.configfile = NAMED_CONFFILE;
11799742fdb4Schristos }
11809742fdb4Schristos
11819742fdb4Schristos if (ctx.predecessor == NULL) {
11829742fdb4Schristos if (argc < isc_commandline_index + 1) {
11839742fdb4Schristos fatal("the key name was not specified");
11849742fdb4Schristos }
11859742fdb4Schristos if (argc > isc_commandline_index + 1) {
11869742fdb4Schristos fatal("extraneous arguments");
11879742fdb4Schristos }
11889742fdb4Schristos }
11899742fdb4Schristos
11909742fdb4Schristos if (ctx.predecessor == NULL && ctx.policy == NULL) {
11919742fdb4Schristos if (algname == NULL) {
11929742fdb4Schristos fatal("no algorithm specified");
11939742fdb4Schristos }
11949742fdb4Schristos r.base = algname;
11959742fdb4Schristos r.length = strlen(algname);
11969742fdb4Schristos ret = dns_secalg_fromtext(&ctx.alg, &r);
11979742fdb4Schristos if (ret != ISC_R_SUCCESS) {
11989742fdb4Schristos fatal("unknown algorithm %s", algname);
11999742fdb4Schristos }
12009742fdb4Schristos if (!dst_algorithm_supported(ctx.alg)) {
12019742fdb4Schristos fatal("unsupported algorithm: %s", algname);
12029742fdb4Schristos }
12039742fdb4Schristos }
12049742fdb4Schristos
12059742fdb4Schristos if (ctx.policy != NULL) {
12069742fdb4Schristos if (ctx.nametype != NULL) {
12079742fdb4Schristos fatal("-k and -n cannot be used together");
12089742fdb4Schristos }
12099742fdb4Schristos if (ctx.predecessor != NULL) {
12109742fdb4Schristos fatal("-k and -S cannot be used together");
12119742fdb4Schristos }
12129742fdb4Schristos if (ctx.oldstyle) {
12139742fdb4Schristos fatal("-k and -C cannot be used together");
12149742fdb4Schristos }
12159742fdb4Schristos if (ctx.setttl) {
12169742fdb4Schristos fatal("-k and -L cannot be used together");
12179742fdb4Schristos }
12189742fdb4Schristos if (ctx.prepub > 0) {
12199742fdb4Schristos fatal("-k and -i cannot be used together");
12209742fdb4Schristos }
12219742fdb4Schristos if (ctx.size != -1) {
12229742fdb4Schristos fatal("-k and -b cannot be used together");
12239742fdb4Schristos }
12249742fdb4Schristos if (ctx.kskflag || ctx.revflag) {
12259742fdb4Schristos fatal("-k and -f cannot be used together");
12269742fdb4Schristos }
12279742fdb4Schristos if (ctx.options & DST_TYPE_KEY) {
12289742fdb4Schristos fatal("-k and -T KEY cannot be used together");
12299742fdb4Schristos }
12309742fdb4Schristos if (ctx.use_nsec3) {
12319742fdb4Schristos fatal("-k and -3 cannot be used together");
12329742fdb4Schristos }
12339742fdb4Schristos
12349742fdb4Schristos ctx.options |= DST_TYPE_STATE;
12359742fdb4Schristos
12369742fdb4Schristos if (strcmp(ctx.policy, "default") == 0) {
12379742fdb4Schristos ctx.use_nsec3 = false;
12389742fdb4Schristos ctx.alg = DST_ALG_ECDSA256;
12399742fdb4Schristos ctx.size = 0;
12409742fdb4Schristos ctx.kskflag = DNS_KEYFLAG_KSK;
12419742fdb4Schristos ctx.ttl = 3600;
12429742fdb4Schristos ctx.setttl = true;
12439742fdb4Schristos ctx.ksk = true;
12449742fdb4Schristos ctx.zsk = true;
12459742fdb4Schristos ctx.lifetime = 0;
12469742fdb4Schristos
12479742fdb4Schristos keygen(&ctx, mctx, argc, argv);
12489742fdb4Schristos } else {
12499742fdb4Schristos cfg_parser_t *parser = NULL;
12509742fdb4Schristos cfg_obj_t *config = NULL;
12519742fdb4Schristos dns_kasp_t *kasp = NULL;
12529742fdb4Schristos dns_kasp_key_t *kaspkey = NULL;
12539742fdb4Schristos
12549742fdb4Schristos RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &parser) ==
12559742fdb4Schristos ISC_R_SUCCESS);
12569742fdb4Schristos if (cfg_parse_file(parser, ctx.configfile,
12579742fdb4Schristos &cfg_type_namedconf,
12589742fdb4Schristos &config) != ISC_R_SUCCESS)
12599742fdb4Schristos {
12609742fdb4Schristos fatal("unable to load dnssec-policy '%s' from "
12619742fdb4Schristos "'%s'",
12629742fdb4Schristos ctx.policy, ctx.configfile);
12639742fdb4Schristos }
12649742fdb4Schristos
12659742fdb4Schristos kasp_from_conf(config, mctx, ctx.policy, &kasp);
12669742fdb4Schristos if (kasp == NULL) {
12679742fdb4Schristos fatal("failed to load dnssec-policy '%s'",
12689742fdb4Schristos ctx.policy);
12699742fdb4Schristos }
12709742fdb4Schristos if (ISC_LIST_EMPTY(dns_kasp_keys(kasp))) {
12719742fdb4Schristos fatal("dnssec-policy '%s' has no keys "
12729742fdb4Schristos "configured",
12739742fdb4Schristos ctx.policy);
12749742fdb4Schristos }
12759742fdb4Schristos
12769742fdb4Schristos ctx.ttl = dns_kasp_dnskeyttl(kasp);
12779742fdb4Schristos ctx.setttl = true;
12789742fdb4Schristos
12799742fdb4Schristos kaspkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
12809742fdb4Schristos
12819742fdb4Schristos while (kaspkey != NULL) {
12829742fdb4Schristos ctx.use_nsec3 = false;
12839742fdb4Schristos ctx.alg = dns_kasp_key_algorithm(kaspkey);
12849742fdb4Schristos ctx.size = dns_kasp_key_size(kaspkey);
12859742fdb4Schristos ctx.kskflag = dns_kasp_key_ksk(kaspkey)
12869742fdb4Schristos ? DNS_KEYFLAG_KSK
12879742fdb4Schristos : 0;
12889742fdb4Schristos ctx.ksk = dns_kasp_key_ksk(kaspkey);
12899742fdb4Schristos ctx.zsk = dns_kasp_key_zsk(kaspkey);
12909742fdb4Schristos ctx.lifetime = dns_kasp_key_lifetime(kaspkey);
12919742fdb4Schristos
12929742fdb4Schristos keygen(&ctx, mctx, argc, argv);
12939742fdb4Schristos
12949742fdb4Schristos kaspkey = ISC_LIST_NEXT(kaspkey, link);
12959742fdb4Schristos }
12969742fdb4Schristos
12979742fdb4Schristos dns_kasp_detach(&kasp);
12989742fdb4Schristos cfg_obj_destroy(parser, &config);
12999742fdb4Schristos cfg_parser_destroy(&parser);
13009742fdb4Schristos }
13019742fdb4Schristos } else {
13029742fdb4Schristos keygen(&ctx, mctx, argc, argv);
13039742fdb4Schristos }
13049742fdb4Schristos
13059742fdb4Schristos cleanup_logging(&lctx);
1306e2b1b9c0Schristos dst_lib_destroy();
13079742fdb4Schristos if (verbose > 10) {
1308e2b1b9c0Schristos isc_mem_stats(mctx, stdout);
13099742fdb4Schristos }
1310e2b1b9c0Schristos isc_mem_destroy(&mctx);
1311e2b1b9c0Schristos
13129742fdb4Schristos if (freeit != NULL) {
1313e2b1b9c0Schristos free(freeit);
13149742fdb4Schristos }
1315e2b1b9c0Schristos
1316e2b1b9c0Schristos return (0);
1317e2b1b9c0Schristos }
1318