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