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