xref: /netbsd-src/external/mpl/bind/dist/lib/dns/kasp.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1*bcda20f6Schristos /*	$NetBSD: kasp.c,v 1.8 2025/01/26 16:25:23 christos Exp $	*/
27f30a007Schristos 
37f30a007Schristos /*
47f30a007Schristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
57f30a007Schristos  *
68596601aSchristos  * SPDX-License-Identifier: MPL-2.0
78596601aSchristos  *
87f30a007Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
97f30a007Schristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
10fce770bdSchristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
117f30a007Schristos  *
127f30a007Schristos  * See the COPYRIGHT file distributed with this work for additional
137f30a007Schristos  * information regarding copyright ownership.
147f30a007Schristos  */
157f30a007Schristos 
167f30a007Schristos /*! \file */
177f30a007Schristos 
187f30a007Schristos #include <string.h>
197f30a007Schristos 
207f30a007Schristos #include <isc/assertions.h>
21fce770bdSchristos #include <isc/buffer.h>
227f30a007Schristos #include <isc/file.h>
23fce770bdSchristos #include <isc/hex.h>
247f30a007Schristos #include <isc/log.h>
257f30a007Schristos #include <isc/mem.h>
267f30a007Schristos #include <isc/util.h>
277f30a007Schristos 
287f30a007Schristos #include <dns/kasp.h>
297f30a007Schristos #include <dns/keyvalues.h>
307f30a007Schristos #include <dns/log.h>
317f30a007Schristos 
32*bcda20f6Schristos #include <dst/dst.h>
33*bcda20f6Schristos 
34bb5aa156Schristos /* Default TTLsig (maximum zone ttl) */
35bb5aa156Schristos #define DEFAULT_TTLSIG 604800 /* one week */
36bb5aa156Schristos 
377f30a007Schristos isc_result_t
387f30a007Schristos dns_kasp_create(isc_mem_t *mctx, const char *name, dns_kasp_t **kaspp) {
397f30a007Schristos 	dns_kasp_t *kasp;
40bb5aa156Schristos 	dns_kasp_t k = {
41bb5aa156Schristos 		.magic = DNS_KASP_MAGIC,
42*bcda20f6Schristos 		.digests = ISC_LIST_INITIALIZER,
43*bcda20f6Schristos 		.keys = ISC_LIST_INITIALIZER,
44*bcda20f6Schristos 		.link = ISC_LINK_INITIALIZER,
45bb5aa156Schristos 	};
467f30a007Schristos 
477f30a007Schristos 	REQUIRE(name != NULL);
487f30a007Schristos 	REQUIRE(kaspp != NULL && *kaspp == NULL);
497f30a007Schristos 
507f30a007Schristos 	kasp = isc_mem_get(mctx, sizeof(*kasp));
51bb5aa156Schristos 	*kasp = k;
52bb5aa156Schristos 
537f30a007Schristos 	kasp->mctx = NULL;
547f30a007Schristos 	isc_mem_attach(mctx, &kasp->mctx);
557f30a007Schristos 	kasp->name = isc_mem_strdup(mctx, name);
567f30a007Schristos 	isc_mutex_init(&kasp->lock);
577f30a007Schristos 	isc_refcount_init(&kasp->references, 1);
587f30a007Schristos 
597f30a007Schristos 	*kaspp = kasp;
60*bcda20f6Schristos 	return ISC_R_SUCCESS;
617f30a007Schristos }
627f30a007Schristos 
637f30a007Schristos void
647f30a007Schristos dns_kasp_attach(dns_kasp_t *source, dns_kasp_t **targetp) {
657f30a007Schristos 	REQUIRE(DNS_KASP_VALID(source));
667f30a007Schristos 	REQUIRE(targetp != NULL && *targetp == NULL);
677f30a007Schristos 
687f30a007Schristos 	isc_refcount_increment(&source->references);
697f30a007Schristos 	*targetp = source;
707f30a007Schristos }
717f30a007Schristos 
728596601aSchristos static void
737f30a007Schristos destroy(dns_kasp_t *kasp) {
74*bcda20f6Schristos 	dns_kasp_key_t *key, *key_next;
75*bcda20f6Schristos 	dns_kasp_digest_t *digest, *digest_next;
767f30a007Schristos 
777f30a007Schristos 	REQUIRE(!ISC_LINK_LINKED(kasp, link));
787f30a007Schristos 
797f30a007Schristos 	for (key = ISC_LIST_HEAD(kasp->keys); key != NULL; key = key_next) {
807f30a007Schristos 		key_next = ISC_LIST_NEXT(key, link);
817f30a007Schristos 		ISC_LIST_UNLINK(kasp->keys, key, link);
827f30a007Schristos 		dns_kasp_key_destroy(key);
837f30a007Schristos 	}
847f30a007Schristos 	INSIST(ISC_LIST_EMPTY(kasp->keys));
857f30a007Schristos 
86*bcda20f6Schristos 	for (digest = ISC_LIST_HEAD(kasp->digests); digest != NULL;
87*bcda20f6Schristos 	     digest = digest_next)
88*bcda20f6Schristos 	{
89*bcda20f6Schristos 		digest_next = ISC_LIST_NEXT(digest, link);
90*bcda20f6Schristos 		ISC_LIST_UNLINK(kasp->digests, digest, link);
91*bcda20f6Schristos 		isc_mem_put(kasp->mctx, digest, sizeof(*digest));
92*bcda20f6Schristos 	}
93*bcda20f6Schristos 	INSIST(ISC_LIST_EMPTY(kasp->digests));
94*bcda20f6Schristos 
957f30a007Schristos 	isc_mutex_destroy(&kasp->lock);
967f30a007Schristos 	isc_mem_free(kasp->mctx, kasp->name);
977f30a007Schristos 	isc_mem_putanddetach(&kasp->mctx, kasp, sizeof(*kasp));
987f30a007Schristos }
997f30a007Schristos 
1007f30a007Schristos void
1017f30a007Schristos dns_kasp_detach(dns_kasp_t **kaspp) {
1027f30a007Schristos 	REQUIRE(kaspp != NULL && DNS_KASP_VALID(*kaspp));
1037f30a007Schristos 
1047f30a007Schristos 	dns_kasp_t *kasp = *kaspp;
1057f30a007Schristos 	*kaspp = NULL;
1067f30a007Schristos 
1077f30a007Schristos 	if (isc_refcount_decrement(&kasp->references) == 1) {
1087f30a007Schristos 		destroy(kasp);
1097f30a007Schristos 	}
1107f30a007Schristos }
1117f30a007Schristos 
1127f30a007Schristos const char *
1137f30a007Schristos dns_kasp_getname(dns_kasp_t *kasp) {
1147f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1157f30a007Schristos 
116*bcda20f6Schristos 	return kasp->name;
1177f30a007Schristos }
1187f30a007Schristos 
1197f30a007Schristos void
1207f30a007Schristos dns_kasp_freeze(dns_kasp_t *kasp) {
1217f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1227f30a007Schristos 	REQUIRE(!kasp->frozen);
1237f30a007Schristos 
1247f30a007Schristos 	kasp->frozen = true;
1257f30a007Schristos }
1267f30a007Schristos 
1277f30a007Schristos void
1287f30a007Schristos dns_kasp_thaw(dns_kasp_t *kasp) {
1297f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1307f30a007Schristos 	REQUIRE(kasp->frozen);
1317f30a007Schristos 
1327f30a007Schristos 	kasp->frozen = false;
1337f30a007Schristos }
1347f30a007Schristos 
1357f30a007Schristos uint32_t
1367f30a007Schristos dns_kasp_signdelay(dns_kasp_t *kasp) {
1377f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1387f30a007Schristos 	REQUIRE(kasp->frozen);
1397f30a007Schristos 
140*bcda20f6Schristos 	return kasp->signatures_validity - kasp->signatures_refresh;
1417f30a007Schristos }
1427f30a007Schristos 
1437f30a007Schristos uint32_t
144dff692fcSchristos dns_kasp_sigjitter(dns_kasp_t *kasp) {
145dff692fcSchristos 	REQUIRE(DNS_KASP_VALID(kasp));
146dff692fcSchristos 	REQUIRE(kasp->frozen);
147dff692fcSchristos 
148*bcda20f6Schristos 	return kasp->signatures_jitter;
149dff692fcSchristos }
150dff692fcSchristos 
151dff692fcSchristos void
152dff692fcSchristos dns_kasp_setsigjitter(dns_kasp_t *kasp, uint32_t value) {
153dff692fcSchristos 	REQUIRE(DNS_KASP_VALID(kasp));
154dff692fcSchristos 	REQUIRE(!kasp->frozen);
155dff692fcSchristos 
156dff692fcSchristos 	kasp->signatures_jitter = value;
157dff692fcSchristos }
158dff692fcSchristos 
159dff692fcSchristos uint32_t
1607f30a007Schristos dns_kasp_sigrefresh(dns_kasp_t *kasp) {
1617f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1627f30a007Schristos 	REQUIRE(kasp->frozen);
1637f30a007Schristos 
164*bcda20f6Schristos 	return kasp->signatures_refresh;
1657f30a007Schristos }
1667f30a007Schristos 
1677f30a007Schristos void
1687f30a007Schristos dns_kasp_setsigrefresh(dns_kasp_t *kasp, uint32_t value) {
1697f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1707f30a007Schristos 	REQUIRE(!kasp->frozen);
1717f30a007Schristos 
1727f30a007Schristos 	kasp->signatures_refresh = value;
1737f30a007Schristos }
1747f30a007Schristos 
1757f30a007Schristos uint32_t
1767f30a007Schristos dns_kasp_sigvalidity(dns_kasp_t *kasp) {
1777f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1787f30a007Schristos 	REQUIRE(kasp->frozen);
1797f30a007Schristos 
180*bcda20f6Schristos 	return kasp->signatures_validity;
1817f30a007Schristos }
1827f30a007Schristos 
1837f30a007Schristos void
1847f30a007Schristos dns_kasp_setsigvalidity(dns_kasp_t *kasp, uint32_t value) {
1857f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1867f30a007Schristos 	REQUIRE(!kasp->frozen);
1877f30a007Schristos 
1887f30a007Schristos 	kasp->signatures_validity = value;
1897f30a007Schristos }
1907f30a007Schristos 
1917f30a007Schristos uint32_t
1927f30a007Schristos dns_kasp_sigvalidity_dnskey(dns_kasp_t *kasp) {
1937f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
1947f30a007Schristos 	REQUIRE(kasp->frozen);
1957f30a007Schristos 
196*bcda20f6Schristos 	return kasp->signatures_validity_dnskey;
1977f30a007Schristos }
1987f30a007Schristos 
1997f30a007Schristos void
2007f30a007Schristos dns_kasp_setsigvalidity_dnskey(dns_kasp_t *kasp, uint32_t value) {
2017f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2027f30a007Schristos 	REQUIRE(!kasp->frozen);
2037f30a007Schristos 
204fce770bdSchristos 	kasp->signatures_validity_dnskey = value;
2057f30a007Schristos }
2067f30a007Schristos 
2077f30a007Schristos dns_ttl_t
2087f30a007Schristos dns_kasp_dnskeyttl(dns_kasp_t *kasp) {
2097f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2107f30a007Schristos 	REQUIRE(kasp->frozen);
2117f30a007Schristos 
212*bcda20f6Schristos 	return kasp->dnskey_ttl;
2137f30a007Schristos }
2147f30a007Schristos 
2157f30a007Schristos void
2167f30a007Schristos dns_kasp_setdnskeyttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
2177f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2187f30a007Schristos 	REQUIRE(!kasp->frozen);
2197f30a007Schristos 
2207f30a007Schristos 	kasp->dnskey_ttl = ttl;
2217f30a007Schristos }
2227f30a007Schristos 
2237f30a007Schristos uint32_t
22499a1c298Schristos dns_kasp_purgekeys(dns_kasp_t *kasp) {
22599a1c298Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
22699a1c298Schristos 	REQUIRE(kasp->frozen);
22799a1c298Schristos 
228*bcda20f6Schristos 	return kasp->purge_keys;
22999a1c298Schristos }
23099a1c298Schristos 
23199a1c298Schristos void
23299a1c298Schristos dns_kasp_setpurgekeys(dns_kasp_t *kasp, uint32_t value) {
23399a1c298Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
23499a1c298Schristos 	REQUIRE(!kasp->frozen);
23599a1c298Schristos 
23699a1c298Schristos 	kasp->purge_keys = value;
23799a1c298Schristos }
23899a1c298Schristos 
23999a1c298Schristos uint32_t
2407f30a007Schristos dns_kasp_publishsafety(dns_kasp_t *kasp) {
2417f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2427f30a007Schristos 	REQUIRE(kasp->frozen);
2437f30a007Schristos 
244*bcda20f6Schristos 	return kasp->publish_safety;
2457f30a007Schristos }
2467f30a007Schristos 
2477f30a007Schristos void
2487f30a007Schristos dns_kasp_setpublishsafety(dns_kasp_t *kasp, uint32_t value) {
2497f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2507f30a007Schristos 	REQUIRE(!kasp->frozen);
2517f30a007Schristos 
2527f30a007Schristos 	kasp->publish_safety = value;
2537f30a007Schristos }
2547f30a007Schristos 
2557f30a007Schristos uint32_t
2567f30a007Schristos dns_kasp_retiresafety(dns_kasp_t *kasp) {
2577f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2587f30a007Schristos 	REQUIRE(kasp->frozen);
2597f30a007Schristos 
260*bcda20f6Schristos 	return kasp->retire_safety;
2617f30a007Schristos }
2627f30a007Schristos 
2637f30a007Schristos void
2647f30a007Schristos dns_kasp_setretiresafety(dns_kasp_t *kasp, uint32_t value) {
2657f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2667f30a007Schristos 	REQUIRE(!kasp->frozen);
2677f30a007Schristos 
2687f30a007Schristos 	kasp->retire_safety = value;
2697f30a007Schristos }
2707f30a007Schristos 
271*bcda20f6Schristos bool
272*bcda20f6Schristos dns_kasp_inlinesigning(dns_kasp_t *kasp) {
273*bcda20f6Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
274*bcda20f6Schristos 	REQUIRE(kasp->frozen);
275*bcda20f6Schristos 
276*bcda20f6Schristos 	return kasp->inline_signing;
277*bcda20f6Schristos }
278*bcda20f6Schristos 
279*bcda20f6Schristos void
280*bcda20f6Schristos dns_kasp_setinlinesigning(dns_kasp_t *kasp, bool value) {
281*bcda20f6Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
282*bcda20f6Schristos 	REQUIRE(!kasp->frozen);
283*bcda20f6Schristos 
284*bcda20f6Schristos 	kasp->inline_signing = value;
285*bcda20f6Schristos }
286*bcda20f6Schristos 
2877f30a007Schristos dns_ttl_t
288bb5aa156Schristos dns_kasp_zonemaxttl(dns_kasp_t *kasp, bool fallback) {
2897f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
2907f30a007Schristos 	REQUIRE(kasp->frozen);
2917f30a007Schristos 
292bb5aa156Schristos 	if (kasp->zone_max_ttl == 0 && fallback) {
293*bcda20f6Schristos 		return DEFAULT_TTLSIG;
294bb5aa156Schristos 	}
295*bcda20f6Schristos 	return kasp->zone_max_ttl;
2967f30a007Schristos }
2977f30a007Schristos 
2987f30a007Schristos void
2997f30a007Schristos dns_kasp_setzonemaxttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
3007f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3017f30a007Schristos 	REQUIRE(!kasp->frozen);
3027f30a007Schristos 
3037f30a007Schristos 	kasp->zone_max_ttl = ttl;
3047f30a007Schristos }
3057f30a007Schristos 
3067f30a007Schristos uint32_t
3077f30a007Schristos dns_kasp_zonepropagationdelay(dns_kasp_t *kasp) {
3087f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3097f30a007Schristos 	REQUIRE(kasp->frozen);
3107f30a007Schristos 
311*bcda20f6Schristos 	return kasp->zone_propagation_delay;
3127f30a007Schristos }
3137f30a007Schristos 
3147f30a007Schristos void
3157f30a007Schristos dns_kasp_setzonepropagationdelay(dns_kasp_t *kasp, uint32_t value) {
3167f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3177f30a007Schristos 	REQUIRE(!kasp->frozen);
3187f30a007Schristos 
3197f30a007Schristos 	kasp->zone_propagation_delay = value;
3207f30a007Schristos }
3217f30a007Schristos 
3227f30a007Schristos dns_ttl_t
3237f30a007Schristos dns_kasp_dsttl(dns_kasp_t *kasp) {
3247f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3257f30a007Schristos 	REQUIRE(kasp->frozen);
3267f30a007Schristos 
327*bcda20f6Schristos 	return kasp->parent_ds_ttl;
3287f30a007Schristos }
3297f30a007Schristos 
3307f30a007Schristos void
3317f30a007Schristos dns_kasp_setdsttl(dns_kasp_t *kasp, dns_ttl_t ttl) {
3327f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3337f30a007Schristos 	REQUIRE(!kasp->frozen);
3347f30a007Schristos 
3357f30a007Schristos 	kasp->parent_ds_ttl = ttl;
3367f30a007Schristos }
3377f30a007Schristos 
3387f30a007Schristos uint32_t
3397f30a007Schristos dns_kasp_parentpropagationdelay(dns_kasp_t *kasp) {
3407f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3417f30a007Schristos 	REQUIRE(kasp->frozen);
3427f30a007Schristos 
343*bcda20f6Schristos 	return kasp->parent_propagation_delay;
3447f30a007Schristos }
3457f30a007Schristos 
3467f30a007Schristos void
3477f30a007Schristos dns_kasp_setparentpropagationdelay(dns_kasp_t *kasp, uint32_t value) {
3487f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3497f30a007Schristos 	REQUIRE(!kasp->frozen);
3507f30a007Schristos 
3517f30a007Schristos 	kasp->parent_propagation_delay = value;
3527f30a007Schristos }
3537f30a007Schristos 
3547f30a007Schristos isc_result_t
3557f30a007Schristos dns_kasplist_find(dns_kasplist_t *list, const char *name, dns_kasp_t **kaspp) {
3567f30a007Schristos 	dns_kasp_t *kasp = NULL;
3577f30a007Schristos 
3587f30a007Schristos 	REQUIRE(kaspp != NULL && *kaspp == NULL);
3597f30a007Schristos 
3607f30a007Schristos 	if (list == NULL) {
361*bcda20f6Schristos 		return ISC_R_NOTFOUND;
3627f30a007Schristos 	}
3637f30a007Schristos 
3647f30a007Schristos 	for (kasp = ISC_LIST_HEAD(*list); kasp != NULL;
3657f30a007Schristos 	     kasp = ISC_LIST_NEXT(kasp, link))
3667f30a007Schristos 	{
3677f30a007Schristos 		if (strcmp(kasp->name, name) == 0) {
3687f30a007Schristos 			break;
3697f30a007Schristos 		}
3707f30a007Schristos 	}
3717f30a007Schristos 
3727f30a007Schristos 	if (kasp == NULL) {
373*bcda20f6Schristos 		return ISC_R_NOTFOUND;
3747f30a007Schristos 	}
3757f30a007Schristos 
3767f30a007Schristos 	dns_kasp_attach(kasp, kaspp);
377*bcda20f6Schristos 	return ISC_R_SUCCESS;
3787f30a007Schristos }
3797f30a007Schristos 
3807f30a007Schristos dns_kasp_keylist_t
3817f30a007Schristos dns_kasp_keys(dns_kasp_t *kasp) {
3827f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3837f30a007Schristos 	REQUIRE(kasp->frozen);
3847f30a007Schristos 
385*bcda20f6Schristos 	return kasp->keys;
3867f30a007Schristos }
3877f30a007Schristos 
3887f30a007Schristos bool
3897f30a007Schristos dns_kasp_keylist_empty(dns_kasp_t *kasp) {
3907f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3917f30a007Schristos 
392*bcda20f6Schristos 	return ISC_LIST_EMPTY(kasp->keys);
3937f30a007Schristos }
3947f30a007Schristos 
3957f30a007Schristos void
3967f30a007Schristos dns_kasp_addkey(dns_kasp_t *kasp, dns_kasp_key_t *key) {
3977f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
3987f30a007Schristos 	REQUIRE(!kasp->frozen);
3997f30a007Schristos 	REQUIRE(key != NULL);
4007f30a007Schristos 
4017f30a007Schristos 	ISC_LIST_APPEND(kasp->keys, key, link);
4027f30a007Schristos }
4037f30a007Schristos 
4047f30a007Schristos isc_result_t
4057f30a007Schristos dns_kasp_key_create(dns_kasp_t *kasp, dns_kasp_key_t **keyp) {
406*bcda20f6Schristos 	dns_kasp_key_t *key = NULL;
407*bcda20f6Schristos 	dns_kasp_key_t k = { .tag_max = 0xffff, .length = -1 };
4087f30a007Schristos 
4097f30a007Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
4107f30a007Schristos 	REQUIRE(keyp != NULL && *keyp == NULL);
4117f30a007Schristos 
4127f30a007Schristos 	key = isc_mem_get(kasp->mctx, sizeof(*key));
413*bcda20f6Schristos 	*key = k;
414*bcda20f6Schristos 
4157f30a007Schristos 	key->mctx = NULL;
4167f30a007Schristos 	isc_mem_attach(kasp->mctx, &key->mctx);
4177f30a007Schristos 
4187f30a007Schristos 	ISC_LINK_INIT(key, link);
4197f30a007Schristos 
4207f30a007Schristos 	*keyp = key;
421*bcda20f6Schristos 	return ISC_R_SUCCESS;
4227f30a007Schristos }
4237f30a007Schristos 
4247f30a007Schristos void
4257f30a007Schristos dns_kasp_key_destroy(dns_kasp_key_t *key) {
4267f30a007Schristos 	REQUIRE(key != NULL);
4277f30a007Schristos 
428*bcda20f6Schristos 	if (key->keystore != NULL) {
429*bcda20f6Schristos 		dns_keystore_detach(&key->keystore);
430*bcda20f6Schristos 	}
4317f30a007Schristos 	isc_mem_putanddetach(&key->mctx, key, sizeof(*key));
4327f30a007Schristos }
4337f30a007Schristos 
4347f30a007Schristos uint32_t
4357f30a007Schristos dns_kasp_key_algorithm(dns_kasp_key_t *key) {
4367f30a007Schristos 	REQUIRE(key != NULL);
4377f30a007Schristos 
438*bcda20f6Schristos 	return key->algorithm;
4397f30a007Schristos }
4407f30a007Schristos 
4417f30a007Schristos unsigned int
4427f30a007Schristos dns_kasp_key_size(dns_kasp_key_t *key) {
4437f30a007Schristos 	unsigned int size = 0;
4447f30a007Schristos 	unsigned int min = 0;
4457f30a007Schristos 
4467f30a007Schristos 	REQUIRE(key != NULL);
4477f30a007Schristos 
4487f30a007Schristos 	switch (key->algorithm) {
4497f30a007Schristos 	case DNS_KEYALG_RSASHA1:
4507f30a007Schristos 	case DNS_KEYALG_NSEC3RSASHA1:
4517f30a007Schristos 	case DNS_KEYALG_RSASHA256:
4527f30a007Schristos 	case DNS_KEYALG_RSASHA512:
453fce770bdSchristos 		min = (key->algorithm == DNS_KEYALG_RSASHA512) ? 1024 : 512;
4547f30a007Schristos 		if (key->length > -1) {
4557f30a007Schristos 			size = (unsigned int)key->length;
4567f30a007Schristos 			if (size < min) {
4577f30a007Schristos 				size = min;
4587f30a007Schristos 			}
4597f30a007Schristos 			if (size > 4096) {
4607f30a007Schristos 				size = 4096;
4617f30a007Schristos 			}
4627f30a007Schristos 		} else {
4637f30a007Schristos 			size = 2048;
4647f30a007Schristos 		}
4657f30a007Schristos 		break;
4667f30a007Schristos 	case DNS_KEYALG_ECDSA256:
4677f30a007Schristos 		size = 256;
4687f30a007Schristos 		break;
4697f30a007Schristos 	case DNS_KEYALG_ECDSA384:
4707f30a007Schristos 		size = 384;
4717f30a007Schristos 		break;
4727f30a007Schristos 	case DNS_KEYALG_ED25519:
473fce770bdSchristos 		size = 256;
4747f30a007Schristos 		break;
4757f30a007Schristos 	case DNS_KEYALG_ED448:
476fce770bdSchristos 		size = 456;
4777f30a007Schristos 		break;
4787f30a007Schristos 	default:
4797f30a007Schristos 		/* unsupported */
4807f30a007Schristos 		break;
4817f30a007Schristos 	}
482*bcda20f6Schristos 	return size;
4837f30a007Schristos }
4847f30a007Schristos 
4857f30a007Schristos uint32_t
4867f30a007Schristos dns_kasp_key_lifetime(dns_kasp_key_t *key) {
4877f30a007Schristos 	REQUIRE(key != NULL);
4887f30a007Schristos 
489*bcda20f6Schristos 	return key->lifetime;
490*bcda20f6Schristos }
491*bcda20f6Schristos 
492*bcda20f6Schristos dns_keystore_t *
493*bcda20f6Schristos dns_kasp_key_keystore(dns_kasp_key_t *key) {
494*bcda20f6Schristos 	REQUIRE(key != NULL);
495*bcda20f6Schristos 
496*bcda20f6Schristos 	return key->keystore;
4977f30a007Schristos }
4987f30a007Schristos 
4997f30a007Schristos bool
5007f30a007Schristos dns_kasp_key_ksk(dns_kasp_key_t *key) {
5017f30a007Schristos 	REQUIRE(key != NULL);
5027f30a007Schristos 
503*bcda20f6Schristos 	return key->role & DNS_KASP_KEY_ROLE_KSK;
5047f30a007Schristos }
5057f30a007Schristos 
5067f30a007Schristos bool
5077f30a007Schristos dns_kasp_key_zsk(dns_kasp_key_t *key) {
5087f30a007Schristos 	REQUIRE(key != NULL);
5097f30a007Schristos 
510*bcda20f6Schristos 	return key->role & DNS_KASP_KEY_ROLE_ZSK;
511*bcda20f6Schristos }
512*bcda20f6Schristos 
513*bcda20f6Schristos uint16_t
514*bcda20f6Schristos dns_kasp_key_tagmin(dns_kasp_key_t *key) {
515*bcda20f6Schristos 	REQUIRE(key != NULL);
516*bcda20f6Schristos 	return key->tag_min;
517*bcda20f6Schristos }
518*bcda20f6Schristos 
519*bcda20f6Schristos uint16_t
520*bcda20f6Schristos dns_kasp_key_tagmax(dns_kasp_key_t *key) {
521*bcda20f6Schristos 	REQUIRE(key != NULL);
522*bcda20f6Schristos 	return key->tag_min;
523*bcda20f6Schristos }
524*bcda20f6Schristos 
525*bcda20f6Schristos bool
526*bcda20f6Schristos dns_kasp_key_match(dns_kasp_key_t *key, dns_dnsseckey_t *dkey) {
527*bcda20f6Schristos 	isc_result_t ret;
528*bcda20f6Schristos 	bool role = false;
529*bcda20f6Schristos 
530*bcda20f6Schristos 	REQUIRE(key != NULL);
531*bcda20f6Schristos 	REQUIRE(dkey != NULL);
532*bcda20f6Schristos 
533*bcda20f6Schristos 	/* Matching algorithms? */
534*bcda20f6Schristos 	if (dst_key_alg(dkey->key) != dns_kasp_key_algorithm(key)) {
535*bcda20f6Schristos 		return false;
536*bcda20f6Schristos 	}
537*bcda20f6Schristos 	/* Matching length? */
538*bcda20f6Schristos 	if (dst_key_size(dkey->key) != dns_kasp_key_size(key)) {
539*bcda20f6Schristos 		return false;
540*bcda20f6Schristos 	}
541*bcda20f6Schristos 	/* Matching role? */
542*bcda20f6Schristos 	ret = dst_key_getbool(dkey->key, DST_BOOL_KSK, &role);
543*bcda20f6Schristos 	if (ret != ISC_R_SUCCESS || role != dns_kasp_key_ksk(key)) {
544*bcda20f6Schristos 		return false;
545*bcda20f6Schristos 	}
546*bcda20f6Schristos 	ret = dst_key_getbool(dkey->key, DST_BOOL_ZSK, &role);
547*bcda20f6Schristos 	if (ret != ISC_R_SUCCESS || role != dns_kasp_key_zsk(key)) {
548*bcda20f6Schristos 		return false;
549*bcda20f6Schristos 	}
550*bcda20f6Schristos 	/* Valid key tag range? */
551*bcda20f6Schristos 	uint16_t id = dst_key_id(dkey->key);
552*bcda20f6Schristos 	uint16_t rid = dst_key_rid(dkey->key);
553*bcda20f6Schristos 	if (id < key->tag_min || id > key->tag_max) {
554*bcda20f6Schristos 		return false;
555*bcda20f6Schristos 	}
556*bcda20f6Schristos 	if (rid < key->tag_min || rid > key->tag_max) {
557*bcda20f6Schristos 		return false;
558*bcda20f6Schristos 	}
559*bcda20f6Schristos 
560*bcda20f6Schristos 	/* Found a match. */
561*bcda20f6Schristos 	return true;
5627f30a007Schristos }
563fce770bdSchristos 
564fce770bdSchristos uint8_t
565fce770bdSchristos dns_kasp_nsec3iter(dns_kasp_t *kasp) {
566fce770bdSchristos 	REQUIRE(kasp != NULL);
567fce770bdSchristos 	REQUIRE(kasp->frozen);
568fce770bdSchristos 	REQUIRE(kasp->nsec3);
569fce770bdSchristos 
570*bcda20f6Schristos 	return kasp->nsec3param.iterations;
571fce770bdSchristos }
572fce770bdSchristos 
573fce770bdSchristos uint8_t
574fce770bdSchristos dns_kasp_nsec3flags(dns_kasp_t *kasp) {
575fce770bdSchristos 	REQUIRE(kasp != NULL);
576fce770bdSchristos 	REQUIRE(kasp->frozen);
577fce770bdSchristos 	REQUIRE(kasp->nsec3);
578fce770bdSchristos 
579fce770bdSchristos 	if (kasp->nsec3param.optout) {
580*bcda20f6Schristos 		return 0x01;
581fce770bdSchristos 	}
582*bcda20f6Schristos 	return 0x00;
583fce770bdSchristos }
584fce770bdSchristos 
585fce770bdSchristos uint8_t
586fce770bdSchristos dns_kasp_nsec3saltlen(dns_kasp_t *kasp) {
587fce770bdSchristos 	REQUIRE(kasp != NULL);
588fce770bdSchristos 	REQUIRE(kasp->frozen);
589fce770bdSchristos 	REQUIRE(kasp->nsec3);
590fce770bdSchristos 
591*bcda20f6Schristos 	return kasp->nsec3param.saltlen;
592fce770bdSchristos }
593fce770bdSchristos 
594fce770bdSchristos bool
595fce770bdSchristos dns_kasp_nsec3(dns_kasp_t *kasp) {
596fce770bdSchristos 	REQUIRE(kasp != NULL);
597fce770bdSchristos 	REQUIRE(kasp->frozen);
598fce770bdSchristos 
599fce770bdSchristos 	return kasp->nsec3;
600fce770bdSchristos }
601fce770bdSchristos 
602fce770bdSchristos void
603fce770bdSchristos dns_kasp_setnsec3(dns_kasp_t *kasp, bool nsec3) {
604fce770bdSchristos 	REQUIRE(kasp != NULL);
605fce770bdSchristos 	REQUIRE(!kasp->frozen);
606fce770bdSchristos 
607fce770bdSchristos 	kasp->nsec3 = nsec3;
608fce770bdSchristos }
609fce770bdSchristos 
610fce770bdSchristos void
611fce770bdSchristos dns_kasp_setnsec3param(dns_kasp_t *kasp, uint8_t iter, bool optout,
612fce770bdSchristos 		       uint8_t saltlen) {
613fce770bdSchristos 	REQUIRE(kasp != NULL);
614fce770bdSchristos 	REQUIRE(!kasp->frozen);
615fce770bdSchristos 	REQUIRE(kasp->nsec3);
616fce770bdSchristos 
617fce770bdSchristos 	kasp->nsec3param.iterations = iter;
618fce770bdSchristos 	kasp->nsec3param.optout = optout;
619fce770bdSchristos 	kasp->nsec3param.saltlen = saltlen;
620fce770bdSchristos }
621*bcda20f6Schristos 
622*bcda20f6Schristos bool
623*bcda20f6Schristos dns_kasp_offlineksk(dns_kasp_t *kasp) {
624*bcda20f6Schristos 	REQUIRE(kasp != NULL);
625*bcda20f6Schristos 	REQUIRE(kasp->frozen);
626*bcda20f6Schristos 
627*bcda20f6Schristos 	return kasp->offlineksk;
628*bcda20f6Schristos }
629*bcda20f6Schristos 
630*bcda20f6Schristos void
631*bcda20f6Schristos dns_kasp_setofflineksk(dns_kasp_t *kasp, bool offlineksk) {
632*bcda20f6Schristos 	REQUIRE(kasp != NULL);
633*bcda20f6Schristos 	REQUIRE(!kasp->frozen);
634*bcda20f6Schristos 
635*bcda20f6Schristos 	kasp->offlineksk = offlineksk;
636*bcda20f6Schristos }
637*bcda20f6Schristos 
638*bcda20f6Schristos bool
639*bcda20f6Schristos dns_kasp_cdnskey(dns_kasp_t *kasp) {
640*bcda20f6Schristos 	REQUIRE(kasp != NULL);
641*bcda20f6Schristos 	REQUIRE(kasp->frozen);
642*bcda20f6Schristos 
643*bcda20f6Schristos 	return kasp->cdnskey;
644*bcda20f6Schristos }
645*bcda20f6Schristos 
646*bcda20f6Schristos void
647*bcda20f6Schristos dns_kasp_setcdnskey(dns_kasp_t *kasp, bool cdnskey) {
648*bcda20f6Schristos 	REQUIRE(kasp != NULL);
649*bcda20f6Schristos 	REQUIRE(!kasp->frozen);
650*bcda20f6Schristos 
651*bcda20f6Schristos 	kasp->cdnskey = cdnskey;
652*bcda20f6Schristos }
653*bcda20f6Schristos 
654*bcda20f6Schristos dns_kasp_digestlist_t
655*bcda20f6Schristos dns_kasp_digests(dns_kasp_t *kasp) {
656*bcda20f6Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
657*bcda20f6Schristos 	REQUIRE(kasp->frozen);
658*bcda20f6Schristos 
659*bcda20f6Schristos 	return kasp->digests;
660*bcda20f6Schristos }
661*bcda20f6Schristos 
662*bcda20f6Schristos void
663*bcda20f6Schristos dns_kasp_adddigest(dns_kasp_t *kasp, dns_dsdigest_t alg) {
664*bcda20f6Schristos 	dns_kasp_digest_t *digest;
665*bcda20f6Schristos 
666*bcda20f6Schristos 	REQUIRE(DNS_KASP_VALID(kasp));
667*bcda20f6Schristos 	REQUIRE(!kasp->frozen);
668*bcda20f6Schristos 
669*bcda20f6Schristos 	/* Suppress unsupported algorithms */
670*bcda20f6Schristos 	if (!dst_ds_digest_supported(alg)) {
671*bcda20f6Schristos 		return;
672*bcda20f6Schristos 	}
673*bcda20f6Schristos 
674*bcda20f6Schristos 	/* Suppress duplicates */
675*bcda20f6Schristos 	for (dns_kasp_digest_t *d = ISC_LIST_HEAD(kasp->digests); d != NULL;
676*bcda20f6Schristos 	     d = ISC_LIST_NEXT(d, link))
677*bcda20f6Schristos 	{
678*bcda20f6Schristos 		if (d->digest == alg) {
679*bcda20f6Schristos 			return;
680*bcda20f6Schristos 		}
681*bcda20f6Schristos 	}
682*bcda20f6Schristos 
683*bcda20f6Schristos 	digest = isc_mem_get(kasp->mctx, sizeof(*digest));
684*bcda20f6Schristos 	digest->digest = alg;
685*bcda20f6Schristos 	ISC_LINK_INIT(digest, link);
686*bcda20f6Schristos 	ISC_LIST_APPEND(kasp->digests, digest, link);
687*bcda20f6Schristos }
688