00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include <config.h>
00040
00041 #include <stdlib.h>
00042 #include <time.h>
00043
00044 #include <isc/buffer.h>
00045 #include <isc/dir.h>
00046 #include <isc/entropy.h>
00047 #include <isc/fsaccess.h>
00048 #include <isc/hmacsha.h>
00049 #include <isc/lex.h>
00050 #include <isc/mem.h>
00051 #include <isc/once.h>
00052 #include <isc/platform.h>
00053 #include <isc/print.h>
00054 #include <isc/refcount.h>
00055 #include <isc/random.h>
00056 #include <isc/string.h>
00057 #include <isc/time.h>
00058 #include <isc/util.h>
00059 #include <isc/file.h>
00060
00061 #define DST_KEY_INTERNAL
00062
00063 #include <dns/fixedname.h>
00064 #include <dns/keyvalues.h>
00065 #include <dns/name.h>
00066 #include <dns/rdata.h>
00067 #include <dns/rdataclass.h>
00068 #include <dns/ttl.h>
00069 #include <dns/types.h>
00070
00071 #include <dst/result.h>
00072
00073 #include "dst_internal.h"
00074
00075 #define DST_AS_STR(t) ((t).value.as_textregion.base)
00076
00077 static dst_func_t *dst_t_func[DST_MAX_ALGS];
00078 static isc_entropy_t *dst_entropy_pool = NULL;
00079 static unsigned int dst_entropy_flags = 0;
00080
00081 isc_boolean_t dst_initialized = ISC_FALSE;
00082
00083 void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
00084
00085 isc_mem_t *dst__memory_pool = NULL;
00086
00087
00088
00089
00090 static dst_key_t * get_key_struct(dns_name_t *name,
00091 unsigned int alg,
00092 unsigned int flags,
00093 unsigned int protocol,
00094 unsigned int bits,
00095 dns_rdataclass_t rdclass,
00096 dns_ttl_t ttl,
00097 isc_mem_t *mctx);
00098 static isc_result_t write_public_key(const dst_key_t *key, int type,
00099 const char *directory);
00100 static isc_result_t buildfilename(dns_name_t *name,
00101 dns_keytag_t id,
00102 unsigned int alg,
00103 unsigned int type,
00104 const char *directory,
00105 isc_buffer_t *out);
00106 static isc_result_t computeid(dst_key_t *key);
00107 static isc_result_t frombuffer(dns_name_t *name,
00108 unsigned int alg,
00109 unsigned int flags,
00110 unsigned int protocol,
00111 dns_rdataclass_t rdclass,
00112 isc_buffer_t *source,
00113 isc_mem_t *mctx,
00114 dst_key_t **keyp);
00115
00116 static isc_result_t algorithm_status(unsigned int alg);
00117
00118 static isc_result_t addsuffix(char *filename, int len,
00119 const char *dirname, const char *ofilename,
00120 const char *suffix);
00121
00122 #define RETERR(x) \
00123 do { \
00124 result = (x); \
00125 if (result != ISC_R_SUCCESS) \
00126 goto out; \
00127 } while (0)
00128
00129 #define CHECKALG(alg) \
00130 do { \
00131 isc_result_t _r; \
00132 _r = algorithm_status(alg); \
00133 if (_r != ISC_R_SUCCESS) \
00134 return (_r); \
00135 } while (0); \
00136
00137 #if defined(OPENSSL)
00138 static void *
00139 default_memalloc(void *arg, size_t size) {
00140 UNUSED(arg);
00141 if (size == 0U)
00142 size = 1;
00143 return (malloc(size));
00144 }
00145
00146 static void
00147 default_memfree(void *arg, void *ptr) {
00148 UNUSED(arg);
00149 free(ptr);
00150 }
00151 #endif
00152
00153 isc_result_t
00154 dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
00155 return (dst_lib_init2(mctx, ectx, NULL, eflags));
00156 }
00157
00158 isc_result_t
00159 dst_lib_init2(isc_mem_t *mctx, isc_entropy_t *ectx,
00160 const char *engine, unsigned int eflags) {
00161 isc_result_t result;
00162
00163 REQUIRE(mctx != NULL);
00164 REQUIRE(dst_initialized == ISC_FALSE);
00165
00166 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
00167 UNUSED(engine);
00168 #endif
00169
00170 dst__memory_pool = NULL;
00171
00172 #if defined(OPENSSL)
00173 UNUSED(mctx);
00174
00175
00176
00177
00178
00179
00180
00181
00182 result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
00183 NULL, &dst__memory_pool, 0);
00184 if (result != ISC_R_SUCCESS)
00185 return (result);
00186 isc_mem_setname(dst__memory_pool, "dst", NULL);
00187 #ifndef OPENSSL_LEAKS
00188 isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE);
00189 #endif
00190 #else
00191 isc_mem_attach(mctx, &dst__memory_pool);
00192 #endif
00193 if (ectx != NULL) {
00194 isc_entropy_attach(ectx, &dst_entropy_pool);
00195 dst_entropy_flags = eflags;
00196 }
00197
00198 dst_result_register();
00199
00200 memset(dst_t_func, 0, sizeof(dst_t_func));
00201 RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
00202 RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
00203 RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
00204 RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
00205 RETERR(dst__hmacsha384_init(&dst_t_func[DST_ALG_HMACSHA384]));
00206 RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512]));
00207 #ifdef OPENSSL
00208 RETERR(dst__openssl_init(engine));
00209 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5],
00210 DST_ALG_RSAMD5));
00211 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1],
00212 DST_ALG_RSASHA1));
00213 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1],
00214 DST_ALG_NSEC3RSASHA1));
00215 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256],
00216 DST_ALG_RSASHA256));
00217 RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512],
00218 DST_ALG_RSASHA512));
00219 #ifdef HAVE_OPENSSL_DSA
00220 RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA]));
00221 RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
00222 #endif
00223 RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
00224 #ifdef HAVE_OPENSSL_GOST
00225 RETERR(dst__opensslgost_init(&dst_t_func[DST_ALG_ECCGOST]));
00226 #endif
00227 #ifdef HAVE_OPENSSL_ECDSA
00228 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
00229 RETERR(dst__opensslecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
00230 #endif
00231 #elif PKCS11CRYPTO
00232 RETERR(dst__pkcs11_init(mctx, engine));
00233 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSAMD5]));
00234 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA1]));
00235 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
00236 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA256]));
00237 RETERR(dst__pkcs11rsa_init(&dst_t_func[DST_ALG_RSASHA512]));
00238 RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_DSA]));
00239 RETERR(dst__pkcs11dsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
00240 RETERR(dst__pkcs11dh_init(&dst_t_func[DST_ALG_DH]));
00241 #ifdef HAVE_PKCS11_ECDSA
00242 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA256]));
00243 RETERR(dst__pkcs11ecdsa_init(&dst_t_func[DST_ALG_ECDSA384]));
00244 #endif
00245 #ifdef HAVE_PKCS11_GOST
00246 RETERR(dst__pkcs11gost_init(&dst_t_func[DST_ALG_ECCGOST]));
00247 #endif
00248 #endif
00249 #ifdef GSSAPI
00250 RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
00251 #endif
00252 dst_initialized = ISC_TRUE;
00253 return (ISC_R_SUCCESS);
00254
00255 out:
00256
00257 dst_initialized = ISC_TRUE;
00258 dst_lib_destroy();
00259 return (result);
00260 }
00261
00262 void
00263 dst_lib_destroy(void) {
00264 int i;
00265 RUNTIME_CHECK(dst_initialized == ISC_TRUE);
00266 dst_initialized = ISC_FALSE;
00267
00268 for (i = 0; i < DST_MAX_ALGS; i++)
00269 if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL)
00270 dst_t_func[i]->cleanup();
00271 #ifdef OPENSSL
00272 dst__openssl_destroy();
00273 #elif PKCS11CRYPTO
00274 (void) dst__pkcs11_destroy();
00275 #endif
00276 if (dst__memory_pool != NULL)
00277 isc_mem_detach(&dst__memory_pool);
00278 if (dst_entropy_pool != NULL)
00279 isc_entropy_detach(&dst_entropy_pool);
00280 }
00281
00282 isc_boolean_t
00283 dst_algorithm_supported(unsigned int alg) {
00284 REQUIRE(dst_initialized == ISC_TRUE);
00285
00286 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
00287 return (ISC_FALSE);
00288 return (ISC_TRUE);
00289 }
00290
00291 isc_boolean_t
00292 dst_ds_digest_supported(unsigned int digest_type) {
00293 #if defined(HAVE_OPENSSL_GOST) || defined(HAVE_PKCS11_GOST)
00294 return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
00295 digest_type == DNS_DSDIGEST_SHA256 ||
00296 digest_type == DNS_DSDIGEST_GOST ||
00297 digest_type == DNS_DSDIGEST_SHA384));
00298 #else
00299 return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
00300 digest_type == DNS_DSDIGEST_SHA256 ||
00301 digest_type == DNS_DSDIGEST_SHA384));
00302 #endif
00303 }
00304
00305 isc_result_t
00306 dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
00307 return (dst_context_create4(key, mctx, DNS_LOGCATEGORY_GENERAL,
00308 ISC_TRUE, 0, dctxp));
00309 }
00310
00311 isc_result_t
00312 dst_context_create2(dst_key_t *key, isc_mem_t *mctx,
00313 isc_logcategory_t *category, dst_context_t **dctxp)
00314 {
00315 return (dst_context_create4(key, mctx, category, ISC_TRUE, 0, dctxp));
00316 }
00317
00318 isc_result_t
00319 dst_context_create3(dst_key_t *key, isc_mem_t *mctx,
00320 isc_logcategory_t *category, isc_boolean_t useforsigning,
00321 dst_context_t **dctxp)
00322 {
00323 return (dst_context_create4(key, mctx, category,
00324 useforsigning, 0, dctxp));
00325 }
00326
00327 isc_result_t
00328 dst_context_create4(dst_key_t *key, isc_mem_t *mctx,
00329 isc_logcategory_t *category, isc_boolean_t useforsigning,
00330 int maxbits, dst_context_t **dctxp)
00331 {
00332 dst_context_t *dctx;
00333 isc_result_t result;
00334
00335 REQUIRE(dst_initialized == ISC_TRUE);
00336 REQUIRE(VALID_KEY(key));
00337 REQUIRE(mctx != NULL);
00338 REQUIRE(dctxp != NULL && *dctxp == NULL);
00339
00340 if (key->func->createctx == NULL &&
00341 key->func->createctx2 == NULL)
00342 return (DST_R_UNSUPPORTEDALG);
00343 if (key->keydata.generic == NULL)
00344 return (DST_R_NULLKEY);
00345
00346 dctx = isc_mem_get(mctx, sizeof(dst_context_t));
00347 if (dctx == NULL)
00348 return (ISC_R_NOMEMORY);
00349 dctx->key = key;
00350 dctx->mctx = mctx;
00351 dctx->category = category;
00352 if (useforsigning)
00353 dctx->use = DO_SIGN;
00354 else
00355 dctx->use = DO_VERIFY;
00356 if (key->func->createctx2 != NULL)
00357 result = key->func->createctx2(key, maxbits, dctx);
00358 else
00359 result = key->func->createctx(key, dctx);
00360 if (result != ISC_R_SUCCESS) {
00361 isc_mem_put(mctx, dctx, sizeof(dst_context_t));
00362 return (result);
00363 }
00364 dctx->magic = CTX_MAGIC;
00365 *dctxp = dctx;
00366 return (ISC_R_SUCCESS);
00367 }
00368
00369 void
00370 dst_context_destroy(dst_context_t **dctxp) {
00371 dst_context_t *dctx;
00372
00373 REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
00374
00375 dctx = *dctxp;
00376 INSIST(dctx->key->func->destroyctx != NULL);
00377 dctx->key->func->destroyctx(dctx);
00378 dctx->magic = 0;
00379 isc_mem_put(dctx->mctx, dctx, sizeof(dst_context_t));
00380 *dctxp = NULL;
00381 }
00382
00383 isc_result_t
00384 dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
00385 REQUIRE(VALID_CTX(dctx));
00386 REQUIRE(data != NULL);
00387 INSIST(dctx->key->func->adddata != NULL);
00388
00389 return (dctx->key->func->adddata(dctx, data));
00390 }
00391
00392 isc_result_t
00393 dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00394 dst_key_t *key;
00395
00396 REQUIRE(VALID_CTX(dctx));
00397 REQUIRE(sig != NULL);
00398
00399 key = dctx->key;
00400 CHECKALG(key->key_alg);
00401 if (key->keydata.generic == NULL)
00402 return (DST_R_NULLKEY);
00403
00404 if (key->func->sign == NULL)
00405 return (DST_R_NOTPRIVATEKEY);
00406 if (key->func->isprivate == NULL ||
00407 key->func->isprivate(key) == ISC_FALSE)
00408 return (DST_R_NOTPRIVATEKEY);
00409
00410 return (key->func->sign(dctx, sig));
00411 }
00412
00413 isc_result_t
00414 dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
00415 REQUIRE(VALID_CTX(dctx));
00416 REQUIRE(sig != NULL);
00417
00418 CHECKALG(dctx->key->key_alg);
00419 if (dctx->key->keydata.generic == NULL)
00420 return (DST_R_NULLKEY);
00421 if (dctx->key->func->verify == NULL)
00422 return (DST_R_NOTPUBLICKEY);
00423
00424 return (dctx->key->func->verify(dctx, sig));
00425 }
00426
00427 isc_result_t
00428 dst_context_verify2(dst_context_t *dctx, unsigned int maxbits,
00429 isc_region_t *sig)
00430 {
00431 REQUIRE(VALID_CTX(dctx));
00432 REQUIRE(sig != NULL);
00433
00434 CHECKALG(dctx->key->key_alg);
00435 if (dctx->key->keydata.generic == NULL)
00436 return (DST_R_NULLKEY);
00437 if (dctx->key->func->verify == NULL &&
00438 dctx->key->func->verify2 == NULL)
00439 return (DST_R_NOTPUBLICKEY);
00440
00441 return (dctx->key->func->verify2 != NULL ?
00442 dctx->key->func->verify2(dctx, maxbits, sig) :
00443 dctx->key->func->verify(dctx, sig));
00444 }
00445
00446 isc_result_t
00447 dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
00448 isc_buffer_t *secret)
00449 {
00450 REQUIRE(dst_initialized == ISC_TRUE);
00451 REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
00452 REQUIRE(secret != NULL);
00453
00454 CHECKALG(pub->key_alg);
00455 CHECKALG(priv->key_alg);
00456
00457 if (pub->keydata.generic == NULL || priv->keydata.generic == NULL)
00458 return (DST_R_NULLKEY);
00459
00460 if (pub->key_alg != priv->key_alg ||
00461 pub->func->computesecret == NULL ||
00462 priv->func->computesecret == NULL)
00463 return (DST_R_KEYCANNOTCOMPUTESECRET);
00464
00465 if (dst_key_isprivate(priv) == ISC_FALSE)
00466 return (DST_R_NOTPRIVATEKEY);
00467
00468 return (pub->func->computesecret(pub, priv, secret));
00469 }
00470
00471 isc_result_t
00472 dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
00473 isc_result_t ret = ISC_R_SUCCESS;
00474
00475 REQUIRE(dst_initialized == ISC_TRUE);
00476 REQUIRE(VALID_KEY(key));
00477 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
00478
00479 CHECKALG(key->key_alg);
00480
00481 if (key->func->tofile == NULL)
00482 return (DST_R_UNSUPPORTEDALG);
00483
00484 if (type & DST_TYPE_PUBLIC) {
00485 ret = write_public_key(key, type, directory);
00486 if (ret != ISC_R_SUCCESS)
00487 return (ret);
00488 }
00489
00490 if ((type & DST_TYPE_PRIVATE) &&
00491 (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
00492 return (key->func->tofile(key, directory));
00493 else
00494 return (ISC_R_SUCCESS);
00495 }
00496
00497 void
00498 dst_key_setexternal(dst_key_t *key, isc_boolean_t value) {
00499 key->external = value;
00500 }
00501
00502 isc_boolean_t
00503 dst_key_isexternal(dst_key_t *key) {
00504 return (key->external);
00505 }
00506
00507 isc_result_t
00508 dst_key_getfilename(dns_name_t *name, dns_keytag_t id,
00509 unsigned int alg, int type, const char *directory,
00510 isc_mem_t *mctx, isc_buffer_t *buf)
00511 {
00512 isc_result_t result;
00513
00514 REQUIRE(dst_initialized == ISC_TRUE);
00515 REQUIRE(dns_name_isabsolute(name));
00516 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
00517 REQUIRE(mctx != NULL);
00518 REQUIRE(buf != NULL);
00519
00520 CHECKALG(alg);
00521
00522 result = buildfilename(name, id, alg, type, directory, buf);
00523 if (result == ISC_R_SUCCESS) {
00524 if (isc_buffer_availablelength(buf) > 0)
00525 isc_buffer_putuint8(buf, 0);
00526 else
00527 result = ISC_R_NOSPACE;
00528 }
00529
00530 return (result);
00531 }
00532
00533 isc_result_t
00534 dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
00535 unsigned int alg, int type, const char *directory,
00536 isc_mem_t *mctx, dst_key_t **keyp)
00537 {
00538 isc_result_t result;
00539 char filename[ISC_DIR_NAMEMAX];
00540 isc_buffer_t buf;
00541 dst_key_t *key;
00542
00543 REQUIRE(dst_initialized == ISC_TRUE);
00544 REQUIRE(dns_name_isabsolute(name));
00545 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
00546 REQUIRE(mctx != NULL);
00547 REQUIRE(keyp != NULL && *keyp == NULL);
00548
00549 CHECKALG(alg);
00550
00551 key = NULL;
00552
00553 isc_buffer_init(&buf, filename, ISC_DIR_NAMEMAX);
00554 result = dst_key_getfilename(name, id, alg, type, NULL, mctx, &buf);
00555 if (result != ISC_R_SUCCESS)
00556 goto out;
00557
00558 result = dst_key_fromnamedfile(filename, directory, type, mctx, &key);
00559 if (result != ISC_R_SUCCESS)
00560 goto out;
00561
00562 result = computeid(key);
00563 if (result != ISC_R_SUCCESS)
00564 goto out;
00565
00566 if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
00567 alg != key->key_alg) {
00568 result = DST_R_INVALIDPRIVATEKEY;
00569 goto out;
00570 }
00571
00572 *keyp = key;
00573 result = ISC_R_SUCCESS;
00574
00575 out:
00576 if ((key != NULL) && (result != ISC_R_SUCCESS))
00577 dst_key_free(&key);
00578
00579 return (result);
00580 }
00581
00582 isc_result_t
00583 dst_key_fromnamedfile(const char *filename, const char *dirname,
00584 int type, isc_mem_t *mctx, dst_key_t **keyp)
00585 {
00586 isc_result_t result;
00587 dst_key_t *pubkey = NULL, *key = NULL;
00588 char *newfilename = NULL;
00589 int newfilenamelen = 0;
00590 isc_lex_t *lex = NULL;
00591
00592 REQUIRE(dst_initialized == ISC_TRUE);
00593 REQUIRE(filename != NULL);
00594 REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
00595 REQUIRE(mctx != NULL);
00596 REQUIRE(keyp != NULL && *keyp == NULL);
00597
00598
00599 #ifndef WIN32
00600 if (filename[0] == '/')
00601 dirname = NULL;
00602 #else
00603 if (filename[0] == '/' || filename[0] == '\\')
00604 dirname = NULL;
00605 #endif
00606
00607 newfilenamelen = strlen(filename) + 5;
00608 if (dirname != NULL)
00609 newfilenamelen += strlen(dirname) + 1;
00610 newfilename = isc_mem_get(mctx, newfilenamelen);
00611 if (newfilename == NULL)
00612 return (ISC_R_NOMEMORY);
00613 result = addsuffix(newfilename, newfilenamelen,
00614 dirname, filename, ".key");
00615 INSIST(result == ISC_R_SUCCESS);
00616
00617 result = dst_key_read_public(newfilename, type, mctx, &pubkey);
00618 isc_mem_put(mctx, newfilename, newfilenamelen);
00619 newfilename = NULL;
00620 RETERR(result);
00621
00622 if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
00623 (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
00624 result = computeid(pubkey);
00625 if (result != ISC_R_SUCCESS) {
00626 dst_key_free(&pubkey);
00627 return (result);
00628 }
00629
00630 *keyp = pubkey;
00631 return (ISC_R_SUCCESS);
00632 }
00633
00634 result = algorithm_status(pubkey->key_alg);
00635 if (result != ISC_R_SUCCESS) {
00636 dst_key_free(&pubkey);
00637 return (result);
00638 }
00639
00640 key = get_key_struct(pubkey->key_name, pubkey->key_alg,
00641 pubkey->key_flags, pubkey->key_proto, 0,
00642 pubkey->key_class, pubkey->key_ttl, mctx);
00643 if (key == NULL) {
00644 dst_key_free(&pubkey);
00645 return (ISC_R_NOMEMORY);
00646 }
00647
00648 if (key->func->parse == NULL)
00649 RETERR(DST_R_UNSUPPORTEDALG);
00650
00651 newfilenamelen = strlen(filename) + 9;
00652 if (dirname != NULL)
00653 newfilenamelen += strlen(dirname) + 1;
00654 newfilename = isc_mem_get(mctx, newfilenamelen);
00655 if (newfilename == NULL)
00656 RETERR(ISC_R_NOMEMORY);
00657 result = addsuffix(newfilename, newfilenamelen,
00658 dirname, filename, ".private");
00659 INSIST(result == ISC_R_SUCCESS);
00660
00661 RETERR(isc_lex_create(mctx, 1500, &lex));
00662 RETERR(isc_lex_openfile(lex, newfilename));
00663 isc_mem_put(mctx, newfilename, newfilenamelen);
00664
00665 RETERR(key->func->parse(key, lex, pubkey));
00666 isc_lex_destroy(&lex);
00667
00668 RETERR(computeid(key));
00669
00670 if (pubkey->key_id != key->key_id)
00671 RETERR(DST_R_INVALIDPRIVATEKEY);
00672 dst_key_free(&pubkey);
00673
00674 *keyp = key;
00675 return (ISC_R_SUCCESS);
00676
00677 out:
00678 if (pubkey != NULL)
00679 dst_key_free(&pubkey);
00680 if (newfilename != NULL)
00681 isc_mem_put(mctx, newfilename, newfilenamelen);
00682 if (lex != NULL)
00683 isc_lex_destroy(&lex);
00684 if (key != NULL)
00685 dst_key_free(&key);
00686 return (result);
00687 }
00688
00689 isc_result_t
00690 dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
00691 REQUIRE(dst_initialized == ISC_TRUE);
00692 REQUIRE(VALID_KEY(key));
00693 REQUIRE(target != NULL);
00694
00695 CHECKALG(key->key_alg);
00696
00697 if (key->func->todns == NULL)
00698 return (DST_R_UNSUPPORTEDALG);
00699
00700 if (isc_buffer_availablelength(target) < 4)
00701 return (ISC_R_NOSPACE);
00702 isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff));
00703 isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto);
00704 isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg);
00705
00706 if (key->key_flags & DNS_KEYFLAG_EXTENDED) {
00707 if (isc_buffer_availablelength(target) < 2)
00708 return (ISC_R_NOSPACE);
00709 isc_buffer_putuint16(target,
00710 (isc_uint16_t)((key->key_flags >> 16)
00711 & 0xffff));
00712 }
00713
00714 if (key->keydata.generic == NULL)
00715 return (ISC_R_SUCCESS);
00716
00717 return (key->func->todns(key, target));
00718 }
00719
00720 isc_result_t
00721 dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
00722 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
00723 {
00724 isc_uint8_t alg, proto;
00725 isc_uint32_t flags, extflags;
00726 dst_key_t *key = NULL;
00727 dns_keytag_t id, rid;
00728 isc_region_t r;
00729 isc_result_t result;
00730
00731 REQUIRE(dst_initialized);
00732
00733 isc_buffer_remainingregion(source, &r);
00734
00735 if (isc_buffer_remaininglength(source) < 4)
00736 return (DST_R_INVALIDPUBLICKEY);
00737 flags = isc_buffer_getuint16(source);
00738 proto = isc_buffer_getuint8(source);
00739 alg = isc_buffer_getuint8(source);
00740
00741 id = dst_region_computeid(&r, alg);
00742 rid = dst_region_computerid(&r, alg);
00743
00744 if (flags & DNS_KEYFLAG_EXTENDED) {
00745 if (isc_buffer_remaininglength(source) < 2)
00746 return (DST_R_INVALIDPUBLICKEY);
00747 extflags = isc_buffer_getuint16(source);
00748 flags |= (extflags << 16);
00749 }
00750
00751 result = frombuffer(name, alg, flags, proto, rdclass, source,
00752 mctx, &key);
00753 if (result != ISC_R_SUCCESS)
00754 return (result);
00755 key->key_id = id;
00756 key->key_rid = rid;
00757
00758 *keyp = key;
00759 return (ISC_R_SUCCESS);
00760 }
00761
00762 isc_result_t
00763 dst_key_frombuffer(dns_name_t *name, unsigned int alg,
00764 unsigned int flags, unsigned int protocol,
00765 dns_rdataclass_t rdclass,
00766 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
00767 {
00768 dst_key_t *key = NULL;
00769 isc_result_t result;
00770
00771 REQUIRE(dst_initialized);
00772
00773 result = frombuffer(name, alg, flags, protocol, rdclass, source,
00774 mctx, &key);
00775 if (result != ISC_R_SUCCESS)
00776 return (result);
00777
00778 result = computeid(key);
00779 if (result != ISC_R_SUCCESS) {
00780 dst_key_free(&key);
00781 return (result);
00782 }
00783
00784 *keyp = key;
00785 return (ISC_R_SUCCESS);
00786 }
00787
00788 isc_result_t
00789 dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
00790 REQUIRE(dst_initialized == ISC_TRUE);
00791 REQUIRE(VALID_KEY(key));
00792 REQUIRE(target != NULL);
00793
00794 CHECKALG(key->key_alg);
00795
00796 if (key->func->todns == NULL)
00797 return (DST_R_UNSUPPORTEDALG);
00798
00799 return (key->func->todns(key, target));
00800 }
00801
00802 isc_result_t
00803 dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
00804 isc_lex_t *lex = NULL;
00805 isc_result_t result = ISC_R_SUCCESS;
00806
00807 REQUIRE(dst_initialized == ISC_TRUE);
00808 REQUIRE(VALID_KEY(key));
00809 REQUIRE(!dst_key_isprivate(key));
00810 REQUIRE(buffer != NULL);
00811
00812 if (key->func->parse == NULL)
00813 RETERR(DST_R_UNSUPPORTEDALG);
00814
00815 RETERR(isc_lex_create(key->mctx, 1500, &lex));
00816 RETERR(isc_lex_openbuffer(lex, buffer));
00817 RETERR(key->func->parse(key, lex, NULL));
00818 out:
00819 if (lex != NULL)
00820 isc_lex_destroy(&lex);
00821 return (result);
00822 }
00823
00824 gss_ctx_id_t
00825 dst_key_getgssctx(const dst_key_t *key)
00826 {
00827 REQUIRE(key != NULL);
00828
00829 return (key->keydata.gssctx);
00830 }
00831
00832 isc_result_t
00833 dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
00834 dst_key_t **keyp, isc_region_t *intoken)
00835 {
00836 dst_key_t *key;
00837 isc_result_t result;
00838
00839 REQUIRE(gssctx != NULL);
00840 REQUIRE(keyp != NULL && *keyp == NULL);
00841
00842 key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
00843 0, dns_rdataclass_in, 0, mctx);
00844 if (key == NULL)
00845 return (ISC_R_NOMEMORY);
00846
00847 if (intoken != NULL) {
00848
00849
00850
00851
00852 RETERR(isc_buffer_allocate(key->mctx, &key->key_tkeytoken,
00853 intoken->length));
00854 RETERR(isc_buffer_copyregion(key->key_tkeytoken, intoken));
00855 }
00856
00857 key->keydata.gssctx = gssctx;
00858 *keyp = key;
00859 result = ISC_R_SUCCESS;
00860 out:
00861 return result;
00862 }
00863
00864 isc_result_t
00865 dst_key_buildinternal(dns_name_t *name, unsigned int alg,
00866 unsigned int bits, unsigned int flags,
00867 unsigned int protocol, dns_rdataclass_t rdclass,
00868 void *data, isc_mem_t *mctx, dst_key_t **keyp)
00869 {
00870 dst_key_t *key;
00871 isc_result_t result;
00872
00873 REQUIRE(dst_initialized == ISC_TRUE);
00874 REQUIRE(dns_name_isabsolute(name));
00875 REQUIRE(mctx != NULL);
00876 REQUIRE(keyp != NULL && *keyp == NULL);
00877 REQUIRE(data != NULL);
00878
00879 CHECKALG(alg);
00880
00881 key = get_key_struct(name, alg, flags, protocol, bits, rdclass,
00882 0, mctx);
00883 if (key == NULL)
00884 return (ISC_R_NOMEMORY);
00885
00886 key->keydata.generic = data;
00887
00888 result = computeid(key);
00889 if (result != ISC_R_SUCCESS) {
00890 dst_key_free(&key);
00891 return (result);
00892 }
00893
00894 *keyp = key;
00895 return (ISC_R_SUCCESS);
00896 }
00897
00898 isc_result_t
00899 dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
00900 unsigned int protocol, dns_rdataclass_t rdclass,
00901 const char *engine, const char *label, const char *pin,
00902 isc_mem_t *mctx, dst_key_t **keyp)
00903 {
00904 dst_key_t *key;
00905 isc_result_t result;
00906
00907 REQUIRE(dst_initialized == ISC_TRUE);
00908 REQUIRE(dns_name_isabsolute(name));
00909 REQUIRE(mctx != NULL);
00910 REQUIRE(keyp != NULL && *keyp == NULL);
00911 REQUIRE(label != NULL);
00912
00913 CHECKALG(alg);
00914
00915 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
00916 if (key == NULL)
00917 return (ISC_R_NOMEMORY);
00918
00919 if (key->func->fromlabel == NULL) {
00920 dst_key_free(&key);
00921 return (DST_R_UNSUPPORTEDALG);
00922 }
00923
00924 result = key->func->fromlabel(key, engine, label, pin);
00925 if (result != ISC_R_SUCCESS) {
00926 dst_key_free(&key);
00927 return (result);
00928 }
00929
00930 result = computeid(key);
00931 if (result != ISC_R_SUCCESS) {
00932 dst_key_free(&key);
00933 return (result);
00934 }
00935
00936 *keyp = key;
00937 return (ISC_R_SUCCESS);
00938 }
00939
00940 isc_result_t
00941 dst_key_generate(dns_name_t *name, unsigned int alg,
00942 unsigned int bits, unsigned int param,
00943 unsigned int flags, unsigned int protocol,
00944 dns_rdataclass_t rdclass,
00945 isc_mem_t *mctx, dst_key_t **keyp)
00946 {
00947 return (dst_key_generate2(name, alg, bits, param, flags, protocol,
00948 rdclass, mctx, keyp, NULL));
00949 }
00950
00951 isc_result_t
00952 dst_key_generate2(dns_name_t *name, unsigned int alg,
00953 unsigned int bits, unsigned int param,
00954 unsigned int flags, unsigned int protocol,
00955 dns_rdataclass_t rdclass,
00956 isc_mem_t *mctx, dst_key_t **keyp,
00957 void (*callback)(int))
00958 {
00959 dst_key_t *key;
00960 isc_result_t ret;
00961
00962 REQUIRE(dst_initialized == ISC_TRUE);
00963 REQUIRE(dns_name_isabsolute(name));
00964 REQUIRE(mctx != NULL);
00965 REQUIRE(keyp != NULL && *keyp == NULL);
00966
00967 CHECKALG(alg);
00968
00969 key = get_key_struct(name, alg, flags, protocol, bits,
00970 rdclass, 0, mctx);
00971 if (key == NULL)
00972 return (ISC_R_NOMEMORY);
00973
00974 if (bits == 0) {
00975 key->key_flags |= DNS_KEYTYPE_NOKEY;
00976 *keyp = key;
00977 return (ISC_R_SUCCESS);
00978 }
00979
00980 if (key->func->generate == NULL) {
00981 dst_key_free(&key);
00982 return (DST_R_UNSUPPORTEDALG);
00983 }
00984
00985 ret = key->func->generate(key, param, callback);
00986 if (ret != ISC_R_SUCCESS) {
00987 dst_key_free(&key);
00988 return (ret);
00989 }
00990
00991 ret = computeid(key);
00992 if (ret != ISC_R_SUCCESS) {
00993 dst_key_free(&key);
00994 return (ret);
00995 }
00996
00997 *keyp = key;
00998 return (ISC_R_SUCCESS);
00999 }
01000
01001 isc_result_t
01002 dst_key_getnum(const dst_key_t *key, int type, isc_uint32_t *valuep)
01003 {
01004 REQUIRE(VALID_KEY(key));
01005 REQUIRE(valuep != NULL);
01006 REQUIRE(type <= DST_MAX_NUMERIC);
01007 if (!key->numset[type])
01008 return (ISC_R_NOTFOUND);
01009 *valuep = key->nums[type];
01010 return (ISC_R_SUCCESS);
01011 }
01012
01013 void
01014 dst_key_setnum(dst_key_t *key, int type, isc_uint32_t value)
01015 {
01016 REQUIRE(VALID_KEY(key));
01017 REQUIRE(type <= DST_MAX_NUMERIC);
01018 key->nums[type] = value;
01019 key->numset[type] = ISC_TRUE;
01020 }
01021
01022 void
01023 dst_key_unsetnum(dst_key_t *key, int type)
01024 {
01025 REQUIRE(VALID_KEY(key));
01026 REQUIRE(type <= DST_MAX_NUMERIC);
01027 key->numset[type] = ISC_FALSE;
01028 }
01029
01030 isc_result_t
01031 dst_key_gettime(const dst_key_t *key, int type, isc_stdtime_t *timep) {
01032 REQUIRE(VALID_KEY(key));
01033 REQUIRE(timep != NULL);
01034 REQUIRE(type <= DST_MAX_TIMES);
01035 if (!key->timeset[type])
01036 return (ISC_R_NOTFOUND);
01037 *timep = key->times[type];
01038 return (ISC_R_SUCCESS);
01039 }
01040
01041 void
01042 dst_key_settime(dst_key_t *key, int type, isc_stdtime_t when) {
01043 REQUIRE(VALID_KEY(key));
01044 REQUIRE(type <= DST_MAX_TIMES);
01045 key->times[type] = when;
01046 key->timeset[type] = ISC_TRUE;
01047 }
01048
01049 void
01050 dst_key_unsettime(dst_key_t *key, int type) {
01051 REQUIRE(VALID_KEY(key));
01052 REQUIRE(type <= DST_MAX_TIMES);
01053 key->timeset[type] = ISC_FALSE;
01054 }
01055
01056 isc_result_t
01057 dst_key_getprivateformat(const dst_key_t *key, int *majorp, int *minorp) {
01058 REQUIRE(VALID_KEY(key));
01059 REQUIRE(majorp != NULL);
01060 REQUIRE(minorp != NULL);
01061 *majorp = key->fmt_major;
01062 *minorp = key->fmt_minor;
01063 return (ISC_R_SUCCESS);
01064 }
01065
01066 void
01067 dst_key_setprivateformat(dst_key_t *key, int major, int minor) {
01068 REQUIRE(VALID_KEY(key));
01069 key->fmt_major = major;
01070 key->fmt_minor = minor;
01071 }
01072
01073 static isc_boolean_t
01074 comparekeys(const dst_key_t *key1, const dst_key_t *key2,
01075 isc_boolean_t match_revoked_key,
01076 isc_boolean_t (*compare)(const dst_key_t *key1,
01077 const dst_key_t *key2))
01078 {
01079 REQUIRE(dst_initialized == ISC_TRUE);
01080 REQUIRE(VALID_KEY(key1));
01081 REQUIRE(VALID_KEY(key2));
01082
01083 if (key1 == key2)
01084 return (ISC_TRUE);
01085
01086 if (key1 == NULL || key2 == NULL)
01087 return (ISC_FALSE);
01088
01089 if (key1->key_alg != key2->key_alg)
01090 return (ISC_FALSE);
01091
01092 if (key1->key_id != key2->key_id) {
01093 if (!match_revoked_key)
01094 return (ISC_FALSE);
01095 if (key1->key_alg == DST_ALG_RSAMD5)
01096 return (ISC_FALSE);
01097 if ((key1->key_flags & DNS_KEYFLAG_REVOKE) ==
01098 (key2->key_flags & DNS_KEYFLAG_REVOKE))
01099 return (ISC_FALSE);
01100 if (key1->key_id != key2->key_rid &&
01101 key1->key_rid != key2->key_id)
01102 return (ISC_FALSE);
01103 }
01104
01105 if (compare != NULL)
01106 return (compare(key1, key2));
01107 else
01108 return (ISC_FALSE);
01109 }
01110
01111
01112
01113
01114
01115
01116 static isc_boolean_t
01117 pub_compare(const dst_key_t *key1, const dst_key_t *key2) {
01118 isc_result_t result;
01119 unsigned char buf1[DST_KEY_MAXSIZE], buf2[DST_KEY_MAXSIZE];
01120 isc_buffer_t b1, b2;
01121 isc_region_t r1, r2;
01122
01123 isc_buffer_init(&b1, buf1, sizeof(buf1));
01124 result = dst_key_todns(key1, &b1);
01125 if (result != ISC_R_SUCCESS)
01126 return (ISC_FALSE);
01127
01128 buf1[0] = buf1[1] = 0;
01129 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
01130 isc_buffer_subtract(&b1, 2);
01131
01132 isc_buffer_init(&b2, buf2, sizeof(buf2));
01133 result = dst_key_todns(key2, &b2);
01134 if (result != ISC_R_SUCCESS)
01135 return (ISC_FALSE);
01136
01137 buf2[0] = buf2[1] = 0;
01138 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0)
01139 isc_buffer_subtract(&b2, 2);
01140
01141 isc_buffer_usedregion(&b1, &r1);
01142
01143 if ((key1->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
01144 memmove(&buf1[4], &buf1[6], r1.length - 6);
01145 r1.length -= 2;
01146 }
01147
01148 isc_buffer_usedregion(&b2, &r2);
01149
01150 if ((key2->key_flags & DNS_KEYFLAG_EXTENDED) != 0) {
01151 memmove(&buf2[4], &buf2[6], r2.length - 6);
01152 r2.length -= 2;
01153 }
01154 return (ISC_TF(isc_region_compare(&r1, &r2) == 0));
01155 }
01156
01157 isc_boolean_t
01158 dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
01159 return (comparekeys(key1, key2, ISC_FALSE, key1->func->compare));
01160 }
01161
01162 isc_boolean_t
01163 dst_key_pubcompare(const dst_key_t *key1, const dst_key_t *key2,
01164 isc_boolean_t match_revoked_key)
01165 {
01166 return (comparekeys(key1, key2, match_revoked_key, pub_compare));
01167 }
01168
01169
01170 isc_boolean_t
01171 dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
01172 REQUIRE(dst_initialized == ISC_TRUE);
01173 REQUIRE(VALID_KEY(key1));
01174 REQUIRE(VALID_KEY(key2));
01175
01176 if (key1 == key2)
01177 return (ISC_TRUE);
01178 if (key1 == NULL || key2 == NULL)
01179 return (ISC_FALSE);
01180 if (key1->key_alg == key2->key_alg &&
01181 key1->func->paramcompare != NULL &&
01182 key1->func->paramcompare(key1, key2) == ISC_TRUE)
01183 return (ISC_TRUE);
01184 else
01185 return (ISC_FALSE);
01186 }
01187
01188 void
01189 dst_key_attach(dst_key_t *source, dst_key_t **target) {
01190
01191 REQUIRE(dst_initialized == ISC_TRUE);
01192 REQUIRE(target != NULL && *target == NULL);
01193 REQUIRE(VALID_KEY(source));
01194
01195 isc_refcount_increment(&source->refs, NULL);
01196 *target = source;
01197 }
01198
01199 void
01200 dst_key_free(dst_key_t **keyp) {
01201 isc_mem_t *mctx;
01202 dst_key_t *key;
01203 unsigned int refs;
01204
01205 REQUIRE(dst_initialized == ISC_TRUE);
01206 REQUIRE(keyp != NULL && VALID_KEY(*keyp));
01207
01208 key = *keyp;
01209 mctx = key->mctx;
01210
01211 isc_refcount_decrement(&key->refs, &refs);
01212 if (refs != 0)
01213 return;
01214
01215 isc_refcount_destroy(&key->refs);
01216 if (key->keydata.generic != NULL) {
01217 INSIST(key->func->destroy != NULL);
01218 key->func->destroy(key);
01219 }
01220 if (key->engine != NULL)
01221 isc_mem_free(mctx, key->engine);
01222 if (key->label != NULL)
01223 isc_mem_free(mctx, key->label);
01224 dns_name_free(key->key_name, mctx);
01225 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
01226 if (key->key_tkeytoken) {
01227 isc_buffer_free(&key->key_tkeytoken);
01228 }
01229 memset(key, 0, sizeof(dst_key_t));
01230 isc_mem_putanddetach(&mctx, key, sizeof(dst_key_t));
01231 *keyp = NULL;
01232 }
01233
01234 isc_boolean_t
01235 dst_key_isprivate(const dst_key_t *key) {
01236 REQUIRE(VALID_KEY(key));
01237 INSIST(key->func->isprivate != NULL);
01238 return (key->func->isprivate(key));
01239 }
01240
01241 isc_result_t
01242 dst_key_buildfilename(const dst_key_t *key, int type,
01243 const char *directory, isc_buffer_t *out) {
01244
01245 REQUIRE(VALID_KEY(key));
01246 REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
01247 type == 0);
01248
01249 return (buildfilename(key->key_name, key->key_id, key->key_alg,
01250 type, directory, out));
01251 }
01252
01253 isc_result_t
01254 dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
01255 REQUIRE(dst_initialized == ISC_TRUE);
01256 REQUIRE(VALID_KEY(key));
01257 REQUIRE(n != NULL);
01258
01259
01260 switch (key->key_alg) {
01261 case DST_ALG_RSAMD5:
01262 case DST_ALG_RSASHA1:
01263 case DST_ALG_NSEC3RSASHA1:
01264 case DST_ALG_RSASHA256:
01265 case DST_ALG_RSASHA512:
01266 *n = (key->key_size + 7) / 8;
01267 break;
01268 case DST_ALG_DSA:
01269 case DST_ALG_NSEC3DSA:
01270 *n = DNS_SIG_DSASIGSIZE;
01271 break;
01272 case DST_ALG_ECCGOST:
01273 *n = DNS_SIG_GOSTSIGSIZE;
01274 break;
01275 case DST_ALG_ECDSA256:
01276 *n = DNS_SIG_ECDSA256SIZE;
01277 break;
01278 case DST_ALG_ECDSA384:
01279 *n = DNS_SIG_ECDSA384SIZE;
01280 break;
01281 case DST_ALG_HMACMD5:
01282 *n = 16;
01283 break;
01284 case DST_ALG_HMACSHA1:
01285 *n = ISC_SHA1_DIGESTLENGTH;
01286 break;
01287 case DST_ALG_HMACSHA224:
01288 *n = ISC_SHA224_DIGESTLENGTH;
01289 break;
01290 case DST_ALG_HMACSHA256:
01291 *n = ISC_SHA256_DIGESTLENGTH;
01292 break;
01293 case DST_ALG_HMACSHA384:
01294 *n = ISC_SHA384_DIGESTLENGTH;
01295 break;
01296 case DST_ALG_HMACSHA512:
01297 *n = ISC_SHA512_DIGESTLENGTH;
01298 break;
01299 case DST_ALG_GSSAPI:
01300 *n = 128;
01301 break;
01302 case DST_ALG_DH:
01303 default:
01304 return (DST_R_UNSUPPORTEDALG);
01305 }
01306 return (ISC_R_SUCCESS);
01307 }
01308
01309 isc_result_t
01310 dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
01311 REQUIRE(dst_initialized == ISC_TRUE);
01312 REQUIRE(VALID_KEY(key));
01313 REQUIRE(n != NULL);
01314
01315 if (key->key_alg == DST_ALG_DH)
01316 *n = (key->key_size + 7) / 8;
01317 else
01318 return (DST_R_UNSUPPORTEDALG);
01319 return (ISC_R_SUCCESS);
01320 }
01321
01322
01323
01324
01325 isc_result_t
01326 dst_key_setflags(dst_key_t *key, isc_uint32_t flags) {
01327 REQUIRE(VALID_KEY(key));
01328 key->key_flags = flags;
01329 return (computeid(key));
01330 }
01331
01332 void
01333 dst_key_format(const dst_key_t *key, char *cp, unsigned int size) {
01334 char namestr[DNS_NAME_FORMATSIZE];
01335 char algstr[DNS_NAME_FORMATSIZE];
01336
01337 dns_name_format(dst_key_name(key), namestr, sizeof(namestr));
01338 dns_secalg_format((dns_secalg_t) dst_key_alg(key), algstr,
01339 sizeof(algstr));
01340 snprintf(cp, size, "%s/%s/%d", namestr, algstr, dst_key_id(key));
01341 }
01342
01343 isc_result_t
01344 dst_key_dump(dst_key_t *key, isc_mem_t *mctx, char **buffer, int *length) {
01345
01346 REQUIRE(buffer != NULL && *buffer == NULL);
01347 REQUIRE(length != NULL && *length == 0);
01348 REQUIRE(VALID_KEY(key));
01349
01350 if (key->func->dump == NULL)
01351 return (ISC_R_NOTIMPLEMENTED);
01352 return (key->func->dump(key, mctx, buffer, length));
01353 }
01354
01355 isc_result_t
01356 dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
01357 unsigned int protocol, dns_rdataclass_t rdclass,
01358 isc_mem_t *mctx, const char *keystr, dst_key_t **keyp)
01359 {
01360 isc_result_t result;
01361 dst_key_t *key;
01362
01363 REQUIRE(dst_initialized == ISC_TRUE);
01364 REQUIRE(keyp != NULL && *keyp == NULL);
01365
01366 if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
01367 return (DST_R_UNSUPPORTEDALG);
01368
01369 if (dst_t_func[alg]->restore == NULL)
01370 return (ISC_R_NOTIMPLEMENTED);
01371
01372 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
01373 if (key == NULL)
01374 return (ISC_R_NOMEMORY);
01375
01376 result = (dst_t_func[alg]->restore)(key, keystr);
01377 if (result == ISC_R_SUCCESS)
01378 *keyp = key;
01379 else
01380 dst_key_free(&key);
01381
01382 return (result);
01383 }
01384
01385
01386
01387
01388
01389
01390
01391
01392 static dst_key_t *
01393 get_key_struct(dns_name_t *name, unsigned int alg,
01394 unsigned int flags, unsigned int protocol,
01395 unsigned int bits, dns_rdataclass_t rdclass,
01396 dns_ttl_t ttl, isc_mem_t *mctx)
01397 {
01398 dst_key_t *key;
01399 isc_result_t result;
01400 int i;
01401
01402 key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
01403 if (key == NULL)
01404 return (NULL);
01405
01406 memset(key, 0, sizeof(dst_key_t));
01407
01408 key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
01409 if (key->key_name == NULL) {
01410 isc_mem_put(mctx, key, sizeof(dst_key_t));
01411 return (NULL);
01412 }
01413
01414 dns_name_init(key->key_name, NULL);
01415 result = dns_name_dup(name, mctx, key->key_name);
01416 if (result != ISC_R_SUCCESS) {
01417 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
01418 isc_mem_put(mctx, key, sizeof(dst_key_t));
01419 return (NULL);
01420 }
01421
01422 result = isc_refcount_init(&key->refs, 1);
01423 if (result != ISC_R_SUCCESS) {
01424 dns_name_free(key->key_name, mctx);
01425 isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
01426 isc_mem_put(mctx, key, sizeof(dst_key_t));
01427 return (NULL);
01428 }
01429 isc_mem_attach(mctx, &key->mctx);
01430 key->key_alg = alg;
01431 key->key_flags = flags;
01432 key->key_proto = protocol;
01433 key->keydata.generic = NULL;
01434 key->key_size = bits;
01435 key->key_class = rdclass;
01436 key->key_ttl = ttl;
01437 key->func = dst_t_func[alg];
01438 key->fmt_major = 0;
01439 key->fmt_minor = 0;
01440 for (i = 0; i < (DST_MAX_TIMES + 1); i++) {
01441 key->times[i] = 0;
01442 key->timeset[i] = ISC_FALSE;
01443 }
01444 key->inactive = ISC_FALSE;
01445 key->magic = KEY_MAGIC;
01446 return (key);
01447 }
01448
01449 isc_boolean_t
01450 dst_key_inactive(const dst_key_t *key) {
01451
01452 REQUIRE(VALID_KEY(key));
01453
01454 return (key->inactive);
01455 }
01456
01457 void
01458 dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive) {
01459
01460 REQUIRE(VALID_KEY(key));
01461
01462 key->inactive = inactive;
01463 }
01464
01465
01466
01467
01468 isc_result_t
01469 dst_key_read_public(const char *filename, int type,
01470 isc_mem_t *mctx, dst_key_t **keyp)
01471 {
01472 u_char rdatabuf[DST_KEY_MAXSIZE];
01473 isc_buffer_t b;
01474 dns_fixedname_t name;
01475 isc_lex_t *lex = NULL;
01476 isc_token_t token;
01477 isc_result_t ret;
01478 dns_rdata_t rdata = DNS_RDATA_INIT;
01479 unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
01480 dns_rdataclass_t rdclass = dns_rdataclass_in;
01481 isc_lexspecials_t specials;
01482 isc_uint32_t ttl = 0;
01483 isc_result_t result;
01484 dns_rdatatype_t keytype;
01485
01486
01487
01488
01489
01490
01491
01492
01493 ret = isc_lex_create(mctx, 1500, &lex);
01494 if (ret != ISC_R_SUCCESS)
01495 goto cleanup;
01496
01497 memset(specials, 0, sizeof(specials));
01498 specials['('] = 1;
01499 specials[')'] = 1;
01500 specials['"'] = 1;
01501 isc_lex_setspecials(lex, specials);
01502 isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
01503
01504 ret = isc_lex_openfile(lex, filename);
01505 if (ret != ISC_R_SUCCESS)
01506 goto cleanup;
01507
01508 #define NEXTTOKEN(lex, opt, token) { \
01509 ret = isc_lex_gettoken(lex, opt, token); \
01510 if (ret != ISC_R_SUCCESS) \
01511 goto cleanup; \
01512 }
01513
01514 #define BADTOKEN() { \
01515 ret = ISC_R_UNEXPECTEDTOKEN; \
01516 goto cleanup; \
01517 }
01518
01519
01520 NEXTTOKEN(lex, opt, &token);
01521 if (token.type != isc_tokentype_string)
01522 BADTOKEN();
01523
01524
01525
01526
01527 if (!strcmp(DST_AS_STR(token), "@"))
01528 BADTOKEN();
01529
01530 dns_fixedname_init(&name);
01531 isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
01532 isc_buffer_add(&b, strlen(DST_AS_STR(token)));
01533 ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname,
01534 0, NULL);
01535 if (ret != ISC_R_SUCCESS)
01536 goto cleanup;
01537
01538
01539 NEXTTOKEN(lex, opt, &token);
01540
01541 if (token.type != isc_tokentype_string)
01542 BADTOKEN();
01543
01544
01545 result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
01546 if (result == ISC_R_SUCCESS)
01547 NEXTTOKEN(lex, opt, &token);
01548
01549 if (token.type != isc_tokentype_string)
01550 BADTOKEN();
01551
01552 ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
01553 if (ret == ISC_R_SUCCESS)
01554 NEXTTOKEN(lex, opt, &token);
01555
01556 if (token.type != isc_tokentype_string)
01557 BADTOKEN();
01558
01559 if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0)
01560 keytype = dns_rdatatype_dnskey;
01561 else if (strcasecmp(DST_AS_STR(token), "KEY") == 0)
01562 keytype = dns_rdatatype_key;
01563 else
01564 BADTOKEN();
01565
01566 if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
01567 ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) {
01568 ret = DST_R_BADKEYTYPE;
01569 goto cleanup;
01570 }
01571
01572 isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
01573 ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL,
01574 ISC_FALSE, mctx, &b, NULL);
01575 if (ret != ISC_R_SUCCESS)
01576 goto cleanup;
01577
01578 ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
01579 keyp);
01580 if (ret != ISC_R_SUCCESS)
01581 goto cleanup;
01582
01583 dst_key_setttl(*keyp, ttl);
01584
01585 cleanup:
01586 if (lex != NULL)
01587 isc_lex_destroy(&lex);
01588 return (ret);
01589 }
01590
01591 static isc_boolean_t
01592 issymmetric(const dst_key_t *key) {
01593 REQUIRE(dst_initialized == ISC_TRUE);
01594 REQUIRE(VALID_KEY(key));
01595
01596
01597 switch (key->key_alg) {
01598 case DST_ALG_RSAMD5:
01599 case DST_ALG_RSASHA1:
01600 case DST_ALG_NSEC3RSASHA1:
01601 case DST_ALG_RSASHA256:
01602 case DST_ALG_RSASHA512:
01603 case DST_ALG_DSA:
01604 case DST_ALG_NSEC3DSA:
01605 case DST_ALG_DH:
01606 case DST_ALG_ECCGOST:
01607 case DST_ALG_ECDSA256:
01608 case DST_ALG_ECDSA384:
01609 return (ISC_FALSE);
01610 case DST_ALG_HMACMD5:
01611 case DST_ALG_GSSAPI:
01612 return (ISC_TRUE);
01613 default:
01614 return (ISC_FALSE);
01615 }
01616 }
01617
01618
01619
01620
01621 static void
01622 printtime(const dst_key_t *key, int type, const char *tag, FILE *stream) {
01623 isc_result_t result;
01624 #ifdef ISC_PLATFORM_USETHREADS
01625 char output[26];
01626 #else
01627 const char *output;
01628 #endif
01629 isc_stdtime_t when;
01630 time_t t;
01631 char utc[sizeof("YYYYMMDDHHSSMM")];
01632 isc_buffer_t b;
01633 isc_region_t r;
01634
01635 result = dst_key_gettime(key, type, &when);
01636 if (result == ISC_R_NOTFOUND)
01637 return;
01638
01639
01640 t = when;
01641 #ifdef ISC_PLATFORM_USETHREADS
01642 #ifdef WIN32
01643 if (ctime_s(output, sizeof(output), &t) != 0)
01644 goto error;
01645 #else
01646 if (ctime_r(&t, output) == NULL)
01647 goto error;
01648 #endif
01649 #else
01650 output = ctime(&t);
01651 #endif
01652
01653 isc_buffer_init(&b, utc, sizeof(utc));
01654 result = dns_time32_totext(when, &b);
01655 if (result != ISC_R_SUCCESS)
01656 goto error;
01657
01658 isc_buffer_usedregion(&b, &r);
01659 fprintf(stream, "%s: %.*s (%.*s)\n", tag, (int)r.length, r.base,
01660 (int)strlen(output) - 1, output);
01661 return;
01662
01663 error:
01664 fprintf(stream, "%s: (set, unable to display)\n", tag);
01665 }
01666
01667
01668
01669
01670 static isc_result_t
01671 write_public_key(const dst_key_t *key, int type, const char *directory) {
01672 FILE *fp;
01673 isc_buffer_t keyb, textb, fileb, classb;
01674 isc_region_t r;
01675 char filename[ISC_DIR_NAMEMAX];
01676 unsigned char key_array[DST_KEY_MAXSIZE];
01677 char text_array[DST_KEY_MAXTEXTSIZE];
01678 char class_array[10];
01679 isc_result_t ret;
01680 dns_rdata_t rdata = DNS_RDATA_INIT;
01681 isc_fsaccess_t access;
01682
01683 REQUIRE(VALID_KEY(key));
01684
01685 isc_buffer_init(&keyb, key_array, sizeof(key_array));
01686 isc_buffer_init(&textb, text_array, sizeof(text_array));
01687 isc_buffer_init(&classb, class_array, sizeof(class_array));
01688
01689 ret = dst_key_todns(key, &keyb);
01690 if (ret != ISC_R_SUCCESS)
01691 return (ret);
01692
01693 isc_buffer_usedregion(&keyb, &r);
01694 dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
01695
01696 ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb);
01697 if (ret != ISC_R_SUCCESS)
01698 return (DST_R_INVALIDPUBLICKEY);
01699
01700 ret = dns_rdataclass_totext(key->key_class, &classb);
01701 if (ret != ISC_R_SUCCESS)
01702 return (DST_R_INVALIDPUBLICKEY);
01703
01704
01705
01706
01707 isc_buffer_init(&fileb, filename, sizeof(filename));
01708 ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
01709 if (ret != ISC_R_SUCCESS)
01710 return (ret);
01711
01712
01713
01714
01715 if ((fp = fopen(filename, "w")) == NULL)
01716 return (DST_R_WRITEERROR);
01717
01718 if (issymmetric(key)) {
01719 access = 0;
01720 isc_fsaccess_add(ISC_FSACCESS_OWNER,
01721 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
01722 &access);
01723 (void)isc_fsaccess_set(filename, access);
01724 }
01725
01726
01727 if ((type & DST_TYPE_KEY) == 0) {
01728 fprintf(fp, "; This is a %s%s-signing key, keyid %d, for ",
01729 (key->key_flags & DNS_KEYFLAG_REVOKE) != 0 ?
01730 "revoked " :
01731 "",
01732 (key->key_flags & DNS_KEYFLAG_KSK) != 0 ?
01733 "key" :
01734 "zone",
01735 key->key_id);
01736 ret = dns_name_print(key->key_name, fp);
01737 if (ret != ISC_R_SUCCESS) {
01738 fclose(fp);
01739 return (ret);
01740 }
01741 fputc('\n', fp);
01742
01743 printtime(key, DST_TIME_CREATED, "; Created", fp);
01744 printtime(key, DST_TIME_PUBLISH, "; Publish", fp);
01745 printtime(key, DST_TIME_ACTIVATE, "; Activate", fp);
01746 printtime(key, DST_TIME_REVOKE, "; Revoke", fp);
01747 printtime(key, DST_TIME_INACTIVE, "; Inactive", fp);
01748 printtime(key, DST_TIME_DELETE, "; Delete", fp);
01749 }
01750
01751
01752 ret = dns_name_print(key->key_name, fp);
01753 fprintf(fp, " ");
01754
01755 if (key->key_ttl != 0)
01756 fprintf(fp, "%d ", key->key_ttl);
01757
01758 isc_buffer_usedregion(&classb, &r);
01759 if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
01760 ret = DST_R_WRITEERROR;
01761
01762 if ((type & DST_TYPE_KEY) != 0)
01763 fprintf(fp, " KEY ");
01764 else
01765 fprintf(fp, " DNSKEY ");
01766
01767 isc_buffer_usedregion(&textb, &r);
01768 if ((unsigned) fwrite(r.base, 1, r.length, fp) != r.length)
01769 ret = DST_R_WRITEERROR;
01770
01771 fputc('\n', fp);
01772 fflush(fp);
01773 if (ferror(fp))
01774 ret = DST_R_WRITEERROR;
01775 fclose(fp);
01776
01777 return (ret);
01778 }
01779
01780 static isc_result_t
01781 buildfilename(dns_name_t *name, dns_keytag_t id,
01782 unsigned int alg, unsigned int type,
01783 const char *directory, isc_buffer_t *out)
01784 {
01785 const char *suffix = "";
01786 unsigned int len;
01787 isc_result_t result;
01788
01789 REQUIRE(out != NULL);
01790 if ((type & DST_TYPE_PRIVATE) != 0)
01791 suffix = ".private";
01792 else if (type == DST_TYPE_PUBLIC)
01793 suffix = ".key";
01794 if (directory != NULL) {
01795 if (isc_buffer_availablelength(out) < strlen(directory))
01796 return (ISC_R_NOSPACE);
01797 isc_buffer_putstr(out, directory);
01798 if (strlen(directory) > 0U &&
01799 directory[strlen(directory) - 1] != '/')
01800 isc_buffer_putstr(out, "/");
01801 }
01802 if (isc_buffer_availablelength(out) < 1)
01803 return (ISC_R_NOSPACE);
01804 isc_buffer_putstr(out, "K");
01805 result = dns_name_tofilenametext(name, ISC_FALSE, out);
01806 if (result != ISC_R_SUCCESS)
01807 return (result);
01808 len = 1 + 3 + 1 + 5 + strlen(suffix) + 1;
01809 if (isc_buffer_availablelength(out) < len)
01810 return (ISC_R_NOSPACE);
01811 sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id,
01812 suffix);
01813 isc_buffer_add(out, len);
01814
01815 return (ISC_R_SUCCESS);
01816 }
01817
01818 static isc_result_t
01819 computeid(dst_key_t *key) {
01820 isc_buffer_t dnsbuf;
01821 unsigned char dns_array[DST_KEY_MAXSIZE];
01822 isc_region_t r;
01823 isc_result_t ret;
01824
01825 isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
01826 ret = dst_key_todns(key, &dnsbuf);
01827 if (ret != ISC_R_SUCCESS)
01828 return (ret);
01829
01830 isc_buffer_usedregion(&dnsbuf, &r);
01831 key->key_id = dst_region_computeid(&r, key->key_alg);
01832 key->key_rid = dst_region_computerid(&r, key->key_alg);
01833 return (ISC_R_SUCCESS);
01834 }
01835
01836 static isc_result_t
01837 frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags,
01838 unsigned int protocol, dns_rdataclass_t rdclass,
01839 isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
01840 {
01841 dst_key_t *key;
01842 isc_result_t ret;
01843
01844 REQUIRE(dns_name_isabsolute(name));
01845 REQUIRE(source != NULL);
01846 REQUIRE(mctx != NULL);
01847 REQUIRE(keyp != NULL && *keyp == NULL);
01848
01849 key = get_key_struct(name, alg, flags, protocol, 0, rdclass, 0, mctx);
01850 if (key == NULL)
01851 return (ISC_R_NOMEMORY);
01852
01853 if (isc_buffer_remaininglength(source) > 0) {
01854 ret = algorithm_status(alg);
01855 if (ret != ISC_R_SUCCESS) {
01856 dst_key_free(&key);
01857 return (ret);
01858 }
01859 if (key->func->fromdns == NULL) {
01860 dst_key_free(&key);
01861 return (DST_R_UNSUPPORTEDALG);
01862 }
01863
01864 ret = key->func->fromdns(key, source);
01865 if (ret != ISC_R_SUCCESS) {
01866 dst_key_free(&key);
01867 return (ret);
01868 }
01869 }
01870
01871 *keyp = key;
01872 return (ISC_R_SUCCESS);
01873 }
01874
01875 static isc_result_t
01876 algorithm_status(unsigned int alg) {
01877 REQUIRE(dst_initialized == ISC_TRUE);
01878
01879 if (dst_algorithm_supported(alg))
01880 return (ISC_R_SUCCESS);
01881 #if !defined(OPENSSL) && !defined(PKCS11CRYPTO)
01882 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
01883 alg == DST_ALG_DSA || alg == DST_ALG_DH ||
01884 alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
01885 alg == DST_ALG_NSEC3RSASHA1 ||
01886 alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512 ||
01887 alg == DST_ALG_ECCGOST ||
01888 alg == DST_ALG_ECDSA256 || alg == DST_ALG_ECDSA384)
01889 return (DST_R_NOCRYPTO);
01890 #endif
01891 return (DST_R_UNSUPPORTEDALG);
01892 }
01893
01894 static isc_result_t
01895 addsuffix(char *filename, int len, const char *odirname,
01896 const char *ofilename, const char *suffix)
01897 {
01898 int olen = strlen(ofilename);
01899 int n;
01900
01901 if (olen > 1 && ofilename[olen - 1] == '.')
01902 olen -= 1;
01903 else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0)
01904 olen -= 8;
01905 else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0)
01906 olen -= 4;
01907
01908 if (odirname == NULL)
01909 n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
01910 else
01911 n = snprintf(filename, len, "%s/%.*s%s",
01912 odirname, olen, ofilename, suffix);
01913 if (n < 0)
01914 return (ISC_R_FAILURE);
01915 if (n >= len)
01916 return (ISC_R_NOSPACE);
01917 return (ISC_R_SUCCESS);
01918 }
01919
01920 isc_result_t
01921 dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
01922 unsigned int flags = dst_entropy_flags;
01923
01924 if (dst_entropy_pool == NULL)
01925 return (ISC_R_FAILURE);
01926
01927 if (len == 0)
01928 return (ISC_R_SUCCESS);
01929
01930 #ifdef PKCS11CRYPTO
01931 UNUSED(pseudo);
01932 UNUSED(flags);
01933 return (pk11_rand_bytes(buf, len));
01934 #else
01935 if (pseudo)
01936 flags &= ~ISC_ENTROPY_GOODONLY;
01937 else
01938 flags |= ISC_ENTROPY_BLOCKING;
01939 return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
01940 #endif
01941 }
01942
01943 unsigned int
01944 dst__entropy_status(void) {
01945 #ifndef PKCS11CRYPTO
01946 #ifdef GSSAPI
01947 unsigned int flags = dst_entropy_flags;
01948 isc_result_t ret;
01949 unsigned char buf[32];
01950 static isc_boolean_t first = ISC_TRUE;
01951
01952 if (dst_entropy_pool == NULL)
01953 return (0);
01954
01955 if (first) {
01956
01957 flags &= ~ISC_ENTROPY_GOODONLY;
01958 ret = isc_entropy_getdata(dst_entropy_pool, buf,
01959 sizeof(buf), NULL, flags);
01960 INSIST(ret == ISC_R_SUCCESS);
01961 isc_entropy_putdata(dst_entropy_pool, buf,
01962 sizeof(buf), 2 * sizeof(buf));
01963 first = ISC_FALSE;
01964 }
01965 #endif
01966 return (isc_entropy_status(dst_entropy_pool));
01967 #else
01968 return (0);
01969 #endif
01970 }
01971
01972 isc_buffer_t *
01973 dst_key_tkeytoken(const dst_key_t *key) {
01974 REQUIRE(VALID_KEY(key));
01975 return (key->key_tkeytoken);
01976 }