New DST API for signing/verifying, as well as some reorganization, cleanup,

and bug fixes.
This commit is contained in:
Brian Wellington
2000-06-02 18:57:51 +00:00
parent 487791cd9c
commit 011463c376
12 changed files with 1517 additions and 2216 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@
/*
* Principal Author: Brian Wellington
* $Id: dst_api.c,v 1.42 2000/06/01 18:26:52 tale Exp $
* $Id: dst_api.c,v 1.43 2000/06/02 18:57:40 bwelling Exp $
*/
#include <config.h>
@@ -38,201 +38,141 @@
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/types.h>
#include <dns/keyvalues.h>
#include <dst/result.h>
#include "dst_internal.h"
#include "dst/result.h"
#include <openssl/rand.h>
#define KEY_MAGIC 0x44535421U /* DST! */
#define KEY_MAGIC 0x4453544BU /* DSTK */
#define CTX_MAGIC 0x44535443U /* DSTC */
#define VALID_KEY(key) ((key) != NULL && (key)->magic == KEY_MAGIC)
#define VALID_KEY(x) ISC_MAGIC_VALID(x, KEY_MAGIC)
#define VALID_CTX(x) ISC_MAGIC_VALID(x, CTX_MAGIC)
dst_func *dst_t_func[DST_MAX_ALGS];
static dst_key_t md5key;
dst_key_t *dst_key_md5 = NULL;
static dst_func *dst_t_func[DST_MAX_ALGS];
static isc_mem_t *dst_memory_pool = NULL;
static isc_once_t once = ISC_ONCE_INIT;
static isc_mutex_t random_lock;
/* Static functions */
static void initialize(void);
static dst_key_t * get_key_struct(dns_name_t *name, const int alg,
const int flags, const int protocol,
const int bits, isc_mem_t *mctx);
static dst_key_t * get_key_struct(dns_name_t *name,
const unsigned int alg,
const unsigned int flags,
const unsigned int protocol,
const unsigned int bits,
isc_mem_t *mctx);
static isc_result_t read_public_key(dns_name_t *name,
const isc_uint16_t id, int in_alg,
isc_mem_t *mctx, dst_key_t **keyp);
const isc_uint16_t id,
const unsigned int alg,
isc_mem_t *mctx,
dst_key_t **keyp);
static isc_result_t write_public_key(const dst_key_t *key);
/*
* dst_algorithm_supported
* This function determines if the crypto system for the specified
* algorithm is present.
* Parameters
* alg The algorithm to test
* Returns
* ISC_TRUE The algorithm is available.
* ISC_FALSE The algorithm is not available.
*/
isc_boolean_t
dst_algorithm_supported(const int alg) {
dst_algorithm_supported(const unsigned int alg) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
return (ISC_FALSE);
return (ISC_TRUE);
}
/*
* dst_key_sign
* An incremental signing function. Data is signed in steps.
* First the context must be initialized (DST_SIGMODE_INIT).
* Then data is hashed (DST_SIGMODE_UPDATE). Finally the signature
* itself is created (DST_SIGMODE_FINAL). This function can be called
* once with DST_SIGMODE_ALL set, or it can be called separately
* for each step. The UPDATE step may be repeated.
* Parameters
* mode A bit mask specifying operation(s) to be performed.
* DST_SIGMODE_INIT Initialize digest
* DST_SIGMODE_UPDATE Add data to digest
* DST_SIGMODE_FINAL Generate signature
* DST_SIGMODE_ALL Perform all operations
* key The private key used to sign the data
* context The state of the operation
* data The data to be signed.
* sig The buffer to which the signature will be written.
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_sign(const unsigned int mode, dst_key_t *key, dst_context_t *context,
isc_region_t *data, isc_buffer_t *sig)
{
dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
dst_context_t *dctx;
isc_result_t result;
REQUIRE(mctx != NULL);
REQUIRE(dctxp != NULL && *dctxp == NULL);
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
REQUIRE(VALID_KEY(key));
REQUIRE((mode & DST_SIGMODE_ALL) != 0);
if ((mode & DST_SIGMODE_UPDATE) != 0)
REQUIRE(data != NULL && data->base != NULL);
dctx = isc_mem_get(mctx, sizeof(dst_context_t));
if (dctx == NULL)
return (ISC_R_NOMEMORY);
dctx->key = key;
dctx->mctx = mctx;
result = key->func->createctx(key, dctx);
if (result != ISC_R_SUCCESS) {
isc_mem_put(mctx, dctx, sizeof(dst_context_t));
return (result);
}
dctx->magic = CTX_MAGIC;
*dctxp = dctx;
return (ISC_R_SUCCESS);
}
if ((mode & DST_SIGMODE_FINAL) != 0)
REQUIRE(sig != NULL);
void
dst_context_destroy(dst_context_t **dctxp) {
dst_context_t *dctx;
if (dst_algorithm_supported(key->key_alg) == ISC_FALSE)
REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
dctx = *dctxp;
dctx->key->func->destroyctx(dctx);
dctx->magic = 0;
isc_mem_put(dctx->mctx, dctx, sizeof(dst_context_t));
*dctxp = NULL;
}
isc_result_t
dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
REQUIRE(VALID_CTX(dctx));
REQUIRE(data != NULL);
return (dctx->key->func->adddata(dctx, data));
}
isc_result_t
dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
REQUIRE(VALID_CTX(dctx));
REQUIRE(sig != NULL);
if (dst_algorithm_supported(dctx->key->key_alg) == ISC_FALSE)
return (DST_R_UNSUPPORTEDALG);
if (key->opaque == NULL)
if (dctx->key->opaque == NULL)
return (DST_R_NULLKEY);
if (key->func->sign == NULL)
if (dctx->key->func->sign == NULL)
return (DST_R_NOTPRIVATEKEY);
return (key->func->sign(mode, key, (void **)context, data, sig,
key->mctx));
return (dctx->key->func->sign(dctx, sig));
}
/*
* dst_key_verify
* An incremental verify function. Data is verified in steps.
* First the context must be initialized (DST_SIGMODE_INIT).
* Then data is hashed (DST_SIGMODE_UPDATE). Finally the signature
* is verified (DST_SIGMODE_FINAL). This function can be called
* once with DST_SIGMODE_ALL set, or it can be called separately
* for each step. The UPDATE step may be repeated.
* Parameters
* mode A bit mask specifying operation(s) to be performed.
* DST_SIGMODE_INIT Initialize digest
* DST_SIGMODE_UPDATE Add data to digest
* DST_SIGMODE_FINAL Verify signature
* DST_SIGMODE_ALL Perform all operations
* key The public key used to verify the signature.
* context The state of the operation
* data The data to be digested.
* sig The signature.
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_verify(const unsigned int mode, dst_key_t *key, dst_context_t *context,
isc_region_t *data, isc_region_t *sig)
{
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
REQUIRE(VALID_KEY(key));
REQUIRE((mode & DST_SIGMODE_ALL) != 0);
dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
REQUIRE(VALID_CTX(dctx));
REQUIRE(sig != NULL);
if ((mode & DST_SIGMODE_UPDATE) != 0)
REQUIRE(data != NULL && data->base != NULL);
if ((mode & DST_SIGMODE_FINAL) != 0)
REQUIRE(sig != NULL && sig->base != NULL);
if (dst_algorithm_supported(key->key_alg) == ISC_FALSE)
if (dst_algorithm_supported(dctx->key->key_alg) == ISC_FALSE)
return (DST_R_UNSUPPORTEDALG);
if (key->opaque == NULL)
if (dctx->key->opaque == NULL)
return (DST_R_NULLKEY);
if (key->func->verify == NULL)
if (dctx->key->func->verify == NULL)
return (DST_R_NOTPUBLICKEY);
return (key->func->verify(mode, key, (void **)context, data, sig,
key->mctx));
return (dctx->key->func->verify(dctx, sig));
}
/*
* dst_key_digest
* An incremental digest function. Data is digested in steps.
* First the context must be initialized (DST_SIGMODE_INIT).
* Then data is hashed (DST_SIGMODE_UPDATE). Finally the digest
* is generated (DST_SIGMODE_FINAL). This function can be called
* once with DST_SIGMODE_ALL set, or it can be called separately
* for each step. The UPDATE step may be repeated.
* Parameters
* mode A bit mask specifying operation(s) to be performed.
* DST_SIGMODE_INIT Initialize digest
* DST_SIGMODE_UPDATE Add data to digest
* DST_SIGMODE_FINAL Complete digest
* DST_SIGMODE_ALL Perform all operations
* alg The digest algorithm to use
* context The state of the operation
* data The data to be digested.
* sig The sdigest.
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_digest(const unsigned int mode, const unsigned int alg,
dst_context_t *context, isc_region_t *data,
isc_buffer_t *digest)
{
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
REQUIRE((mode & DST_SIGMODE_ALL) != 0);
dst_context_digest(dst_context_t *dctx, isc_buffer_t *digest) {
REQUIRE(VALID_CTX(dctx));
REQUIRE(digest != NULL);
if ((mode & DST_SIGMODE_UPDATE) != 0)
REQUIRE(data != NULL && data->base != NULL);
if ((mode & DST_SIGMODE_FINAL) != 0)
REQUIRE(digest != NULL);
if (alg != DST_DIGEST_MD5)
if (dst_algorithm_supported(dctx->key->key_alg) == ISC_FALSE)
return (DST_R_UNSUPPORTEDALG);
if (dctx->key->func->digest == NULL)
return (DST_R_UNSUPPORTEDALG);
return (dst_s_md5(mode, context, data, digest, dst_memory_pool));
return (dctx->key->func->digest(dctx, digest));
}
/*
* dst_key_computesecret
* A function to compute a shared secret from two (Diffie-Hellman) keys.
* Parameters
* pub The public key
* priv The private key
* secret A buffer into which the secret is written
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
isc_buffer_t *secret)
@@ -259,21 +199,9 @@ dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
return (pub->func->computesecret(pub, priv, secret));
}
/*
* dst_key_tofile
* Writes a key to disk. The key can either be a public or private key.
* The public key is written in DNS format and the private key is
* written as a set of base64 encoded values.
* Parameters
* key The key to be written.
* type Either DST_PUBLIC or DST_PRIVATE, or both
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_tofile(const dst_key_t *key, const int type) {
int ret = ISC_R_SUCCESS;
isc_result_t ret = ISC_R_SUCCESS;
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
REQUIRE(VALID_KEY(key));
@@ -291,7 +219,7 @@ dst_key_tofile(const dst_key_t *key, const int type) {
if ((type & DST_TYPE_PRIVATE) &&
(key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
{
ret = key->func->to_file(key);
ret = key->func->tofile(key);
if (ret != ISC_R_SUCCESS)
return (ret);
}
@@ -299,24 +227,10 @@ dst_key_tofile(const dst_key_t *key, const int type) {
return (ret);
}
/*
* dst_key_fromfile
* Reads a key from disk. The key can either be a public or private
* key, and is specified by name, algorithm, and id.
* Parameters
* name The key name.
* id The id of the key.
* alg The algorithm of the key.
* type Either DST_PUBLIC or DST_PRIVATE
* mctx Memory context used to allocate key structure
* keyp Returns the new key
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_fromfile(dns_name_t *name, const isc_uint16_t id, const int alg,
const int type, isc_mem_t *mctx, dst_key_t **keyp)
dst_key_fromfile(dns_name_t *name, const isc_uint16_t id,
const unsigned int alg, const int type, isc_mem_t *mctx,
dst_key_t **keyp)
{
dst_key_t *key = NULL, *pubkey = NULL;
isc_result_t ret;
@@ -357,7 +271,7 @@ dst_key_fromfile(dns_name_t *name, const isc_uint16_t id, const int alg,
/*
* Fill in private key and some fields in the general key structure.
*/
ret = key->func->from_file(key, id, mctx);
ret = key->func->fromfile(key, id);
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
@@ -367,16 +281,6 @@ dst_key_fromfile(dns_name_t *name, const isc_uint16_t id, const int alg,
return (ISC_R_SUCCESS);
}
/*
* dst_key_todns
* Function to encode a public key into DNS KEY format
* Parameters
* key Key structure to encode.
* target Buffer to write the encoded key into.
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
isc_region_t r;
@@ -407,22 +311,9 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
if (key->opaque == NULL) /* NULL KEY */
return (ISC_R_SUCCESS);
return (key->func->to_dns(key, target));
return (key->func->todns(key, target));
}
/*
* dst_key_fromdns
* This function converts the contents of a DNS KEY RR into a key
* Paramters
* name Name of the new key
* source A buffer containing the KEY RR
* mctx The memory context used to allocate the key
* keyp Returns the new key
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_fromdns(dns_name_t *name, isc_buffer_t *source, isc_mem_t *mctx,
dst_key_t **keyp)
@@ -461,7 +352,7 @@ dst_key_fromdns(dns_name_t *name, isc_buffer_t *source, isc_mem_t *mctx,
if (key == NULL)
return (ISC_R_NOMEMORY);
ret = key->func->from_dns(key, source, mctx);
ret = key->func->fromdns(key, source);
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
@@ -471,27 +362,10 @@ dst_key_fromdns(dns_name_t *name, isc_buffer_t *source, isc_mem_t *mctx,
return (ISC_R_SUCCESS);
}
/*
* dst_key_frombuffer
* Function to convert raw data into a public key. The raw data format
* is basically DNS KEY rdata format.
* Parameters
* name The key name
* alg The algorithm
* flags The key's flags
* protocol The key's protocol
* source A buffer containing the key
* mctx The memory context used to allocate the key
* keyp Returns the new key
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_frombuffer(dns_name_t *name, const int alg, const int flags,
const int protocol, isc_buffer_t *source, isc_mem_t *mctx,
dst_key_t **keyp)
dst_key_frombuffer(dns_name_t *name, const unsigned int alg,
const unsigned int flags, const unsigned int protocol,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
{
dst_key_t *key;
isc_result_t ret;
@@ -510,7 +384,7 @@ dst_key_frombuffer(dns_name_t *name, const int alg, const int flags,
if (key == NULL)
return (ISC_R_NOMEMORY);
ret = key->func->from_dns(key, source, mctx);
ret = key->func->fromdns(key, source);
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
@@ -520,17 +394,6 @@ dst_key_frombuffer(dns_name_t *name, const int alg, const int flags,
return (ISC_R_SUCCESS);
}
/*
* dst_key_tobuffer
* Function to convert a public key into raw data. The raw data format
* is basically DNS KEY rdata format.
* Parameters
* key The key
* target The buffer to be written into.
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
@@ -540,39 +403,13 @@ dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
if (dst_algorithm_supported(key->key_alg) == ISC_FALSE)
return (DST_R_UNSUPPORTEDALG);
return (key->func->to_dns(key, target));
return (key->func->todns(key, target));
}
/*
* dst_key_generate
* Generate a public/private keypair.
* Parameters
* name Name of the new key. Used to create key files
* K<name>+<alg>+<id>.public
* K<name>+<alg>+<id>.private
* alg The algorithm to use
* bits Size of the new key in bits
* param Algorithm specific
* RSA: exponent
* 0 use exponent 3
* !0 use Fermat4 (2^16 + 1)
* DH: generator
* 0 default - use well-known prime if bits == 768
* or 1024, otherwise use generator 2
* !0 use this value as the generator
* DSA/HMACMD5: unused
* flags The default value of the DNS Key flags.
* protocol Default value of the DNS Key protocol field.
* mctx The memory context used to allocate the key
* keyp Returns the new key
*
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_key_generate(dns_name_t *name, const int alg, const int bits,
const int exp, const int flags, const int protocol,
dst_key_generate(dns_name_t *name, const unsigned int alg,
const unsigned int bits, const unsigned int param,
const unsigned int flags, const unsigned int protocol,
isc_mem_t *mctx, dst_key_t **keyp)
{
dst_key_t *key;
@@ -596,7 +433,12 @@ dst_key_generate(dns_name_t *name, const int alg, const int bits,
return (ISC_R_SUCCESS);
}
ret = key->func->generate(key, exp, mctx);
if (key->func->generate == NULL) {
dst_key_free(&key);
return (DST_R_UNSUPPORTEDALG);
}
ret = key->func->generate(key, param);
if (ret != ISC_R_SUCCESS) {
dst_key_free(&key);
return (ret);
@@ -606,15 +448,6 @@ dst_key_generate(dns_name_t *name, const int alg, const int bits,
return (ISC_R_SUCCESS);
}
/*
* dst_key_compare
* Compares two keys for equality.
* Parameters
* key1, key2 Two keys to be compared.
* Returns
* ISC_TRUE The keys are equal.
* ISC_FALSE The keys are not equal.
*/
isc_boolean_t
dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
@@ -632,17 +465,7 @@ dst_key_compare(const dst_key_t *key1, const dst_key_t *key2) {
else
return (ISC_FALSE);
}
/*
* dst_key_paramcompare
* Compares two keys' parameters for equality. This is designed to
* determine if two (Diffie-Hellman) keys can be used to derive a shared
* secret.
* Parameters
* key1, key2 Two keys whose parameters are to be compared.
* Returns
* ISC_TRUE The keys' parameters are equal.
* ISC_FALSE The keys' parameters are not equal.
*/
isc_boolean_t
dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
@@ -661,12 +484,6 @@ dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
return (ISC_FALSE);
}
/*
* dst_key_free
* Release all data structures pointed to by a key structure.
* Parameters
* keyp Pointer to key structure to be freed.
*/
void
dst_key_free(dst_key_t **keyp) {
isc_mem_t *mctx;
@@ -679,7 +496,7 @@ dst_key_free(dst_key_t **keyp) {
mctx = key->mctx;
if (key->opaque != NULL)
key->func->destroy(key->opaque, mctx);
key->func->destroy(key);
dns_name_free(key->key_name, mctx);
isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
@@ -694,19 +511,19 @@ dst_key_name(const dst_key_t *key) {
return (key->key_name);
}
int
unsigned int
dst_key_size(const dst_key_t *key) {
REQUIRE(VALID_KEY(key));
return (key->key_size);
}
int
unsigned int
dst_key_proto(const dst_key_t *key) {
REQUIRE(VALID_KEY(key));
return (key->key_proto);
}
int
unsigned int
dst_key_alg(const dst_key_t *key) {
REQUIRE(VALID_KEY(key));
return (key->key_alg);
@@ -792,7 +609,7 @@ dst_key_buildfilename(const dst_key_t *key, const int type, isc_buffer_t *out)
isc_result_t
dst_key_parsefilename(isc_buffer_t *source, isc_mem_t *mctx, dns_name_t *name,
isc_uint16_t *id, int *alg, char **suffix)
isc_uint16_t *id, unsigned int *alg, char **suffix)
{
isc_result_t result = ISC_R_SUCCESS;
char c, str[6], *p, *endp;
@@ -867,17 +684,6 @@ dst_key_parsefilename(isc_buffer_t *source, isc_mem_t *mctx, dns_name_t *name,
return (ISC_R_SUCCESS);
}
/*
* dst_key_sigsize
* Computes the maximum size of a signature generated by the given key
* Parameters
* key The DST key
* n Stores the number of bytes necessary to hold a signature
* with the key.
* Returns
* ISC_R_SUCCESS
* DST_R_UNSUPPORTEDALG
*/
isc_result_t
dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
@@ -894,27 +700,14 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
case DST_ALG_HMACMD5:
*n = 16;
break;
case DST_ALG_HMACSHA1:
*n = 20;
break;
case DST_ALG_DH:
case DST_ALG_MD5:
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_key_secretsize(const dst_key_t *key, unsigned int *n) {
RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
@@ -928,25 +721,13 @@ dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
case DST_ALG_RSA:
case DST_ALG_DSA:
case DST_ALG_HMACMD5:
case DST_ALG_HMACSHA1:
case DST_ALG_MD5:
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;
@@ -990,13 +771,23 @@ initialize(void) {
dst_result_register();
dst_s_hmacmd5_init();
#if defined(BSAFE) || defined(DNSSAFE)
dst_s_bsafersa_init();
dst_s_hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]);
#ifdef DNSSAFE
dst_s_dnssafersa_init(&dst_t_func[DST_ALG_RSA]);
#endif
#ifdef OPENSSL
dst_s_openssldsa_init();
dst_s_openssldh_init();
dst_s_openssldsa_init(&dst_t_func[DST_ALG_DSA]);
dst_s_openssldh_init(&dst_t_func[DST_ALG_DH]);
dst_s_opensslmd5_init(&dst_t_func[DST_ALG_MD5]);
memset(&md5key, 0, sizeof(dst_key_t));
md5key.magic = KEY_MAGIC;
md5key.key_name = NULL;
md5key.key_alg = DST_ALG_MD5;
md5key.mctx = dst_memory_pool;
md5key.opaque = NULL;
md5key.func = dst_t_func[DST_ALG_MD5];
dst_key_md5 = &md5key;
/*
* Seed the random number generator, if necessary.
@@ -1037,8 +828,9 @@ initialize(void) {
* valid pointer otherwise
*/
static dst_key_t *
get_key_struct(dns_name_t *name, const int alg, const int flags,
const int protocol, const int bits, isc_mem_t *mctx)
get_key_struct(dns_name_t *name, const unsigned int alg,
const unsigned int flags, const unsigned int protocol,
const unsigned int bits, isc_mem_t *mctx)
{
dst_key_t *key;
isc_result_t result;
@@ -1089,7 +881,7 @@ get_key_struct(dns_name_t *name, const int alg, const int flags,
*/
static isc_result_t
read_public_key(dns_name_t *name, const isc_uint16_t id, int alg,
read_public_key(dns_name_t *name, const isc_uint16_t id, const unsigned int alg,
isc_mem_t *mctx, dst_key_t **keyp)
{
char filename[ISC_DIR_NAMEMAX];

View File

@@ -48,9 +48,9 @@ typedef struct dst_func dst_func;
struct dst_key {
unsigned int magic;
dns_name_t * key_name; /* name of the key */
int key_size; /* size of the key in bits */
int key_proto; /* protocols this key is used for */
int key_alg; /* algorithm of the key */
unsigned int key_size; /* size of the key in bits */
unsigned int key_proto; /* protocols this key is used for */
unsigned int key_alg; /* algorithm of the key */
isc_uint32_t key_flags; /* flags of the public key */
isc_uint16_t key_id; /* identifier of the key */
isc_mem_t *mctx; /* memory context */
@@ -58,51 +58,65 @@ struct dst_key {
dst_func * func; /* crypto package specific functions */
};
struct dst_context {
unsigned int magic;
dst_key_t *key;
isc_mem_t *mctx;
void *opaque;
};
struct dst_func {
isc_result_t (*sign)(const unsigned int mode, dst_key_t *key,
void **context, isc_region_t *data,
isc_buffer_t *sig, isc_mem_t *mctx);
isc_result_t (*verify)(const unsigned int mode, dst_key_t *key,
void **context, isc_region_t *data,
isc_region_t *sig, isc_mem_t *mctx);
/*
* Context functions
*/
isc_result_t (*createctx)(dst_key_t *key, dst_context_t *dctx);
void (*destroyctx)(dst_context_t *dctx);
isc_result_t (*adddata)(dst_context_t *dctx, const isc_region_t *data);
/*
* Key operations
*/
isc_result_t (*sign)(dst_context_t *dctx, isc_buffer_t *sig);
isc_result_t (*verify)(dst_context_t *dctx, const isc_region_t *sig);
isc_result_t (*digest)(dst_context_t *dctx, isc_buffer_t *digest);
isc_result_t (*computesecret)(const dst_key_t *pub,
const dst_key_t *priv,
isc_buffer_t *secret);
isc_boolean_t (*compare)(const dst_key_t *key1, const dst_key_t *key2);
isc_boolean_t (*paramcompare)(const dst_key_t *key1,
const dst_key_t *key2);
isc_result_t (*generate)(dst_key_t *key, int parms, isc_mem_t *mctx);
isc_result_t (*generate)(dst_key_t *key, int parms);
isc_boolean_t (*isprivate)(const dst_key_t *key);
void (*destroy)(void *key, isc_mem_t *mctx);
/* conversion functions */
isc_result_t (*to_dns)(const dst_key_t *key, isc_buffer_t *data);
isc_result_t (*from_dns)(dst_key_t *key, isc_buffer_t *data,
isc_mem_t *mctx);
isc_result_t (*to_file)(const dst_key_t *key);
isc_result_t (*from_file)(dst_key_t *key, const isc_uint16_t id,
isc_mem_t *mctx);
};
void (*destroy)(dst_key_t *key);
extern dst_func *dst_t_func[DST_MAX_ALGS];
/* conversion functions */
isc_result_t (*todns)(const dst_key_t *key, isc_buffer_t *data);
isc_result_t (*fromdns)(dst_key_t *key, isc_buffer_t *data);
isc_result_t (*tofile)(const dst_key_t *key);
isc_result_t (*fromfile)(dst_key_t *key, const isc_uint16_t id);
};
#ifndef DST_HASH_SIZE
#define DST_HASH_SIZE 20 /* RIPEMD160 & SHA-1 are 20 bytes, MD5 is 16 */
#endif
void
dst_s_hmacmd5_init(void);
dst_s_hmacmd5_init(struct dst_func **funcp);
void
dst_s_bsafersa_init(void);
dst_s_dnssafersa_init(struct dst_func **funcp);
void
dst_s_openssldsa_init(void);
dst_s_openssldsa_init(struct dst_func **funcp);
void
dst_s_openssldh_init(void);
dst_s_openssldh_init(struct dst_func **funcp);
void
dst_s_opensslmd5_init(struct dst_func **funcp);
/*
* Support functions.
*/
int
dst_s_calculate_bits(const unsigned char *str, const int max_bits);
isc_uint16_t
dst_s_id_calc(const unsigned char *key, const int keysize);

View File

@@ -19,7 +19,7 @@
/*
* Principal Author: Brian Wellington
* $Id: dst_parse.c,v 1.17 2000/06/01 18:26:53 tale Exp $
* $Id: dst_parse.c,v 1.18 2000/06/02 18:57:42 bwelling Exp $
*/
#include <config.h>
@@ -47,7 +47,7 @@
#define HMACMD5_STR "HMAC_MD5"
struct parse_map {
int value;
const int value;
const char *tag;
};
@@ -77,7 +77,7 @@ static struct parse_map map[] = {
};
static int
find_value(const char *s, const int alg) {
find_value(const char *s, const unsigned int alg) {
int i;
for (i = 0; ; i++) {
@@ -156,7 +156,7 @@ check_hmac_md5(const dst_private_t *priv) {
}
static int
check_data(const dst_private_t *priv, const int alg) {
check_data(const dst_private_t *priv, const unsigned int alg) {
switch (alg) {
case DST_ALG_RSA:
return (check_rsa(priv));

View File

@@ -28,8 +28,8 @@
#define MAXFIELDS 12
#define TAG_SHIFT 4
#define TAG_ALG(tag) (tag >> TAG_SHIFT)
#define TAG(alg, off) ((alg << TAG_SHIFT) + off)
#define TAG_ALG(tag) ((unsigned int)(tag) >> TAG_SHIFT)
#define TAG(alg, off) (((alg) << TAG_SHIFT) + (off))
#define RSA_NTAGS 8
#define TAG_RSA_MODULUS ((DST_ALG_RSA << TAG_SHIFT) + 0)

View File

@@ -17,7 +17,7 @@
/*
* Principal Author: Brian Wellington
* $Id: dst_result.c,v 1.9 2000/06/01 18:26:54 tale Exp $
* $Id: dst_result.c,v 1.10 2000/06/02 18:57:44 bwelling Exp $
*/
#include <config.h>
@@ -38,12 +38,12 @@ static const char *text[DST_R_NRESULTS] = {
"key name is too long", /* 6 */
"error occurred writing key to disk", /* 7 */
"invalid algorithm specific parameter", /* 8 */
"sign init failure", /* 9 */
"sign update failure", /* 10 */
"sign final failure", /* 11 */
"verify init failure", /* 12 */
"verify update failure", /* 13 */
"verify final failure", /* 14 */
"UNUSED9", /* 9 */
"UNUSED10", /* 10 */
"sign failure", /* 11 */
"UNUSED12", /* 12 */
"UNUSED13", /* 13 */
"verify failure", /* 14 */
"not a public key", /* 15 */
"not a private key", /* 16 */
"not a key that can compute a secret", /* 17 */

View File

@@ -19,7 +19,7 @@
/*
* Principal Author: Brian Wellington
* $Id: hmac_link.c,v 1.28 2000/06/01 02:33:26 bwelling Exp $
* $Id: hmac_link.c,v 1.29 2000/06/02 18:57:45 bwelling Exp $
*/
#include <config.h>
@@ -45,226 +45,191 @@
return (ret); \
} while (0)
static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
typedef struct hmackey {
unsigned char ipad[64], opad[64];
} HMAC_Key;
static struct dst_func hmacmd5_functions;
static isc_result_t
dst_hmacmd5_sign(const unsigned int mode, dst_key_t *key,
void **context, isc_region_t *data, isc_buffer_t *sig,
isc_mem_t *mctx);
hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
dst_context_t *md5ctx = NULL;
HMAC_Key *hkey = key->opaque;
isc_region_t r;
isc_result_t result;
static isc_result_t
dst_hmacmd5_verify(const unsigned int mode, dst_key_t *key, void **context,
isc_region_t *data, isc_region_t *sig, isc_mem_t *mctx);
static isc_boolean_t
dst_hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2);
static isc_result_t
dst_hmacmd5_generate(dst_key_t *key, int exp, isc_mem_t *mctx);
static isc_boolean_t
dst_hmacmd5_isprivate(const dst_key_t *key);
result = dst_context_create(DST_KEY_MD5, dctx->mctx, &md5ctx);
if (result != ISC_R_SUCCESS)
return (result);
r.base = hkey->ipad;
r.length = HMAC_LEN;
result = dst_context_adddata(md5ctx, &r);
if (result != ISC_R_SUCCESS) {
dst_context_destroy(&md5ctx);
return (result);
}
dctx->opaque = md5ctx;
return (ISC_R_SUCCESS);
}
static void
dst_hmacmd5_destroy(void *key, isc_mem_t *mctx);
hmacmd5_destroyctx(dst_context_t *dctx) {
dst_context_t *md5ctx = dctx->opaque;
static isc_result_t
dst_hmacmd5_to_dns(const dst_key_t *in_key, isc_buffer_t *data);
static isc_result_t
dst_hmacmd5_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx);
static isc_result_t
dst_hmacmd5_to_file(const dst_key_t *key);
static isc_result_t
dst_hmacmd5_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx);
/*
* dst_s_hmacmd5_init()
* Sets up function pointers for HMAC-MD5 related functions
*/
void
dst_s_hmacmd5_init(void) {
REQUIRE(dst_t_func[DST_ALG_HMACMD5] == NULL);
dst_t_func[DST_ALG_HMACMD5] = &hmacmd5_functions;
memset(&hmacmd5_functions, 0, sizeof(struct dst_func));
hmacmd5_functions.sign = dst_hmacmd5_sign;
hmacmd5_functions.verify = dst_hmacmd5_verify;
hmacmd5_functions.computesecret = NULL;
hmacmd5_functions.compare = dst_hmacmd5_compare;
hmacmd5_functions.paramcompare = NULL;
hmacmd5_functions.generate = dst_hmacmd5_generate;
hmacmd5_functions.isprivate = dst_hmacmd5_isprivate;
hmacmd5_functions.destroy = dst_hmacmd5_destroy;
hmacmd5_functions.to_dns = dst_hmacmd5_to_dns;
hmacmd5_functions.from_dns = dst_hmacmd5_from_dns;
hmacmd5_functions.to_file = dst_hmacmd5_to_file;
hmacmd5_functions.from_file = dst_hmacmd5_from_file;
if (md5ctx != NULL)
dst_context_destroy(&md5ctx);
}
/*
* dst_hmacmd5_sign
* Call HMAC-MD5 signing functions to sign a block of data.
* There are three steps to signing, INIT (initialize structures),
* UPDATE (hash (more) data), FINAL (generate a signature). This
* routine performs one or more of these steps.
* Parameters
* mode DST_SIGMODE_{INIT_UPDATE_FINAL|ALL}
* key key to use for signing
* context the context to use for this computation
* data data to be signed
* signature buffer to store signature
* mctx memory context for temporary allocations
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_hmacmd5_sign(const unsigned int mode, dst_key_t *key, void **context,
isc_region_t *data, isc_buffer_t *sig, isc_mem_t *mctx)
{
hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
dst_context_t *md5ctx = dctx->opaque;
return (dst_context_adddata(md5ctx, data));
}
static isc_result_t
hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
dst_context_t *md5ctx = dctx->opaque;
dst_key_t *key = dctx->key;
HMAC_Key *hkey = key->opaque;
isc_region_t r;
isc_result_t ret;
void *ctx;
isc_result_t result;
unsigned char digest[MD5_DIGEST_LENGTH];
isc_buffer_t b;
if ((mode & DST_SIGMODE_ALL) != DST_SIGMODE_ALL)
REQUIRE(context != NULL);
else
context = &ctx;
isc_buffer_init(&b, digest, sizeof(digest));
if (mode & DST_SIGMODE_INIT) {
HMAC_Key *hkey = key->opaque;
result = dst_context_digest(md5ctx, &b);
if (result != ISC_R_SUCCESS)
return (result);
dst_context_destroy(&md5ctx);
dctx->opaque = NULL;
r.base = hkey->ipad;
r.length = HMAC_LEN;
RETERR(dst_s_md5(DST_SIGMODE_INIT, context, NULL, NULL, mctx));
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, &r, NULL, mctx));
}
if (mode & DST_SIGMODE_UPDATE) {
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, data, NULL,
mctx));
}
if (mode & DST_SIGMODE_FINAL) {
HMAC_Key *hkey = key->opaque;
unsigned char digest[MD5_DIGEST_LENGTH];
isc_buffer_t b;
result = dst_context_create(DST_KEY_MD5, dctx->mctx, &md5ctx);
if (result != ISC_R_SUCCESS)
return (result);
dctx->opaque = md5ctx;
isc_buffer_init(&b, digest, sizeof(digest));
r.base = hkey->opad;
r.length = HMAC_LEN;
result = dst_context_adddata(md5ctx, &r);
if (result != ISC_R_SUCCESS)
return (result);
RETERR(dst_s_md5(DST_SIGMODE_FINAL, context, NULL, &b, mctx));
isc_buffer_usedregion(&b, &r);
result = dst_context_adddata(md5ctx, &r);
if (result != ISC_R_SUCCESS)
return (result);
RETERR(dst_s_md5(DST_SIGMODE_INIT, context, NULL, NULL, mctx));
r.base = hkey->opad;
r.length = HMAC_LEN;
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, &r, NULL, mctx));
isc_buffer_usedregion(&b, &r);
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, &r, NULL, mctx));
RETERR(dst_s_md5(DST_SIGMODE_FINAL, context, NULL, sig, mctx));
}
result = dst_context_digest(md5ctx, sig);
return (result);
}
static isc_result_t
hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
dst_context_t *md5ctx = dctx->opaque;
dst_key_t *key = dctx->key;
HMAC_Key *hkey = key->opaque;
isc_region_t r;
isc_result_t result;
unsigned char digest[MD5_DIGEST_LENGTH];
isc_buffer_t b;
isc_buffer_init(&b, digest, sizeof(digest));
result = dst_context_digest(md5ctx, &b);
if (result != ISC_R_SUCCESS)
return (result);
dst_context_destroy(&md5ctx);
dctx->opaque = NULL;
result = dst_context_create(DST_KEY_MD5, dctx->mctx, &md5ctx);
if (result != ISC_R_SUCCESS)
return (result);
dctx->opaque = md5ctx;
r.base = hkey->opad;
r.length = HMAC_LEN;
result = dst_context_adddata(md5ctx, &r);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_usedregion(&b, &r);
result = dst_context_adddata(md5ctx, &r);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_clear(&b);
result = dst_context_digest(md5ctx, &b);
if (result != ISC_R_SUCCESS)
return (result);
if (memcmp(digest, sig->base, MD5_DIGEST_LENGTH) != 0)
return (DST_R_VERIFYFAILURE);
return (ISC_R_SUCCESS);
}
/*
* dst_hmacmd5_verify
* Calls HMAC-MD5 verification routines. There are three steps to
* verification, INIT (initialize structures), UPDATE (hash (more) data),
* FINAL (generate a signature). This routine performs one or more of
* these steps.
* Parameters
* mode DST_SIGMODE_{INIT_UPDATE_FINAL|ALL}
* key key to use for verifying
* context the context to use for this computation
* data signed data
* signature signature
* mctx memory context for temporary allocations
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_hmacmd5_verify(const unsigned int mode, dst_key_t *key, void **context,
isc_region_t *data, isc_region_t *sig, isc_mem_t *mctx)
{
isc_region_t r;
isc_result_t ret;
void *ctx;
if ((mode & DST_SIGMODE_ALL) != DST_SIGMODE_ALL)
REQUIRE(context != NULL);
else
context = &ctx;
if (mode & DST_SIGMODE_INIT) {
HMAC_Key *hkey = key->opaque;
r.base = hkey->ipad;
r.length = HMAC_LEN;
RETERR(dst_s_md5(DST_SIGMODE_INIT, context, NULL, NULL, mctx));
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, &r, NULL, mctx));
}
if (mode & DST_SIGMODE_UPDATE) {
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, data, NULL,
mctx));
}
if (mode & DST_SIGMODE_FINAL) {
HMAC_Key *hkey = key->opaque;
unsigned char digest[MD5_DIGEST_LENGTH];
isc_buffer_t b;
isc_buffer_init(&b, digest, sizeof(digest));
RETERR(dst_s_md5(DST_SIGMODE_FINAL, context, NULL, &b, mctx));
RETERR(dst_s_md5(DST_SIGMODE_INIT, context, NULL, NULL, mctx));
r.base = hkey->opad;
r.length = HMAC_LEN;
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, &r, NULL, mctx));
isc_buffer_usedregion(&b, &r);
RETERR(dst_s_md5(DST_SIGMODE_UPDATE, context, &r, NULL, mctx));
isc_buffer_clear(&b);
RETERR(dst_s_md5(DST_SIGMODE_FINAL, context, NULL, &b, mctx));
if (memcmp(digest, sig->base, MD5_DIGEST_LENGTH) != 0)
return (DST_R_VERIFYFINALFAILURE);
}
return (ISC_R_SUCCESS);
}
/*
* dst_hmacmd5_isprivate
* Is this a private key? Yes
* Parameters
* key DST KEY structure
* Returns
* ISC_TRUE
*/
static isc_boolean_t
dst_hmacmd5_isprivate(const dst_key_t *key) {
UNUSED(key);
hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
HMAC_Key *hkey1, *hkey2;
hkey1 = (HMAC_Key *)key1->opaque;
hkey2 = (HMAC_Key *)key2->opaque;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
if (memcmp(hkey1->ipad, hkey2->ipad, HMAC_LEN) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}
static isc_result_t
hmacmd5_generate(dst_key_t *key, int unused) {
isc_buffer_t b;
isc_result_t ret;
int bytes;
unsigned char data[HMAC_LEN];
UNUSED(unused);
bytes = (key->key_size + 7) / 8;
if (bytes > 64) {
bytes = 64;
key->key_size = 512;
}
memset(data, 0, HMAC_LEN);
isc_buffer_init(&b, data, sizeof(data));
ret = dst_random_get(bytes, &b);
if (ret != ISC_R_SUCCESS)
return (ret);
ret = hmacmd5_fromdns(key, &b);
memset(data, 0, HMAC_LEN);
return (ret);
}
static isc_boolean_t
hmacmd5_isprivate(const dst_key_t *key) {
UNUSED(key);
return (ISC_TRUE);
}
/*
* dst_hmacmd5_to_dns
* Converts key from HMAC to DNS rdata (raw bytes)
* Parameters
* key DST KEY structure
* data output data
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static void
hmacmd5_destroy(dst_key_t *key) {
HMAC_Key *hkey = key->opaque;
memset(hkey, 0, sizeof(HMAC_Key));
isc_mem_put(key->mctx, hkey, sizeof(HMAC_Key));
}
static isc_result_t
dst_hmacmd5_to_dns(const dst_key_t *key, isc_buffer_t *data) {
hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
HMAC_Key *hkey;
isc_region_t r;
unsigned int bytes, i;
@@ -287,20 +252,11 @@ dst_hmacmd5_to_dns(const dst_key_t *key, isc_buffer_t *data) {
return (ISC_R_SUCCESS);
}
/*
* dst_hmacmd5_from_dns
* Converts from a DNS KEY RR format to an HMAC-MD5 KEY.
* Parameters
* key Partially filled key structure
* data Buffer containing key in DNS format
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_hmacmd5_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx) {
hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
HMAC_Key *hkey;
isc_region_t r;
isc_mem_t *mctx = key->mctx;
int i, keylen;
isc_buffer_remainingregion(data, &r);
@@ -345,18 +301,8 @@ dst_hmacmd5_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx) {
return (ISC_R_SUCCESS);
}
/*
* dst_hmacmd5_to_file
* Encodes an HMAC-MD5 Key into the portable file format.
* Parameters
* key DST KEY structure
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_hmacmd5_to_file(const dst_key_t *key) {
hmacmd5_tofile(const dst_key_t *key) {
int i, cnt = 0;
HMAC_Key *hkey;
dst_private_t priv;
@@ -379,23 +325,12 @@ dst_hmacmd5_to_file(const dst_key_t *key) {
return (dst_s_write_private_key_file(key, &priv));
}
/*
* dst_hmacmd5_from_file
* Converts contents of a private key file into a private HMAC-MD5 key.
* Parameters
* key Partially filled HMAC-MD5 KEY structure
* id The key id
* path The directory that the file will be read from
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_hmacmd5_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx) {
hmacmd5_fromfile(dst_key_t *key, const isc_uint16_t id) {
dst_private_t priv;
isc_result_t ret;
isc_buffer_t b;
isc_mem_t *mctx = key->mctx;
/* read private key file */
ret = dst_s_parse_private_key_file(key, id, &priv, mctx);
@@ -404,83 +339,34 @@ dst_hmacmd5_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx) {
isc_buffer_init(&b, priv.elements[0].data, priv.elements[0].length);
isc_buffer_add(&b, priv.elements[0].length);
ret = dst_hmacmd5_from_dns(key, &b, mctx);
dst_s_free_private_structure_fields(&priv, mctx);
memset(&priv, 0, sizeof(priv));
return (ret);
return (hmacmd5_fromdns(key, &b));
}
/*
* dst_hmacmd5_destroy
* Frees all dynamically allocated structures in key.
*/
static void
dst_hmacmd5_destroy(void *key, isc_mem_t *mctx) {
HMAC_Key *hkey = (HMAC_Key *) key;
memset(hkey, 0, sizeof(HMAC_Key));
isc_mem_put(mctx, hkey, sizeof(HMAC_Key));
static struct dst_func hmacmd5_functions = {
hmacmd5_createctx,
hmacmd5_destroyctx,
hmacmd5_adddata,
hmacmd5_sign,
hmacmd5_verify,
NULL, /* digest */
NULL, /* computesecret */
hmacmd5_compare,
NULL, /* paramcompare */
hmacmd5_generate,
hmacmd5_isprivate,
hmacmd5_destroy,
hmacmd5_todns,
hmacmd5_fromdns,
hmacmd5_tofile,
hmacmd5_fromfile,
};
void
dst_s_hmacmd5_init(struct dst_func **funcp) {
REQUIRE(funcp != NULL && *funcp == NULL);
*funcp = &hmacmd5_functions;
}
/*
* dst_hmacmd5_generate
* Creates an HMAC-MD5 key. If the specified size is more than 512
* bits, a key of size 512 is generated.
* Parameters
* key DST Key structure
* unused algorithm specific data, unused for HMAC-MD5.
* mctx memory context to allocate key
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_hmacmd5_generate(dst_key_t *key, int unused, isc_mem_t *mctx) {
isc_buffer_t b;
isc_result_t ret;
int bytes;
unsigned char data[HMAC_LEN];
UNUSED(unused);
bytes = (key->key_size + 7) / 8;
if (bytes > 64) {
bytes = 64;
key->key_size = 512;
}
memset(data, 0, HMAC_LEN);
isc_buffer_init(&b, data, sizeof(data));
ret = dst_random_get(bytes, &b);
if (ret != ISC_R_SUCCESS)
return (ret);
ret = dst_hmacmd5_from_dns(key, &b, mctx);
memset(data, 0, HMAC_LEN);
return (ret);
}
/**************************************************************************
* dst_hmacmd5_compare
* Compare two keys for equality.
* Return
* ISC_TRUE The keys are equal
* ISC_FALSE The keys are not equal
*/
static isc_boolean_t
dst_hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
HMAC_Key *hkey1, *hkey2;
hkey1 = (HMAC_Key *)key1->opaque;
hkey2 = (HMAC_Key *)key2->opaque;
if (hkey1 == NULL && hkey2 == NULL)
return (ISC_TRUE);
else if (hkey1 == NULL || hkey2 == NULL)
return (ISC_FALSE);
if (memcmp(hkey1->ipad, hkey2->ipad, HMAC_LEN) == 0)
return (ISC_TRUE);
else
return (ISC_FALSE);
}

View File

@@ -18,8 +18,8 @@ ISC_LANG_BEGINDECLS
* to set attributes, new accessor functions will be written.
*/
typedef struct dst_key dst_key_t;
typedef void * dst_context_t;
typedef struct dst_key dst_key_t;
typedef struct dst_context dst_context_t;
/* DST algorithm codes */
#define DST_ALG_UNKNOWN 0
@@ -27,22 +27,10 @@ typedef void * dst_context_t;
#define DST_ALG_DH 2
#define DST_ALG_DSA 3
#define DST_ALG_HMACMD5 157
#define DST_ALG_HMACSHA1 158 /* not implemented */
#define DST_ALG_MD5 158
#define DST_ALG_PRIVATE 254
#define DST_ALG_EXPAND 255
#define DST_MAX_ALGS DST_ALG_HMACSHA1
/* DST algorithm codes */
#define DST_DIGEST_MD5 258
#define DST_DIGEST_SHA1 259
/* 'Mode' passed into dst_sign() and dst_verify() */
#define DST_SIGMODE_INIT 1 /* initialize digest */
#define DST_SIGMODE_UPDATE 2 /* add data to digest */
#define DST_SIGMODE_FINAL 4 /* generate/verify signature */
#define DST_SIGMODE_ALL (DST_SIGMODE_INIT | \
DST_SIGMODE_UPDATE | \
DST_SIGMODE_FINAL)
#define DST_MAX_ALGS (DST_ALG_MD5 + 1)
/* A buffer of this size is large enough to hold any key */
#define DST_KEY_MAXSIZE 1024
@@ -51,93 +39,147 @@ typedef void * dst_context_t;
#define DST_TYPE_PRIVATE 0x2000000
#define DST_TYPE_PUBLIC 0x4000000
extern dst_key_t *dst_key_md5;
#define DST_KEY_MD5 dst_key_md5
/***
*** Functions
***/
isc_boolean_t
dst_algorithm_supported(const int alg);
dst_algorithm_supported(const unsigned int alg);
/*
* Check that a given algorithm is supported
* Checks that a given algorithm is supported by DST.
*
* Returns:
* ISC_TRUE
* ISC_FALSE
*/
isc_result_t
dst_key_sign(const unsigned int mode, dst_key_t *key, dst_context_t *context,
isc_region_t *data, isc_buffer_t *sig);
dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp);
/*
* Sign a block of data.
* Creates a context to be used for a sign, verify, or digest operation.
*
* Requires:
* "mode" is some combination of DST_SIGMODE_INIT, DST_SIGMODE_UPDATE,
* and DST_SIGMODE_FINAL.
* "key" is a valid key.
* "context" contains a value appropriate for the value of "mode".
* "data" is a valid region.
* "mctx" is a valid memory context.
* dctxp != NULL && *dctxp == NULL
*
* Returns:
* ISC_R_SUCCESS
* ISC_R_NOMEMORY
*
* Ensures:
* *dctxp will contain a usable context.
*/
void
dst_context_destroy(dst_context_t **dctxp);
/*
* Destroys all memory associated with a context.
*
* Requires:
* *dctxp != NULL && *dctxp == NULL
*
* Ensures:
* *dctxp == NULL
*/
isc_result_t
dst_context_adddata(dst_context_t *dctx, const isc_region_t *data);
/*
* Incrementally adds data to the context to be used in a sign, verify, or
* digest operation.
*
* Requires:
* "dctx" is a valid context
* "data" is a valid region
*
* Returns:
* ISC_R_SUCCESS
* DST_R_SIGNFAILURE
* all other errors indicate failure
*/
isc_result_t
dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig);
/*
* Computes a signature using the data and key stored in the context.
*
* Requires:
* "dctx" is a valid context.
* "sig" is a valid buffer.
*
* Returns:
* ISC_R_SUCCESS
* DST_R_VERIFYFAILURE
* all other errors indicate failure
*
* Ensures:
* All allocated memory will be freed after the FINAL call. "sig"
* will contain a signature if all operations completed successfully.
* "sig" will contain the signature
*/
isc_result_t
dst_key_verify(const unsigned int mode, dst_key_t *key, dst_context_t *context,
isc_region_t *data, isc_region_t *sig);
dst_context_verify(dst_context_t *dctx, isc_region_t *sig);
/*
* Verify a signature on a block of data.
* Verifies the signature using the data and key stored in the context.
*
* Requires:
* "mode" is some combination of DST_SIGMODE_INIT, DST_SIGMODE_UPDATE,
* and DST_SIGMODE_FINAL.
* "key" is a valid key.
* "context" contains a value appropriate for the value of "mode".
* "data" is a valid region.
* "dctx" is a valid context.
* "sig" is a valid region.
*
* Returns:
* ISC_R_SUCCESS
* all other errors indicate failure
*
* Ensures:
* All allocated memory will be freed after the FINAL call.
* "sig" will contain the signature
*/
isc_result_t
dst_key_digest(const unsigned int mode, const unsigned int alg,
dst_context_t *context, isc_region_t *data,
isc_buffer_t *digest);
dst_context_digest(dst_context_t *dctx, isc_buffer_t *digest);
/*
* Digest a block of data.
* Digests the data stored in the context.
*
* Requires:
* "mode" is some combination of DST_SIGMODE_INIT, DST_SIGMODE_UPDATE,
* and DST_SIGMODE_FINAL.
* "alg" is a valid digest algorithm
* "context" contains a value appropriate for the value of "mode".
* "data" is a valid region.
* "digest" is a valid buffer.
* "dctx" is a valid context.
* "sig" is a valid buffer.
*
* Returns:
* ISC_R_SUCCESS
* all other errors indicate failure
*
* Ensures:
* All allocated memory will be freed after the FINAL call. "digest"
* will contain a digest if all operations completed successfully.
* "digest" will contain the digest
*/
isc_result_t
dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
isc_buffer_t *secret);
/*
* A function to compute a shared secret from two (Diffie-Hellman) keys.
* Computes a shared secret from two (Diffie-Hellman) keys.
*
* Requires:
* "pub" is a valid key that can be used to derive a shared secret
* "priv" is a valid private key that can be used to derive a shared secret
* "secret" is a valid buffer
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* If successful, secret will contain the derived shared secret.
*/
isc_result_t
dst_key_fromfile(dns_name_t *name, const isc_uint16_t id, const int alg,
const int type, isc_mem_t *mctx, dst_key_t **keyp);
dst_key_fromfile(dns_name_t *name, const isc_uint16_t id,
const unsigned int alg, const int type,
isc_mem_t *mctx, dst_key_t **keyp);
/*
* Reads a key from permanent storage.
* Reads a key from permanent storage. The key can either be a public or
* key, and is specified by name, algorithm, and id.
*
* Requires:
* "name" is a valid absolute dns name.
@@ -147,6 +189,10 @@ dst_key_fromfile(dns_name_t *name, const isc_uint16_t id, const int alg,
* "mctx" is a valid memory context.
* "keyp" is not NULL and "*keyp" is NULL.
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* If successful, *keyp will contain a valid key.
*/
@@ -154,11 +200,17 @@ dst_key_fromfile(dns_name_t *name, const isc_uint16_t id, const int alg,
isc_result_t
dst_key_tofile(const dst_key_t *key, const int type);
/*
* Writes a key to permanent storage.
* Writes a key to permanent storage. The key can either be a public or
* private key. Public keys are written in DNS format and private keys
* are written as a set of base64 encoded values.
*
* Requires:
* "key" is a valid key.
* "type" is either DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or both.
* "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*/
isc_result_t
@@ -173,6 +225,10 @@ dst_key_fromdns(dns_name_t *name, isc_buffer_t *source, isc_mem_t *mctx,
* "mctx" is a valid memory context.
* "keyp" is not NULL and "*keyp" is NULL.
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* If successful, *keyp will contain a valid key, and the consumed
* pointer in data will be advanced.
@@ -187,14 +243,18 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target);
* "key" is a valid key.
* "target" is a valid buffer. There must be at least 4 bytes unused.
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* If successful, the used pointer in 'target' is advanced by at least 4.
*/
isc_result_t
dst_key_frombuffer(dns_name_t *name, const int alg, const int flags,
const int protocol, isc_buffer_t *source, isc_mem_t *mctx,
dst_key_t **keyp);
dst_key_frombuffer(dns_name_t *name, const unsigned int alg,
const unsigned int flags, const unsigned int protocol,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
/*
* Converts a buffer containing DNS KEY RDATA into a DST key.
*
@@ -205,6 +265,10 @@ dst_key_frombuffer(dns_name_t *name, const int alg, const int flags,
* "mctx" is a valid memory context.
* "keyp" is not NULL and "*keyp" is NULL.
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* If successful, *keyp will contain a valid key, and the consumed
* pointer in source will be advanced.
@@ -219,23 +283,40 @@ dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target);
* "key" is a valid key.
* "target" is a valid buffer.
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* If successful, the used pointer in 'target' is advanced.
*/
isc_result_t
dst_key_generate(dns_name_t *name, const int alg, const int bits,
const int param, const int flags, const int protocol,
dst_key_generate(dns_name_t *name, const unsigned int alg,
const unsigned int bits, const unsigned int param,
const unsigned int flags, const unsigned int protocol,
isc_mem_t *mctx, dst_key_t **keyp);
/*
* Generate a DST key (or keypair)
* Generate a DST key (or keypair) with the supplied parameters. The
* interpretation of the "param" field depends on the algorithm:
* RSA: exponent
* 0 use exponent 3
* !0 use Fermat4 (2^16 + 1)
* DH: generator
* 0 default - use well known prime if bits == 768 or 1024,
* otherwise use 2 as the generator.
* !0 use this value as the generator.
* DSA: unused
* HMACMD5:unused
*
* Requires:
* "name" is a valid absolute dns name.
* "alg" is a supported algorithm
* "bits" is a valid key size for the given algorithm
* "keyp" is not NULL and "*keyp" is NULL.
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* If successful, *keyp will contain a valid key.
*/
@@ -248,22 +329,31 @@ dst_key_compare(const dst_key_t *key1, const dst_key_t *key2);
* Requires:
* "key1" is a valid key.
* "key2" is a valid key.
*
* Returns:
* ISC_TRUE
* ISC_FALSE
*/
isc_boolean_t
dst_key_paramcompare(const dst_key_t *key1, const dst_key_t *key2);
/*
* Compares the parameters of two DST keys.
* Compares the parameters of two DST keys. This is used to determine if
* two (Diffie-Hellman) keys can be used to derive a shared secret.
*
* Requires:
* "key1" is a valid key.
* "key2" is a valid key.
*
* Returns:
* ISC_TRUE
* ISC_FALSE
*/
void
dst_key_free(dst_key_t **keyp);
/*
* Free a DST key.
* Release all memory associated with the key.
*
* Requires:
* "keyp" is not NULL and "*keyp" is a valid key.
@@ -282,13 +372,13 @@ dst_key_free(dst_key_t **keyp);
dns_name_t *
dst_key_name(const dst_key_t *key);
int
unsigned int
dst_key_size(const dst_key_t *key);
int
unsigned int
dst_key_proto(const dst_key_t *key);
int
unsigned int
dst_key_alg(const dst_key_t *key);
isc_uint32_t
@@ -313,7 +403,7 @@ dst_key_buildfilename(const dst_key_t *key, const int type, isc_buffer_t *out);
*
* Requires:
* "key" is a valid key
* "type" is either DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or 0
* "type" is either DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or 0 for no suffix.
* "out" is a valid buffer
*
* Ensures:
@@ -323,7 +413,7 @@ dst_key_buildfilename(const dst_key_t *key, const int type, isc_buffer_t *out);
isc_result_t
dst_key_parsefilename(isc_buffer_t *source, isc_mem_t *mctx, dns_name_t *name,
isc_uint16_t *id, int *alg, char **suffix);
isc_uint16_t *id, unsigned int *alg, char **suffix);
/*
* Parses a dst key filename into its components.
*
@@ -352,6 +442,9 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n);
* Returns:
* ISC_R_SUCCESS
* DST_R_UNSUPPORTEDALG
*
* Ensures:
* "n" stores the size of a generated signature
*/
isc_result_t
@@ -366,6 +459,9 @@ dst_key_secretsize(const dst_key_t *key, unsigned int *n);
* Returns:
* ISC_R_SUCCESS
* DST_R_UNSUPPORTEDALG
*
* Ensures:
* "n" stores the size of a generated shared secret
*/
isc_result_t
@@ -376,9 +472,13 @@ dst_random_get(const unsigned int wanted, isc_buffer_t *data);
* Requires:
* "data" is a valid buffer, with at least "wanted" bytes available.
*
* Returns:
* ISC_R_SUCCESS
* any other result indicates failure
*
* Ensures:
* <= wanted bytes will be written to "data", and the used pointer will
* be advanced.
* "wanted" bytes will be written to "data", and the used pointer will
* be advanced.
*/
ISC_LANG_ENDDECLS

View File

@@ -38,12 +38,12 @@
#define DST_R_NAMETOOLONG (ISC_RESULTCLASS_DST + 6)
#define DST_R_WRITEERROR (ISC_RESULTCLASS_DST + 7)
#define DST_R_INVALIDPARAM (ISC_RESULTCLASS_DST + 8)
#define DST_R_SIGNINITFAILURE (ISC_RESULTCLASS_DST + 9)
#define DST_R_SIGNUPDATEFAILURE (ISC_RESULTCLASS_DST + 10)
#define DST_R_SIGNFINALFAILURE (ISC_RESULTCLASS_DST + 11)
#define DST_R_VERIFYINITFAILURE (ISC_RESULTCLASS_DST + 12)
#define DST_R_VERIFYUPDATEFAILURE (ISC_RESULTCLASS_DST + 13)
#define DST_R_VERIFYFINALFAILURE (ISC_RESULTCLASS_DST + 14)
/* 9 is unused */
/* 10 is unused */
#define DST_R_SIGNFAILURE (ISC_RESULTCLASS_DST + 11)
/* 12 is unused */
/* 13 is unused */
#define DST_R_VERIFYFAILURE (ISC_RESULTCLASS_DST + 14)
#define DST_R_NOTPUBLICKEY (ISC_RESULTCLASS_DST + 15)
#define DST_R_NOTPRIVATEKEY (ISC_RESULTCLASS_DST + 16)
#define DST_R_KEYCANNOTCOMPUTESECRET (ISC_RESULTCLASS_DST + 17)

View File

@@ -19,7 +19,7 @@
/*
* Principal Author: Brian Wellington
* $Id: openssl_link.c,v 1.23 2000/05/15 21:30:44 bwelling Exp $
* $Id: openssl_link.c,v 1.24 2000/06/02 18:57:46 bwelling Exp $
*/
#if defined(OPENSSL)
@@ -37,240 +37,201 @@
#include <openssl/dsa.h>
#include <openssl/sha.h>
static struct dst_func openssl_functions;
static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
static isc_result_t
dst_openssl_sign(const unsigned int mode, dst_key_t *key, void **context,
isc_region_t *data, isc_buffer_t *sig, isc_mem_t *mctx);
openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
SHA_CTX *ctx;
static isc_result_t
dst_openssl_verify(const unsigned int mode, dst_key_t *key, void **context,
isc_region_t *data, isc_region_t *sig, isc_mem_t *mctx);
UNUSED(key);
static isc_boolean_t
dst_openssl_compare(const dst_key_t *key1, const dst_key_t *key2);
static isc_result_t
dst_openssl_generate(dst_key_t *key, int unused, isc_mem_t *mctx);
static isc_boolean_t
dst_openssl_isprivate(const dst_key_t *key);
ctx = isc_mem_get(dctx->mctx, sizeof(SHA_CTX));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
SHA1_Init(ctx);
dctx->opaque = ctx;
return (ISC_R_SUCCESS);
}
static void
dst_openssl_destroy(void *key, isc_mem_t *mctx);
openssldsa_destroyctx(dst_context_t *dctx) {
SHA_CTX *ctx = dctx->opaque;
isc_mem_put(dctx->mctx, ctx, sizeof(SHA_CTX));
}
static isc_result_t
dst_openssl_to_dns(const dst_key_t *in_key, isc_buffer_t *data);
static isc_result_t
dst_openssl_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx);
static isc_result_t
dst_openssl_to_file(const dst_key_t *key);
static isc_result_t
dst_openssl_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx);
openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
SHA_CTX *ctx = dctx->opaque;
SHA1_Update(ctx, data->base, data->length);
return (ISC_R_SUCCESS);
}
static int
BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size);
BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
int bytes = size - BN_num_bytes(bn);
while (bytes-- > 0)
*buf++ = 0;
BN_bn2bin(bn, buf);
return (size);
}
/*
* dst_s_openssldsa_init()
* Sets up function pointers for OpenSSL related functions
*/
void
dst_s_openssldsa_init(void) {
REQUIRE(dst_t_func[DST_ALG_DSA] == NULL);
dst_t_func[DST_ALG_DSA] = &openssl_functions;
memset(&openssl_functions, 0, sizeof(struct dst_func));
openssl_functions.sign = dst_openssl_sign;
openssl_functions.verify = dst_openssl_verify;
openssl_functions.computesecret = NULL;
openssl_functions.compare = dst_openssl_compare;
openssl_functions.paramcompare = NULL; /* is this useful for DSA? */
openssl_functions.generate = dst_openssl_generate;
openssl_functions.isprivate = dst_openssl_isprivate;
openssl_functions.destroy = dst_openssl_destroy;
openssl_functions.to_dns = dst_openssl_to_dns;
openssl_functions.from_dns = dst_openssl_from_dns;
openssl_functions.to_file = dst_openssl_to_file;
openssl_functions.from_file = dst_openssl_from_file;
CRYPTO_set_mem_functions(dst_mem_alloc, dst_mem_realloc, dst_mem_free);
}
/*
* dst_openssl_sign
* Call OpenSSL signing functions to sign a block of data.
* There are three steps to signing, INIT (initialize structures),
* UPDATE (hash (more) data), FINAL (generate a signature). This
* routine performs one or more of these steps.
* Parameters
* mode DST_SIGMODE_{INIT_UPDATE_FINAL|ALL}
* key key to use for signing
* context the context to use for this computation
* data data to be signed
* signature buffer to store signature
* mctx memory context for temporary allocations
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssl_sign(const unsigned int mode, dst_key_t *key, void **context,
isc_region_t *data, isc_buffer_t *sig, isc_mem_t *mctx)
{
openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
isc_region_t r;
SHA_CTX *ctx = NULL;
if (mode & DST_SIGMODE_INIT) {
ctx = (SHA_CTX *) isc_mem_get(mctx, sizeof(SHA_CTX));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
}
else if (context != NULL)
ctx = (SHA_CTX *) *context;
REQUIRE (ctx != NULL);
dst_key_t *key;
SHA_CTX *ctx;
DSA *dsa;
DSA_SIG *dsasig;
unsigned char digest[SHA_DIGEST_LENGTH];
if (mode & DST_SIGMODE_INIT)
SHA1_Init(ctx);
isc_buffer_availableregion(sig, &r);
if (r.length < SHA_DIGEST_LENGTH * 2 + 1)
return (ISC_R_NOSPACE);
if ((mode & DST_SIGMODE_UPDATE))
SHA1_Update(ctx, data->base, data->length);
ctx = dctx->opaque;
key = dctx->key;
dsa = key->opaque;
if (mode & DST_SIGMODE_FINAL) {
DSA *dsa;
DSA_SIG *dsasig;
unsigned char digest[SHA_DIGEST_LENGTH];
SHA1_Final(digest, ctx);
isc_buffer_availableregion(sig, &r);
if (r.length < SHA_DIGEST_LENGTH * 2 + 1)
return (ISC_R_NOSPACE);
dsasig = DSA_do_sign(digest, SHA_DIGEST_LENGTH, dsa);
if (dsasig == NULL)
return (DST_R_SIGNFAILURE);
dsa = key->opaque;
SHA1_Final(digest, ctx);
isc_mem_put(mctx, ctx, sizeof(SHA_CTX));
dsasig = DSA_do_sign(digest, SHA_DIGEST_LENGTH, dsa);
if (dsasig == NULL)
return (DST_R_SIGNFINALFAILURE);
*r.base++ = (key->key_size - 512)/64;
BN_bn2bin_fixed(dsasig->r, r.base, SHA_DIGEST_LENGTH);
r.base += SHA_DIGEST_LENGTH;
BN_bn2bin_fixed(dsasig->s, r.base, SHA_DIGEST_LENGTH);
r.base += SHA_DIGEST_LENGTH;
DSA_SIG_free(dsasig);
isc_buffer_add(sig, SHA_DIGEST_LENGTH * 2 + 1);
}
else
*context = ctx;
*r.base++ = (key->key_size - 512)/64;
BN_bn2bin_fixed(dsasig->r, r.base, SHA_DIGEST_LENGTH);
r.base += SHA_DIGEST_LENGTH;
BN_bn2bin_fixed(dsasig->s, r.base, SHA_DIGEST_LENGTH);
r.base += SHA_DIGEST_LENGTH;
DSA_SIG_free(dsasig);
isc_buffer_add(sig, SHA_DIGEST_LENGTH * 2 + 1);
return (ISC_R_SUCCESS);
}
/*
* dst_openssl_verify
* Calls OpenSSL verification routines. There are three steps to
* verification, INIT (initialize structures), UPDATE (hash (more) data),
* FINAL (generate a signature). This routine performs one or more of
* these steps.
* Parameters
* mode DST_SIGMODE_{INIT_UPDATE_FINAL|ALL}
* key key to use for verifying
* context the context to use for this computation
* data signed data
* signature signature
* mctx memory context for temporary allocations
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssl_verify(const unsigned int mode, dst_key_t *key, void **context,
isc_region_t *data, isc_region_t *sig, isc_mem_t *mctx)
{
openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
int status = 0;
SHA_CTX *ctx = NULL;
if (mode & DST_SIGMODE_INIT) {
ctx = (SHA_CTX *) isc_mem_get(mctx, sizeof(SHA_CTX));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
}
else if (context != NULL)
ctx = (SHA_CTX *) *context;
REQUIRE (ctx != NULL);
dst_key_t *key;
SHA_CTX *ctx;
DSA *dsa;
DSA_SIG *dsasig;
unsigned char digest[SHA_DIGEST_LENGTH];
unsigned char *cp = sig->base;
if (mode & DST_SIGMODE_INIT)
SHA1_Init(ctx);
ctx = dctx->opaque;
key = dctx->key;
dsa = key->opaque;
if ((mode & DST_SIGMODE_UPDATE))
SHA1_Update(ctx, data->base, data->length);
SHA1_Final(digest, ctx);
if (mode & DST_SIGMODE_FINAL) {
DSA *dsa;
DSA_SIG *dsasig;
unsigned char digest[SHA_DIGEST_LENGTH];
unsigned char *cp = sig->base;
if (sig->length < 2 * SHA_DIGEST_LENGTH + 1)
return (DST_R_VERIFYFAILURE);
dsa = key->opaque;
cp++; /* Skip T */
dsasig = DSA_SIG_new();
dsasig->r = BN_bin2bn(cp, SHA_DIGEST_LENGTH, NULL);
cp += SHA_DIGEST_LENGTH;
dsasig->s = BN_bin2bn(cp, SHA_DIGEST_LENGTH, NULL);
cp += SHA_DIGEST_LENGTH;
SHA1_Final(digest, ctx);
isc_mem_put(mctx, ctx, sizeof(SHA_CTX));
if (sig->length < 2 * SHA_DIGEST_LENGTH + 1)
return (DST_R_VERIFYFINALFAILURE);
cp++; /* Skip T */
dsasig = DSA_SIG_new();
dsasig->r = BN_bin2bn(cp, SHA_DIGEST_LENGTH, NULL);
cp += SHA_DIGEST_LENGTH;
dsasig->s = BN_bin2bn(cp, SHA_DIGEST_LENGTH, NULL);
cp += SHA_DIGEST_LENGTH;
status = DSA_do_verify(digest, SHA_DIGEST_LENGTH, dsasig, dsa);
DSA_SIG_free(dsasig);
if (status == 0)
return (DST_R_VERIFYFINALFAILURE);
}
else
*context = ctx;
status = DSA_do_verify(digest, SHA_DIGEST_LENGTH, dsasig, dsa);
DSA_SIG_free(dsasig);
if (status == 0)
return (DST_R_VERIFYFAILURE);
return (ISC_R_SUCCESS);
}
/*
* dst_openssl_isprivate
* Is this a private key?
* Parameters
* key DST KEY structure
* Returns
* ISC_TRUE
* ISC_FALSE
*/
static isc_boolean_t
dst_openssl_isprivate(const dst_key_t *key) {
openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DSA *dsa1, *dsa2;
dsa1 = (DSA *) key1->opaque;
dsa2 = (DSA *) key2->opaque;
if (dsa1 == NULL && dsa2 == NULL)
return (ISC_TRUE);
else if (dsa1 == NULL || dsa2 == NULL)
return (ISC_FALSE);
status = BN_cmp(dsa1->p, dsa2->p) ||
BN_cmp(dsa1->q, dsa2->q) ||
BN_cmp(dsa1->g, dsa2->g) ||
BN_cmp(dsa1->pub_key, dsa2->pub_key);
if (status != 0)
return (ISC_FALSE);
if (dsa1->priv_key != NULL || dsa2->priv_key != NULL) {
if (dsa1->priv_key == NULL || dsa2->priv_key == NULL)
return (ISC_FALSE);
if (BN_cmp(dsa1->priv_key, dsa2->priv_key))
return (ISC_FALSE);
}
return (ISC_TRUE);
}
static isc_result_t
openssldsa_generate(dst_key_t *key, int unused) {
DSA *dsa;
unsigned char dns_array[DST_KEY_MAXSIZE];
unsigned char rand_array[SHA_DIGEST_LENGTH];
isc_buffer_t dns, rand;
isc_result_t result;
isc_region_t r;
UNUSED(unused);
isc_buffer_init(&rand, rand_array, sizeof(rand_array));
result = dst_random_get(SHA_DIGEST_LENGTH, &rand);
if (result != ISC_R_SUCCESS)
return (result);
dsa = DSA_generate_parameters(key->key_size, rand_array,
SHA_DIGEST_LENGTH, NULL, NULL,
NULL, NULL);
if (dsa == NULL)
return (ISC_R_NOMEMORY);
if (DSA_generate_key(dsa) == 0) {
DSA_free(dsa);
return (ISC_R_NOMEMORY);
}
key->opaque = dsa;
isc_buffer_init(&dns, dns_array, sizeof(dns_array));
result = openssldsa_todns(key, &dns);
if (result != ISC_R_SUCCESS) {
DSA_free(dsa);
return (result);
}
isc_buffer_usedregion(&dns, &r);
key->key_id = dst_s_id_calc(r.base, r.length);
return (ISC_R_SUCCESS);
}
static isc_boolean_t
openssldsa_isprivate(const dst_key_t *key) {
DSA *dsa = (DSA *) key->opaque;
return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
}
static void
openssldsa_destroy(dst_key_t *key) {
DSA *dsa = key->opaque;
DSA_free(dsa);
}
/*
* dst_openssl_to_dns
* Converts key from DSA to DNS distribution format
* Parameters
* key DST KEY structure
* data output data
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssl_to_dns(const dst_key_t *key, isc_buffer_t *data) {
openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
DSA *dsa;
isc_region_t r;
int dnslen;
@@ -306,22 +267,12 @@ dst_openssl_to_dns(const dst_key_t *key, isc_buffer_t *data) {
return (ISC_R_SUCCESS);
}
/*
* dst_openssl_from_dns
* Converts from a DNS KEY RR format to a DSA KEY.
* Parameters
* key Partially filled key structure
* data Buffer containing key in DNS format
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssl_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx) {
openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
DSA *dsa;
isc_region_t r;
unsigned int t, p_bytes;
isc_mem_t *mctx = key->mctx;
UNUSED(mctx);
@@ -370,17 +321,8 @@ dst_openssl_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx) {
}
/*
* dst_openssl_to_file
* Encodes a DSA Key into the portable file format.
* Parameters
* key DST KEY structure
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssl_to_file(const dst_key_t *key) {
openssldsa_tofile(const dst_key_t *key) {
int cnt = 0;
DSA *dsa;
dst_private_t priv;
@@ -425,21 +367,8 @@ dst_openssl_to_file(const dst_key_t *key) {
return (dst_s_write_private_key_file(key, &priv));
}
/*
* dst_openssl_from_file
* Converts contents of a private key file into a private DSA key.
* Parameters
* key Partially filled DSA KEY structure
* id The key id
* path The directory that the file will be read from
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssl_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx) {
openssldsa_fromfile(dst_key_t *key, const isc_uint16_t id) {
dst_private_t priv;
isc_result_t ret;
isc_buffer_t dns;
@@ -447,6 +376,7 @@ dst_openssl_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx) {
unsigned char dns_array[1024];
int i;
DSA *dsa = NULL;
isc_mem_t *mctx = key->mctx;
#define DST_RET(a) {ret = a; goto err;}
/* read private key file */
@@ -488,7 +418,7 @@ dst_openssl_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx) {
key->key_size = BN_num_bits(dsa->p);
isc_buffer_init(&dns, dns_array, sizeof(dns_array));
ret = dst_openssl_to_dns(key, &dns);
ret = openssldsa_todns(key, &dns);
if (ret != ISC_R_SUCCESS)
DST_RET(ret);
isc_buffer_usedregion(&dns, &r);
@@ -500,124 +430,36 @@ dst_openssl_from_file(dst_key_t *key, const isc_uint16_t id, isc_mem_t *mctx) {
return (ISC_R_SUCCESS);
err:
key->opaque = NULL;
dst_openssl_destroy(dsa, mctx);
openssldsa_destroy(key);
dst_s_free_private_structure_fields(&priv, mctx);
memset(&priv, 0, sizeof(priv));
return (ret);
}
/*
* dst_openssl_destroy
* Frees all dynamically allocated structures in key.
*/
static void
dst_openssl_destroy(void *key, isc_mem_t *mctx) {
DSA *dsa = (DSA *) key;
static struct dst_func openssldsa_functions = {
openssldsa_createctx,
openssldsa_destroyctx,
openssldsa_adddata,
openssldsa_sign,
openssldsa_verify,
NULL, /* digest */
NULL, /* computesecret */
openssldsa_compare,
NULL, /* paramcompare */
openssldsa_generate,
openssldsa_isprivate,
openssldsa_destroy,
openssldsa_todns,
openssldsa_fromdns,
openssldsa_tofile,
openssldsa_fromfile,
};
UNUSED(mctx);
if (dsa == NULL)
return;
DSA_free(dsa);
void
dst_s_openssldsa_init(struct dst_func **funcp) {
REQUIRE(funcp != NULL && *funcp == NULL);
CRYPTO_set_mem_functions(dst_mem_alloc, dst_mem_realloc, dst_mem_free);
*funcp = &openssldsa_functions;
}
/*
* dst_openssl_generate
* Generates unique keys that are hard to predict.
* Parameters
* key DST Key structure
* unused algorithm specific data, unused for DSA.
* mctx memory context to allocate key
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssl_generate(dst_key_t *key, int unused, isc_mem_t *mctx) {
DSA *dsa;
unsigned char dns_array[1024];
unsigned char rand_array[SHA_DIGEST_LENGTH];
isc_buffer_t dns, rand;
isc_result_t ret;
isc_region_t r;
UNUSED(unused);
UNUSED(mctx);
isc_buffer_init(&rand, rand_array, sizeof(rand_array));
ret = dst_random_get(SHA_DIGEST_LENGTH, &rand);
if (ret != ISC_R_SUCCESS)
return (ret);
dsa = DSA_generate_parameters(key->key_size, rand_array,
SHA_DIGEST_LENGTH, NULL, NULL,
NULL, NULL);
if (dsa == NULL)
return (ISC_R_NOMEMORY);
if (DSA_generate_key(dsa) == 0)
return (ISC_R_NOMEMORY);
key->opaque = dsa;
isc_buffer_init(&dns, dns_array, sizeof(dns_array));
dst_openssl_to_dns(key, &dns);
isc_buffer_usedregion(&dns, &r);
key->key_id = dst_s_id_calc(r.base, r.length);
return (ISC_R_SUCCESS);
}
/**************************************************************************
* dst_openssl_compare
* Compare two keys for equality.
* Return
* ISC_TRUE The keys are equal
* ISC_FALSE The keys are not equal
*/
static isc_boolean_t
dst_openssl_compare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DSA *dsa1, *dsa2;
dsa1 = (DSA *) key1->opaque;
dsa2 = (DSA *) key2->opaque;
if (dsa1 == NULL && dsa2 == NULL)
return (ISC_TRUE);
else if (dsa1 == NULL || dsa2 == NULL)
return (ISC_FALSE);
status = BN_cmp(dsa1->p, dsa2->p) ||
BN_cmp(dsa1->q, dsa2->q) ||
BN_cmp(dsa1->g, dsa2->g) ||
BN_cmp(dsa1->pub_key, dsa2->pub_key);
if (status != 0)
return (ISC_FALSE);
if (dsa1->priv_key != NULL || dsa2->priv_key != NULL) {
if (dsa1->priv_key == NULL || dsa2->priv_key == NULL)
return (ISC_FALSE);
if (BN_cmp(dsa1->priv_key, dsa2->priv_key))
return (ISC_FALSE);
}
return (ISC_TRUE);
}
static int
BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
int bytes = size - BN_num_bytes(bn);
while (bytes-- > 0)
*buf++ = 0;
BN_bn2bin(bn, buf);
return (size);
}
#endif /* OPENSSL */

