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