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