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