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