1143731Sdougb/* 2254402Serwin * Portions Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") 3143731Sdougb * Portions Copyright (C) 1999-2003 Internet Software Consortium. 4193149Sdougb * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6193149Sdougb * purpose with or without fee is hereby granted, provided that the above 7193149Sdougb * copyright notice and this permission notice appear in all copies. 8193149Sdougb * 9193149Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 10193149Sdougb * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11193149Sdougb * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 12193149Sdougb * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13193149Sdougb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14193149Sdougb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 15193149Sdougb * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16193149Sdougb * 17143731Sdougb * Portions Copyright (C) 1995-2000 by Network Associates, Inc. 18143731Sdougb * 19193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 20143731Sdougb * purpose with or without fee is hereby granted, provided that the above 21143731Sdougb * copyright notice and this permission notice appear in all copies. 22143731Sdougb * 23143731Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS 24143731Sdougb * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 25143731Sdougb * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE 26143731Sdougb * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 27143731Sdougb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 28143731Sdougb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 29143731Sdougb * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30143731Sdougb */ 31143731Sdougb 32143731Sdougb/* 33143731Sdougb * Principal Author: Brian Wellington 34254897Serwin * $Id: dst_api.c,v 1.65 2011/10/20 21:20:02 marka Exp $ 35143731Sdougb */ 36143731Sdougb 37170222Sdougb/*! \file */ 38170222Sdougb 39143731Sdougb#include <config.h> 40143731Sdougb 41143731Sdougb#include <stdlib.h> 42224092Sdougb#include <time.h> 43143731Sdougb 44143731Sdougb#include <isc/buffer.h> 45143731Sdougb#include <isc/dir.h> 46143731Sdougb#include <isc/entropy.h> 47143731Sdougb#include <isc/fsaccess.h> 48170222Sdougb#include <isc/hmacsha.h> 49143731Sdougb#include <isc/lex.h> 50143731Sdougb#include <isc/mem.h> 51143731Sdougb#include <isc/once.h> 52224092Sdougb#include <isc/platform.h> 53143731Sdougb#include <isc/print.h> 54218384Sdougb#include <isc/refcount.h> 55143731Sdougb#include <isc/random.h> 56143731Sdougb#include <isc/string.h> 57143731Sdougb#include <isc/time.h> 58143731Sdougb#include <isc/util.h> 59245163Serwin#include <isc/file.h> 60143731Sdougb 61254897Serwin#define DST_KEY_INTERNAL 62254897Serwin 63143731Sdougb#include <dns/fixedname.h> 64143731Sdougb#include <dns/keyvalues.h> 65143731Sdougb#include <dns/name.h> 66143731Sdougb#include <dns/rdata.h> 67143731Sdougb#include <dns/rdataclass.h> 68143731Sdougb#include <dns/ttl.h> 69143731Sdougb#include <dns/types.h> 70143731Sdougb 71143731Sdougb#include <dst/result.h> 72143731Sdougb 73143731Sdougb#include "dst_internal.h" 74143731Sdougb 75143731Sdougb#define DST_AS_STR(t) ((t).value.as_textregion.base) 76143731Sdougb 77143731Sdougbstatic dst_func_t *dst_t_func[DST_MAX_ALGS]; 78224092Sdougb#ifdef BIND9 79143731Sdougbstatic isc_entropy_t *dst_entropy_pool = NULL; 80224092Sdougb#endif 81143731Sdougbstatic unsigned int dst_entropy_flags = 0; 82143731Sdougbstatic isc_boolean_t dst_initialized = ISC_FALSE; 83143731Sdougb 84193149Sdougbvoid gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); 85193149Sdougb 86143731Sdougbisc_mem_t *dst__memory_pool = NULL; 87143731Sdougb 88143731Sdougb/* 89143731Sdougb * Static functions. 90143731Sdougb */ 91143731Sdougbstatic dst_key_t * get_key_struct(dns_name_t *name, 92143731Sdougb unsigned int alg, 93143731Sdougb unsigned int flags, 94143731Sdougb unsigned int protocol, 95143731Sdougb unsigned int bits, 96143731Sdougb dns_rdataclass_t rdclass, 97254897Serwin dns_ttl_t ttl, 98143731Sdougb isc_mem_t *mctx); 99143731Sdougbstatic isc_result_t write_public_key(const dst_key_t *key, int type, 100143731Sdougb const char *directory); 101143731Sdougbstatic isc_result_t buildfilename(dns_name_t *name, 102143731Sdougb dns_keytag_t id, 103143731Sdougb unsigned int alg, 104143731Sdougb unsigned int type, 105143731Sdougb const char *directory, 106143731Sdougb isc_buffer_t *out); 107143731Sdougbstatic isc_result_t computeid(dst_key_t *key); 108143731Sdougbstatic isc_result_t frombuffer(dns_name_t *name, 109143731Sdougb unsigned int alg, 110143731Sdougb unsigned int flags, 111143731Sdougb unsigned int protocol, 112143731Sdougb dns_rdataclass_t rdclass, 113143731Sdougb isc_buffer_t *source, 114143731Sdougb isc_mem_t *mctx, 115143731Sdougb dst_key_t **keyp); 116143731Sdougb 117143731Sdougbstatic isc_result_t algorithm_status(unsigned int alg); 118143731Sdougb 119224092Sdougbstatic isc_result_t addsuffix(char *filename, int len, 120224092Sdougb const char *dirname, const char *ofilename, 121224092Sdougb const char *suffix); 122143731Sdougb 123224092Sdougb#define RETERR(x) \ 124143731Sdougb do { \ 125143731Sdougb result = (x); \ 126143731Sdougb if (result != ISC_R_SUCCESS) \ 127143731Sdougb goto out; \ 128143731Sdougb } while (0) 129143731Sdougb 130143731Sdougb#define CHECKALG(alg) \ 131143731Sdougb do { \ 132143731Sdougb isc_result_t _r; \ 133143731Sdougb _r = algorithm_status(alg); \ 134143731Sdougb if (_r != ISC_R_SUCCESS) \ 135143731Sdougb return (_r); \ 136143731Sdougb } while (0); \ 137143731Sdougb 138224092Sdougb#if defined(OPENSSL) && defined(BIND9) 139170222Sdougbstatic void * 140170222Sdougbdefault_memalloc(void *arg, size_t size) { 141193149Sdougb UNUSED(arg); 142193149Sdougb if (size == 0U) 143193149Sdougb size = 1; 144193149Sdougb return (malloc(size)); 145170222Sdougb} 146170222Sdougb 147170222Sdougbstatic void 148170222Sdougbdefault_memfree(void *arg, void *ptr) { 149193149Sdougb UNUSED(arg); 150193149Sdougb free(ptr); 151170222Sdougb} 152193149Sdougb#endif 153170222Sdougb 154143731Sdougbisc_result_t 155143731Sdougbdst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { 156224092Sdougb return (dst_lib_init2(mctx, ectx, NULL, eflags)); 157224092Sdougb} 158224092Sdougb 159224092Sdougbisc_result_t 160224092Sdougbdst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx, 161224092Sdougb const char *engine, unsigned int eflags) { 162143731Sdougb isc_result_t result; 163143731Sdougb 164224092Sdougb REQUIRE(mctx != NULL); 165224092Sdougb#ifdef BIND9 166224092Sdougb REQUIRE(ectx != NULL); 167224092Sdougb#else 168224092Sdougb UNUSED(ectx); 169224092Sdougb#endif 170143731Sdougb REQUIRE(dst_initialized == ISC_FALSE); 171143731Sdougb 172224092Sdougb#ifndef OPENSSL 173224092Sdougb UNUSED(engine); 174224092Sdougb#endif 175224092Sdougb 176143731Sdougb dst__memory_pool = NULL; 177143731Sdougb 178224092Sdougb#if defined(OPENSSL) && defined(BIND9) 179143731Sdougb UNUSED(mctx); 180143731Sdougb /* 181143731Sdougb * When using --with-openssl, there seems to be no good way of not 182143731Sdougb * leaking memory due to the openssl error handling mechanism. 183143731Sdougb * Avoid assertions by using a local memory context and not checking 184170222Sdougb * for leaks on exit. Note: as there are leaks we cannot use 185170222Sdougb * ISC_MEMFLAG_INTERNAL as it will free up memory still being used 186170222Sdougb * by libcrypto. 187143731Sdougb */ 188170222Sdougb result = isc_mem_createx2(0, 0, default_memalloc, default_memfree, 189170222Sdougb NULL, &dst__memory_pool, 0); 190143731Sdougb if (result != ISC_R_SUCCESS) 191143731Sdougb return (result); 192193149Sdougb isc_mem_setname(dst__memory_pool, "dst", NULL); 193224092Sdougb#ifndef OPENSSL_LEAKS 194143731Sdougb isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE); 195224092Sdougb#endif 196143731Sdougb#else 197143731Sdougb isc_mem_attach(mctx, &dst__memory_pool); 198143731Sdougb#endif 199224092Sdougb#ifdef BIND9 200143731Sdougb isc_entropy_attach(ectx, &dst_entropy_pool); 201224092Sdougb#endif 202143731Sdougb dst_entropy_flags = eflags; 203143731Sdougb 204143731Sdougb dst_result_register(); 205143731Sdougb 206143731Sdougb memset(dst_t_func, 0, sizeof(dst_t_func)); 207143731Sdougb RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5])); 208170222Sdougb RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1])); 209170222Sdougb RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224])); 210170222Sdougb RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256])); 211170222Sdougb RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384])); 212170222Sdougb RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); 213143731Sdougb#ifdef OPENSSL 214224092Sdougb RETERR(dst__openssl_init(engine)); 215204619Sdougb RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5], 216204619Sdougb DST_ALG_RSAMD5)); 217204619Sdougb RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1], 218204619Sdougb DST_ALG_RSASHA1)); 219204619Sdougb RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1], 220204619Sdougb DST_ALG_NSEC3RSASHA1)); 221204619Sdougb RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256], 222204619Sdougb DST_ALG_RSASHA256)); 223204619Sdougb RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512], 224204619Sdougb DST_ALG_RSASHA512)); 225143731Sdougb#ifdef HAVE_OPENSSL_DSA 226143731Sdougb RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA])); 227193149Sdougb RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); 228143731Sdougb#endif 229143731Sdougb RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH])); 230224092Sdougb#ifdef HAVE_OPENSSL_GOST 231224092Sdougb RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST])); 232224092Sdougb#endif 233245163Serwin#ifdef HAVE_OPENSSL_ECDSA 234245163Serwin RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256])); 235245163Serwin RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384])); 236245163Serwin#endif 237143731Sdougb#endif /* OPENSSL */ 238143731Sdougb#ifdef GSSAPI 239143731Sdougb RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI])); 240143731Sdougb#endif 241143731Sdougb dst_initialized = ISC_TRUE; 242143731Sdougb return (ISC_R_SUCCESS); 243143731Sdougb 244143731Sdougb out: 245224092Sdougb /* avoid immediate crash! */ 246224092Sdougb dst_initialized = ISC_TRUE; 247143731Sdougb dst_lib_destroy(); 248143731Sdougb return (result); 249143731Sdougb} 250143731Sdougb 251143731Sdougbvoid 252143731Sdougbdst_lib_destroy(void) { 253143731Sdougb int i; 254143731Sdougb RUNTIME_CHECK(dst_initialized == ISC_TRUE); 255143731Sdougb dst_initialized = ISC_FALSE; 256143731Sdougb 257143731Sdougb for (i = 0; i < DST_MAX_ALGS; i++) 258143731Sdougb if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL) 259143731Sdougb dst_t_func[i]->cleanup(); 260143731Sdougb#ifdef OPENSSL 261143731Sdougb dst__openssl_destroy(); 262143731Sdougb#endif 263143731Sdougb if (dst__memory_pool != NULL) 264143731Sdougb isc_mem_detach(&dst__memory_pool); 265224092Sdougb#ifdef BIND9 266143731Sdougb if (dst_entropy_pool != NULL) 267143731Sdougb isc_entropy_detach(&dst_entropy_pool); 268224092Sdougb#endif 269143731Sdougb} 270143731Sdougb 271143731Sdougbisc_boolean_t 272143731Sdougbdst_algorithm_supported(unsigned int alg) { 273143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 274143731Sdougb 275143731Sdougb if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) 276143731Sdougb return (ISC_FALSE); 277143731Sdougb return (ISC_TRUE); 278143731Sdougb} 279143731Sdougb 280143731Sdougbisc_result_t 281143731Sdougbdst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) { 282254402Serwin return (dst_context_create2(key, mctx, 283254402Serwin DNS_LOGCATEGORY_GENERAL, dctxp)); 284254402Serwin} 285254402Serwin 286254402Serwinisc_result_t 287254402Serwindst_context_create2(dst_key_t *key, isc_mem_t *mctx, 288254402Serwin isc_logcategory_t *category, dst_context_t **dctxp) { 289143731Sdougb dst_context_t *dctx; 290143731Sdougb isc_result_t result; 291143731Sdougb 292143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 293143731Sdougb REQUIRE(VALID_KEY(key)); 294143731Sdougb REQUIRE(mctx != NULL); 295143731Sdougb REQUIRE(dctxp != NULL && *dctxp == NULL); 296143731Sdougb 297143731Sdougb if (key->func->createctx == NULL) 298143731Sdougb return (DST_R_UNSUPPORTEDALG); 299193149Sdougb if (key->keydata.generic == NULL) 300143731Sdougb return (DST_R_NULLKEY); 301143731Sdougb 302143731Sdougb dctx = isc_mem_get(mctx, sizeof(dst_context_t)); 303143731Sdougb if (dctx == NULL) 304143731Sdougb return (ISC_R_NOMEMORY); 305143731Sdougb dctx->key = key; 306143731Sdougb dctx->mctx = mctx; 307254402Serwin dctx->category = category; 308143731Sdougb result = key->func->createctx(key, dctx); 309143731Sdougb if (result != ISC_R_SUCCESS) { 310143731Sdougb isc_mem_put(mctx, dctx, sizeof(dst_context_t)); 311143731Sdougb return (result); 312143731Sdougb } 313143731Sdougb dctx->magic = CTX_MAGIC; 314143731Sdougb *dctxp = dctx; 315143731Sdougb return (ISC_R_SUCCESS); 316143731Sdougb} 317143731Sdougb 318143731Sdougbvoid 319143731Sdougbdst_context_destroy(dst_context_t **dctxp) { 320143731Sdougb dst_context_t *dctx; 321143731Sdougb 322143731Sdougb REQUIRE(dctxp != NULL && VALID_CTX(*dctxp)); 323143731Sdougb 324143731Sdougb dctx = *dctxp; 325143731Sdougb INSIST(dctx->key->func->destroyctx != NULL); 326143731Sdougb dctx->key->func->destroyctx(dctx); 327143731Sdougb dctx->magic = 0; 328143731Sdougb isc_mem_put(dctx->mctx, dctx, sizeof(dst_context_t)); 329143731Sdougb *dctxp = NULL; 330143731Sdougb} 331143731Sdougb 332143731Sdougbisc_result_t 333143731Sdougbdst_context_adddata(dst_context_t *dctx, const isc_region_t *data) { 334143731Sdougb REQUIRE(VALID_CTX(dctx)); 335143731Sdougb REQUIRE(data != NULL); 336143731Sdougb INSIST(dctx->key->func->adddata != NULL); 337143731Sdougb 338143731Sdougb return (dctx->key->func->adddata(dctx, data)); 339143731Sdougb} 340143731Sdougb 341143731Sdougbisc_result_t 342143731Sdougbdst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) { 343143731Sdougb dst_key_t *key; 344143731Sdougb 345143731Sdougb REQUIRE(VALID_CTX(dctx)); 346143731Sdougb REQUIRE(sig != NULL); 347143731Sdougb 348143731Sdougb key = dctx->key; 349143731Sdougb CHECKALG(key->key_alg); 350193149Sdougb if (key->keydata.generic == NULL) 351143731Sdougb return (DST_R_NULLKEY); 352193149Sdougb 353143731Sdougb if (key->func->sign == NULL) 354143731Sdougb return (DST_R_NOTPRIVATEKEY); 355143731Sdougb if (key->func->isprivate == NULL || 356143731Sdougb key->func->isprivate(key) == ISC_FALSE) 357143731Sdougb return (DST_R_NOTPRIVATEKEY); 358143731Sdougb 359143731Sdougb return (key->func->sign(dctx, sig)); 360143731Sdougb} 361143731Sdougb 362143731Sdougbisc_result_t 363143731Sdougbdst_context_verify(dst_context_t *dctx, isc_region_t *sig) { 364143731Sdougb REQUIRE(VALID_CTX(dctx)); 365143731Sdougb REQUIRE(sig != NULL); 366143731Sdougb 367143731Sdougb CHECKALG(dctx->key->key_alg); 368193149Sdougb if (dctx->key->keydata.generic == NULL) 369143731Sdougb return (DST_R_NULLKEY); 370143731Sdougb if (dctx->key->func->verify == NULL) 371143731Sdougb return (DST_R_NOTPUBLICKEY); 372143731Sdougb 373143731Sdougb return (dctx->key->func->verify(dctx, sig)); 374143731Sdougb} 375143731Sdougb 376143731Sdougbisc_result_t 377254897Serwindst_context_verify2(dst_context_t *dctx, unsigned int maxbits, 378254897Serwin isc_region_t *sig) 379254897Serwin{ 380254897Serwin REQUIRE(VALID_CTX(dctx)); 381254897Serwin REQUIRE(sig != NULL); 382254897Serwin 383254897Serwin CHECKALG(dctx->key->key_alg); 384254897Serwin if (dctx->key->keydata.generic == NULL) 385254897Serwin return (DST_R_NULLKEY); 386254897Serwin if (dctx->key->func->verify == NULL && 387254897Serwin dctx->key->func->verify2 == NULL) 388254897Serwin return (DST_R_NOTPUBLICKEY); 389254897Serwin 390254897Serwin return (dctx->key->func->verify2 != NULL ? 391254897Serwin dctx->key->func->verify2(dctx, maxbits, sig) : 392254897Serwin dctx->key->func->verify(dctx, sig)); 393254897Serwin} 394254897Serwin 395254897Serwinisc_result_t 396143731Sdougbdst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv, 397143731Sdougb isc_buffer_t *secret) 398143731Sdougb{ 399143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 400143731Sdougb REQUIRE(VALID_KEY(pub) && VALID_KEY(priv)); 401143731Sdougb REQUIRE(secret != NULL); 402143731Sdougb 403143731Sdougb CHECKALG(pub->key_alg); 404143731Sdougb CHECKALG(priv->key_alg); 405143731Sdougb 406193149Sdougb if (pub->keydata.generic == NULL || priv->keydata.generic == NULL) 407143731Sdougb return (DST_R_NULLKEY); 408143731Sdougb 409143731Sdougb if (pub->key_alg != priv->key_alg || 410143731Sdougb pub->func->computesecret == NULL || 411143731Sdougb priv->func->computesecret == NULL) 412143731Sdougb return (DST_R_KEYCANNOTCOMPUTESECRET); 413143731Sdougb 414143731Sdougb if (dst_key_isprivate(priv) == ISC_FALSE) 415143731Sdougb return (DST_R_NOTPRIVATEKEY); 416143731Sdougb 417143731Sdougb return (pub->func->computesecret(pub, priv, secret)); 418143731Sdougb} 419143731Sdougb 420143731Sdougbisc_result_t 421143731Sdougbdst_key_tofile(const dst_key_t *key, int type, const char *directory) { 422143731Sdougb isc_result_t ret = ISC_R_SUCCESS; 423143731Sdougb 424143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 425143731Sdougb REQUIRE(VALID_KEY(key)); 426143731Sdougb REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 427143731Sdougb 428143731Sdougb CHECKALG(key->key_alg); 429143731Sdougb 430143731Sdougb if (key->func->tofile == NULL) 431143731Sdougb return (DST_R_UNSUPPORTEDALG); 432143731Sdougb 433143731Sdougb if (type & DST_TYPE_PUBLIC) { 434143731Sdougb ret = write_public_key(key, type, directory); 435143731Sdougb if (ret != ISC_R_SUCCESS) 436143731Sdougb return (ret); 437143731Sdougb } 438143731Sdougb 439143731Sdougb if ((type & DST_TYPE_PRIVATE) && 440143731Sdougb (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY) 441143731Sdougb return (key->func->tofile(key, directory)); 442143731Sdougb else 443143731Sdougb return (ISC_R_SUCCESS); 444143731Sdougb} 445143731Sdougb 446262706Serwinvoid 447262706Serwindst_key_setexternal(dst_key_t *key, isc_boolean_t value) { 448262706Serwin key->external = value; 449262706Serwin} 450262706Serwin 451262706Serwinisc_boolean_t 452262706Serwindst_key_isexternal(dst_key_t *key) { 453262706Serwin return (key->external); 454262706Serwin} 455262706Serwin 456143731Sdougbisc_result_t 457143731Sdougbdst_key_fromfile(dns_name_t *name, dns_keytag_t id, 458143731Sdougb unsigned int alg, int type, const char *directory, 459143731Sdougb isc_mem_t *mctx, dst_key_t **keyp) 460143731Sdougb{ 461143731Sdougb char filename[ISC_DIR_NAMEMAX]; 462143731Sdougb isc_buffer_t b; 463143731Sdougb dst_key_t *key; 464143731Sdougb isc_result_t result; 465143731Sdougb 466143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 467143731Sdougb REQUIRE(dns_name_isabsolute(name)); 468143731Sdougb REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 469143731Sdougb REQUIRE(mctx != NULL); 470143731Sdougb REQUIRE(keyp != NULL && *keyp == NULL); 471143731Sdougb 472143731Sdougb CHECKALG(alg); 473143731Sdougb 474143731Sdougb isc_buffer_init(&b, filename, sizeof(filename)); 475143731Sdougb result = buildfilename(name, id, alg, type, directory, &b); 476143731Sdougb if (result != ISC_R_SUCCESS) 477143731Sdougb return (result); 478143731Sdougb 479143731Sdougb key = NULL; 480224092Sdougb result = dst_key_fromnamedfile(filename, NULL, type, mctx, &key); 481143731Sdougb if (result != ISC_R_SUCCESS) 482143731Sdougb return (result); 483143731Sdougb 484143731Sdougb result = computeid(key); 485143731Sdougb if (result != ISC_R_SUCCESS) { 486143731Sdougb dst_key_free(&key); 487143731Sdougb return (result); 488143731Sdougb } 489143731Sdougb 490193149Sdougb if (!dns_name_equal(name, key->key_name) || id != key->key_id || 491193149Sdougb alg != key->key_alg) { 492143731Sdougb dst_key_free(&key); 493143731Sdougb return (DST_R_INVALIDPRIVATEKEY); 494143731Sdougb } 495143731Sdougb 496143731Sdougb *keyp = key; 497143731Sdougb return (ISC_R_SUCCESS); 498143731Sdougb} 499143731Sdougb 500143731Sdougbisc_result_t 501224092Sdougbdst_key_fromnamedfile(const char *filename, const char *dirname, 502224092Sdougb int type, isc_mem_t *mctx, dst_key_t **keyp) 503143731Sdougb{ 504143731Sdougb isc_result_t result; 505143731Sdougb dst_key_t *pubkey = NULL, *key = NULL; 506143731Sdougb char *newfilename = NULL; 507143731Sdougb int newfilenamelen = 0; 508143731Sdougb isc_lex_t *lex = NULL; 509143731Sdougb 510143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 511143731Sdougb REQUIRE(filename != NULL); 512143731Sdougb REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0); 513143731Sdougb REQUIRE(mctx != NULL); 514143731Sdougb REQUIRE(keyp != NULL && *keyp == NULL); 515143731Sdougb 516224092Sdougb /* If an absolute path is specified, don't use the key directory */ 517224092Sdougb#ifndef WIN32 518224092Sdougb if (filename[0] == '/') 519224092Sdougb dirname = NULL; 520224092Sdougb#else /* WIN32 */ 521224092Sdougb if (filename[0] == '/' || filename[0] == '\\') 522224092Sdougb dirname = NULL; 523224092Sdougb#endif 524224092Sdougb 525170222Sdougb newfilenamelen = strlen(filename) + 5; 526224092Sdougb if (dirname != NULL) 527224092Sdougb newfilenamelen += strlen(dirname) + 1; 528170222Sdougb newfilename = isc_mem_get(mctx, newfilenamelen); 529170222Sdougb if (newfilename == NULL) 530170222Sdougb return (ISC_R_NOMEMORY); 531224092Sdougb result = addsuffix(newfilename, newfilenamelen, 532224092Sdougb dirname, filename, ".key"); 533170222Sdougb INSIST(result == ISC_R_SUCCESS); 534170222Sdougb 535170222Sdougb result = dst_key_read_public(newfilename, type, mctx, &pubkey); 536170222Sdougb isc_mem_put(mctx, newfilename, newfilenamelen); 537170222Sdougb newfilename = NULL; 538254402Serwin RETERR(result); 539143731Sdougb 540143731Sdougb if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC || 541193149Sdougb (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) { 542143731Sdougb result = computeid(pubkey); 543143731Sdougb if (result != ISC_R_SUCCESS) { 544143731Sdougb dst_key_free(&pubkey); 545143731Sdougb return (result); 546143731Sdougb } 547143731Sdougb 548143731Sdougb *keyp = pubkey; 549143731Sdougb return (ISC_R_SUCCESS); 550143731Sdougb } 551143731Sdougb 552143731Sdougb result = algorithm_status(pubkey->key_alg); 553143731Sdougb if (result != ISC_R_SUCCESS) { 554143731Sdougb dst_key_free(&pubkey); 555143731Sdougb return (result); 556143731Sdougb } 557143731Sdougb 558143731Sdougb key = get_key_struct(pubkey->key_name, pubkey->key_alg, 559143731Sdougb pubkey->key_flags, pubkey->key_proto, 0, 560254897Serwin pubkey->key_class, pubkey->key_ttl, mctx); 561224092Sdougb if (key == NULL) { 562224092Sdougb dst_key_free(&pubkey); 563143731Sdougb return (ISC_R_NOMEMORY); 564224092Sdougb } 565143731Sdougb 566143731Sdougb if (key->func->parse == NULL) 567143731Sdougb RETERR(DST_R_UNSUPPORTEDALG); 568143731Sdougb 569143731Sdougb newfilenamelen = strlen(filename) + 9; 570224092Sdougb if (dirname != NULL) 571224092Sdougb newfilenamelen += strlen(dirname) + 1; 572143731Sdougb newfilename = isc_mem_get(mctx, newfilenamelen); 573143731Sdougb if (newfilename == NULL) 574143731Sdougb RETERR(ISC_R_NOMEMORY); 575224092Sdougb result = addsuffix(newfilename, newfilenamelen, 576224092Sdougb dirname, filename, ".private"); 577143731Sdougb INSIST(result == ISC_R_SUCCESS); 578143731Sdougb 579143731Sdougb RETERR(isc_lex_create(mctx, 1500, &lex)); 580143731Sdougb RETERR(isc_lex_openfile(lex, newfilename)); 581143731Sdougb isc_mem_put(mctx, newfilename, newfilenamelen); 582143731Sdougb 583224092Sdougb RETERR(key->func->parse(key, lex, pubkey)); 584143731Sdougb isc_lex_destroy(&lex); 585143731Sdougb 586143731Sdougb RETERR(computeid(key)); 587143731Sdougb 588224092Sdougb if (pubkey->key_id != key->key_id) 589143731Sdougb RETERR(DST_R_INVALIDPRIVATEKEY); 590224092Sdougb dst_key_free(&pubkey); 591143731Sdougb 592143731Sdougb *keyp = key; 593143731Sdougb return (ISC_R_SUCCESS); 594218384Sdougb 595143731Sdougb out: 596224092Sdougb if (pubkey != NULL) 597224092Sdougb dst_key_free(&pubkey); 598143731Sdougb if (newfilename != NULL) 599143731Sdougb isc_mem_put(mctx, newfilename, newfilenamelen); 600143731Sdougb if (lex != NULL) 601143731Sdougb isc_lex_destroy(&lex); 602254402Serwin if (key != NULL) 603254402Serwin dst_key_free(&key); 604143731Sdougb return (result); 605143731Sdougb} 606143731Sdougb 607143731Sdougbisc_result_t 608143731Sdougbdst_key_todns(const dst_key_t *key, isc_buffer_t *target) { 609143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 610143731Sdougb REQUIRE(VALID_KEY(key)); 611143731Sdougb REQUIRE(target != NULL); 612143731Sdougb 613143731Sdougb CHECKALG(key->key_alg); 614143731Sdougb 615143731Sdougb if (key->func->todns == NULL) 616143731Sdougb return (DST_R_UNSUPPORTEDALG); 617143731Sdougb 618143731Sdougb if (isc_buffer_availablelength(target) < 4) 619143731Sdougb return (ISC_R_NOSPACE); 620143731Sdougb isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff)); 621143731Sdougb isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto); 622143731Sdougb isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg); 623143731Sdougb 624143731Sdougb if (key->key_flags & DNS_KEYFLAG_EXTENDED) { 625143731Sdougb if (isc_buffer_availablelength(target) < 2) 626143731Sdougb return (ISC_R_NOSPACE); 627143731Sdougb isc_buffer_putuint16(target, 628143731Sdougb (isc_uint16_t)((key->key_flags >> 16) 629143731Sdougb & 0xffff)); 630143731Sdougb } 631143731Sdougb 632193149Sdougb if (key->keydata.generic == NULL) /*%< NULL KEY */ 633143731Sdougb return (ISC_R_SUCCESS); 634143731Sdougb 635143731Sdougb return (key->func->todns(key, target)); 636143731Sdougb} 637143731Sdougb 638143731Sdougbisc_result_t 639143731Sdougbdst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass, 640143731Sdougb isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) 641143731Sdougb{ 642143731Sdougb isc_uint8_t alg, proto; 643143731Sdougb isc_uint32_t flags, extflags; 644143731Sdougb dst_key_t *key = NULL; 645234010Sdougb dns_keytag_t id, rid; 646143731Sdougb isc_region_t r; 647143731Sdougb isc_result_t result; 648143731Sdougb 649143731Sdougb REQUIRE(dst_initialized); 650143731Sdougb 651143731Sdougb isc_buffer_remainingregion(source, &r); 652143731Sdougb 653143731Sdougb if (isc_buffer_remaininglength(source) < 4) 654143731Sdougb return (DST_R_INVALIDPUBLICKEY); 655143731Sdougb flags = isc_buffer_getuint16(source); 656143731Sdougb proto = isc_buffer_getuint8(source); 657143731Sdougb alg = isc_buffer_getuint8(source); 658143731Sdougb 659143731Sdougb id = dst_region_computeid(&r, alg); 660234010Sdougb rid = dst_region_computerid(&r, alg); 661143731Sdougb 662143731Sdougb if (flags & DNS_KEYFLAG_EXTENDED) { 663143731Sdougb if (isc_buffer_remaininglength(source) < 2) 664143731Sdougb return (DST_R_INVALIDPUBLICKEY); 665143731Sdougb extflags = isc_buffer_getuint16(source); 666143731Sdougb flags |= (extflags << 16); 667143731Sdougb } 668143731Sdougb 669143731Sdougb result = frombuffer(name, alg, flags, proto, rdclass, source, 670143731Sdougb mctx, &key); 671143731Sdougb if (result != ISC_R_SUCCESS) 672143731Sdougb return (result); 673143731Sdougb key->key_id = id; 674234010Sdougb key->key_rid = rid; 675143731Sdougb 676143731Sdougb *keyp = key; 677143731Sdougb return (ISC_R_SUCCESS); 678143731Sdougb} 679143731Sdougb 680143731Sdougbisc_result_t 681143731Sdougbdst_key_frombuffer(dns_name_t *name, unsigned int alg, 682143731Sdougb unsigned int flags, unsigned int protocol, 683143731Sdougb dns_rdataclass_t rdclass, 684143731Sdougb isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) 685143731Sdougb{ 686143731Sdougb dst_key_t *key = NULL; 687143731Sdougb isc_result_t result; 688143731Sdougb 689143731Sdougb REQUIRE(dst_initialized); 690143731Sdougb 691143731Sdougb result = frombuffer(name, alg, flags, protocol, rdclass, source, 692143731Sdougb mctx, &key); 693143731Sdougb if (result != ISC_R_SUCCESS) 694143731Sdougb return (result); 695143731Sdougb 696143731Sdougb result = computeid(key); 697143731Sdougb if (result != ISC_R_SUCCESS) { 698143731Sdougb dst_key_free(&key); 699143731Sdougb return (result); 700143731Sdougb } 701143731Sdougb 702143731Sdougb *keyp = key; 703143731Sdougb return (ISC_R_SUCCESS); 704143731Sdougb} 705143731Sdougb 706143731Sdougbisc_result_t 707143731Sdougbdst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) { 708143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 709143731Sdougb REQUIRE(VALID_KEY(key)); 710143731Sdougb REQUIRE(target != NULL); 711143731Sdougb 712143731Sdougb CHECKALG(key->key_alg); 713143731Sdougb 714143731Sdougb if (key->func->todns == NULL) 715143731Sdougb return (DST_R_UNSUPPORTEDALG); 716143731Sdougb 717143731Sdougb return (key->func->todns(key, target)); 718143731Sdougb} 719143731Sdougb 720143731Sdougbisc_result_t 721143731Sdougbdst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) { 722143731Sdougb isc_lex_t *lex = NULL; 723143731Sdougb isc_result_t result = ISC_R_SUCCESS; 724143731Sdougb 725143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 726143731Sdougb REQUIRE(VALID_KEY(key)); 727143731Sdougb REQUIRE(!dst_key_isprivate(key)); 728143731Sdougb REQUIRE(buffer != NULL); 729143731Sdougb 730143731Sdougb if (key->func->parse == NULL) 731143731Sdougb RETERR(DST_R_UNSUPPORTEDALG); 732143731Sdougb 733143731Sdougb RETERR(isc_lex_create(key->mctx, 1500, &lex)); 734143731Sdougb RETERR(isc_lex_openbuffer(lex, buffer)); 735224092Sdougb RETERR(key->func->parse(key, lex, NULL)); 736143731Sdougb out: 737143731Sdougb if (lex != NULL) 738143731Sdougb isc_lex_destroy(&lex); 739143731Sdougb return (result); 740143731Sdougb} 741143731Sdougb 742193149Sdougbgss_ctx_id_t 743193149Sdougbdst_key_getgssctx(const dst_key_t *key) 744193149Sdougb{ 745193149Sdougb REQUIRE(key != NULL); 746193149Sdougb 747193149Sdougb return (key->keydata.gssctx); 748193149Sdougb} 749193149Sdougb 750143731Sdougbisc_result_t 751193149Sdougbdst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx, 752224092Sdougb dst_key_t **keyp, isc_region_t *intoken) 753143731Sdougb{ 754143731Sdougb dst_key_t *key; 755224092Sdougb isc_result_t result; 756143731Sdougb 757193149Sdougb REQUIRE(gssctx != NULL); 758143731Sdougb REQUIRE(keyp != NULL && *keyp == NULL); 759143731Sdougb 760143731Sdougb key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC, 761254897Serwin 0, dns_rdataclass_in, 0, mctx); 762143731Sdougb if (key == NULL) 763143731Sdougb return (ISC_R_NOMEMORY); 764193149Sdougb 765224092Sdougb if (intoken != NULL) { 766224092Sdougb /* 767224092Sdougb * Keep the token for use by external ssu rules. They may need 768224092Sdougb * to examine the PAC in the kerberos ticket. 769224092Sdougb */ 770224092Sdougb RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken, 771224092Sdougb intoken->length)); 772224092Sdougb RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken)); 773224092Sdougb } 774224092Sdougb 775193149Sdougb key->keydata.gssctx = gssctx; 776143731Sdougb *keyp = key; 777224092Sdougb result = ISC_R_SUCCESS; 778224092Sdougbout: 779224092Sdougb return result; 780143731Sdougb} 781143731Sdougb 782143731Sdougbisc_result_t 783254897Serwindst_key_buildinternal(dns_name_t *name, unsigned int alg, 784254897Serwin unsigned int bits, unsigned int flags, 785254897Serwin unsigned int protocol, dns_rdataclass_t rdclass, 786254897Serwin void *data, isc_mem_t *mctx, dst_key_t **keyp) 787254897Serwin{ 788254897Serwin dst_key_t *key; 789254897Serwin isc_result_t result; 790254897Serwin 791254897Serwin REQUIRE(dst_initialized == ISC_TRUE); 792254897Serwin REQUIRE(dns_name_isabsolute(name)); 793254897Serwin REQUIRE(mctx != NULL); 794254897Serwin REQUIRE(keyp != NULL && *keyp == NULL); 795254897Serwin REQUIRE(data != NULL); 796254897Serwin 797254897Serwin CHECKALG(alg); 798254897Serwin 799254897Serwin key = get_key_struct(name, alg, flags, protocol, bits, rdclass, 800254897Serwin 0, mctx); 801254897Serwin if (key == NULL) 802254897Serwin return (ISC_R_NOMEMORY); 803254897Serwin 804254897Serwin key->keydata.generic = data; 805254897Serwin 806254897Serwin result = computeid(key); 807254897Serwin if (result != ISC_R_SUCCESS) { 808254897Serwin dst_key_free(&key); 809254897Serwin return (result); 810254897Serwin } 811254897Serwin 812254897Serwin *keyp = key; 813254897Serwin return (ISC_R_SUCCESS); 814254897Serwin} 815254897Serwin 816254897Serwinisc_result_t 817193149Sdougbdst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags, 818193149Sdougb unsigned int protocol, dns_rdataclass_t rdclass, 819193149Sdougb const char *engine, const char *label, const char *pin, 820193149Sdougb isc_mem_t *mctx, dst_key_t **keyp) 821193149Sdougb{ 822193149Sdougb dst_key_t *key; 823193149Sdougb isc_result_t result; 824193149Sdougb 825193149Sdougb REQUIRE(dst_initialized == ISC_TRUE); 826193149Sdougb REQUIRE(dns_name_isabsolute(name)); 827193149Sdougb REQUIRE(mctx != NULL); 828193149Sdougb REQUIRE(keyp != NULL && *keyp == NULL); 829193149Sdougb REQUIRE(label != NULL); 830193149Sdougb 831193149Sdougb CHECKALG(alg); 832193149Sdougb 833254897Serwin key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 834193149Sdougb if (key == NULL) 835193149Sdougb return (ISC_R_NOMEMORY); 836193149Sdougb 837193149Sdougb if (key->func->fromlabel == NULL) { 838193149Sdougb dst_key_free(&key); 839193149Sdougb return (DST_R_UNSUPPORTEDALG); 840193149Sdougb } 841193149Sdougb 842193149Sdougb result = key->func->fromlabel(key, engine, label, pin); 843193149Sdougb if (result != ISC_R_SUCCESS) { 844193149Sdougb dst_key_free(&key); 845193149Sdougb return (result); 846193149Sdougb } 847193149Sdougb 848193149Sdougb result = computeid(key); 849193149Sdougb if (result != ISC_R_SUCCESS) { 850193149Sdougb dst_key_free(&key); 851193149Sdougb return (result); 852193149Sdougb } 853193149Sdougb 854193149Sdougb *keyp = key; 855193149Sdougb return (ISC_R_SUCCESS); 856193149Sdougb} 857193149Sdougb 858193149Sdougbisc_result_t 859143731Sdougbdst_key_generate(dns_name_t *name, unsigned int alg, 860143731Sdougb unsigned int bits, unsigned int param, 861143731Sdougb unsigned int flags, unsigned int protocol, 862143731Sdougb dns_rdataclass_t rdclass, 863143731Sdougb isc_mem_t *mctx, dst_key_t **keyp) 864143731Sdougb{ 865224092Sdougb return (dst_key_generate2(name, alg, bits, param, flags, protocol, 866224092Sdougb rdclass, mctx, keyp, NULL)); 867224092Sdougb} 868224092Sdougb 869224092Sdougbisc_result_t 870224092Sdougbdst_key_generate2(dns_name_t *name, unsigned int alg, 871224092Sdougb unsigned int bits, unsigned int param, 872224092Sdougb unsigned int flags, unsigned int protocol, 873224092Sdougb dns_rdataclass_t rdclass, 874224092Sdougb isc_mem_t *mctx, dst_key_t **keyp, 875224092Sdougb void (*callback)(int)) 876224092Sdougb{ 877143731Sdougb dst_key_t *key; 878143731Sdougb isc_result_t ret; 879143731Sdougb 880143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 881143731Sdougb REQUIRE(dns_name_isabsolute(name)); 882143731Sdougb REQUIRE(mctx != NULL); 883143731Sdougb REQUIRE(keyp != NULL && *keyp == NULL); 884143731Sdougb 885143731Sdougb CHECKALG(alg); 886143731Sdougb 887254897Serwin key = get_key_struct(name, alg, flags, protocol, bits, 888254897Serwin rdclass, 0, mctx); 889143731Sdougb if (key == NULL) 890143731Sdougb return (ISC_R_NOMEMORY); 891143731Sdougb 892170222Sdougb if (bits == 0) { /*%< NULL KEY */ 893143731Sdougb key->key_flags |= DNS_KEYTYPE_NOKEY; 894143731Sdougb *keyp = key; 895143731Sdougb return (ISC_R_SUCCESS); 896143731Sdougb } 897143731Sdougb 898143731Sdougb if (key->func->generate == NULL) { 899143731Sdougb dst_key_free(&key); 900143731Sdougb return (DST_R_UNSUPPORTEDALG); 901143731Sdougb } 902143731Sdougb 903224092Sdougb ret = key->func->generate(key, param, callback); 904143731Sdougb if (ret != ISC_R_SUCCESS) { 905143731Sdougb dst_key_free(&key); 906143731Sdougb return (ret); 907143731Sdougb } 908143731Sdougb 909143731Sdougb ret = computeid(key); 910143731Sdougb if (ret != ISC_R_SUCCESS) { 911143731Sdougb dst_key_free(&key); 912143731Sdougb return (ret); 913143731Sdougb } 914143731Sdougb 915143731Sdougb *keyp = key; 916143731Sdougb return (ISC_R_SUCCESS); 917143731Sdougb} 918143731Sdougb 919224092Sdougbisc_result_t 920224092Sdougbdst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep) 921224092Sdougb{ 922224092Sdougb REQUIRE(VALID_KEY(key)); 923224092Sdougb REQUIRE(valuep != NULL); 924224092Sdougb REQUIRE(type <= DST_MAX_NUMERIC); 925224092Sdougb if (!key->numset[type]) 926224092Sdougb return (ISC_R_NOTFOUND); 927224092Sdougb *valuep = key->nums[type]; 928224092Sdougb return (ISC_R_SUCCESS); 929224092Sdougb} 930224092Sdougb 931224092Sdougbvoid 932224092Sdougbdst_key_setnum(dst_key_t *key, int type, isc_uint32_t value) 933224092Sdougb{ 934224092Sdougb REQUIRE(VALID_KEY(key)); 935224092Sdougb REQUIRE(type <= DST_MAX_NUMERIC); 936224092Sdougb key->nums[type] = value; 937224092Sdougb key->numset[type] = ISC_TRUE; 938224092Sdougb} 939224092Sdougb 940224092Sdougbvoid 941224092Sdougbdst_key_unsetnum(dst_key_t *key, int type) 942224092Sdougb{ 943224092Sdougb REQUIRE(VALID_KEY(key)); 944224092Sdougb REQUIRE(type <= DST_MAX_NUMERIC); 945224092Sdougb key->numset[type] = ISC_FALSE; 946224092Sdougb} 947224092Sdougb 948224092Sdougbisc_result_t 949224092Sdougbdst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) { 950224092Sdougb REQUIRE(VALID_KEY(key)); 951224092Sdougb REQUIRE(timep != NULL); 952224092Sdougb REQUIRE(type <= DST_MAX_TIMES); 953224092Sdougb if (!key->timeset[type]) 954224092Sdougb return (ISC_R_NOTFOUND); 955224092Sdougb *timep = key->times[type]; 956224092Sdougb return (ISC_R_SUCCESS); 957224092Sdougb} 958224092Sdougb 959224092Sdougbvoid 960224092Sdougbdst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) { 961224092Sdougb REQUIRE(VALID_KEY(key)); 962224092Sdougb REQUIRE(type <= DST_MAX_TIMES); 963224092Sdougb key->times[type] = when; 964224092Sdougb key->timeset[type] = ISC_TRUE; 965224092Sdougb} 966224092Sdougb 967224092Sdougbvoid 968224092Sdougbdst_key_unsettime(dst_key_t *key, int type) { 969224092Sdougb REQUIRE(VALID_KEY(key)); 970224092Sdougb REQUIRE(type <= DST_MAX_TIMES); 971224092Sdougb key->timeset[type] = ISC_FALSE; 972224092Sdougb} 973224092Sdougb 974224092Sdougbisc_result_t 975224092Sdougbdst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) { 976224092Sdougb REQUIRE(VALID_KEY(key)); 977224092Sdougb REQUIRE(majorp != NULL); 978224092Sdougb REQUIRE(minorp != NULL); 979224092Sdougb *majorp = key->fmt_major; 980224092Sdougb *minorp = key->fmt_minor; 981224092Sdougb return (ISC_R_SUCCESS); 982224092Sdougb} 983224092Sdougb 984224092Sdougbvoid 985224092Sdougbdst_key_setprivateformat(dst_key_t *key, int major, int minor) { 986224092Sdougb REQUIRE(VALID_KEY(key)); 987224092Sdougb key->fmt_major = major; 988224092Sdougb key->fmt_minor = minor; 989224092Sdougb} 990224092Sdougb 991224092Sdougbstatic isc_boolean_t 992224092Sdougbcomparekeys(const dst_key_t *key1, const dst_key_t *key2, 993224092Sdougb isc_boolean_t match_revoked_key, 994224092Sdougb isc_boolean_t (*compare)(const dst_key_t *key1, 995224092Sdougb const dst_key_t *key2)) 996224092Sdougb{ 997143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 998143731Sdougb REQUIRE(VALID_KEY(key1)); 999143731Sdougb REQUIRE(VALID_KEY(key2)); 1000143731Sdougb 1001143731Sdougb if (key1 == key2) 1002143731Sdougb return (ISC_TRUE); 1003224092Sdougb 1004143731Sdougb if (key1 == NULL || key2 == NULL) 1005143731Sdougb return (ISC_FALSE); 1006224092Sdougb 1007224092Sdougb if (key1->key_alg != key2->key_alg) 1008224092Sdougb return (ISC_FALSE); 1009224092Sdougb 1010224092Sdougb if (key1->key_id != key2->key_id) { 1011224092Sdougb if (!match_revoked_key) 1012224092Sdougb return (ISC_FALSE); 1013224092Sdougb if (key1->key_alg == DST_ALG_RSAMD5) 1014224092Sdougb return (ISC_FALSE); 1015224092Sdougb if ((key1->key_flags & DNS_KEYFLAG_REVOKE) == 1016224092Sdougb (key2->key_flags & DNS_KEYFLAG_REVOKE)) 1017224092Sdougb return (ISC_FALSE); 1018234010Sdougb if (key1->key_id != key2->key_rid && 1019234010Sdougb key1->key_rid != key2->key_id) 1020224092Sdougb return (ISC_FALSE); 1021224092Sdougb } 1022224092Sdougb 1023224092Sdougb if (compare != NULL) 1024224092Sdougb return (compare(key1, key2)); 1025143731Sdougb else 1026143731Sdougb return (ISC_FALSE); 1027143731Sdougb} 1028143731Sdougb 1029224092Sdougb 1030224092Sdougb/* 1031224092Sdougb * Compares only the public portion of two keys, by converting them 1032224092Sdougb * both to wire format and comparing the results. 1033224092Sdougb */ 1034224092Sdougbstatic isc_boolean_t 1035224092Sdougbpub_compare(const dst_key_t *key1, const dst_key_t *key2) { 1036224092Sdougb isc_result_t result; 1037224092Sdougb unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE]; 1038224092Sdougb isc_buffer_t b1, b2; 1039224092Sdougb isc_region_t r1, r2; 1040224092Sdougb 1041224092Sdougb isc_buffer_init(&b1, buf1, sizeof(buf1)); 1042224092Sdougb result = dst_key_todns(key1, &b1); 1043224092Sdougb if (result != ISC_R_SUCCESS) 1044224092Sdougb return (ISC_FALSE); 1045224092Sdougb /* Zero out flags. */ 1046224092Sdougb buf1[0] = buf1[1] = 0; 1047224092Sdougb if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) 1048224092Sdougb isc_buffer_subtract(&b1, 2); 1049224092Sdougb 1050224092Sdougb isc_buffer_init(&b2, buf2, sizeof(buf2)); 1051224092Sdougb result = dst_key_todns(key2, &b2); 1052224092Sdougb if (result != ISC_R_SUCCESS) 1053224092Sdougb return (ISC_FALSE); 1054224092Sdougb /* Zero out flags. */ 1055224092Sdougb buf2[0] = buf2[1] = 0; 1056224092Sdougb if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) 1057224092Sdougb isc_buffer_subtract(&b2, 2); 1058224092Sdougb 1059224092Sdougb isc_buffer_usedregion(&b1, &r1); 1060224092Sdougb /* Remove extended flags. */ 1061224092Sdougb if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1062224092Sdougb memmove(&buf1[4], &buf1[6], r1.length - 6); 1063224092Sdougb r1.length -= 2; 1064224092Sdougb } 1065224092Sdougb 1066224092Sdougb isc_buffer_usedregion(&b2, &r2); 1067224092Sdougb /* Remove extended flags. */ 1068224092Sdougb if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) { 1069224092Sdougb memmove(&buf2[4], &buf2[6], r2.length - 6); 1070224092Sdougb r2.length -= 2; 1071224092Sdougb } 1072224092Sdougb return (ISC_TF(isc_region_compare(&r1, &r2) == 0)); 1073224092Sdougb} 1074224092Sdougb 1075143731Sdougbisc_boolean_t 1076224092Sdougbdst_key_compare(const dst_key_t *key1, const dst_key_t *key2) { 1077224092Sdougb return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare)); 1078224092Sdougb} 1079224092Sdougb 1080224092Sdougbisc_boolean_t 1081224092Sdougbdst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2, 1082224092Sdougb isc_boolean_t match_revoked_key) 1083224092Sdougb{ 1084224092Sdougb return (comparekeys(key1, key2, match_revoked_key, pub_compare)); 1085224092Sdougb} 1086224092Sdougb 1087224092Sdougb 1088224092Sdougbisc_boolean_t 1089143731Sdougbdst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) { 1090143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1091143731Sdougb REQUIRE(VALID_KEY(key1)); 1092143731Sdougb REQUIRE(VALID_KEY(key2)); 1093143731Sdougb 1094143731Sdougb if (key1 == key2) 1095143731Sdougb return (ISC_TRUE); 1096143731Sdougb if (key1 == NULL || key2 == NULL) 1097143731Sdougb return (ISC_FALSE); 1098143731Sdougb if (key1->key_alg == key2->key_alg && 1099143731Sdougb key1->func->paramcompare != NULL && 1100143731Sdougb key1->func->paramcompare(key1, key2) == ISC_TRUE) 1101143731Sdougb return (ISC_TRUE); 1102143731Sdougb else 1103143731Sdougb return (ISC_FALSE); 1104143731Sdougb} 1105143731Sdougb 1106143731Sdougbvoid 1107218384Sdougbdst_key_attach(dst_key_t *source, dst_key_t **target) { 1108218384Sdougb 1109218384Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1110218384Sdougb REQUIRE(target != NULL && *target == NULL); 1111218384Sdougb REQUIRE(VALID_KEY(source)); 1112218384Sdougb 1113218384Sdougb isc_refcount_increment(&source->refs, NULL); 1114218384Sdougb *target = source; 1115218384Sdougb} 1116218384Sdougb 1117218384Sdougbvoid 1118143731Sdougbdst_key_free(dst_key_t **keyp) { 1119143731Sdougb isc_mem_t *mctx; 1120143731Sdougb dst_key_t *key; 1121218384Sdougb unsigned int refs; 1122143731Sdougb 1123143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1124143731Sdougb REQUIRE(keyp != NULL && VALID_KEY(*keyp)); 1125143731Sdougb 1126143731Sdougb key = *keyp; 1127143731Sdougb mctx = key->mctx; 1128143731Sdougb 1129218384Sdougb isc_refcount_decrement(&key->refs, &refs); 1130218384Sdougb if (refs != 0) 1131218384Sdougb return; 1132218384Sdougb 1133218384Sdougb isc_refcount_destroy(&key->refs); 1134193149Sdougb if (key->keydata.generic != NULL) { 1135143731Sdougb INSIST(key->func->destroy != NULL); 1136143731Sdougb key->func->destroy(key); 1137143731Sdougb } 1138193149Sdougb if (key->engine != NULL) 1139193149Sdougb isc_mem_free(mctx, key->engine); 1140193149Sdougb if (key->label != NULL) 1141193149Sdougb isc_mem_free(mctx, key->label); 1142143731Sdougb dns_name_free(key->key_name, mctx); 1143143731Sdougb isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); 1144224092Sdougb if (key->key_tkeytoken) { 1145224092Sdougb isc_buffer_free(&key->key_tkeytoken); 1146224092Sdougb } 1147143731Sdougb memset(key, 0, sizeof(dst_key_t)); 1148254897Serwin isc_mem_putanddetach(&mctx, key, sizeof(dst_key_t)); 1149143731Sdougb *keyp = NULL; 1150143731Sdougb} 1151143731Sdougb 1152143731Sdougbisc_boolean_t 1153143731Sdougbdst_key_isprivate(const dst_key_t *key) { 1154143731Sdougb REQUIRE(VALID_KEY(key)); 1155143731Sdougb INSIST(key->func->isprivate != NULL); 1156143731Sdougb return (key->func->isprivate(key)); 1157143731Sdougb} 1158143731Sdougb 1159143731Sdougbisc_result_t 1160143731Sdougbdst_key_buildfilename(const dst_key_t *key, int type, 1161143731Sdougb const char *directory, isc_buffer_t *out) { 1162143731Sdougb 1163143731Sdougb REQUIRE(VALID_KEY(key)); 1164143731Sdougb REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC || 1165143731Sdougb type == 0); 1166143731Sdougb 1167143731Sdougb return (buildfilename(key->key_name, key->key_id, key->key_alg, 1168143731Sdougb type, directory, out)); 1169143731Sdougb} 1170143731Sdougb 1171143731Sdougbisc_result_t 1172143731Sdougbdst_key_sigsize(const dst_key_t *key, unsigned int *n) { 1173143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1174143731Sdougb REQUIRE(VALID_KEY(key)); 1175143731Sdougb REQUIRE(n != NULL); 1176143731Sdougb 1177143731Sdougb /* XXXVIX this switch statement is too sparse to gen a jump table. */ 1178143731Sdougb switch (key->key_alg) { 1179143731Sdougb case DST_ALG_RSAMD5: 1180143731Sdougb case DST_ALG_RSASHA1: 1181193149Sdougb case DST_ALG_NSEC3RSASHA1: 1182204619Sdougb case DST_ALG_RSASHA256: 1183204619Sdougb case DST_ALG_RSASHA512: 1184143731Sdougb *n = (key->key_size + 7) / 8; 1185143731Sdougb break; 1186143731Sdougb case DST_ALG_DSA: 1187193149Sdougb case DST_ALG_NSEC3DSA: 1188143731Sdougb *n = DNS_SIG_DSASIGSIZE; 1189143731Sdougb break; 1190224092Sdougb case DST_ALG_ECCGOST: 1191224092Sdougb *n = DNS_SIG_GOSTSIGSIZE; 1192224092Sdougb break; 1193245163Serwin case DST_ALG_ECDSA256: 1194245163Serwin *n = DNS_SIG_ECDSA256SIZE; 1195245163Serwin break; 1196245163Serwin case DST_ALG_ECDSA384: 1197245163Serwin *n = DNS_SIG_ECDSA384SIZE; 1198245163Serwin break; 1199143731Sdougb case DST_ALG_HMACMD5: 1200143731Sdougb *n = 16; 1201143731Sdougb break; 1202170222Sdougb case DST_ALG_HMACSHA1: 1203170222Sdougb *n = ISC_SHA1_DIGESTLENGTH; 1204170222Sdougb break; 1205170222Sdougb case DST_ALG_HMACSHA224: 1206170222Sdougb *n = ISC_SHA224_DIGESTLENGTH; 1207170222Sdougb break; 1208170222Sdougb case DST_ALG_HMACSHA256: 1209170222Sdougb *n = ISC_SHA256_DIGESTLENGTH; 1210170222Sdougb break; 1211170222Sdougb case DST_ALG_HMACSHA384: 1212170222Sdougb *n = ISC_SHA384_DIGESTLENGTH; 1213170222Sdougb break; 1214170222Sdougb case DST_ALG_HMACSHA512: 1215170222Sdougb *n = ISC_SHA512_DIGESTLENGTH; 1216170222Sdougb break; 1217143731Sdougb case DST_ALG_GSSAPI: 1218170222Sdougb *n = 128; /*%< XXX */ 1219143731Sdougb break; 1220143731Sdougb case DST_ALG_DH: 1221143731Sdougb default: 1222143731Sdougb return (DST_R_UNSUPPORTEDALG); 1223143731Sdougb } 1224143731Sdougb return (ISC_R_SUCCESS); 1225143731Sdougb} 1226143731Sdougb 1227143731Sdougbisc_result_t 1228143731Sdougbdst_key_secretsize(const dst_key_t *key, unsigned int *n) { 1229143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1230143731Sdougb REQUIRE(VALID_KEY(key)); 1231143731Sdougb REQUIRE(n != NULL); 1232143731Sdougb 1233143731Sdougb if (key->key_alg == DST_ALG_DH) 1234143731Sdougb *n = (key->key_size + 7) / 8; 1235143731Sdougb else 1236143731Sdougb return (DST_R_UNSUPPORTEDALG); 1237143731Sdougb return (ISC_R_SUCCESS); 1238143731Sdougb} 1239143731Sdougb 1240224092Sdougb/*% 1241224092Sdougb * Set the flags on a key, then recompute the key ID 1242224092Sdougb */ 1243224092Sdougbisc_result_t 1244224092Sdougbdst_key_setflags(dst_key_t *key, isc_uint32_t flags) { 1245224092Sdougb REQUIRE(VALID_KEY(key)); 1246224092Sdougb key->key_flags = flags; 1247224092Sdougb return (computeid(key)); 1248224092Sdougb} 1249224092Sdougb 1250224092Sdougbvoid 1251224092Sdougbdst_key_format(const dst_key_t *key, char *cp, unsigned int size) { 1252224092Sdougb char namestr[DNS_NAME_FORMATSIZE]; 1253224092Sdougb char algstr[DNS_NAME_FORMATSIZE]; 1254224092Sdougb 1255224092Sdougb dns_name_format(dst_key_name(key), namestr, sizeof(namestr)); 1256224092Sdougb dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr, 1257224092Sdougb sizeof(algstr)); 1258224092Sdougb snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key)); 1259224092Sdougb} 1260224092Sdougb 1261224092Sdougbisc_result_t 1262224092Sdougbdst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) { 1263224092Sdougb 1264224092Sdougb REQUIRE(buffer != NULL && *buffer == NULL); 1265224092Sdougb REQUIRE(length != NULL && *length == 0); 1266224092Sdougb REQUIRE(VALID_KEY(key)); 1267224092Sdougb 1268254402Serwin if (key->func->dump == NULL) 1269224092Sdougb return (ISC_R_NOTIMPLEMENTED); 1270224092Sdougb return (key->func->dump(key, mctx, buffer, length)); 1271224092Sdougb} 1272224092Sdougb 1273224092Sdougbisc_result_t 1274224092Sdougbdst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags, 1275224092Sdougb unsigned int protocol, dns_rdataclass_t rdclass, 1276224092Sdougb isc_mem_t *mctx, const char *keystr, dst_key_t **keyp) 1277224092Sdougb{ 1278224092Sdougb isc_result_t result; 1279224092Sdougb dst_key_t *key; 1280224092Sdougb 1281224092Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1282224092Sdougb REQUIRE(keyp != NULL && *keyp == NULL); 1283224092Sdougb 1284224092Sdougb if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL) 1285224092Sdougb return (DST_R_UNSUPPORTEDALG); 1286224092Sdougb 1287224092Sdougb if (dst_t_func[alg]->restore == NULL) 1288224092Sdougb return (ISC_R_NOTIMPLEMENTED); 1289224092Sdougb 1290254897Serwin key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 1291224092Sdougb if (key == NULL) 1292224092Sdougb return (ISC_R_NOMEMORY); 1293224092Sdougb 1294224092Sdougb result = (dst_t_func[alg]->restore)(key, keystr); 1295224092Sdougb if (result == ISC_R_SUCCESS) 1296224092Sdougb *keyp = key; 1297224092Sdougb else 1298224092Sdougb dst_key_free(&key); 1299224092Sdougb 1300224092Sdougb return (result); 1301224092Sdougb} 1302224092Sdougb 1303143731Sdougb/*** 1304143731Sdougb *** Static methods 1305143731Sdougb ***/ 1306143731Sdougb 1307170222Sdougb/*% 1308143731Sdougb * Allocates a key structure and fills in some of the fields. 1309143731Sdougb */ 1310143731Sdougbstatic dst_key_t * 1311143731Sdougbget_key_struct(dns_name_t *name, unsigned int alg, 1312143731Sdougb unsigned int flags, unsigned int protocol, 1313143731Sdougb unsigned int bits, dns_rdataclass_t rdclass, 1314254897Serwin dns_ttl_t ttl, isc_mem_t *mctx) 1315143731Sdougb{ 1316143731Sdougb dst_key_t *key; 1317143731Sdougb isc_result_t result; 1318224092Sdougb int i; 1319143731Sdougb 1320143731Sdougb key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t)); 1321143731Sdougb if (key == NULL) 1322143731Sdougb return (NULL); 1323143731Sdougb 1324143731Sdougb memset(key, 0, sizeof(dst_key_t)); 1325143731Sdougb 1326143731Sdougb key->key_name = isc_mem_get(mctx, sizeof(dns_name_t)); 1327143731Sdougb if (key->key_name == NULL) { 1328143731Sdougb isc_mem_put(mctx, key, sizeof(dst_key_t)); 1329143731Sdougb return (NULL); 1330143731Sdougb } 1331254402Serwin 1332143731Sdougb dns_name_init(key->key_name, NULL); 1333143731Sdougb result = dns_name_dup(name, mctx, key->key_name); 1334143731Sdougb if (result != ISC_R_SUCCESS) { 1335143731Sdougb isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); 1336143731Sdougb isc_mem_put(mctx, key, sizeof(dst_key_t)); 1337143731Sdougb return (NULL); 1338143731Sdougb } 1339254402Serwin 1340254402Serwin result = isc_refcount_init(&key->refs, 1); 1341254402Serwin if (result != ISC_R_SUCCESS) { 1342254402Serwin dns_name_free(key->key_name, mctx); 1343254402Serwin isc_mem_put(mctx, key->key_name, sizeof(dns_name_t)); 1344254402Serwin isc_mem_put(mctx, key, sizeof(dst_key_t)); 1345254402Serwin return (NULL); 1346254402Serwin } 1347254897Serwin isc_mem_attach(mctx, &key->mctx); 1348143731Sdougb key->key_alg = alg; 1349143731Sdougb key->key_flags = flags; 1350143731Sdougb key->key_proto = protocol; 1351193149Sdougb key->keydata.generic = NULL; 1352143731Sdougb key->key_size = bits; 1353143731Sdougb key->key_class = rdclass; 1354254897Serwin key->key_ttl = ttl; 1355143731Sdougb key->func = dst_t_func[alg]; 1356224092Sdougb key->fmt_major = 0; 1357224092Sdougb key->fmt_minor = 0; 1358224092Sdougb for (i = 0; i < (DST_MAX_TIMES + 1); i++) { 1359224092Sdougb key->times[i] = 0; 1360224092Sdougb key->timeset[i] = ISC_FALSE; 1361224092Sdougb } 1362262706Serwin key->inactive = ISC_FALSE; 1363254402Serwin key->magic = KEY_MAGIC; 1364143731Sdougb return (key); 1365143731Sdougb} 1366143731Sdougb 1367262706Serwinisc_boolean_t 1368262706Serwindst_key_inactive(const dst_key_t *key) { 1369262706Serwin 1370262706Serwin REQUIRE(VALID_KEY(key)); 1371262706Serwin 1372262706Serwin return (key->inactive); 1373262706Serwin} 1374262706Serwin 1375262706Serwinvoid 1376262706Serwindst_key_setinactive(dst_key_t *key, isc_boolean_t inactive) { 1377262706Serwin 1378262706Serwin REQUIRE(VALID_KEY(key)); 1379262706Serwin 1380262706Serwin key->inactive = inactive; 1381262706Serwin} 1382262706Serwin 1383170222Sdougb/*% 1384143731Sdougb * Reads a public key from disk 1385143731Sdougb */ 1386170222Sdougbisc_result_t 1387170222Sdougbdst_key_read_public(const char *filename, int type, 1388170222Sdougb isc_mem_t *mctx, dst_key_t **keyp) 1389143731Sdougb{ 1390143731Sdougb u_char rdatabuf[DST_KEY_MAXSIZE]; 1391143731Sdougb isc_buffer_t b; 1392143731Sdougb dns_fixedname_t name; 1393143731Sdougb isc_lex_t *lex = NULL; 1394143731Sdougb isc_token_t token; 1395143731Sdougb isc_result_t ret; 1396143731Sdougb dns_rdata_t rdata = DNS_RDATA_INIT; 1397143731Sdougb unsigned int opt = ISC_LEXOPT_DNSMULTILINE; 1398143731Sdougb dns_rdataclass_t rdclass = dns_rdataclass_in; 1399143731Sdougb isc_lexspecials_t specials; 1400254897Serwin isc_uint32_t ttl = 0; 1401143731Sdougb isc_result_t result; 1402143731Sdougb dns_rdatatype_t keytype; 1403143731Sdougb 1404143731Sdougb /* 1405143731Sdougb * Open the file and read its formatted contents 1406143731Sdougb * File format: 1407170222Sdougb * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key> 1408143731Sdougb */ 1409143731Sdougb 1410143731Sdougb /* 1500 should be large enough for any key */ 1411143731Sdougb ret = isc_lex_create(mctx, 1500, &lex); 1412143731Sdougb if (ret != ISC_R_SUCCESS) 1413143731Sdougb goto cleanup; 1414143731Sdougb 1415143731Sdougb memset(specials, 0, sizeof(specials)); 1416143731Sdougb specials['('] = 1; 1417143731Sdougb specials[')'] = 1; 1418143731Sdougb specials['"'] = 1; 1419143731Sdougb isc_lex_setspecials(lex, specials); 1420143731Sdougb isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE); 1421143731Sdougb 1422170222Sdougb ret = isc_lex_openfile(lex, filename); 1423143731Sdougb if (ret != ISC_R_SUCCESS) 1424143731Sdougb goto cleanup; 1425143731Sdougb 1426143731Sdougb#define NEXTTOKEN(lex, opt, token) { \ 1427143731Sdougb ret = isc_lex_gettoken(lex, opt, token); \ 1428143731Sdougb if (ret != ISC_R_SUCCESS) \ 1429143731Sdougb goto cleanup; \ 1430143731Sdougb } 1431143731Sdougb 1432143731Sdougb#define BADTOKEN() { \ 1433143731Sdougb ret = ISC_R_UNEXPECTEDTOKEN; \ 1434143731Sdougb goto cleanup; \ 1435143731Sdougb } 1436143731Sdougb 1437143731Sdougb /* Read the domain name */ 1438143731Sdougb NEXTTOKEN(lex, opt, &token); 1439143731Sdougb if (token.type != isc_tokentype_string) 1440143731Sdougb BADTOKEN(); 1441193149Sdougb 1442193149Sdougb /* 1443193149Sdougb * We don't support "@" in .key files. 1444193149Sdougb */ 1445193149Sdougb if (!strcmp(DST_AS_STR(token), "@")) 1446193149Sdougb BADTOKEN(); 1447193149Sdougb 1448143731Sdougb dns_fixedname_init(&name); 1449143731Sdougb isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token))); 1450143731Sdougb isc_buffer_add(&b, strlen(DST_AS_STR(token))); 1451143731Sdougb ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname, 1452224092Sdougb 0, NULL); 1453143731Sdougb if (ret != ISC_R_SUCCESS) 1454143731Sdougb goto cleanup; 1455143731Sdougb 1456143731Sdougb /* Read the next word: either TTL, class, or 'KEY' */ 1457143731Sdougb NEXTTOKEN(lex, opt, &token); 1458143731Sdougb 1459204619Sdougb if (token.type != isc_tokentype_string) 1460204619Sdougb BADTOKEN(); 1461204619Sdougb 1462143731Sdougb /* If it's a TTL, read the next one */ 1463143731Sdougb result = dns_ttl_fromtext(&token.value.as_textregion, &ttl); 1464143731Sdougb if (result == ISC_R_SUCCESS) 1465143731Sdougb NEXTTOKEN(lex, opt, &token); 1466143731Sdougb 1467143731Sdougb if (token.type != isc_tokentype_string) 1468143731Sdougb BADTOKEN(); 1469143731Sdougb 1470143731Sdougb ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion); 1471143731Sdougb if (ret == ISC_R_SUCCESS) 1472143731Sdougb NEXTTOKEN(lex, opt, &token); 1473143731Sdougb 1474143731Sdougb if (token.type != isc_tokentype_string) 1475143731Sdougb BADTOKEN(); 1476143731Sdougb 1477143731Sdougb if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0) 1478143731Sdougb keytype = dns_rdatatype_dnskey; 1479143731Sdougb else if (strcasecmp(DST_AS_STR(token), "KEY") == 0) 1480170222Sdougb keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */ 1481143731Sdougb else 1482143731Sdougb BADTOKEN(); 1483143731Sdougb 1484143731Sdougb if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) || 1485143731Sdougb ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) { 1486143731Sdougb ret = DST_R_BADKEYTYPE; 1487143731Sdougb goto cleanup; 1488143731Sdougb } 1489143731Sdougb 1490143731Sdougb isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf)); 1491143731Sdougb ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL, 1492143731Sdougb ISC_FALSE, mctx, &b, NULL); 1493143731Sdougb if (ret != ISC_R_SUCCESS) 1494143731Sdougb goto cleanup; 1495143731Sdougb 1496143731Sdougb ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx, 1497143731Sdougb keyp); 1498143731Sdougb if (ret != ISC_R_SUCCESS) 1499143731Sdougb goto cleanup; 1500143731Sdougb 1501254897Serwin dst_key_setttl(*keyp, ttl); 1502254897Serwin 1503143731Sdougb cleanup: 1504143731Sdougb if (lex != NULL) 1505143731Sdougb isc_lex_destroy(&lex); 1506143731Sdougb return (ret); 1507143731Sdougb} 1508143731Sdougb 1509143731Sdougbstatic isc_boolean_t 1510143731Sdougbissymmetric(const dst_key_t *key) { 1511143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1512143731Sdougb REQUIRE(VALID_KEY(key)); 1513143731Sdougb 1514143731Sdougb /* XXXVIX this switch statement is too sparse to gen a jump table. */ 1515143731Sdougb switch (key->key_alg) { 1516143731Sdougb case DST_ALG_RSAMD5: 1517143731Sdougb case DST_ALG_RSASHA1: 1518193149Sdougb case DST_ALG_NSEC3RSASHA1: 1519204619Sdougb case DST_ALG_RSASHA256: 1520204619Sdougb case DST_ALG_RSASHA512: 1521143731Sdougb case DST_ALG_DSA: 1522193149Sdougb case DST_ALG_NSEC3DSA: 1523143731Sdougb case DST_ALG_DH: 1524224092Sdougb case DST_ALG_ECCGOST: 1525245163Serwin case DST_ALG_ECDSA256: 1526245163Serwin case DST_ALG_ECDSA384: 1527143731Sdougb return (ISC_FALSE); 1528143731Sdougb case DST_ALG_HMACMD5: 1529143731Sdougb case DST_ALG_GSSAPI: 1530143731Sdougb return (ISC_TRUE); 1531143731Sdougb default: 1532143731Sdougb return (ISC_FALSE); 1533143731Sdougb } 1534143731Sdougb} 1535143731Sdougb 1536170222Sdougb/*% 1537224092Sdougb * Write key timing metadata to a file pointer, preceded by 'tag' 1538224092Sdougb */ 1539224092Sdougbstatic void 1540224092Sdougbprinttime(const dst_key_t *key, int type, const char *tag, FILE *stream) { 1541224092Sdougb isc_result_t result; 1542224092Sdougb#ifdef ISC_PLATFORM_USETHREADS 1543224092Sdougb char output[26]; /* Minimum buffer as per ctime_r() specification. */ 1544224092Sdougb#else 1545224092Sdougb const char *output; 1546224092Sdougb#endif 1547224092Sdougb isc_stdtime_t when; 1548224092Sdougb time_t t; 1549224092Sdougb char utc[sizeof("YYYYMMDDHHSSMM")]; 1550224092Sdougb isc_buffer_t b; 1551224092Sdougb isc_region_t r; 1552224092Sdougb 1553224092Sdougb result = dst_key_gettime(key, type, &when); 1554224092Sdougb if (result == ISC_R_NOTFOUND) 1555224092Sdougb return; 1556224092Sdougb 1557224092Sdougb /* time_t and isc_stdtime_t might be different sizes */ 1558224092Sdougb t = when; 1559224092Sdougb#ifdef ISC_PLATFORM_USETHREADS 1560224092Sdougb#ifdef WIN32 1561224092Sdougb if (ctime_s(output, sizeof(output), &t) != 0) 1562224092Sdougb goto error; 1563224092Sdougb#else 1564224092Sdougb if (ctime_r(&t, output) == NULL) 1565224092Sdougb goto error; 1566224092Sdougb#endif 1567224092Sdougb#else 1568224092Sdougb output = ctime(&t); 1569224092Sdougb#endif 1570224092Sdougb 1571224092Sdougb isc_buffer_init(&b, utc, sizeof(utc)); 1572224092Sdougb result = dns_time32_totext(when, &b); 1573224092Sdougb if (result != ISC_R_SUCCESS) 1574224092Sdougb goto error; 1575224092Sdougb 1576224092Sdougb isc_buffer_usedregion(&b, &r); 1577224092Sdougb fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base, 1578224092Sdougb (int)strlen(output) - 1, output); 1579224092Sdougb return; 1580224092Sdougb 1581224092Sdougb error: 1582224092Sdougb fprintf(stream, "%s: (set, unable to display)\n", tag); 1583224092Sdougb} 1584224092Sdougb 1585224092Sdougb/*% 1586143731Sdougb * Writes a public key to disk in DNS format. 1587143731Sdougb */ 1588143731Sdougbstatic isc_result_t 1589143731Sdougbwrite_public_key(const dst_key_t *key, int type, const char *directory) { 1590143731Sdougb FILE *fp; 1591143731Sdougb isc_buffer_t keyb, textb, fileb, classb; 1592143731Sdougb isc_region_t r; 1593143731Sdougb char filename[ISC_DIR_NAMEMAX]; 1594143731Sdougb unsigned char key_array[DST_KEY_MAXSIZE]; 1595143731Sdougb char text_array[DST_KEY_MAXTEXTSIZE]; 1596143731Sdougb char class_array[10]; 1597143731Sdougb isc_result_t ret; 1598143731Sdougb dns_rdata_t rdata = DNS_RDATA_INIT; 1599143731Sdougb isc_fsaccess_t access; 1600143731Sdougb 1601143731Sdougb REQUIRE(VALID_KEY(key)); 1602143731Sdougb 1603143731Sdougb isc_buffer_init(&keyb, key_array, sizeof(key_array)); 1604143731Sdougb isc_buffer_init(&textb, text_array, sizeof(text_array)); 1605143731Sdougb isc_buffer_init(&classb, class_array, sizeof(class_array)); 1606143731Sdougb 1607143731Sdougb ret = dst_key_todns(key, &keyb); 1608143731Sdougb if (ret != ISC_R_SUCCESS) 1609143731Sdougb return (ret); 1610143731Sdougb 1611143731Sdougb isc_buffer_usedregion(&keyb, &r); 1612143731Sdougb dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r); 1613143731Sdougb 1614143731Sdougb ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb); 1615143731Sdougb if (ret != ISC_R_SUCCESS) 1616143731Sdougb return (DST_R_INVALIDPUBLICKEY); 1617143731Sdougb 1618143731Sdougb ret = dns_rdataclass_totext(key->key_class, &classb); 1619143731Sdougb if (ret != ISC_R_SUCCESS) 1620143731Sdougb return (DST_R_INVALIDPUBLICKEY); 1621143731Sdougb 1622143731Sdougb /* 1623143731Sdougb * Make the filename. 1624143731Sdougb */ 1625143731Sdougb isc_buffer_init(&fileb, filename, sizeof(filename)); 1626143731Sdougb ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb); 1627143731Sdougb if (ret != ISC_R_SUCCESS) 1628143731Sdougb return (ret); 1629143731Sdougb 1630143731Sdougb /* 1631143731Sdougb * Create public key file. 1632143731Sdougb */ 1633143731Sdougb if ((fp = fopen(filename, "w")) == NULL) 1634143731Sdougb return (DST_R_WRITEERROR); 1635143731Sdougb 1636143731Sdougb if (issymmetric(key)) { 1637143731Sdougb access = 0; 1638143731Sdougb isc_fsaccess_add(ISC_FSACCESS_OWNER, 1639143731Sdougb ISC_FSACCESS_READ | ISC_FSACCESS_WRITE, 1640143731Sdougb &access); 1641143731Sdougb (void)isc_fsaccess_set(filename, access); 1642143731Sdougb } 1643143731Sdougb 1644224092Sdougb /* Write key information in comments */ 1645224092Sdougb if ((type & DST_TYPE_KEY) == 0) { 1646224092Sdougb fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ", 1647224092Sdougb (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ? 1648224092Sdougb "revoked " : 1649224092Sdougb "", 1650224092Sdougb (key->key_flags & DNS_KEYFLAG_KSK) != 0 ? 1651224092Sdougb "key" : 1652224092Sdougb "zone", 1653224092Sdougb key->key_id); 1654224092Sdougb ret = dns_name_print(key->key_name, fp); 1655224092Sdougb if (ret != ISC_R_SUCCESS) { 1656224092Sdougb fclose(fp); 1657224092Sdougb return (ret); 1658224092Sdougb } 1659224092Sdougb fputc('\n', fp); 1660224092Sdougb 1661224092Sdougb printtime(key, DST_TIME_CREATED, "; Created", fp); 1662224092Sdougb printtime(key, DST_TIME_PUBLISH, "; Publish", fp); 1663224092Sdougb printtime(key, DST_TIME_ACTIVATE, "; Activate", fp); 1664224092Sdougb printtime(key, DST_TIME_REVOKE, "; Revoke", fp); 1665224092Sdougb printtime(key, DST_TIME_INACTIVE, "; Inactive", fp); 1666224092Sdougb printtime(key, DST_TIME_DELETE, "; Delete", fp); 1667165071Sdougb } 1668143731Sdougb 1669224092Sdougb /* Now print the actual key */ 1670224092Sdougb ret = dns_name_print(key->key_name, fp); 1671143731Sdougb fprintf(fp, " "); 1672143731Sdougb 1673254897Serwin if (key->key_ttl != 0) 1674254897Serwin fprintf(fp, "%d ", key->key_ttl); 1675254897Serwin 1676143731Sdougb isc_buffer_usedregion(&classb, &r); 1677234010Sdougb if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length) 1678234010Sdougb ret = DST_R_WRITEERROR; 1679143731Sdougb 1680143731Sdougb if ((type & DST_TYPE_KEY) != 0) 1681143731Sdougb fprintf(fp, " KEY "); 1682143731Sdougb else 1683143731Sdougb fprintf(fp, " DNSKEY "); 1684143731Sdougb 1685143731Sdougb isc_buffer_usedregion(&textb, &r); 1686234010Sdougb if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length) 1687234010Sdougb ret = DST_R_WRITEERROR; 1688143731Sdougb 1689143731Sdougb fputc('\n', fp); 1690193149Sdougb fflush(fp); 1691193149Sdougb if (ferror(fp)) 1692193149Sdougb ret = DST_R_WRITEERROR; 1693143731Sdougb fclose(fp); 1694143731Sdougb 1695193149Sdougb return (ret); 1696143731Sdougb} 1697143731Sdougb 1698143731Sdougbstatic isc_result_t 1699143731Sdougbbuildfilename(dns_name_t *name, dns_keytag_t id, 1700143731Sdougb unsigned int alg, unsigned int type, 1701143731Sdougb const char *directory, isc_buffer_t *out) 1702143731Sdougb{ 1703143731Sdougb const char *suffix = ""; 1704143731Sdougb unsigned int len; 1705143731Sdougb isc_result_t result; 1706143731Sdougb 1707143731Sdougb REQUIRE(out != NULL); 1708143731Sdougb if ((type & DST_TYPE_PRIVATE) != 0) 1709143731Sdougb suffix = ".private"; 1710143731Sdougb else if (type == DST_TYPE_PUBLIC) 1711143731Sdougb suffix = ".key"; 1712143731Sdougb if (directory != NULL) { 1713143731Sdougb if (isc_buffer_availablelength(out) < strlen(directory)) 1714143731Sdougb return (ISC_R_NOSPACE); 1715143731Sdougb isc_buffer_putstr(out, directory); 1716143731Sdougb if (strlen(directory) > 0U && 1717143731Sdougb directory[strlen(directory) - 1] != '/') 1718143731Sdougb isc_buffer_putstr(out, "/"); 1719143731Sdougb } 1720143731Sdougb if (isc_buffer_availablelength(out) < 1) 1721143731Sdougb return (ISC_R_NOSPACE); 1722143731Sdougb isc_buffer_putstr(out, "K"); 1723143731Sdougb result = dns_name_tofilenametext(name, ISC_FALSE, out); 1724143731Sdougb if (result != ISC_R_SUCCESS) 1725143731Sdougb return (result); 1726143731Sdougb len = 1 + 3 + 1 + 5 + strlen(suffix) + 1; 1727143731Sdougb if (isc_buffer_availablelength(out) < len) 1728143731Sdougb return (ISC_R_NOSPACE); 1729193149Sdougb sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id, 1730193149Sdougb suffix); 1731143731Sdougb isc_buffer_add(out, len); 1732193149Sdougb 1733143731Sdougb return (ISC_R_SUCCESS); 1734143731Sdougb} 1735143731Sdougb 1736143731Sdougbstatic isc_result_t 1737143731Sdougbcomputeid(dst_key_t *key) { 1738143731Sdougb isc_buffer_t dnsbuf; 1739143731Sdougb unsigned char dns_array[DST_KEY_MAXSIZE]; 1740143731Sdougb isc_region_t r; 1741143731Sdougb isc_result_t ret; 1742143731Sdougb 1743143731Sdougb isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array)); 1744143731Sdougb ret = dst_key_todns(key, &dnsbuf); 1745143731Sdougb if (ret != ISC_R_SUCCESS) 1746143731Sdougb return (ret); 1747143731Sdougb 1748143731Sdougb isc_buffer_usedregion(&dnsbuf, &r); 1749143731Sdougb key->key_id = dst_region_computeid(&r, key->key_alg); 1750234010Sdougb key->key_rid = dst_region_computerid(&r, key->key_alg); 1751143731Sdougb return (ISC_R_SUCCESS); 1752143731Sdougb} 1753143731Sdougb 1754143731Sdougbstatic isc_result_t 1755143731Sdougbfrombuffer(dns_name_t *name, unsigned int alg, unsigned int flags, 1756143731Sdougb unsigned int protocol, dns_rdataclass_t rdclass, 1757143731Sdougb isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) 1758143731Sdougb{ 1759143731Sdougb dst_key_t *key; 1760143731Sdougb isc_result_t ret; 1761143731Sdougb 1762143731Sdougb REQUIRE(dns_name_isabsolute(name)); 1763143731Sdougb REQUIRE(source != NULL); 1764143731Sdougb REQUIRE(mctx != NULL); 1765143731Sdougb REQUIRE(keyp != NULL && *keyp == NULL); 1766143731Sdougb 1767254897Serwin key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx); 1768143731Sdougb if (key == NULL) 1769143731Sdougb return (ISC_R_NOMEMORY); 1770143731Sdougb 1771143731Sdougb if (isc_buffer_remaininglength(source) > 0) { 1772143731Sdougb ret = algorithm_status(alg); 1773143731Sdougb if (ret != ISC_R_SUCCESS) { 1774143731Sdougb dst_key_free(&key); 1775143731Sdougb return (ret); 1776143731Sdougb } 1777143731Sdougb if (key->func->fromdns == NULL) { 1778143731Sdougb dst_key_free(&key); 1779143731Sdougb return (DST_R_UNSUPPORTEDALG); 1780143731Sdougb } 1781143731Sdougb 1782143731Sdougb ret = key->func->fromdns(key, source); 1783143731Sdougb if (ret != ISC_R_SUCCESS) { 1784143731Sdougb dst_key_free(&key); 1785143731Sdougb return (ret); 1786143731Sdougb } 1787143731Sdougb } 1788143731Sdougb 1789143731Sdougb *keyp = key; 1790143731Sdougb return (ISC_R_SUCCESS); 1791143731Sdougb} 1792143731Sdougb 1793143731Sdougbstatic isc_result_t 1794143731Sdougbalgorithm_status(unsigned int alg) { 1795143731Sdougb REQUIRE(dst_initialized == ISC_TRUE); 1796143731Sdougb 1797143731Sdougb if (dst_algorithm_supported(alg)) 1798143731Sdougb return (ISC_R_SUCCESS); 1799143731Sdougb#ifndef OPENSSL 1800143731Sdougb if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || 1801143731Sdougb alg == DST_ALG_DSA || alg == DST_ALG_DH || 1802193149Sdougb alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA || 1803204619Sdougb alg == DST_ALG_NSEC3RSASHA1 || 1804224092Sdougb alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 || 1805245163Serwin alg == DST_ALG_ECCGOST || 1806245163Serwin alg == DST_ALG_ECDSA256 || alg == DST_ALG_ECDSA384) 1807143731Sdougb return (DST_R_NOCRYPTO); 1808143731Sdougb#endif 1809143731Sdougb return (DST_R_UNSUPPORTEDALG); 1810143731Sdougb} 1811143731Sdougb 1812143731Sdougbstatic isc_result_t 1813224092Sdougbaddsuffix(char *filename, int len, const char *odirname, 1814224092Sdougb const char *ofilename, const char *suffix) 1815143731Sdougb{ 1816143731Sdougb int olen = strlen(ofilename); 1817143731Sdougb int n; 1818143731Sdougb 1819143731Sdougb if (olen > 1 && ofilename[olen - 1] == '.') 1820143731Sdougb olen -= 1; 1821143731Sdougb else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0) 1822143731Sdougb olen -= 8; 1823143731Sdougb else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0) 1824143731Sdougb olen -= 4; 1825143731Sdougb 1826224092Sdougb if (odirname == NULL) 1827224092Sdougb n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix); 1828224092Sdougb else 1829224092Sdougb n = snprintf(filename, len, "%s/%.*s%s", 1830224092Sdougb odirname, olen, ofilename, suffix); 1831143731Sdougb if (n < 0) 1832204619Sdougb return (ISC_R_FAILURE); 1833224092Sdougb if (n >= len) 1834143731Sdougb return (ISC_R_NOSPACE); 1835143731Sdougb return (ISC_R_SUCCESS); 1836143731Sdougb} 1837143731Sdougb 1838143731Sdougbisc_result_t 1839143731Sdougbdst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { 1840224092Sdougb#ifdef BIND9 1841143731Sdougb unsigned int flags = dst_entropy_flags; 1842204619Sdougb 1843204619Sdougb if (len == 0) 1844204619Sdougb return (ISC_R_SUCCESS); 1845143731Sdougb if (pseudo) 1846143731Sdougb flags &= ~ISC_ENTROPY_GOODONLY; 1847224092Sdougb else 1848224092Sdougb flags |= ISC_ENTROPY_BLOCKING; 1849143731Sdougb return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags)); 1850224092Sdougb#else 1851224092Sdougb UNUSED(buf); 1852224092Sdougb UNUSED(len); 1853224092Sdougb UNUSED(pseudo); 1854224092Sdougb 1855224092Sdougb return (ISC_R_NOTIMPLEMENTED); 1856224092Sdougb#endif 1857143731Sdougb} 1858193149Sdougb 1859193149Sdougbunsigned int 1860193149Sdougbdst__entropy_status(void) { 1861224092Sdougb#ifdef BIND9 1862204619Sdougb#ifdef GSSAPI 1863204619Sdougb unsigned int flags = dst_entropy_flags; 1864204619Sdougb isc_result_t ret; 1865204619Sdougb unsigned char buf[32]; 1866204619Sdougb static isc_boolean_t first = ISC_TRUE; 1867204619Sdougb 1868204619Sdougb if (first) { 1869204619Sdougb /* Someone believes RAND_status() initializes the PRNG */ 1870204619Sdougb flags &= ~ISC_ENTROPY_GOODONLY; 1871204619Sdougb ret = isc_entropy_getdata(dst_entropy_pool, buf, 1872204619Sdougb sizeof(buf), NULL, flags); 1873204619Sdougb INSIST(ret == ISC_R_SUCCESS); 1874204619Sdougb isc_entropy_putdata(dst_entropy_pool, buf, 1875204619Sdougb sizeof(buf), 2 * sizeof(buf)); 1876204619Sdougb first = ISC_FALSE; 1877204619Sdougb } 1878204619Sdougb#endif 1879193149Sdougb return (isc_entropy_status(dst_entropy_pool)); 1880224092Sdougb#else 1881224092Sdougb return (0); 1882224092Sdougb#endif 1883193149Sdougb} 1884224092Sdougb 1885224092Sdougbisc_buffer_t * 1886224092Sdougbdst_key_tkeytoken(const dst_key_t *key) { 1887225361Sdougb REQUIRE(VALID_KEY(key)); 1888224092Sdougb return (key->key_tkeytoken); 1889224092Sdougb} 1890