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