dst_api.c revision 1.9
1/* $NetBSD: dst_api.c,v 1.9 2021/04/05 11:27:02 rillig Exp $ */ 2 3/* 4 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 9 * 10 * See the COPYRIGHT file distributed with this work for additional 11 * information regarding copyright ownership. 12 * 13 * Portions Copyright (C) Network Associates, Inc. 14 * 15 * Permission to use, copy, modify, and/or distribute this software for any 16 * purpose with or without fee is hereby granted, provided that the above 17 * copyright notice and this permission notice appear in all copies. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 20 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 22 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 24 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 25 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 */ 27 28/*! \file */ 29 30#include <inttypes.h> 31#include <stdbool.h> 32#include <stdlib.h> 33#include <time.h> 34 35#include <isc/buffer.h> 36#include <isc/dir.h> 37#include <isc/file.h> 38#include <isc/fsaccess.h> 39#include <isc/lex.h> 40#include <isc/mem.h> 41#include <isc/once.h> 42#include <isc/platform.h> 43#include <isc/print.h> 44#include <isc/random.h> 45#include <isc/refcount.h> 46#include <isc/safe.h> 47#include <isc/string.h> 48#include <isc/time.h> 49#include <isc/util.h> 50 51#include <pk11/site.h> 52 53#define DST_KEY_INTERNAL 54 55#include <dns/fixedname.h> 56#include <dns/keyvalues.h> 57#include <dns/name.h> 58#include <dns/rdata.h> 59#include <dns/rdataclass.h> 60#include <dns/ttl.h> 61#include <dns/types.h> 62 63#include <dst/result.h> 64 65#include "dst_internal.h" 66 67#define DST_AS_STR(t) ((t).value.as_textregion.base) 68 69#define NEXTTOKEN(lex, opt, token) \ 70 { \ 71 ret = isc_lex_gettoken(lex, opt, token); \ 72 if (ret != ISC_R_SUCCESS) \ 73 goto cleanup; \ 74 } 75 76#define NEXTTOKEN_OR_EOF(lex, opt, token) \ 77 do { \ 78 ret = isc_lex_gettoken(lex, opt, token); \ 79 if (ret == ISC_R_EOF) \ 80 break; \ 81 if (ret != ISC_R_SUCCESS) \ 82 goto cleanup; \ 83 } while ((*token).type == isc_tokentype_eol); 84 85#define READLINE(lex, opt, token) \ 86 do { \ 87 ret = isc_lex_gettoken(lex, opt, token); \ 88 if (ret == ISC_R_EOF) \ 89 break; \ 90 if (ret != ISC_R_SUCCESS) \ 91 goto cleanup; \ 92 } while ((*token).type != isc_tokentype_eol) 93 94#define BADTOKEN() \ 95 { \ 96 ret = ISC_R_UNEXPECTEDTOKEN; \ 97 goto cleanup; \ 98 } 99 100#define NUMERIC_NTAGS (DST_MAX_NUMERIC + 1) 101static const char *numerictags[NUMERIC_NTAGS] = { 102 "Predecessor:", "Successor:", "MaxTTL:", "RollPeriod:", "Lifetime:" 103}; 104 105#define BOOLEAN_NTAGS (DST_MAX_BOOLEAN + 1) 106static const char *booleantags[BOOLEAN_NTAGS] = { "KSK:", "ZSK:" }; 107 108#define TIMING_NTAGS (DST_MAX_TIMES + 1) 109static const char *timingtags[TIMING_NTAGS] = { 110 "Generated:", "Published:", "Active:", "Revoked:", 111 "Retired:", "Removed:", 112 113 "DSPublish:", "SyncPublish:", "SyncDelete:", 114 115 "DNSKEYChange:", "ZRRSIGChange:", "KRRSIGChange:", "DSChange:", 116 117 "DSRemoved:" 118}; 119 120#define KEYSTATES_NTAGS (DST_MAX_KEYSTATES + 1) 121static const char *keystatestags[KEYSTATES_NTAGS] = { 122 "DNSKEYState:", "ZRRSIGState:", "KRRSIGState:", "DSState:", "GoalState:" 123}; 124 125#define KEYSTATES_NVALUES 4 126static const char *keystates[KEYSTATES_NVALUES] = { 127 "hidden", 128 "rumoured", 129 "omnipresent", 130 "unretentive", 131}; 132 133#define STATE_ALGORITHM_STR "Algorithm:" 134#define STATE_LENGTH_STR "Length:" 135#define MAX_NTAGS \ 136 (DST_MAX_NUMERIC + DST_MAX_BOOLEAN + DST_MAX_TIMES + DST_MAX_KEYSTATES) 137 138static dst_func_t *dst_t_func[DST_MAX_ALGS]; 139 140static bool dst_initialized = false; 141 142void 143gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); 144 145/* 146 * Static functions. 147 */ 148static dst_key_t * 149get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags, 150 unsigned int protocol, unsigned int bits, 151 dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx); 152static isc_result_t 153write_public_key(const dst_key_t *key, int type, const char *directory); 154static isc_result_t 155write_key_state(const dst_key_t *key, int type, const char *directory); 156static isc_result_t 157buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg, 158 unsigned int type, const char *directory, isc_buffer_t *out); 159static isc_result_t 160computeid(dst_key_t *key); 161static isc_result_t 162frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, 163 unsigned int protocol, dns_rdataclass_t rdclass, 164 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); 165 166static isc_result_t 167algorithm_status(unsigned int alg); 168 169static isc_result_t 170addsuffix(char *filename, int len, const char *dirname, const char *ofilename, 171 const char *suffix); 172 173#define RETERR(x) \ 174 do { \ 175 result = (x); \ 176 if (result != ISC_R_SUCCESS) \ 177 goto out; \ 178 } while (0) 179 180#define CHECKALG(alg) \ 181 do { \ 182 isc_result_t _r; \ 183 _r = algorithm_status(alg); \ 184 if (_r != ISC_R_SUCCESS) \ 185 return ((_r)); \ 186 } while (0) 187 188isc_result_t 189dst_lib_init(isc_mem_t *mctx, const char *engine) { 190 isc_result_t result; 191 192 REQUIRE(mctx != NULL); 193 REQUIRE(!dst_initialized); 194 195 UNUSED(engine); 196 197 dst_result_register(); 198 199 memset(dst_t_func, 0, sizeof(dst_t_func)); 200 RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5])); 201 RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1])); 202 RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224])); 203 RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256])); 204 RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384])); 205 RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); 206 RETERR(dst__openssl_init(mctx, engine)); 207 RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH])); 208#if USE_OPENSSL 209 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1], 210 DST_ALG_RSASHA1)); 211 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1], 212 DST_ALG_NSEC3RSASHA1)); 213 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256], 214 DST_ALG_RSASHA256)); 215 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512], 216 DST_ALG_RSASHA512)); 217 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256])); 218 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); 219#ifdef HAVE_OPENSSL_ED25519 220 RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED25519])); 221#endif /* ifdef HAVE_OPENSSL_ED25519 */ 222#ifdef HAVE_OPENSSL_ED448 223 RETERR(dst__openssleddsa_init(&dst_t_func[DST_ALG_ED448])); 224#endif /* ifdef HAVE_OPENSSL_ED448 */ 225#endif /* USE_OPENSSL */ 226 227#if USE_PKCS11 228 RETERR(dst__pkcs11_init(mctx, engine)); 229 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1])); 230 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1])); 231 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256])); 232 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512])); 233 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256])); 234 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); 235 RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED25519])); 236 RETERR(dst__pkcs11eddsa_init(&dst_t_func[DST_ALG_ED448])); 237#endif /* USE_PKCS11 */ 238#ifdef GSSAPI 239 RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI])); 240#endif /* ifdef GSSAPI */ 241 242 dst_initialized = true; 243 return (ISC_R_SUCCESS); 244 245out: 246 /* avoid immediate crash! */ 247 dst_initialized = true; 248 dst_lib_destroy(); 249 return (result); 250} 251 252void 253dst_lib_destroy(void) { 254 int i; 255 RUNTIME_CHECK(dst_initialized); 256 dst_initialized = false; 257 258 for (i = 0; i < DST_MAX_ALGS; i++) { 259 if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL) { 260 dst_t_func[i]->cleanup(); 261 } 262 } 263 dst__openssl_destroy(); 264#if USE_PKCS11 265 (void)dst__pkcs11_destroy(); 266#endif /* USE_PKCS11 */ 267} 268 269bool 270dst_algorithm_supported(unsigned int alg) { 271 REQUIRE(dst_initialized); 272 273 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) { 274 return (false); 275 } 276 return (true); 277} 278 279bool 280dst_ds_digest_supported(unsigned int digest_type) { 281 return (digest_type == DNS_DSDIGEST_SHA1 || 282 digest_type == DNS_DSDIGEST_SHA256 || 283 digest_type == DNS_DSDIGEST_SHA384); 284} 285 286isc_result_t 287dst_context_create(dst_key_t *key, isc_mem_t *mctx, isc_logcategory_t *category, 288 bool useforsigning, int maxbits, dst_context_t **dctxp) { 289 dst_context_t *dctx; 290 isc_result_t result; 291 292 REQUIRE(dst_initialized); 293 REQUIRE(VALID_KEY(key)); 294 REQUIRE(mctx != NULL); 295 REQUIRE(dctxp != NULL && *dctxp == NULL); 296 297 if (key->func->createctx == NULL && key->func->createctx2 == NULL) { 298 return (DST_R_UNSUPPORTEDALG); 299 } 300 if (key->keydata.generic == NULL) { 301 return (DST_R_NULLKEY); 302 } 303 304 dctx = isc_mem_get(mctx, sizeof(dst_context_t)); 305 memset(dctx, 0, sizeof(*dctx)); 306 dst_key_attach(key, &dctx->key); 307 isc_mem_attach(mctx, &dctx->mctx); 308 dctx->category = category; 309 if (useforsigning) { 310 dctx->use = DO_SIGN; 311 } else { 312 dctx->use = DO_VERIFY; 313 } 314 if (key->func->createctx2 != NULL) { 315 result = key->func->createctx2(key, maxbits, dctx); 316 } else { 317 result = key->func->createctx(key, dctx); 318 } 319 if (result != ISC_R_SUCCESS) { 320 if (dctx->key != NULL) { 321 dst_key_free(&dctx->key); 322 } 323 isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t)); 324 return (result); 325 } 326 dctx->magic = CTX_MAGIC; 327 *dctxp = dctx; 328 return (ISC_R_SUCCESS); 329} 330 331void 332dst_context_destroy(dst_context_t **dctxp) { 333 dst_context_t *dctx; 334 335 REQUIRE(dctxp != NULL && VALID_CTX(*dctxp)); 336 337 dctx = *dctxp; 338 *dctxp = NULL; 339 INSIST(dctx->key->func->destroyctx != NULL); 340 dctx->key->func->destroyctx(dctx); 341 if (dctx->key != NULL) { 342 dst_key_free(&dctx->key); 343 } 344 dctx->magic = 0; 345 isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(dst_context_t)); 346} 347 348isc_result_t 349dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) { 350 REQUIRE(VALID_CTX(dctx)); 351 REQUIRE(data != NULL); 352 INSIST(dctx->key->func->adddata != NULL); 353 354 return (dctx->key->func->adddata(dctx, data)); 355} 356 357isc_result_t 358dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) { 359 dst_key_t *key; 360 361 REQUIRE(VALID_CTX(dctx)); 362 REQUIRE(sig != NULL); 363 364 key = dctx->key; 365 CHECKALG(key->key_alg); 366 if (key->keydata.generic == NULL) { 367 return (DST_R_NULLKEY); 368 } 369 370 if (key->func->sign == NULL) { 371 return (DST_R_NOTPRIVATEKEY); 372 } 373 if (key->func->isprivate == NULL || !key->func->isprivate(key)) { 374 return (DST_R_NOTPRIVATEKEY); 375 } 376 377 return (key->func->sign(dctx, sig)); 378} 379 380isc_result_t 381dst_context_verify(dst_context_t *dctx, isc_region_t *sig) { 382 REQUIRE(VALID_CTX(dctx)); 383 REQUIRE(sig != NULL); 384 385 CHECKALG(dctx->key->key_alg); 386 if (dctx->key->keydata.generic == NULL) { 387 return (DST_R_NULLKEY); 388 } 389 if (dctx->key->func->verify == NULL) { 390 return (DST_R_NOTPUBLICKEY); 391 } 392 393 return (dctx->key->func->verify(dctx, sig)); 394} 395 396isc_result_t 397dst_context_verify2(dst_context_t *dctx, unsigned int maxbits, 398 isc_region_t *sig) { 399 REQUIRE(VALID_CTX(dctx)); 400 REQUIRE(sig != NULL); 401 402 CHECKALG(dctx->key->key_alg); 403 if (dctx->key->keydata.generic == NULL) { 404 return (DST_R_NULLKEY); 405 } 406 if (dctx->key->func->verify == NULL && dctx->key->func->verify2 == NULL) 407 { 408 return (DST_R_NOTPUBLICKEY); 409 } 410 411 return (dctx->key->func->verify2 != NULL 412 ? dctx->key->func->verify2(dctx, maxbits, sig) 413 : dctx->key->func->verify(dctx, sig)); 414} 415 416isc_result_t 417dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv, 418 isc_buffer_t *secret) { 419 REQUIRE(dst_initialized); 420 REQUIRE(VALID_KEY(pub) && VALID_KEY(priv)); 421 REQUIRE(secret != NULL); 422 423 CHECKALG(pub->key_alg); 424 CHECKALG(priv->key_alg); 425 426 if (pub->keydata.generic == NULL || priv->keydata.generic == NULL) { 427 return (DST_R_NULLKEY); 428 } 429 430 if (pub->key_alg != priv->key_alg || pub->func->computesecret == NULL || 431 priv->func->computesecret == NULL) 432 { 433 return (DST_R_KEYCANNOTCOMPUTESECRET); 434 } 435 436 if (!dst_key_isprivate(priv)) { 437 return (DST_R_NOTPRIVATEKEY); 438 } 439 440 return (pub->func->computesecret(pub, priv, secret)); 441} 442 443isc_result_t 444dst_key_tofile(const dst_key_t *key, int type, const char *directory) { 445 isc_result_t ret = ISC_R_SUCCESS; 446 447 REQUIRE(dst_initialized); 448 REQUIRE(VALID_KEY(key)); 449 REQUIRE((type & 450 (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0); 451 452 CHECKALG(key->key_alg); 453 454 if (key->func->tofile == NULL) { 455 return (DST_R_UNSUPPORTEDALG); 456 } 457 458 if ((type & DST_TYPE_PUBLIC) != 0) { 459 ret = write_public_key(key, type, directory); 460 if (ret != ISC_R_SUCCESS) { 461 return (ret); 462 } 463 } 464 465 if ((type & DST_TYPE_STATE) != 0) { 466 ret = write_key_state(key, type, directory); 467 if (ret != ISC_R_SUCCESS) { 468 return (ret); 469 } 470 } 471 472 if (((type & DST_TYPE_PRIVATE) != 0) && 473 (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY) 474 { 475 return (key->func->tofile(key, directory)); 476 } 477 return (ISC_R_SUCCESS); 478} 479 480void 481dst_key_setexternal(dst_key_t *key, bool value) { 482 key->external = value; 483} 484 485bool 486dst_key_isexternal(dst_key_t *key) { 487 return (key->external); 488} 489 490isc_result_t 491dst_key_getfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg, 492 int type, const char *directory, isc_mem_t *mctx, 493 isc_buffer_t *buf) { 494 isc_result_t result; 495 496 REQUIRE(dst_initialized); 497 REQUIRE(dns_name_isabsolute(name)); 498 REQUIRE((type & 499 (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_STATE)) != 0); 500 REQUIRE(mctx != NULL); 501 REQUIRE(buf != NULL); 502 503 CHECKALG(alg); 504 505 result = buildfilename(name, id, alg, type, directory, buf); 506 if (result == ISC_R_SUCCESS) { 507 if (isc_buffer_availablelength(buf) > 0) { 508 isc_buffer_putuint8(buf, 0); 509 } else { 510 result = ISC_R_NOSPACE; 511 } 512 } 513 514 return (result); 515} 516 517isc_result_t 518dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type, 519 const char *directory, isc_mem_t *mctx, dst_key_t **keyp) { 520 isc_result_t result; 521 char filename[NAME_MAX]; 522 isc_buffer_t buf; 523 dst_key_t *key; 524 525 REQUIRE(dst_initialized); 526 REQUIRE(dns_name_isabsolute(name)); 527 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 528 REQUIRE(mctx != NULL); 529 REQUIRE(keyp != NULL && *keyp == NULL); 530 531 CHECKALG(alg); 532 533 key = NULL; 534 535 isc_buffer_init(&buf, filename, NAME_MAX); 536 result = dst_key_getfilename(name, id, alg, type, NULL, mctx, &buf); 537 if (result != ISC_R_SUCCESS) { 538 goto out; 539 } 540 541 result = dst_key_fromnamedfile(filename, directory, type, mctx, &key); 542 if (result != ISC_R_SUCCESS) { 543 goto out; 544 } 545 546 result = computeid(key); 547 if (result != ISC_R_SUCCESS) { 548 goto out; 549 } 550 551 if (!dns_name_equal(name, key->key_name) || id != key->key_id || 552 alg != key->key_alg) 553 { 554 result = DST_R_INVALIDPRIVATEKEY; 555 goto out; 556 } 557 558 *keyp = key; 559 result = ISC_R_SUCCESS; 560 561out: 562 if ((key != NULL) && (result != ISC_R_SUCCESS)) { 563 dst_key_free(&key); 564 } 565 566 return (result); 567} 568 569isc_result_t 570dst_key_fromnamedfile(const char *filename, const char *dirname, int type, 571 isc_mem_t *mctx, dst_key_t **keyp) { 572 isc_result_t result; 573 dst_key_t *pubkey = NULL, *key = NULL; 574 char *newfilename = NULL; 575 int newfilenamelen = 0; 576 isc_lex_t *lex = NULL; 577 578 REQUIRE(dst_initialized); 579 REQUIRE(filename != NULL); 580 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 581 REQUIRE(mctx != NULL); 582 REQUIRE(keyp != NULL && *keyp == NULL); 583 584 /* If an absolute path is specified, don't use the key directory */ 585#ifndef WIN32 586 if (filename[0] == '/') { 587 dirname = NULL; 588 } 589#else /* WIN32 */ 590 if (filename[0] == '/' || filename[0] == '\\') { 591 dirname = NULL; 592 } 593#endif /* ifndef WIN32 */ 594 595 newfilenamelen = strlen(filename) + 5; 596 if (dirname != NULL) { 597 newfilenamelen += strlen(dirname) + 1; 598 } 599 newfilename = isc_mem_get(mctx, newfilenamelen); 600 result = addsuffix(newfilename, newfilenamelen, dirname, filename, 601 ".key"); 602 INSIST(result == ISC_R_SUCCESS); 603 604 result = dst_key_read_public(newfilename, type, mctx, &pubkey); 605 isc_mem_put(mctx, newfilename, newfilenamelen); 606 newfilename = NULL; 607 RETERR(result); 608 609 if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC || 610 (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) 611 { 612 result = computeid(pubkey); 613 if (result != ISC_R_SUCCESS) { 614 dst_key_free(&pubkey); 615 return (result); 616 } 617 618 *keyp = pubkey; 619 return (ISC_R_SUCCESS); 620 } 621 622 result = algorithm_status(pubkey->key_alg); 623 if (result != ISC_R_SUCCESS) { 624 dst_key_free(&pubkey); 625 return (result); 626 } 627 628 key = get_key_struct(pubkey->key_name, pubkey->key_alg, 629 pubkey->key_flags, pubkey->key_proto, 630 pubkey->key_size, pubkey->key_class, 631 pubkey->key_ttl, mctx); 632 if (key == NULL) { 633 dst_key_free(&pubkey); 634 return (ISC_R_NOMEMORY); 635 } 636 637 if (key->func->parse == NULL) { 638 RETERR(DST_R_UNSUPPORTEDALG); 639 } 640 641 /* 642 * Read the state file, if requested by type. 643 */ 644 if ((type & DST_TYPE_STATE) != 0) { 645 newfilenamelen = strlen(filename) + 7; 646 if (dirname != NULL) { 647 newfilenamelen += strlen(dirname) + 1; 648 } 649 newfilename = isc_mem_get(mctx, newfilenamelen); 650 result = addsuffix(newfilename, newfilenamelen, dirname, 651 filename, ".state"); 652 INSIST(result == ISC_R_SUCCESS); 653 654 key->kasp = false; 655 result = dst_key_read_state(newfilename, mctx, &key); 656 if (result == ISC_R_SUCCESS) { 657 key->kasp = true; 658 } else if (result == ISC_R_FILENOTFOUND) { 659 /* Having no state is valid. */ 660 result = ISC_R_SUCCESS; 661 } 662 isc_mem_put(mctx, newfilename, newfilenamelen); 663 newfilename = NULL; 664 RETERR(result); 665 } 666 667 newfilenamelen = strlen(filename) + 9; 668 if (dirname != NULL) { 669 newfilenamelen += strlen(dirname) + 1; 670 } 671 newfilename = isc_mem_get(mctx, newfilenamelen); 672 result = addsuffix(newfilename, newfilenamelen, dirname, filename, 673 ".private"); 674 INSIST(result == ISC_R_SUCCESS); 675 676 RETERR(isc_lex_create(mctx, 1500, &lex)); 677 RETERR(isc_lex_openfile(lex, newfilename)); 678 isc_mem_put(mctx, newfilename, newfilenamelen); 679 680 RETERR(key->func->parse(key, lex, pubkey)); 681 isc_lex_destroy(&lex); 682 683 RETERR(computeid(key)); 684 685 if (pubkey->key_id != key->key_id) { 686 RETERR(DST_R_INVALIDPRIVATEKEY); 687 } 688 dst_key_free(&pubkey); 689 690 *keyp = key; 691 return (ISC_R_SUCCESS); 692 693out: 694 if (pubkey != NULL) { 695 dst_key_free(&pubkey); 696 } 697 if (newfilename != NULL) { 698 isc_mem_put(mctx, newfilename, newfilenamelen); 699 } 700 if (lex != NULL) { 701 isc_lex_destroy(&lex); 702 } 703 if (key != NULL) { 704 dst_key_free(&key); 705 } 706 return (result); 707} 708 709isc_result_t 710dst_key_todns(const dst_key_t *key, isc_buffer_t *target) { 711 REQUIRE(dst_initialized); 712 REQUIRE(VALID_KEY(key)); 713 REQUIRE(target != NULL); 714 715 CHECKALG(key->key_alg); 716 717 if (key->func->todns == NULL) { 718 return (DST_R_UNSUPPORTEDALG); 719 } 720 721 if (isc_buffer_availablelength(target) < 4) { 722 return (ISC_R_NOSPACE); 723 } 724 isc_buffer_putuint16(target, (uint16_t)(key->key_flags & 0xffff)); 725 isc_buffer_putuint8(target, (uint8_t)key->key_proto); 726 isc_buffer_putuint8(target, (uint8_t)key->key_alg); 727 728 if ((key->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 729 if (isc_buffer_availablelength(target) < 2) { 730 return (ISC_R_NOSPACE); 731 } 732 isc_buffer_putuint16( 733 target, (uint16_t)((key->key_flags >> 16) & 0xffff)); 734 } 735 736 if (key->keydata.generic == NULL) { /*%< NULL KEY */ 737 return (ISC_R_SUCCESS); 738 } 739 740 return (key->func->todns(key, target)); 741} 742 743isc_result_t 744dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, 745 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { 746 uint8_t alg, proto; 747 uint32_t flags, extflags; 748 dst_key_t *key = NULL; 749 dns_keytag_t id, rid; 750 isc_region_t r; 751 isc_result_t result; 752 753 REQUIRE(dst_initialized); 754 755 isc_buffer_remainingregion(source, &r); 756 757 if (isc_buffer_remaininglength(source) < 4) { 758 return (DST_R_INVALIDPUBLICKEY); 759 } 760 flags = isc_buffer_getuint16(source); 761 proto = isc_buffer_getuint8(source); 762 alg = isc_buffer_getuint8(source); 763 764 id = dst_region_computeid(&r); 765 rid = dst_region_computerid(&r); 766 767 if ((flags & DNS_KEYFLAG_EXTENDED) != 0) { 768 if (isc_buffer_remaininglength(source) < 2) { 769 return (DST_R_INVALIDPUBLICKEY); 770 } 771 extflags = isc_buffer_getuint16(source); 772 flags |= (extflags << 16); 773 } 774 775 result = frombuffer(name, alg, flags, proto, rdclass, source, mctx, 776 &key); 777 if (result != ISC_R_SUCCESS) { 778 return (result); 779 } 780 key->key_id = id; 781 key->key_rid = rid; 782 783 *keyp = key; 784 return (ISC_R_SUCCESS); 785} 786 787isc_result_t 788dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, 789 unsigned int protocol, dns_rdataclass_t rdclass, 790 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { 791 dst_key_t *key = NULL; 792 isc_result_t result; 793 794 REQUIRE(dst_initialized); 795 796 result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx, 797 &key); 798 if (result != ISC_R_SUCCESS) { 799 return (result); 800 } 801 802 result = computeid(key); 803 if (result != ISC_R_SUCCESS) { 804 dst_key_free(&key); 805 return (result); 806 } 807 808 *keyp = key; 809 return (ISC_R_SUCCESS); 810} 811 812isc_result_t 813dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) { 814 REQUIRE(dst_initialized); 815 REQUIRE(VALID_KEY(key)); 816 REQUIRE(target != NULL); 817 818 CHECKALG(key->key_alg); 819 820 if (key->func->todns == NULL) { 821 return (DST_R_UNSUPPORTEDALG); 822 } 823 824 return (key->func->todns(key, target)); 825} 826 827isc_result_t 828dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) { 829 isc_lex_t *lex = NULL; 830 isc_result_t result = ISC_R_SUCCESS; 831 832 REQUIRE(dst_initialized); 833 REQUIRE(VALID_KEY(key)); 834 REQUIRE(!dst_key_isprivate(key)); 835 REQUIRE(buffer != NULL); 836 837 if (key->func->parse == NULL) { 838 RETERR(DST_R_UNSUPPORTEDALG); 839 } 840 841 RETERR(isc_lex_create(key->mctx, 1500, &lex)); 842 RETERR(isc_lex_openbuffer(lex, buffer)); 843 RETERR(key->func->parse(key, lex, NULL)); 844out: 845 if (lex != NULL) { 846 isc_lex_destroy(&lex); 847 } 848 return (result); 849} 850 851gss_ctx_id_t 852dst_key_getgssctx(const dst_key_t *key) { 853 REQUIRE(key != NULL); 854 855 return (key->keydata.gssctx); 856} 857 858isc_result_t 859dst_key_fromgssapi(const dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, 860 dst_key_t **keyp, isc_region_t *intoken) { 861 dst_key_t *key; 862 isc_result_t result; 863 864 REQUIRE(gssctx != NULL); 865 REQUIRE(keyp != NULL && *keyp == NULL); 866 867 key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 0, 868 dns_rdataclass_in, 0, mctx); 869 if (key == NULL) { 870 return (ISC_R_NOMEMORY); 871 } 872 873 if (intoken != NULL) { 874 /* 875 * Keep the token for use by external ssu rules. They may need 876 * to examine the PAC in the kerberos ticket. 877 */ 878 isc_buffer_allocate(key->mctx, &key->key_tkeytoken, 879 intoken->length); 880 RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken)); 881 } 882 883 key->keydata.gssctx = gssctx; 884 *keyp = key; 885 result = ISC_R_SUCCESS; 886out: 887 if (result != ISC_R_SUCCESS) { 888 dst_key_free(&key); 889 } 890 return (result); 891} 892 893isc_result_t 894dst_key_buildinternal(const dns_name_t *name, unsigned int alg, 895 unsigned int bits, unsigned int flags, 896 unsigned int protocol, dns_rdataclass_t rdclass, 897 void *data, isc_mem_t *mctx, dst_key_t **keyp) { 898 dst_key_t *key; 899 isc_result_t result; 900 901 REQUIRE(dst_initialized); 902 REQUIRE(dns_name_isabsolute(name)); 903 REQUIRE(mctx != NULL); 904 REQUIRE(keyp != NULL && *keyp == NULL); 905 REQUIRE(data != NULL); 906 907 CHECKALG(alg); 908 909 key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0, 910 mctx); 911 if (key == NULL) { 912 return (ISC_R_NOMEMORY); 913 } 914 915 key->keydata.generic = data; 916 917 result = computeid(key); 918 if (result != ISC_R_SUCCESS) { 919 dst_key_free(&key); 920 return (result); 921 } 922 923 *keyp = key; 924 return (ISC_R_SUCCESS); 925} 926 927isc_result_t 928dst_key_fromlabel(const dns_name_t *name, int alg, unsigned int flags, 929 unsigned int protocol, dns_rdataclass_t rdclass, 930 const char *engine, const char *label, const char *pin, 931 isc_mem_t *mctx, dst_key_t **keyp) { 932 dst_key_t *key; 933 isc_result_t result; 934 935 REQUIRE(dst_initialized); 936 REQUIRE(dns_name_isabsolute(name)); 937 REQUIRE(mctx != NULL); 938 REQUIRE(keyp != NULL && *keyp == NULL); 939 REQUIRE(label != NULL); 940 941 CHECKALG(alg); 942 943 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 944 if (key == NULL) { 945 return (ISC_R_NOMEMORY); 946 } 947 948 if (key->func->fromlabel == NULL) { 949 dst_key_free(&key); 950 return (DST_R_UNSUPPORTEDALG); 951 } 952 953 result = key->func->fromlabel(key, engine, label, pin); 954 if (result != ISC_R_SUCCESS) { 955 dst_key_free(&key); 956 return (result); 957 } 958 959 result = computeid(key); 960 if (result != ISC_R_SUCCESS) { 961 dst_key_free(&key); 962 return (result); 963 } 964 965 *keyp = key; 966 return (ISC_R_SUCCESS); 967} 968 969isc_result_t 970dst_key_generate(const dns_name_t *name, unsigned int alg, unsigned int bits, 971 unsigned int param, unsigned int flags, unsigned int protocol, 972 dns_rdataclass_t rdclass, isc_mem_t *mctx, dst_key_t **keyp, 973 void (*callback)(int)) { 974 dst_key_t *key; 975 isc_result_t ret; 976 977 REQUIRE(dst_initialized); 978 REQUIRE(dns_name_isabsolute(name)); 979 REQUIRE(mctx != NULL); 980 REQUIRE(keyp != NULL && *keyp == NULL); 981 982 CHECKALG(alg); 983 984 key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 0, 985 mctx); 986 if (key == NULL) { 987 return (ISC_R_NOMEMORY); 988 } 989 990 if (bits == 0) { /*%< NULL KEY */ 991 key->key_flags |= DNS_KEYTYPE_NOKEY; 992 *keyp = key; 993 return (ISC_R_SUCCESS); 994 } 995 996 if (key->func->generate == NULL) { 997 dst_key_free(&key); 998 return (DST_R_UNSUPPORTEDALG); 999 } 1000 1001 ret = key->func->generate(key, param, callback); 1002 if (ret != ISC_R_SUCCESS) { 1003 dst_key_free(&key); 1004 return (ret); 1005 } 1006 1007 ret = computeid(key); 1008 if (ret != ISC_R_SUCCESS) { 1009 dst_key_free(&key); 1010 return (ret); 1011 } 1012 1013 *keyp = key; 1014 return (ISC_R_SUCCESS); 1015} 1016 1017isc_result_t 1018dst_key_getbool(const dst_key_t *key, int type, bool *valuep) { 1019 REQUIRE(VALID_KEY(key)); 1020 REQUIRE(valuep != NULL); 1021 REQUIRE(type <= DST_MAX_BOOLEAN); 1022 if (!key->boolset[type]) { 1023 return (ISC_R_NOTFOUND); 1024 } 1025 *valuep = key->bools[type]; 1026 return (ISC_R_SUCCESS); 1027} 1028 1029void 1030dst_key_setbool(dst_key_t *key, int type, bool value) { 1031 REQUIRE(VALID_KEY(key)); 1032 REQUIRE(type <= DST_MAX_BOOLEAN); 1033 key->bools[type] = value; 1034 key->boolset[type] = true; 1035} 1036 1037void 1038dst_key_unsetbool(dst_key_t *key, int type) { 1039 REQUIRE(VALID_KEY(key)); 1040 REQUIRE(type <= DST_MAX_BOOLEAN); 1041 key->boolset[type] = false; 1042} 1043 1044isc_result_t 1045dst_key_getnum(const dst_key_t *key, int type, uint32_t *valuep) { 1046 REQUIRE(VALID_KEY(key)); 1047 REQUIRE(valuep != NULL); 1048 REQUIRE(type <= DST_MAX_NUMERIC); 1049 if (!key->numset[type]) { 1050 return (ISC_R_NOTFOUND); 1051 } 1052 *valuep = key->nums[type]; 1053 return (ISC_R_SUCCESS); 1054} 1055 1056void 1057dst_key_setnum(dst_key_t *key, int type, uint32_t value) { 1058 REQUIRE(VALID_KEY(key)); 1059 REQUIRE(type <= DST_MAX_NUMERIC); 1060 key->nums[type] = value; 1061 key->numset[type] = true; 1062} 1063 1064void 1065dst_key_unsetnum(dst_key_t *key, int type) { 1066 REQUIRE(VALID_KEY(key)); 1067 REQUIRE(type <= DST_MAX_NUMERIC); 1068 key->numset[type] = false; 1069} 1070 1071isc_result_t 1072dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) { 1073 REQUIRE(VALID_KEY(key)); 1074 REQUIRE(timep != NULL); 1075 REQUIRE(type <= DST_MAX_TIMES); 1076 if (!key->timeset[type]) { 1077 return (ISC_R_NOTFOUND); 1078 } 1079 *timep = key->times[type]; 1080 return (ISC_R_SUCCESS); 1081} 1082 1083void 1084dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) { 1085 REQUIRE(VALID_KEY(key)); 1086 REQUIRE(type <= DST_MAX_TIMES); 1087 key->times[type] = when; 1088 key->timeset[type] = true; 1089} 1090 1091void 1092dst_key_unsettime(dst_key_t *key, int type) { 1093 REQUIRE(VALID_KEY(key)); 1094 REQUIRE(type <= DST_MAX_TIMES); 1095 key->timeset[type] = false; 1096} 1097 1098isc_result_t 1099dst_key_getstate(const dst_key_t *key, int type, dst_key_state_t *statep) { 1100 REQUIRE(VALID_KEY(key)); 1101 REQUIRE(statep != NULL); 1102 REQUIRE(type <= DST_MAX_KEYSTATES); 1103 if (!key->keystateset[type]) { 1104 return (ISC_R_NOTFOUND); 1105 } 1106 *statep = key->keystates[type]; 1107 return (ISC_R_SUCCESS); 1108} 1109 1110void 1111dst_key_setstate(dst_key_t *key, int type, dst_key_state_t state) { 1112 REQUIRE(VALID_KEY(key)); 1113 REQUIRE(type <= DST_MAX_KEYSTATES); 1114 key->keystates[type] = state; 1115 key->keystateset[type] = true; 1116} 1117 1118void 1119dst_key_unsetstate(dst_key_t *key, int type) { 1120 REQUIRE(VALID_KEY(key)); 1121 REQUIRE(type <= DST_MAX_KEYSTATES); 1122 key->keystateset[type] = false; 1123} 1124 1125isc_result_t 1126dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) { 1127 REQUIRE(VALID_KEY(key)); 1128 REQUIRE(majorp != NULL); 1129 REQUIRE(minorp != NULL); 1130 *majorp = key->fmt_major; 1131 *minorp = key->fmt_minor; 1132 return (ISC_R_SUCCESS); 1133} 1134 1135void 1136dst_key_setprivateformat(dst_key_t *key, int major, int minor) { 1137 REQUIRE(VALID_KEY(key)); 1138 key->fmt_major = major; 1139 key->fmt_minor = minor; 1140} 1141 1142static bool 1143comparekeys(const dst_key_t *key1, const dst_key_t *key2, 1144 bool match_revoked_key, 1145 bool (*compare)(const dst_key_t *key1, const dst_key_t *key2)) { 1146 REQUIRE(dst_initialized); 1147 REQUIRE(VALID_KEY(key1)); 1148 REQUIRE(VALID_KEY(key2)); 1149 1150 if (key1 == key2) { 1151 return (true); 1152 } 1153 1154 if (key1->key_alg != key2->key_alg) { 1155 return (false); 1156 } 1157 1158 if (key1->key_id != key2->key_id) { 1159 if (!match_revoked_key) { 1160 return (false); 1161 } 1162 if ((key1->key_flags & DNS_KEYFLAG_REVOKE) == 1163 (key2->key_flags & DNS_KEYFLAG_REVOKE)) 1164 { 1165 return (false); 1166 } 1167 if (key1->key_id != key2->key_rid && 1168 key1->key_rid != key2->key_id) { 1169 return (false); 1170 } 1171 } 1172 1173 if (compare != NULL) { 1174 return (compare(key1, key2)); 1175 } else { 1176 return (false); 1177 } 1178} 1179 1180/* 1181 * Compares only the public portion of two keys, by converting them 1182 * both to wire format and comparing the results. 1183 */ 1184static bool 1185pub_compare(const dst_key_t *key1, const dst_key_t *key2) { 1186 isc_result_t result; 1187 unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE]; 1188 isc_buffer_t b1, b2; 1189 isc_region_t r1, r2; 1190 1191 isc_buffer_init(&b1, buf1, sizeof(buf1)); 1192 result = dst_key_todns(key1, &b1); 1193 if (result != ISC_R_SUCCESS) { 1194 return (false); 1195 } 1196 /* Zero out flags. */ 1197 buf1[0] = buf1[1] = 0; 1198 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1199 isc_buffer_subtract(&b1, 2); 1200 } 1201 1202 isc_buffer_init(&b2, buf2, sizeof(buf2)); 1203 result = dst_key_todns(key2, &b2); 1204 if (result != ISC_R_SUCCESS) { 1205 return (false); 1206 } 1207 /* Zero out flags. */ 1208 buf2[0] = buf2[1] = 0; 1209 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1210 isc_buffer_subtract(&b2, 2); 1211 } 1212 1213 isc_buffer_usedregion(&b1, &r1); 1214 /* Remove extended flags. */ 1215 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1216 memmove(&buf1[4], &buf1[6], r1.length - 6); 1217 r1.length -= 2; 1218 } 1219 1220 isc_buffer_usedregion(&b2, &r2); 1221 /* Remove extended flags. */ 1222 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1223 memmove(&buf2[4], &buf2[6], r2.length - 6); 1224 r2.length -= 2; 1225 } 1226 return (isc_region_compare(&r1, &r2) == 0); 1227} 1228 1229bool 1230dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) { 1231 return (comparekeys(key1, key2, false, key1->func->compare)); 1232} 1233 1234bool 1235dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2, 1236 bool match_revoked_key) { 1237 return (comparekeys(key1, key2, match_revoked_key, pub_compare)); 1238} 1239 1240bool 1241dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { 1242 REQUIRE(dst_initialized); 1243 REQUIRE(VALID_KEY(key1)); 1244 REQUIRE(VALID_KEY(key2)); 1245 1246 if (key1 == key2) { 1247 return (true); 1248 } 1249 if (key1->key_alg == key2->key_alg && 1250 key1->func->paramcompare != NULL && 1251 key1->func->paramcompare(key1, key2)) 1252 { 1253 return (true); 1254 } else { 1255 return (false); 1256 } 1257} 1258 1259void 1260dst_key_attach(dst_key_t *source, dst_key_t **target) { 1261 REQUIRE(dst_initialized); 1262 REQUIRE(target != NULL && *target == NULL); 1263 REQUIRE(VALID_KEY(source)); 1264 1265 isc_refcount_increment(&source->refs); 1266 *target = source; 1267} 1268 1269void 1270dst_key_free(dst_key_t **keyp) { 1271 REQUIRE(dst_initialized); 1272 REQUIRE(keyp != NULL && VALID_KEY(*keyp)); 1273 dst_key_t *key = *keyp; 1274 *keyp = NULL; 1275 1276 if (isc_refcount_decrement(&key->refs) == 1) { 1277 isc_refcount_destroy(&key->refs); 1278 isc_mem_t *mctx = key->mctx; 1279 if (key->keydata.generic != NULL) { 1280 INSIST(key->func->destroy != NULL); 1281 key->func->destroy(key); 1282 } 1283 if (key->engine != NULL) { 1284 isc_mem_free(mctx, key->engine); 1285 } 1286 if (key->label != NULL) { 1287 isc_mem_free(mctx, key->label); 1288 } 1289 dns_name_free(key->key_name, mctx); 1290 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); 1291 if (key->key_tkeytoken) { 1292 isc_buffer_free(&key->key_tkeytoken); 1293 } 1294 isc_safe_memwipe(key, sizeof(*key)); 1295 isc_mem_putanddetach(&mctx, key, sizeof(*key)); 1296 } 1297} 1298 1299bool 1300dst_key_isprivate(const dst_key_t *key) { 1301 REQUIRE(VALID_KEY(key)); 1302 INSIST(key->func->isprivate != NULL); 1303 return (key->func->isprivate(key)); 1304} 1305 1306isc_result_t 1307dst_key_buildfilename(const dst_key_t *key, int type, const char *directory, 1308 isc_buffer_t *out) { 1309 REQUIRE(VALID_KEY(key)); 1310 REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC || 1311 type == DST_TYPE_STATE || type == 0); 1312 1313 return (buildfilename(key->key_name, key->key_id, key->key_alg, type, 1314 directory, out)); 1315} 1316 1317isc_result_t 1318dst_key_sigsize(const dst_key_t *key, unsigned int *n) { 1319 REQUIRE(dst_initialized); 1320 REQUIRE(VALID_KEY(key)); 1321 REQUIRE(n != NULL); 1322 1323 /* XXXVIX this switch statement is too sparse to gen a jump table. */ 1324 switch (key->key_alg) { 1325 case DST_ALG_RSASHA1: 1326 case DST_ALG_NSEC3RSASHA1: 1327 case DST_ALG_RSASHA256: 1328 case DST_ALG_RSASHA512: 1329 *n = (key->key_size + 7) / 8; 1330 break; 1331 case DST_ALG_ECDSA256: 1332 *n = DNS_SIG_ECDSA256SIZE; 1333 break; 1334 case DST_ALG_ECDSA384: 1335 *n = DNS_SIG_ECDSA384SIZE; 1336 break; 1337 case DST_ALG_ED25519: 1338 *n = DNS_SIG_ED25519SIZE; 1339 break; 1340 case DST_ALG_ED448: 1341 *n = DNS_SIG_ED448SIZE; 1342 break; 1343 case DST_ALG_HMACMD5: 1344 *n = isc_md_type_get_size(ISC_MD_MD5); 1345 break; 1346 case DST_ALG_HMACSHA1: 1347 *n = isc_md_type_get_size(ISC_MD_SHA1); 1348 break; 1349 case DST_ALG_HMACSHA224: 1350 *n = isc_md_type_get_size(ISC_MD_SHA224); 1351 break; 1352 case DST_ALG_HMACSHA256: 1353 *n = isc_md_type_get_size(ISC_MD_SHA256); 1354 break; 1355 case DST_ALG_HMACSHA384: 1356 *n = isc_md_type_get_size(ISC_MD_SHA384); 1357 break; 1358 case DST_ALG_HMACSHA512: 1359 *n = isc_md_type_get_size(ISC_MD_SHA512); 1360 break; 1361 case DST_ALG_GSSAPI: 1362 *n = 128; /*%< XXX */ 1363 break; 1364 case DST_ALG_DH: 1365 default: 1366 return (DST_R_UNSUPPORTEDALG); 1367 } 1368 return (ISC_R_SUCCESS); 1369} 1370 1371isc_result_t 1372dst_key_secretsize(const dst_key_t *key, unsigned int *n) { 1373 REQUIRE(dst_initialized); 1374 REQUIRE(VALID_KEY(key)); 1375 REQUIRE(n != NULL); 1376 1377 if (key->key_alg == DST_ALG_DH) { 1378 *n = (key->key_size + 7) / 8; 1379 return (ISC_R_SUCCESS); 1380 } 1381 return (DST_R_UNSUPPORTEDALG); 1382} 1383 1384/*% 1385 * Set the flags on a key, then recompute the key ID 1386 */ 1387isc_result_t 1388dst_key_setflags(dst_key_t *key, uint32_t flags) { 1389 REQUIRE(VALID_KEY(key)); 1390 key->key_flags = flags; 1391 return (computeid(key)); 1392} 1393 1394void 1395dst_key_format(const dst_key_t *key, char *cp, unsigned int size) { 1396 char namestr[DNS_NAME_FORMATSIZE]; 1397 char algstr[DNS_NAME_FORMATSIZE]; 1398 1399 dns_name_format(dst_key_name(key), namestr, sizeof(namestr)); 1400 dns_secalg_format((dns_secalg_t)dst_key_alg(key), algstr, 1401 sizeof(algstr)); 1402 snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key)); 1403} 1404 1405isc_result_t 1406dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) { 1407 REQUIRE(buffer != NULL && *buffer == NULL); 1408 REQUIRE(length != NULL && *length == 0); 1409 REQUIRE(VALID_KEY(key)); 1410 1411 if (key->func->dump == NULL) { 1412 return (ISC_R_NOTIMPLEMENTED); 1413 } 1414 return (key->func->dump(key, mctx, buffer, length)); 1415} 1416 1417isc_result_t 1418dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags, 1419 unsigned int protocol, dns_rdataclass_t rdclass, 1420 isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) { 1421 isc_result_t result; 1422 dst_key_t *key; 1423 1424 REQUIRE(dst_initialized); 1425 REQUIRE(keyp != NULL && *keyp == NULL); 1426 1427 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) { 1428 return (DST_R_UNSUPPORTEDALG); 1429 } 1430 1431 if (dst_t_func[alg]->restore == NULL) { 1432 return (ISC_R_NOTIMPLEMENTED); 1433 } 1434 1435 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 1436 if (key == NULL) { 1437 return (ISC_R_NOMEMORY); 1438 } 1439 1440 result = (dst_t_func[alg]->restore)(key, keystr); 1441 if (result == ISC_R_SUCCESS) { 1442 *keyp = key; 1443 } else { 1444 dst_key_free(&key); 1445 } 1446 1447 return (result); 1448} 1449 1450/*** 1451 *** Static methods 1452 ***/ 1453 1454/*% 1455 * Allocates a key structure and fills in some of the fields. 1456 */ 1457static dst_key_t * 1458get_key_struct(const dns_name_t *name, unsigned int alg, unsigned int flags, 1459 unsigned int protocol, unsigned int bits, 1460 dns_rdataclass_t rdclass, dns_ttl_t ttl, isc_mem_t *mctx) { 1461 dst_key_t *key; 1462 int i; 1463 1464 key = isc_mem_get(mctx, sizeof(dst_key_t)); 1465 1466 memset(key, 0, sizeof(dst_key_t)); 1467 1468 key->key_name = isc_mem_get(mctx, sizeof(dns_name_t)); 1469 1470 dns_name_init(key->key_name, NULL); 1471 dns_name_dup(name, mctx, key->key_name); 1472 1473 isc_refcount_init(&key->refs, 1); 1474 isc_mem_attach(mctx, &key->mctx); 1475 key->key_alg = alg; 1476 key->key_flags = flags; 1477 key->key_proto = protocol; 1478 key->keydata.generic = NULL; 1479 key->key_size = bits; 1480 key->key_class = rdclass; 1481 key->key_ttl = ttl; 1482 key->func = dst_t_func[alg]; 1483 key->fmt_major = 0; 1484 key->fmt_minor = 0; 1485 for (i = 0; i < (DST_MAX_TIMES + 1); i++) { 1486 key->times[i] = 0; 1487 key->timeset[i] = false; 1488 } 1489 key->inactive = false; 1490 key->magic = KEY_MAGIC; 1491 return (key); 1492} 1493 1494bool 1495dst_key_inactive(const dst_key_t *key) { 1496 REQUIRE(VALID_KEY(key)); 1497 1498 return (key->inactive); 1499} 1500 1501void 1502dst_key_setinactive(dst_key_t *key, bool inactive) { 1503 REQUIRE(VALID_KEY(key)); 1504 1505 key->inactive = inactive; 1506} 1507 1508/*% 1509 * Reads a public key from disk. 1510 */ 1511isc_result_t 1512dst_key_read_public(const char *filename, int type, isc_mem_t *mctx, 1513 dst_key_t **keyp) { 1514 u_char rdatabuf[DST_KEY_MAXSIZE]; 1515 isc_buffer_t b; 1516 dns_fixedname_t name; 1517 isc_lex_t *lex = NULL; 1518 isc_token_t token; 1519 isc_result_t ret; 1520 dns_rdata_t rdata = DNS_RDATA_INIT; 1521 unsigned int opt = ISC_LEXOPT_DNSMULTILINE; 1522 dns_rdataclass_t rdclass = dns_rdataclass_in; 1523 isc_lexspecials_t specials; 1524 uint32_t ttl = 0; 1525 isc_result_t result; 1526 dns_rdatatype_t keytype; 1527 1528 /* 1529 * Open the file and read its formatted contents 1530 * File format: 1531 * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> 1532 * <algorithm> <key> 1533 */ 1534 1535 /* 1500 should be large enough for any key */ 1536 ret = isc_lex_create(mctx, 1500, &lex); 1537 if (ret != ISC_R_SUCCESS) { 1538 goto cleanup; 1539 } 1540 1541 memset(specials, 0, sizeof(specials)); 1542 specials['('] = 1; 1543 specials[')'] = 1; 1544 specials['"'] = 1; 1545 isc_lex_setspecials(lex, specials); 1546 isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); 1547 1548 ret = isc_lex_openfile(lex, filename); 1549 if (ret != ISC_R_SUCCESS) { 1550 goto cleanup; 1551 } 1552 1553 /* Read the domain name */ 1554 NEXTTOKEN(lex, opt, &token); 1555 if (token.type != isc_tokentype_string) { 1556 BADTOKEN(); 1557 } 1558 1559 /* 1560 * We don't support "@" in .key files. 1561 */ 1562 if (!strcmp(DST_AS_STR(token), "@")) { 1563 BADTOKEN(); 1564 } 1565 1566 dns_fixedname_init(&name); 1567 isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token))); 1568 isc_buffer_add(&b, strlen(DST_AS_STR(token))); 1569 ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, 0, 1570 NULL); 1571 if (ret != ISC_R_SUCCESS) { 1572 goto cleanup; 1573 } 1574 1575 /* Read the next word: either TTL, class, or 'KEY' */ 1576 NEXTTOKEN(lex, opt, &token); 1577 1578 if (token.type != isc_tokentype_string) { 1579 BADTOKEN(); 1580 } 1581 1582 /* If it's a TTL, read the next one */ 1583 result = dns_ttl_fromtext(&token.value.as_textregion, &ttl); 1584 if (result == ISC_R_SUCCESS) { 1585 NEXTTOKEN(lex, opt, &token); 1586 } 1587 1588 if (token.type != isc_tokentype_string) { 1589 BADTOKEN(); 1590 } 1591 1592 ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion); 1593 if (ret == ISC_R_SUCCESS) { 1594 NEXTTOKEN(lex, opt, &token); 1595 } 1596 1597 if (token.type != isc_tokentype_string) { 1598 BADTOKEN(); 1599 } 1600 1601 if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0) { 1602 keytype = dns_rdatatype_dnskey; 1603 } else if (strcasecmp(DST_AS_STR(token), "KEY") == 0) { 1604 keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */ 1605 } else { 1606 BADTOKEN(); 1607 } 1608 1609 if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) || 1610 ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) 1611 { 1612 ret = DST_R_BADKEYTYPE; 1613 goto cleanup; 1614 } 1615 1616 isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf)); 1617 ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL, false, 1618 mctx, &b, NULL); 1619 if (ret != ISC_R_SUCCESS) { 1620 goto cleanup; 1621 } 1622 1623 ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx, 1624 keyp); 1625 if (ret != ISC_R_SUCCESS) { 1626 goto cleanup; 1627 } 1628 1629 dst_key_setttl(*keyp, ttl); 1630 1631cleanup: 1632 if (lex != NULL) { 1633 isc_lex_destroy(&lex); 1634 } 1635 return (ret); 1636} 1637 1638static int 1639find_metadata(const char *s, const char *tags[], int ntags) { 1640 for (int i = 0; i < ntags; i++) { 1641 if (tags[i] != NULL && strcasecmp(s, tags[i]) == 0) { 1642 return (i); 1643 } 1644 } 1645 return (-1); 1646} 1647 1648static int 1649find_numericdata(const char *s) { 1650 return (find_metadata(s, numerictags, NUMERIC_NTAGS)); 1651} 1652 1653static int 1654find_booleandata(const char *s) { 1655 return (find_metadata(s, booleantags, BOOLEAN_NTAGS)); 1656} 1657 1658static int 1659find_timingdata(const char *s) { 1660 return (find_metadata(s, timingtags, TIMING_NTAGS)); 1661} 1662 1663static int 1664find_keystatedata(const char *s) { 1665 return (find_metadata(s, keystatestags, KEYSTATES_NTAGS)); 1666} 1667 1668static isc_result_t 1669keystate_fromtext(const char *s, dst_key_state_t *state) { 1670 for (int i = 0; i < KEYSTATES_NVALUES; i++) { 1671 if (keystates[i] != NULL && strcasecmp(s, keystates[i]) == 0) { 1672 *state = (dst_key_state_t)i; 1673 return (ISC_R_SUCCESS); 1674 } 1675 } 1676 return (ISC_R_NOTFOUND); 1677} 1678 1679/*% 1680 * Reads a key state from disk. 1681 */ 1682isc_result_t 1683dst_key_read_state(const char *filename, isc_mem_t *mctx, dst_key_t **keyp) { 1684 isc_lex_t *lex = NULL; 1685 isc_token_t token; 1686 isc_result_t ret; 1687 unsigned int opt = ISC_LEXOPT_EOL; 1688 1689 ret = isc_lex_create(mctx, 1500, &lex); 1690 if (ret != ISC_R_SUCCESS) { 1691 goto cleanup; 1692 } 1693 isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); 1694 1695 ret = isc_lex_openfile(lex, filename); 1696 if (ret != ISC_R_SUCCESS) { 1697 goto cleanup; 1698 } 1699 1700 /* 1701 * Read the comment line. 1702 */ 1703 READLINE(lex, opt, &token); 1704 1705 /* 1706 * Read the algorithm line. 1707 */ 1708 NEXTTOKEN(lex, opt, &token); 1709 if (token.type != isc_tokentype_string || 1710 strcmp(DST_AS_STR(token), STATE_ALGORITHM_STR) != 0) 1711 { 1712 BADTOKEN(); 1713 } 1714 1715 NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); 1716 if (token.type != isc_tokentype_number || 1717 token.value.as_ulong != (unsigned long)dst_key_alg(*keyp)) 1718 { 1719 BADTOKEN(); 1720 } 1721 1722 READLINE(lex, opt, &token); 1723 1724 /* 1725 * Read the length line. 1726 */ 1727 NEXTTOKEN(lex, opt, &token); 1728 if (token.type != isc_tokentype_string || 1729 strcmp(DST_AS_STR(token), STATE_LENGTH_STR) != 0) 1730 { 1731 BADTOKEN(); 1732 } 1733 1734 NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); 1735 if (token.type != isc_tokentype_number || 1736 token.value.as_ulong != (unsigned long)dst_key_size(*keyp)) 1737 { 1738 BADTOKEN(); 1739 } 1740 1741 READLINE(lex, opt, &token); 1742 1743 /* 1744 * Read the metadata. 1745 */ 1746 for (int n = 0; n < MAX_NTAGS; n++) { 1747 int tag; 1748 1749 NEXTTOKEN_OR_EOF(lex, opt, &token); 1750 if (ret == ISC_R_EOF) { 1751 break; 1752 } 1753 if (token.type != isc_tokentype_string) { 1754 BADTOKEN(); 1755 } 1756 1757 /* Numeric metadata */ 1758 tag = find_numericdata(DST_AS_STR(token)); 1759 if (tag >= 0) { 1760 INSIST(tag < NUMERIC_NTAGS); 1761 1762 NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token); 1763 if (token.type != isc_tokentype_number) { 1764 BADTOKEN(); 1765 } 1766 1767 dst_key_setnum(*keyp, tag, token.value.as_ulong); 1768 goto next; 1769 } 1770 1771 /* Boolean metadata */ 1772 tag = find_booleandata(DST_AS_STR(token)); 1773 if (tag >= 0) { 1774 INSIST(tag < BOOLEAN_NTAGS); 1775 1776 NEXTTOKEN(lex, opt, &token); 1777 if (token.type != isc_tokentype_string) { 1778 BADTOKEN(); 1779 } 1780 1781 if (strcmp(DST_AS_STR(token), "yes") == 0) { 1782 dst_key_setbool(*keyp, tag, true); 1783 } else if (strcmp(DST_AS_STR(token), "no") == 0) { 1784 dst_key_setbool(*keyp, tag, false); 1785 } else { 1786 BADTOKEN(); 1787 } 1788 goto next; 1789 } 1790 1791 /* Timing metadata */ 1792 tag = find_timingdata(DST_AS_STR(token)); 1793 if (tag >= 0) { 1794 uint32_t when; 1795 1796 INSIST(tag < TIMING_NTAGS); 1797 1798 NEXTTOKEN(lex, opt, &token); 1799 if (token.type != isc_tokentype_string) { 1800 BADTOKEN(); 1801 } 1802 1803 ret = dns_time32_fromtext(DST_AS_STR(token), &when); 1804 if (ret != ISC_R_SUCCESS) { 1805 goto cleanup; 1806 } 1807 1808 dst_key_settime(*keyp, tag, when); 1809 goto next; 1810 } 1811 1812 /* Keystate metadata */ 1813 tag = find_keystatedata(DST_AS_STR(token)); 1814 if (tag >= 0) { 1815 dst_key_state_t state; 1816 1817 INSIST(tag < KEYSTATES_NTAGS); 1818 1819 NEXTTOKEN(lex, opt, &token); 1820 if (token.type != isc_tokentype_string) { 1821 BADTOKEN(); 1822 } 1823 1824 ret = keystate_fromtext(DST_AS_STR(token), &state); 1825 if (ret != ISC_R_SUCCESS) { 1826 goto cleanup; 1827 } 1828 1829 dst_key_setstate(*keyp, tag, state); 1830 goto next; 1831 } 1832 1833 next: 1834 READLINE(lex, opt, &token); 1835 } 1836 1837 /* Done, successfully parsed the whole file. */ 1838 ret = ISC_R_SUCCESS; 1839 1840cleanup: 1841 if (lex != NULL) { 1842 isc_lex_destroy(&lex); 1843 } 1844 return (ret); 1845} 1846 1847static bool 1848issymmetric(const dst_key_t *key) { 1849 REQUIRE(dst_initialized); 1850 REQUIRE(VALID_KEY(key)); 1851 1852 /* XXXVIX this switch statement is too sparse to gen a jump table. */ 1853 switch (key->key_alg) { 1854 case DST_ALG_RSASHA1: 1855 case DST_ALG_NSEC3RSASHA1: 1856 case DST_ALG_RSASHA256: 1857 case DST_ALG_RSASHA512: 1858 case DST_ALG_DH: 1859 case DST_ALG_ECDSA256: 1860 case DST_ALG_ECDSA384: 1861 case DST_ALG_ED25519: 1862 case DST_ALG_ED448: 1863 return (false); 1864 case DST_ALG_HMACMD5: 1865 case DST_ALG_HMACSHA1: 1866 case DST_ALG_HMACSHA224: 1867 case DST_ALG_HMACSHA256: 1868 case DST_ALG_HMACSHA384: 1869 case DST_ALG_HMACSHA512: 1870 case DST_ALG_GSSAPI: 1871 return (true); 1872 default: 1873 return (false); 1874 } 1875} 1876 1877/*% 1878 * Write key boolean metadata to a file pointer, preceded by 'tag' 1879 */ 1880static void 1881printbool(const dst_key_t *key, int type, const char *tag, FILE *stream) { 1882 isc_result_t result; 1883 bool value = 0; 1884 1885 result = dst_key_getbool(key, type, &value); 1886 if (result != ISC_R_SUCCESS) { 1887 return; 1888 } 1889 fprintf(stream, "%s: %s\n", tag, value ? "yes" : "no"); 1890} 1891 1892/*% 1893 * Write key numeric metadata to a file pointer, preceded by 'tag' 1894 */ 1895static void 1896printnum(const dst_key_t *key, int type, const char *tag, FILE *stream) { 1897 isc_result_t result; 1898 uint32_t value = 0; 1899 1900 result = dst_key_getnum(key, type, &value); 1901 if (result != ISC_R_SUCCESS) { 1902 return; 1903 } 1904 fprintf(stream, "%s: %u\n", tag, value); 1905} 1906 1907/*% 1908 * Write key timing metadata to a file pointer, preceded by 'tag' 1909 */ 1910static void 1911printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) { 1912 isc_result_t result; 1913 char output[26]; /* Minimum buffer as per ctime_r() specification. */ 1914 isc_stdtime_t when; 1915 char utc[sizeof("YYYYMMDDHHSSMM")]; 1916 isc_buffer_t b; 1917 isc_region_t r; 1918 1919 result = dst_key_gettime(key, type, &when); 1920 if (result == ISC_R_NOTFOUND) { 1921 return; 1922 } 1923 1924 isc_stdtime_tostring(when, output, sizeof(output)); 1925 isc_buffer_init(&b, utc, sizeof(utc)); 1926 result = dns_time32_totext(when, &b); 1927 if (result != ISC_R_SUCCESS) { 1928 goto error; 1929 } 1930 1931 isc_buffer_usedregion(&b, &r); 1932 fprintf(stream, "%s: %.*s (%s)\n", tag, (int)r.length, r.base, output); 1933 return; 1934 1935error: 1936 fprintf(stream, "%s: (set, unable to display)\n", tag); 1937} 1938 1939/*% 1940 * Write key state metadata to a file pointer, preceded by 'tag' 1941 */ 1942static void 1943printstate(const dst_key_t *key, int type, const char *tag, FILE *stream) { 1944 isc_result_t result; 1945 dst_key_state_t value = 0; 1946 1947 result = dst_key_getstate(key, type, &value); 1948 if (result != ISC_R_SUCCESS) { 1949 return; 1950 } 1951 fprintf(stream, "%s: %s\n", tag, keystates[value]); 1952} 1953 1954/*% 1955 * Writes a key state to disk. 1956 */ 1957static isc_result_t 1958write_key_state(const dst_key_t *key, int type, const char *directory) { 1959 FILE *fp; 1960 isc_buffer_t fileb; 1961 char filename[NAME_MAX]; 1962 isc_result_t ret; 1963 isc_fsaccess_t access; 1964 1965 REQUIRE(VALID_KEY(key)); 1966 1967 /* 1968 * Make the filename. 1969 */ 1970 isc_buffer_init(&fileb, filename, sizeof(filename)); 1971 ret = dst_key_buildfilename(key, DST_TYPE_STATE, directory, &fileb); 1972 if (ret != ISC_R_SUCCESS) { 1973 return (ret); 1974 } 1975 1976 /* 1977 * Create public key file. 1978 */ 1979 if ((fp = fopen(filename, "w")) == NULL) { 1980 return (DST_R_WRITEERROR); 1981 } 1982 1983 if (issymmetric(key)) { 1984 access = 0; 1985 isc_fsaccess_add(ISC_FSACCESS_OWNER, 1986 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, 1987 &access); 1988 (void)isc_fsaccess_set(filename, access); 1989 } 1990 1991 /* Write key state */ 1992 if ((type & DST_TYPE_KEY) == 0) { 1993 fprintf(fp, "; This is the state of key %d, for ", key->key_id); 1994 ret = dns_name_print(key->key_name, fp); 1995 if (ret != ISC_R_SUCCESS) { 1996 fclose(fp); 1997 return (ret); 1998 } 1999 fputc('\n', fp); 2000 2001 fprintf(fp, "Algorithm: %u\n", key->key_alg); 2002 fprintf(fp, "Length: %u\n", key->key_size); 2003 2004 printnum(key, DST_NUM_LIFETIME, "Lifetime", fp); 2005 printnum(key, DST_NUM_PREDECESSOR, "Predecessor", fp); 2006 printnum(key, DST_NUM_SUCCESSOR, "Successor", fp); 2007 2008 printbool(key, DST_BOOL_KSK, "KSK", fp); 2009 printbool(key, DST_BOOL_ZSK, "ZSK", fp); 2010 2011 printtime(key, DST_TIME_CREATED, "Generated", fp); 2012 printtime(key, DST_TIME_PUBLISH, "Published", fp); 2013 printtime(key, DST_TIME_ACTIVATE, "Active", fp); 2014 printtime(key, DST_TIME_INACTIVE, "Retired", fp); 2015 printtime(key, DST_TIME_REVOKE, "Revoked", fp); 2016 printtime(key, DST_TIME_DELETE, "Removed", fp); 2017 printtime(key, DST_TIME_DSPUBLISH, "DSPublish", fp); 2018 printtime(key, DST_TIME_DSDELETE, "DSRemoved", fp); 2019 printtime(key, DST_TIME_SYNCPUBLISH, "PublishCDS", fp); 2020 printtime(key, DST_TIME_SYNCDELETE, "DeleteCDS", fp); 2021 2022 printtime(key, DST_TIME_DNSKEY, "DNSKEYChange", fp); 2023 printtime(key, DST_TIME_ZRRSIG, "ZRRSIGChange", fp); 2024 printtime(key, DST_TIME_KRRSIG, "KRRSIGChange", fp); 2025 printtime(key, DST_TIME_DS, "DSChange", fp); 2026 2027 printstate(key, DST_KEY_DNSKEY, "DNSKEYState", fp); 2028 printstate(key, DST_KEY_ZRRSIG, "ZRRSIGState", fp); 2029 printstate(key, DST_KEY_KRRSIG, "KRRSIGState", fp); 2030 printstate(key, DST_KEY_DS, "DSState", fp); 2031 printstate(key, DST_KEY_GOAL, "GoalState", fp); 2032 } 2033 2034 fflush(fp); 2035 if (ferror(fp)) { 2036 ret = DST_R_WRITEERROR; 2037 } 2038 fclose(fp); 2039 2040 return (ret); 2041} 2042 2043/*% 2044 * Writes a public key to disk in DNS format. 2045 */ 2046static isc_result_t 2047write_public_key(const dst_key_t *key, int type, const char *directory) { 2048 FILE *fp; 2049 isc_buffer_t keyb, textb, fileb, classb; 2050 isc_region_t r; 2051 char filename[NAME_MAX]; 2052 unsigned char key_array[DST_KEY_MAXSIZE]; 2053 char text_array[DST_KEY_MAXTEXTSIZE]; 2054 char class_array[10]; 2055 isc_result_t ret; 2056 dns_rdata_t rdata = DNS_RDATA_INIT; 2057 isc_fsaccess_t access; 2058 2059 REQUIRE(VALID_KEY(key)); 2060 2061 isc_buffer_init(&keyb, key_array, sizeof(key_array)); 2062 isc_buffer_init(&textb, text_array, sizeof(text_array)); 2063 isc_buffer_init(&classb, class_array, sizeof(class_array)); 2064 2065 ret = dst_key_todns(key, &keyb); 2066 if (ret != ISC_R_SUCCESS) { 2067 return (ret); 2068 } 2069 2070 isc_buffer_usedregion(&keyb, &r); 2071 dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r); 2072 2073 ret = dns_rdata_totext(&rdata, (dns_name_t *)NULL, &textb); 2074 if (ret != ISC_R_SUCCESS) { 2075 return (DST_R_INVALIDPUBLICKEY); 2076 } 2077 2078 ret = dns_rdataclass_totext(key->key_class, &classb); 2079 if (ret != ISC_R_SUCCESS) { 2080 return (DST_R_INVALIDPUBLICKEY); 2081 } 2082 2083 /* 2084 * Make the filename. 2085 */ 2086 isc_buffer_init(&fileb, filename, sizeof(filename)); 2087 ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb); 2088 if (ret != ISC_R_SUCCESS) { 2089 return (ret); 2090 } 2091 2092 /* 2093 * Create public key file. 2094 */ 2095 if ((fp = fopen(filename, "w")) == NULL) { 2096 return (DST_R_WRITEERROR); 2097 } 2098 2099 if (issymmetric(key)) { 2100 access = 0; 2101 isc_fsaccess_add(ISC_FSACCESS_OWNER, 2102 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, 2103 &access); 2104 (void)isc_fsaccess_set(filename, access); 2105 } 2106 2107 /* Write key information in comments */ 2108 if ((type & DST_TYPE_KEY) == 0) { 2109 fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ", 2110 (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ? "revoked " 2111 : "", 2112 (key->key_flags & DNS_KEYFLAG_KSK) != 0 ? "key" 2113 : "zone", 2114 key->key_id); 2115 ret = dns_name_print(key->key_name, fp); 2116 if (ret != ISC_R_SUCCESS) { 2117 fclose(fp); 2118 return (ret); 2119 } 2120 fputc('\n', fp); 2121 2122 printtime(key, DST_TIME_CREATED, "; Created", fp); 2123 printtime(key, DST_TIME_PUBLISH, "; Publish", fp); 2124 printtime(key, DST_TIME_ACTIVATE, "; Activate", fp); 2125 printtime(key, DST_TIME_REVOKE, "; Revoke", fp); 2126 printtime(key, DST_TIME_INACTIVE, "; Inactive", fp); 2127 printtime(key, DST_TIME_DELETE, "; Delete", fp); 2128 printtime(key, DST_TIME_SYNCPUBLISH, "; SyncPublish", fp); 2129 printtime(key, DST_TIME_SYNCDELETE, "; SyncDelete", fp); 2130 } 2131 2132 /* Now print the actual key */ 2133 ret = dns_name_print(key->key_name, fp); 2134 fprintf(fp, " "); 2135 2136 if (key->key_ttl != 0) { 2137 fprintf(fp, "%u ", key->key_ttl); 2138 } 2139 2140 isc_buffer_usedregion(&classb, &r); 2141 if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) { 2142 ret = DST_R_WRITEERROR; 2143 } 2144 2145 if ((type & DST_TYPE_KEY) != 0) { 2146 fprintf(fp, " KEY "); 2147 } else { 2148 fprintf(fp, " DNSKEY "); 2149 } 2150 2151 isc_buffer_usedregion(&textb, &r); 2152 if ((unsigned)fwrite(r.base, 1, r.length, fp) != r.length) { 2153 ret = DST_R_WRITEERROR; 2154 } 2155 2156 fputc('\n', fp); 2157 fflush(fp); 2158 if (ferror(fp)) { 2159 ret = DST_R_WRITEERROR; 2160 } 2161 fclose(fp); 2162 2163 return (ret); 2164} 2165 2166static isc_result_t 2167buildfilename(dns_name_t *name, dns_keytag_t id, unsigned int alg, 2168 unsigned int type, const char *directory, isc_buffer_t *out) { 2169 const char *suffix = ""; 2170 isc_result_t result; 2171 2172 REQUIRE(out != NULL); 2173 if ((type & DST_TYPE_PRIVATE) != 0) { 2174 suffix = ".private"; 2175 } else if ((type & DST_TYPE_PUBLIC) != 0) { 2176 suffix = ".key"; 2177 } else if ((type & DST_TYPE_STATE) != 0) { 2178 suffix = ".state"; 2179 } 2180 2181 if (directory != NULL) { 2182 if (isc_buffer_availablelength(out) < strlen(directory)) { 2183 return (ISC_R_NOSPACE); 2184 } 2185 isc_buffer_putstr(out, directory); 2186 if (strlen(directory) > 0U && 2187 directory[strlen(directory) - 1] != '/') { 2188 isc_buffer_putstr(out, "/"); 2189 } 2190 } 2191 if (isc_buffer_availablelength(out) < 1) { 2192 return (ISC_R_NOSPACE); 2193 } 2194 isc_buffer_putstr(out, "K"); 2195 result = dns_name_tofilenametext(name, false, out); 2196 if (result != ISC_R_SUCCESS) { 2197 return (result); 2198 } 2199 2200 return (isc_buffer_printf(out, "+%03d+%05d%s", alg, id, suffix)); 2201} 2202 2203static isc_result_t 2204computeid(dst_key_t *key) { 2205 isc_buffer_t dnsbuf; 2206 unsigned char dns_array[DST_KEY_MAXSIZE]; 2207 isc_region_t r; 2208 isc_result_t ret; 2209 2210 isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array)); 2211 ret = dst_key_todns(key, &dnsbuf); 2212 if (ret != ISC_R_SUCCESS) { 2213 return (ret); 2214 } 2215 2216 isc_buffer_usedregion(&dnsbuf, &r); 2217 key->key_id = dst_region_computeid(&r); 2218 key->key_rid = dst_region_computerid(&r); 2219 return (ISC_R_SUCCESS); 2220} 2221 2222static isc_result_t 2223frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, 2224 unsigned int protocol, dns_rdataclass_t rdclass, 2225 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { 2226 dst_key_t *key; 2227 isc_result_t ret; 2228 2229 REQUIRE(dns_name_isabsolute(name)); 2230 REQUIRE(source != NULL); 2231 REQUIRE(mctx != NULL); 2232 REQUIRE(keyp != NULL && *keyp == NULL); 2233 2234 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 2235 if (key == NULL) { 2236 return (ISC_R_NOMEMORY); 2237 } 2238 2239 if (isc_buffer_remaininglength(source) > 0) { 2240 ret = algorithm_status(alg); 2241 if (ret != ISC_R_SUCCESS) { 2242 dst_key_free(&key); 2243 return (ret); 2244 } 2245 if (key->func->fromdns == NULL) { 2246 dst_key_free(&key); 2247 return (DST_R_UNSUPPORTEDALG); 2248 } 2249 2250 ret = key->func->fromdns(key, source); 2251 if (ret != ISC_R_SUCCESS) { 2252 dst_key_free(&key); 2253 return (ret); 2254 } 2255 } 2256 2257 *keyp = key; 2258 return (ISC_R_SUCCESS); 2259} 2260 2261static isc_result_t 2262algorithm_status(unsigned int alg) { 2263 REQUIRE(dst_initialized); 2264 2265 if (dst_algorithm_supported(alg)) { 2266 return (ISC_R_SUCCESS); 2267 } 2268 return (DST_R_UNSUPPORTEDALG); 2269} 2270 2271static isc_result_t 2272addsuffix(char *filename, int len, const char *odirname, const char *ofilename, 2273 const char *suffix) { 2274 int olen = strlen(ofilename); 2275 int n; 2276 2277 if (olen > 1 && ofilename[olen - 1] == '.') { 2278 olen -= 1; 2279 } else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0) { 2280 olen -= 8; 2281 } else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) { 2282 olen -= 4; 2283 } 2284 2285 if (odirname == NULL) { 2286 n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix); 2287 } else { 2288 n = snprintf(filename, len, "%s/%.*s%s", odirname, olen, 2289 ofilename, suffix); 2290 } 2291 if (n < 0) { 2292 return (ISC_R_FAILURE); 2293 } 2294 if (n >= len) { 2295 return (ISC_R_NOSPACE); 2296 } 2297 return (ISC_R_SUCCESS); 2298} 2299 2300isc_buffer_t * 2301dst_key_tkeytoken(const dst_key_t *key) { 2302 REQUIRE(VALID_KEY(key)); 2303 return (key->key_tkeytoken); 2304} 2305 2306/* 2307 * A key is considered unused if it does not have any timing metadata set 2308 * other than "Created". 2309 * 2310 */ 2311bool 2312dst_key_is_unused(dst_key_t *key) { 2313 isc_stdtime_t val; 2314 dst_key_state_t st; 2315 int state_type; 2316 bool state_type_set; 2317 2318 REQUIRE(VALID_KEY(key)); 2319 2320 /* 2321 * None of the key timing metadata, except Created, may be set. Key 2322 * state times may be set only if their respective state is HIDDEN. 2323 */ 2324 for (int i = 0; i < DST_MAX_TIMES + 1; i++) { 2325 state_type_set = false; 2326 2327 switch (i) { 2328 case DST_TIME_CREATED: 2329 break; 2330 case DST_TIME_DNSKEY: 2331 state_type = DST_KEY_DNSKEY; 2332 state_type_set = true; 2333 break; 2334 case DST_TIME_ZRRSIG: 2335 state_type = DST_KEY_ZRRSIG; 2336 state_type_set = true; 2337 break; 2338 case DST_TIME_KRRSIG: 2339 state_type = DST_KEY_KRRSIG; 2340 state_type_set = true; 2341 break; 2342 case DST_TIME_DS: 2343 state_type = DST_KEY_DS; 2344 state_type_set = true; 2345 break; 2346 default: 2347 break; 2348 } 2349 2350 /* Created is fine. */ 2351 if (i == DST_TIME_CREATED) { 2352 continue; 2353 } 2354 /* No such timing metadata found, that is fine too. */ 2355 if (dst_key_gettime(key, i, &val) == ISC_R_NOTFOUND) { 2356 continue; 2357 } 2358 /* 2359 * Found timing metadata and it is not related to key states. 2360 * This key is used. 2361 */ 2362 if (!state_type_set) { 2363 return (false); 2364 } 2365 /* 2366 * If the state is not HIDDEN, the key is in use. 2367 * If the state is not set, this is odd and we default to NA. 2368 */ 2369 if (dst_key_getstate(key, state_type, &st) != ISC_R_SUCCESS) { 2370 st = DST_KEY_STATE_NA; 2371 } 2372 if (st != DST_KEY_STATE_HIDDEN) { 2373 return (false); 2374 } 2375 } 2376 /* This key is unused. */ 2377 return (true); 2378} 2379 2380static void 2381get_ksk_zsk(dst_key_t *key, bool *ksk, bool *zsk) { 2382 bool k = false, z = false; 2383 2384 if (dst_key_getbool(key, DST_BOOL_KSK, &k) == ISC_R_SUCCESS) { 2385 *ksk = k; 2386 } else { 2387 *ksk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) != 0); 2388 } 2389 if (dst_key_getbool(key, DST_BOOL_ZSK, &z) == ISC_R_SUCCESS) { 2390 *zsk = z; 2391 } else { 2392 *zsk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0); 2393 } 2394} 2395 2396/* Hints on key whether it can be published and/or used for signing. */ 2397 2398bool 2399dst_key_is_published(dst_key_t *key, isc_stdtime_t now, 2400 isc_stdtime_t *publish) { 2401 dst_key_state_t state; 2402 isc_result_t result; 2403 isc_stdtime_t when; 2404 bool state_ok = true, time_ok = false; 2405 2406 REQUIRE(VALID_KEY(key)); 2407 2408 result = dst_key_gettime(key, DST_TIME_PUBLISH, &when); 2409 if (result == ISC_R_SUCCESS) { 2410 *publish = when; 2411 time_ok = (when <= now); 2412 } 2413 2414 /* Check key states: 2415 * If the DNSKEY state is RUMOURED or OMNIPRESENT, it means it 2416 * should be published. 2417 */ 2418 result = dst_key_getstate(key, DST_KEY_DNSKEY, &state); 2419 if (result == ISC_R_SUCCESS) { 2420 state_ok = ((state == DST_KEY_STATE_RUMOURED) || 2421 (state == DST_KEY_STATE_OMNIPRESENT)); 2422 /* 2423 * Key states trump timing metadata. 2424 * Ignore inactive time. 2425 */ 2426 time_ok = true; 2427 } 2428 2429 return (state_ok && time_ok); 2430} 2431 2432bool 2433dst_key_is_active(dst_key_t *key, isc_stdtime_t now) { 2434 dst_key_state_t state; 2435 isc_result_t result; 2436 isc_stdtime_t when = 0; 2437 bool ksk = false, zsk = false, inactive = false; 2438 bool ds_ok = true, zrrsig_ok = true, time_ok = false; 2439 2440 REQUIRE(VALID_KEY(key)); 2441 2442 result = dst_key_gettime(key, DST_TIME_INACTIVE, &when); 2443 if (result == ISC_R_SUCCESS) { 2444 inactive = (when <= now); 2445 } 2446 2447 result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when); 2448 if (result == ISC_R_SUCCESS) { 2449 time_ok = (when <= now); 2450 } 2451 2452 get_ksk_zsk(key, &ksk, &zsk); 2453 2454 /* Check key states: 2455 * KSK: If the DS is RUMOURED or OMNIPRESENT the key is considered 2456 * active. 2457 */ 2458 if (ksk) { 2459 result = dst_key_getstate(key, DST_KEY_DS, &state); 2460 if (result == ISC_R_SUCCESS) { 2461 ds_ok = ((state == DST_KEY_STATE_RUMOURED) || 2462 (state == DST_KEY_STATE_OMNIPRESENT)); 2463 /* 2464 * Key states trump timing metadata. 2465 * Ignore inactive time. 2466 */ 2467 time_ok = true; 2468 inactive = false; 2469 } 2470 } 2471 /* 2472 * ZSK: If the ZRRSIG state is RUMOURED or OMNIPRESENT, it means the 2473 * key is active. 2474 */ 2475 if (zsk) { 2476 result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state); 2477 if (result == ISC_R_SUCCESS) { 2478 zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) || 2479 (state == DST_KEY_STATE_OMNIPRESENT)); 2480 /* 2481 * Key states trump timing metadata. 2482 * Ignore inactive time. 2483 */ 2484 time_ok = true; 2485 inactive = false; 2486 } 2487 } 2488 return (ds_ok && zrrsig_ok && time_ok && !inactive); 2489} 2490 2491bool 2492dst_key_is_signing(dst_key_t *key, int role, isc_stdtime_t now, 2493 isc_stdtime_t *active) { 2494 dst_key_state_t state; 2495 isc_result_t result; 2496 isc_stdtime_t when = 0; 2497 bool ksk = false, zsk = false, inactive = false; 2498 bool krrsig_ok = true, zrrsig_ok = true, time_ok = false; 2499 2500 REQUIRE(VALID_KEY(key)); 2501 2502 result = dst_key_gettime(key, DST_TIME_INACTIVE, &when); 2503 if (result == ISC_R_SUCCESS) { 2504 inactive = (when <= now); 2505 } 2506 2507 result = dst_key_gettime(key, DST_TIME_ACTIVATE, &when); 2508 if (result == ISC_R_SUCCESS) { 2509 *active = when; 2510 time_ok = (when <= now); 2511 } 2512 2513 get_ksk_zsk(key, &ksk, &zsk); 2514 2515 /* Check key states: 2516 * If the RRSIG state is RUMOURED or OMNIPRESENT, it means the key 2517 * is active. 2518 */ 2519 if (ksk && role == DST_BOOL_KSK) { 2520 result = dst_key_getstate(key, DST_KEY_KRRSIG, &state); 2521 if (result == ISC_R_SUCCESS) { 2522 krrsig_ok = ((state == DST_KEY_STATE_RUMOURED) || 2523 (state == DST_KEY_STATE_OMNIPRESENT)); 2524 /* 2525 * Key states trump timing metadata. 2526 * Ignore inactive time. 2527 */ 2528 time_ok = true; 2529 inactive = false; 2530 } 2531 } else if (zsk && role == DST_BOOL_ZSK) { 2532 result = dst_key_getstate(key, DST_KEY_ZRRSIG, &state); 2533 if (result == ISC_R_SUCCESS) { 2534 zrrsig_ok = ((state == DST_KEY_STATE_RUMOURED) || 2535 (state == DST_KEY_STATE_OMNIPRESENT)); 2536 /* 2537 * Key states trump timing metadata. 2538 * Ignore inactive time. 2539 */ 2540 time_ok = true; 2541 inactive = false; 2542 } 2543 } 2544 return (krrsig_ok && zrrsig_ok && time_ok && !inactive); 2545} 2546 2547bool 2548dst_key_is_revoked(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *revoke) { 2549 isc_result_t result; 2550 isc_stdtime_t when = 0; 2551 bool time_ok = false; 2552 2553 REQUIRE(VALID_KEY(key)); 2554 2555 result = dst_key_gettime(key, DST_TIME_REVOKE, &when); 2556 if (result == ISC_R_SUCCESS) { 2557 *revoke = when; 2558 time_ok = (when <= now); 2559 } 2560 2561 return (time_ok); 2562} 2563 2564bool 2565dst_key_is_removed(dst_key_t *key, isc_stdtime_t now, isc_stdtime_t *remove) { 2566 dst_key_state_t state; 2567 isc_result_t result; 2568 isc_stdtime_t when = 0; 2569 bool state_ok = true, time_ok = false; 2570 2571 REQUIRE(VALID_KEY(key)); 2572 2573 if (dst_key_is_unused(key)) { 2574 /* This key was never used. */ 2575 return (false); 2576 } 2577 2578 result = dst_key_gettime(key, DST_TIME_DELETE, &when); 2579 if (result == ISC_R_SUCCESS) { 2580 *remove = when; 2581 time_ok = (when <= now); 2582 } 2583 2584 /* Check key states: 2585 * If the DNSKEY state is UNRETENTIVE or HIDDEN, it means the key 2586 * should not be published. 2587 */ 2588 result = dst_key_getstate(key, DST_KEY_DNSKEY, &state); 2589 if (result == ISC_R_SUCCESS) { 2590 state_ok = ((state == DST_KEY_STATE_UNRETENTIVE) || 2591 (state == DST_KEY_STATE_HIDDEN)); 2592 /* 2593 * Key states trump timing metadata. 2594 * Ignore delete time. 2595 */ 2596 time_ok = true; 2597 } 2598 2599 return (state_ok && time_ok); 2600} 2601 2602dst_key_state_t 2603dst_key_goal(dst_key_t *key) { 2604 dst_key_state_t state; 2605 isc_result_t result; 2606 2607 REQUIRE(VALID_KEY(key)); 2608 2609 result = dst_key_getstate(key, DST_KEY_GOAL, &state); 2610 if (result == ISC_R_SUCCESS) { 2611 return (state); 2612 } 2613 return (DST_KEY_STATE_HIDDEN); 2614} 2615 2616bool 2617dst_key_haskasp(dst_key_t *key) { 2618 REQUIRE(VALID_KEY(key)); 2619 2620 return (key->kasp); 2621} 2622 2623void 2624dst_key_copy_metadata(dst_key_t *to, dst_key_t *from) { 2625 dst_key_state_t state; 2626 isc_stdtime_t when; 2627 uint32_t num; 2628 bool yesno; 2629 isc_result_t result; 2630 2631 REQUIRE(VALID_KEY(to)); 2632 REQUIRE(VALID_KEY(from)); 2633 2634 for (int i = 0; i < DST_MAX_TIMES + 1; i++) { 2635 result = dst_key_gettime(from, i, &when); 2636 if (result == ISC_R_SUCCESS) { 2637 dst_key_settime(to, i, when); 2638 } else { 2639 dst_key_unsettime(to, i); 2640 } 2641 } 2642 2643 for (int i = 0; i < DST_MAX_NUMERIC + 1; i++) { 2644 result = dst_key_getnum(from, i, &num); 2645 if (result == ISC_R_SUCCESS) { 2646 dst_key_setnum(to, i, num); 2647 } else { 2648 dst_key_unsetnum(to, i); 2649 } 2650 } 2651 2652 for (int i = 0; i < DST_MAX_BOOLEAN + 1; i++) { 2653 result = dst_key_getbool(from, i, &yesno); 2654 if (result == ISC_R_SUCCESS) { 2655 dst_key_setbool(to, i, yesno); 2656 } else { 2657 dst_key_unsetnum(to, i); 2658 } 2659 } 2660 2661 for (int i = 0; i < DST_MAX_KEYSTATES + 1; i++) { 2662 result = dst_key_getstate(from, i, &state); 2663 if (result == ISC_R_SUCCESS) { 2664 dst_key_setstate(to, i, state); 2665 } else { 2666 dst_key_unsetstate(to, i); 2667 } 2668 } 2669} 2670