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