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