dst_api.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
00010  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
00011  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
00012  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
00015  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  *
00017  * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
00018  *
00019  * Permission to use, copy, modify, and/or distribute this software for any
00020  * purpose with or without fee is hereby granted, provided that the above
00021  * copyright notice and this permission notice appear in all copies.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
00024  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
00025  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
00026  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00027  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00028  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
00029  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00030  */
00031 
00032 /*
00033  * Principal Author: Brian Wellington
00034  * $Id: dst_api.c,v 1.65 2011/10/20 21:20:02 marka Exp $
00035  */
00036 
00037 /*! \file */
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  * Static functions.
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          * When using --with-openssl, there seems to be no good way of not
00176          * leaking memory due to the openssl error handling mechanism.
00177          * Avoid assertions by using a local memory context and not checking
00178          * for leaks on exit.  Note: as there are leaks we cannot use
00179          * ISC_MEMFLAG_INTERNAL as it will free up memory still being used
00180          * by libcrypto.
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 /* OPENSSL */
00191         isc_mem_attach(mctx, &dst__memory_pool);
00192 #endif /* OPENSSL */
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 /* if OPENSSL, elif PKCS11CRYPTO */
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         /* avoid immediate crash! */
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 /* if OPENSSL, elif PKCS11CRYPTO */
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         /* If an absolute path is specified, don't use the key directory */
00599 #ifndef WIN32
00600         if (filename[0] == '/')
00601                 dirname = NULL;
00602 #else /* WIN32 */
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) /*%< NULL KEY */
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                  * Keep the token for use by external ssu rules. They may need
00850                  * to examine the PAC in the kerberos ticket.
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) { /*%< NULL KEY */
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  * Compares only the public portion of two keys, by converting them
01114  * both to wire format and comparing the results.
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         /* Zero out flags. */
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         /* Zero out flags. */
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         /* Remove extended flags. */
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         /* Remove extended flags. */
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         /* XXXVIX this switch statement is too sparse to gen a jump table. */
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; /*%< XXX */
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  * Set the flags on a key, then recompute the key ID
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  *** Static methods
01387  ***/
01388 
01389 /*%
01390  * Allocates a key structure and fills in some of the fields.
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  * Reads a public key from disk
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          * Open the file and read its formatted contents
01488          * File format:
01489          *    domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
01490          */
01491 
01492         /* 1500 should be large enough for any key */
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         /* Read the domain name */
01520         NEXTTOKEN(lex, opt, &token);
01521         if (token.type != isc_tokentype_string)
01522                 BADTOKEN();
01523 
01524         /*
01525          * We don't support "@" in .key files.
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         /* Read the next word: either TTL, class, or 'KEY' */
01539         NEXTTOKEN(lex, opt, &token);
01540 
01541         if (token.type != isc_tokentype_string)
01542                 BADTOKEN();
01543 
01544         /* If it's a TTL, read the next one */
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; /*%< SIG(0), TKEY */
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         /* XXXVIX this switch statement is too sparse to gen a jump table. */
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  * Write key timing metadata to a file pointer, preceded by 'tag'
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]; /* Minimum buffer as per ctime_r() specification. */
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         /* time_t and isc_stdtime_t might be different sizes */
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  * Writes a public key to disk in DNS format.
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          * Make the filename.
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          * Create public key file.
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         /* Write key information in comments */
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         /* Now print the actual key */
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 /* PKCS11CRYPTO */
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 /* PKCS11CRYPTO */
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                 /* Someone believes RAND_status() initializes the PRNG */
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 }

Generated on Tue Apr 28 17:40:56 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha