1/* $NetBSD: keymgr.c,v 1.1 2024/02/18 20:57:32 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 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/*! \file */ 17 18#include <inttypes.h> 19#include <stdbool.h> 20#include <stdlib.h> 21#include <unistd.h> 22 23#include <isc/buffer.h> 24#include <isc/dir.h> 25#include <isc/mem.h> 26#include <isc/print.h> 27#include <isc/string.h> 28#include <isc/util.h> 29 30#include <dns/dnssec.h> 31#include <dns/kasp.h> 32#include <dns/keymgr.h> 33#include <dns/keyvalues.h> 34#include <dns/log.h> 35#include <dns/result.h> 36 37#include <dst/dst.h> 38#include <dst/result.h> 39 40#define RETERR(x) \ 41 do { \ 42 result = (x); \ 43 if (result != ISC_R_SUCCESS) \ 44 goto failure; \ 45 } while (0) 46 47/* 48 * Set key state to `target` state and change last changed 49 * to `time`, only if key state has not been set before. 50 */ 51#define INITIALIZE_STATE(key, state, timing, target, time) \ 52 do { \ 53 dst_key_state_t s; \ 54 if (dst_key_getstate((key), (state), &s) == ISC_R_NOTFOUND) { \ 55 dst_key_setstate((key), (state), (target)); \ 56 dst_key_settime((key), (timing), time); \ 57 } \ 58 } while (0) 59 60/* Shorter keywords for better readability. */ 61#define HIDDEN DST_KEY_STATE_HIDDEN 62#define RUMOURED DST_KEY_STATE_RUMOURED 63#define OMNIPRESENT DST_KEY_STATE_OMNIPRESENT 64#define UNRETENTIVE DST_KEY_STATE_UNRETENTIVE 65#define NA DST_KEY_STATE_NA 66 67/* Quickly get key state timing metadata. */ 68#define NUM_KEYSTATES (DST_MAX_KEYSTATES) 69static int keystatetimes[NUM_KEYSTATES] = { DST_TIME_DNSKEY, DST_TIME_ZRRSIG, 70 DST_TIME_KRRSIG, DST_TIME_DS }; 71/* Readable key state types and values. */ 72static const char *keystatetags[NUM_KEYSTATES] = { "DNSKEY", "ZRRSIG", "KRRSIG", 73 "DS" }; 74static const char *keystatestrings[4] = { "HIDDEN", "RUMOURED", "OMNIPRESENT", 75 "UNRETENTIVE" }; 76 77/* 78 * Print key role. 79 * 80 */ 81static const char * 82keymgr_keyrole(dst_key_t *key) { 83 bool ksk = false, zsk = false; 84 isc_result_t ret; 85 ret = dst_key_getbool(key, DST_BOOL_KSK, &ksk); 86 if (ret != ISC_R_SUCCESS) { 87 return ("UNKNOWN"); 88 } 89 ret = dst_key_getbool(key, DST_BOOL_ZSK, &zsk); 90 if (ret != ISC_R_SUCCESS) { 91 return ("UNKNOWN"); 92 } 93 if (ksk && zsk) { 94 return ("CSK"); 95 } else if (ksk) { 96 return ("KSK"); 97 } else if (zsk) { 98 return ("ZSK"); 99 } 100 return ("NOSIGN"); 101} 102 103/* 104 * Set the remove time on key given its retire time. 105 * 106 */ 107static void 108keymgr_settime_remove(dns_dnsseckey_t *key, dns_kasp_t *kasp) { 109 isc_stdtime_t retire = 0, remove = 0, ksk_remove = 0, zsk_remove = 0; 110 bool zsk = false, ksk = false; 111 isc_result_t ret; 112 113 REQUIRE(key != NULL); 114 REQUIRE(key->key != NULL); 115 116 ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire); 117 if (ret != ISC_R_SUCCESS) { 118 return; 119 } 120 121 ret = dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk); 122 if (ret == ISC_R_SUCCESS && zsk) { 123 /* ZSK: Iret = Dsgn + Dprp + TTLsig */ 124 zsk_remove = retire + dns_kasp_zonemaxttl(kasp) + 125 dns_kasp_zonepropagationdelay(kasp) + 126 dns_kasp_retiresafety(kasp) + 127 dns_kasp_signdelay(kasp); 128 } 129 ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk); 130 if (ret == ISC_R_SUCCESS && ksk) { 131 /* KSK: Iret = DprpP + TTLds */ 132 ksk_remove = retire + dns_kasp_dsttl(kasp) + 133 dns_kasp_parentpropagationdelay(kasp) + 134 dns_kasp_retiresafety(kasp); 135 } 136 137 remove = ksk_remove > zsk_remove ? ksk_remove : zsk_remove; 138 dst_key_settime(key->key, DST_TIME_DELETE, remove); 139} 140 141/* 142 * Set the SyncPublish time (when the DS may be submitted to the parent) 143 * 144 */ 145static void 146keymgr_settime_syncpublish(dns_dnsseckey_t *key, dns_kasp_t *kasp, bool first) { 147 isc_stdtime_t published, syncpublish; 148 bool ksk = false; 149 isc_result_t ret; 150 151 REQUIRE(key != NULL); 152 REQUIRE(key->key != NULL); 153 154 ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &published); 155 if (ret != ISC_R_SUCCESS) { 156 return; 157 } 158 159 ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk); 160 if (ret != ISC_R_SUCCESS || !ksk) { 161 return; 162 } 163 164 syncpublish = published + dst_key_getttl(key->key) + 165 dns_kasp_zonepropagationdelay(kasp) + 166 dns_kasp_publishsafety(kasp); 167 if (first) { 168 /* Also need to wait until the signatures are omnipresent. */ 169 isc_stdtime_t zrrsig_present; 170 zrrsig_present = published + dns_kasp_zonemaxttl(kasp) + 171 dns_kasp_zonepropagationdelay(kasp) + 172 dns_kasp_publishsafety(kasp); 173 if (zrrsig_present > syncpublish) { 174 syncpublish = zrrsig_present; 175 } 176 } 177 dst_key_settime(key->key, DST_TIME_SYNCPUBLISH, syncpublish); 178} 179 180/* 181 * Calculate prepublication time of a successor key of 'key'. 182 * This function can have side effects: 183 * 1. If there is no active time set, which would be super weird, set it now. 184 * 2. If there is no published time set, also super weird, set it now. 185 * 3. If there is no syncpublished time set, set it now. 186 * 4. If the lifetime is not set, it will be set now. 187 * 5. If there should be a retire time and it is not set, it will be set now. 188 * 6. The removed time is adjusted accordingly. 189 * 190 * This returns when the successor key needs to be published in the zone. 191 * A special value of 0 means there is no need for a successor. 192 * 193 */ 194static isc_stdtime_t 195keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp, 196 uint32_t lifetime, isc_stdtime_t now) { 197 isc_result_t ret; 198 isc_stdtime_t active, retire, pub, prepub; 199 bool zsk = false, ksk = false; 200 201 REQUIRE(key != NULL); 202 REQUIRE(key->key != NULL); 203 204 active = 0; 205 pub = 0; 206 retire = 0; 207 208 /* 209 * An active key must have publish and activate timing 210 * metadata. 211 */ 212 ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); 213 if (ret != ISC_R_SUCCESS) { 214 /* Super weird, but if it happens, set it to now. */ 215 dst_key_settime(key->key, DST_TIME_ACTIVATE, now); 216 active = now; 217 } 218 ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub); 219 if (ret != ISC_R_SUCCESS) { 220 /* Super weird, but if it happens, set it to now. */ 221 dst_key_settime(key->key, DST_TIME_PUBLISH, now); 222 pub = now; 223 } 224 225 /* 226 * Calculate prepublication time. 227 */ 228 prepub = dst_key_getttl(key->key) + dns_kasp_publishsafety(kasp) + 229 dns_kasp_zonepropagationdelay(kasp); 230 ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk); 231 if (ret == ISC_R_SUCCESS && ksk) { 232 isc_stdtime_t syncpub; 233 234 /* 235 * Set PublishCDS if not set. 236 */ 237 ret = dst_key_gettime(key->key, DST_TIME_SYNCPUBLISH, &syncpub); 238 if (ret != ISC_R_SUCCESS) { 239 uint32_t tag; 240 isc_stdtime_t syncpub1, syncpub2; 241 242 syncpub1 = pub + prepub; 243 syncpub2 = 0; 244 ret = dst_key_getnum(key->key, DST_NUM_PREDECESSOR, 245 &tag); 246 if (ret != ISC_R_SUCCESS) { 247 /* 248 * No predecessor, wait for zone to be 249 * completely signed. 250 */ 251 syncpub2 = pub + dns_kasp_zonemaxttl(kasp) + 252 dns_kasp_publishsafety(kasp) + 253 dns_kasp_zonepropagationdelay(kasp); 254 } 255 256 syncpub = syncpub1 > syncpub2 ? syncpub1 : syncpub2; 257 dst_key_settime(key->key, DST_TIME_SYNCPUBLISH, 258 syncpub); 259 } 260 } 261 262 /* 263 * Not sure what to do when dst_key_getbool() fails here. Extending 264 * the prepublication time anyway is arguably the safest thing to do, 265 * so ignore the result code. 266 */ 267 (void)dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk); 268 269 ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire); 270 if (ret != ISC_R_SUCCESS) { 271 uint32_t klifetime = 0; 272 273 ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime); 274 if (ret != ISC_R_SUCCESS) { 275 dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime); 276 klifetime = lifetime; 277 } 278 if (klifetime == 0) { 279 /* 280 * No inactive time and no lifetime, 281 * so no need to start a rollover. 282 */ 283 return (0); 284 } 285 286 retire = active + klifetime; 287 dst_key_settime(key->key, DST_TIME_INACTIVE, retire); 288 } 289 290 /* 291 * Update remove time. 292 */ 293 keymgr_settime_remove(key, kasp); 294 295 /* 296 * Publish successor 'prepub' time before the 'retire' time of 'key'. 297 */ 298 if (prepub > retire) { 299 /* We should have already prepublished the new key. */ 300 return (now); 301 } 302 return (retire - prepub); 303} 304 305static void 306keymgr_key_retire(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now) { 307 char keystr[DST_KEY_FORMATSIZE]; 308 isc_result_t ret; 309 isc_stdtime_t retire; 310 dst_key_state_t s; 311 bool ksk = false, zsk = false; 312 313 REQUIRE(key != NULL); 314 REQUIRE(key->key != NULL); 315 316 /* This key wants to retire and hide in a corner. */ 317 ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire); 318 if (ret != ISC_R_SUCCESS || (retire > now)) { 319 dst_key_settime(key->key, DST_TIME_INACTIVE, now); 320 } 321 dst_key_setstate(key->key, DST_KEY_GOAL, HIDDEN); 322 keymgr_settime_remove(key, kasp); 323 324 /* This key may not have key states set yet. Pretend as if they are 325 * in the OMNIPRESENT state. 326 */ 327 if (dst_key_getstate(key->key, DST_KEY_DNSKEY, &s) != ISC_R_SUCCESS) { 328 dst_key_setstate(key->key, DST_KEY_DNSKEY, OMNIPRESENT); 329 dst_key_settime(key->key, DST_TIME_DNSKEY, now); 330 } 331 332 ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk); 333 if (ret == ISC_R_SUCCESS && ksk) { 334 if (dst_key_getstate(key->key, DST_KEY_KRRSIG, &s) != 335 ISC_R_SUCCESS) 336 { 337 dst_key_setstate(key->key, DST_KEY_KRRSIG, OMNIPRESENT); 338 dst_key_settime(key->key, DST_TIME_KRRSIG, now); 339 } 340 if (dst_key_getstate(key->key, DST_KEY_DS, &s) != ISC_R_SUCCESS) 341 { 342 dst_key_setstate(key->key, DST_KEY_DS, OMNIPRESENT); 343 dst_key_settime(key->key, DST_TIME_DS, now); 344 } 345 } 346 ret = dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk); 347 if (ret == ISC_R_SUCCESS && zsk) { 348 if (dst_key_getstate(key->key, DST_KEY_ZRRSIG, &s) != 349 ISC_R_SUCCESS) 350 { 351 dst_key_setstate(key->key, DST_KEY_ZRRSIG, OMNIPRESENT); 352 dst_key_settime(key->key, DST_TIME_ZRRSIG, now); 353 } 354 } 355 356 dst_key_format(key->key, keystr, sizeof(keystr)); 357 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC, 358 ISC_LOG_INFO, "keymgr: retire DNSKEY %s (%s)", keystr, 359 keymgr_keyrole(key->key)); 360} 361 362/* 363 * Check if a dnsseckey matches kasp key configuration. A dnsseckey matches 364 * if it has the same algorithm and size, and if it has the same role as the 365 * kasp key configuration. 366 * 367 */ 368static bool 369keymgr_dnsseckey_kaspkey_match(dns_dnsseckey_t *dkey, dns_kasp_key_t *kkey) { 370 dst_key_t *key; 371 isc_result_t ret; 372 bool role = false; 373 374 REQUIRE(dkey != NULL); 375 REQUIRE(kkey != NULL); 376 377 key = dkey->key; 378 379 /* Matching algorithms? */ 380 if (dst_key_alg(key) != dns_kasp_key_algorithm(kkey)) { 381 return (false); 382 } 383 /* Matching length? */ 384 if (dst_key_size(key) != dns_kasp_key_size(kkey)) { 385 return (false); 386 } 387 /* Matching role? */ 388 ret = dst_key_getbool(key, DST_BOOL_KSK, &role); 389 if (ret != ISC_R_SUCCESS || role != dns_kasp_key_ksk(kkey)) { 390 return (false); 391 } 392 ret = dst_key_getbool(key, DST_BOOL_ZSK, &role); 393 if (ret != ISC_R_SUCCESS || role != dns_kasp_key_zsk(kkey)) { 394 return (false); 395 } 396 397 /* Found a match. */ 398 return (true); 399} 400 401static bool 402keymgr_keyid_conflict(dst_key_t *newkey, dns_dnsseckeylist_t *keys) { 403 uint16_t id = dst_key_id(newkey); 404 uint32_t rid = dst_key_rid(newkey); 405 uint32_t alg = dst_key_alg(newkey); 406 407 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keys); dkey != NULL; 408 dkey = ISC_LIST_NEXT(dkey, link)) 409 { 410 if (dst_key_alg(dkey->key) != alg) { 411 continue; 412 } 413 if (dst_key_id(dkey->key) == id || 414 dst_key_rid(dkey->key) == id || 415 dst_key_id(dkey->key) == rid || 416 dst_key_rid(dkey->key) == rid) 417 { 418 return (true); 419 } 420 } 421 return (false); 422} 423 424/* 425 * Create a new key for 'origin' given the kasp key configuration 'kkey'. 426 * This will check for key id collisions with keys in 'keylist'. 427 * The created key will be stored in 'dst_key'. 428 * 429 */ 430static isc_result_t 431keymgr_createkey(dns_kasp_key_t *kkey, const dns_name_t *origin, 432 dns_rdataclass_t rdclass, isc_mem_t *mctx, 433 dns_dnsseckeylist_t *keylist, dns_dnsseckeylist_t *newkeys, 434 dst_key_t **dst_key) { 435 bool conflict = false; 436 int keyflags = DNS_KEYOWNER_ZONE; 437 isc_result_t result = ISC_R_SUCCESS; 438 dst_key_t *newkey = NULL; 439 440 do { 441 uint32_t algo = dns_kasp_key_algorithm(kkey); 442 int size = dns_kasp_key_size(kkey); 443 444 if (dns_kasp_key_ksk(kkey)) { 445 keyflags |= DNS_KEYFLAG_KSK; 446 } 447 RETERR(dst_key_generate(origin, algo, size, 0, keyflags, 448 DNS_KEYPROTO_DNSSEC, rdclass, mctx, 449 &newkey, NULL)); 450 451 /* Key collision? */ 452 conflict = keymgr_keyid_conflict(newkey, keylist); 453 if (!conflict) { 454 conflict = keymgr_keyid_conflict(newkey, newkeys); 455 } 456 if (conflict) { 457 /* Try again. */ 458 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 459 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 460 "keymgr: key collision id %d", 461 dst_key_id(newkey)); 462 dst_key_free(&newkey); 463 } 464 } while (conflict); 465 466 INSIST(!conflict); 467 dst_key_setnum(newkey, DST_NUM_LIFETIME, dns_kasp_key_lifetime(kkey)); 468 dst_key_setbool(newkey, DST_BOOL_KSK, dns_kasp_key_ksk(kkey)); 469 dst_key_setbool(newkey, DST_BOOL_ZSK, dns_kasp_key_zsk(kkey)); 470 *dst_key = newkey; 471 return (ISC_R_SUCCESS); 472 473failure: 474 return (result); 475} 476 477/* 478 * Return the desired state for this record 'type'. The desired state depends 479 * on whether the key wants to be active, or wants to retire. This implements 480 * the edges of our state machine: 481 * 482 * ----> OMNIPRESENT ---- 483 * | | 484 * | \|/ 485 * 486 * RUMOURED <----> UNRETENTIVE 487 * 488 * /|\ | 489 * | | 490 * ---- HIDDEN <---- 491 * 492 * A key that wants to be active eventually wants to have its record types 493 * in the OMNIPRESENT state (that is, all resolvers that know about these 494 * type of records know about these records specifically). 495 * 496 * A key that wants to be retired eventually wants to have its record types 497 * in the HIDDEN state (that is, all resolvers that know about these type 498 * of records specifically don't know about these records). 499 * 500 */ 501static dst_key_state_t 502keymgr_desiredstate(dns_dnsseckey_t *key, dst_key_state_t state) { 503 dst_key_state_t goal; 504 505 if (dst_key_getstate(key->key, DST_KEY_GOAL, &goal) != ISC_R_SUCCESS) { 506 /* No goal? No movement. */ 507 return (state); 508 } 509 510 if (goal == HIDDEN) { 511 switch (state) { 512 case RUMOURED: 513 case OMNIPRESENT: 514 return (UNRETENTIVE); 515 case HIDDEN: 516 case UNRETENTIVE: 517 return (HIDDEN); 518 default: 519 return (state); 520 } 521 } else if (goal == OMNIPRESENT) { 522 switch (state) { 523 case RUMOURED: 524 case OMNIPRESENT: 525 return (OMNIPRESENT); 526 case HIDDEN: 527 case UNRETENTIVE: 528 return (RUMOURED); 529 default: 530 return (state); 531 } 532 } 533 534 /* Unknown goal. */ 535 return (state); 536} 537 538/* 539 * Check if 'key' matches specific 'states'. 540 * A state in 'states' that is NA matches any state. 541 * A state in 'states' that is HIDDEN also matches if the state is not set. 542 * If 'next_state' is set (not NA), we are pretending as if record 'type' of 543 * 'subject' key already transitioned to the 'next state'. 544 * 545 */ 546static bool 547keymgr_key_match_state(dst_key_t *key, dst_key_t *subject, int type, 548 dst_key_state_t next_state, 549 dst_key_state_t states[NUM_KEYSTATES]) { 550 REQUIRE(key != NULL); 551 552 for (int i = 0; i < NUM_KEYSTATES; i++) { 553 dst_key_state_t state; 554 if (states[i] == NA) { 555 continue; 556 } 557 if (next_state != NA && i == type && 558 dst_key_id(key) == dst_key_id(subject)) 559 { 560 /* Check next state rather than current state. */ 561 state = next_state; 562 } else if (dst_key_getstate(key, i, &state) != ISC_R_SUCCESS) { 563 /* This is fine only if expected state is HIDDEN. */ 564 if (states[i] != HIDDEN) { 565 return (false); 566 } 567 continue; 568 } 569 if (state != states[i]) { 570 return (false); 571 } 572 } 573 /* Match. */ 574 return (true); 575} 576 577/* 578 * Key d directly depends on k if d is the direct predecessor of k. 579 */ 580static bool 581keymgr_direct_dep(dst_key_t *d, dst_key_t *k) { 582 uint32_t s, p; 583 584 if (dst_key_getnum(d, DST_NUM_SUCCESSOR, &s) != ISC_R_SUCCESS) { 585 return (false); 586 } 587 if (dst_key_getnum(k, DST_NUM_PREDECESSOR, &p) != ISC_R_SUCCESS) { 588 return (false); 589 } 590 return (dst_key_id(d) == p && dst_key_id(k) == s); 591} 592 593/* 594 * Determine which key (if any) has a dependency on k. 595 */ 596static bool 597keymgr_dep(dst_key_t *k, dns_dnsseckeylist_t *keyring, uint32_t *dep) { 598 for (dns_dnsseckey_t *d = ISC_LIST_HEAD(*keyring); d != NULL; 599 d = ISC_LIST_NEXT(d, link)) 600 { 601 /* 602 * Check if k is a direct successor of d, e.g. d depends on k. 603 */ 604 if (keymgr_direct_dep(d->key, k)) { 605 if (dep != NULL) { 606 *dep = dst_key_id(d->key); 607 } 608 return (true); 609 } 610 } 611 return (false); 612} 613 614/* 615 * Check if a 'z' is a successor of 'x'. 616 * This implements Equation(2) of "Flexible and Robust Key Rollover". 617 */ 618static bool 619keymgr_key_is_successor(dst_key_t *x, dst_key_t *z, dst_key_t *key, int type, 620 dst_key_state_t next_state, 621 dns_dnsseckeylist_t *keyring) { 622 uint32_t dep_x; 623 uint32_t dep_z; 624 625 /* 626 * The successor relation requires that the predecessor key must not 627 * have any other keys relying on it. In other words, there must be 628 * nothing depending on x. 629 */ 630 if (keymgr_dep(x, keyring, &dep_x)) { 631 return (false); 632 } 633 634 /* 635 * If there is no keys relying on key z, then z is not a successor. 636 */ 637 if (!keymgr_dep(z, keyring, &dep_z)) { 638 return (false); 639 } 640 641 /* 642 * x depends on z, thus key z is a direct successor of key x. 643 */ 644 if (dst_key_id(x) == dep_z) { 645 return (true); 646 } 647 648 /* 649 * It is possible to roll keys faster than the time required to finish 650 * the rollover procedure. For example, consider the keys x, y, z. 651 * Key x is currently published and is going to be replaced by y. The 652 * DNSKEY for x is removed from the zone and at the same moment the 653 * DNSKEY for y is introduced. Key y is a direct dependency for key x 654 * and is therefore the successor of x. However, before the new DNSKEY 655 * has been propagated, key z will replace key y. The DNSKEY for y is 656 * removed and moves into the same state as key x. Key y now directly 657 * depends on key z, and key z will be a new successor key for x. 658 */ 659 dst_key_state_t zst[NUM_KEYSTATES] = { NA, NA, NA, NA }; 660 for (int i = 0; i < NUM_KEYSTATES; i++) { 661 dst_key_state_t state; 662 if (dst_key_getstate(z, i, &state) != ISC_R_SUCCESS) { 663 continue; 664 } 665 zst[i] = state; 666 } 667 668 for (dns_dnsseckey_t *y = ISC_LIST_HEAD(*keyring); y != NULL; 669 y = ISC_LIST_NEXT(y, link)) 670 { 671 if (dst_key_id(y->key) == dst_key_id(z)) { 672 continue; 673 } 674 675 if (dst_key_id(y->key) != dep_z) { 676 continue; 677 } 678 /* 679 * This is another key y, that depends on key z. It may be 680 * part of the successor relation if the key states match 681 * those of key z. 682 */ 683 684 if (keymgr_key_match_state(y->key, key, type, next_state, zst)) 685 { 686 /* 687 * If y is a successor of x, then z is also a 688 * successor of x. 689 */ 690 return (keymgr_key_is_successor(x, y->key, key, type, 691 next_state, keyring)); 692 } 693 } 694 695 return (false); 696} 697 698/* 699 * Check if a key exists in 'keyring' that matches 'states'. 700 * 701 * If 'match_algorithms', the key must also match the algorithm of 'key'. 702 * If 'next_state' is not NA, we are actually looking for a key as if 703 * 'key' already transitioned to the next state. 704 * If 'check_successor', we also want to make sure there is a successor 705 * relationship with the found key that matches 'states2'. 706 */ 707static bool 708keymgr_key_exists_with_state(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, 709 int type, dst_key_state_t next_state, 710 dst_key_state_t states[NUM_KEYSTATES], 711 dst_key_state_t states2[NUM_KEYSTATES], 712 bool check_successor, bool match_algorithms) { 713 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 714 dkey = ISC_LIST_NEXT(dkey, link)) 715 { 716 if (match_algorithms && 717 (dst_key_alg(dkey->key) != dst_key_alg(key->key))) 718 { 719 continue; 720 } 721 722 if (!keymgr_key_match_state(dkey->key, key->key, type, 723 next_state, states)) 724 { 725 continue; 726 } 727 728 /* Found a match. */ 729 if (!check_successor) { 730 return (true); 731 } 732 733 /* 734 * We have to make sure that the key we are checking, also 735 * has a successor relationship with another key. 736 */ 737 for (dns_dnsseckey_t *skey = ISC_LIST_HEAD(*keyring); 738 skey != NULL; skey = ISC_LIST_NEXT(skey, link)) 739 { 740 if (skey == dkey) { 741 continue; 742 } 743 744 if (!keymgr_key_match_state(skey->key, key->key, type, 745 next_state, states2)) 746 { 747 continue; 748 } 749 750 /* 751 * Found a possible successor, check. 752 */ 753 if (keymgr_key_is_successor(dkey->key, skey->key, 754 key->key, type, next_state, 755 keyring)) 756 { 757 return (true); 758 } 759 } 760 } 761 /* No match. */ 762 return (false); 763} 764 765/* 766 * Check if a key has a successor. 767 */ 768static bool 769keymgr_key_has_successor(dns_dnsseckey_t *predecessor, 770 dns_dnsseckeylist_t *keyring) { 771 for (dns_dnsseckey_t *successor = ISC_LIST_HEAD(*keyring); 772 successor != NULL; successor = ISC_LIST_NEXT(successor, link)) 773 { 774 if (keymgr_direct_dep(predecessor->key, successor->key)) { 775 return (true); 776 } 777 } 778 return (false); 779} 780 781/* 782 * Check if all keys have their DS hidden. If not, then there must be at 783 * least one key with an OMNIPRESENT DNSKEY. 784 * 785 * If 'next_state' is not NA, we are actually looking for a key as if 786 * 'key' already transitioned to the next state. 787 * If 'match_algorithms', only consider keys with same algorithm of 'key'. 788 * 789 */ 790static bool 791keymgr_ds_hidden_or_chained(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, 792 int type, dst_key_state_t next_state, 793 bool match_algorithms, bool must_be_hidden) { 794 /* (3e) */ 795 dst_key_state_t dnskey_chained[NUM_KEYSTATES] = { OMNIPRESENT, NA, 796 OMNIPRESENT, NA }; 797 dst_key_state_t ds_hidden[NUM_KEYSTATES] = { NA, NA, NA, HIDDEN }; 798 /* successor n/a */ 799 dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA }; 800 801 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 802 dkey = ISC_LIST_NEXT(dkey, link)) 803 { 804 if (match_algorithms && 805 (dst_key_alg(dkey->key) != dst_key_alg(key->key))) 806 { 807 continue; 808 } 809 810 if (keymgr_key_match_state(dkey->key, key->key, type, 811 next_state, ds_hidden)) 812 { 813 /* This key has its DS hidden. */ 814 continue; 815 } 816 817 if (must_be_hidden) { 818 return (false); 819 } 820 821 /* 822 * This key does not have its DS hidden. There must be at 823 * least one key with the same algorithm that provides a 824 * chain of trust (can be this key). 825 */ 826 if (keymgr_key_match_state(dkey->key, key->key, type, 827 next_state, dnskey_chained)) 828 { 829 /* This DNSKEY and KRRSIG are OMNIPRESENT. */ 830 continue; 831 } 832 833 /* 834 * Perhaps another key provides a chain of trust. 835 */ 836 dnskey_chained[DST_KEY_DS] = OMNIPRESENT; 837 if (!keymgr_key_exists_with_state(keyring, key, type, 838 next_state, dnskey_chained, 839 na, false, match_algorithms)) 840 { 841 /* There is no chain of trust. */ 842 return (false); 843 } 844 } 845 /* All good. */ 846 return (true); 847} 848 849/* 850 * Check if all keys have their DNSKEY hidden. If not, then there must be at 851 * least one key with an OMNIPRESENT ZRRSIG. 852 * 853 * If 'next_state' is not NA, we are actually looking for a key as if 854 * 'key' already transitioned to the next state. 855 * If 'match_algorithms', only consider keys with same algorithm of 'key'. 856 * 857 */ 858static bool 859keymgr_dnskey_hidden_or_chained(dns_dnsseckeylist_t *keyring, 860 dns_dnsseckey_t *key, int type, 861 dst_key_state_t next_state, 862 bool match_algorithms) { 863 /* (3i) */ 864 dst_key_state_t rrsig_chained[NUM_KEYSTATES] = { OMNIPRESENT, 865 OMNIPRESENT, NA, NA }; 866 dst_key_state_t dnskey_hidden[NUM_KEYSTATES] = { HIDDEN, NA, NA, NA }; 867 /* successor n/a */ 868 dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA }; 869 870 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 871 dkey = ISC_LIST_NEXT(dkey, link)) 872 { 873 if (match_algorithms && 874 (dst_key_alg(dkey->key) != dst_key_alg(key->key))) 875 { 876 continue; 877 } 878 879 if (keymgr_key_match_state(dkey->key, key->key, type, 880 next_state, dnskey_hidden)) 881 { 882 /* This key has its DNSKEY hidden. */ 883 continue; 884 } 885 886 /* 887 * This key does not have its DNSKEY hidden. There must be at 888 * least one key with the same algorithm that has its RRSIG 889 * records OMNIPRESENT. 890 */ 891 (void)dst_key_getstate(dkey->key, DST_KEY_DNSKEY, 892 &rrsig_chained[DST_KEY_DNSKEY]); 893 if (!keymgr_key_exists_with_state(keyring, key, type, 894 next_state, rrsig_chained, na, 895 false, match_algorithms)) 896 { 897 /* There is no chain of trust. */ 898 return (false); 899 } 900 } 901 /* All good. */ 902 return (true); 903} 904 905/* 906 * Check for existence of DS. 907 * 908 */ 909static bool 910keymgr_have_ds(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type, 911 dst_key_state_t next_state, bool secure_to_insecure) { 912 /* (3a) */ 913 dst_key_state_t states[2][NUM_KEYSTATES] = { 914 /* DNSKEY, ZRRSIG, KRRSIG, DS */ 915 { NA, NA, NA, OMNIPRESENT }, /* DS present */ 916 { NA, NA, NA, RUMOURED } /* DS introducing */ 917 }; 918 /* successor n/a */ 919 dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA }; 920 921 /* 922 * Equation (3a): 923 * There is a key with the DS in either RUMOURD or OMNIPRESENT state. 924 */ 925 return (keymgr_key_exists_with_state(keyring, key, type, next_state, 926 states[0], na, false, false) || 927 keymgr_key_exists_with_state(keyring, key, type, next_state, 928 states[1], na, false, false) || 929 (secure_to_insecure && 930 keymgr_key_exists_with_state(keyring, key, type, next_state, 931 na, na, false, false))); 932} 933 934/* 935 * Check for existence of DNSKEY, or at least a good DNSKEY state. 936 * See equations what are good DNSKEY states. 937 * 938 */ 939static bool 940keymgr_have_dnskey(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type, 941 dst_key_state_t next_state) { 942 dst_key_state_t states[9][NUM_KEYSTATES] = { 943 /* DNSKEY, ZRRSIG, KRRSIG, DS */ 944 { OMNIPRESENT, NA, OMNIPRESENT, OMNIPRESENT }, /* (3b) */ 945 946 { OMNIPRESENT, NA, OMNIPRESENT, UNRETENTIVE }, /* (3c)p */ 947 { OMNIPRESENT, NA, OMNIPRESENT, RUMOURED }, /* (3c)s */ 948 949 { UNRETENTIVE, NA, UNRETENTIVE, OMNIPRESENT }, /* (3d)p */ 950 { OMNIPRESENT, NA, UNRETENTIVE, OMNIPRESENT }, /* (3d)p */ 951 { UNRETENTIVE, NA, OMNIPRESENT, OMNIPRESENT }, /* (3d)p */ 952 { RUMOURED, NA, RUMOURED, OMNIPRESENT }, /* (3d)s */ 953 { OMNIPRESENT, NA, RUMOURED, OMNIPRESENT }, /* (3d)s */ 954 { RUMOURED, NA, OMNIPRESENT, OMNIPRESENT }, /* (3d)s */ 955 }; 956 /* successor n/a */ 957 dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA }; 958 959 return ( 960 /* 961 * Equation (3b): 962 * There is a key with the same algorithm with its DNSKEY, 963 * KRRSIG and DS records in OMNIPRESENT state. 964 */ 965 keymgr_key_exists_with_state(keyring, key, type, next_state, 966 states[0], na, false, true) || 967 /* 968 * Equation (3c): 969 * There are two or more keys with an OMNIPRESENT DNSKEY and 970 * the DS records get swapped. These keys must be in a 971 * successor relation. 972 */ 973 keymgr_key_exists_with_state(keyring, key, type, next_state, 974 states[1], states[2], true, 975 true) || 976 /* 977 * Equation (3d): 978 * There are two or more keys with an OMNIPRESENT DS and 979 * the DNSKEY records and its KRRSIG records get swapped. 980 * These keys must be in a successor relation. Since the 981 * state for DNSKEY and KRRSIG move independently, we have 982 * to check all combinations for DNSKEY and KRRSIG in 983 * OMNIPRESENT/UNRETENTIVE state for the predecessor, and 984 * OMNIPRESENT/RUMOURED state for the successor. 985 */ 986 keymgr_key_exists_with_state(keyring, key, type, next_state, 987 states[3], states[6], true, 988 true) || 989 keymgr_key_exists_with_state(keyring, key, type, next_state, 990 states[3], states[7], true, 991 true) || 992 keymgr_key_exists_with_state(keyring, key, type, next_state, 993 states[3], states[8], true, 994 true) || 995 keymgr_key_exists_with_state(keyring, key, type, next_state, 996 states[4], states[6], true, 997 true) || 998 keymgr_key_exists_with_state(keyring, key, type, next_state, 999 states[4], states[7], true, 1000 true) || 1001 keymgr_key_exists_with_state(keyring, key, type, next_state, 1002 states[4], states[8], true, 1003 true) || 1004 keymgr_key_exists_with_state(keyring, key, type, next_state, 1005 states[5], states[6], true, 1006 true) || 1007 keymgr_key_exists_with_state(keyring, key, type, next_state, 1008 states[5], states[7], true, 1009 true) || 1010 keymgr_key_exists_with_state(keyring, key, type, next_state, 1011 states[5], states[8], true, 1012 true) || 1013 /* 1014 * Equation (3e): 1015 * The key may be in any state as long as all keys have their 1016 * DS HIDDEN, or when their DS is not HIDDEN, there must be a 1017 * key with its DS in the same state and its DNSKEY omnipresent. 1018 * In other words, if a DS record for the same algorithm is 1019 * is still available to some validators, there must be a 1020 * chain of trust for those validators. 1021 */ 1022 keymgr_ds_hidden_or_chained(keyring, key, type, next_state, 1023 true, false)); 1024} 1025 1026/* 1027 * Check for existence of RRSIG (zsk), or a good RRSIG state. 1028 * See equations what are good RRSIG states. 1029 * 1030 */ 1031static bool 1032keymgr_have_rrsig(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, int type, 1033 dst_key_state_t next_state) { 1034 dst_key_state_t states[11][NUM_KEYSTATES] = { 1035 /* DNSKEY, ZRRSIG, KRRSIG, DS */ 1036 { OMNIPRESENT, OMNIPRESENT, NA, NA }, /* (3f) */ 1037 { UNRETENTIVE, OMNIPRESENT, NA, NA }, /* (3g)p */ 1038 { RUMOURED, OMNIPRESENT, NA, NA }, /* (3g)s */ 1039 { OMNIPRESENT, UNRETENTIVE, NA, NA }, /* (3h)p */ 1040 { OMNIPRESENT, RUMOURED, NA, NA }, /* (3h)s */ 1041 }; 1042 /* successor n/a */ 1043 dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA }; 1044 1045 return ( 1046 /* 1047 * If all DS records are hidden than this rule can be ignored. 1048 */ 1049 keymgr_ds_hidden_or_chained(keyring, key, type, next_state, 1050 true, true) || 1051 /* 1052 * Equation (3f): 1053 * There is a key with the same algorithm with its DNSKEY and 1054 * ZRRSIG records in OMNIPRESENT state. 1055 */ 1056 keymgr_key_exists_with_state(keyring, key, type, next_state, 1057 states[0], na, false, true) || 1058 /* 1059 * Equation (3g): 1060 * There are two or more keys with OMNIPRESENT ZRRSIG 1061 * records and the DNSKEY records get swapped. These keys 1062 * must be in a successor relation. 1063 */ 1064 keymgr_key_exists_with_state(keyring, key, type, next_state, 1065 states[1], states[2], true, 1066 true) || 1067 /* 1068 * Equation (3h): 1069 * There are two or more keys with an OMNIPRESENT DNSKEY 1070 * and the ZRRSIG records get swapped. These keys must be in 1071 * a successor relation. 1072 */ 1073 keymgr_key_exists_with_state(keyring, key, type, next_state, 1074 states[3], states[4], true, 1075 true) || 1076 /* 1077 * Equation (3i): 1078 * If no DNSKEYs are published, the state of the signatures is 1079 * irrelevant. In case a DNSKEY is published however, there 1080 * must be a path that can be validated from there. 1081 */ 1082 keymgr_dnskey_hidden_or_chained(keyring, key, type, next_state, 1083 true)); 1084} 1085 1086/* 1087 * Check if a transition in the state machine is allowed by the policy. 1088 * This means when we do rollovers, we want to follow the rules of the 1089 * 1. Pre-publish rollover method (in case of a ZSK) 1090 * - First introduce the DNSKEY record. 1091 * - Only if the DNSKEY record is OMNIPRESENT, introduce ZRRSIG records. 1092 * 1093 * 2. Double-KSK rollover method (in case of a KSK) 1094 * - First introduce the DNSKEY record, as well as the KRRSIG records. 1095 * - Only if the DNSKEY record is OMNIPRESENT, suggest to introduce the DS. 1096 */ 1097static bool 1098keymgr_policy_approval(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, 1099 int type, dst_key_state_t next) { 1100 dst_key_state_t dnskeystate = HIDDEN; 1101 dst_key_state_t ksk_present[NUM_KEYSTATES] = { OMNIPRESENT, NA, 1102 OMNIPRESENT, 1103 OMNIPRESENT }; 1104 dst_key_state_t ds_rumoured[NUM_KEYSTATES] = { OMNIPRESENT, NA, 1105 OMNIPRESENT, RUMOURED }; 1106 dst_key_state_t ds_retired[NUM_KEYSTATES] = { OMNIPRESENT, NA, 1107 OMNIPRESENT, 1108 UNRETENTIVE }; 1109 dst_key_state_t ksk_rumoured[NUM_KEYSTATES] = { RUMOURED, NA, NA, 1110 OMNIPRESENT }; 1111 dst_key_state_t ksk_retired[NUM_KEYSTATES] = { UNRETENTIVE, NA, NA, 1112 OMNIPRESENT }; 1113 /* successor n/a */ 1114 dst_key_state_t na[NUM_KEYSTATES] = { NA, NA, NA, NA }; 1115 1116 if (next != RUMOURED) { 1117 /* 1118 * Local policy only adds an extra barrier on transitions to 1119 * the RUMOURED state. 1120 */ 1121 return (true); 1122 } 1123 1124 switch (type) { 1125 case DST_KEY_DNSKEY: 1126 /* No restrictions. */ 1127 return (true); 1128 case DST_KEY_ZRRSIG: 1129 /* Make sure the DNSKEY record is OMNIPRESENT. */ 1130 (void)dst_key_getstate(key->key, DST_KEY_DNSKEY, &dnskeystate); 1131 if (dnskeystate == OMNIPRESENT) { 1132 return (true); 1133 } 1134 /* 1135 * Or are we introducing a new key for this algorithm? Because 1136 * in that case allow publishing the RRSIG records before the 1137 * DNSKEY. 1138 */ 1139 return (!(keymgr_key_exists_with_state(keyring, key, type, next, 1140 ksk_present, na, false, 1141 true) || 1142 keymgr_key_exists_with_state(keyring, key, type, next, 1143 ds_retired, ds_rumoured, 1144 true, true) || 1145 keymgr_key_exists_with_state( 1146 keyring, key, type, next, ksk_retired, 1147 ksk_rumoured, true, true))); 1148 case DST_KEY_KRRSIG: 1149 /* Only introduce if the DNSKEY is also introduced. */ 1150 (void)dst_key_getstate(key->key, DST_KEY_DNSKEY, &dnskeystate); 1151 return (dnskeystate != HIDDEN); 1152 case DST_KEY_DS: 1153 /* Make sure the DNSKEY record is OMNIPRESENT. */ 1154 (void)dst_key_getstate(key->key, DST_KEY_DNSKEY, &dnskeystate); 1155 return (dnskeystate == OMNIPRESENT); 1156 default: 1157 return (false); 1158 } 1159} 1160 1161/* 1162 * Check if a transition in the state machine is DNSSEC safe. 1163 * This implements Equation(1) of "Flexible and Robust Key Rollover". 1164 * 1165 */ 1166static bool 1167keymgr_transition_allowed(dns_dnsseckeylist_t *keyring, dns_dnsseckey_t *key, 1168 int type, dst_key_state_t next_state, 1169 bool secure_to_insecure) { 1170 /* Debug logging. */ 1171 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { 1172 bool rule1a, rule1b, rule2a, rule2b, rule3a, rule3b; 1173 char keystr[DST_KEY_FORMATSIZE]; 1174 dst_key_format(key->key, keystr, sizeof(keystr)); 1175 rule1a = keymgr_have_ds(keyring, key, type, NA, 1176 secure_to_insecure); 1177 rule1b = keymgr_have_ds(keyring, key, type, next_state, 1178 secure_to_insecure); 1179 rule2a = keymgr_have_dnskey(keyring, key, type, NA); 1180 rule2b = keymgr_have_dnskey(keyring, key, type, next_state); 1181 rule3a = keymgr_have_rrsig(keyring, key, type, NA); 1182 rule3b = keymgr_have_rrsig(keyring, key, type, next_state); 1183 isc_log_write( 1184 dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC, 1185 ISC_LOG_DEBUG(1), 1186 "keymgr: dnssec evaluation of %s %s record %s: " 1187 "rule1=(~%s or %s) rule2=(~%s or %s) " 1188 "rule3=(~%s or %s)", 1189 keymgr_keyrole(key->key), keystr, keystatetags[type], 1190 rule1a ? "true" : "false", rule1b ? "true" : "false", 1191 rule2a ? "true" : "false", rule2b ? "true" : "false", 1192 rule3a ? "true" : "false", rule3b ? "true" : "false"); 1193 } 1194 1195 return ( 1196 /* 1197 * Rule 1: There must be a DS at all times. 1198 * First check the current situation: if the rule check fails, 1199 * we allow the transition to attempt to move us out of the 1200 * invalid state. If the rule check passes, also check if 1201 * the next state is also still a valid situation. 1202 */ 1203 (!keymgr_have_ds(keyring, key, type, NA, secure_to_insecure) || 1204 keymgr_have_ds(keyring, key, type, next_state, 1205 secure_to_insecure)) && 1206 /* 1207 * Rule 2: There must be a DNSKEY at all times. Again, first 1208 * check the current situation, then assess the next state. 1209 */ 1210 (!keymgr_have_dnskey(keyring, key, type, NA) || 1211 keymgr_have_dnskey(keyring, key, type, next_state)) && 1212 /* 1213 * Rule 3: There must be RRSIG records at all times. Again, 1214 * first check the current situation, then assess the next 1215 * state. 1216 */ 1217 (!keymgr_have_rrsig(keyring, key, type, NA) || 1218 keymgr_have_rrsig(keyring, key, type, next_state))); 1219} 1220 1221/* 1222 * Calculate the time when it is safe to do the next transition. 1223 * 1224 */ 1225static void 1226keymgr_transition_time(dns_dnsseckey_t *key, int type, 1227 dst_key_state_t next_state, dns_kasp_t *kasp, 1228 isc_stdtime_t now, isc_stdtime_t *when) { 1229 isc_result_t ret; 1230 isc_stdtime_t lastchange, dstime, nexttime = now; 1231 1232 /* 1233 * No need to wait if we move things into an uncertain state. 1234 */ 1235 if (next_state == RUMOURED || next_state == UNRETENTIVE) { 1236 *when = now; 1237 return; 1238 } 1239 1240 ret = dst_key_gettime(key->key, keystatetimes[type], &lastchange); 1241 if (ret != ISC_R_SUCCESS) { 1242 /* No last change, for safety purposes let's set it to now. */ 1243 dst_key_settime(key->key, keystatetimes[type], now); 1244 lastchange = now; 1245 } 1246 1247 switch (type) { 1248 case DST_KEY_DNSKEY: 1249 case DST_KEY_KRRSIG: 1250 switch (next_state) { 1251 case OMNIPRESENT: 1252 /* 1253 * RFC 7583: The publication interval (Ipub) is the 1254 * amount of time that must elapse after the 1255 * publication of a DNSKEY (plus RRSIG (KSK)) before 1256 * it can be assumed that any resolvers that have the 1257 * relevant RRset cached have a copy of the new 1258 * information. This is the sum of the propagation 1259 * delay (Dprp) and the DNSKEY TTL (TTLkey). This 1260 * translates to zone-propagation-delay + dnskey-ttl. 1261 * We will also add the publish-safety interval. 1262 */ 1263 nexttime = lastchange + dst_key_getttl(key->key) + 1264 dns_kasp_zonepropagationdelay(kasp) + 1265 dns_kasp_publishsafety(kasp); 1266 break; 1267 case HIDDEN: 1268 /* 1269 * Same as OMNIPRESENT but without the publish-safety 1270 * interval. 1271 */ 1272 nexttime = lastchange + dst_key_getttl(key->key) + 1273 dns_kasp_zonepropagationdelay(kasp); 1274 break; 1275 default: 1276 nexttime = now; 1277 break; 1278 } 1279 break; 1280 case DST_KEY_ZRRSIG: 1281 switch (next_state) { 1282 case OMNIPRESENT: 1283 case HIDDEN: 1284 /* 1285 * RFC 7583: The retire interval (Iret) is the amount 1286 * of time that must elapse after a DNSKEY or 1287 * associated data enters the retire state for any 1288 * dependent information (RRSIG ZSK) to be purged from 1289 * validating resolver caches. This is defined as: 1290 * 1291 * Iret = Dsgn + Dprp + TTLsig 1292 * 1293 * Where Dsgn is the Dsgn is the delay needed to 1294 * ensure that all existing RRsets have been re-signed 1295 * with the new key, Dprp is the propagation delay and 1296 * TTLsig is the maximum TTL of all zone RRSIG 1297 * records. This translates to: 1298 * 1299 * Dsgn + zone-propagation-delay + max-zone-ttl. 1300 * 1301 * We will also add the retire-safety interval. 1302 */ 1303 nexttime = lastchange + dns_kasp_zonemaxttl(kasp) + 1304 dns_kasp_zonepropagationdelay(kasp) + 1305 dns_kasp_retiresafety(kasp); 1306 /* 1307 * Only add the sign delay Dsgn if there is an actual 1308 * predecessor or successor key. 1309 */ 1310 uint32_t tag; 1311 ret = dst_key_getnum(key->key, DST_NUM_PREDECESSOR, 1312 &tag); 1313 if (ret != ISC_R_SUCCESS) { 1314 ret = dst_key_getnum(key->key, 1315 DST_NUM_SUCCESSOR, &tag); 1316 } 1317 if (ret == ISC_R_SUCCESS) { 1318 nexttime += dns_kasp_signdelay(kasp); 1319 } 1320 break; 1321 default: 1322 nexttime = now; 1323 break; 1324 } 1325 break; 1326 case DST_KEY_DS: 1327 switch (next_state) { 1328 /* 1329 * RFC 7583: The successor DS record is published in 1330 * the parent zone and after the registration delay 1331 * (Dreg), the time taken after the DS record has been 1332 * submitted to the parent zone manager for it to be 1333 * placed in the zone. Key N (the predecessor) must 1334 * remain in the zone until any caches that contain a 1335 * copy of the DS RRset have a copy containing the new 1336 * DS record. This interval is the retire interval 1337 * (Iret), given by: 1338 * 1339 * Iret = DprpP + TTLds 1340 * 1341 * This translates to: 1342 * 1343 * parent-propagation-delay + parent-ds-ttl. 1344 * 1345 * We will also add the retire-safety interval. 1346 */ 1347 case OMNIPRESENT: 1348 /* Make sure DS has been seen in the parent. */ 1349 ret = dst_key_gettime(key->key, DST_TIME_DSPUBLISH, 1350 &dstime); 1351 if (ret != ISC_R_SUCCESS || dstime > now) { 1352 /* Not yet, try again in an hour. */ 1353 nexttime = now + 3600; 1354 } else { 1355 nexttime = 1356 dstime + dns_kasp_dsttl(kasp) + 1357 dns_kasp_parentpropagationdelay(kasp) + 1358 dns_kasp_retiresafety(kasp); 1359 } 1360 break; 1361 case HIDDEN: 1362 /* Make sure DS has been withdrawn from the parent. */ 1363 ret = dst_key_gettime(key->key, DST_TIME_DSDELETE, 1364 &dstime); 1365 if (ret != ISC_R_SUCCESS || dstime > now) { 1366 /* Not yet, try again in an hour. */ 1367 nexttime = now + 3600; 1368 } else { 1369 nexttime = 1370 dstime + dns_kasp_dsttl(kasp) + 1371 dns_kasp_parentpropagationdelay(kasp) + 1372 dns_kasp_retiresafety(kasp); 1373 } 1374 break; 1375 default: 1376 nexttime = now; 1377 break; 1378 } 1379 break; 1380 default: 1381 UNREACHABLE(); 1382 break; 1383 } 1384 1385 *when = nexttime; 1386} 1387 1388/* 1389 * Update keys. 1390 * This implements Algorithm (1) of "Flexible and Robust Key Rollover". 1391 * 1392 */ 1393static isc_result_t 1394keymgr_update(dns_dnsseckeylist_t *keyring, dns_kasp_t *kasp, isc_stdtime_t now, 1395 isc_stdtime_t *nexttime, bool secure_to_insecure) { 1396 bool changed; 1397 1398 /* Repeat until nothing changed. */ 1399transition: 1400 changed = false; 1401 1402 /* For all keys in the zone. */ 1403 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 1404 dkey = ISC_LIST_NEXT(dkey, link)) 1405 { 1406 char keystr[DST_KEY_FORMATSIZE]; 1407 dst_key_format(dkey->key, keystr, sizeof(keystr)); 1408 1409 /* For all records related to this key. */ 1410 for (int i = 0; i < NUM_KEYSTATES; i++) { 1411 isc_result_t ret; 1412 isc_stdtime_t when; 1413 dst_key_state_t state, next_state; 1414 1415 ret = dst_key_getstate(dkey->key, i, &state); 1416 if (ret == ISC_R_NOTFOUND) { 1417 /* 1418 * This record type is not applicable for this 1419 * key, continue to the next record type. 1420 */ 1421 continue; 1422 } 1423 1424 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1425 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1426 "keymgr: examine %s %s type %s " 1427 "in state %s", 1428 keymgr_keyrole(dkey->key), keystr, 1429 keystatetags[i], keystatestrings[state]); 1430 1431 /* Get the desired next state. */ 1432 next_state = keymgr_desiredstate(dkey, state); 1433 if (state == next_state) { 1434 /* 1435 * This record is in a stable state. 1436 * No change needed, continue with the next 1437 * record type. 1438 */ 1439 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1440 DNS_LOGMODULE_DNSSEC, 1441 ISC_LOG_DEBUG(1), 1442 "keymgr: %s %s type %s in " 1443 "stable state %s", 1444 keymgr_keyrole(dkey->key), keystr, 1445 keystatetags[i], 1446 keystatestrings[state]); 1447 continue; 1448 } 1449 1450 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1451 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1452 "keymgr: can we transition %s %s type %s " 1453 "state %s to state %s?", 1454 keymgr_keyrole(dkey->key), keystr, 1455 keystatetags[i], keystatestrings[state], 1456 keystatestrings[next_state]); 1457 1458 /* Is the transition allowed according to policy? */ 1459 if (!keymgr_policy_approval(keyring, dkey, i, 1460 next_state)) 1461 { 1462 /* No, please respect rollover methods. */ 1463 isc_log_write( 1464 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1465 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1466 "keymgr: policy says no to %s %s type " 1467 "%s " 1468 "state %s to state %s", 1469 keymgr_keyrole(dkey->key), keystr, 1470 keystatetags[i], keystatestrings[state], 1471 keystatestrings[next_state]); 1472 1473 continue; 1474 } 1475 1476 /* Is the transition DNSSEC safe? */ 1477 if (!keymgr_transition_allowed(keyring, dkey, i, 1478 next_state, 1479 secure_to_insecure)) 1480 { 1481 /* No, this would make the zone bogus. */ 1482 isc_log_write( 1483 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1484 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1485 "keymgr: dnssec says no to %s %s type " 1486 "%s " 1487 "state %s to state %s", 1488 keymgr_keyrole(dkey->key), keystr, 1489 keystatetags[i], keystatestrings[state], 1490 keystatestrings[next_state]); 1491 continue; 1492 } 1493 1494 /* Is it time to make the transition? */ 1495 when = now; 1496 keymgr_transition_time(dkey, i, next_state, kasp, now, 1497 &when); 1498 if (when > now) { 1499 /* Not yet. */ 1500 isc_log_write( 1501 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1502 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1503 "keymgr: time says no to %s %s type %s " 1504 "state %s to state %s (wait %u " 1505 "seconds)", 1506 keymgr_keyrole(dkey->key), keystr, 1507 keystatetags[i], keystatestrings[state], 1508 keystatestrings[next_state], 1509 when - now); 1510 if (*nexttime == 0 || *nexttime > when) { 1511 *nexttime = when; 1512 } 1513 continue; 1514 } 1515 1516 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1517 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1518 "keymgr: transition %s %s type %s " 1519 "state %s to state %s!", 1520 keymgr_keyrole(dkey->key), keystr, 1521 keystatetags[i], keystatestrings[state], 1522 keystatestrings[next_state]); 1523 1524 /* It is safe to make the transition. */ 1525 dst_key_setstate(dkey->key, i, next_state); 1526 dst_key_settime(dkey->key, keystatetimes[i], now); 1527 INSIST(dst_key_ismodified(dkey->key)); 1528 changed = true; 1529 } 1530 } 1531 1532 /* We changed something, continue processing. */ 1533 if (changed) { 1534 goto transition; 1535 } 1536 1537 return (ISC_R_SUCCESS); 1538} 1539 1540/* 1541 * See if this key needs to be initialized with properties. A key created 1542 * and derived from a dnssec-policy will have the required metadata available, 1543 * otherwise these may be missing and need to be initialized. The key states 1544 * will be initialized according to existing timing metadata. 1545 * 1546 */ 1547static void 1548keymgr_key_init(dns_dnsseckey_t *key, dns_kasp_t *kasp, isc_stdtime_t now, 1549 bool csk) { 1550 bool ksk, zsk; 1551 isc_result_t ret; 1552 isc_stdtime_t active = 0, pub = 0, syncpub = 0, retire = 0, remove = 0; 1553 dst_key_state_t dnskey_state = HIDDEN; 1554 dst_key_state_t ds_state = HIDDEN; 1555 dst_key_state_t zrrsig_state = HIDDEN; 1556 dst_key_state_t goal_state = HIDDEN; 1557 1558 REQUIRE(key != NULL); 1559 REQUIRE(key->key != NULL); 1560 1561 /* Initialize role. */ 1562 ret = dst_key_getbool(key->key, DST_BOOL_KSK, &ksk); 1563 if (ret != ISC_R_SUCCESS) { 1564 ksk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) != 0); 1565 dst_key_setbool(key->key, DST_BOOL_KSK, (ksk || csk)); 1566 } 1567 ret = dst_key_getbool(key->key, DST_BOOL_ZSK, &zsk); 1568 if (ret != ISC_R_SUCCESS) { 1569 zsk = ((dst_key_flags(key->key) & DNS_KEYFLAG_KSK) == 0); 1570 dst_key_setbool(key->key, DST_BOOL_ZSK, (zsk || csk)); 1571 } 1572 1573 /* Get time metadata. */ 1574 ret = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); 1575 if (active <= now && ret == ISC_R_SUCCESS) { 1576 dns_ttl_t zone_ttl = dns_kasp_zonemaxttl(kasp); 1577 zone_ttl += dns_kasp_zonepropagationdelay(kasp); 1578 if ((active + zone_ttl) <= now) { 1579 zrrsig_state = OMNIPRESENT; 1580 } else { 1581 zrrsig_state = RUMOURED; 1582 } 1583 goal_state = OMNIPRESENT; 1584 } 1585 ret = dst_key_gettime(key->key, DST_TIME_PUBLISH, &pub); 1586 if (pub <= now && ret == ISC_R_SUCCESS) { 1587 dns_ttl_t key_ttl = dst_key_getttl(key->key); 1588 key_ttl += dns_kasp_zonepropagationdelay(kasp); 1589 if ((pub + key_ttl) <= now) { 1590 dnskey_state = OMNIPRESENT; 1591 } else { 1592 dnskey_state = RUMOURED; 1593 } 1594 goal_state = OMNIPRESENT; 1595 } 1596 ret = dst_key_gettime(key->key, DST_TIME_SYNCPUBLISH, &syncpub); 1597 if (syncpub <= now && ret == ISC_R_SUCCESS) { 1598 dns_ttl_t ds_ttl = dns_kasp_dsttl(kasp); 1599 ds_ttl += dns_kasp_parentpropagationdelay(kasp); 1600 if ((syncpub + ds_ttl) <= now) { 1601 ds_state = OMNIPRESENT; 1602 } else { 1603 ds_state = RUMOURED; 1604 } 1605 goal_state = OMNIPRESENT; 1606 } 1607 ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire); 1608 if (retire <= now && ret == ISC_R_SUCCESS) { 1609 dns_ttl_t zone_ttl = dns_kasp_zonemaxttl(kasp); 1610 zone_ttl += dns_kasp_zonepropagationdelay(kasp); 1611 if ((retire + zone_ttl) <= now) { 1612 zrrsig_state = HIDDEN; 1613 } else { 1614 zrrsig_state = UNRETENTIVE; 1615 } 1616 ds_state = UNRETENTIVE; 1617 goal_state = HIDDEN; 1618 } 1619 ret = dst_key_gettime(key->key, DST_TIME_DELETE, &remove); 1620 if (remove <= now && ret == ISC_R_SUCCESS) { 1621 dns_ttl_t key_ttl = dst_key_getttl(key->key); 1622 key_ttl += dns_kasp_zonepropagationdelay(kasp); 1623 if ((remove + key_ttl) <= now) { 1624 dnskey_state = HIDDEN; 1625 } else { 1626 dnskey_state = UNRETENTIVE; 1627 } 1628 zrrsig_state = HIDDEN; 1629 ds_state = HIDDEN; 1630 goal_state = HIDDEN; 1631 } 1632 1633 /* Set goal if not already set. */ 1634 if (dst_key_getstate(key->key, DST_KEY_GOAL, &goal_state) != 1635 ISC_R_SUCCESS) 1636 { 1637 dst_key_setstate(key->key, DST_KEY_GOAL, goal_state); 1638 } 1639 1640 /* Set key states for all keys that do not have them. */ 1641 INITIALIZE_STATE(key->key, DST_KEY_DNSKEY, DST_TIME_DNSKEY, 1642 dnskey_state, now); 1643 if (ksk || csk) { 1644 INITIALIZE_STATE(key->key, DST_KEY_KRRSIG, DST_TIME_KRRSIG, 1645 dnskey_state, now); 1646 INITIALIZE_STATE(key->key, DST_KEY_DS, DST_TIME_DS, ds_state, 1647 now); 1648 } 1649 if (zsk || csk) { 1650 INITIALIZE_STATE(key->key, DST_KEY_ZRRSIG, DST_TIME_ZRRSIG, 1651 zrrsig_state, now); 1652 } 1653} 1654 1655static isc_result_t 1656keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key, 1657 dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *newkeys, 1658 const dns_name_t *origin, dns_rdataclass_t rdclass, 1659 dns_kasp_t *kasp, uint32_t lifetime, bool rollover, 1660 isc_stdtime_t now, isc_stdtime_t *nexttime, 1661 isc_mem_t *mctx) { 1662 char keystr[DST_KEY_FORMATSIZE]; 1663 isc_stdtime_t retire = 0, active = 0, prepub = 0; 1664 dns_dnsseckey_t *new_key = NULL; 1665 dns_dnsseckey_t *candidate = NULL; 1666 dst_key_t *dst_key = NULL; 1667 1668 /* Do we need to create a successor for the active key? */ 1669 if (active_key != NULL) { 1670 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { 1671 dst_key_format(active_key->key, keystr, sizeof(keystr)); 1672 isc_log_write( 1673 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1674 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1675 "keymgr: DNSKEY %s (%s) is active in policy %s", 1676 keystr, keymgr_keyrole(active_key->key), 1677 dns_kasp_getname(kasp)); 1678 } 1679 1680 /* 1681 * Calculate when the successor needs to be published 1682 * in the zone. 1683 */ 1684 prepub = keymgr_prepublication_time(active_key, kasp, lifetime, 1685 now); 1686 if (prepub == 0 || prepub > now) { 1687 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { 1688 dst_key_format(active_key->key, keystr, 1689 sizeof(keystr)); 1690 isc_log_write( 1691 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1692 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1693 "keymgr: new successor needed for " 1694 "DNSKEY %s (%s) (policy %s) in %u " 1695 "seconds", 1696 keystr, keymgr_keyrole(active_key->key), 1697 dns_kasp_getname(kasp), (prepub - now)); 1698 } 1699 1700 /* No need to start rollover now. */ 1701 if (*nexttime == 0 || prepub < *nexttime) { 1702 *nexttime = prepub; 1703 } 1704 return (ISC_R_SUCCESS); 1705 } 1706 1707 if (keymgr_key_has_successor(active_key, keyring)) { 1708 /* Key already has successor. */ 1709 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { 1710 dst_key_format(active_key->key, keystr, 1711 sizeof(keystr)); 1712 isc_log_write( 1713 dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1714 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1715 "keymgr: key DNSKEY %s (%s) (policy " 1716 "%s) already has successor", 1717 keystr, keymgr_keyrole(active_key->key), 1718 dns_kasp_getname(kasp)); 1719 } 1720 return (ISC_R_SUCCESS); 1721 } 1722 1723 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { 1724 dst_key_format(active_key->key, keystr, sizeof(keystr)); 1725 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1726 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1727 "keymgr: need successor for DNSKEY %s " 1728 "(%s) (policy %s)", 1729 keystr, keymgr_keyrole(active_key->key), 1730 dns_kasp_getname(kasp)); 1731 } 1732 1733 /* 1734 * If rollover is not allowed, warn. 1735 */ 1736 if (!rollover) { 1737 dst_key_format(active_key->key, keystr, sizeof(keystr)); 1738 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1739 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1740 "keymgr: DNSKEY %s (%s) is offline in " 1741 "policy %s, cannot start rollover", 1742 keystr, keymgr_keyrole(active_key->key), 1743 dns_kasp_getname(kasp)); 1744 return (ISC_R_SUCCESS); 1745 } 1746 } else if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { 1747 char namestr[DNS_NAME_FORMATSIZE]; 1748 dns_name_format(origin, namestr, sizeof(namestr)); 1749 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1750 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 1751 "keymgr: no active key found for %s (policy %s)", 1752 namestr, dns_kasp_getname(kasp)); 1753 } 1754 1755 /* It is time to do key rollover, we need a new key. */ 1756 1757 /* 1758 * Check if there is a key available in pool because keys 1759 * may have been pregenerated with dnssec-keygen. 1760 */ 1761 for (candidate = ISC_LIST_HEAD(*keyring); candidate != NULL; 1762 candidate = ISC_LIST_NEXT(candidate, link)) 1763 { 1764 if (keymgr_dnsseckey_kaspkey_match(candidate, kaspkey) && 1765 dst_key_is_unused(candidate->key)) 1766 { 1767 /* Found a candidate in keyring. */ 1768 break; 1769 } 1770 } 1771 1772 if (candidate == NULL) { 1773 /* No key available in keyring, create a new one. */ 1774 bool csk = (dns_kasp_key_ksk(kaspkey) && 1775 dns_kasp_key_zsk(kaspkey)); 1776 1777 isc_result_t result = keymgr_createkey(kaspkey, origin, rdclass, 1778 mctx, keyring, newkeys, 1779 &dst_key); 1780 if (result != ISC_R_SUCCESS) { 1781 return (result); 1782 } 1783 dst_key_setttl(dst_key, dns_kasp_dnskeyttl(kasp)); 1784 dst_key_settime(dst_key, DST_TIME_CREATED, now); 1785 result = dns_dnsseckey_create(mctx, &dst_key, &new_key); 1786 if (result != ISC_R_SUCCESS) { 1787 return (result); 1788 } 1789 keymgr_key_init(new_key, kasp, now, csk); 1790 } else { 1791 new_key = candidate; 1792 } 1793 dst_key_setnum(new_key->key, DST_NUM_LIFETIME, lifetime); 1794 1795 /* Got a key. */ 1796 if (active_key == NULL) { 1797 /* 1798 * If there is no active key found yet for this kasp 1799 * key configuration, immediately make this key active. 1800 */ 1801 dst_key_settime(new_key->key, DST_TIME_PUBLISH, now); 1802 dst_key_settime(new_key->key, DST_TIME_ACTIVATE, now); 1803 keymgr_settime_syncpublish(new_key, kasp, true); 1804 active = now; 1805 } else { 1806 /* 1807 * This is a successor. Mark the relationship. 1808 */ 1809 isc_stdtime_t created; 1810 (void)dst_key_gettime(new_key->key, DST_TIME_CREATED, &created); 1811 1812 dst_key_setnum(new_key->key, DST_NUM_PREDECESSOR, 1813 dst_key_id(active_key->key)); 1814 dst_key_setnum(active_key->key, DST_NUM_SUCCESSOR, 1815 dst_key_id(new_key->key)); 1816 (void)dst_key_gettime(active_key->key, DST_TIME_INACTIVE, 1817 &retire); 1818 active = retire; 1819 1820 /* 1821 * If prepublication time and/or retire time are 1822 * in the past (before the new key was created), use 1823 * creation time as published and active time, 1824 * effectively immediately making the key active. 1825 */ 1826 if (prepub < created) { 1827 active += (created - prepub); 1828 prepub = created; 1829 } 1830 if (active < created) { 1831 active = created; 1832 } 1833 dst_key_settime(new_key->key, DST_TIME_PUBLISH, prepub); 1834 dst_key_settime(new_key->key, DST_TIME_ACTIVATE, active); 1835 keymgr_settime_syncpublish(new_key, kasp, false); 1836 1837 /* 1838 * Retire predecessor. 1839 */ 1840 dst_key_setstate(active_key->key, DST_KEY_GOAL, HIDDEN); 1841 } 1842 1843 /* This key wants to be present. */ 1844 dst_key_setstate(new_key->key, DST_KEY_GOAL, OMNIPRESENT); 1845 1846 /* Do we need to set retire time? */ 1847 if (lifetime > 0) { 1848 dst_key_settime(new_key->key, DST_TIME_INACTIVE, 1849 (active + lifetime)); 1850 keymgr_settime_remove(new_key, kasp); 1851 } 1852 1853 /* Append dnsseckey to list of new keys. */ 1854 dns_dnssec_get_hints(new_key, now); 1855 new_key->source = dns_keysource_repository; 1856 INSIST(!new_key->legacy); 1857 if (candidate == NULL) { 1858 ISC_LIST_APPEND(*newkeys, new_key, link); 1859 } 1860 1861 /* Logging. */ 1862 dst_key_format(new_key->key, keystr, sizeof(keystr)); 1863 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_DNSSEC, 1864 ISC_LOG_INFO, "keymgr: DNSKEY %s (%s) %s for policy %s", 1865 keystr, keymgr_keyrole(new_key->key), 1866 (candidate != NULL) ? "selected" : "created", 1867 dns_kasp_getname(kasp)); 1868 return (ISC_R_SUCCESS); 1869} 1870 1871static bool 1872keymgr_key_may_be_purged(dst_key_t *key, uint32_t after, isc_stdtime_t now) { 1873 bool ksk = false; 1874 bool zsk = false; 1875 dst_key_state_t hidden[NUM_KEYSTATES] = { HIDDEN, NA, NA, NA }; 1876 isc_stdtime_t lastchange = 0; 1877 1878 char keystr[DST_KEY_FORMATSIZE]; 1879 dst_key_format(key, keystr, sizeof(keystr)); 1880 1881 /* If 'purge-keys' is disabled, always retain keys. */ 1882 if (after == 0) { 1883 return (false); 1884 } 1885 1886 /* Don't purge keys with goal OMNIPRESENT */ 1887 if (dst_key_goal(key) == OMNIPRESENT) { 1888 return (false); 1889 } 1890 1891 /* Don't purge unused keys. */ 1892 if (dst_key_is_unused(key)) { 1893 return (false); 1894 } 1895 1896 /* If this key is completely HIDDEN it may be purged. */ 1897 (void)dst_key_getbool(key, DST_BOOL_KSK, &ksk); 1898 (void)dst_key_getbool(key, DST_BOOL_ZSK, &zsk); 1899 if (ksk) { 1900 hidden[DST_KEY_KRRSIG] = HIDDEN; 1901 hidden[DST_KEY_DS] = HIDDEN; 1902 } 1903 if (zsk) { 1904 hidden[DST_KEY_ZRRSIG] = HIDDEN; 1905 } 1906 if (!keymgr_key_match_state(key, key, 0, NA, hidden)) { 1907 return (false); 1908 } 1909 1910 /* 1911 * Check 'purge-keys' interval. If the interval has passed since 1912 * the last key change, it may be purged. 1913 */ 1914 for (int i = 0; i < NUM_KEYSTATES; i++) { 1915 isc_stdtime_t change = 0; 1916 (void)dst_key_gettime(key, keystatetimes[i], &change); 1917 if (change > lastchange) { 1918 lastchange = change; 1919 } 1920 } 1921 1922 return ((lastchange + after) < now); 1923} 1924 1925static void 1926keymgr_purge_keyfile(dst_key_t *key, const char *dir, int type) { 1927 isc_result_t ret; 1928 isc_buffer_t fileb; 1929 char filename[NAME_MAX]; 1930 1931 /* 1932 * Make the filename. 1933 */ 1934 isc_buffer_init(&fileb, filename, sizeof(filename)); 1935 ret = dst_key_buildfilename(key, type, dir, &fileb); 1936 if (ret != ISC_R_SUCCESS) { 1937 char keystr[DST_KEY_FORMATSIZE]; 1938 dst_key_format(key, keystr, sizeof(keystr)); 1939 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1940 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1941 "keymgr: failed to purge DNSKEY %s (%s): cannot " 1942 "build filename (%s)", 1943 keystr, keymgr_keyrole(key), 1944 isc_result_totext(ret)); 1945 return; 1946 } 1947 1948 if (unlink(filename) < 0) { 1949 char keystr[DST_KEY_FORMATSIZE]; 1950 dst_key_format(key, keystr, sizeof(keystr)); 1951 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 1952 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1953 "keymgr: failed to purge DNSKEY %s (%s): unlink " 1954 "'%s' failed", 1955 keystr, keymgr_keyrole(key), filename); 1956 } 1957} 1958 1959/* 1960 * Examine 'keys' and match 'kasp' policy. 1961 * 1962 */ 1963isc_result_t 1964dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass, 1965 const char *directory, isc_mem_t *mctx, 1966 dns_dnsseckeylist_t *keyring, dns_dnsseckeylist_t *dnskeys, 1967 dns_kasp_t *kasp, isc_stdtime_t now, isc_stdtime_t *nexttime) { 1968 isc_result_t result = ISC_R_SUCCESS; 1969 dns_dnsseckeylist_t newkeys; 1970 dns_kasp_key_t *kkey; 1971 dns_dnsseckey_t *newkey = NULL; 1972 isc_dir_t dir; 1973 bool dir_open = false; 1974 bool secure_to_insecure = false; 1975 int numkeys = 0; 1976 int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE); 1977 char keystr[DST_KEY_FORMATSIZE]; 1978 1979 REQUIRE(DNS_KASP_VALID(kasp)); 1980 REQUIRE(keyring != NULL); 1981 1982 ISC_LIST_INIT(newkeys); 1983 1984 isc_dir_init(&dir); 1985 if (directory == NULL) { 1986 directory = "."; 1987 } 1988 1989 RETERR(isc_dir_open(&dir, directory)); 1990 dir_open = true; 1991 1992 *nexttime = 0; 1993 1994 /* Debug logging: what keys are available in the keyring? */ 1995 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) { 1996 if (ISC_LIST_EMPTY(*keyring)) { 1997 char namebuf[DNS_NAME_FORMATSIZE]; 1998 dns_name_format(origin, namebuf, sizeof(namebuf)); 1999 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2000 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 2001 "keymgr: keyring empty (zone %s policy " 2002 "%s)", 2003 namebuf, dns_kasp_getname(kasp)); 2004 } 2005 2006 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); 2007 dkey != NULL; dkey = ISC_LIST_NEXT(dkey, link)) 2008 { 2009 dst_key_format(dkey->key, keystr, sizeof(keystr)); 2010 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2011 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 2012 "keymgr: keyring: %s (policy %s)", keystr, 2013 dns_kasp_getname(kasp)); 2014 } 2015 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*dnskeys); 2016 dkey != NULL; dkey = ISC_LIST_NEXT(dkey, link)) 2017 { 2018 dst_key_format(dkey->key, keystr, sizeof(keystr)); 2019 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2020 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1), 2021 "keymgr: dnskeys: %s (policy %s)", keystr, 2022 dns_kasp_getname(kasp)); 2023 } 2024 } 2025 2026 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*dnskeys); dkey != NULL; 2027 dkey = ISC_LIST_NEXT(dkey, link)) 2028 { 2029 numkeys++; 2030 } 2031 2032 /* Do we need to remove keys? */ 2033 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 2034 dkey = ISC_LIST_NEXT(dkey, link)) 2035 { 2036 bool found_match = false; 2037 2038 keymgr_key_init(dkey, kasp, now, (numkeys == 1)); 2039 2040 for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL; 2041 kkey = ISC_LIST_NEXT(kkey, link)) 2042 { 2043 if (keymgr_dnsseckey_kaspkey_match(dkey, kkey)) { 2044 found_match = true; 2045 break; 2046 } 2047 } 2048 2049 /* No match, so retire unwanted retire key. */ 2050 if (!found_match) { 2051 keymgr_key_retire(dkey, kasp, now); 2052 } 2053 2054 /* Check purge-keys interval. */ 2055 if (keymgr_key_may_be_purged(dkey->key, 2056 dns_kasp_purgekeys(kasp), now)) 2057 { 2058 dst_key_format(dkey->key, keystr, sizeof(keystr)); 2059 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2060 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO, 2061 "keymgr: purge DNSKEY %s (%s) according " 2062 "to policy %s", 2063 keystr, keymgr_keyrole(dkey->key), 2064 dns_kasp_getname(kasp)); 2065 2066 keymgr_purge_keyfile(dkey->key, directory, 2067 DST_TYPE_PUBLIC); 2068 keymgr_purge_keyfile(dkey->key, directory, 2069 DST_TYPE_PRIVATE); 2070 keymgr_purge_keyfile(dkey->key, directory, 2071 DST_TYPE_STATE); 2072 2073 dkey->purge = true; 2074 } 2075 } 2076 2077 /* Create keys according to the policy, if come in short. */ 2078 for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL; 2079 kkey = ISC_LIST_NEXT(kkey, link)) 2080 { 2081 uint32_t lifetime = dns_kasp_key_lifetime(kkey); 2082 dns_dnsseckey_t *active_key = NULL; 2083 bool rollover_allowed = true; 2084 2085 /* Do we have keys available for this kasp key? */ 2086 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); 2087 dkey != NULL; dkey = ISC_LIST_NEXT(dkey, link)) 2088 { 2089 if (keymgr_dnsseckey_kaspkey_match(dkey, kkey)) { 2090 /* Found a match. */ 2091 dst_key_format(dkey->key, keystr, 2092 sizeof(keystr)); 2093 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2094 DNS_LOGMODULE_DNSSEC, 2095 ISC_LOG_DEBUG(1), 2096 "keymgr: DNSKEY %s (%s) matches " 2097 "policy %s", 2098 keystr, keymgr_keyrole(dkey->key), 2099 dns_kasp_getname(kasp)); 2100 2101 /* Initialize lifetime if not set. */ 2102 uint32_t l; 2103 if (dst_key_getnum(dkey->key, DST_NUM_LIFETIME, 2104 &l) != ISC_R_SUCCESS) 2105 { 2106 dst_key_setnum(dkey->key, 2107 DST_NUM_LIFETIME, 2108 lifetime); 2109 } 2110 2111 if (active_key) { 2112 /* We already have an active key that 2113 * matches the kasp policy. 2114 */ 2115 if (!dst_key_is_unused(dkey->key) && 2116 (dst_key_goal(dkey->key) == 2117 OMNIPRESENT) && 2118 !keymgr_dep(dkey->key, keyring, 2119 NULL) && 2120 !keymgr_dep(active_key->key, 2121 keyring, NULL)) 2122 { 2123 /* 2124 * Multiple signing keys match 2125 * the kasp key configuration. 2126 * Retire excess keys in use. 2127 */ 2128 keymgr_key_retire(dkey, kasp, 2129 now); 2130 } 2131 continue; 2132 } 2133 2134 /* 2135 * Save the matched key only if it is active 2136 * or desires to be active. 2137 */ 2138 if (dst_key_goal(dkey->key) == OMNIPRESENT || 2139 dst_key_is_active(dkey->key, now)) 2140 { 2141 active_key = dkey; 2142 } 2143 } 2144 } 2145 2146 if (active_key == NULL) { 2147 /* 2148 * We didn't found an active key, perhaps the .private 2149 * key file is offline. If so, we don't want to create 2150 * a successor key. Check if we have an appropriate 2151 * state file. 2152 */ 2153 for (dns_dnsseckey_t *dnskey = ISC_LIST_HEAD(*dnskeys); 2154 dnskey != NULL; 2155 dnskey = ISC_LIST_NEXT(dnskey, link)) 2156 { 2157 if (keymgr_dnsseckey_kaspkey_match(dnskey, 2158 kkey)) 2159 { 2160 /* Found a match. */ 2161 dst_key_format(dnskey->key, keystr, 2162 sizeof(keystr)); 2163 isc_log_write( 2164 dns_lctx, 2165 DNS_LOGCATEGORY_DNSSEC, 2166 DNS_LOGMODULE_DNSSEC, 2167 ISC_LOG_DEBUG(1), 2168 "keymgr: DNSKEY %s (%s) " 2169 "offline, policy %s", 2170 keystr, 2171 keymgr_keyrole(dnskey->key), 2172 dns_kasp_getname(kasp)); 2173 rollover_allowed = false; 2174 active_key = dnskey; 2175 break; 2176 } 2177 } 2178 } 2179 2180 /* See if this key requires a rollover. */ 2181 RETERR(keymgr_key_rollover( 2182 kkey, active_key, keyring, &newkeys, origin, rdclass, 2183 kasp, lifetime, rollover_allowed, now, nexttime, mctx)); 2184 } 2185 2186 /* Walked all kasp key configurations. Append new keys. */ 2187 if (!ISC_LIST_EMPTY(newkeys)) { 2188 ISC_LIST_APPENDLIST(*keyring, newkeys, link); 2189 } 2190 2191 /* 2192 * If the policy has an empty key list, this means the zone is going 2193 * back to unsigned. 2194 */ 2195 secure_to_insecure = dns_kasp_keylist_empty(kasp); 2196 2197 /* Read to update key states. */ 2198 keymgr_update(keyring, kasp, now, nexttime, secure_to_insecure); 2199 2200 /* Store key states and update hints. */ 2201 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 2202 dkey = ISC_LIST_NEXT(dkey, link)) 2203 { 2204 if (dst_key_ismodified(dkey->key) && !dkey->purge) { 2205 dns_dnssec_get_hints(dkey, now); 2206 RETERR(dst_key_tofile(dkey->key, options, directory)); 2207 dst_key_setmodified(dkey->key, false); 2208 } 2209 } 2210 2211 result = ISC_R_SUCCESS; 2212 2213failure: 2214 if (dir_open) { 2215 isc_dir_close(&dir); 2216 } 2217 2218 if (result != ISC_R_SUCCESS) { 2219 while ((newkey = ISC_LIST_HEAD(newkeys)) != NULL) { 2220 ISC_LIST_UNLINK(newkeys, newkey, link); 2221 INSIST(newkey->key != NULL); 2222 dst_key_free(&newkey->key); 2223 dns_dnsseckey_destroy(mctx, &newkey); 2224 } 2225 } 2226 2227 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) { 2228 char namebuf[DNS_NAME_FORMATSIZE]; 2229 dns_name_format(origin, namebuf, sizeof(namebuf)); 2230 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2231 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(3), 2232 "keymgr: %s done", namebuf); 2233 } 2234 return (result); 2235} 2236 2237static isc_result_t 2238keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring, 2239 const char *directory, isc_stdtime_t now, isc_stdtime_t when, 2240 bool dspublish, dns_keytag_t id, unsigned int alg, 2241 bool check_id) { 2242 int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE); 2243 isc_dir_t dir; 2244 isc_result_t result; 2245 dns_dnsseckey_t *ksk_key = NULL; 2246 2247 REQUIRE(DNS_KASP_VALID(kasp)); 2248 REQUIRE(keyring != NULL); 2249 2250 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 2251 dkey = ISC_LIST_NEXT(dkey, link)) 2252 { 2253 isc_result_t ret; 2254 bool ksk = false; 2255 2256 ret = dst_key_getbool(dkey->key, DST_BOOL_KSK, &ksk); 2257 if (ret == ISC_R_SUCCESS && ksk) { 2258 if (check_id && dst_key_id(dkey->key) != id) { 2259 continue; 2260 } 2261 if (alg > 0 && dst_key_alg(dkey->key) != alg) { 2262 continue; 2263 } 2264 2265 if (ksk_key != NULL) { 2266 /* 2267 * Only checkds for one key at a time. 2268 */ 2269 return (DNS_R_TOOMANYKEYS); 2270 } 2271 2272 ksk_key = dkey; 2273 } 2274 } 2275 2276 if (ksk_key == NULL) { 2277 return (DNS_R_NOKEYMATCH); 2278 } 2279 2280 if (dspublish) { 2281 dst_key_state_t s; 2282 dst_key_settime(ksk_key->key, DST_TIME_DSPUBLISH, when); 2283 result = dst_key_getstate(ksk_key->key, DST_KEY_DS, &s); 2284 if (result != ISC_R_SUCCESS || s != RUMOURED) { 2285 dst_key_setstate(ksk_key->key, DST_KEY_DS, RUMOURED); 2286 } 2287 } else { 2288 dst_key_state_t s; 2289 dst_key_settime(ksk_key->key, DST_TIME_DSDELETE, when); 2290 result = dst_key_getstate(ksk_key->key, DST_KEY_DS, &s); 2291 if (result != ISC_R_SUCCESS || s != UNRETENTIVE) { 2292 dst_key_setstate(ksk_key->key, DST_KEY_DS, UNRETENTIVE); 2293 } 2294 } 2295 2296 if (isc_log_wouldlog(dns_lctx, ISC_LOG_NOTICE)) { 2297 char keystr[DST_KEY_FORMATSIZE]; 2298 char timestr[26]; /* Minimal buf as per ctime_r() spec. */ 2299 2300 dst_key_format(ksk_key->key, keystr, sizeof(keystr)); 2301 isc_stdtime_tostring(when, timestr, sizeof(timestr)); 2302 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, 2303 DNS_LOGMODULE_DNSSEC, ISC_LOG_NOTICE, 2304 "keymgr: checkds DS for key %s seen %s at %s", 2305 keystr, dspublish ? "published" : "withdrawn", 2306 timestr); 2307 } 2308 2309 /* Store key state and update hints. */ 2310 isc_dir_init(&dir); 2311 if (directory == NULL) { 2312 directory = "."; 2313 } 2314 result = isc_dir_open(&dir, directory); 2315 if (result != ISC_R_SUCCESS) { 2316 return (result); 2317 } 2318 2319 dns_dnssec_get_hints(ksk_key, now); 2320 result = dst_key_tofile(ksk_key->key, options, directory); 2321 if (result == ISC_R_SUCCESS) { 2322 dst_key_setmodified(ksk_key->key, false); 2323 } 2324 isc_dir_close(&dir); 2325 2326 return (result); 2327} 2328 2329isc_result_t 2330dns_keymgr_checkds(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring, 2331 const char *directory, isc_stdtime_t now, isc_stdtime_t when, 2332 bool dspublish) { 2333 return (keymgr_checkds(kasp, keyring, directory, now, when, dspublish, 2334 0, 0, false)); 2335} 2336 2337isc_result_t 2338dns_keymgr_checkds_id(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring, 2339 const char *directory, isc_stdtime_t now, 2340 isc_stdtime_t when, bool dspublish, dns_keytag_t id, 2341 unsigned int alg) { 2342 return (keymgr_checkds(kasp, keyring, directory, now, when, dspublish, 2343 id, alg, true)); 2344} 2345 2346static void 2347keytime_status(dst_key_t *key, isc_stdtime_t now, isc_buffer_t *buf, 2348 const char *pre, int ks, int kt) { 2349 char timestr[26]; /* Minimal buf as per ctime_r() spec. */ 2350 isc_result_t ret; 2351 isc_stdtime_t when = 0; 2352 dst_key_state_t state = NA; 2353 2354 isc_buffer_printf(buf, "%s", pre); 2355 (void)dst_key_getstate(key, ks, &state); 2356 ret = dst_key_gettime(key, kt, &when); 2357 if (state == RUMOURED || state == OMNIPRESENT) { 2358 isc_buffer_printf(buf, "yes - since "); 2359 } else if (now < when) { 2360 isc_buffer_printf(buf, "no - scheduled "); 2361 } else { 2362 isc_buffer_printf(buf, "no\n"); 2363 return; 2364 } 2365 if (ret == ISC_R_SUCCESS) { 2366 isc_stdtime_tostring(when, timestr, sizeof(timestr)); 2367 isc_buffer_printf(buf, "%s\n", timestr); 2368 } 2369} 2370 2371static void 2372rollover_status(dns_dnsseckey_t *dkey, dns_kasp_t *kasp, isc_stdtime_t now, 2373 isc_buffer_t *buf, bool zsk) { 2374 char timestr[26]; /* Minimal buf as per ctime_r() spec. */ 2375 isc_result_t ret = ISC_R_SUCCESS; 2376 isc_stdtime_t active_time = 0; 2377 dst_key_state_t state = NA, goal = NA; 2378 int rrsig, active, retire; 2379 dst_key_t *key = dkey->key; 2380 2381 if (zsk) { 2382 rrsig = DST_KEY_ZRRSIG; 2383 active = DST_TIME_ACTIVATE; 2384 retire = DST_TIME_INACTIVE; 2385 } else { 2386 rrsig = DST_KEY_KRRSIG; 2387 active = DST_TIME_PUBLISH; 2388 retire = DST_TIME_DELETE; 2389 } 2390 2391 isc_buffer_printf(buf, "\n"); 2392 2393 (void)dst_key_getstate(key, DST_KEY_GOAL, &goal); 2394 (void)dst_key_getstate(key, rrsig, &state); 2395 (void)dst_key_gettime(key, active, &active_time); 2396 if (active_time == 0) { 2397 // only interested in keys that were once active. 2398 return; 2399 } 2400 2401 if (goal == HIDDEN && (state == UNRETENTIVE || state == HIDDEN)) { 2402 isc_stdtime_t remove_time = 0; 2403 // is the key removed yet? 2404 state = NA; 2405 (void)dst_key_getstate(key, DST_KEY_DNSKEY, &state); 2406 if (state == RUMOURED || state == OMNIPRESENT) { 2407 ret = dst_key_gettime(key, DST_TIME_DELETE, 2408 &remove_time); 2409 if (ret == ISC_R_SUCCESS) { 2410 isc_buffer_printf(buf, " Key is retired, will " 2411 "be removed on "); 2412 isc_stdtime_tostring(remove_time, timestr, 2413 sizeof(timestr)); 2414 isc_buffer_printf(buf, "%s", timestr); 2415 } 2416 } else { 2417 isc_buffer_printf( 2418 buf, " Key has been removed from the zone"); 2419 } 2420 } else { 2421 isc_stdtime_t retire_time = 0; 2422 uint32_t lifetime = 0; 2423 (void)dst_key_getnum(key, DST_NUM_LIFETIME, &lifetime); 2424 ret = dst_key_gettime(key, retire, &retire_time); 2425 if (ret == ISC_R_SUCCESS) { 2426 if (now < retire_time) { 2427 if (goal == OMNIPRESENT) { 2428 isc_buffer_printf(buf, 2429 " Next rollover " 2430 "scheduled on "); 2431 retire_time = keymgr_prepublication_time( 2432 dkey, kasp, lifetime, now); 2433 } else { 2434 isc_buffer_printf( 2435 buf, " Key will retire on "); 2436 } 2437 } else { 2438 isc_buffer_printf(buf, 2439 " Rollover is due since "); 2440 } 2441 isc_stdtime_tostring(retire_time, timestr, 2442 sizeof(timestr)); 2443 isc_buffer_printf(buf, "%s", timestr); 2444 } else { 2445 isc_buffer_printf(buf, " No rollover scheduled"); 2446 } 2447 } 2448 isc_buffer_printf(buf, "\n"); 2449} 2450 2451static void 2452keystate_status(dst_key_t *key, isc_buffer_t *buf, const char *pre, int ks) { 2453 dst_key_state_t state = NA; 2454 2455 (void)dst_key_getstate(key, ks, &state); 2456 switch (state) { 2457 case HIDDEN: 2458 isc_buffer_printf(buf, " - %shidden\n", pre); 2459 break; 2460 case RUMOURED: 2461 isc_buffer_printf(buf, " - %srumoured\n", pre); 2462 break; 2463 case OMNIPRESENT: 2464 isc_buffer_printf(buf, " - %somnipresent\n", pre); 2465 break; 2466 case UNRETENTIVE: 2467 isc_buffer_printf(buf, " - %sunretentive\n", pre); 2468 break; 2469 case NA: 2470 default: 2471 /* print nothing */ 2472 break; 2473 } 2474} 2475 2476void 2477dns_keymgr_status(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring, 2478 isc_stdtime_t now, char *out, size_t out_len) { 2479 isc_buffer_t buf; 2480 char timestr[26]; /* Minimal buf as per ctime_r() spec. */ 2481 2482 REQUIRE(DNS_KASP_VALID(kasp)); 2483 REQUIRE(keyring != NULL); 2484 REQUIRE(out != NULL); 2485 2486 isc_buffer_init(&buf, out, out_len); 2487 2488 // policy name 2489 isc_buffer_printf(&buf, "dnssec-policy: %s\n", dns_kasp_getname(kasp)); 2490 isc_buffer_printf(&buf, "current time: "); 2491 isc_stdtime_tostring(now, timestr, sizeof(timestr)); 2492 isc_buffer_printf(&buf, "%s\n", timestr); 2493 2494 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 2495 dkey = ISC_LIST_NEXT(dkey, link)) 2496 { 2497 char algstr[DNS_NAME_FORMATSIZE]; 2498 bool ksk = false, zsk = false; 2499 isc_result_t ret; 2500 2501 if (dst_key_is_unused(dkey->key)) { 2502 continue; 2503 } 2504 2505 // key data 2506 dns_secalg_format((dns_secalg_t)dst_key_alg(dkey->key), algstr, 2507 sizeof(algstr)); 2508 isc_buffer_printf(&buf, "\nkey: %d (%s), %s\n", 2509 dst_key_id(dkey->key), algstr, 2510 keymgr_keyrole(dkey->key)); 2511 2512 // publish status 2513 keytime_status(dkey->key, now, &buf, 2514 " published: ", DST_KEY_DNSKEY, 2515 DST_TIME_PUBLISH); 2516 2517 // signing status 2518 ret = dst_key_getbool(dkey->key, DST_BOOL_KSK, &ksk); 2519 if (ret == ISC_R_SUCCESS && ksk) { 2520 keytime_status(dkey->key, now, &buf, 2521 " key signing: ", DST_KEY_KRRSIG, 2522 DST_TIME_PUBLISH); 2523 } 2524 ret = dst_key_getbool(dkey->key, DST_BOOL_ZSK, &zsk); 2525 if (ret == ISC_R_SUCCESS && zsk) { 2526 keytime_status(dkey->key, now, &buf, 2527 " zone signing: ", DST_KEY_ZRRSIG, 2528 DST_TIME_ACTIVATE); 2529 } 2530 2531 // rollover status 2532 rollover_status(dkey, kasp, now, &buf, zsk); 2533 2534 // key states 2535 keystate_status(dkey->key, &buf, 2536 "goal: ", DST_KEY_GOAL); 2537 keystate_status(dkey->key, &buf, 2538 "dnskey: ", DST_KEY_DNSKEY); 2539 keystate_status(dkey->key, &buf, 2540 "ds: ", DST_KEY_DS); 2541 keystate_status(dkey->key, &buf, 2542 "zone rrsig: ", DST_KEY_ZRRSIG); 2543 keystate_status(dkey->key, &buf, 2544 "key rrsig: ", DST_KEY_KRRSIG); 2545 } 2546} 2547 2548isc_result_t 2549dns_keymgr_rollover(dns_kasp_t *kasp, dns_dnsseckeylist_t *keyring, 2550 const char *directory, isc_stdtime_t now, 2551 isc_stdtime_t when, dns_keytag_t id, 2552 unsigned int algorithm) { 2553 int options = (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE); 2554 isc_dir_t dir; 2555 isc_result_t result; 2556 dns_dnsseckey_t *key = NULL; 2557 isc_stdtime_t active, retire, prepub; 2558 2559 REQUIRE(DNS_KASP_VALID(kasp)); 2560 REQUIRE(keyring != NULL); 2561 2562 for (dns_dnsseckey_t *dkey = ISC_LIST_HEAD(*keyring); dkey != NULL; 2563 dkey = ISC_LIST_NEXT(dkey, link)) 2564 { 2565 if (dst_key_id(dkey->key) != id) { 2566 continue; 2567 } 2568 if (algorithm > 0 && dst_key_alg(dkey->key) != algorithm) { 2569 continue; 2570 } 2571 if (key != NULL) { 2572 /* 2573 * Only rollover for one key at a time. 2574 */ 2575 return (DNS_R_TOOMANYKEYS); 2576 } 2577 key = dkey; 2578 } 2579 2580 if (key == NULL) { 2581 return (DNS_R_NOKEYMATCH); 2582 } 2583 2584 result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); 2585 if (result != ISC_R_SUCCESS || active > now) { 2586 return (DNS_R_KEYNOTACTIVE); 2587 } 2588 2589 result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire); 2590 if (result != ISC_R_SUCCESS) { 2591 /** 2592 * Default to as if this key was not scheduled to 2593 * become retired, as if it had unlimited lifetime. 2594 */ 2595 retire = 0; 2596 } 2597 2598 /** 2599 * Usually when is set to now, which is before the scheduled 2600 * prepublication time, meaning we reduce the lifetime of the 2601 * key. But in some cases, the lifetime can also be extended. 2602 * We accept it, but we can return an error here if that 2603 * turns out to be unintuitive behavior. 2604 */ 2605 prepub = dst_key_getttl(key->key) + dns_kasp_publishsafety(kasp) + 2606 dns_kasp_zonepropagationdelay(kasp); 2607 retire = when + prepub; 2608 2609 dst_key_settime(key->key, DST_TIME_INACTIVE, retire); 2610 dst_key_setnum(key->key, DST_NUM_LIFETIME, (retire - active)); 2611 2612 /* Store key state and update hints. */ 2613 isc_dir_init(&dir); 2614 if (directory == NULL) { 2615 directory = "."; 2616 } 2617 result = isc_dir_open(&dir, directory); 2618 if (result != ISC_R_SUCCESS) { 2619 return (result); 2620 } 2621 2622 dns_dnssec_get_hints(key, now); 2623 result = dst_key_tofile(key->key, options, directory); 2624 if (result == ISC_R_SUCCESS) { 2625 dst_key_setmodified(key->key, false); 2626 } 2627 isc_dir_close(&dir); 2628 2629 return (result); 2630} 2631