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