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