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