View File

@@ -19,7 +19,7 @@
/*
* Principal Author: Brian Wellington
* $Id: openssldh_link.c,v 1.17 2000/05/24 05:09:37 tale Exp $
* $Id: openssldh_link.c,v 1.18 2000/06/02 18:57:47 bwelling Exp $
*/
#if defined(OPENSSL)
@@ -47,96 +47,13 @@
"5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
"B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
static struct dst_func openssldh_functions;
static isc_result_t
dst_openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
isc_buffer_t *secret);
static isc_boolean_t
dst_openssldh_compare(const dst_key_t *key1, const dst_key_t *key2);
static isc_boolean_t
dst_openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2);
static isc_result_t
dst_openssldh_generate(dst_key_t *key, int generator, isc_mem_t *mctx);
static isc_boolean_t
dst_openssldh_isprivate(const dst_key_t *key);
static void
dst_openssldh_destroy(void *key, isc_mem_t *mctx);
static isc_result_t
dst_openssldh_to_dns(const dst_key_t *in_key, isc_buffer_t *data);
static isc_result_t
dst_openssldh_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx);
static isc_result_t
dst_openssldh_to_file(const dst_key_t *key);
static isc_result_t
dst_openssldh_from_file(dst_key_t *key, const isc_uint16_t id,
isc_mem_t *mctx);
static void
uint16_toregion(isc_uint16_t val, isc_region_t *region);
static isc_uint16_t
uint16_fromregion(isc_region_t *region);
static void
BN_fromhex(BIGNUM *b, const char *str);
static isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data);
static BIGNUM bn2, bn768, bn1024;
/*
* dst_s_openssldh_init()
* Sets up function pointers for OpenSSL related functions
*/
void
dst_s_openssldh_init(void) {
REQUIRE(dst_t_func[DST_ALG_DH] == NULL);
dst_t_func[DST_ALG_DH] = &openssldh_functions;
memset(&openssldh_functions, 0, sizeof(struct dst_func));
openssldh_functions.sign = NULL;
openssldh_functions.verify = NULL;
openssldh_functions.computesecret = dst_openssldh_computesecret;
openssldh_functions.compare = dst_openssldh_compare;
openssldh_functions.paramcompare = dst_openssldh_paramcompare;
openssldh_functions.generate = dst_openssldh_generate;
openssldh_functions.isprivate = dst_openssldh_isprivate;
openssldh_functions.destroy = dst_openssldh_destroy;
openssldh_functions.to_dns = dst_openssldh_to_dns;
openssldh_functions.from_dns = dst_openssldh_from_dns;
openssldh_functions.to_file = dst_openssldh_to_file;
openssldh_functions.from_file = dst_openssldh_from_file;
CRYPTO_set_mem_functions(dst_mem_alloc, dst_mem_realloc, dst_mem_free);
BN_init(&bn2);
BN_init(&bn768);
BN_init(&bn1024);
BN_set_word(&bn2, 2);
BN_fromhex(&bn768, PRIME768);
BN_fromhex(&bn1024, PRIME1024);
}
/*
* dst_openssldh_computesecret
* Compute a shared secret from this public and private key
* Parameters
* pub The public key
* priv The private key
* secret A buffer into which the secret is written
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
isc_buffer_t *secret)
openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
isc_buffer_t *secret)
{
DH *dhpub, *dhpriv;
int ret;
@@ -160,35 +77,145 @@ dst_openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
return (ISC_R_SUCCESS);
}
/*
* dst_openssldh_isprivate
* Is this a private key?
* Parameters
* key DST KEY structure
* Returns
* ISC_TRUE
* ISC_FALSE
*/
static isc_boolean_t
dst_openssldh_isprivate(const dst_key_t *key) {
openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DH *dh1, *dh2;
dh1 = (DH *) key1->opaque;
dh2 = (DH *) key2->opaque;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
else if (dh1 == NULL || dh2 == NULL)
return (ISC_FALSE);
status = BN_cmp(dh1->p, dh2->p) ||
BN_cmp(dh1->g, dh2->g) ||
BN_cmp(dh1->pub_key, dh2->pub_key);
if (status != 0)
return (ISC_FALSE);
if (dh1->priv_key != NULL || dh2->priv_key != NULL) {
if (dh1->priv_key == NULL || dh2->priv_key == NULL)
return (ISC_FALSE);
if (BN_cmp(dh1->priv_key, dh2->priv_key) != 0)
return (ISC_FALSE);
}
return (ISC_TRUE);
}
static isc_boolean_t
openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DH *dh1, *dh2;
dh1 = (DH *) key1->opaque;
dh2 = (DH *) key2->opaque;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
else if (dh1 == NULL || dh2 == NULL)
return (ISC_FALSE);
status = BN_cmp(dh1->p, dh2->p) ||
BN_cmp(dh1->g, dh2->g);
if (status != 0)
return (ISC_FALSE);
return (ISC_TRUE);
}
static isc_result_t
openssldh_generate(dst_key_t *key, int generator) {
DH *dh = NULL;
unsigned char dns_array[DST_KEY_MAXSIZE];
isc_buffer_t dns;
isc_region_t r;
isc_result_t result;
if (generator == 0) {
if (key->key_size == 768 || key->key_size == 1024) {
dh = DH_new();
if (dh == NULL)
return (ISC_R_NOMEMORY);
if (key->key_size == 768)
dh->p = &bn768;
else
dh->p = &bn1024;
dh->g = &bn2;
}
else
generator = 2;
}
if (generator != 0)
dh = DH_generate_parameters(key->key_size, generator,
NULL, NULL);
if (dh == NULL)
return (DST_R_INVALIDPARAM);
if (DH_generate_key(dh) == 0) {
DH_free(dh);
return (ISC_R_NOMEMORY);
}
key->opaque = dh;
isc_buffer_init(&dns, dns_array, sizeof(dns_array));
result = openssldh_todns(key, &dns);
if (result != ISC_R_SUCCESS) {
DH_free(dh);
return (result);
}
isc_buffer_usedregion(&dns, &r);
key->key_id = dst_s_id_calc(r.base, r.length);
return (ISC_R_SUCCESS);
}
static isc_boolean_t
openssldh_isprivate(const dst_key_t *key) {
DH *dh = (DH *) key->opaque;
return (ISC_TF(dh != NULL && dh->priv_key != NULL));
}
static void
openssldh_destroy(dst_key_t *key) {
DH *dh = key->opaque;
/*
* dst_openssldh_to_dns
* Converts key from DH to DNS distribution format
* Parameters
* key DST KEY structure
* data output data
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
if (dh == NULL)
return;
if (dh->p == &bn768 || dh->p == &bn1024)
dh->p = NULL;
if (dh->g == &bn2)
dh->g = NULL;
DH_free(dh);
}
static void
uint16_toregion(isc_uint16_t val, isc_region_t *region) {
*region->base++ = (val & 0xff00) >> 8;
*region->base++ = (val & 0x00ff);
}
static isc_uint16_t
uint16_fromregion(isc_region_t *region) {
isc_uint16_t val;
unsigned char *cp = region->base;
val = ((unsigned int)(cp[0])) << 8;
val |= ((unsigned int)(cp[1]));
region->base += 2;
return (val);
}
static isc_result_t
dst_openssldh_to_dns(const dst_key_t *key, isc_buffer_t *data) {
openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
DH *dh;
isc_region_t r;
isc_uint16_t dnslen, plen, glen, publen;
@@ -237,26 +264,13 @@ dst_openssldh_to_dns(const dst_key_t *key, isc_buffer_t *data) {
return (ISC_R_SUCCESS);
}
/*
* dst_openssldh_from_dns
* Converts from a DNS KEY RR format to a DH KEY.
* Parameters
* key Partially filled key structure
* data Buffer containing key in DNS format
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssldh_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx) {
openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
DH *dh;
isc_region_t r;
isc_uint16_t plen, glen, publen;
int special = 0;
UNUSED(mctx);
isc_buffer_remainingregion(data, &r);
if (r.length == 0)
return (ISC_R_SUCCESS);
@@ -365,18 +379,8 @@ dst_openssldh_from_dns(dst_key_t *key, isc_buffer_t *data, isc_mem_t *mctx) {
return (ISC_R_SUCCESS);
}
/*
* dst_openssldh_to_file
* Encodes a DH Key into the portable file format.
* Parameters
* key DST KEY structure
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssldh_to_file(const dst_key_t *key) {
openssldh_tofile(const dst_key_t *key) {
int cnt = 0;
DH *dh;
dst_private_t priv;
@@ -415,22 +419,8 @@ dst_openssldh_to_file(const dst_key_t *key) {
return (dst_s_write_private_key_file(key, &priv));
}
/*
* dst_openssldh_from_file
* Converts contents of a private key file into a private DH key.
* Parameters
* key Partially filled DH KEY structure
* id The key id
* path The directory that the file will be read from
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssldh_from_file(dst_key_t *key, const isc_uint16_t id,
isc_mem_t *mctx) {
openssldh_fromfile(dst_key_t *key, const isc_uint16_t id) {
dst_private_t priv;
isc_result_t ret;
isc_buffer_t dns;
@@ -438,8 +428,11 @@ dst_openssldh_from_file(dst_key_t *key, const isc_uint16_t id,
unsigned char dns_array[1024];
int i;
DH *dh = NULL;
isc_mem_t *mctx;
#define DST_RET(a) {ret = a; goto err;}
mctx = key->mctx;
/* read private key file */
ret = dst_s_parse_private_key_file(key, id, &priv, mctx);
if (ret != ISC_R_SUCCESS)
@@ -493,7 +486,7 @@ dst_openssldh_from_file(dst_key_t *key, const isc_uint16_t id,
}
}
isc_buffer_init(&dns, dns_array, sizeof(dns_array));
ret = dst_openssldh_to_dns(key, &dns);
ret = openssldh_todns(key, &dns);
if (ret != ISC_R_SUCCESS)
DST_RET(ret);
isc_buffer_usedregion(&dns, &r);
@@ -505,175 +498,12 @@ dst_openssldh_from_file(dst_key_t *key, const isc_uint16_t id,
return (ISC_R_SUCCESS);
err:
key->opaque = NULL;
dst_openssldh_destroy(dh, mctx);
openssldh_destroy(key);
dst_s_free_private_structure_fields(&priv, mctx);
memset(&priv, 0, sizeof(priv));
return (ret);
}
/*
* dst_openssldh_destroy
* Frees all dynamically allocated structures in key.
*/
static void
dst_openssldh_destroy(void *key, isc_mem_t *mctx) {
DH *dh = (DH *) key;
UNUSED(mctx);
if (dh == NULL)
return;
if (dh->p == &bn768 || dh->p == &bn1024)
dh->p = NULL;
if (dh->g == &bn2)
dh->g = NULL;
DH_free(dh);
}
/*
* dst_openssldh_generate
* Generates unique keys that are hard to predict.
* Parameters
* key DST Key structure
* generator generator
* mctx memory context to allocate key
* Return
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
static isc_result_t
dst_openssldh_generate(dst_key_t *key, int generator, isc_mem_t *mctx) {
DH *dh = NULL;
unsigned char dns_array[1024];
isc_buffer_t dns;
isc_region_t r;
UNUSED(mctx);
if (generator == 0) {
if (key->key_size == 768 || key->key_size == 1024) {
dh = DH_new();
if (dh == NULL)
return (ISC_R_NOMEMORY);
if (key->key_size == 768)
dh->p = &bn768;
else
dh->p = &bn1024;
dh->g = &bn2;
}
else
generator = 2;
}
if (generator != 0)
dh = DH_generate_parameters(key->key_size, generator,
NULL, NULL);
if (dh == NULL)
return (DST_R_INVALIDPARAM);
if (DH_generate_key(dh) == 0) {
DH_free(dh);
return (ISC_R_NOMEMORY);
}
key->opaque = dh;
isc_buffer_init(&dns, dns_array, sizeof(dns_array));
dst_openssldh_to_dns(key, &dns);
isc_buffer_usedregion(&dns, &r);
key->key_id = dst_s_id_calc(r.base, r.length);
return (ISC_R_SUCCESS);
}
/**************************************************************************
* dst_openssldh_compare
* Compare two keys for equality.
* Return
* ISC_TRUE The keys are equal
* ISC_FALSE The keys are not equal
*/
static isc_boolean_t
dst_openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DH *dh1, *dh2;
dh1 = (DH *) key1->opaque;
dh2 = (DH *) key2->opaque;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
else if (dh1 == NULL || dh2 == NULL)
return (ISC_FALSE);
status = BN_cmp(dh1->p, dh2->p) ||
BN_cmp(dh1->g, dh2->g) ||
BN_cmp(dh1->pub_key, dh2->pub_key);
if (status != 0)
return (ISC_FALSE);
if (dh1->priv_key != NULL || dh2->priv_key != NULL) {
if (dh1->priv_key == NULL || dh2->priv_key == NULL)
return (ISC_FALSE);
if (BN_cmp(dh1->priv_key, dh2->priv_key) != 0)
return (ISC_FALSE);
}
return (ISC_TRUE);
}
/**************************************************************************
* dst_openssldh_paramcompare
* Compare two keys' parameters for equality.
* Return
* ISC_TRUE The keys are equal
* ISC_FALSE The keys are not equal
*/
static isc_boolean_t
dst_openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
int status;
DH *dh1, *dh2;
dh1 = (DH *) key1->opaque;
dh2 = (DH *) key2->opaque;
if (dh1 == NULL && dh2 == NULL)
return (ISC_TRUE);
else if (dh1 == NULL || dh2 == NULL)
return (ISC_FALSE);
status = BN_cmp(dh1->p, dh2->p) ||
BN_cmp(dh1->g, dh2->g);
if (status != 0)
return (ISC_FALSE);
return (ISC_TRUE);
}
static void
uint16_toregion(isc_uint16_t val, isc_region_t *region) {
*region->base++ = (val & 0xff00) >> 8;
*region->base++ = (val & 0x00ff);
}
static isc_uint16_t
uint16_fromregion(isc_region_t *region) {
isc_uint16_t val;
unsigned char *cp = region->base;
val = ((unsigned int)(cp[0])) << 8;
val |= ((unsigned int)(cp[1]));
region->base += 2;
return (val);
}
static void
BN_fromhex(BIGNUM *b, const char *str) {
static const char hexdigits[] = "0123456789abcdef";
@@ -700,4 +530,36 @@ BN_fromhex(BIGNUM *b, const char *str) {
RUNTIME_CHECK(out != NULL);
}
static struct dst_func openssldh_functions = {
NULL, /* createctx */
NULL, /* destroyctx */
NULL, /* adddata */
NULL, /* openssldh_sign */
NULL, /* openssldh_verify */
NULL, /* digest */
openssldh_computesecret,
openssldh_compare,
openssldh_paramcompare,
openssldh_generate,
openssldh_isprivate,
openssldh_destroy,
openssldh_todns,
openssldh_fromdns,
openssldh_tofile,
openssldh_fromfile,
};
void
dst_s_openssldh_init(struct dst_func **funcp) {
REQUIRE(funcp != NULL && *funcp == NULL);
CRYPTO_set_mem_functions(dst_mem_alloc, dst_mem_realloc, dst_mem_free);
BN_init(&bn2);
BN_init(&bn768);
BN_init(&bn1024);
BN_set_word(&bn2, 2);
BN_fromhex(&bn768, PRIME768);
BN_fromhex(&bn1024, PRIME1024);
*funcp = &openssldh_functions;
}
#endif /* OPENSSL */

View File

@@ -19,7 +19,7 @@
/*
* Principal Author: Brian Wellington
* $Id: opensslmd5_link.c,v 1.7 2000/05/08 14:37:10 tale Exp $
* $Id: opensslmd5_link.c,v 1.8 2000/06/02 18:57:48 bwelling Exp $
*/
#if defined(OPENSSL)
@@ -30,61 +30,75 @@
#include <isc/util.h>
#include "dst_internal.h"
#include "dst_parse.h"
#include <openssl/md5.h>
/*
* dst_s_md5
* Call MD5 functions to digest a block of data.
* There are three steps to signing, INIT (initialize structures),
* UPDATE (hash (more) data), FINAL (generate a digest). This
* routine performs one or more of these steps.
* Parameters
* mode DST_SIGMODE_{INIT_UPDATE_FINAL|ALL}
* context the context to use for this computation
* data data to be signed
* digest buffer to store digest
* mctx memory context for temporary allocations
* Returns
* ISC_R_SUCCESS Success
* !ISC_R_SUCCESS Failure
*/
isc_result_t
dst_s_md5(const unsigned int mode, void **context, isc_region_t *data,
isc_buffer_t *digest, isc_mem_t *mctx)
{
static isc_result_t
opensslmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
MD5_CTX *ctx;
UNUSED(key);
ctx = isc_mem_get(dctx->mctx, sizeof(MD5_CTX));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
MD5_Init(ctx);
dctx->opaque = ctx;
return (ISC_R_SUCCESS);
}
static void
opensslmd5_destroyctx(dst_context_t *dctx) {
MD5_CTX *ctx = dctx->opaque;
isc_mem_put(dctx->mctx, ctx, sizeof(MD5_CTX));
}
static isc_result_t
opensslmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
MD5_CTX *ctx = dctx->opaque;
MD5_Update(ctx, data->base, data->length);
return (ISC_R_SUCCESS);
}
static isc_result_t
opensslmd5_digest(dst_context_t *dctx, isc_buffer_t *digest) {
MD5_CTX *ctx = dctx->opaque;
isc_region_t r;
MD5_CTX *ctx = NULL;
if (mode & DST_SIGMODE_INIT) {
ctx = (MD5_CTX *) isc_mem_get(mctx, sizeof(MD5_CTX));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
}
else if (context != NULL)
ctx = (MD5_CTX *) *context;
REQUIRE (ctx != NULL);
isc_buffer_availableregion(digest, &r);
if (r.length < MD5_DIGEST_LENGTH)
return (ISC_R_NOSPACE);
if (mode & DST_SIGMODE_INIT)
MD5_Init(ctx);
if (mode & DST_SIGMODE_UPDATE)
MD5_Update(ctx, data->base, data->length);
if (mode & DST_SIGMODE_FINAL) {
isc_buffer_availableregion(digest, &r);
if (r.length < MD5_DIGEST_LENGTH)
return (ISC_R_NOSPACE);
MD5_Final(r.base, ctx);
isc_buffer_add(digest, MD5_DIGEST_LENGTH);
isc_mem_put(mctx, ctx, sizeof(MD5_CTX));
}
else
*context = ctx;
MD5_Final(r.base, ctx);
isc_buffer_add(digest, MD5_DIGEST_LENGTH);
return (ISC_R_SUCCESS);
}
static struct dst_func opensslmd5_functions = {
opensslmd5_createctx,
opensslmd5_destroyctx,
opensslmd5_adddata,
NULL, /* openssldsa_sign */
NULL, /* openssldsa_verify */
opensslmd5_digest,
NULL, /* computesecret */
NULL, /* compare */
NULL, /* paramcompare */
NULL, /* generate */
NULL, /* isprivate */
NULL, /* destroy */
NULL, /* todns */
NULL, /* fromdns */
NULL, /* tofile */
NULL, /* fromfile */
};
void
dst_s_opensslmd5_init(struct dst_func **funcp) {
REQUIRE(funcp != NULL && *funcp == NULL);
*funcp = &opensslmd5_functions;
}
#endif /* OPENSSL */