1 /* $NetBSD: dst_api.c,v 1.11 2014/12/10 04:37:58 christos Exp $ */ 2 3 /* 4 * Portions Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") 5 * Portions Copyright (C) 1999-2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 12 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 14 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 17 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 * 19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc. 20 * 21 * Permission to use, copy, modify, and/or distribute this software for any 22 * purpose with or without fee is hereby granted, provided that the above 23 * copyright notice and this permission notice appear in all copies. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 32 */ 33 34 /* 35 * Principal Author: Brian Wellington 36 * Id: dst_api.c,v 1.65 2011/10/20 21:20:02 marka Exp 37 */ 38 39 /*! \file */ 40 41 #include <config.h> 42 43 #include <stdlib.h> 44 #include <time.h> 45 46 #include <isc/buffer.h> 47 #include <isc/dir.h> 48 #include <isc/entropy.h> 49 #include <isc/fsaccess.h> 50 #include <isc/hmacsha.h> 51 #include <isc/lex.h> 52 #include <isc/mem.h> 53 #include <isc/once.h> 54 #include <isc/platform.h> 55 #include <isc/print.h> 56 #include <isc/refcount.h> 57 #include <isc/random.h> 58 #include <isc/string.h> 59 #include <isc/time.h> 60 #include <isc/util.h> 61 #include <isc/file.h> 62 63 #define DST_KEY_INTERNAL 64 65 #include <dns/fixedname.h> 66 #include <dns/keyvalues.h> 67 #include <dns/name.h> 68 #include <dns/rdata.h> 69 #include <dns/rdataclass.h> 70 #include <dns/ttl.h> 71 #include <dns/types.h> 72 73 #include <dst/result.h> 74 75 #include "dst_internal.h" 76 77 #define DST_AS_STR(t) ((t).value.as_textregion.base) 78 79 static dst_func_t *dst_t_func[DST_MAX_ALGS]; 80 static isc_entropy_t *dst_entropy_pool = NULL; 81 static unsigned int dst_entropy_flags = 0; 82 static isc_boolean_t dst_initialized = ISC_FALSE; 83 84 void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); 85 86 isc_mem_t *dst__memory_pool = NULL; 87 88 /* 89 * Static functions. 90 */ 91 static dst_key_t * get_key_struct(dns_name_t *name, 92 unsigned int alg, 93 unsigned int flags, 94 unsigned int protocol, 95 unsigned int bits, 96 dns_rdataclass_t rdclass, 97 dns_ttl_t ttl, 98 isc_mem_t *mctx); 99 static isc_result_t write_public_key(const dst_key_t *key, int type, 100 const char *directory); 101 static isc_result_t buildfilename(dns_name_t *name, 102 dns_keytag_t id, 103 unsigned int alg, 104 unsigned int type, 105 const char *directory, 106 isc_buffer_t *out); 107 static isc_result_t computeid(dst_key_t *key); 108 static isc_result_t frombuffer(dns_name_t *name, 109 unsigned int alg, 110 unsigned int flags, 111 unsigned int protocol, 112 dns_rdataclass_t rdclass, 113 isc_buffer_t *source, 114 isc_mem_t *mctx, 115 dst_key_t **keyp); 116 117 static isc_result_t algorithm_status(unsigned int alg); 118 119 static isc_result_t addsuffix(char *filename, int len, 120 const char *dirname, const char *ofilename, 121 const char *suffix); 122 123 #define RETERR(x) \ 124 do { \ 125 result = (x); \ 126 if (result != ISC_R_SUCCESS) \ 127 goto out; \ 128 } while (/*CONSTCOND*/0) 129 130 #define CHECKALG(alg) \ 131 do { \ 132 isc_result_t _r; \ 133 _r = algorithm_status(alg); \ 134 if (_r != ISC_R_SUCCESS) \ 135 return (_r); \ 136 } while (/*CONSTCOND*/0); \ 137 138 #if defined(OPENSSL) 139 static void * 140 default_memalloc(void *arg, size_t size) { 141 UNUSED(arg); 142 if (size == 0U) 143 size = 1; 144 return (malloc(size)); 145 } 146 147 static void 148 default_memfree(void *arg, void *ptr) { 149 UNUSED(arg); 150 free(ptr); 151 } 152 #endif 153 154 isc_result_t 155 dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { 156 return (dst_lib_init2(mctx, ectx, NULL, eflags)); 157 } 158 159 isc_result_t 160 dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, 161 const char *engine, unsigned int eflags) { 162 isc_result_t result; 163 164 REQUIRE(mctx != NULL); 165 UNUSED(ectx); 166 REQUIRE(dst_initialized == ISC_FALSE); 167 168 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO) 169 UNUSED(engine); 170 #endif 171 172 dst__memory_pool = NULL; 173 174 #if defined(OPENSSL) 175 UNUSED(mctx); 176 /* 177 * When using --with-openssl, there seems to be no good way of not 178 * leaking memory due to the openssl error handling mechanism. 179 * Avoid assertions by using a local memory context and not checking 180 * for leaks on exit. Note: as there are leaks we cannot use 181 * ISC_MEMFLAG_INTERNAL as it will free up memory still being used 182 * by libcrypto. 183 */ 184 result = isc_mem_createx2(0, 0, default_memalloc, default_memfree, 185 NULL, &dst__memory_pool, 0); 186 if (result != ISC_R_SUCCESS) 187 return (result); 188 isc_mem_setname(dst__memory_pool, "dst", NULL); 189 #ifndef OPENSSL_LEAKS 190 isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE); 191 #endif 192 #else /* OPENSSL */ 193 isc_mem_attach(mctx, &dst__memory_pool); 194 #endif /* OPENSSL */ 195 if (ectx != NULL) { 196 isc_entropy_attach(ectx, &dst_entropy_pool); 197 dst_entropy_flags = eflags; 198 } 199 200 dst_result_register(); 201 202 memset(dst_t_func, 0, sizeof(dst_t_func)); 203 RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5])); 204 RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1])); 205 RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224])); 206 RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256])); 207 RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384])); 208 RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); 209 #ifdef OPENSSL 210 RETERR(dst__openssl_init(engine)); 211 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5], 212 DST_ALG_RSAMD5)); 213 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1], 214 DST_ALG_RSASHA1)); 215 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1], 216 DST_ALG_NSEC3RSASHA1)); 217 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256], 218 DST_ALG_RSASHA256)); 219 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512], 220 DST_ALG_RSASHA512)); 221 #ifdef HAVE_OPENSSL_DSA 222 RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA])); 223 RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); 224 #endif 225 RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH])); 226 #ifdef HAVE_OPENSSL_GOST 227 RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST])); 228 #endif 229 #ifdef HAVE_OPENSSL_ECDSA 230 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256])); 231 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); 232 #endif 233 #elif PKCS11CRYPTO 234 RETERR(dst__pkcs11_init(mctx, engine)); 235 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5])); 236 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1])); 237 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1])); 238 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256])); 239 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512])); 240 RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA])); 241 RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); 242 RETERR(dst__pkcs11dh_init(&dst_t_func[DST_ALG_DH])); 243 #ifdef HAVE_PKCS11_ECDSA 244 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256])); 245 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); 246 #endif 247 #ifdef HAVE_PKCS11_GOST 248 RETERR(dst__pkcs11gost_init(&dst_t_func[DST_ALG_ECCGOST])); 249 #endif 250 #endif /* if OPENSSL, elif PKCS11CRYPTO */ 251 #ifdef GSSAPI 252 RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI])); 253 #endif 254 dst_initialized = ISC_TRUE; 255 return (ISC_R_SUCCESS); 256 257 out: 258 /* avoid immediate crash! */ 259 dst_initialized = ISC_TRUE; 260 dst_lib_destroy(); 261 return (result); 262 } 263 264 void 265 dst_lib_destroy(void) { 266 int i; 267 RUNTIME_CHECK(dst_initialized == ISC_TRUE); 268 dst_initialized = ISC_FALSE; 269 270 for (i = 0; i < DST_MAX_ALGS; i++) 271 if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL) 272 dst_t_func[i]->cleanup(); 273 #ifdef OPENSSL 274 dst__openssl_destroy(); 275 #elif PKCS11CRYPTO 276 (void) dst__pkcs11_destroy(); 277 #endif /* if OPENSSL, elif PKCS11CRYPTO */ 278 if (dst__memory_pool != NULL) 279 isc_mem_detach(&dst__memory_pool); 280 if (dst_entropy_pool != NULL) 281 isc_entropy_detach(&dst_entropy_pool); 282 } 283 284 isc_boolean_t 285 dst_algorithm_supported(unsigned int alg) { 286 REQUIRE(dst_initialized == ISC_TRUE); 287 288 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) 289 return (ISC_FALSE); 290 return (ISC_TRUE); 291 } 292 293 isc_boolean_t 294 dst_ds_digest_supported(unsigned int digest_type) { 295 #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST) 296 return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 || 297 digest_type == DNS_DSDIGEST_SHA256 || 298 digest_type == DNS_DSDIGEST_GOST || 299 digest_type == DNS_DSDIGEST_SHA384)); 300 #else 301 return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 || 302 digest_type == DNS_DSDIGEST_SHA256 || 303 digest_type == DNS_DSDIGEST_SHA384)); 304 #endif 305 } 306 307 isc_result_t 308 dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) { 309 return (dst_context_create4(key, mctx, DNS_LOGCATEGORY_GENERAL, 310 ISC_TRUE, 0, dctxp)); 311 } 312 313 isc_result_t 314 dst_context_create2(dst_key_t *key, isc_mem_t *mctx, 315 isc_logcategory_t *category, dst_context_t **dctxp) 316 { 317 return (dst_context_create4(key, mctx, category, ISC_TRUE, 0, dctxp)); 318 } 319 320 isc_result_t 321 dst_context_create3(dst_key_t *key, isc_mem_t *mctx, 322 isc_logcategory_t *category, isc_boolean_t useforsigning, 323 dst_context_t **dctxp) 324 { 325 return (dst_context_create4(key, mctx, category, 326 useforsigning, 0, dctxp)); 327 } 328 329 isc_result_t 330 dst_context_create4(dst_key_t *key, isc_mem_t *mctx, 331 isc_logcategory_t *category, isc_boolean_t useforsigning, 332 int maxbits, dst_context_t **dctxp) 333 { 334 dst_context_t *dctx; 335 isc_result_t result; 336 337 REQUIRE(dst_initialized == ISC_TRUE); 338 REQUIRE(VALID_KEY(key)); 339 REQUIRE(mctx != NULL); 340 REQUIRE(dctxp != NULL && *dctxp == NULL); 341 342 if (key->func->createctx == NULL && 343 key->func->createctx2 == NULL) 344 return (DST_R_UNSUPPORTEDALG); 345 if (key->keydata.generic == NULL) 346 return (DST_R_NULLKEY); 347 348 dctx = isc_mem_get(mctx, sizeof(dst_context_t)); 349 if (dctx == NULL) 350 return (ISC_R_NOMEMORY); 351 dctx->key = key; 352 dctx->mctx = mctx; 353 dctx->category = category; 354 if (useforsigning) 355 dctx->use = DO_SIGN; 356 else 357 dctx->use = DO_VERIFY; 358 if (key->func->createctx2 != NULL) 359 result = key->func->createctx2(key, maxbits, dctx); 360 else 361 result = key->func->createctx(key, dctx); 362 if (result != ISC_R_SUCCESS) { 363 isc_mem_put(mctx, dctx, sizeof(dst_context_t)); 364 return (result); 365 } 366 dctx->magic = CTX_MAGIC; 367 *dctxp = dctx; 368 return (ISC_R_SUCCESS); 369 } 370 371 void 372 dst_context_destroy(dst_context_t **dctxp) { 373 dst_context_t *dctx; 374 375 REQUIRE(dctxp != NULL && VALID_CTX(*dctxp)); 376 377 dctx = *dctxp; 378 INSIST(dctx->key->func->destroyctx != NULL); 379 dctx->key->func->destroyctx(dctx); 380 dctx->magic = 0; 381 isc_mem_put(dctx->mctx, dctx, sizeof(dst_context_t)); 382 *dctxp = NULL; 383 } 384 385 isc_result_t 386 dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) { 387 REQUIRE(VALID_CTX(dctx)); 388 REQUIRE(data != NULL); 389 INSIST(dctx->key->func->adddata != NULL); 390 391 return (dctx->key->func->adddata(dctx, data)); 392 } 393 394 isc_result_t 395 dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) { 396 dst_key_t *key; 397 398 REQUIRE(VALID_CTX(dctx)); 399 REQUIRE(sig != NULL); 400 401 key = dctx->key; 402 CHECKALG(key->key_alg); 403 if (key->keydata.generic == NULL) 404 return (DST_R_NULLKEY); 405 406 if (key->func->sign == NULL) 407 return (DST_R_NOTPRIVATEKEY); 408 if (key->func->isprivate == NULL || 409 key->func->isprivate(key) == ISC_FALSE) 410 return (DST_R_NOTPRIVATEKEY); 411 412 return (key->func->sign(dctx, sig)); 413 } 414 415 isc_result_t 416 dst_context_verify(dst_context_t *dctx, isc_region_t *sig) { 417 REQUIRE(VALID_CTX(dctx)); 418 REQUIRE(sig != NULL); 419 420 CHECKALG(dctx->key->key_alg); 421 if (dctx->key->keydata.generic == NULL) 422 return (DST_R_NULLKEY); 423 if (dctx->key->func->verify == NULL) 424 return (DST_R_NOTPUBLICKEY); 425 426 return (dctx->key->func->verify(dctx, sig)); 427 } 428 429 isc_result_t 430 dst_context_verify2(dst_context_t *dctx, unsigned int maxbits, 431 isc_region_t *sig) 432 { 433 REQUIRE(VALID_CTX(dctx)); 434 REQUIRE(sig != NULL); 435 436 CHECKALG(dctx->key->key_alg); 437 if (dctx->key->keydata.generic == NULL) 438 return (DST_R_NULLKEY); 439 if (dctx->key->func->verify == NULL && 440 dctx->key->func->verify2 == NULL) 441 return (DST_R_NOTPUBLICKEY); 442 443 return (dctx->key->func->verify2 != NULL ? 444 dctx->key->func->verify2(dctx, maxbits, sig) : 445 dctx->key->func->verify(dctx, sig)); 446 } 447 448 isc_result_t 449 dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv, 450 isc_buffer_t *secret) 451 { 452 REQUIRE(dst_initialized == ISC_TRUE); 453 REQUIRE(VALID_KEY(pub) && VALID_KEY(priv)); 454 REQUIRE(secret != NULL); 455 456 CHECKALG(pub->key_alg); 457 CHECKALG(priv->key_alg); 458 459 if (pub->keydata.generic == NULL || priv->keydata.generic == NULL) 460 return (DST_R_NULLKEY); 461 462 if (pub->key_alg != priv->key_alg || 463 pub->func->computesecret == NULL || 464 priv->func->computesecret == NULL) 465 return (DST_R_KEYCANNOTCOMPUTESECRET); 466 467 if (dst_key_isprivate(priv) == ISC_FALSE) 468 return (DST_R_NOTPRIVATEKEY); 469 470 return (pub->func->computesecret(pub, priv, secret)); 471 } 472 473 isc_result_t 474 dst_key_tofile(const dst_key_t *key, int type, const char *directory) { 475 isc_result_t ret = ISC_R_SUCCESS; 476 477 REQUIRE(dst_initialized == ISC_TRUE); 478 REQUIRE(VALID_KEY(key)); 479 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 480 481 CHECKALG(key->key_alg); 482 483 if (key->func->tofile == NULL) 484 return (DST_R_UNSUPPORTEDALG); 485 486 if (type & DST_TYPE_PUBLIC) { 487 ret = write_public_key(key, type, directory); 488 if (ret != ISC_R_SUCCESS) 489 return (ret); 490 } 491 492 if ((type & DST_TYPE_PRIVATE) && 493 (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY) 494 return (key->func->tofile(key, directory)); 495 else 496 return (ISC_R_SUCCESS); 497 } 498 499 void 500 dst_key_setexternal(dst_key_t *key, isc_boolean_t value) { 501 key->external = value; 502 } 503 504 isc_boolean_t 505 dst_key_isexternal(dst_key_t *key) { 506 return (key->external); 507 } 508 509 isc_result_t 510 dst_key_fromfile(dns_name_t *name, dns_keytag_t id, 511 unsigned int alg, int type, const char *directory, 512 isc_mem_t *mctx, dst_key_t **keyp) 513 { 514 char filename[ISC_DIR_NAMEMAX]; 515 isc_buffer_t b; 516 dst_key_t *key; 517 isc_result_t result; 518 519 REQUIRE(dst_initialized == ISC_TRUE); 520 REQUIRE(dns_name_isabsolute(name)); 521 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 522 REQUIRE(mctx != NULL); 523 REQUIRE(keyp != NULL && *keyp == NULL); 524 525 CHECKALG(alg); 526 527 isc_buffer_init(&b, filename, sizeof(filename)); 528 result = buildfilename(name, id, alg, type, directory, &b); 529 if (result != ISC_R_SUCCESS) 530 return (result); 531 532 key = NULL; 533 result = dst_key_fromnamedfile(filename, NULL, type, mctx, &key); 534 if (result != ISC_R_SUCCESS) 535 return (result); 536 537 result = computeid(key); 538 if (result != ISC_R_SUCCESS) { 539 dst_key_free(&key); 540 return (result); 541 } 542 543 if (!dns_name_equal(name, key->key_name) || id != key->key_id || 544 alg != key->key_alg) { 545 dst_key_free(&key); 546 return (DST_R_INVALIDPRIVATEKEY); 547 } 548 549 *keyp = key; 550 return (ISC_R_SUCCESS); 551 } 552 553 isc_result_t 554 dst_key_fromnamedfile(const char *filename, const char *dirname, 555 int type, isc_mem_t *mctx, dst_key_t **keyp) 556 { 557 isc_result_t result; 558 dst_key_t *pubkey = NULL, *key = NULL; 559 char *newfilename = NULL; 560 int newfilenamelen = 0; 561 isc_lex_t *lex = NULL; 562 563 REQUIRE(dst_initialized == ISC_TRUE); 564 REQUIRE(filename != NULL); 565 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 566 REQUIRE(mctx != NULL); 567 REQUIRE(keyp != NULL && *keyp == NULL); 568 569 /* If an absolute path is specified, don't use the key directory */ 570 #ifndef WIN32 571 if (filename[0] == '/') 572 dirname = NULL; 573 #else /* WIN32 */ 574 if (filename[0] == '/' || filename[0] == '\\') 575 dirname = NULL; 576 #endif 577 578 newfilenamelen = strlen(filename) + 5; 579 if (dirname != NULL) 580 newfilenamelen += strlen(dirname) + 1; 581 newfilename = isc_mem_get(mctx, newfilenamelen); 582 if (newfilename == NULL) 583 return (ISC_R_NOMEMORY); 584 result = addsuffix(newfilename, newfilenamelen, 585 dirname, filename, ".key"); 586 INSIST(result == ISC_R_SUCCESS); 587 588 result = dst_key_read_public(newfilename, type, mctx, &pubkey); 589 isc_mem_put(mctx, newfilename, newfilenamelen); 590 newfilename = NULL; 591 RETERR(result); 592 593 if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC || 594 (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { 595 result = computeid(pubkey); 596 if (result != ISC_R_SUCCESS) { 597 dst_key_free(&pubkey); 598 return (result); 599 } 600 601 *keyp = pubkey; 602 return (ISC_R_SUCCESS); 603 } 604 605 result = algorithm_status(pubkey->key_alg); 606 if (result != ISC_R_SUCCESS) { 607 dst_key_free(&pubkey); 608 return (result); 609 } 610 611 key = get_key_struct(pubkey->key_name, pubkey->key_alg, 612 pubkey->key_flags, pubkey->key_proto, 0, 613 pubkey->key_class, pubkey->key_ttl, mctx); 614 if (key == NULL) { 615 dst_key_free(&pubkey); 616 return (ISC_R_NOMEMORY); 617 } 618 619 if (key->func->parse == NULL) 620 RETERR(DST_R_UNSUPPORTEDALG); 621 622 newfilenamelen = strlen(filename) + 9; 623 if (dirname != NULL) 624 newfilenamelen += strlen(dirname) + 1; 625 newfilename = isc_mem_get(mctx, newfilenamelen); 626 if (newfilename == NULL) 627 RETERR(ISC_R_NOMEMORY); 628 result = addsuffix(newfilename, newfilenamelen, 629 dirname, filename, ".private"); 630 INSIST(result == ISC_R_SUCCESS); 631 632 RETERR(isc_lex_create(mctx, 1500, &lex)); 633 RETERR(isc_lex_openfile(lex, newfilename)); 634 isc_mem_put(mctx, newfilename, newfilenamelen); 635 636 RETERR(key->func->parse(key, lex, pubkey)); 637 isc_lex_destroy(&lex); 638 639 RETERR(computeid(key)); 640 641 if (pubkey->key_id != key->key_id) 642 RETERR(DST_R_INVALIDPRIVATEKEY); 643 dst_key_free(&pubkey); 644 645 *keyp = key; 646 return (ISC_R_SUCCESS); 647 648 out: 649 if (pubkey != NULL) 650 dst_key_free(&pubkey); 651 if (newfilename != NULL) 652 isc_mem_put(mctx, newfilename, newfilenamelen); 653 if (lex != NULL) 654 isc_lex_destroy(&lex); 655 if (key != NULL) 656 dst_key_free(&key); 657 return (result); 658 } 659 660 isc_result_t 661 dst_key_todns(const dst_key_t *key, isc_buffer_t *target) { 662 REQUIRE(dst_initialized == ISC_TRUE); 663 REQUIRE(VALID_KEY(key)); 664 REQUIRE(target != NULL); 665 666 CHECKALG(key->key_alg); 667 668 if (key->func->todns == NULL) 669 return (DST_R_UNSUPPORTEDALG); 670 671 if (isc_buffer_availablelength(target) < 4) 672 return (ISC_R_NOSPACE); 673 isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff)); 674 isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto); 675 isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg); 676 677 if (key->key_flags & DNS_KEYFLAG_EXTENDED) { 678 if (isc_buffer_availablelength(target) < 2) 679 return (ISC_R_NOSPACE); 680 isc_buffer_putuint16(target, 681 (isc_uint16_t)((key->key_flags >> 16) 682 & 0xffff)); 683 } 684 685 if (key->keydata.generic == NULL) /*%< NULL KEY */ 686 return (ISC_R_SUCCESS); 687 688 return (key->func->todns(key, target)); 689 } 690 691 isc_result_t 692 dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass, 693 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) 694 { 695 isc_uint8_t alg, proto; 696 isc_uint32_t flags, extflags; 697 dst_key_t *key = NULL; 698 dns_keytag_t id, rid; 699 isc_region_t r; 700 isc_result_t result; 701 702 REQUIRE(dst_initialized); 703 704 isc_buffer_remainingregion(source, &r); 705 706 if (isc_buffer_remaininglength(source) < 4) 707 return (DST_R_INVALIDPUBLICKEY); 708 flags = isc_buffer_getuint16(source); 709 proto = isc_buffer_getuint8(source); 710 alg = isc_buffer_getuint8(source); 711 712 id = dst_region_computeid(&r, alg); 713 rid = dst_region_computerid(&r, alg); 714 715 if (flags & DNS_KEYFLAG_EXTENDED) { 716 if (isc_buffer_remaininglength(source) < 2) 717 return (DST_R_INVALIDPUBLICKEY); 718 extflags = isc_buffer_getuint16(source); 719 flags |= (extflags << 16); 720 } 721 722 result = frombuffer(name, alg, flags, proto, rdclass, source, 723 mctx, &key); 724 if (result != ISC_R_SUCCESS) 725 return (result); 726 key->key_id = id; 727 key->key_rid = rid; 728 729 *keyp = key; 730 return (ISC_R_SUCCESS); 731 } 732 733 isc_result_t 734 dst_key_frombuffer(dns_name_t *name, unsigned int alg, 735 unsigned int flags, unsigned int protocol, 736 dns_rdataclass_t rdclass, 737 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) 738 { 739 dst_key_t *key = NULL; 740 isc_result_t result; 741 742 REQUIRE(dst_initialized); 743 744 result = frombuffer(name, alg, flags, protocol, rdclass, source, 745 mctx, &key); 746 if (result != ISC_R_SUCCESS) 747 return (result); 748 749 result = computeid(key); 750 if (result != ISC_R_SUCCESS) { 751 dst_key_free(&key); 752 return (result); 753 } 754 755 *keyp = key; 756 return (ISC_R_SUCCESS); 757 } 758 759 isc_result_t 760 dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) { 761 REQUIRE(dst_initialized == ISC_TRUE); 762 REQUIRE(VALID_KEY(key)); 763 REQUIRE(target != NULL); 764 765 CHECKALG(key->key_alg); 766 767 if (key->func->todns == NULL) 768 return (DST_R_UNSUPPORTEDALG); 769 770 return (key->func->todns(key, target)); 771 } 772 773 isc_result_t 774 dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) { 775 isc_lex_t *lex = NULL; 776 isc_result_t result = ISC_R_SUCCESS; 777 778 REQUIRE(dst_initialized == ISC_TRUE); 779 REQUIRE(VALID_KEY(key)); 780 REQUIRE(!dst_key_isprivate(key)); 781 REQUIRE(buffer != NULL); 782 783 if (key->func->parse == NULL) 784 RETERR(DST_R_UNSUPPORTEDALG); 785 786 RETERR(isc_lex_create(key->mctx, 1500, &lex)); 787 RETERR(isc_lex_openbuffer(lex, buffer)); 788 RETERR(key->func->parse(key, lex, NULL)); 789 out: 790 if (lex != NULL) 791 isc_lex_destroy(&lex); 792 return (result); 793 } 794 795 gss_ctx_id_t 796 dst_key_getgssctx(const dst_key_t *key) 797 { 798 REQUIRE(key != NULL); 799 800 return (key->keydata.gssctx); 801 } 802 803 isc_result_t 804 dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, 805 dst_key_t **keyp, isc_region_t *intoken) 806 { 807 dst_key_t *key; 808 isc_result_t result; 809 810 REQUIRE(gssctx != NULL); 811 REQUIRE(keyp != NULL && *keyp == NULL); 812 813 key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 814 0, dns_rdataclass_in, 0, mctx); 815 if (key == NULL) 816 return (ISC_R_NOMEMORY); 817 818 if (intoken != NULL) { 819 /* 820 * Keep the token for use by external ssu rules. They may need 821 * to examine the PAC in the kerberos ticket. 822 */ 823 RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken, 824 intoken->length)); 825 RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken)); 826 } 827 828 key->keydata.gssctx = gssctx; 829 *keyp = key; 830 result = ISC_R_SUCCESS; 831 out: 832 return result; 833 } 834 835 isc_result_t 836 dst_key_buildinternal(dns_name_t *name, unsigned int alg, 837 unsigned int bits, unsigned int flags, 838 unsigned int protocol, dns_rdataclass_t rdclass, 839 void *data, isc_mem_t *mctx, dst_key_t **keyp) 840 { 841 dst_key_t *key; 842 isc_result_t result; 843 844 REQUIRE(dst_initialized == ISC_TRUE); 845 REQUIRE(dns_name_isabsolute(name)); 846 REQUIRE(mctx != NULL); 847 REQUIRE(keyp != NULL && *keyp == NULL); 848 REQUIRE(data != NULL); 849 850 CHECKALG(alg); 851 852 key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 853 0, mctx); 854 if (key == NULL) 855 return (ISC_R_NOMEMORY); 856 857 key->keydata.generic = data; 858 859 result = computeid(key); 860 if (result != ISC_R_SUCCESS) { 861 dst_key_free(&key); 862 return (result); 863 } 864 865 *keyp = key; 866 return (ISC_R_SUCCESS); 867 } 868 869 isc_result_t 870 dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags, 871 unsigned int protocol, dns_rdataclass_t rdclass, 872 const char *engine, const char *label, const char *pin, 873 isc_mem_t *mctx, dst_key_t **keyp) 874 { 875 dst_key_t *key; 876 isc_result_t result; 877 878 REQUIRE(dst_initialized == ISC_TRUE); 879 REQUIRE(dns_name_isabsolute(name)); 880 REQUIRE(mctx != NULL); 881 REQUIRE(keyp != NULL && *keyp == NULL); 882 REQUIRE(label != NULL); 883 884 CHECKALG(alg); 885 886 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 887 if (key == NULL) 888 return (ISC_R_NOMEMORY); 889 890 if (key->func->fromlabel == NULL) { 891 dst_key_free(&key); 892 return (DST_R_UNSUPPORTEDALG); 893 } 894 895 result = key->func->fromlabel(key, engine, label, pin); 896 if (result != ISC_R_SUCCESS) { 897 dst_key_free(&key); 898 return (result); 899 } 900 901 result = computeid(key); 902 if (result != ISC_R_SUCCESS) { 903 dst_key_free(&key); 904 return (result); 905 } 906 907 *keyp = key; 908 return (ISC_R_SUCCESS); 909 } 910 911 isc_result_t 912 dst_key_generate(dns_name_t *name, unsigned int alg, 913 unsigned int bits, unsigned int param, 914 unsigned int flags, unsigned int protocol, 915 dns_rdataclass_t rdclass, 916 isc_mem_t *mctx, dst_key_t **keyp) 917 { 918 return (dst_key_generate2(name, alg, bits, param, flags, protocol, 919 rdclass, mctx, keyp, NULL)); 920 } 921 922 isc_result_t 923 dst_key_generate2(dns_name_t *name, unsigned int alg, 924 unsigned int bits, unsigned int param, 925 unsigned int flags, unsigned int protocol, 926 dns_rdataclass_t rdclass, 927 isc_mem_t *mctx, dst_key_t **keyp, 928 void (*callback)(int)) 929 { 930 dst_key_t *key; 931 isc_result_t ret; 932 933 REQUIRE(dst_initialized == ISC_TRUE); 934 REQUIRE(dns_name_isabsolute(name)); 935 REQUIRE(mctx != NULL); 936 REQUIRE(keyp != NULL && *keyp == NULL); 937 938 CHECKALG(alg); 939 940 key = get_key_struct(name, alg, flags, protocol, bits, 941 rdclass, 0, mctx); 942 if (key == NULL) 943 return (ISC_R_NOMEMORY); 944 945 if (bits == 0) { /*%< NULL KEY */ 946 key->key_flags |= DNS_KEYTYPE_NOKEY; 947 *keyp = key; 948 return (ISC_R_SUCCESS); 949 } 950 951 if (key->func->generate == NULL) { 952 dst_key_free(&key); 953 return (DST_R_UNSUPPORTEDALG); 954 } 955 956 ret = key->func->generate(key, param, callback); 957 if (ret != ISC_R_SUCCESS) { 958 dst_key_free(&key); 959 return (ret); 960 } 961 962 ret = computeid(key); 963 if (ret != ISC_R_SUCCESS) { 964 dst_key_free(&key); 965 return (ret); 966 } 967 968 *keyp = key; 969 return (ISC_R_SUCCESS); 970 } 971 972 isc_result_t 973 dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep) 974 { 975 REQUIRE(VALID_KEY(key)); 976 REQUIRE(valuep != NULL); 977 REQUIRE(type <= DST_MAX_NUMERIC); 978 if (!key->numset[type]) 979 return (ISC_R_NOTFOUND); 980 *valuep = key->nums[type]; 981 return (ISC_R_SUCCESS); 982 } 983 984 void 985 dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value) 986 { 987 REQUIRE(VALID_KEY(key)); 988 REQUIRE(type <= DST_MAX_NUMERIC); 989 key->nums[type] = value; 990 key->numset[type] = ISC_TRUE; 991 } 992 993 void 994 dst_key_unsetnum(dst_key_t *key, int type) 995 { 996 REQUIRE(VALID_KEY(key)); 997 REQUIRE(type <= DST_MAX_NUMERIC); 998 key->numset[type] = ISC_FALSE; 999 } 1000 1001 isc_result_t 1002 dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) { 1003 REQUIRE(VALID_KEY(key)); 1004 REQUIRE(timep != NULL); 1005 REQUIRE(type <= DST_MAX_TIMES); 1006 if (!key->timeset[type]) 1007 return (ISC_R_NOTFOUND); 1008 *timep = key->times[type]; 1009 return (ISC_R_SUCCESS); 1010 } 1011 1012 void 1013 dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) { 1014 REQUIRE(VALID_KEY(key)); 1015 REQUIRE(type <= DST_MAX_TIMES); 1016 key->times[type] = when; 1017 key->timeset[type] = ISC_TRUE; 1018 } 1019 1020 void 1021 dst_key_unsettime(dst_key_t *key, int type) { 1022 REQUIRE(VALID_KEY(key)); 1023 REQUIRE(type <= DST_MAX_TIMES); 1024 key->timeset[type] = ISC_FALSE; 1025 } 1026 1027 isc_result_t 1028 dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) { 1029 REQUIRE(VALID_KEY(key)); 1030 REQUIRE(majorp != NULL); 1031 REQUIRE(minorp != NULL); 1032 *majorp = key->fmt_major; 1033 *minorp = key->fmt_minor; 1034 return (ISC_R_SUCCESS); 1035 } 1036 1037 void 1038 dst_key_setprivateformat(dst_key_t *key, int major, int minor) { 1039 REQUIRE(VALID_KEY(key)); 1040 key->fmt_major = major; 1041 key->fmt_minor = minor; 1042 } 1043 1044 static isc_boolean_t 1045 comparekeys(const dst_key_t *key1, const dst_key_t *key2, 1046 isc_boolean_t match_revoked_key, 1047 isc_boolean_t (*compare)(const dst_key_t *key1, 1048 const dst_key_t *key2)) 1049 { 1050 REQUIRE(dst_initialized == ISC_TRUE); 1051 REQUIRE(VALID_KEY(key1)); 1052 REQUIRE(VALID_KEY(key2)); 1053 1054 if (key1 == key2) 1055 return (ISC_TRUE); 1056 1057 if (key1 == NULL || key2 == NULL) 1058 return (ISC_FALSE); 1059 1060 if (key1->key_alg != key2->key_alg) 1061 return (ISC_FALSE); 1062 1063 if (key1->key_id != key2->key_id) { 1064 if (!match_revoked_key) 1065 return (ISC_FALSE); 1066 if (key1->key_alg == DST_ALG_RSAMD5) 1067 return (ISC_FALSE); 1068 if ((key1->key_flags & DNS_KEYFLAG_REVOKE) == 1069 (key2->key_flags & DNS_KEYFLAG_REVOKE)) 1070 return (ISC_FALSE); 1071 if (key1->key_id != key2->key_rid && 1072 key1->key_rid != key2->key_id) 1073 return (ISC_FALSE); 1074 } 1075 1076 if (compare != NULL) 1077 return (compare(key1, key2)); 1078 else 1079 return (ISC_FALSE); 1080 } 1081 1082 1083 /* 1084 * Compares only the public portion of two keys, by converting them 1085 * both to wire format and comparing the results. 1086 */ 1087 static isc_boolean_t 1088 pub_compare(const dst_key_t *key1, const dst_key_t *key2) { 1089 isc_result_t result; 1090 unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE]; 1091 isc_buffer_t b1, b2; 1092 isc_region_t r1, r2; 1093 1094 isc_buffer_init(&b1, buf1, sizeof(buf1)); 1095 result = dst_key_todns(key1, &b1); 1096 if (result != ISC_R_SUCCESS) 1097 return (ISC_FALSE); 1098 /* Zero out flags. */ 1099 buf1[0] = buf1[1] = 0; 1100 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) 1101 isc_buffer_subtract(&b1, 2); 1102 1103 isc_buffer_init(&b2, buf2, sizeof(buf2)); 1104 result = dst_key_todns(key2, &b2); 1105 if (result != ISC_R_SUCCESS) 1106 return (ISC_FALSE); 1107 /* Zero out flags. */ 1108 buf2[0] = buf2[1] = 0; 1109 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) 1110 isc_buffer_subtract(&b2, 2); 1111 1112 isc_buffer_usedregion(&b1, &r1); 1113 /* Remove extended flags. */ 1114 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1115 memmove(&buf1[4], &buf1[6], r1.length - 6); 1116 r1.length -= 2; 1117 } 1118 1119 isc_buffer_usedregion(&b2, &r2); 1120 /* Remove extended flags. */ 1121 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1122 memmove(&buf2[4], &buf2[6], r2.length - 6); 1123 r2.length -= 2; 1124 } 1125 return (ISC_TF(isc_region_compare(&r1, &r2) == 0)); 1126 } 1127 1128 isc_boolean_t 1129 dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) { 1130 return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare)); 1131 } 1132 1133 isc_boolean_t 1134 dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2, 1135 isc_boolean_t match_revoked_key) 1136 { 1137 return (comparekeys(key1, key2, match_revoked_key, pub_compare)); 1138 } 1139 1140 1141 isc_boolean_t 1142 dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { 1143 REQUIRE(dst_initialized == ISC_TRUE); 1144 REQUIRE(VALID_KEY(key1)); 1145 REQUIRE(VALID_KEY(key2)); 1146 1147 if (key1 == key2) 1148 return (ISC_TRUE); 1149 if (key1 == NULL || key2 == NULL) 1150 return (ISC_FALSE); 1151 if (key1->key_alg == key2->key_alg && 1152 key1->func->paramcompare != NULL && 1153 key1->func->paramcompare(key1, key2) == ISC_TRUE) 1154 return (ISC_TRUE); 1155 else 1156 return (ISC_FALSE); 1157 } 1158 1159 void 1160 dst_key_attach(dst_key_t *source, dst_key_t **target) { 1161 1162 REQUIRE(dst_initialized == ISC_TRUE); 1163 REQUIRE(target != NULL && *target == NULL); 1164 REQUIRE(VALID_KEY(source)); 1165 1166 isc_refcount_increment(&source->refs, NULL); 1167 *target = source; 1168 } 1169 1170 void 1171 dst_key_free(dst_key_t **keyp) { 1172 isc_mem_t *mctx; 1173 dst_key_t *key; 1174 unsigned int refs; 1175 1176 REQUIRE(dst_initialized == ISC_TRUE); 1177 REQUIRE(keyp != NULL && VALID_KEY(*keyp)); 1178 1179 key = *keyp; 1180 mctx = key->mctx; 1181 1182 isc_refcount_decrement(&key->refs, &refs); 1183 if (refs != 0) 1184 return; 1185 1186 isc_refcount_destroy(&key->refs); 1187 if (key->keydata.generic != NULL) { 1188 INSIST(key->func->destroy != NULL); 1189 key->func->destroy(key); 1190 } 1191 if (key->engine != NULL) 1192 isc_mem_free(mctx, key->engine); 1193 if (key->label != NULL) 1194 isc_mem_free(mctx, key->label); 1195 dns_name_free(key->key_name, mctx); 1196 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); 1197 if (key->key_tkeytoken) { 1198 isc_buffer_free(&key->key_tkeytoken); 1199 } 1200 memset(key, 0, sizeof(dst_key_t)); 1201 isc_mem_putanddetach(&mctx, key, sizeof(dst_key_t)); 1202 *keyp = NULL; 1203 } 1204 1205 isc_boolean_t 1206 dst_key_isprivate(const dst_key_t *key) { 1207 REQUIRE(VALID_KEY(key)); 1208 INSIST(key->func->isprivate != NULL); 1209 return (key->func->isprivate(key)); 1210 } 1211 1212 isc_result_t 1213 dst_key_buildfilename(const dst_key_t *key, int type, 1214 const char *directory, isc_buffer_t *out) { 1215 1216 REQUIRE(VALID_KEY(key)); 1217 REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC || 1218 type == 0); 1219 1220 return (buildfilename(key->key_name, key->key_id, key->key_alg, 1221 type, directory, out)); 1222 } 1223 1224 isc_result_t 1225 dst_key_sigsize(const dst_key_t *key, unsigned int *n) { 1226 REQUIRE(dst_initialized == ISC_TRUE); 1227 REQUIRE(VALID_KEY(key)); 1228 REQUIRE(n != NULL); 1229 1230 /* XXXVIX this switch statement is too sparse to gen a jump table. */ 1231 switch (key->key_alg) { 1232 case DST_ALG_RSAMD5: 1233 case DST_ALG_RSASHA1: 1234 case DST_ALG_NSEC3RSASHA1: 1235 case DST_ALG_RSASHA256: 1236 case DST_ALG_RSASHA512: 1237 *n = (key->key_size + 7) / 8; 1238 break; 1239 case DST_ALG_DSA: 1240 case DST_ALG_NSEC3DSA: 1241 *n = DNS_SIG_DSASIGSIZE; 1242 break; 1243 case DST_ALG_ECCGOST: 1244 *n = DNS_SIG_GOSTSIGSIZE; 1245 break; 1246 case DST_ALG_ECDSA256: 1247 *n = DNS_SIG_ECDSA256SIZE; 1248 break; 1249 case DST_ALG_ECDSA384: 1250 *n = DNS_SIG_ECDSA384SIZE; 1251 break; 1252 case DST_ALG_HMACMD5: 1253 *n = 16; 1254 break; 1255 case DST_ALG_HMACSHA1: 1256 *n = ISC_SHA1_DIGESTLENGTH; 1257 break; 1258 case DST_ALG_HMACSHA224: 1259 *n = ISC_SHA224_DIGESTLENGTH; 1260 break; 1261 case DST_ALG_HMACSHA256: 1262 *n = ISC_SHA256_DIGESTLENGTH; 1263 break; 1264 case DST_ALG_HMACSHA384: 1265 *n = ISC_SHA384_DIGESTLENGTH; 1266 break; 1267 case DST_ALG_HMACSHA512: 1268 *n = ISC_SHA512_DIGESTLENGTH; 1269 break; 1270 case DST_ALG_GSSAPI: 1271 *n = 128; /*%< XXX */ 1272 break; 1273 case DST_ALG_DH: 1274 default: 1275 return (DST_R_UNSUPPORTEDALG); 1276 } 1277 return (ISC_R_SUCCESS); 1278 } 1279 1280 isc_result_t 1281 dst_key_secretsize(const dst_key_t *key, unsigned int *n) { 1282 REQUIRE(dst_initialized == ISC_TRUE); 1283 REQUIRE(VALID_KEY(key)); 1284 REQUIRE(n != NULL); 1285 1286 if (key->key_alg == DST_ALG_DH) 1287 *n = (key->key_size + 7) / 8; 1288 else 1289 return (DST_R_UNSUPPORTEDALG); 1290 return (ISC_R_SUCCESS); 1291 } 1292 1293 /*% 1294 * Set the flags on a key, then recompute the key ID 1295 */ 1296 isc_result_t 1297 dst_key_setflags(dst_key_t *key, isc_uint32_t flags) { 1298 REQUIRE(VALID_KEY(key)); 1299 key->key_flags = flags; 1300 return (computeid(key)); 1301 } 1302 1303 void 1304 dst_key_format(const dst_key_t *key, char *cp, unsigned int size) { 1305 char namestr[DNS_NAME_FORMATSIZE]; 1306 char algstr[DNS_NAME_FORMATSIZE]; 1307 1308 dns_name_format(dst_key_name(key), namestr, sizeof(namestr)); 1309 dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr, 1310 sizeof(algstr)); 1311 snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key)); 1312 } 1313 1314 isc_result_t 1315 dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) { 1316 1317 REQUIRE(buffer != NULL && *buffer == NULL); 1318 REQUIRE(length != NULL && *length == 0); 1319 REQUIRE(VALID_KEY(key)); 1320 1321 if (key->func->dump == NULL) 1322 return (ISC_R_NOTIMPLEMENTED); 1323 return (key->func->dump(key, mctx, buffer, length)); 1324 } 1325 1326 isc_result_t 1327 dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags, 1328 unsigned int protocol, dns_rdataclass_t rdclass, 1329 isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) 1330 { 1331 isc_result_t result; 1332 dst_key_t *key; 1333 1334 REQUIRE(dst_initialized == ISC_TRUE); 1335 REQUIRE(keyp != NULL && *keyp == NULL); 1336 1337 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) 1338 return (DST_R_UNSUPPORTEDALG); 1339 1340 if (dst_t_func[alg]->restore == NULL) 1341 return (ISC_R_NOTIMPLEMENTED); 1342 1343 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 1344 if (key == NULL) 1345 return (ISC_R_NOMEMORY); 1346 1347 result = (dst_t_func[alg]->restore)(key, keystr); 1348 if (result == ISC_R_SUCCESS) 1349 *keyp = key; 1350 else 1351 dst_key_free(&key); 1352 1353 return (result); 1354 } 1355 1356 /*** 1357 *** Static methods 1358 ***/ 1359 1360 /*% 1361 * Allocates a key structure and fills in some of the fields. 1362 */ 1363 static dst_key_t * 1364 get_key_struct(dns_name_t *name, unsigned int alg, 1365 unsigned int flags, unsigned int protocol, 1366 unsigned int bits, dns_rdataclass_t rdclass, 1367 dns_ttl_t ttl, isc_mem_t *mctx) 1368 { 1369 dst_key_t *key; 1370 isc_result_t result; 1371 int i; 1372 1373 key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t)); 1374 if (key == NULL) 1375 return (NULL); 1376 1377 memset(key, 0, sizeof(dst_key_t)); 1378 1379 key->key_name = isc_mem_get(mctx, sizeof(dns_name_t)); 1380 if (key->key_name == NULL) { 1381 isc_mem_put(mctx, key, sizeof(dst_key_t)); 1382 return (NULL); 1383 } 1384 1385 dns_name_init(key->key_name, NULL); 1386 result = dns_name_dup(name, mctx, key->key_name); 1387 if (result != ISC_R_SUCCESS) { 1388 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); 1389 isc_mem_put(mctx, key, sizeof(dst_key_t)); 1390 return (NULL); 1391 } 1392 1393 result = isc_refcount_init(&key->refs, 1); 1394 if (result != ISC_R_SUCCESS) { 1395 dns_name_free(key->key_name, mctx); 1396 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); 1397 isc_mem_put(mctx, key, sizeof(dst_key_t)); 1398 return (NULL); 1399 } 1400 isc_mem_attach(mctx, &key->mctx); 1401 key->key_alg = alg; 1402 key->key_flags = flags; 1403 key->key_proto = protocol; 1404 key->keydata.generic = NULL; 1405 key->key_size = bits; 1406 key->key_class = rdclass; 1407 key->key_ttl = ttl; 1408 key->func = dst_t_func[alg]; 1409 key->fmt_major = 0; 1410 key->fmt_minor = 0; 1411 for (i = 0; i < (DST_MAX_TIMES + 1); i++) { 1412 key->times[i] = 0; 1413 key->timeset[i] = ISC_FALSE; 1414 } 1415 key->inactive = ISC_FALSE; 1416 key->magic = KEY_MAGIC; 1417 return (key); 1418 } 1419 1420 isc_boolean_t 1421 dst_key_inactive(const dst_key_t *key) { 1422 1423 REQUIRE(VALID_KEY(key)); 1424 1425 return (key->inactive); 1426 } 1427 1428 void 1429 dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive) { 1430 1431 REQUIRE(VALID_KEY(key)); 1432 1433 key->inactive = inactive; 1434 } 1435 1436 /*% 1437 * Reads a public key from disk 1438 */ 1439 isc_result_t 1440 dst_key_read_public(const char *filename, int type, 1441 isc_mem_t *mctx, dst_key_t **keyp) 1442 { 1443 u_char rdatabuf[DST_KEY_MAXSIZE]; 1444 isc_buffer_t b; 1445 dns_fixedname_t name; 1446 isc_lex_t *lex = NULL; 1447 isc_token_t token; 1448 isc_result_t ret; 1449 dns_rdata_t rdata = DNS_RDATA_INIT; 1450 unsigned int opt = ISC_LEXOPT_DNSMULTILINE; 1451 dns_rdataclass_t rdclass = dns_rdataclass_in; 1452 isc_lexspecials_t specials; 1453 isc_uint32_t ttl = 0; 1454 isc_result_t result; 1455 dns_rdatatype_t keytype; 1456 1457 /* 1458 * Open the file and read its formatted contents 1459 * File format: 1460 * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key> 1461 */ 1462 1463 /* 1500 should be large enough for any key */ 1464 ret = isc_lex_create(mctx, 1500, &lex); 1465 if (ret != ISC_R_SUCCESS) 1466 goto cleanup; 1467 1468 memset(specials, 0, sizeof(specials)); 1469 specials['('] = 1; 1470 specials[')'] = 1; 1471 specials['"'] = 1; 1472 isc_lex_setspecials(lex, specials); 1473 isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); 1474 1475 ret = isc_lex_openfile(lex, filename); 1476 if (ret != ISC_R_SUCCESS) 1477 goto cleanup; 1478 1479 #define NEXTTOKEN(lex, opt, token) { \ 1480 ret = isc_lex_gettoken(lex, opt, token); \ 1481 if (ret != ISC_R_SUCCESS) \ 1482 goto cleanup; \ 1483 } 1484 1485 #define BADTOKEN() { \ 1486 ret = ISC_R_UNEXPECTEDTOKEN; \ 1487 goto cleanup; \ 1488 } 1489 1490 /* Read the domain name */ 1491 NEXTTOKEN(lex, opt, &token); 1492 if (token.type != isc_tokentype_string) 1493 BADTOKEN(); 1494 1495 /* 1496 * We don't support "@" in .key files. 1497 */ 1498 if (!strcmp(DST_AS_STR(token), "@")) 1499 BADTOKEN(); 1500 1501 dns_fixedname_init(&name); 1502 isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token))); 1503 isc_buffer_add(&b, strlen(DST_AS_STR(token))); 1504 ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, 1505 0, NULL); 1506 if (ret != ISC_R_SUCCESS) 1507 goto cleanup; 1508 1509 /* Read the next word: either TTL, class, or 'KEY' */ 1510 NEXTTOKEN(lex, opt, &token); 1511 1512 if (token.type != isc_tokentype_string) 1513 BADTOKEN(); 1514 1515 /* If it's a TTL, read the next one */ 1516 result = dns_ttl_fromtext(&token.value.as_textregion, &ttl); 1517 if (result == ISC_R_SUCCESS) 1518 NEXTTOKEN(lex, opt, &token); 1519 1520 if (token.type != isc_tokentype_string) 1521 BADTOKEN(); 1522 1523 ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion); 1524 if (ret == ISC_R_SUCCESS) 1525 NEXTTOKEN(lex, opt, &token); 1526 1527 if (token.type != isc_tokentype_string) 1528 BADTOKEN(); 1529 1530 if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0) 1531 keytype = dns_rdatatype_dnskey; 1532 else if (strcasecmp(DST_AS_STR(token), "KEY") == 0) 1533 keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */ 1534 else 1535 BADTOKEN(); 1536 1537 if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) || 1538 ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) { 1539 ret = DST_R_BADKEYTYPE; 1540 goto cleanup; 1541 } 1542 1543 isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf)); 1544 ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL, 1545 ISC_FALSE, mctx, &b, NULL); 1546 if (ret != ISC_R_SUCCESS) 1547 goto cleanup; 1548 1549 ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx, 1550 keyp); 1551 if (ret != ISC_R_SUCCESS) 1552 goto cleanup; 1553 1554 dst_key_setttl(*keyp, ttl); 1555 1556 cleanup: 1557 if (lex != NULL) 1558 isc_lex_destroy(&lex); 1559 return (ret); 1560 } 1561 1562 static isc_boolean_t 1563 issymmetric(const dst_key_t *key) { 1564 REQUIRE(dst_initialized == ISC_TRUE); 1565 REQUIRE(VALID_KEY(key)); 1566 1567 /* XXXVIX this switch statement is too sparse to gen a jump table. */ 1568 switch (key->key_alg) { 1569 case DST_ALG_RSAMD5: 1570 case DST_ALG_RSASHA1: 1571 case DST_ALG_NSEC3RSASHA1: 1572 case DST_ALG_RSASHA256: 1573 case DST_ALG_RSASHA512: 1574 case DST_ALG_DSA: 1575 case DST_ALG_NSEC3DSA: 1576 case DST_ALG_DH: 1577 case DST_ALG_ECCGOST: 1578 case DST_ALG_ECDSA256: 1579 case DST_ALG_ECDSA384: 1580 return (ISC_FALSE); 1581 case DST_ALG_HMACMD5: 1582 case DST_ALG_GSSAPI: 1583 return (ISC_TRUE); 1584 default: 1585 return (ISC_FALSE); 1586 } 1587 } 1588 1589 /*% 1590 * Write key timing metadata to a file pointer, preceded by 'tag' 1591 */ 1592 static void 1593 printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) { 1594 isc_result_t result; 1595 #ifdef ISC_PLATFORM_USETHREADS 1596 char output[26]; /* Minimum buffer as per ctime_r() specification. */ 1597 #else 1598 const char *output; 1599 #endif 1600 isc_stdtime_t when; 1601 time_t t; 1602 char utc[sizeof("YYYYMMDDHHSSMM")]; 1603 isc_buffer_t b; 1604 isc_region_t r; 1605 1606 result = dst_key_gettime(key, type, &when); 1607 if (result == ISC_R_NOTFOUND) 1608 return; 1609 1610 /* time_t and isc_stdtime_t might be different sizes */ 1611 t = when; 1612 #ifdef ISC_PLATFORM_USETHREADS 1613 #ifdef WIN32 1614 if (ctime_s(output, sizeof(output), &t) != 0) 1615 goto error; 1616 #else 1617 if (ctime_r(&t, output) == NULL) 1618 goto error; 1619 #endif 1620 #else 1621 output = ctime(&t); 1622 #endif 1623 1624 isc_buffer_init(&b, utc, sizeof(utc)); 1625 result = dns_time32_totext(when, &b); 1626 if (result != ISC_R_SUCCESS) 1627 goto error; 1628 1629 isc_buffer_usedregion(&b, &r); 1630 fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base, 1631 (int)strlen(output) - 1, output); 1632 return; 1633 1634 error: 1635 fprintf(stream, "%s: (set, unable to display)\n", tag); 1636 } 1637 1638 /*% 1639 * Writes a public key to disk in DNS format. 1640 */ 1641 static isc_result_t 1642 write_public_key(const dst_key_t *key, int type, const char *directory) { 1643 FILE *fp; 1644 isc_buffer_t keyb, textb, fileb, classb; 1645 isc_region_t r; 1646 char filename[ISC_DIR_NAMEMAX]; 1647 unsigned char key_array[DST_KEY_MAXSIZE]; 1648 char text_array[DST_KEY_MAXTEXTSIZE]; 1649 char class_array[10]; 1650 isc_result_t ret; 1651 dns_rdata_t rdata = DNS_RDATA_INIT; 1652 isc_fsaccess_t access; 1653 1654 REQUIRE(VALID_KEY(key)); 1655 1656 isc_buffer_init(&keyb, key_array, sizeof(key_array)); 1657 isc_buffer_init(&textb, text_array, sizeof(text_array)); 1658 isc_buffer_init(&classb, class_array, sizeof(class_array)); 1659 1660 ret = dst_key_todns(key, &keyb); 1661 if (ret != ISC_R_SUCCESS) 1662 return (ret); 1663 1664 isc_buffer_usedregion(&keyb, &r); 1665 dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r); 1666 1667 ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb); 1668 if (ret != ISC_R_SUCCESS) 1669 return (DST_R_INVALIDPUBLICKEY); 1670 1671 ret = dns_rdataclass_totext(key->key_class, &classb); 1672 if (ret != ISC_R_SUCCESS) 1673 return (DST_R_INVALIDPUBLICKEY); 1674 1675 /* 1676 * Make the filename. 1677 */ 1678 isc_buffer_init(&fileb, filename, sizeof(filename)); 1679 ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb); 1680 if (ret != ISC_R_SUCCESS) 1681 return (ret); 1682 1683 /* 1684 * Create public key file. 1685 */ 1686 if ((fp = fopen(filename, "w")) == NULL) 1687 return (DST_R_WRITEERROR); 1688 1689 if (issymmetric(key)) { 1690 access = 0; 1691 isc_fsaccess_add(ISC_FSACCESS_OWNER, 1692 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, 1693 &access); 1694 (void)isc_fsaccess_set(filename, access); 1695 } 1696 1697 /* Write key information in comments */ 1698 if ((type & DST_TYPE_KEY) == 0) { 1699 fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ", 1700 (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ? 1701 "revoked " : 1702 "", 1703 (key->key_flags & DNS_KEYFLAG_KSK) != 0 ? 1704 "key" : 1705 "zone", 1706 key->key_id); 1707 ret = dns_name_print(key->key_name, fp); 1708 if (ret != ISC_R_SUCCESS) { 1709 fclose(fp); 1710 return (ret); 1711 } 1712 fputc('\n', fp); 1713 1714 printtime(key, DST_TIME_CREATED, "; Created", fp); 1715 printtime(key, DST_TIME_PUBLISH, "; Publish", fp); 1716 printtime(key, DST_TIME_ACTIVATE, "; Activate", fp); 1717 printtime(key, DST_TIME_REVOKE, "; Revoke", fp); 1718 printtime(key, DST_TIME_INACTIVE, "; Inactive", fp); 1719 printtime(key, DST_TIME_DELETE, "; Delete", fp); 1720 } 1721 1722 /* Now print the actual key */ 1723 ret = dns_name_print(key->key_name, fp); 1724 fprintf(fp, " "); 1725 1726 if (key->key_ttl != 0) 1727 fprintf(fp, "%d ", key->key_ttl); 1728 1729 isc_buffer_usedregion(&classb, &r); 1730 if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length) 1731 ret = DST_R_WRITEERROR; 1732 1733 if ((type & DST_TYPE_KEY) != 0) 1734 fprintf(fp, " KEY "); 1735 else 1736 fprintf(fp, " DNSKEY "); 1737 1738 isc_buffer_usedregion(&textb, &r); 1739 if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length) 1740 ret = DST_R_WRITEERROR; 1741 1742 fputc('\n', fp); 1743 fflush(fp); 1744 if (ferror(fp)) 1745 ret = DST_R_WRITEERROR; 1746 fclose(fp); 1747 1748 return (ret); 1749 } 1750 1751 static isc_result_t 1752 buildfilename(dns_name_t *name, dns_keytag_t id, 1753 unsigned int alg, unsigned int type, 1754 const char *directory, isc_buffer_t *out) 1755 { 1756 const char *suffix = ""; 1757 unsigned int len; 1758 isc_result_t result; 1759 1760 REQUIRE(out != NULL); 1761 if ((type & DST_TYPE_PRIVATE) != 0) 1762 suffix = ".private"; 1763 else if (type == DST_TYPE_PUBLIC) 1764 suffix = ".key"; 1765 if (directory != NULL) { 1766 if (isc_buffer_availablelength(out) < strlen(directory)) 1767 return (ISC_R_NOSPACE); 1768 isc_buffer_putstr(out, directory); 1769 if (strlen(directory) > 0U && 1770 directory[strlen(directory) - 1] != '/') 1771 isc_buffer_putstr(out, "/"); 1772 } 1773 if (isc_buffer_availablelength(out) < 1) 1774 return (ISC_R_NOSPACE); 1775 isc_buffer_putstr(out, "K"); 1776 result = dns_name_tofilenametext(name, ISC_FALSE, out); 1777 if (result != ISC_R_SUCCESS) 1778 return (result); 1779 len = 1 + 3 + 1 + 5 + strlen(suffix) + 1; 1780 if (isc_buffer_availablelength(out) < len) 1781 return (ISC_R_NOSPACE); 1782 sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id, 1783 suffix); 1784 isc_buffer_add(out, len); 1785 1786 return (ISC_R_SUCCESS); 1787 } 1788 1789 static isc_result_t 1790 computeid(dst_key_t *key) { 1791 isc_buffer_t dnsbuf; 1792 unsigned char dns_array[DST_KEY_MAXSIZE]; 1793 isc_region_t r; 1794 isc_result_t ret; 1795 1796 isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array)); 1797 ret = dst_key_todns(key, &dnsbuf); 1798 if (ret != ISC_R_SUCCESS) 1799 return (ret); 1800 1801 isc_buffer_usedregion(&dnsbuf, &r); 1802 key->key_id = dst_region_computeid(&r, key->key_alg); 1803 key->key_rid = dst_region_computerid(&r, key->key_alg); 1804 return (ISC_R_SUCCESS); 1805 } 1806 1807 static isc_result_t 1808 frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags, 1809 unsigned int protocol, dns_rdataclass_t rdclass, 1810 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) 1811 { 1812 dst_key_t *key; 1813 isc_result_t ret; 1814 1815 REQUIRE(dns_name_isabsolute(name)); 1816 REQUIRE(source != NULL); 1817 REQUIRE(mctx != NULL); 1818 REQUIRE(keyp != NULL && *keyp == NULL); 1819 1820 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 1821 if (key == NULL) 1822 return (ISC_R_NOMEMORY); 1823 1824 if (isc_buffer_remaininglength(source) > 0) { 1825 ret = algorithm_status(alg); 1826 if (ret != ISC_R_SUCCESS) { 1827 dst_key_free(&key); 1828 return (ret); 1829 } 1830 if (key->func->fromdns == NULL) { 1831 dst_key_free(&key); 1832 return (DST_R_UNSUPPORTEDALG); 1833 } 1834 1835 ret = key->func->fromdns(key, source); 1836 if (ret != ISC_R_SUCCESS) { 1837 dst_key_free(&key); 1838 return (ret); 1839 } 1840 } 1841 1842 *keyp = key; 1843 return (ISC_R_SUCCESS); 1844 } 1845 1846 static isc_result_t 1847 algorithm_status(unsigned int alg) { 1848 REQUIRE(dst_initialized == ISC_TRUE); 1849 1850 if (dst_algorithm_supported(alg)) 1851 return (ISC_R_SUCCESS); 1852 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO) 1853 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || 1854 alg == DST_ALG_DSA || alg == DST_ALG_DH || 1855 alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA || 1856 alg == DST_ALG_NSEC3RSASHA1 || 1857 alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 || 1858 alg == DST_ALG_ECCGOST || 1859 alg == DST_ALG_ECDSA256 || alg == DST_ALG_ECDSA384) 1860 return (DST_R_NOCRYPTO); 1861 #endif 1862 return (DST_R_UNSUPPORTEDALG); 1863 } 1864 1865 static isc_result_t 1866 addsuffix(char *filename, int len, const char *odirname, 1867 const char *ofilename, const char *suffix) 1868 { 1869 int olen = strlen(ofilename); 1870 int n; 1871 1872 if (olen > 1 && ofilename[olen - 1] == '.') 1873 olen -= 1; 1874 else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0) 1875 olen -= 8; 1876 else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) 1877 olen -= 4; 1878 1879 if (odirname == NULL) 1880 n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix); 1881 else 1882 n = snprintf(filename, len, "%s/%.*s%s", 1883 odirname, olen, ofilename, suffix); 1884 if (n < 0) 1885 return (ISC_R_FAILURE); 1886 if (n >= len) 1887 return (ISC_R_NOSPACE); 1888 return (ISC_R_SUCCESS); 1889 } 1890 1891 isc_result_t 1892 dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { 1893 unsigned int flags = dst_entropy_flags; 1894 1895 if (dst_entropy_pool == NULL) 1896 return (ISC_R_FAILURE); 1897 1898 if (len == 0) 1899 return (ISC_R_SUCCESS); 1900 1901 #ifdef PKCS11CRYPTO 1902 UNUSED(pseudo); 1903 UNUSED(flags); 1904 return (pk11_rand_bytes(buf, len)); 1905 #else /* PKCS11CRYPTO */ 1906 if (pseudo) 1907 flags &= ~ISC_ENTROPY_GOODONLY; 1908 else 1909 flags |= ISC_ENTROPY_BLOCKING; 1910 return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags)); 1911 #endif /* PKCS11CRYPTO */ 1912 } 1913 1914 unsigned int 1915 dst__entropy_status(void) { 1916 #ifndef PKCS11CRYPTO 1917 #ifdef GSSAPI 1918 unsigned int flags = dst_entropy_flags; 1919 isc_result_t ret; 1920 unsigned char buf[32]; 1921 static isc_boolean_t first = ISC_TRUE; 1922 1923 if (dst_entropy_pool == NULL) 1924 return (0); 1925 1926 if (first) { 1927 /* Someone believes RAND_status() initializes the PRNG */ 1928 flags &= ~ISC_ENTROPY_GOODONLY; 1929 ret = isc_entropy_getdata(dst_entropy_pool, buf, 1930 sizeof(buf), NULL, flags); 1931 INSIST(ret == ISC_R_SUCCESS); 1932 isc_entropy_putdata(dst_entropy_pool, buf, 1933 sizeof(buf), 2 * sizeof(buf)); 1934 first = ISC_FALSE; 1935 } 1936 #endif 1937 return (isc_entropy_status(dst_entropy_pool)); 1938 #else 1939 return (0); 1940 #endif 1941 } 1942 1943 isc_buffer_t * 1944 dst_key_tkeytoken(const dst_key_t *key) { 1945 REQUIRE(VALID_KEY(key)); 1946 return (key->key_tkeytoken); 1947 } 1948