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