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