xref: /netbsd-src/external/mpl/bind/dist/lib/dns/dst_api.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
1 /*	$NetBSD: dst_api.c,v 1.7 2020/08/03 17:23:41 christos Exp $	*/
2 
3 /*
4  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
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 http://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  *
13  * Portions Copyright (C) Network Associates, Inc.
14  *
15  * Permission to use, copy, modify, and/or distribute this software for any
16  * purpose with or without fee is hereby granted, provided that the above
17  * copyright notice and this permission notice appear in all copies.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
20  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
22  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
25  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26  */
27 
28 /*! \file */
29 
30 #include <inttypes.h>
31 #include <stdbool.h>
32 #include <stdlib.h>
33 #include <time.h>
34 
35 #include <isc/buffer.h>
36 #include <isc/dir.h>
37 #include <isc/file.h>
38 #include <isc/fsaccess.h>
39 #include <isc/lex.h>
40 #include <isc/mem.h>
41 #include <isc/once.h>
42 #include <isc/platform.h>
43 #include <isc/print.h>
44 #include <isc/random.h>
45 #include <isc/refcount.h>
46 #include <isc/safe.h>
47 #include <isc/string.h>
48 #include <isc/time.h>
49 #include <isc/util.h>
50 
51 #include <pk11/site.h>
52 
53 #define DST_KEY_INTERNAL
54 
55 #include <dns/fixedname.h>
56 #include <dns/keyvalues.h>
57 #include <dns/name.h>
58 #include <dns/rdata.h>
59 #include <dns/rdataclass.h>
60 #include <dns/ttl.h>
61 #include <dns/types.h>
62 
63 #include <dst/result.h>
64 
65 #include "dst_internal.h"
66 
67 #define DST_AS_STR(t) ((t).value.as_textregion.base)
68 
69 #define NEXTTOKEN(lex, opt, token)                       \
70 	{                                                \
71 		ret = isc_lex_gettoken(lex, opt, token); \
72 		if (ret != ISC_R_SUCCESS)                \
73 			goto cleanup;                    \
74 	}
75 
76 #define NEXTTOKEN_OR_EOF(lex, opt, token)                \
77 	do {                                             \
78 		ret = isc_lex_gettoken(lex, opt, token); \
79 		if (ret == ISC_R_EOF)                    \
80 			break;                           \
81 		if (ret != ISC_R_SUCCESS)                \
82 			goto cleanup;                    \
83 	} while ((*token).type == isc_tokentype_eol);
84 
85 #define READLINE(lex, opt, token)                        \
86 	do {                                             \
87 		ret = isc_lex_gettoken(lex, opt, token); \
88 		if (ret == ISC_R_EOF)                    \
89 			break;                           \
90 		if (ret != ISC_R_SUCCESS)                \
91 			goto cleanup;                    \
92 	} while ((*token).type != isc_tokentype_eol)
93 
94 #define BADTOKEN()                           \
95 	{                                    \
96 		ret = ISC_R_UNEXPECTEDTOKEN; \
97 		goto cleanup;                \
98 	}
99 
100 #define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1)
101 static const char *numerictags[NUMERIC_NTAGS] = {
102 	"Predecessor:", "Successor:", "MaxTTL:", "RollPeriod:", "Lifetime:"
103 };
104 
105 #define BOOLEAN_NTAGS (DST_MAX_BOOLEAN + 1)
106 static const char *booleantags[BOOLEAN_NTAGS] = { "KSK:", "ZSK:" };
107 
108 #define TIMING_NTAGS (DST_MAX_TIMES + 1)
109 static const char *timingtags[TIMING_NTAGS] = {
110 	"Generated:",	 "Published:",	  "Active:",	   "Revoked:",
111 	"Retired:",	 "Removed:",
112 
113 	"DSPublish:",	 "SyncPublish:",  "SyncDelete:",
114 
115 	"DNSKEYChange:", "ZRRSIGChange:", "KRRSIGChange:", "DSChange:"
116 };
117 
118 #define KEYSTATES_NTAGS (DST_MAX_KEYSTATES + 1)
119 static const char *keystatestags[KEYSTATES_NTAGS] = {
120 	"DNSKEYState:", "ZRRSIGState:", "KRRSIGState:", "DSState:", "GoalState:"
121 };
122 
123 #define KEYSTATES_NVALUES 4
124 static const char *keystates[KEYSTATES_NVALUES] = {
125 	"hidden",
126 	"rumoured",
127 	"omnipresent",
128 	"unretentive",
129 };
130 
131 #define STATE_ALGORITHM_STR "Algorithm:"
132 #define STATE_LENGTH_STR    "Length:"
133 #define MAX_NTAGS \
134 	(DST_MAX_NUMERIC + DST_MAX_BOOLEAN + DST_MAX_TIMES + DST_MAX_KEYSTATES)
135 
136 static dst_func_t *dst_t_func[DST_MAX_ALGS];
137 
138 static bool dst_initialized = false;
139 
140 void
141 gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
142 
143 /*
144  * Static functions.
145  */
146 static dst_key_t *
147 get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags,
148 	       unsigned int protocol, unsigned int bits,
149 	       dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx);
150 static isc_result_t
151 write_public_key(const dst_key_t *key, int type, const char *directory);
152 static isc_result_t
153 write_key_state(const dst_key_t *key, int type, const char *directory);
154 static isc_result_t
155 buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
156 	      unsigned int type, const char *directory, isc_buffer_t *out);
157 static isc_result_t
158 computeid(dst_key_t *key);
159 static isc_result_t
160 frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
161 	   unsigned int protocol, dns_rdataclass_t rdclass,
162 	   isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
163 
164 static isc_result_t
165 algorithm_status(unsigned int alg);
166 
167 static isc_result_t
168 addsuffix(char *filename, int len, const char *dirname, const char *ofilename,
169 	  const char *suffix);
170 
171 #define RETERR(x)                            \
172 	do {                                 \
173 		result = (x);                \
174 		if (result != ISC_R_SUCCESS) \
175 			goto out;            \
176 	} while (/*CONSTCOND*/0)
177 
178 #define CHECKALG(alg)                       \
179 	do {                                \
180 		isc_result_t _r;            \
181 		_r = algorithm_status(alg); \
182 		if (_r != ISC_R_SUCCESS)    \
183 			return ((_r));      \
184 	} while (/*CONSTCOND*/0)
185 
186 isc_result_t
187 dst_lib_init(isc_mem_t *mctx, const char *engine) {
188 	isc_result_t result;
189 
190 	REQUIRE(mctx != NULL);
191 	REQUIRE(!dst_initialized);
192 
193 	UNUSED(engine);
194 
195 	dst_result_register();
196 
197 	memset(dst_t_func, 0, sizeof(dst_t_func));
198 	RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
199 	RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
200 	RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
201 	RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
202 	RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
203 	RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
204 	RETERR(dst__openssl_init(mctx, engine));
205 	RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
206 #if USE_OPENSSL
207 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
208 				    DST_ALG_RSASHA1));
209 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1],
210 				    DST_ALG_NSEC3RSASHA1));
211 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256],
212 				    DST_ALG_RSASHA256));
213 	RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512],
214 				    DST_ALG_RSASHA512));
215 	RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
216 	RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
217 #ifdef HAVE_OPENSSL_ED25519
218 	RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED25519]));
219 #endif /* ifdef HAVE_OPENSSL_ED25519 */
220 #ifdef HAVE_OPENSSL_ED448
221 	RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448]));
222 #endif /* ifdef HAVE_OPENSSL_ED448 */
223 #endif /* USE_OPENSSL */
224 
225 #if USE_PKCS11
226 	RETERR(dst__pkcs11_init(mctx, engine));
227 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1]));
228 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
229 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256]));
230 	RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512]));
231 	RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
232 	RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
233 	RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED25519]));
234 	RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED448]));
235 #endif /* USE_PKCS11 */
236 #ifdef GSSAPI
237 	RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
238 #endif /* ifdef GSSAPI */
239 
240 	dst_initialized = true;
241 	return (ISC_R_SUCCESS);
242 
243 out:
244 	/* avoid immediate crash! */
245 	dst_initialized = true;
246 	dst_lib_destroy();
247 	return (result);
248 }
249 
250 void
251 dst_lib_destroy(void) {
252 	int i;
253 	RUNTIME_CHECK(dst_initialized);
254 	dst_initialized = false;
255 
256 	for (i = 0; i < DST_MAX_ALGS; i++) {
257 		if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL) {
258 			dst_t_func[i]->cleanup();
259 		}
260 	}
261 	dst__openssl_destroy();
262 #if USE_PKCS11
263 	(void)dst__pkcs11_destroy();
264 #endif /* USE_PKCS11 */
265 }
266 
267 bool
268 dst_algorithm_supported(unsigned int alg) {
269 	REQUIRE(dst_initialized);
270 
271 	if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) {
272 		return (false);
273 	}
274 	return (true);
275 }
276 
277 bool
278 dst_ds_digest_supported(unsigned int digest_type) {
279 	return (digest_type == DNS_DSDIGEST_SHA1 ||
280 		digest_type == DNS_DSDIGEST_SHA256 ||
281 		digest_type == DNS_DSDIGEST_SHA384);
282 }
283 
284 isc_result_t
285 dst_context_create(dst_key_t *key, isc_mem_t *mctx, isc_logcategory_t *category,
286 		   bool useforsigning, int maxbits, dst_context_t **dctxp) {
287 	dst_context_t *dctx;
288 	isc_result_t result;
289 
290 	REQUIRE(dst_initialized);
291 	REQUIRE(VALID_KEY(key));
292 	REQUIRE(mctx != NULL);
293 	REQUIRE(dctxp != NULL && *dctxp == NULL);
294 
295 	if (key->func->createctx == NULL && key->func->createctx2 == NULL) {
296 		return (DST_R_UNSUPPORTEDALG);
297 	}
298 	if (key->keydata.generic == NULL) {
299 		return (DST_R_NULLKEY);
300 	}
301 
302 	dctx = isc_mem_get(mctx, sizeof(dst_context_t));
303 	memset(dctx, 0, sizeof(*dctx));
304 	dst_key_attach(key, &dctx->key);
305 	isc_mem_attach(mctx, &dctx->mctx);
306 	dctx->category = category;
307 	if (useforsigning) {
308 		dctx->use = DO_SIGN;
309 	} else {
310 		dctx->use = DO_VERIFY;
311 	}
312 	if (key->func->createctx2 != NULL) {
313 		result = key->func->createctx2(key, maxbits, dctx);
314 	} else {
315 		result = key->func->createctx(key, dctx);
316 	}
317 	if (result != ISC_R_SUCCESS) {
318 		if (dctx->key != NULL) {
319 			dst_key_free(&dctx->key);
320 		}
321 		isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
322 		return (result);
323 	}
324 	dctx->magic = CTX_MAGIC;
325 	*dctxp = dctx;
326 	return (ISC_R_SUCCESS);
327 }
328 
329 void
330 dst_context_destroy(dst_context_t **dctxp) {
331 	dst_context_t *dctx;
332 
333 	REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
334 
335 	dctx = *dctxp;
336 	*dctxp = NULL;
337 	INSIST(dctx->key->func->destroyctx != NULL);
338 	dctx->key->func->destroyctx(dctx);
339 	if (dctx->key != NULL) {
340 		dst_key_free(&dctx->key);
341 	}
342 	dctx->magic = 0;
343 	isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t));
344 }
345 
346 isc_result_t
347 dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
348 	REQUIRE(VALID_CTX(dctx));
349 	REQUIRE(data != NULL);
350 	INSIST(dctx->key->func->adddata != NULL);
351 
352 	return (dctx->key->func->adddata(dctx, data));
353 }
354 
355 isc_result_t
356 dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
357 	dst_key_t *key;
358 
359 	REQUIRE(VALID_CTX(dctx));
360 	REQUIRE(sig != NULL);
361 
362 	key = dctx->key;
363 	CHECKALG(key->key_alg);
364 	if (key->keydata.generic == NULL) {
365 		return (DST_R_NULLKEY);
366 	}
367 
368 	if (key->func->sign == NULL) {
369 		return (DST_R_NOTPRIVATEKEY);
370 	}
371 	if (key->func->isprivate == NULL || !key->func->isprivate(key)) {
372 		return (DST_R_NOTPRIVATEKEY);
373 	}
374 
375 	return (key->func->sign(dctx, sig));
376 }
377 
378 isc_result_t
379 dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
380 	REQUIRE(VALID_CTX(dctx));
381 	REQUIRE(sig != NULL);
382 
383 	CHECKALG(dctx->key->key_alg);
384 	if (dctx->key->keydata.generic == NULL) {
385 		return (DST_R_NULLKEY);
386 	}
387 	if (dctx->key->func->verify == NULL) {
388 		return (DST_R_NOTPUBLICKEY);
389 	}
390 
391 	return (dctx->key->func->verify(dctx, sig));
392 }
393 
394 isc_result_t
395 dst_context_verify2(dst_context_t *dctx, unsigned int maxbits,
396 		    isc_region_t *sig) {
397 	REQUIRE(VALID_CTX(dctx));
398 	REQUIRE(sig != NULL);
399 
400 	CHECKALG(dctx->key->key_alg);
401 	if (dctx->key->keydata.generic == NULL) {
402 		return (DST_R_NULLKEY);
403 	}
404 	if (dctx->key->func->verify == NULL && dctx->key->func->verify2 == NULL)
405 	{
406 		return (DST_R_NOTPUBLICKEY);
407 	}
408 
409 	return (dctx->key->func->verify2 != NULL
410 			? dctx->key->func->verify2(dctx, maxbits, sig)
411 			: dctx->key->func->verify(dctx, sig));
412 }
413 
414 isc_result_t
415 dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
416 		      isc_buffer_t *secret) {
417 	REQUIRE(dst_initialized);
418 	REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
419 	REQUIRE(secret != NULL);
420 
421 	CHECKALG(pub->key_alg);
422 	CHECKALG(priv->key_alg);
423 
424 	if (pub->keydata.generic == NULL || priv->keydata.generic == NULL) {
425 		return (DST_R_NULLKEY);
426 	}
427 
428 	if (pub->key_alg != priv->key_alg || pub->func->computesecret == NULL ||
429 	    priv->func->computesecret == NULL)
430 	{
431 		return (DST_R_KEYCANNOTCOMPUTESECRET);
432 	}
433 
434 	if (!dst_key_isprivate(priv)) {
435 		return (DST_R_NOTPRIVATEKEY);
436 	}
437 
438 	return (pub->func->computesecret(pub, priv, secret));
439 }
440 
441 isc_result_t
442 dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
443 	isc_result_t ret = ISC_R_SUCCESS;
444 
445 	REQUIRE(dst_initialized);
446 	REQUIRE(VALID_KEY(key));
447 	REQUIRE((type &
448 		 (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0);
449 
450 	CHECKALG(key->key_alg);
451 
452 	if (key->func->tofile == NULL) {
453 		return (DST_R_UNSUPPORTEDALG);
454 	}
455 
456 	if ((type & DST_TYPE_PUBLIC) != 0) {
457 		ret = write_public_key(key, type, directory);
458 		if (ret != ISC_R_SUCCESS) {
459 			return (ret);
460 		}
461 	}
462 
463 	if ((type & DST_TYPE_STATE) != 0) {
464 		ret = write_key_state(key, type, directory);
465 		if (ret != ISC_R_SUCCESS) {
466 			return (ret);
467 		}
468 	}
469 
470 	if (((type & DST_TYPE_PRIVATE) != 0) &&
471 	    (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
472 	{
473 		return (key->func->tofile(key, directory));
474 	}
475 	return (ISC_R_SUCCESS);
476 }
477 
478 void
479 dst_key_setexternal(dst_key_t *key, bool value) {
480 	key->external = value;
481 }
482 
483 bool
484 dst_key_isexternal(dst_key_t *key) {
485 	return (key->external);
486 }
487 
488 isc_result_t
489 dst_key_getfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
490 		    int type, const char *directory, isc_mem_t *mctx,
491 		    isc_buffer_t *buf) {
492 	isc_result_t result;
493 
494 	REQUIRE(dst_initialized);
495 	REQUIRE(dns_name_isabsolute(name));
496 	REQUIRE((type &
497 		 (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0);
498 	REQUIRE(mctx != NULL);
499 	REQUIRE(buf != NULL);
500 
501 	CHECKALG(alg);
502 
503 	result = buildfilename(name, id, alg, type, directory, buf);
504 	if (result == ISC_R_SUCCESS) {
505 		if (isc_buffer_availablelength(buf) > 0) {
506 			isc_buffer_putuint8(buf, 0);
507 		} else {
508 			result = ISC_R_NOSPACE;
509 		}
510 	}
511 
512 	return (result);
513 }
514 
515 isc_result_t
516 dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type,
517 		 const char *directory, isc_mem_t *mctx, dst_key_t **keyp) {
518 	isc_result_t result;
519 	char filename[NAME_MAX];
520 	isc_buffer_t buf;
521 	dst_key_t *key;
522 
523 	REQUIRE(dst_initialized);
524 	REQUIRE(dns_name_isabsolute(name));
525 	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
526 	REQUIRE(mctx != NULL);
527 	REQUIRE(keyp != NULL && *keyp == NULL);
528 
529 	CHECKALG(alg);
530 
531 	key = NULL;
532 
533 	isc_buffer_init(&buf, filename, NAME_MAX);
534 	result = dst_key_getfilename(name, id, alg, type, NULL, mctx, &buf);
535 	if (result != ISC_R_SUCCESS) {
536 		goto out;
537 	}
538 
539 	result = dst_key_fromnamedfile(filename, directory, type, mctx, &key);
540 	if (result != ISC_R_SUCCESS) {
541 		goto out;
542 	}
543 
544 	result = computeid(key);
545 	if (result != ISC_R_SUCCESS) {
546 		goto out;
547 	}
548 
549 	if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
550 	    alg != key->key_alg)
551 	{
552 		result = DST_R_INVALIDPRIVATEKEY;
553 		goto out;
554 	}
555 
556 	*keyp = key;
557 	result = ISC_R_SUCCESS;
558 
559 out:
560 	if ((key != NULL) && (result != ISC_R_SUCCESS)) {
561 		dst_key_free(&key);
562 	}
563 
564 	return (result);
565 }
566 
567 isc_result_t
568 dst_key_fromnamedfile(const char *filename, const char *dirname, int type,
569 		      isc_mem_t *mctx, dst_key_t **keyp) {
570 	isc_result_t result;
571 	dst_key_t *pubkey = NULL, *key = NULL;
572 	char *newfilename = NULL;
573 	int newfilenamelen = 0;
574 	isc_lex_t *lex = NULL;
575 
576 	REQUIRE(dst_initialized);
577 	REQUIRE(filename != NULL);
578 	REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
579 	REQUIRE(mctx != NULL);
580 	REQUIRE(keyp != NULL && *keyp == NULL);
581 
582 	/* If an absolute path is specified, don't use the key directory */
583 #ifndef WIN32
584 	if (filename[0] == '/') {
585 		dirname = NULL;
586 	}
587 #else  /* WIN32 */
588 	if (filename[0] == '/' || filename[0] == '\\') {
589 		dirname = NULL;
590 	}
591 #endif /* ifndef WIN32 */
592 
593 	newfilenamelen = strlen(filename) + 5;
594 	if (dirname != NULL) {
595 		newfilenamelen += strlen(dirname) + 1;
596 	}
597 	newfilename = isc_mem_get(mctx, newfilenamelen);
598 	result = addsuffix(newfilename, newfilenamelen, dirname, filename,
599 			   ".key");
600 	INSIST(result == ISC_R_SUCCESS);
601 
602 	result = dst_key_read_public(newfilename, type, mctx, &pubkey);
603 	isc_mem_put(mctx, newfilename, newfilenamelen);
604 	newfilename = NULL;
605 	RETERR(result);
606 
607 	if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
608 	    (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
609 	{
610 		result = computeid(pubkey);
611 		if (result != ISC_R_SUCCESS) {
612 			dst_key_free(&pubkey);
613 			return (result);
614 		}
615 
616 		*keyp = pubkey;
617 		return (ISC_R_SUCCESS);
618 	}
619 
620 	result = algorithm_status(pubkey->key_alg);
621 	if (result != ISC_R_SUCCESS) {
622 		dst_key_free(&pubkey);
623 		return (result);
624 	}
625 
626 	key = get_key_struct(pubkey->key_name, pubkey->key_alg,
627 			     pubkey->key_flags, pubkey->key_proto,
628 			     pubkey->key_size, pubkey->key_class,
629 			     pubkey->key_ttl, mctx);
630 	if (key == NULL) {
631 		dst_key_free(&pubkey);
632 		return (ISC_R_NOMEMORY);
633 	}
634 
635 	if (key->func->parse == NULL) {
636 		RETERR(DST_R_UNSUPPORTEDALG);
637 	}
638 
639 	/*
640 	 * Read the state file, if requested by type.
641 	 */
642 	if ((type & DST_TYPE_STATE) != 0) {
643 		newfilenamelen = strlen(filename) + 7;
644 		if (dirname != NULL) {
645 			newfilenamelen += strlen(dirname) + 1;
646 		}
647 		newfilename = isc_mem_get(mctx, newfilenamelen);
648 		result = addsuffix(newfilename, newfilenamelen, dirname,
649 				   filename, ".state");
650 		INSIST(result == ISC_R_SUCCESS);
651 
652 		result = dst_key_read_state(newfilename, mctx, &key);
653 		if (result == ISC_R_FILENOTFOUND) {
654 			/* Having no state is valid. */
655 			result = ISC_R_SUCCESS;
656 		}
657 
658 		isc_mem_put(mctx, newfilename, newfilenamelen);
659 		newfilename = NULL;
660 		RETERR(result);
661 	}
662 
663 	newfilenamelen = strlen(filename) + 9;
664 	if (dirname != NULL) {
665 		newfilenamelen += strlen(dirname) + 1;
666 	}
667 	newfilename = isc_mem_get(mctx, newfilenamelen);
668 	result = addsuffix(newfilename, newfilenamelen, dirname, filename,
669 			   ".private");
670 	INSIST(result == ISC_R_SUCCESS);
671 
672 	RETERR(isc_lex_create(mctx, 1500, &lex));
673 	RETERR(isc_lex_openfile(lex, newfilename));
674 	isc_mem_put(mctx, newfilename, newfilenamelen);
675 
676 	RETERR(key->func->parse(key, lex, pubkey));
677 	isc_lex_destroy(&lex);
678 
679 	RETERR(computeid(key));
680 
681 	if (pubkey->key_id != key->key_id) {
682 		RETERR(DST_R_INVALIDPRIVATEKEY);
683 	}
684 	dst_key_free(&pubkey);
685 
686 	*keyp = key;
687 	return (ISC_R_SUCCESS);
688 
689 out:
690 	if (pubkey != NULL) {
691 		dst_key_free(&pubkey);
692 	}
693 	if (newfilename != NULL) {
694 		isc_mem_put(mctx, newfilename, newfilenamelen);
695 	}
696 	if (lex != NULL) {
697 		isc_lex_destroy(&lex);
698 	}
699 	if (key != NULL) {
700 		dst_key_free(&key);
701 	}
702 	return (result);
703 }
704 
705 isc_result_t
706 dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
707 	REQUIRE(dst_initialized);
708 	REQUIRE(VALID_KEY(key));
709 	REQUIRE(target != NULL);
710 
711 	CHECKALG(key->key_alg);
712 
713 	if (key->func->todns == NULL) {
714 		return (DST_R_UNSUPPORTEDALG);
715 	}
716 
717 	if (isc_buffer_availablelength(target) < 4) {
718 		return (ISC_R_NOSPACE);
719 	}
720 	isc_buffer_putuint16(target, (uint16_t)(key->key_flags & 0xffff));
721 	isc_buffer_putuint8(target, (uint8_t)key->key_proto);
722 	isc_buffer_putuint8(target, (uint8_t)key->key_alg);
723 
724 	if ((key->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
725 		if (isc_buffer_availablelength(target) < 2) {
726 			return (ISC_R_NOSPACE);
727 		}
728 		isc_buffer_putuint16(
729 			target, (uint16_t)((key->key_flags >> 16) & 0xffff));
730 	}
731 
732 	if (key->keydata.generic == NULL) { /*%< NULL KEY */
733 		return (ISC_R_SUCCESS);
734 	}
735 
736 	return (key->func->todns(key, target));
737 }
738 
739 isc_result_t
740 dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
741 		isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
742 	uint8_t alg, proto;
743 	uint32_t flags, extflags;
744 	dst_key_t *key = NULL;
745 	dns_keytag_t id, rid;
746 	isc_region_t r;
747 	isc_result_t result;
748 
749 	REQUIRE(dst_initialized);
750 
751 	isc_buffer_remainingregion(source, &r);
752 
753 	if (isc_buffer_remaininglength(source) < 4) {
754 		return (DST_R_INVALIDPUBLICKEY);
755 	}
756 	flags = isc_buffer_getuint16(source);
757 	proto = isc_buffer_getuint8(source);
758 	alg = isc_buffer_getuint8(source);
759 
760 	id = dst_region_computeid(&r);
761 	rid = dst_region_computerid(&r);
762 
763 	if ((flags & DNS_KEYFLAG_EXTENDED) != 0) {
764 		if (isc_buffer_remaininglength(source) < 2) {
765 			return (DST_R_INVALIDPUBLICKEY);
766 		}
767 		extflags = isc_buffer_getuint16(source);
768 		flags |= (extflags << 16);
769 	}
770 
771 	result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
772 			    &key);
773 	if (result != ISC_R_SUCCESS) {
774 		return (result);
775 	}
776 	key->key_id = id;
777 	key->key_rid = rid;
778 
779 	*keyp = key;
780 	return (ISC_R_SUCCESS);
781 }
782 
783 isc_result_t
784 dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
785 		   unsigned int protocol, dns_rdataclass_t rdclass,
786 		   isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
787 	dst_key_t *key = NULL;
788 	isc_result_t result;
789 
790 	REQUIRE(dst_initialized);
791 
792 	result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
793 			    &key);
794 	if (result != ISC_R_SUCCESS) {
795 		return (result);
796 	}
797 
798 	result = computeid(key);
799 	if (result != ISC_R_SUCCESS) {
800 		dst_key_free(&key);
801 		return (result);
802 	}
803 
804 	*keyp = key;
805 	return (ISC_R_SUCCESS);
806 }
807 
808 isc_result_t
809 dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
810 	REQUIRE(dst_initialized);
811 	REQUIRE(VALID_KEY(key));
812 	REQUIRE(target != NULL);
813 
814 	CHECKALG(key->key_alg);
815 
816 	if (key->func->todns == NULL) {
817 		return (DST_R_UNSUPPORTEDALG);
818 	}
819 
820 	return (key->func->todns(key, target));
821 }
822 
823 isc_result_t
824 dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
825 	isc_lex_t *lex = NULL;
826 	isc_result_t result = ISC_R_SUCCESS;
827 
828 	REQUIRE(dst_initialized);
829 	REQUIRE(VALID_KEY(key));
830 	REQUIRE(!dst_key_isprivate(key));
831 	REQUIRE(buffer != NULL);
832 
833 	if (key->func->parse == NULL) {
834 		RETERR(DST_R_UNSUPPORTEDALG);
835 	}
836 
837 	RETERR(isc_lex_create(key->mctx, 1500, &lex));
838 	RETERR(isc_lex_openbuffer(lex, buffer));
839 	RETERR(key->func->parse(key, lex, NULL));
840 out:
841 	if (lex != NULL) {
842 		isc_lex_destroy(&lex);
843 	}
844 	return (result);
845 }
846 
847 gss_ctx_id_t
848 dst_key_getgssctx(const dst_key_t *key) {
849 	REQUIRE(key != NULL);
850 
851 	return (key->keydata.gssctx);
852 }
853 
854 isc_result_t
855 dst_key_fromgssapi(const dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
856 		   dst_key_t **keyp, isc_region_t *intoken) {
857 	dst_key_t *key;
858 	isc_result_t result;
859 
860 	REQUIRE(gssctx != NULL);
861 	REQUIRE(keyp != NULL && *keyp == NULL);
862 
863 	key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0,
864 			     dns_rdataclass_in, 0, mctx);
865 	if (key == NULL) {
866 		return (ISC_R_NOMEMORY);
867 	}
868 
869 	if (intoken != NULL) {
870 		/*
871 		 * Keep the token for use by external ssu rules. They may need
872 		 * to examine the PAC in the kerberos ticket.
873 		 */
874 		isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
875 				    intoken->length);
876 		RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
877 	}
878 
879 	key->keydata.gssctx = gssctx;
880 	*keyp = key;
881 	result = ISC_R_SUCCESS;
882 out:
883 	if (result != ISC_R_SUCCESS) {
884 		dst_key_free(&key);
885 	}
886 	return (result);
887 }
888 
889 isc_result_t
890 dst_key_buildinternal(const dns_name_t *name, unsigned int alg,
891 		      unsigned int bits, unsigned int flags,
892 		      unsigned int protocol, dns_rdataclass_t rdclass,
893 		      void *data, isc_mem_t *mctx, dst_key_t **keyp) {
894 	dst_key_t *key;
895 	isc_result_t result;
896 
897 	REQUIRE(dst_initialized);
898 	REQUIRE(dns_name_isabsolute(name));
899 	REQUIRE(mctx != NULL);
900 	REQUIRE(keyp != NULL && *keyp == NULL);
901 	REQUIRE(data != NULL);
902 
903 	CHECKALG(alg);
904 
905 	key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0,
906 			     mctx);
907 	if (key == NULL) {
908 		return (ISC_R_NOMEMORY);
909 	}
910 
911 	key->keydata.generic = data;
912 
913 	result = computeid(key);
914 	if (result != ISC_R_SUCCESS) {
915 		dst_key_free(&key);
916 		return (result);
917 	}
918 
919 	*keyp = key;
920 	return (ISC_R_SUCCESS);
921 }
922 
923 isc_result_t
924 dst_key_fromlabel(const dns_name_t *name, int alg, unsigned int flags,
925 		  unsigned int protocol, dns_rdataclass_t rdclass,
926 		  const char *engine, const char *label, const char *pin,
927 		  isc_mem_t *mctx, dst_key_t **keyp) {
928 	dst_key_t *key;
929 	isc_result_t result;
930 
931 	REQUIRE(dst_initialized);
932 	REQUIRE(dns_name_isabsolute(name));
933 	REQUIRE(mctx != NULL);
934 	REQUIRE(keyp != NULL && *keyp == NULL);
935 	REQUIRE(label != NULL);
936 
937 	CHECKALG(alg);
938 
939 	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
940 	if (key == NULL) {
941 		return (ISC_R_NOMEMORY);
942 	}
943 
944 	if (key->func->fromlabel == NULL) {
945 		dst_key_free(&key);
946 		return (DST_R_UNSUPPORTEDALG);
947 	}
948 
949 	result = key->func->fromlabel(key, engine, label, pin);
950 	if (result != ISC_R_SUCCESS) {
951 		dst_key_free(&key);
952 		return (result);
953 	}
954 
955 	result = computeid(key);
956 	if (result != ISC_R_SUCCESS) {
957 		dst_key_free(&key);
958 		return (result);
959 	}
960 
961 	*keyp = key;
962 	return (ISC_R_SUCCESS);
963 }
964 
965 isc_result_t
966 dst_key_generate(const dns_name_t *name, unsigned int alg, unsigned int bits,
967 		 unsigned int param, unsigned int flags, unsigned int protocol,
968 		 dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp,
969 		 void (*callback)(int)) {
970 	dst_key_t *key;
971 	isc_result_t ret;
972 
973 	REQUIRE(dst_initialized);
974 	REQUIRE(dns_name_isabsolute(name));
975 	REQUIRE(mctx != NULL);
976 	REQUIRE(keyp != NULL && *keyp == NULL);
977 
978 	CHECKALG(alg);
979 
980 	key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0,
981 			     mctx);
982 	if (key == NULL) {
983 		return (ISC_R_NOMEMORY);
984 	}
985 
986 	if (bits == 0) { /*%< NULL KEY */
987 		key->key_flags |= DNS_KEYTYPE_NOKEY;
988 		*keyp = key;
989 		return (ISC_R_SUCCESS);
990 	}
991 
992 	if (key->func->generate == NULL) {
993 		dst_key_free(&key);
994 		return (DST_R_UNSUPPORTEDALG);
995 	}
996 
997 	ret = key->func->generate(key, param, callback);
998 	if (ret != ISC_R_SUCCESS) {
999 		dst_key_free(&key);
1000 		return (ret);
1001 	}
1002 
1003 	ret = computeid(key);
1004 	if (ret != ISC_R_SUCCESS) {
1005 		dst_key_free(&key);
1006 		return (ret);
1007 	}
1008 
1009 	*keyp = key;
1010 	return (ISC_R_SUCCESS);
1011 }
1012 
1013 isc_result_t
1014 dst_key_getbool(const dst_key_t *key, int type, bool *valuep) {
1015 	REQUIRE(VALID_KEY(key));
1016 	REQUIRE(valuep != NULL);
1017 	REQUIRE(type <= DST_MAX_BOOLEAN);
1018 	if (!key->boolset[type]) {
1019 		return (ISC_R_NOTFOUND);
1020 	}
1021 	*valuep = key->bools[type];
1022 	return (ISC_R_SUCCESS);
1023 }
1024 
1025 void
1026 dst_key_setbool(dst_key_t *key, int type, bool value) {
1027 	REQUIRE(VALID_KEY(key));
1028 	REQUIRE(type <= DST_MAX_BOOLEAN);
1029 	key->bools[type] = value;
1030 	key->boolset[type] = true;
1031 }
1032 
1033 void
1034 dst_key_unsetbool(dst_key_t *key, int type) {
1035 	REQUIRE(VALID_KEY(key));
1036 	REQUIRE(type <= DST_MAX_BOOLEAN);
1037 	key->boolset[type] = false;
1038 }
1039 
1040 isc_result_t
1041 dst_key_getnum(const dst_key_t *key, int type, uint32_t *valuep) {
1042 	REQUIRE(VALID_KEY(key));
1043 	REQUIRE(valuep != NULL);
1044 	REQUIRE(type <= DST_MAX_NUMERIC);
1045 	if (!key->numset[type]) {
1046 		return (ISC_R_NOTFOUND);
1047 	}
1048 	*valuep = key->nums[type];
1049 	return (ISC_R_SUCCESS);
1050 }
1051 
1052 void
1053 dst_key_setnum(dst_key_t *key, int type, uint32_t value) {
1054 	REQUIRE(VALID_KEY(key));
1055 	REQUIRE(type <= DST_MAX_NUMERIC);
1056 	key->nums[type] = value;
1057 	key->numset[type] = true;
1058 }
1059 
1060 void
1061 dst_key_unsetnum(dst_key_t *key, int type) {
1062 	REQUIRE(VALID_KEY(key));
1063 	REQUIRE(type <= DST_MAX_NUMERIC);
1064 	key->numset[type] = false;
1065 }
1066 
1067 isc_result_t
1068 dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
1069 	REQUIRE(VALID_KEY(key));
1070 	REQUIRE(timep != NULL);
1071 	REQUIRE(type <= DST_MAX_TIMES);
1072 	if (!key->timeset[type]) {
1073 		return (ISC_R_NOTFOUND);
1074 	}
1075 	*timep = key->times[type];
1076 	return (ISC_R_SUCCESS);
1077 }
1078 
1079 void
1080 dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
1081 	REQUIRE(VALID_KEY(key));
1082 	REQUIRE(type <= DST_MAX_TIMES);
1083 	key->times[type] = when;
1084 	key->timeset[type] = true;
1085 }
1086 
1087 void
1088 dst_key_unsettime(dst_key_t *key, int type) {
1089 	REQUIRE(VALID_KEY(key));
1090 	REQUIRE(type <= DST_MAX_TIMES);
1091 	key->timeset[type] = false;
1092 }
1093 
1094 isc_result_t
1095 dst_key_getstate(const dst_key_t *key, int type, dst_key_state_t *statep) {
1096 	REQUIRE(VALID_KEY(key));
1097 	REQUIRE(statep != NULL);
1098 	REQUIRE(type <= DST_MAX_KEYSTATES);
1099 	if (!key->keystateset[type]) {
1100 		return (ISC_R_NOTFOUND);
1101 	}
1102 	*statep = key->keystates[type];
1103 	return (ISC_R_SUCCESS);
1104 }
1105 
1106 void
1107 dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state) {
1108 	REQUIRE(VALID_KEY(key));
1109 	REQUIRE(type <= DST_MAX_KEYSTATES);
1110 	key->keystates[type] = state;
1111 	key->keystateset[type] = true;
1112 }
1113 
1114 void
1115 dst_key_unsetstate(dst_key_t *key, int type) {
1116 	REQUIRE(VALID_KEY(key));
1117 	REQUIRE(type <= DST_MAX_KEYSTATES);
1118 	key->keystateset[type] = false;
1119 }
1120 
1121 isc_result_t
1122 dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
1123 	REQUIRE(VALID_KEY(key));
1124 	REQUIRE(majorp != NULL);
1125 	REQUIRE(minorp != NULL);
1126 	*majorp = key->fmt_major;
1127 	*minorp = key->fmt_minor;
1128 	return (ISC_R_SUCCESS);
1129 }
1130 
1131 void
1132 dst_key_setprivateformat(dst_key_t *key, int major, int minor) {
1133 	REQUIRE(VALID_KEY(key));
1134 	key->fmt_major = major;
1135 	key->fmt_minor = minor;
1136 }
1137 
1138 static bool
1139 comparekeys(const dst_key_t *key1, const dst_key_t *key2,
1140 	    bool match_revoked_key,
1141 	    bool (*compare)(const dst_key_t *key1, const dst_key_t *key2)) {
1142 	REQUIRE(dst_initialized);
1143 	REQUIRE(VALID_KEY(key1));
1144 	REQUIRE(VALID_KEY(key2));
1145 
1146 	if (key1 == key2) {
1147 		return (true);
1148 	}
1149 
1150 	if (key1->key_alg != key2->key_alg) {
1151 		return (false);
1152 	}
1153 
1154 	if (key1->key_id != key2->key_id) {
1155 		if (!match_revoked_key) {
1156 			return (false);
1157 		}
1158 		if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
1159 		    (key2->key_flags & DNS_KEYFLAG_REVOKE))
1160 		{
1161 			return (false);
1162 		}
1163 		if (key1->key_id != key2->key_rid &&
1164 		    key1->key_rid != key2->key_id) {
1165 			return (false);
1166 		}
1167 	}
1168 
1169 	if (compare != NULL) {
1170 		return (compare(key1, key2));
1171 	} else {
1172 		return (false);
1173 	}
1174 }
1175 
1176 /*
1177  * Compares only the public portion of two keys, by converting them
1178  * both to wire format and comparing the results.
1179  */
1180 static bool
1181 pub_compare(const dst_key_t *key1, const dst_key_t *key2) {
1182 	isc_result_t result;
1183 	unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
1184 	isc_buffer_t b1, b2;
1185 	isc_region_t r1, r2;
1186 
1187 	isc_buffer_init(&b1, buf1, sizeof(buf1));
1188 	result = dst_key_todns(key1, &b1);
1189 	if (result != ISC_R_SUCCESS) {
1190 		return (false);
1191 	}
1192 	/* Zero out flags. */
1193 	buf1[0] = buf1[1] = 0;
1194 	if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1195 		isc_buffer_subtract(&b1, 2);
1196 	}
1197 
1198 	isc_buffer_init(&b2, buf2, sizeof(buf2));
1199 	result = dst_key_todns(key2, &b2);
1200 	if (result != ISC_R_SUCCESS) {
1201 		return (false);
1202 	}
1203 	/* Zero out flags. */
1204 	buf2[0] = buf2[1] = 0;
1205 	if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1206 		isc_buffer_subtract(&b2, 2);
1207 	}
1208 
1209 	isc_buffer_usedregion(&b1, &r1);
1210 	/* Remove extended flags. */
1211 	if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1212 		memmove(&buf1[4], &buf1[6], r1.length - 6);
1213 		r1.length -= 2;
1214 	}
1215 
1216 	isc_buffer_usedregion(&b2, &r2);
1217 	/* Remove extended flags. */
1218 	if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
1219 		memmove(&buf2[4], &buf2[6], r2.length - 6);
1220 		r2.length -= 2;
1221 	}
1222 	return (isc_region_compare(&r1, &r2) == 0);
1223 }
1224 
1225 bool
1226 dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
1227 	return (comparekeys(key1, key2, false, key1->func->compare));
1228 }
1229 
1230 bool
1231 dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
1232 		   bool match_revoked_key) {
1233 	return (comparekeys(key1, key2, match_revoked_key, pub_compare));
1234 }
1235 
1236 bool
1237 dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
1238 	REQUIRE(dst_initialized);
1239 	REQUIRE(VALID_KEY(key1));
1240 	REQUIRE(VALID_KEY(key2));
1241 
1242 	if (key1 == key2) {
1243 		return (true);
1244 	}
1245 	if (key1->key_alg == key2->key_alg &&
1246 	    key1->func->paramcompare != NULL &&
1247 	    key1->func->paramcompare(key1, key2))
1248 	{
1249 		return (true);
1250 	} else {
1251 		return (false);
1252 	}
1253 }
1254 
1255 void
1256 dst_key_attach(dst_key_t *source, dst_key_t **target) {
1257 	REQUIRE(dst_initialized);
1258 	REQUIRE(target != NULL && *target == NULL);
1259 	REQUIRE(VALID_KEY(source));
1260 
1261 	isc_refcount_increment(&source->refs);
1262 	*target = source;
1263 }
1264 
1265 void
1266 dst_key_free(dst_key_t **keyp) {
1267 	REQUIRE(dst_initialized);
1268 	REQUIRE(keyp != NULL && VALID_KEY(*keyp));
1269 	dst_key_t *key = *keyp;
1270 	*keyp = NULL;
1271 
1272 	if (isc_refcount_decrement(&key->refs) == 1) {
1273 		isc_refcount_destroy(&key->refs);
1274 		isc_mem_t *mctx = key->mctx;
1275 		if (key->keydata.generic != NULL) {
1276 			INSIST(key->func->destroy != NULL);
1277 			key->func->destroy(key);
1278 		}
1279 		if (key->engine != NULL) {
1280 			isc_mem_free(mctx, key->engine);
1281 		}
1282 		if (key->label != NULL) {
1283 			isc_mem_free(mctx, key->label);
1284 		}
1285 		dns_name_free(key->key_name, mctx);
1286 		isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
1287 		if (key->key_tkeytoken) {
1288 			isc_buffer_free(&key->key_tkeytoken);
1289 		}
1290 		isc_safe_memwipe(key, sizeof(*key));
1291 		isc_mem_putanddetach(&mctx, key, sizeof(*key));
1292 	}
1293 }
1294 
1295 bool
1296 dst_key_isprivate(const dst_key_t *key) {
1297 	REQUIRE(VALID_KEY(key));
1298 	INSIST(key->func->isprivate != NULL);
1299 	return (key->func->isprivate(key));
1300 }
1301 
1302 isc_result_t
1303 dst_key_buildfilename(const dst_key_t *key, int type, const char *directory,
1304 		      isc_buffer_t *out) {
1305 	REQUIRE(VALID_KEY(key));
1306 	REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
1307 		type == DST_TYPE_STATE || type == 0);
1308 
1309 	return (buildfilename(key->key_name, key->key_id, key->key_alg, type,
1310 			      directory, out));
1311 }
1312 
1313 isc_result_t
1314 dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
1315 	REQUIRE(dst_initialized);
1316 	REQUIRE(VALID_KEY(key));
1317 	REQUIRE(n != NULL);
1318 
1319 	/* XXXVIX this switch statement is too sparse to gen a jump table. */
1320 	switch (key->key_alg) {
1321 	case DST_ALG_RSASHA1:
1322 	case DST_ALG_NSEC3RSASHA1:
1323 	case DST_ALG_RSASHA256:
1324 	case DST_ALG_RSASHA512:
1325 		*n = (key->key_size + 7) / 8;
1326 		break;
1327 	case DST_ALG_ECDSA256:
1328 		*n = DNS_SIG_ECDSA256SIZE;
1329 		break;
1330 	case DST_ALG_ECDSA384:
1331 		*n = DNS_SIG_ECDSA384SIZE;
1332 		break;
1333 	case DST_ALG_ED25519:
1334 		*n = DNS_SIG_ED25519SIZE;
1335 		break;
1336 	case DST_ALG_ED448:
1337 		*n = DNS_SIG_ED448SIZE;
1338 		break;
1339 	case DST_ALG_HMACMD5:
1340 		*n = isc_md_type_get_size(ISC_MD_MD5);
1341 		break;
1342 	case DST_ALG_HMACSHA1:
1343 		*n = isc_md_type_get_size(ISC_MD_SHA1);
1344 		break;
1345 	case DST_ALG_HMACSHA224:
1346 		*n = isc_md_type_get_size(ISC_MD_SHA224);
1347 		break;
1348 	case DST_ALG_HMACSHA256:
1349 		*n = isc_md_type_get_size(ISC_MD_SHA256);
1350 		break;
1351 	case DST_ALG_HMACSHA384:
1352 		*n = isc_md_type_get_size(ISC_MD_SHA384);
1353 		break;
1354 	case DST_ALG_HMACSHA512:
1355 		*n = isc_md_type_get_size(ISC_MD_SHA512);
1356 		break;
1357 	case DST_ALG_GSSAPI:
1358 		*n = 128; /*%< XXX */
1359 		break;
1360 	case DST_ALG_DH:
1361 	default:
1362 		return (DST_R_UNSUPPORTEDALG);
1363 	}
1364 	return (ISC_R_SUCCESS);
1365 }
1366 
1367 isc_result_t
1368 dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
1369 	REQUIRE(dst_initialized);
1370 	REQUIRE(VALID_KEY(key));
1371 	REQUIRE(n != NULL);
1372 
1373 	if (key->key_alg == DST_ALG_DH) {
1374 		*n = (key->key_size + 7) / 8;
1375 		return (ISC_R_SUCCESS);
1376 	}
1377 	return (DST_R_UNSUPPORTEDALG);
1378 }
1379 
1380 /*%
1381  * Set the flags on a key, then recompute the key ID
1382  */
1383 isc_result_t
1384 dst_key_setflags(dst_key_t *key, uint32_t flags) {
1385 	REQUIRE(VALID_KEY(key));
1386 	key->key_flags = flags;
1387 	return (computeid(key));
1388 }
1389 
1390 void
1391 dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
1392 	char namestr[DNS_NAME_FORMATSIZE];
1393 	char algstr[DNS_NAME_FORMATSIZE];
1394 
1395 	dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
1396 	dns_secalg_format((dns_secalg_t)dst_key_alg(key), algstr,
1397 			  sizeof(algstr));
1398 	snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
1399 }
1400 
1401 isc_result_t
1402 dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
1403 	REQUIRE(buffer != NULL && *buffer == NULL);
1404 	REQUIRE(length != NULL && *length == 0);
1405 	REQUIRE(VALID_KEY(key));
1406 
1407 	if (key->func->dump == NULL) {
1408 		return (ISC_R_NOTIMPLEMENTED);
1409 	}
1410 	return (key->func->dump(key, mctx, buffer, length));
1411 }
1412 
1413 isc_result_t
1414 dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
1415 		unsigned int protocol, dns_rdataclass_t rdclass,
1416 		isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) {
1417 	isc_result_t result;
1418 	dst_key_t *key;
1419 
1420 	REQUIRE(dst_initialized);
1421 	REQUIRE(keyp != NULL && *keyp == NULL);
1422 
1423 	if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) {
1424 		return (DST_R_UNSUPPORTEDALG);
1425 	}
1426 
1427 	if (dst_t_func[alg]->restore == NULL) {
1428 		return (ISC_R_NOTIMPLEMENTED);
1429 	}
1430 
1431 	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
1432 	if (key == NULL) {
1433 		return (ISC_R_NOMEMORY);
1434 	}
1435 
1436 	result = (dst_t_func[alg]->restore)(key, keystr);
1437 	if (result == ISC_R_SUCCESS) {
1438 		*keyp = key;
1439 	} else {
1440 		dst_key_free(&key);
1441 	}
1442 
1443 	return (result);
1444 }
1445 
1446 /***
1447  *** Static methods
1448  ***/
1449 
1450 /*%
1451  * Allocates a key structure and fills in some of the fields.
1452  */
1453 static dst_key_t *
1454 get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags,
1455 	       unsigned int protocol, unsigned int bits,
1456 	       dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx) {
1457 	dst_key_t *key;
1458 	int i;
1459 
1460 	key = isc_mem_get(mctx, sizeof(dst_key_t));
1461 
1462 	memset(key, 0, sizeof(dst_key_t));
1463 
1464 	key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
1465 
1466 	dns_name_init(key->key_name, NULL);
1467 	dns_name_dup(name, mctx, key->key_name);
1468 
1469 	isc_refcount_init(&key->refs, 1);
1470 	isc_mem_attach(mctx, &key->mctx);
1471 	key->key_alg = alg;
1472 	key->key_flags = flags;
1473 	key->key_proto = protocol;
1474 	key->keydata.generic = NULL;
1475 	key->key_size = bits;
1476 	key->key_class = rdclass;
1477 	key->key_ttl = ttl;
1478 	key->func = dst_t_func[alg];
1479 	key->fmt_major = 0;
1480 	key->fmt_minor = 0;
1481 	for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
1482 		key->times[i] = 0;
1483 		key->timeset[i] = false;
1484 	}
1485 	key->inactive = false;
1486 	key->magic = KEY_MAGIC;
1487 	return (key);
1488 }
1489 
1490 bool
1491 dst_key_inactive(const dst_key_t *key) {
1492 	REQUIRE(VALID_KEY(key));
1493 
1494 	return (key->inactive);
1495 }
1496 
1497 void
1498 dst_key_setinactive(dst_key_t *key, bool inactive) {
1499 	REQUIRE(VALID_KEY(key));
1500 
1501 	key->inactive = inactive;
1502 }
1503 
1504 /*%
1505  * Reads a public key from disk.
1506  */
1507 isc_result_t
1508 dst_key_read_public(const char *filename, int type, isc_mem_t *mctx,
1509 		    dst_key_t **keyp) {
1510 	u_char rdatabuf[DST_KEY_MAXSIZE];
1511 	isc_buffer_t b;
1512 	dns_fixedname_t name;
1513 	isc_lex_t *lex = NULL;
1514 	isc_token_t token;
1515 	isc_result_t ret;
1516 	dns_rdata_t rdata = DNS_RDATA_INIT;
1517 	unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
1518 	dns_rdataclass_t rdclass = dns_rdataclass_in;
1519 	isc_lexspecials_t specials;
1520 	uint32_t ttl = 0;
1521 	isc_result_t result;
1522 	dns_rdatatype_t keytype;
1523 
1524 	/*
1525 	 * Open the file and read its formatted contents
1526 	 * File format:
1527 	 *    domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol>
1528 	 * <algorithm> <key>
1529 	 */
1530 
1531 	/* 1500 should be large enough for any key */
1532 	ret = isc_lex_create(mctx, 1500, &lex);
1533 	if (ret != ISC_R_SUCCESS) {
1534 		goto cleanup;
1535 	}
1536 
1537 	memset(specials, 0, sizeof(specials));
1538 	specials['('] = 1;
1539 	specials[')'] = 1;
1540 	specials['"'] = 1;
1541 	isc_lex_setspecials(lex, specials);
1542 	isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
1543 
1544 	ret = isc_lex_openfile(lex, filename);
1545 	if (ret != ISC_R_SUCCESS) {
1546 		goto cleanup;
1547 	}
1548 
1549 	/* Read the domain name */
1550 	NEXTTOKEN(lex, opt, &token);
1551 	if (token.type != isc_tokentype_string) {
1552 		BADTOKEN();
1553 	}
1554 
1555 	/*
1556 	 * We don't support "@" in .key files.
1557 	 */
1558 	if (!strcmp(DST_AS_STR(token), "@")) {
1559 		BADTOKEN();
1560 	}
1561 
1562 	dns_fixedname_init(&name);
1563 	isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
1564 	isc_buffer_add(&b, strlen(DST_AS_STR(token)));
1565 	ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, 0,
1566 				NULL);
1567 	if (ret != ISC_R_SUCCESS) {
1568 		goto cleanup;
1569 	}
1570 
1571 	/* Read the next word: either TTL, class, or 'KEY' */
1572 	NEXTTOKEN(lex, opt, &token);
1573 
1574 	if (token.type != isc_tokentype_string) {
1575 		BADTOKEN();
1576 	}
1577 
1578 	/* If it's a TTL, read the next one */
1579 	result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
1580 	if (result == ISC_R_SUCCESS) {
1581 		NEXTTOKEN(lex, opt, &token);
1582 	}
1583 
1584 	if (token.type != isc_tokentype_string) {
1585 		BADTOKEN();
1586 	}
1587 
1588 	ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
1589 	if (ret == ISC_R_SUCCESS) {
1590 		NEXTTOKEN(lex, opt, &token);
1591 	}
1592 
1593 	if (token.type != isc_tokentype_string) {
1594 		BADTOKEN();
1595 	}
1596 
1597 	if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0) {
1598 		keytype = dns_rdatatype_dnskey;
1599 	} else if (strcasecmp(DST_AS_STR(token), "KEY") == 0) {
1600 		keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
1601 	} else {
1602 		BADTOKEN();
1603 	}
1604 
1605 	if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
1606 	    ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey))
1607 	{
1608 		ret = DST_R_BADKEYTYPE;
1609 		goto cleanup;
1610 	}
1611 
1612 	isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
1613 	ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL, false,
1614 				 mctx, &b, NULL);
1615 	if (ret != ISC_R_SUCCESS) {
1616 		goto cleanup;
1617 	}
1618 
1619 	ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
1620 			      keyp);
1621 	if (ret != ISC_R_SUCCESS) {
1622 		goto cleanup;
1623 	}
1624 
1625 	dst_key_setttl(*keyp, ttl);
1626 
1627 cleanup:
1628 	if (lex != NULL) {
1629 		isc_lex_destroy(&lex);
1630 	}
1631 	return (ret);
1632 }
1633 
1634 static int
1635 find_metadata(const char *s, const char *tags[], int ntags) {
1636 	for (int i = 0; i < ntags; i++) {
1637 		if (tags[i] != NULL && strcasecmp(s, tags[i]) == 0) {
1638 			return (i);
1639 		}
1640 	}
1641 	return (-1);
1642 }
1643 
1644 static int
1645 find_numericdata(const char *s) {
1646 	return (find_metadata(s, numerictags, NUMERIC_NTAGS));
1647 }
1648 
1649 static int
1650 find_booleandata(const char *s) {
1651 	return (find_metadata(s, booleantags, BOOLEAN_NTAGS));
1652 }
1653 
1654 static int
1655 find_timingdata(const char *s) {
1656 	return (find_metadata(s, timingtags, TIMING_NTAGS));
1657 }
1658 
1659 static int
1660 find_keystatedata(const char *s) {
1661 	return (find_metadata(s, keystatestags, KEYSTATES_NTAGS));
1662 }
1663 
1664 static isc_result_t
1665 keystate_fromtext(const char *s, dst_key_state_t *state) {
1666 	for (int i = 0; i < KEYSTATES_NVALUES; i++) {
1667 		if (keystates[i] != NULL && strcasecmp(s, keystates[i]) == 0) {
1668 			*state = (dst_key_state_t)i;
1669 			return (ISC_R_SUCCESS);
1670 		}
1671 	}
1672 	return (ISC_R_NOTFOUND);
1673 }
1674 
1675 /*%
1676  * Reads a key state from disk.
1677  */
1678 isc_result_t
1679 dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t **keyp) {
1680 	isc_lex_t *lex = NULL;
1681 	isc_token_t token;
1682 	isc_result_t ret;
1683 	unsigned int opt = ISC_LEXOPT_EOL;
1684 
1685 	ret = isc_lex_create(mctx, 1500, &lex);
1686 	if (ret != ISC_R_SUCCESS) {
1687 		goto cleanup;
1688 	}
1689 	isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
1690 
1691 	ret = isc_lex_openfile(lex, filename);
1692 	if (ret != ISC_R_SUCCESS) {
1693 		goto cleanup;
1694 	}
1695 
1696 	/*
1697 	 * Read the comment line.
1698 	 */
1699 	READLINE(lex, opt, &token);
1700 
1701 	/*
1702 	 * Read the algorithm line.
1703 	 */
1704 	NEXTTOKEN(lex, opt, &token);
1705 	if (token.type != isc_tokentype_string ||
1706 	    strcmp(DST_AS_STR(token), STATE_ALGORITHM_STR) != 0)
1707 	{
1708 		BADTOKEN();
1709 	}
1710 
1711 	NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
1712 	if (token.type != isc_tokentype_number ||
1713 	    token.value.as_ulong != (unsigned long)dst_key_alg(*keyp))
1714 	{
1715 		BADTOKEN();
1716 	}
1717 
1718 	READLINE(lex, opt, &token);
1719 
1720 	/*
1721 	 * Read the length line.
1722 	 */
1723 	NEXTTOKEN(lex, opt, &token);
1724 	if (token.type != isc_tokentype_string ||
1725 	    strcmp(DST_AS_STR(token), STATE_LENGTH_STR) != 0)
1726 	{
1727 		BADTOKEN();
1728 	}
1729 
1730 	NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
1731 	if (token.type != isc_tokentype_number ||
1732 	    token.value.as_ulong != (unsigned long)dst_key_size(*keyp))
1733 	{
1734 		BADTOKEN();
1735 	}
1736 
1737 	READLINE(lex, opt, &token);
1738 
1739 	/*
1740 	 * Read the metadata.
1741 	 */
1742 	for (int n = 0; n < MAX_NTAGS; n++) {
1743 		int tag;
1744 
1745 		NEXTTOKEN_OR_EOF(lex, opt, &token);
1746 		if (ret == ISC_R_EOF) {
1747 			break;
1748 		}
1749 		if (token.type != isc_tokentype_string) {
1750 			BADTOKEN();
1751 		}
1752 
1753 		/* Numeric metadata */
1754 		tag = find_numericdata(DST_AS_STR(token));
1755 		if (tag >= 0) {
1756 			INSIST(tag < NUMERIC_NTAGS);
1757 
1758 			NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
1759 			if (token.type != isc_tokentype_number) {
1760 				BADTOKEN();
1761 			}
1762 
1763 			dst_key_setnum(*keyp, tag, token.value.as_ulong);
1764 			goto next;
1765 		}
1766 
1767 		/* Boolean metadata */
1768 		tag = find_booleandata(DST_AS_STR(token));
1769 		if (tag >= 0) {
1770 			INSIST(tag < BOOLEAN_NTAGS);
1771 
1772 			NEXTTOKEN(lex, opt, &token);
1773 			if (token.type != isc_tokentype_string) {
1774 				BADTOKEN();
1775 			}
1776 
1777 			if (strcmp(DST_AS_STR(token), "yes") == 0) {
1778 				dst_key_setbool(*keyp, tag, true);
1779 			} else if (strcmp(DST_AS_STR(token), "no") == 0) {
1780 				dst_key_setbool(*keyp, tag, false);
1781 			} else {
1782 				BADTOKEN();
1783 			}
1784 			goto next;
1785 		}
1786 
1787 		/* Timing metadata */
1788 		tag = find_timingdata(DST_AS_STR(token));
1789 		if (tag >= 0) {
1790 			uint32_t when;
1791 
1792 			INSIST(tag < TIMING_NTAGS);
1793 
1794 			NEXTTOKEN(lex, opt, &token);
1795 			if (token.type != isc_tokentype_string) {
1796 				BADTOKEN();
1797 			}
1798 
1799 			ret = dns_time32_fromtext(DST_AS_STR(token), &when);
1800 			if (ret != ISC_R_SUCCESS) {
1801 				goto cleanup;
1802 			}
1803 
1804 			dst_key_settime(*keyp, tag, when);
1805 			goto next;
1806 		}
1807 
1808 		/* Keystate metadata */
1809 		tag = find_keystatedata(DST_AS_STR(token));
1810 		if (tag >= 0) {
1811 			dst_key_state_t state;
1812 
1813 			INSIST(tag < KEYSTATES_NTAGS);
1814 
1815 			NEXTTOKEN(lex, opt, &token);
1816 			if (token.type != isc_tokentype_string) {
1817 				BADTOKEN();
1818 			}
1819 
1820 			ret = keystate_fromtext(DST_AS_STR(token), &state);
1821 			if (ret != ISC_R_SUCCESS) {
1822 				goto cleanup;
1823 			}
1824 
1825 			dst_key_setstate(*keyp, tag, state);
1826 			goto next;
1827 		}
1828 
1829 	next:
1830 		READLINE(lex, opt, &token);
1831 	}
1832 
1833 	/* Done, successfully parsed the whole file. */
1834 	ret = ISC_R_SUCCESS;
1835 
1836 cleanup:
1837 	if (lex != NULL) {
1838 		isc_lex_destroy(&lex);
1839 	}
1840 	return (ret);
1841 }
1842 
1843 static bool
1844 issymmetric(const dst_key_t *key) {
1845 	REQUIRE(dst_initialized);
1846 	REQUIRE(VALID_KEY(key));
1847 
1848 	/* XXXVIX this switch statement is too sparse to gen a jump table. */
1849 	switch (key->key_alg) {
1850 	case DST_ALG_RSASHA1:
1851 	case DST_ALG_NSEC3RSASHA1:
1852 	case DST_ALG_RSASHA256:
1853 	case DST_ALG_RSASHA512:
1854 	case DST_ALG_DH:
1855 	case DST_ALG_ECDSA256:
1856 	case DST_ALG_ECDSA384:
1857 	case DST_ALG_ED25519:
1858 	case DST_ALG_ED448:
1859 		return (false);
1860 	case DST_ALG_HMACMD5:
1861 	case DST_ALG_HMACSHA1:
1862 	case DST_ALG_HMACSHA224:
1863 	case DST_ALG_HMACSHA256:
1864 	case DST_ALG_HMACSHA384:
1865 	case DST_ALG_HMACSHA512:
1866 	case DST_ALG_GSSAPI:
1867 		return (true);
1868 	default:
1869 		return (false);
1870 	}
1871 }
1872 
1873 /*%
1874  * Write key boolean metadata to a file pointer, preceded by 'tag'
1875  */
1876 static void
1877 printbool(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1878 	isc_result_t result;
1879 	bool value = 0;
1880 
1881 	result = dst_key_getbool(key, type, &value);
1882 	if (result != ISC_R_SUCCESS) {
1883 		return;
1884 	}
1885 	fprintf(stream, "%s: %s\n", tag, value ? "yes" : "no");
1886 }
1887 
1888 /*%
1889  * Write key numeric metadata to a file pointer, preceded by 'tag'
1890  */
1891 static void
1892 printnum(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1893 	isc_result_t result;
1894 	uint32_t value = 0;
1895 
1896 	result = dst_key_getnum(key, type, &value);
1897 	if (result != ISC_R_SUCCESS) {
1898 		return;
1899 	}
1900 	fprintf(stream, "%s: %u\n", tag, value);
1901 }
1902 
1903 /*%
1904  * Write key timing metadata to a file pointer, preceded by 'tag'
1905  */
1906 static void
1907 printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1908 	isc_result_t result;
1909 	char output[26]; /* Minimum buffer as per ctime_r() specification. */
1910 	isc_stdtime_t when;
1911 	char utc[sizeof("YYYYMMDDHHSSMM")];
1912 	isc_buffer_t b;
1913 	isc_region_t r;
1914 
1915 	result = dst_key_gettime(key, type, &when);
1916 	if (result == ISC_R_NOTFOUND) {
1917 		return;
1918 	}
1919 
1920 	isc_stdtime_tostring(when, output, sizeof(output));
1921 	isc_buffer_init(&b, utc, sizeof(utc));
1922 	result = dns_time32_totext(when, &b);
1923 	if (result != ISC_R_SUCCESS) {
1924 		goto error;
1925 	}
1926 
1927 	isc_buffer_usedregion(&b, &r);
1928 	fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base,
1929 		(int)strlen(output) - 1, output);
1930 	return;
1931 
1932 error:
1933 	fprintf(stream, "%s: (set, unable to display)\n", tag);
1934 }
1935 
1936 /*%
1937  * Write key state metadata to a file pointer, preceded by 'tag'
1938  */
1939 static void
1940 printstate(const dst_key_t *key, int type, const char *tag, FILE *stream) {
1941 	isc_result_t result;
1942 	dst_key_state_t value = 0;
1943 
1944 	result = dst_key_getstate(key, type, &value);
1945 	if (result != ISC_R_SUCCESS) {
1946 		return;
1947 	}
1948 	fprintf(stream, "%s: %s\n", tag, keystates[value]);
1949 }
1950 
1951 /*%
1952  * Writes a key state to disk.
1953  */
1954 static isc_result_t
1955 write_key_state(const dst_key_t *key, int type, const char *directory) {
1956 	FILE *fp;
1957 	isc_buffer_t fileb;
1958 	char filename[NAME_MAX];
1959 	isc_result_t ret;
1960 	isc_fsaccess_t access;
1961 
1962 	REQUIRE(VALID_KEY(key));
1963 
1964 	/*
1965 	 * Make the filename.
1966 	 */
1967 	isc_buffer_init(&fileb, filename, sizeof(filename));
1968 	ret = dst_key_buildfilename(key, DST_TYPE_STATE, directory, &fileb);
1969 	if (ret != ISC_R_SUCCESS) {
1970 		return (ret);
1971 	}
1972 
1973 	/*
1974 	 * Create public key file.
1975 	 */
1976 	if ((fp = fopen(filename, "w")) == NULL) {
1977 		return (DST_R_WRITEERROR);
1978 	}
1979 
1980 	if (issymmetric(key)) {
1981 		access = 0;
1982 		isc_fsaccess_add(ISC_FSACCESS_OWNER,
1983 				 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
1984 				 &access);
1985 		(void)isc_fsaccess_set(filename, access);
1986 	}
1987 
1988 	/* Write key state */
1989 	if ((type & DST_TYPE_KEY) == 0) {
1990 		fprintf(fp, "; This is the state of key %d, for ", key->key_id);
1991 		ret = dns_name_print(key->key_name, fp);
1992 		if (ret != ISC_R_SUCCESS) {
1993 			fclose(fp);
1994 			return (ret);
1995 		}
1996 		fputc('\n', fp);
1997 
1998 		fprintf(fp, "Algorithm: %u\n", key->key_alg);
1999 		fprintf(fp, "Length: %u\n", key->key_size);
2000 
2001 		printnum(key, DST_NUM_LIFETIME, "Lifetime", fp);
2002 		printnum(key, DST_NUM_PREDECESSOR, "Predecessor", fp);
2003 		printnum(key, DST_NUM_SUCCESSOR, "Successor", fp);
2004 
2005 		printbool(key, DST_BOOL_KSK, "KSK", fp);
2006 		printbool(key, DST_BOOL_ZSK, "ZSK", fp);
2007 
2008 		printtime(key, DST_TIME_CREATED, "Generated", fp);
2009 		printtime(key, DST_TIME_PUBLISH, "Published", fp);
2010 		printtime(key, DST_TIME_ACTIVATE, "Active", fp);
2011 		printtime(key, DST_TIME_INACTIVE, "Retired", fp);
2012 		printtime(key, DST_TIME_REVOKE, "Revoked", fp);
2013 		printtime(key, DST_TIME_DELETE, "Removed", fp);
2014 		printtime(key, DST_TIME_SYNCPUBLISH, "PublishCDS", fp);
2015 		printtime(key, DST_TIME_SYNCDELETE, "DeleteCDS", fp);
2016 
2017 		printtime(key, DST_TIME_DNSKEY, "DNSKEYChange", fp);
2018 		printtime(key, DST_TIME_ZRRSIG, "ZRRSIGChange", fp);
2019 		printtime(key, DST_TIME_KRRSIG, "KRRSIGChange", fp);
2020 		printtime(key, DST_TIME_DS, "DSChange", fp);
2021 
2022 		printstate(key, DST_KEY_DNSKEY, "DNSKEYState", fp);
2023 		printstate(key, DST_KEY_ZRRSIG, "ZRRSIGState", fp);
2024 		printstate(key, DST_KEY_KRRSIG, "KRRSIGState", fp);
2025 		printstate(key, DST_KEY_DS, "DSState", fp);
2026 		printstate(key, DST_KEY_GOAL, "GoalState", fp);
2027 	}
2028 
2029 	fflush(fp);
2030 	if (ferror(fp)) {
2031 		ret = DST_R_WRITEERROR;
2032 	}
2033 	fclose(fp);
2034 
2035 	return (ret);
2036 }
2037 
2038 /*%
2039  * Writes a public key to disk in DNS format.
2040  */
2041 static isc_result_t
2042 write_public_key(const dst_key_t *key, int type, const char *directory) {
2043 	FILE *fp;
2044 	isc_buffer_t keyb, textb, fileb, classb;
2045 	isc_region_t r;
2046 	char filename[NAME_MAX];
2047 	unsigned char key_array[DST_KEY_MAXSIZE];
2048 	char text_array[DST_KEY_MAXTEXTSIZE];
2049 	char class_array[10];
2050 	isc_result_t ret;
2051 	dns_rdata_t rdata = DNS_RDATA_INIT;
2052 	isc_fsaccess_t access;
2053 
2054 	REQUIRE(VALID_KEY(key));
2055 
2056 	isc_buffer_init(&keyb, key_array, sizeof(key_array));
2057 	isc_buffer_init(&textb, text_array, sizeof(text_array));
2058 	isc_buffer_init(&classb, class_array, sizeof(class_array));
2059 
2060 	ret = dst_key_todns(key, &keyb);
2061 	if (ret != ISC_R_SUCCESS) {
2062 		return (ret);
2063 	}
2064 
2065 	isc_buffer_usedregion(&keyb, &r);
2066 	dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
2067 
2068 	ret = dns_rdata_totext(&rdata, (dns_name_t *)NULL, &textb);
2069 	if (ret != ISC_R_SUCCESS) {
2070 		return (DST_R_INVALIDPUBLICKEY);
2071 	}
2072 
2073 	ret = dns_rdataclass_totext(key->key_class, &classb);
2074 	if (ret != ISC_R_SUCCESS) {
2075 		return (DST_R_INVALIDPUBLICKEY);
2076 	}
2077 
2078 	/*
2079 	 * Make the filename.
2080 	 */
2081 	isc_buffer_init(&fileb, filename, sizeof(filename));
2082 	ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
2083 	if (ret != ISC_R_SUCCESS) {
2084 		return (ret);
2085 	}
2086 
2087 	/*
2088 	 * Create public key file.
2089 	 */
2090 	if ((fp = fopen(filename, "w")) == NULL) {
2091 		return (DST_R_WRITEERROR);
2092 	}
2093 
2094 	if (issymmetric(key)) {
2095 		access = 0;
2096 		isc_fsaccess_add(ISC_FSACCESS_OWNER,
2097 				 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
2098 				 &access);
2099 		(void)isc_fsaccess_set(filename, access);
2100 	}
2101 
2102 	/* Write key information in comments */
2103 	if ((type & DST_TYPE_KEY) == 0) {
2104 		fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
2105 			(key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ? "revoked "
2106 								   : "",
2107 			(key->key_flags & DNS_KEYFLAG_KSK) != 0 ? "key"
2108 								: "zone",
2109 			key->key_id);
2110 		ret = dns_name_print(key->key_name, fp);
2111 		if (ret != ISC_R_SUCCESS) {
2112 			fclose(fp);
2113 			return (ret);
2114 		}
2115 		fputc('\n', fp);
2116 
2117 		printtime(key, DST_TIME_CREATED, "; Created", fp);
2118 		printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
2119 		printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
2120 		printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
2121 		printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
2122 		printtime(key, DST_TIME_DELETE, "; Delete", fp);
2123 		printtime(key, DST_TIME_SYNCPUBLISH, "; SyncPublish", fp);
2124 		printtime(key, DST_TIME_SYNCDELETE, "; SyncDelete", fp);
2125 	}
2126 
2127 	/* Now print the actual key */
2128 	ret = dns_name_print(key->key_name, fp);
2129 	fprintf(fp, " ");
2130 
2131 	if (key->key_ttl != 0) {
2132 		fprintf(fp, "%u ", key->key_ttl);
2133 	}
2134 
2135 	isc_buffer_usedregion(&classb, &r);
2136 	if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) {
2137 		ret = DST_R_WRITEERROR;
2138 	}
2139 
2140 	if ((type & DST_TYPE_KEY) != 0) {
2141 		fprintf(fp, " KEY ");
2142 	} else {
2143 		fprintf(fp, " DNSKEY ");
2144 	}
2145 
2146 	isc_buffer_usedregion(&textb, &r);
2147 	if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) {
2148 		ret = DST_R_WRITEERROR;
2149 	}
2150 
2151 	fputc('\n', fp);
2152 	fflush(fp);
2153 	if (ferror(fp)) {
2154 		ret = DST_R_WRITEERROR;
2155 	}
2156 	fclose(fp);
2157 
2158 	return (ret);
2159 }
2160 
2161 static isc_result_t
2162 buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg,
2163 	      unsigned int type, const char *directory, isc_buffer_t *out) {
2164 	const char *suffix = "";
2165 	isc_result_t result;
2166 
2167 	REQUIRE(out != NULL);
2168 	if ((type & DST_TYPE_PRIVATE) != 0) {
2169 		suffix = ".private";
2170 	} else if ((type & DST_TYPE_PUBLIC) != 0) {
2171 		suffix = ".key";
2172 	} else if ((type & DST_TYPE_STATE) != 0) {
2173 		suffix = ".state";
2174 	}
2175 
2176 	if (directory != NULL) {
2177 		if (isc_buffer_availablelength(out) < strlen(directory)) {
2178 			return (ISC_R_NOSPACE);
2179 		}
2180 		isc_buffer_putstr(out, directory);
2181 		if (strlen(directory) > 0U &&
2182 		    directory[strlen(directory) - 1] != '/') {
2183 			isc_buffer_putstr(out, "/");
2184 		}
2185 	}
2186 	if (isc_buffer_availablelength(out) < 1) {
2187 		return (ISC_R_NOSPACE);
2188 	}
2189 	isc_buffer_putstr(out, "K");
2190 	result = dns_name_tofilenametext(name, false, out);
2191 	if (result != ISC_R_SUCCESS) {
2192 		return (result);
2193 	}
2194 
2195 	return (isc_buffer_printf(out, "+%03d+%05d%s", alg, id, suffix));
2196 }
2197 
2198 static isc_result_t
2199 computeid(dst_key_t *key) {
2200 	isc_buffer_t dnsbuf;
2201 	unsigned char dns_array[DST_KEY_MAXSIZE];
2202 	isc_region_t r;
2203 	isc_result_t ret;
2204 
2205 	isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
2206 	ret = dst_key_todns(key, &dnsbuf);
2207 	if (ret != ISC_R_SUCCESS) {
2208 		return (ret);
2209 	}
2210 
2211 	isc_buffer_usedregion(&dnsbuf, &r);
2212 	key->key_id = dst_region_computeid(&r);
2213 	key->key_rid = dst_region_computerid(&r);
2214 	return (ISC_R_SUCCESS);
2215 }
2216 
2217 static isc_result_t
2218 frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
2219 	   unsigned int protocol, dns_rdataclass_t rdclass,
2220 	   isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
2221 	dst_key_t *key;
2222 	isc_result_t ret;
2223 
2224 	REQUIRE(dns_name_isabsolute(name));
2225 	REQUIRE(source != NULL);
2226 	REQUIRE(mctx != NULL);
2227 	REQUIRE(keyp != NULL && *keyp == NULL);
2228 
2229 	key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
2230 	if (key == NULL) {
2231 		return (ISC_R_NOMEMORY);
2232 	}
2233 
2234 	if (isc_buffer_remaininglength(source) > 0) {
2235 		ret = algorithm_status(alg);
2236 		if (ret != ISC_R_SUCCESS) {
2237 			dst_key_free(&key);
2238 			return (ret);
2239 		}
2240 		if (key->func->fromdns == NULL) {
2241 			dst_key_free(&key);
2242 			return (DST_R_UNSUPPORTEDALG);
2243 		}
2244 
2245 		ret = key->func->fromdns(key, source);
2246 		if (ret != ISC_R_SUCCESS) {
2247 			dst_key_free(&key);
2248 			return (ret);
2249 		}
2250 	}
2251 
2252 	*keyp = key;
2253 	return (ISC_R_SUCCESS);
2254 }
2255 
2256 static isc_result_t
2257 algorithm_status(unsigned int alg) {
2258 	REQUIRE(dst_initialized);
2259 
2260 	if (dst_algorithm_supported(alg)) {
2261 		return (ISC_R_SUCCESS);
2262 	}
2263 	return (DST_R_UNSUPPORTEDALG);
2264 }
2265 
2266 static isc_result_t
2267 addsuffix(char *filename, int len, const char *odirname, const char *ofilename,
2268 	  const char *suffix) {
2269 	int olen = strlen(ofilename);
2270 	int n;
2271 
2272 	if (olen > 1 && ofilename[olen - 1] == '.') {
2273 		olen -= 1;
2274 	} else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0) {
2275 		olen -= 8;
2276 	} else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) {
2277 		olen -= 4;
2278 	}
2279 
2280 	if (odirname == NULL) {
2281 		n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
2282 	} else {
2283 		n = snprintf(filename, len, "%s/%.*s%s", odirname, olen,
2284 			     ofilename, suffix);
2285 	}
2286 	if (n < 0) {
2287 		return (ISC_R_FAILURE);
2288 	}
2289 	if (n >= len) {
2290 		return (ISC_R_NOSPACE);
2291 	}
2292 	return (ISC_R_SUCCESS);
2293 }
2294 
2295 isc_buffer_t *
2296 dst_key_tkeytoken(const dst_key_t *key) {
2297 	REQUIRE(VALID_KEY(key));
2298 	return (key->key_tkeytoken);
2299 }
2300 
2301 /*
2302  * A key is considered unused if it does not have any timing metadata set
2303  * other than "Created".
2304  *
2305  */
2306 bool
2307 dst_key_is_unused(dst_key_t *key) {
2308 	isc_stdtime_t val;
2309 	dst_key_state_t st;
2310 	int state_type;
2311 	bool state_type_set;
2312 
2313 	REQUIRE(VALID_KEY(key));
2314 
2315 	/*
2316 	 * None of the key timing metadata, except Created, may be set.  Key
2317 	 * state times may be set only if their respective state is HIDDEN.
2318 	 */
2319 	for (int i = 0; i < DST_MAX_TIMES + 1; i++) {
2320 		state_type_set = false;
2321 
2322 		switch (i) {
2323 		case DST_TIME_CREATED:
2324 			break;
2325 		case DST_TIME_DNSKEY:
2326 			state_type = DST_KEY_DNSKEY;
2327 			state_type_set = true;
2328 			break;
2329 		case DST_TIME_ZRRSIG:
2330 			state_type = DST_KEY_ZRRSIG;
2331 			state_type_set = true;
2332 			break;
2333 		case DST_TIME_KRRSIG:
2334 			state_type = DST_KEY_KRRSIG;
2335 			state_type_set = true;
2336 			break;
2337 		case DST_TIME_DS:
2338 			state_type = DST_KEY_DS;
2339 			state_type_set = true;
2340 			break;
2341 		default:
2342 			break;
2343 		}
2344 
2345 		/* Created is fine. */
2346 		if (i == DST_TIME_CREATED) {
2347 			continue;
2348 		}
2349 		/* No such timing metadata found, that is fine too. */
2350 		if (dst_key_gettime(key, i, &val) == ISC_R_NOTFOUND) {
2351 			continue;
2352 		}
2353 		/*
2354 		 * Found timing metadata and it is not related to key states.
2355 		 * This key is used.
2356 		 */
2357 		if (!state_type_set) {
2358 			return (false);
2359 		}
2360 		/*
2361 		 * If the state is not HIDDEN, the key is in use.
2362 		 * If the state is not set, this is odd and we default to NA.
2363 		 */
2364 		if (dst_key_getstate(key, state_type, &st) != ISC_R_SUCCESS) {
2365 			st = DST_KEY_STATE_NA;
2366 		}
2367 		if (st != DST_KEY_STATE_HIDDEN) {
2368 			return (false);
2369 		}
2370 	}
2371 	/* This key is unused. */
2372 	return (true);
2373 }
2374 
2375 static void
2376 get_ksk_zsk(dst_key_t *key, bool *ksk, bool *zsk) {
2377 	bool k = false, z = false;
2378 
2379 	if (dst_key_getbool(key, DST_BOOL_KSK, &k) == ISC_R_SUCCESS) {
2380 		*ksk = k;
2381 	} else {
2382 		*ksk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) != 0);
2383 	}
2384 	if (dst_key_getbool(key, DST_BOOL_ZSK, &z) == ISC_R_SUCCESS) {
2385 		*zsk = z;
2386 	} else {
2387 		*zsk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0);
2388 	}
2389 }
2390 
2391 /* Hints on key whether it can be published and/or used for signing. */
2392 
2393 bool
2394 dst_key_is_published(dst_key_t *key, isc_stdtime_t now,
2395 		     isc_stdtime_t *publish) {
2396 	dst_key_state_t state;
2397 	isc_result_t result;
2398 	isc_stdtime_t when;
2399 	bool state_ok = true, time_ok = false;
2400 
2401 	REQUIRE(VALID_KEY(key));
2402 
2403 	result = dst_key_gettime(key, DST_TIME_PUBLISH, &when);
2404 	if (result == ISC_R_SUCCESS) {
2405 		*publish = when;
2406 		time_ok = (when <= now);
2407 	}
2408 
2409 	/* Check key states:
2410 	 * If the DNSKEY state is RUMOURED or OMNIPRESENT, it means it
2411 	 * should be published.
2412 	 */
2413 	result = dst_key_getstate(key, DST_KEY_DNSKEY, &state);
2414 	if (result == ISC_R_SUCCESS) {
2415 		state_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2416 			    (state == DST_KEY_STATE_OMNIPRESENT));
2417 		/*
2418 		 * Key states trump timing metadata.
2419 		 * Ignore inactive time.
2420 		 */
2421 		time_ok = true;
2422 	}
2423 
2424 	return (state_ok && time_ok);
2425 }
2426 
2427 bool
2428 dst_key_is_active(dst_key_t *key, isc_stdtime_t now) {
2429 	dst_key_state_t state;
2430 	isc_result_t result;
2431 	isc_stdtime_t when = 0;
2432 	bool ksk = false, zsk = false, inactive = false;
2433 	bool ds_ok = true, zrrsig_ok = true, time_ok = false;
2434 
2435 	REQUIRE(VALID_KEY(key));
2436 
2437 	result = dst_key_gettime(key, DST_TIME_INACTIVE, &when);
2438 	if (result == ISC_R_SUCCESS) {
2439 		inactive = (when <= now);
2440 	}
2441 
2442 	result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when);
2443 	if (result == ISC_R_SUCCESS) {
2444 		time_ok = (when <= now);
2445 	}
2446 
2447 	get_ksk_zsk(key, &ksk, &zsk);
2448 
2449 	/* Check key states:
2450 	 * KSK: If the DS is RUMOURED or OMNIPRESENT the key is considered
2451 	 * active.
2452 	 */
2453 	if (ksk) {
2454 		result = dst_key_getstate(key, DST_KEY_DS, &state);
2455 		if (result == ISC_R_SUCCESS) {
2456 			ds_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2457 				 (state == DST_KEY_STATE_OMNIPRESENT));
2458 			/*
2459 			 * Key states trump timing metadata.
2460 			 * Ignore inactive time.
2461 			 */
2462 			time_ok = true;
2463 			inactive = false;
2464 		}
2465 	}
2466 	/*
2467 	 * ZSK: If the ZRRSIG state is RUMOURED or OMNIPRESENT, it means the
2468 	 * key is active.
2469 	 */
2470 	if (zsk) {
2471 		result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state);
2472 		if (result == ISC_R_SUCCESS) {
2473 			zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2474 				     (state == DST_KEY_STATE_OMNIPRESENT));
2475 			/*
2476 			 * Key states trump timing metadata.
2477 			 * Ignore inactive time.
2478 			 */
2479 			time_ok = true;
2480 			inactive = false;
2481 		}
2482 	}
2483 	return (ds_ok && zrrsig_ok && time_ok && !inactive);
2484 }
2485 
2486 bool
2487 dst_key_is_signing(dst_key_t *key, int role, isc_stdtime_t now,
2488 		   isc_stdtime_t *active) {
2489 	dst_key_state_t state;
2490 	isc_result_t result;
2491 	isc_stdtime_t when = 0;
2492 	bool ksk = false, zsk = false, inactive = false;
2493 	bool krrsig_ok = true, zrrsig_ok = true, time_ok = false;
2494 
2495 	REQUIRE(VALID_KEY(key));
2496 
2497 	result = dst_key_gettime(key, DST_TIME_INACTIVE, &when);
2498 	if (result == ISC_R_SUCCESS) {
2499 		inactive = (when <= now);
2500 	}
2501 
2502 	result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when);
2503 	if (result == ISC_R_SUCCESS) {
2504 		*active = when;
2505 		time_ok = (when <= now);
2506 	}
2507 
2508 	get_ksk_zsk(key, &ksk, &zsk);
2509 
2510 	/* Check key states:
2511 	 * If the RRSIG state is RUMOURED or OMNIPRESENT, it means the key
2512 	 * is active.
2513 	 */
2514 	if (ksk && role == DST_BOOL_KSK) {
2515 		result = dst_key_getstate(key, DST_KEY_KRRSIG, &state);
2516 		if (result == ISC_R_SUCCESS) {
2517 			krrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2518 				     (state == DST_KEY_STATE_OMNIPRESENT));
2519 			/*
2520 			 * Key states trump timing metadata.
2521 			 * Ignore inactive time.
2522 			 */
2523 			time_ok = true;
2524 			inactive = false;
2525 		}
2526 	} else if (zsk && role == DST_BOOL_ZSK) {
2527 		result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state);
2528 		if (result == ISC_R_SUCCESS) {
2529 			zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) ||
2530 				     (state == DST_KEY_STATE_OMNIPRESENT));
2531 			/*
2532 			 * Key states trump timing metadata.
2533 			 * Ignore inactive time.
2534 			 */
2535 			time_ok = true;
2536 			inactive = false;
2537 		}
2538 	}
2539 	return (krrsig_ok && zrrsig_ok && time_ok && !inactive);
2540 }
2541 
2542 bool
2543 dst_key_is_revoked(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *revoke) {
2544 	isc_result_t result;
2545 	isc_stdtime_t when = 0;
2546 	bool time_ok = false;
2547 
2548 	REQUIRE(VALID_KEY(key));
2549 
2550 	result = dst_key_gettime(key, DST_TIME_REVOKE, &when);
2551 	if (result == ISC_R_SUCCESS) {
2552 		*revoke = when;
2553 		time_ok = (when <= now);
2554 	}
2555 
2556 	return (time_ok);
2557 }
2558 
2559 bool
2560 dst_key_is_removed(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *remove) {
2561 	dst_key_state_t state;
2562 	isc_result_t result;
2563 	isc_stdtime_t when = 0;
2564 	bool state_ok = true, time_ok = false;
2565 
2566 	REQUIRE(VALID_KEY(key));
2567 
2568 	if (dst_key_is_unused(key)) {
2569 		/* This key was never used. */
2570 		return (false);
2571 	}
2572 
2573 	result = dst_key_gettime(key, DST_TIME_DELETE, &when);
2574 	if (result == ISC_R_SUCCESS) {
2575 		*remove = when;
2576 		time_ok = (when <= now);
2577 	}
2578 
2579 	/* Check key states:
2580 	 * If the DNSKEY state is UNRETENTIVE or HIDDEN, it means the key
2581 	 * should not be published.
2582 	 */
2583 	result = dst_key_getstate(key, DST_KEY_DNSKEY, &state);
2584 	if (result == ISC_R_SUCCESS) {
2585 		state_ok = ((state == DST_KEY_STATE_UNRETENTIVE) ||
2586 			    (state == DST_KEY_STATE_HIDDEN));
2587 		/*
2588 		 * Key states trump timing metadata.
2589 		 * Ignore delete time.
2590 		 */
2591 		time_ok = true;
2592 	}
2593 
2594 	return (state_ok && time_ok);
2595 }
2596 
2597 dst_key_state_t
2598 dst_key_goal(dst_key_t *key) {
2599 	dst_key_state_t state;
2600 	isc_result_t result;
2601 
2602 	result = dst_key_getstate(key, DST_KEY_GOAL, &state);
2603 	if (result == ISC_R_SUCCESS) {
2604 		return (state);
2605 	}
2606 	return (DST_KEY_STATE_HIDDEN);
2607 }
2608 
2609 void
2610 dst_key_copy_metadata(dst_key_t *to, dst_key_t *from) {
2611 	dst_key_state_t state;
2612 	isc_stdtime_t when;
2613 	uint32_t num;
2614 	bool yesno;
2615 	isc_result_t result;
2616 
2617 	REQUIRE(VALID_KEY(to));
2618 	REQUIRE(VALID_KEY(from));
2619 
2620 	for (int i = 0; i < DST_MAX_TIMES + 1; i++) {
2621 		result = dst_key_gettime(from, i, &when);
2622 		if (result == ISC_R_SUCCESS) {
2623 			dst_key_settime(to, i, when);
2624 		} else {
2625 			dst_key_unsettime(to, i);
2626 		}
2627 	}
2628 
2629 	for (int i = 0; i < DST_MAX_NUMERIC + 1; i++) {
2630 		result = dst_key_getnum(from, i, &num);
2631 		if (result == ISC_R_SUCCESS) {
2632 			dst_key_setnum(to, i, num);
2633 		} else {
2634 			dst_key_unsetnum(to, i);
2635 		}
2636 	}
2637 
2638 	for (int i = 0; i < DST_MAX_BOOLEAN + 1; i++) {
2639 		result = dst_key_getbool(from, i, &yesno);
2640 		if (result == ISC_R_SUCCESS) {
2641 			dst_key_setbool(to, i, yesno);
2642 		} else {
2643 			dst_key_unsetnum(to, i);
2644 		}
2645 	}
2646 
2647 	for (int i = 0; i < DST_MAX_KEYSTATES + 1; i++) {
2648 		result = dst_key_getstate(from, i, &state);
2649 		if (result == ISC_R_SUCCESS) {
2650 			dst_key_setstate(to, i, state);
2651 		} else {
2652 			dst_key_unsetstate(to, i);
2653 		}
2654 	}
2655 }
2656