1/* $NetBSD: kasp.c,v 1.6 2024/02/21 22:52:06 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 <string.h> 19 20#include <isc/assertions.h> 21#include <isc/buffer.h> 22#include <isc/file.h> 23#include <isc/hex.h> 24#include <isc/log.h> 25#include <isc/mem.h> 26#include <isc/util.h> 27 28#include <dns/kasp.h> 29#include <dns/keyvalues.h> 30#include <dns/log.h> 31 32/* Default TTLsig (maximum zone ttl) */ 33#define DEFAULT_TTLSIG 604800 /* one week */ 34 35isc_result_t 36dns_kasp_create(isc_mem_t *mctx, const char *name, dns_kasp_t **kaspp) { 37 dns_kasp_t *kasp; 38 dns_kasp_t k = { 39 .magic = DNS_KASP_MAGIC, 40 }; 41 42 REQUIRE(name != NULL); 43 REQUIRE(kaspp != NULL && *kaspp == NULL); 44 45 kasp = isc_mem_get(mctx, sizeof(*kasp)); 46 *kasp = k; 47 48 kasp->mctx = NULL; 49 isc_mem_attach(mctx, &kasp->mctx); 50 kasp->name = isc_mem_strdup(mctx, name); 51 isc_mutex_init(&kasp->lock); 52 isc_refcount_init(&kasp->references, 1); 53 54 ISC_LINK_INIT(kasp, link); 55 ISC_LIST_INIT(kasp->keys); 56 57 *kaspp = kasp; 58 return (ISC_R_SUCCESS); 59} 60 61void 62dns_kasp_attach(dns_kasp_t *source, dns_kasp_t **targetp) { 63 REQUIRE(DNS_KASP_VALID(source)); 64 REQUIRE(targetp != NULL && *targetp == NULL); 65 66 isc_refcount_increment(&source->references); 67 *targetp = source; 68} 69 70static void 71destroy(dns_kasp_t *kasp) { 72 dns_kasp_key_t *key; 73 dns_kasp_key_t *key_next; 74 75 REQUIRE(!ISC_LINK_LINKED(kasp, link)); 76 77 for (key = ISC_LIST_HEAD(kasp->keys); key != NULL; key = key_next) { 78 key_next = ISC_LIST_NEXT(key, link); 79 ISC_LIST_UNLINK(kasp->keys, key, link); 80 dns_kasp_key_destroy(key); 81 } 82 INSIST(ISC_LIST_EMPTY(kasp->keys)); 83 84 isc_mutex_destroy(&kasp->lock); 85 isc_mem_free(kasp->mctx, kasp->name); 86 isc_mem_putanddetach(&kasp->mctx, kasp, sizeof(*kasp)); 87} 88 89void 90dns_kasp_detach(dns_kasp_t **kaspp) { 91 REQUIRE(kaspp != NULL && DNS_KASP_VALID(*kaspp)); 92 93 dns_kasp_t *kasp = *kaspp; 94 *kaspp = NULL; 95 96 if (isc_refcount_decrement(&kasp->references) == 1) { 97 destroy(kasp); 98 } 99} 100 101const char * 102dns_kasp_getname(dns_kasp_t *kasp) { 103 REQUIRE(DNS_KASP_VALID(kasp)); 104 105 return (kasp->name); 106} 107 108void 109dns_kasp_freeze(dns_kasp_t *kasp) { 110 REQUIRE(DNS_KASP_VALID(kasp)); 111 REQUIRE(!kasp->frozen); 112 113 kasp->frozen = true; 114} 115 116void 117dns_kasp_thaw(dns_kasp_t *kasp) { 118 REQUIRE(DNS_KASP_VALID(kasp)); 119 REQUIRE(kasp->frozen); 120 121 kasp->frozen = false; 122} 123 124uint32_t 125dns_kasp_signdelay(dns_kasp_t *kasp) { 126 REQUIRE(DNS_KASP_VALID(kasp)); 127 REQUIRE(kasp->frozen); 128 129 return (kasp->signatures_validity - kasp->signatures_refresh); 130} 131 132uint32_t 133dns_kasp_sigrefresh(dns_kasp_t *kasp) { 134 REQUIRE(DNS_KASP_VALID(kasp)); 135 REQUIRE(kasp->frozen); 136 137 return (kasp->signatures_refresh); 138} 139 140void 141dns_kasp_setsigrefresh(dns_kasp_t *kasp, uint32_t value) { 142 REQUIRE(DNS_KASP_VALID(kasp)); 143 REQUIRE(!kasp->frozen); 144 145 kasp->signatures_refresh = value; 146} 147 148uint32_t 149dns_kasp_sigvalidity(dns_kasp_t *kasp) { 150 REQUIRE(DNS_KASP_VALID(kasp)); 151 REQUIRE(kasp->frozen); 152 153 return (kasp->signatures_validity); 154} 155 156void 157dns_kasp_setsigvalidity(dns_kasp_t *kasp, uint32_t value) { 158 REQUIRE(DNS_KASP_VALID(kasp)); 159 REQUIRE(!kasp->frozen); 160 161 kasp->signatures_validity = value; 162} 163 164uint32_t 165dns_kasp_sigvalidity_dnskey(dns_kasp_t *kasp) { 166 REQUIRE(DNS_KASP_VALID(kasp)); 167 REQUIRE(kasp->frozen); 168 169 return (kasp->signatures_validity_dnskey); 170} 171 172void 173dns_kasp_setsigvalidity_dnskey(dns_kasp_t *kasp, uint32_t value) { 174 REQUIRE(DNS_KASP_VALID(kasp)); 175 REQUIRE(!kasp->frozen); 176 177 kasp->signatures_validity_dnskey = value; 178} 179 180dns_ttl_t 181dns_kasp_dnskeyttl(dns_kasp_t *kasp) { 182 REQUIRE(DNS_KASP_VALID(kasp)); 183 REQUIRE(kasp->frozen); 184 185 return (kasp->dnskey_ttl); 186} 187 188void 189dns_kasp_setdnskeyttl(dns_kasp_t *kasp, dns_ttl_t ttl) { 190 REQUIRE(DNS_KASP_VALID(kasp)); 191 REQUIRE(!kasp->frozen); 192 193 kasp->dnskey_ttl = ttl; 194} 195 196uint32_t 197dns_kasp_purgekeys(dns_kasp_t *kasp) { 198 REQUIRE(DNS_KASP_VALID(kasp)); 199 REQUIRE(kasp->frozen); 200 201 return (kasp->purge_keys); 202} 203 204void 205dns_kasp_setpurgekeys(dns_kasp_t *kasp, uint32_t value) { 206 REQUIRE(DNS_KASP_VALID(kasp)); 207 REQUIRE(!kasp->frozen); 208 209 kasp->purge_keys = value; 210} 211 212uint32_t 213dns_kasp_publishsafety(dns_kasp_t *kasp) { 214 REQUIRE(DNS_KASP_VALID(kasp)); 215 REQUIRE(kasp->frozen); 216 217 return (kasp->publish_safety); 218} 219 220void 221dns_kasp_setpublishsafety(dns_kasp_t *kasp, uint32_t value) { 222 REQUIRE(DNS_KASP_VALID(kasp)); 223 REQUIRE(!kasp->frozen); 224 225 kasp->publish_safety = value; 226} 227 228uint32_t 229dns_kasp_retiresafety(dns_kasp_t *kasp) { 230 REQUIRE(DNS_KASP_VALID(kasp)); 231 REQUIRE(kasp->frozen); 232 233 return (kasp->retire_safety); 234} 235 236void 237dns_kasp_setretiresafety(dns_kasp_t *kasp, uint32_t value) { 238 REQUIRE(DNS_KASP_VALID(kasp)); 239 REQUIRE(!kasp->frozen); 240 241 kasp->retire_safety = value; 242} 243 244dns_ttl_t 245dns_kasp_zonemaxttl(dns_kasp_t *kasp, bool fallback) { 246 REQUIRE(DNS_KASP_VALID(kasp)); 247 REQUIRE(kasp->frozen); 248 249 if (kasp->zone_max_ttl == 0 && fallback) { 250 return (DEFAULT_TTLSIG); 251 } 252 return (kasp->zone_max_ttl); 253} 254 255void 256dns_kasp_setzonemaxttl(dns_kasp_t *kasp, dns_ttl_t ttl) { 257 REQUIRE(DNS_KASP_VALID(kasp)); 258 REQUIRE(!kasp->frozen); 259 260 kasp->zone_max_ttl = ttl; 261} 262 263uint32_t 264dns_kasp_zonepropagationdelay(dns_kasp_t *kasp) { 265 REQUIRE(DNS_KASP_VALID(kasp)); 266 REQUIRE(kasp->frozen); 267 268 return (kasp->zone_propagation_delay); 269} 270 271void 272dns_kasp_setzonepropagationdelay(dns_kasp_t *kasp, uint32_t value) { 273 REQUIRE(DNS_KASP_VALID(kasp)); 274 REQUIRE(!kasp->frozen); 275 276 kasp->zone_propagation_delay = value; 277} 278 279dns_ttl_t 280dns_kasp_dsttl(dns_kasp_t *kasp) { 281 REQUIRE(DNS_KASP_VALID(kasp)); 282 REQUIRE(kasp->frozen); 283 284 return (kasp->parent_ds_ttl); 285} 286 287void 288dns_kasp_setdsttl(dns_kasp_t *kasp, dns_ttl_t ttl) { 289 REQUIRE(DNS_KASP_VALID(kasp)); 290 REQUIRE(!kasp->frozen); 291 292 kasp->parent_ds_ttl = ttl; 293} 294 295uint32_t 296dns_kasp_parentpropagationdelay(dns_kasp_t *kasp) { 297 REQUIRE(DNS_KASP_VALID(kasp)); 298 REQUIRE(kasp->frozen); 299 300 return (kasp->parent_propagation_delay); 301} 302 303void 304dns_kasp_setparentpropagationdelay(dns_kasp_t *kasp, uint32_t value) { 305 REQUIRE(DNS_KASP_VALID(kasp)); 306 REQUIRE(!kasp->frozen); 307 308 kasp->parent_propagation_delay = value; 309} 310 311isc_result_t 312dns_kasplist_find(dns_kasplist_t *list, const char *name, dns_kasp_t **kaspp) { 313 dns_kasp_t *kasp = NULL; 314 315 REQUIRE(kaspp != NULL && *kaspp == NULL); 316 317 if (list == NULL) { 318 return (ISC_R_NOTFOUND); 319 } 320 321 for (kasp = ISC_LIST_HEAD(*list); kasp != NULL; 322 kasp = ISC_LIST_NEXT(kasp, link)) 323 { 324 if (strcmp(kasp->name, name) == 0) { 325 break; 326 } 327 } 328 329 if (kasp == NULL) { 330 return (ISC_R_NOTFOUND); 331 } 332 333 dns_kasp_attach(kasp, kaspp); 334 return (ISC_R_SUCCESS); 335} 336 337dns_kasp_keylist_t 338dns_kasp_keys(dns_kasp_t *kasp) { 339 REQUIRE(DNS_KASP_VALID(kasp)); 340 REQUIRE(kasp->frozen); 341 342 return (kasp->keys); 343} 344 345bool 346dns_kasp_keylist_empty(dns_kasp_t *kasp) { 347 REQUIRE(DNS_KASP_VALID(kasp)); 348 349 return (ISC_LIST_EMPTY(kasp->keys)); 350} 351 352void 353dns_kasp_addkey(dns_kasp_t *kasp, dns_kasp_key_t *key) { 354 REQUIRE(DNS_KASP_VALID(kasp)); 355 REQUIRE(!kasp->frozen); 356 REQUIRE(key != NULL); 357 358 ISC_LIST_APPEND(kasp->keys, key, link); 359} 360 361isc_result_t 362dns_kasp_key_create(dns_kasp_t *kasp, dns_kasp_key_t **keyp) { 363 dns_kasp_key_t *key; 364 365 REQUIRE(DNS_KASP_VALID(kasp)); 366 REQUIRE(keyp != NULL && *keyp == NULL); 367 368 key = isc_mem_get(kasp->mctx, sizeof(*key)); 369 key->mctx = NULL; 370 isc_mem_attach(kasp->mctx, &key->mctx); 371 372 ISC_LINK_INIT(key, link); 373 374 key->lifetime = 0; 375 key->algorithm = 0; 376 key->length = -1; 377 key->role = 0; 378 *keyp = key; 379 return (ISC_R_SUCCESS); 380} 381 382void 383dns_kasp_key_destroy(dns_kasp_key_t *key) { 384 REQUIRE(key != NULL); 385 386 isc_mem_putanddetach(&key->mctx, key, sizeof(*key)); 387} 388 389uint32_t 390dns_kasp_key_algorithm(dns_kasp_key_t *key) { 391 REQUIRE(key != NULL); 392 393 return (key->algorithm); 394} 395 396unsigned int 397dns_kasp_key_size(dns_kasp_key_t *key) { 398 unsigned int size = 0; 399 unsigned int min = 0; 400 401 REQUIRE(key != NULL); 402 403 switch (key->algorithm) { 404 case DNS_KEYALG_RSASHA1: 405 case DNS_KEYALG_NSEC3RSASHA1: 406 case DNS_KEYALG_RSASHA256: 407 case DNS_KEYALG_RSASHA512: 408 min = (key->algorithm == DNS_KEYALG_RSASHA512) ? 1024 : 512; 409 if (key->length > -1) { 410 size = (unsigned int)key->length; 411 if (size < min) { 412 size = min; 413 } 414 if (size > 4096) { 415 size = 4096; 416 } 417 } else { 418 size = 2048; 419 } 420 break; 421 case DNS_KEYALG_ECDSA256: 422 size = 256; 423 break; 424 case DNS_KEYALG_ECDSA384: 425 size = 384; 426 break; 427 case DNS_KEYALG_ED25519: 428 size = 256; 429 break; 430 case DNS_KEYALG_ED448: 431 size = 456; 432 break; 433 default: 434 /* unsupported */ 435 break; 436 } 437 return (size); 438} 439 440uint32_t 441dns_kasp_key_lifetime(dns_kasp_key_t *key) { 442 REQUIRE(key != NULL); 443 444 return (key->lifetime); 445} 446 447bool 448dns_kasp_key_ksk(dns_kasp_key_t *key) { 449 REQUIRE(key != NULL); 450 451 return (key->role & DNS_KASP_KEY_ROLE_KSK); 452} 453 454bool 455dns_kasp_key_zsk(dns_kasp_key_t *key) { 456 REQUIRE(key != NULL); 457 458 return (key->role & DNS_KASP_KEY_ROLE_ZSK); 459} 460 461uint8_t 462dns_kasp_nsec3iter(dns_kasp_t *kasp) { 463 REQUIRE(kasp != NULL); 464 REQUIRE(kasp->frozen); 465 REQUIRE(kasp->nsec3); 466 467 return (kasp->nsec3param.iterations); 468} 469 470uint8_t 471dns_kasp_nsec3flags(dns_kasp_t *kasp) { 472 REQUIRE(kasp != NULL); 473 REQUIRE(kasp->frozen); 474 REQUIRE(kasp->nsec3); 475 476 if (kasp->nsec3param.optout) { 477 return (0x01); 478 } 479 return (0x00); 480} 481 482uint8_t 483dns_kasp_nsec3saltlen(dns_kasp_t *kasp) { 484 REQUIRE(kasp != NULL); 485 REQUIRE(kasp->frozen); 486 REQUIRE(kasp->nsec3); 487 488 return (kasp->nsec3param.saltlen); 489} 490 491bool 492dns_kasp_nsec3(dns_kasp_t *kasp) { 493 REQUIRE(kasp != NULL); 494 REQUIRE(kasp->frozen); 495 496 return kasp->nsec3; 497} 498 499void 500dns_kasp_setnsec3(dns_kasp_t *kasp, bool nsec3) { 501 REQUIRE(kasp != NULL); 502 REQUIRE(!kasp->frozen); 503 504 kasp->nsec3 = nsec3; 505} 506 507void 508dns_kasp_setnsec3param(dns_kasp_t *kasp, uint8_t iter, bool optout, 509 uint8_t saltlen) { 510 REQUIRE(kasp != NULL); 511 REQUIRE(!kasp->frozen); 512 REQUIRE(kasp->nsec3); 513 514 kasp->nsec3param.iterations = iter; 515 kasp->nsec3param.optout = optout; 516 kasp->nsec3param.saltlen = saltlen; 517} 518