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