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