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