New DST API for signing/verifying, as well as some reorganization, cleanup,
and bug fixes.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user