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