xref: /netbsd/external/mpl/bind/dist/lib/dns/keymgr.c (revision a706c3b7)
1 /*	$NetBSD: keymgr.c,v 1.10 2023/06/26 22:03:00 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)
69 static int keystatetimes[NUM_KEYSTATES] = { DST_TIME_DNSKEY, DST_TIME_ZRRSIG,
70 					    DST_TIME_KRRSIG, DST_TIME_DS };
71 /* Readable key state types and values. */
72 static const char *keystatetags[NUM_KEYSTATES] = { "DNSKEY", "ZRRSIG", "KRRSIG",
73 						   "DS" };
74 static const char *keystatestrings[4] = { "HIDDEN", "RUMOURED", "OMNIPRESENT",
75 					  "UNRETENTIVE" };
76 
77 /*
78  * Print key role.
79  *
80  */
81 static const char *
keymgr_keyrole(dst_key_t * key)82 keymgr_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  */
107 static void
keymgr_settime_remove(dns_dnsseckey_t * key,dns_kasp_t * kasp)108 keymgr_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  */
145 static void
keymgr_settime_syncpublish(dns_dnsseckey_t * key,dns_kasp_t * kasp,bool first)146 keymgr_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  */
194 static isc_stdtime_t
keymgr_prepublication_time(dns_dnsseckey_t * key,dns_kasp_t * kasp,uint32_t lifetime,isc_stdtime_t now)195 keymgr_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 
305 static void
keymgr_key_retire(dns_dnsseckey_t * key,dns_kasp_t * kasp,isc_stdtime_t now)306 keymgr_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  */
368 static bool
keymgr_dnsseckey_kaspkey_match(dns_dnsseckey_t * dkey,dns_kasp_key_t * kkey)369 keymgr_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 
401 static bool
keymgr_keyid_conflict(dst_key_t * newkey,dns_dnsseckeylist_t * keys)402 keymgr_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  */
430 static isc_result_t
keymgr_createkey(dns_kasp_key_t * kkey,const dns_name_t * origin,dns_rdataclass_t rdclass,isc_mem_t * mctx,dns_dnsseckeylist_t * keylist,dns_dnsseckeylist_t * newkeys,dst_key_t ** dst_key)431 keymgr_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 
473 failure:
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  */
501 static dst_key_state_t
keymgr_desiredstate(dns_dnsseckey_t * key,dst_key_state_t state)502 keymgr_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  */
546 static bool
keymgr_key_match_state(dst_key_t * key,dst_key_t * subject,int type,dst_key_state_t next_state,dst_key_state_t states[NUM_KEYSTATES])547 keymgr_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  */
580 static bool
keymgr_direct_dep(dst_key_t * d,dst_key_t * k)581 keymgr_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  */
596 static bool
keymgr_dep(dst_key_t * k,dns_dnsseckeylist_t * keyring,uint32_t * dep)597 keymgr_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  */
618 static bool
keymgr_key_is_successor(dst_key_t * x,dst_key_t * z,dst_key_t * key,int type,dst_key_state_t next_state,dns_dnsseckeylist_t * keyring)619 keymgr_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  */
707 static bool
keymgr_key_exists_with_state(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next_state,dst_key_state_t states[NUM_KEYSTATES],dst_key_state_t states2[NUM_KEYSTATES],bool check_successor,bool match_algorithms)708 keymgr_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  */
768 static bool
keymgr_key_has_successor(dns_dnsseckey_t * predecessor,dns_dnsseckeylist_t * keyring)769 keymgr_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  */
790 static bool
keymgr_ds_hidden_or_chained(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next_state,bool match_algorithms,bool must_be_hidden)791 keymgr_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  */
858 static bool
keymgr_dnskey_hidden_or_chained(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next_state,bool match_algorithms)859 keymgr_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  */
909 static bool
keymgr_have_ds(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next_state,bool secure_to_insecure)910 keymgr_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  */
939 static bool
keymgr_have_dnskey(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next_state)940 keymgr_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  */
1031 static bool
keymgr_have_rrsig(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next_state)1032 keymgr_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  */
1097 static bool
keymgr_policy_approval(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next)1098 keymgr_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  */
1166 static bool
keymgr_transition_allowed(dns_dnsseckeylist_t * keyring,dns_dnsseckey_t * key,int type,dst_key_state_t next_state,bool secure_to_insecure)1167 keymgr_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  */
1225 static void
keymgr_transition_time(dns_dnsseckey_t * key,int type,dst_key_state_t next_state,dns_kasp_t * kasp,isc_stdtime_t now,isc_stdtime_t * when)1226 keymgr_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  */
1393 static isc_result_t
keymgr_update(dns_dnsseckeylist_t * keyring,dns_kasp_t * kasp,isc_stdtime_t now,isc_stdtime_t * nexttime,bool secure_to_insecure)1394 keymgr_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. */
1399 transition:
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  */
1547 static void
keymgr_key_init(dns_dnsseckey_t * key,dns_kasp_t * kasp,isc_stdtime_t now,bool csk)1548 keymgr_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 
1655 static isc_result_t
keymgr_key_rollover(dns_kasp_key_t * kaspkey,dns_dnsseckey_t * active_key,dns_dnsseckeylist_t * keyring,dns_dnsseckeylist_t * newkeys,const dns_name_t * origin,dns_rdataclass_t rdclass,dns_kasp_t * kasp,uint32_t lifetime,bool rollover,isc_stdtime_t now,isc_stdtime_t * nexttime,isc_mem_t * mctx)1656 keymgr_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 
1871 static bool
keymgr_key_may_be_purged(dst_key_t * key,uint32_t after,isc_stdtime_t now)1872 keymgr_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 
1925 static void
keymgr_purge_keyfile(dst_key_t * key,const char * dir,int type)1926 keymgr_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  */
1963 isc_result_t
dns_keymgr_run(const dns_name_t * origin,dns_rdataclass_t rdclass,const char * directory,isc_mem_t * mctx,dns_dnsseckeylist_t * keyring,dns_dnsseckeylist_t * dnskeys,dns_kasp_t * kasp,isc_stdtime_t now,isc_stdtime_t * nexttime)1964 dns_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 
2213 failure:
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 
2237 static isc_result_t
keymgr_checkds(dns_kasp_t * kasp,dns_dnsseckeylist_t * keyring,const char * directory,isc_stdtime_t now,isc_stdtime_t when,bool dspublish,dns_keytag_t id,unsigned int alg,bool check_id)2238 keymgr_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 
2329 isc_result_t
dns_keymgr_checkds(dns_kasp_t * kasp,dns_dnsseckeylist_t * keyring,const char * directory,isc_stdtime_t now,isc_stdtime_t when,bool dspublish)2330 dns_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 
2337 isc_result_t
dns_keymgr_checkds_id(dns_kasp_t * kasp,dns_dnsseckeylist_t * keyring,const char * directory,isc_stdtime_t now,isc_stdtime_t when,bool dspublish,dns_keytag_t id,unsigned int alg)2338 dns_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 
2346 static void
keytime_status(dst_key_t * key,isc_stdtime_t now,isc_buffer_t * buf,const char * pre,int ks,int kt)2347 keytime_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 
2371 static void
rollover_status(dns_dnsseckey_t * dkey,dns_kasp_t * kasp,isc_stdtime_t now,isc_buffer_t * buf,bool zsk)2372 rollover_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 
2451 static void
keystate_status(dst_key_t * key,isc_buffer_t * buf,const char * pre,int ks)2452 keystate_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 
2476 void
dns_keymgr_status(dns_kasp_t * kasp,dns_dnsseckeylist_t * keyring,isc_stdtime_t now,char * out,size_t out_len)2477 dns_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 
2548 isc_result_t
dns_keymgr_rollover(dns_kasp_t * kasp,dns_dnsseckeylist_t * keyring,const char * directory,isc_stdtime_t now,isc_stdtime_t when,dns_keytag_t id,unsigned int algorithm)2549 dns_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