dst_api.c revision 63bf060be4ff2a7ade02fd86abb98694a5afc250
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/*
784a904bd06c7492361ed09a882d10c636b1291bAutomatic Updater * Portions Copyright (c) 1995-1999 by Network Associates, Inc.
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * copyright notice and this permission notice appear in all copies.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley *
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND NETWORK ASSOCIATES
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * NETWORK ASSOCIATES BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
28a8f5b0de57d269cf2845c69cb6abe18cbd3b3aMark Andrews/*
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * Principal Author: Brian Wellington
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * $Id: dst_api.c,v 1.27 2000/04/12 15:52:11 bwelling Exp $
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <config.h>
f1788d67add6bf3d301e91b3f54fa3c90a87328eBrian Wellington
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <ctype.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <limits.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <stdio.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <stdlib.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <string.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/assertions.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/buffer.h>
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews#include <isc/dir.h>
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews#include <isc/error.h>
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews#include <isc/int.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/lex.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/mem.h>
c1ee8bb4ba3e9ab1463403ed685729631de406b1Mark Andrews#include <isc/mutex.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/once.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/random.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/region.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <isc/time.h>
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews#include <dns/rdata.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <dns/keyvalues.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <openssl/rand.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include "dst_internal.h"
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include "dst/result.h"
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define KEY_MAGIC 0x44535421U /* DST! */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define VALID_KEY(key) (key != NULL && key->magic == KEY_MAGIC)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrewsdst_func *dst_t_func[DST_MAX_ALGS];
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic isc_mem_t *dst_memory_pool = NULL;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic isc_once_t once = ISC_ONCE_INIT;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic isc_mutex_t random_lock;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/* Static functions */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void initialize(void);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic dst_key_t * get_key_struct(const char *name, const int alg,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley const int flags, const int protocol,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley const int bits, isc_mem_t *mctx);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic isc_result_t read_public_key(const char *name,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley const isc_uint16_t id, int in_alg,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_mem_t *mctx, dst_key_t **keyp);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic isc_result_t write_public_key(const dst_key_t *key);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/*
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * dst_supported_algorithm
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * This function determines if the crypto system for the specified
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * algorithm is present.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Parameters
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * alg The algorithm to test
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Returns
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * ISC_TRUE The algorithm is available.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * ISC_FALSE The algorithm is not available.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_boolean_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydst_supported_algorithm(const int alg) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews return (ISC_FALSE);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_TRUE);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * dst_sign
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * An incremental signing function. Data is signed in steps.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * First the context must be initialized (DST_SIGMODE_INIT).
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Then data is hashed (DST_SIGMODE_UPDATE). Finally the signature
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * itself is created (DST_SIGMODE_FINAL). This function can be called
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * once with DST_SIGMODE_ALL set, or it can be called separately
7cd4c3ddd1baf5f2b204562fdba3da37c716cc78Andreas Gustafsson * for each step. The UPDATE step may be repeated.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Parameters
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * mode A bit mask specifying operation(s) to be performed.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * DST_SIGMODE_INIT Initialize digest
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * DST_SIGMODE_UPDATE Add data to digest
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * DST_SIGMODE_FINAL Generate signature
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * DST_SIGMODE_ALL Perform all operations
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * key The private key used to sign the data
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * context The state of the operation
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * data The data to be signed.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * sig The buffer to which the signature will be written.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Return
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * ISC_R_SUCCESS Success
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * !ISC_R_SUCCESS Failure
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydst_sign(const unsigned int mode, dst_key_t *key, dst_context_t *context,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_region_t *data, isc_buffer_t *sig)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley{
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE((mode & DST_SIGMODE_ALL) != 0);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if ((mode & DST_SIGMODE_UPDATE) != 0)
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley REQUIRE(data != NULL && data->base != NULL);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if ((mode & DST_SIGMODE_FINAL) != 0)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley REQUIRE(sig != NULL);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (dst_supported_algorithm(key->key_alg) == ISC_FALSE)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (DST_R_UNSUPPORTEDALG);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (key->opaque == NULL)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (DST_R_NULLKEY);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (key->func->sign == NULL)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (DST_R_NOTPRIVATEKEY);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (key->func->sign(mode, key, (void **)context, data, sig,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley key->mctx));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews/*
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * dst_verify
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * An incremental verify function. Data is verified in steps.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * First the context must be initialized (DST_SIGMODE_INIT).
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Then data is hashed (DST_SIGMODE_UPDATE). Finally the signature
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * is verified (DST_SIGMODE_FINAL). This function can be called
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * once with DST_SIGMODE_ALL set, or it can be called separately
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * for each step. The UPDATE step may be repeated.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Parameters
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * mode A bit mask specifying operation(s) to be performed.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * DST_SIGMODE_INIT Initialize digest
7cd4c3ddd1baf5f2b204562fdba3da37c716cc78Andreas Gustafsson * DST_SIGMODE_UPDATE Add data to digest
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley * DST_SIGMODE_FINAL Verify signature
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * DST_SIGMODE_ALL Perform all operations
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews * key The public key used to verify the signature.
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews * context The state of the operation
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews * data The data to be digested.
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews * sig The signature.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Returns
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * ISC_R_SUCCESS Success
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * !ISC_R_SUCCESS Failure
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halleyisc_result_t
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halleydst_verify(const unsigned int mode, dst_key_t *key, dst_context_t *context,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley isc_region_t *data, isc_region_t *sig)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley{
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley REQUIRE(VALID_KEY(key));
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley REQUIRE((mode & DST_SIGMODE_ALL) != 0);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if ((mode & DST_SIGMODE_UPDATE) != 0)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley REQUIRE(data != NULL && data->base != NULL);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if ((mode & DST_SIGMODE_FINAL) != 0)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley REQUIRE(sig != NULL && sig->base != NULL);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley if (dst_supported_algorithm(key->key_alg) == ISC_FALSE)
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley return (DST_R_UNSUPPORTEDALG);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (key->opaque == NULL)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley return (DST_R_NULLKEY);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (key->func->verify == NULL)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley return (DST_R_NOTPUBLICKEY);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley return (key->func->verify(mode, key, (void **)context, data, sig,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley key->mctx));
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley}
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley/*
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * dst_digest
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * An incremental digest function. Data is digested in steps.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * First the context must be initialized (DST_SIGMODE_INIT).
fbe2cff19f5cddc67b967764ad95038dfcafc85aEvan Hunt * Then data is hashed (DST_SIGMODE_UPDATE). Finally the digest
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * is generated (DST_SIGMODE_FINAL). This function can be called
b5fff54fe9335b20c02d749831fc0eaeda97198fBrian Wellington * once with DST_SIGMODE_ALL set, or it can be called separately
b5fff54fe9335b20c02d749831fc0eaeda97198fBrian Wellington * for each step. The UPDATE step may be repeated.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Parameters
32f985bcf464816d3a8700185afdebb122cb4cecMark Andrews * mode A bit mask specifying operation(s) to be performed.
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * DST_SIGMODE_INIT Initialize digest
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * DST_SIGMODE_UPDATE Add data to digest
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * DST_SIGMODE_FINAL Complete digest
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * DST_SIGMODE_ALL Perform all operations
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * alg The digest algorithm to use
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * context The state of the operation
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * data The data to be digested.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * sig The sdigest.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Returns
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * ISC_R_SUCCESS Success
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * !ISC_R_SUCCESS Failure
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews */
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsisc_result_t
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdst_digest(const unsigned int mode, const unsigned int alg,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews dst_context_t *context, isc_region_t *data, isc_buffer_t *digest)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews{
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE((mode & DST_SIGMODE_ALL) != 0);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if ((mode & DST_SIGMODE_UPDATE) != 0)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(data != NULL && data->base != NULL);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if ((mode & DST_SIGMODE_FINAL) != 0)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley REQUIRE(digest != NULL);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (alg != DST_DIGEST_MD5)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (DST_R_UNSUPPORTEDALG);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (dst_s_md5(mode, context, data, digest, dst_memory_pool));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley/*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * dst_computesecret
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * A function to compute a shared secret from two (Diffie-Hellman) keys.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * Parameters
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * pub The public key
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * priv The private key
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * secret A buffer into which the secret is written
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * Returns
c1ee8bb4ba3e9ab1463403ed685729631de406b1Mark Andrews * ISC_R_SUCCESS Success
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * !ISC_R_SUCCESS Failure
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydst_computesecret(const dst_key_t *pub, const dst_key_t *priv,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_buffer_t *secret)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley{
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson REQUIRE(secret != NULL);
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley
6de9744cf9c64be2145f663e4051196a4eaa9d45Evan Hunt if (dst_supported_algorithm(pub->key_alg) == ISC_FALSE ||
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews dst_supported_algorithm(priv->key_alg) == ISC_FALSE)
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews return (DST_R_UNSUPPORTEDALG);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (pub->opaque == NULL || priv->opaque == NULL)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (DST_R_NULLKEY);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
08af8bf5ade4131fe44926ad04fd489e64a620bbBob Halley if (pub->key_alg != priv->key_alg ||
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley pub->func->computesecret == NULL ||
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley priv->func->computesecret == NULL)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (DST_R_KEYCANNOTCOMPUTESECRET);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
b2ca6fd3a8293440b4d263723525396059cf2400Brian Wellington if (dst_key_isprivate(priv) == ISC_FALSE)
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington return (DST_R_NOTPRIVATEKEY);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews return (pub->func->computesecret(pub, priv, secret));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley}
8569ab045a4cf6ecd1b5a3354ddb1c93ef34ea57Brian Wellington
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley/*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * dst_key_tofile
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Writes a key to disk. The key can either be a public or private key.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * The public key is written in DNS format and the private key is
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * written as a set of base64 encoded values.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Parameters
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * key The key to be written.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * type Either DST_PUBLIC or DST_PRIVATE, or both
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Returns
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * ISC_R_SUCCESS Success
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * !ISC_R_SUCCESS Failure
569d094440399b000e059d4cb3434391c2c4d330Michael Graff */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
6de9744cf9c64be2145f663e4051196a4eaa9d45Evan Huntdst_key_tofile(const dst_key_t *key, const int type) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley int ret = ISC_R_SUCCESS;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (dst_supported_algorithm(key->key_alg) == ISC_FALSE)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (DST_R_UNSUPPORTEDALG);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == 0)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (DST_R_UNSUPPORTEDTYPE);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (type & DST_TYPE_PUBLIC)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if ((ret = write_public_key(key)) != ISC_R_SUCCESS)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ret);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if ((type & DST_TYPE_PRIVATE) &&
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews ret = key->func->to_file(key);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (ret != ISC_R_SUCCESS)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ret);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ret);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley}
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence/*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * dst_key_fromfile
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews * Reads a key from disk. The key can either be a public or private
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * key, and is specified by name, algorithm, and id.
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * Parameters
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * name The key name.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * id The id of the key.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * alg The algorithm of the key.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * type Either DST_PUBLIC or DST_PRIVATE
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * mctx Memory context used to allocate key structure
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * keyp Returns the new key
b2ca6fd3a8293440b4d263723525396059cf2400Brian Wellington * Returns
b2ca6fd3a8293440b4d263723525396059cf2400Brian Wellington * ISC_R_SUCCESS Success
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington * !ISC_R_SUCCESS Failure
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleyisc_result_t
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleydst_key_fromfile(const char *name, const isc_uint16_t id, const int alg,
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley const int type, isc_mem_t *mctx, dst_key_t **keyp)
94a08e09db3dc844b6ee4841c368a2d7074a9c3fAndreas Gustafsson{
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dst_key_t *key = NULL, *pubkey = NULL;
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff isc_result_t ret;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley REQUIRE(name != NULL);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley REQUIRE(mctx != NULL);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley REQUIRE(keyp != NULL);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
8569ab045a4cf6ecd1b5a3354ddb1c93ef34ea57Brian Wellington *keyp = NULL;
8569ab045a4cf6ecd1b5a3354ddb1c93ef34ea57Brian Wellington if (dst_supported_algorithm(alg) == ISC_FALSE)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (DST_R_UNSUPPORTEDALG);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == 0)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (DST_R_UNSUPPORTEDTYPE);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley ret = read_public_key(name, id, alg, mctx, &pubkey);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (ret == ISC_R_NOTFOUND && (type & DST_TYPE_PUBLIC) == 0)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley key = get_key_struct(name, alg, 0, 0, 0, mctx);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley else if (ret != ISC_R_SUCCESS)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ret);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley else {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (type == DST_TYPE_PUBLIC ||
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) ==
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley DNS_KEYTYPE_NOKEY)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley *keyp = pubkey;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_R_SUCCESS);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley key = get_key_struct(name, pubkey->key_alg, pubkey->key_flags,
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley pubkey->key_proto, 0, mctx);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dst_key_free(pubkey);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence if (key == NULL)
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence return (ISC_R_NOMEMORY);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence /* Fill in private key and some fields in the general key structure */
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence ret = key->func->from_file(key, id, mctx);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (ret != ISC_R_SUCCESS) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dst_key_free(key);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ret);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews }
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews *keyp = key;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (ISC_R_SUCCESS);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley/*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * dst_key_todns
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Function to encode a public key into DNS KEY format
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Parameters
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * key Key structure to encode.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * target Buffer to write the encoded key into.
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence * Returns
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence * ISC_R_SUCCESS Success
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * !ISC_R_SUCCESS Failure
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleyisc_result_t
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleydst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_region_t r;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(VALID_KEY(key));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(target != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (dst_supported_algorithm(key->key_alg) == ISC_FALSE)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (DST_R_UNSUPPORTEDALG);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_available(target, &r);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (r.length < 4)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_NOSPACE);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (key->key_flags & DNS_KEYFLAG_EXTENDED) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_available(target, &r);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (r.length < 2)
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews return (ISC_R_NOSPACE);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_putuint16(target,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews (isc_uint16_t)((key->key_flags >> 16)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews & 0xffff));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews }
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (key->opaque == NULL) /* NULL KEY */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (key->func->to_dns(key, target));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews/*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * dst_key_fromdns
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * This function converts the contents of a DNS KEY RR into a key
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Paramters
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * name Name of the new key
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews * source A buffer containing the KEY RR
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * mctx The memory context used to allocate the key
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * keyp Returns the new key
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Returns
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews * ISC_R_SUCCESS Success
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * !ISC_R_SUCCESS Failure
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsisc_result_t
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsdst_key_fromdns(const char *name, isc_buffer_t *source, isc_mem_t *mctx,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dst_key_t **keyp)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews{
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_region_t r;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_uint8_t alg, proto;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_uint32_t flags, extflags;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_result_t ret;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE (name != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE (source != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE (mctx != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE (keyp != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_remaining(source, &r);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (r.length < 4) /* 2 bytes of flags, 1 proto, 1 alg */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (DST_R_INVALIDPUBLICKEY);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews flags = isc_buffer_getuint16(source);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews proto = isc_buffer_getuint8(source);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews alg = isc_buffer_getuint8(source);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (!dst_supported_algorithm(alg))
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (DST_R_UNSUPPORTEDALG);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews if (flags & DNS_KEYFLAG_EXTENDED) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_remaining(source, &r);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (r.length < 2)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (DST_R_INVALIDPUBLICKEY);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews extflags = isc_buffer_getuint16(source);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews flags |= (extflags << 16);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews }
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews *keyp = get_key_struct(name, alg, flags, proto, 0, mctx);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (*keyp == NULL)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_NOMEMORY);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews ret = (*keyp)->func->from_dns(*keyp, source, mctx);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (ret != ISC_R_SUCCESS)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews dst_key_free((*keyp));
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ret);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews}
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
32f985bcf464816d3a8700185afdebb122cb4cecMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews/*
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * dst_key_frombuffer
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Function to convert raw data into a public key. The raw data format
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * is basically DNS KEY rdata format.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Parameters
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * name The key name
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * alg The algorithm
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * flags The key's flags
7ac0df532272d803c3f72ff7a109587e92622f5aMark Andrews * protocol The key's protocol
7ac0df532272d803c3f72ff7a109587e92622f5aMark Andrews * source A buffer containing the key
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 * mctx The memory context used to allocate the key
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 * keyp Returns the new key
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 * Returns
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * ISC_R_SUCCESS Success
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * !ISC_R_SUCCESS Failure
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews */
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsisc_result_t
7ac0df532272d803c3f72ff7a109587e92622f5aMark Andrewsdst_key_frombuffer(const char *name, const int alg, const int flags,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews const int protocol, isc_buffer_t *source, isc_mem_t *mctx,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dst_key_t **keyp)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews{
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_result_t ret;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(name != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(source != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(mctx != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (dst_supported_algorithm(alg) == ISC_FALSE)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (DST_R_UNSUPPORTEDALG);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews *keyp = get_key_struct(name, alg, flags, protocol, 0, mctx);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (*keyp == NULL)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_NOMEMORY);
6de9744cf9c64be2145f663e4051196a4eaa9d45Evan Hunt
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews ret = (*keyp)->func->from_dns((*keyp), source, mctx);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (ret != ISC_R_SUCCESS) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews dst_key_free((*keyp));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ret);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews }
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_R_SUCCESS);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews/*
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * dst_key_tobuffer
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Function to convert a public key into raw data. The raw data format
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * is basically DNS KEY rdata format.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Parameters
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * key The key
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * target The buffer to be written into.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Returns
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * ISC_R_SUCCESS Success
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * !ISC_R_SUCCESS Failure
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsisc_result_t
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsdst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(VALID_KEY(key));
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(target != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (dst_supported_algorithm(key->key_alg) == ISC_FALSE)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (DST_R_UNSUPPORTEDALG);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->func->to_dns(key, target));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews/*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * dst_key_generate
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Generate a public/private keypair.
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Parameters
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * name Name of the new key. Used to create key files
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * K<name>+<alg>+<id>.public
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * K<name>+<alg>+<id>.private
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * alg The algorithm to use
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * bits Size of the new key in bits
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * param Algorithm specific
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * RSA: exponent
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * 0 use exponent 3
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * !0 use Fermat4 (2^16 + 1)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * DH: generator
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * 0 default - use well-known prime if bits == 768
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * or 1024, otherwise use generator 2
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * !0 use this value as the generator
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * DSA/HMACMD5: unused
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * flags The default value of the DNS Key flags.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * protocol Default value of the DNS Key protocol field.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * mctx The memory context used to allocate the key
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * keyp Returns the new key
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews *
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Return
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * ISC_R_SUCCESS Success
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * !ISC_R_SUCCESS Failure
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews */
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsisc_result_t
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsdst_key_generate(const char *name, const int alg, const int bits,
515c7f3c43f76d7b439905b18009105364b36100Automatic Updater const int exp, const int flags, const int protocol,
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews isc_mem_t *mctx, dst_key_t **keyp)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews{
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews isc_result_t ret;
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(name != NULL);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(mctx != NULL);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(keyp != NULL);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (dst_supported_algorithm(alg) == ISC_FALSE)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (DST_R_UNSUPPORTEDALG);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews *keyp = get_key_struct(name, alg, flags, protocol, bits, mctx);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (*keyp == NULL)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_R_NOMEMORY);
6de9744cf9c64be2145f663e4051196a4eaa9d45Evan Hunt
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (bits == 0) { /* NULL KEY */
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews (*keyp)->key_flags |= DNS_KEYTYPE_NOKEY;
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_R_SUCCESS);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews }
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews ret = (*keyp)->func->generate(*keyp, exp, mctx);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (ret != ISC_R_SUCCESS) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews dst_key_free(*keyp);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ret);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews }
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_R_SUCCESS);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews}
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews/*
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * dst_key_compare
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Compares two keys for equality.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Parameters
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * key1, key2 Two keys to be compared.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Returns
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * ISC_TRUE The keys are equal.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * ISC_FALSE The keys are not equal.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews */
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsisc_boolean_t
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsdst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(VALID_KEY(key1));
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(VALID_KEY(key2));
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (key1 == key2)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_TRUE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (key1 == NULL || key2 == NULL)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_FALSE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (key1->key_alg == key2->key_alg &&
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews key1->key_id == key2->key_id &&
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews key1->func->compare(key1, key2) == ISC_TRUE)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_TRUE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews else
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_FALSE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews}
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews/*
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * dst_key_paramcompare
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Compares two keys' parameters for equality. This is designed to
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * determine if two (Diffie-Hellman) keys can be used to derive a shared
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * secret.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Parameters
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * key1, key2 Two keys whose parameters are to be compared.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * Returns
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * ISC_TRUE The keys' parameters are equal.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews * ISC_FALSE The keys' parameters are not equal.
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews */
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsisc_boolean_t
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsdst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(VALID_KEY(key1));
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews REQUIRE(VALID_KEY(key2));
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (key1 == key2)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_TRUE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (key1 == NULL || key2 == NULL)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_FALSE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (key1->key_alg == key2->key_alg &&
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews key1->func->paramcompare != NULL &&
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews key1->func->paramcompare(key1, key2) == ISC_TRUE)
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_TRUE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews else
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews return (ISC_FALSE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews}
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews/*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * dst_key_free
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Release all data structures pointed to by a key structure.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Parameters
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * key Key structure to be freed.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsvoid
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsdst_key_free(dst_key_t *key) {
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews isc_mem_t *mctx;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(VALID_KEY(key));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews mctx = key->mctx;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (key->opaque != NULL)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews key->func->destroy(key->opaque, mctx);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_mem_free(mctx, key->key_name);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews memset(key, 0, sizeof(dst_key_t));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews isc_mem_put(mctx, key, sizeof(dst_key_t));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewschar *
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdst_key_name(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->key_name);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsint
6de9744cf9c64be2145f663e4051196a4eaa9d45Evan Huntdst_key_size(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->key_size);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsint
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdst_key_proto(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->key_proto);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsint
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdst_key_alg(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->key_alg);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsisc_uint32_t
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrewsdst_key_flags(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->key_flags);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsisc_uint16_t
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdst_key_id(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->key_id);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsisc_boolean_t
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdst_key_isprivate(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (key->func->isprivate(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsisc_boolean_t
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrewsdst_key_iszonekey(const dst_key_t *key) {
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(VALID_KEY(key));
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if ((key->key_flags & DNS_KEYTYPE_NOAUTH) != 0)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (ISC_FALSE);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if ((key->key_flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (ISC_FALSE);
b335299322e50f045f10e4636262cd2f8d407a8bMark Andrews if (key->key_proto != DNS_KEYPROTO_DNSSEC &&
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews key->key_proto != DNS_KEYPROTO_ANY)
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (ISC_FALSE);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews return (ISC_TRUE);
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews}
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews/*
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * dst_sig_size
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Computes the maximum size of a signature generated by the given key
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * Parameters
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * key The DST key
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * n Stores the number of bytes necessary to hold a signature
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews * with the key.
* Returns
* ISC_R_SUCCESS
* DST_R_UNSUPPORTEDALG
*/
isc_result_t
dst_sig_size(const dst_key_t *key, unsigned int *n) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
REQUIRE(VALID_KEY(key));
REQUIRE(n != NULL);
switch (key->key_alg) {
case DST_ALG_RSA:
*n = (key->key_size + 7) / 8;
break;
case DST_ALG_DSA:
*n = DNS_SIG_DSASIGSIZE;
break;
case DST_ALG_HMACMD5:
*n = 16;
break;
case DST_ALG_HMACSHA1:
*n = 20;
break;
case DST_ALG_DH:
default:
return (DST_R_UNSUPPORTEDALG);
}
return (ISC_R_SUCCESS);
}
/*
* dst_secret_size
* Computes the maximum size of a shared secret generated by the given key
* Parameters
* key The DST key
* n Stores the number of bytes necessary to hold a shared secret
* generated by the key.
* Returns
* ISC_R_SUCCESS
* DST_R_UNSUPPORTEDALG
*/
isc_result_t
dst_secret_size(const dst_key_t *key, unsigned int *n) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
REQUIRE(VALID_KEY(key));
REQUIRE(n != NULL);
switch (key->key_alg) {
case DST_ALG_DH:
*n = (key->key_size + 7) / 8;
break;
case DST_ALG_RSA:
case DST_ALG_DSA:
case DST_ALG_HMACMD5:
case DST_ALG_HMACSHA1:
default:
return (DST_R_UNSUPPORTEDALG);
}
return (ISC_R_SUCCESS);
}
/*
* dst_random_get
* a random number generator that can generate different levels of
* randomness
* Parameters
* mode selects the random number generator
* wanted the number of random bytes requested
* target the buffer to store the random data
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_random_get(const unsigned int wanted, isc_buffer_t *target) {
isc_region_t r;
int status;
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
REQUIRE(target != NULL);
isc_buffer_available(target, &r);
if (r.length < wanted)
return (ISC_R_NOSPACE);
RUNTIME_CHECK(isc_mutex_lock((&random_lock)) == ISC_R_SUCCESS);
status = RAND_bytes(r.base, wanted);
RUNTIME_CHECK(isc_mutex_unlock((&random_lock)) == ISC_R_SUCCESS);
if (status == 0)
return (DST_R_NORANDOMNESS);
isc_buffer_add(target, wanted);
return (ISC_R_SUCCESS);
}
/***
*** Static methods
***/
/*
* initialize
* This function initializes the Digital Signature Toolkit.
* Parameters
* none
* Returns
* none
*/
static void
initialize() {
memset(dst_t_func, 0, sizeof(dst_t_func));
RUNTIME_CHECK(isc_mem_create(0, 0, &dst_memory_pool) == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_mutex_init(&random_lock) == ISC_R_SUCCESS);
dst_result_register();
dst_s_hmacmd5_init();
#if defined(BSAFE) || defined(DNSSAFE)
dst_s_bsafersa_init();
#endif
#ifdef OPENSSL
dst_s_openssldsa_init();
dst_s_openssldh_init();
/*
* Seed the random number generator, if necessary.
* XXX This doesn't do a very good job, and must be fixed.
*/
if (RAND_status() == 0) {
isc_random_t rctx;
isc_uint32_t val;
isc_time_t now;
isc_result_t result;
isc_random_init(&rctx);
result = isc_time_now(&now);
INSIST(result == ISC_R_SUCCESS);
isc_random_seed(&rctx, isc_time_nanoseconds(&now));
while (RAND_status() == 0) {
isc_random_get(&rctx, &val);
RAND_add(&val, sizeof(isc_uint32_t), 1);
}
isc_random_invalidate(&rctx);
}
#endif
}
/*
* get_key_struct
* This function allocates key structure and fills in some of the
* fields of the structure.
* Parameters:
* name the name of the key
* alg the algorithm number
* flags the dns flags of the key
* protocol the dns protocol of the key
* bits the size of the key
* mctx the memory context to allocate from
* Returns:
* NULL error
* valid pointer otherwise
*/
static dst_key_t *
get_key_struct(const char *name, const int alg, const int flags,
const int protocol, const int bits, isc_mem_t *mctx)
{
dst_key_t *key;
REQUIRE(dst_supported_algorithm(alg) != ISC_FALSE);
key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
if (key == NULL)
return (NULL);
memset(key, 0, sizeof(dst_key_t));
key->magic = KEY_MAGIC;
if (name[strlen(name) - 1] == '.') {
key->key_name = isc_mem_strdup(mctx, name);
if (key->key_name == NULL) {
isc_mem_free(mctx, key);
return (NULL);
}
}
else {
key->key_name = isc_mem_allocate(mctx, strlen(name) + 2);
if (key->key_name == NULL) {
isc_mem_free(mctx, key);
return (NULL);
}
sprintf(key->key_name, "%s.", name);
}
key->key_alg = alg;
key->key_flags = flags;
key->key_proto = protocol;
key->mctx = mctx;
key->opaque = NULL;
key->key_size = bits;
key->func = dst_t_func[alg];
return (key);
}
/*
* dst_read_public_key
* Read a public key from disk
* Parameters
* name The name
* id The id
* alg The algorithm
* mctx The memory context used to allocate the key
* keyp Returns the new key
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
read_public_key(const char *name, const isc_uint16_t id, int alg,
isc_mem_t *mctx, dst_key_t **keyp)
{
char filename[ISC_DIR_NAMEMAX];
u_char rdatabuf[DST_KEY_MAXSIZE];
isc_buffer_t b;
isc_lex_t *lex = NULL;
isc_token_t token;
isc_result_t ret;
dns_rdata_t rdata;
unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
if (dst_s_build_filename(filename, name, id, alg, PUBLIC_KEY,
sizeof(filename)) != ISC_R_SUCCESS)
return (DST_R_NAMETOOLONG);
/*
* Open the file and read its formatted contents
* File format:
* domain.name [ttl] [IN] KEY <flags> <protocol> <algorithm> <key>
*/
/* 1500 should be large enough for any key */
ret = isc_lex_create(mctx, 1500, &lex);
if (ret != ISC_R_SUCCESS)
return (ISC_R_NOMEMORY);
ret = isc_lex_openfile(lex, filename);
if (ret != ISC_R_SUCCESS) {
if (ret == ISC_R_FAILURE)
ret = ISC_R_NOTFOUND;
goto cleanup;
}
#define NEXTTOKEN(lex, opt, token) { \
ret = isc_lex_gettoken(lex, opt, token); \
if (ret != ISC_R_SUCCESS) \
goto cleanup; \
}
#define BADTOKEN() { \
ret = ISC_R_UNEXPECTEDTOKEN; \
goto cleanup; \
}
/* Read the domain name */
NEXTTOKEN(lex, opt, &token);
/* Read the next word: either TTL, 'IN', or 'KEY' */
NEXTTOKEN(lex, opt, &token);
/* If it's a TTL, read the next one */
if (token.type == isc_tokentype_number)
NEXTTOKEN(lex, opt, &token);
if (token.type != isc_tokentype_string)
BADTOKEN();
if (strcasecmp(token.value.as_pointer, "IN") == 0)
NEXTTOKEN(lex, opt, &token);
if (token.type != isc_tokentype_string)
BADTOKEN();
if (strcasecmp(token.value.as_pointer, "KEY") != 0)
BADTOKEN();
isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf), ISC_BUFFERTYPE_BINARY);
ret = dns_rdata_fromtext(&rdata, dns_rdataclass_in, dns_rdatatype_key,
lex, NULL, ISC_FALSE, &b, NULL);
if (ret != ISC_R_SUCCESS)
goto cleanup;
ret = dst_key_fromdns(name, &b, mctx, keyp);
if (ret != ISC_R_SUCCESS || (*keyp)->key_alg != alg)
goto cleanup;
isc_lex_close(lex);
isc_lex_destroy(&lex);
return (ISC_R_SUCCESS);
cleanup:
if (lex != NULL) {
isc_lex_close(lex);
isc_lex_destroy(&lex);
}
return (ret);
}
/*
* write_public_key
* Write a key to disk in DNS format.
* Parameters
* key A DST key
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
write_public_key(const dst_key_t *key) {
FILE *fp;
isc_buffer_t keyb, textb;
isc_region_t r;
char filename[ISC_DIR_NAMEMAX];
unsigned char key_array[DST_KEY_MAXSIZE];
char text_array[DST_KEY_MAXSIZE];
isc_result_t ret;
isc_result_t dnsret;
dns_rdata_t rdata;
REQUIRE(VALID_KEY(key));
isc_buffer_init(&keyb, key_array, sizeof(key_array),
ISC_BUFFERTYPE_BINARY);
isc_buffer_init(&textb, text_array, sizeof(text_array),
ISC_BUFFERTYPE_TEXT);
ret = dst_key_todns(key, &keyb);
if (ret != ISC_R_SUCCESS)
return (ret);
isc_buffer_used(&keyb, &r);
dns_rdata_fromregion(&rdata, dns_rdataclass_in, dns_rdatatype_key, &r);
dnsret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb);
if (dnsret != ISC_R_SUCCESS)
return (DST_R_INVALIDPUBLICKEY);
dns_rdata_freestruct(&rdata);
isc_buffer_used(&textb, &r);
/*
* Make the filename.
*/
if (dst_s_build_filename(filename,
key->key_name, key->key_id, key->key_alg,
PUBLIC_KEY, sizeof(filename)) < 0)
return (DST_R_NAMETOOLONG);
/*
* Create public key file.
*/
if ((fp = fopen(filename, "w")) == NULL)
return (DST_R_WRITEERROR);
fprintf(fp, "%s IN KEY ", key->key_name);
fwrite(r.base, 1, r.length, fp);
fputc('\n', fp);
fclose(fp);
return (ISC_R_SUCCESS);
}
void *
dst_mem_alloc(size_t size) {
INSIST(dst_memory_pool != NULL);
return (isc_mem_allocate(dst_memory_pool, size));
}
void
dst_mem_free(void *ptr) {
INSIST(dst_memory_pool != NULL);
if (ptr != NULL)
isc_mem_free(dst_memory_pool, ptr);
}
void *
dst_mem_realloc(void *ptr, size_t size) {
void *p;
INSIST(dst_memory_pool != NULL);
p = NULL;
if (size > 0) {
p = dst_mem_alloc(size);
if (p != NULL && ptr != NULL)
memcpy(p, ptr, size);
}
if (ptr != NULL)
dst_mem_free(ptr);
return (p);
}