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