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