Remove dnssafe, cylink, and the broken dst random generator.
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
OBJS= bsafe_link.@O@ cylink_link.@O@ dst_api.@O@ eay_dss_link.@O@ \
|
||||
hmac_link.@O@ md5_dgst.@O@ prandom.@O@ rsaref_link.@O@ support.@O@
|
||||
OBJS= dst_api.@O@ hmac_link.@O@ md5_dgst.@O@ support.@O@
|
||||
|
||||
SRCS= bsafe_link.c cylink_link.c dst_api.c eay_dss_link.c \
|
||||
hmac_link.c md5_dgst.c prandom.c rsaref_link.c support.c
|
||||
SRCS= dst_api.c hmac_link.c md5_dgst.c support.c
|
||||
|
||||
TARGETS= ${OBJS}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,678 +0,0 @@
|
||||
#ifdef CYLINK_DSS
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/cylink_link.c,v 1.1 2001/03/29 06:31:31 marka Exp $";
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
* This file contains two components
|
||||
* 1. Interface to the CYLINK library to allow compilation of Bind
|
||||
* with TIS/DNSSEC when CYLINK is not available
|
||||
* all calls to CYLINK are contained inside this file.
|
||||
* 2. The glue to connvert DSA KEYS to and from external formats
|
||||
*/
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
#include <toolkit.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
typedef struct cylinkkey {
|
||||
char *dk_signer;
|
||||
uchar *dk_p;
|
||||
uchar *dk_q;
|
||||
uchar *dk_g;
|
||||
uchar *dk_x;
|
||||
uchar *dk_y;
|
||||
ushort dk_p_bytes;
|
||||
} DSA_Key;
|
||||
|
||||
#define NULL_PRIV_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \
|
||||
k->dk_g == NULL || k->dk_x == NULL)
|
||||
#define NULL_PUB_KEY(k)(k == NULL || k->dk_p == NULL || k->dk_q == NULL || \
|
||||
k->dk_g == NULL || k->dk_y == NULL)
|
||||
|
||||
static int dst_cylink_sign(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
u_char *signature, const int sig_len);
|
||||
|
||||
static int dst_cylink_verify(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
const u_char *signature, const int sig_len);
|
||||
|
||||
static int dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str,
|
||||
const int out_len);
|
||||
static int dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key,
|
||||
const int len);
|
||||
static int dst_cylink_key_to_file_format(const DST_KEY *key, char *buff,
|
||||
const int buff_len);
|
||||
static int dst_cylink_key_from_file_format(DST_KEY *d_key,
|
||||
const char *buff,
|
||||
const int buff_len);
|
||||
static void *dst_cylink_free_key_structure(void *key);
|
||||
|
||||
static int dst_cylink_generate_keypair(DST_KEY *key, int exp);
|
||||
static int dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2);
|
||||
|
||||
static void *memcpyend(void *dest, const void *src, size_t n, size_t size);
|
||||
|
||||
/*
|
||||
* dst_cylink_init() Function to answer set up function pointers for
|
||||
* CYLINK related functions
|
||||
*/
|
||||
int
|
||||
dst_cylink_init()
|
||||
{
|
||||
if (dst_t_func[KEY_DSA] != NULL)
|
||||
return (1);
|
||||
dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func));
|
||||
if (dst_t_func[KEY_DSA] == NULL)
|
||||
return (0);
|
||||
memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func));
|
||||
dst_t_func[KEY_DSA]->sign = dst_cylink_sign;
|
||||
dst_t_func[KEY_DSA]->verify = dst_cylink_verify;
|
||||
dst_t_func[KEY_DSA]->compare = dst_cylink_compare_keys;
|
||||
dst_t_func[KEY_DSA]->generate = dst_cylink_generate_keypair;
|
||||
dst_t_func[KEY_DSA]->destroy = dst_cylink_free_key_structure;
|
||||
dst_t_func[KEY_DSA]->from_dns_key = dst_cylink_from_dns_key;
|
||||
dst_t_func[KEY_DSA]->to_dns_key = dst_cylink_to_dns_key;
|
||||
dst_t_func[KEY_DSA]->from_file_fmt = dst_cylink_key_from_file_format;
|
||||
dst_t_func[KEY_DSA]->to_file_fmt = dst_cylink_key_to_file_format;
|
||||
SetDataOrder(1);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_cylink_sign
|
||||
* Call CYLINK 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 SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* algobj structure holds context for a sign done in multiple calls.
|
||||
* context the context to use for this computation
|
||||
* data data to be signed.
|
||||
* len length in bytes of data.
|
||||
* priv_key key to use for signing.
|
||||
* signature location to store signature.
|
||||
* sig_len size in bytes of signature field.
|
||||
* returns
|
||||
* N Success on SIG_MODE_FINAL = returns signature length in bytes
|
||||
* N is 41 for DNS
|
||||
* 0 Success on SIG_MODE_INIT and UPDATE
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_cylink_sign(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
u_char *signature, const int sig_len)
|
||||
{
|
||||
int sign_len = 0;
|
||||
int status;
|
||||
SHA_context *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = (SHA_context *) malloc(sizeof(SHA_context));
|
||||
else if (context)
|
||||
ctx = (SHA_context *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
SHAInit(ctx);
|
||||
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) {
|
||||
status = SHAUpdate(ctx, data, len);
|
||||
if (status != SUCCESS)
|
||||
return (SIGN_UPDATE_FAILURE);
|
||||
}
|
||||
if (mode & SIG_MODE_FINAL) {
|
||||
DSA_Key *key;
|
||||
uchar digest[SHA_LENGTH];
|
||||
uchar rand[SHA_LENGTH];
|
||||
uchar r[SHA_LENGTH], s[SHA_LENGTH];
|
||||
|
||||
if (signature == NULL || sig_len < 2 * SHA_LENGTH)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
if ((status = SHAFinal(ctx, digest)) != SUCCESS)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
SAFE_FREE(ctx);
|
||||
if (dkey == NULL || dkey->dk_KEY_struct == NULL)
|
||||
return (-1);
|
||||
key = (DSA_Key *) dkey->dk_KEY_struct;
|
||||
if (NULL_PRIV_KEY(key))
|
||||
return (-2);
|
||||
dst_random(DST_RAND_STD, sizeof(rand), rand);
|
||||
status = GenDSSSignature(key->dk_p_bytes, key->dk_p,
|
||||
key->dk_q, key->dk_g, key->dk_x,
|
||||
rand, r, s, digest);
|
||||
if (status != SUCCESS)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
*signature = (dkey->dk_key_size - 512)/64;
|
||||
sign_len = 1;
|
||||
memcpy(signature + sign_len, r, SHA_LENGTH);
|
||||
sign_len += SHA_LENGTH;
|
||||
memcpy(signature + sign_len, s, SHA_LENGTH);
|
||||
sign_len += SHA_LENGTH;
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
return (sign_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dst_cylink_verify
|
||||
* Calls CYLINK 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 SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* dkey structure holds context for a verify done in multiple calls.
|
||||
* context algorithm specific context for the current context processing
|
||||
* data data signed.
|
||||
* len length in bytes of data.
|
||||
* pub_key key to use for verify.
|
||||
* signature signature.
|
||||
* sig_len length in bytes of signature.
|
||||
* returns
|
||||
* 0 Success
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_cylink_verify(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
const u_char *signature, const int sig_len)
|
||||
{
|
||||
int status;
|
||||
SHA_context *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = (SHA_context *) malloc(sizeof(SHA_context));
|
||||
else if (context)
|
||||
ctx = (SHA_context *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
SHAInit(ctx);
|
||||
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) {
|
||||
status = SHAUpdate(ctx, data, len);
|
||||
if (status != SUCCESS)
|
||||
return (VERIFY_UPDATE_FAILURE);
|
||||
}
|
||||
if (mode & SIG_MODE_FINAL) {
|
||||
DSA_Key *key;
|
||||
uchar digest[SHA_LENGTH];
|
||||
uchar r[SHA_LENGTH], s[SHA_LENGTH];
|
||||
|
||||
if (dkey == NULL || dkey->dk_KEY_struct == NULL)
|
||||
return (-1);
|
||||
key = (DSA_Key *) dkey->dk_KEY_struct;
|
||||
if (NULL_PUB_KEY(key))
|
||||
return (-2);
|
||||
if (signature == NULL || sig_len != (2 * SHA_LENGTH +1))
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
status = SHAFinal(ctx, digest);
|
||||
SAFE_FREE(ctx);
|
||||
if (status != SUCCESS)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
if (((int)*signature) != ((key->dk_p_bytes -64)/8))
|
||||
return(VERIFY_FINAL_FAILURE);
|
||||
|
||||
memcpy(r, signature +1, SHA_LENGTH);
|
||||
memcpy(s, signature + SHA_LENGTH +1, SHA_LENGTH);
|
||||
status = VerDSSSignature(key->dk_p_bytes, key->dk_p,
|
||||
key->dk_q, key->dk_g, key->dk_y,
|
||||
r, s, digest);
|
||||
if (status != SUCCESS)
|
||||
return (VERIFY_FINAL_FAILURE);
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_cylink_to_dns_key
|
||||
* Converts key from DSA to DNS distribution format
|
||||
* This function gets in a pointer to the public key and a work area
|
||||
* to write the key into.
|
||||
* Parameters
|
||||
* public KEY structure
|
||||
* out_str buffer to write encoded key into
|
||||
* out_len size of out_str
|
||||
* Return
|
||||
* N >= 0 length of encoded key
|
||||
* n < 0 error
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_cylink_to_dns_key(const DST_KEY *in_key, u_char *out_str,
|
||||
const int out_len)
|
||||
{
|
||||
u_char *op = out_str;
|
||||
int t;
|
||||
DSA_Key *key;
|
||||
|
||||
if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
|
||||
out_len <= 0 || out_str == NULL)
|
||||
return (-1);
|
||||
key = (DSA_Key *) in_key->dk_KEY_struct;
|
||||
|
||||
t = (key->dk_p_bytes - 64) / 8;
|
||||
|
||||
*op++ = t;
|
||||
memcpy(op, key->dk_q, SHA_LENGTH);
|
||||
op += SHA_LENGTH;
|
||||
memcpy(op, key->dk_p, key->dk_p_bytes);
|
||||
op += key->dk_p_bytes;
|
||||
memcpy(op, key->dk_g, key->dk_p_bytes);
|
||||
op += key->dk_p_bytes;
|
||||
memcpy(op, key->dk_y, key->dk_p_bytes);
|
||||
op += key->dk_p_bytes;
|
||||
|
||||
return (op - out_str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_cylink_from_dns_key
|
||||
* Converts from a DNS KEY RR format to an RSA KEY.
|
||||
* Parameters
|
||||
* len Length in bytes of DNS key
|
||||
* key DNS key
|
||||
* name Key name
|
||||
* s_key DST structure that will point to the RSA key this routine
|
||||
* will build.
|
||||
* Return
|
||||
* 0 The input key, s_key or name was null.
|
||||
* 1 Success
|
||||
*/
|
||||
static int
|
||||
dst_cylink_from_dns_key(DST_KEY *s_key, const u_char *key, const int len)
|
||||
{
|
||||
int t;
|
||||
const u_char *key_ptr = key;
|
||||
DSA_Key *d_key;
|
||||
|
||||
if (s_key == NULL || len < 0 || key == NULL)
|
||||
return (0);
|
||||
|
||||
if (len == 0) /* process null key */
|
||||
return (1);
|
||||
|
||||
if (key_ptr == NULL)
|
||||
return (0);
|
||||
t = (int) *key_ptr++; /* length of exponent in bytes */
|
||||
|
||||
if ((3 * (t * 8 + 64) + SHA_LENGTH + 1) != len)
|
||||
return (0);
|
||||
|
||||
if ((d_key = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) {
|
||||
EREPORT(("dst_cylink_from_dns_key(): Memory allocation error 1"));
|
||||
return (0);
|
||||
}
|
||||
memset(d_key, 0, sizeof(DSA_Key));
|
||||
s_key->dk_KEY_struct = (void *) d_key;
|
||||
d_key->dk_signer = strdup(s_key->dk_key_name);
|
||||
d_key->dk_p_bytes = 64 + 8 * t;
|
||||
|
||||
if ((d_key->dk_q = (uchar *) malloc(SHA_LENGTH)) == NULL)
|
||||
return (0);
|
||||
memcpy(d_key->dk_q, key_ptr, SHA_LENGTH);
|
||||
key_ptr += SHA_LENGTH;
|
||||
|
||||
if ((d_key->dk_p = (uchar *) malloc(d_key->dk_p_bytes)) == NULL)
|
||||
return (0);
|
||||
memcpy(d_key->dk_p, key_ptr, d_key->dk_p_bytes);
|
||||
key_ptr += d_key->dk_p_bytes;
|
||||
|
||||
if ((d_key->dk_g = (uchar *) malloc(d_key->dk_p_bytes)) == NULL)
|
||||
return (0);
|
||||
memcpy(d_key->dk_g, key_ptr, d_key->dk_p_bytes);
|
||||
key_ptr += d_key->dk_p_bytes;
|
||||
|
||||
if ((d_key->dk_y = (uchar *) malloc(d_key->dk_p_bytes)) == NULL)
|
||||
return (0);
|
||||
memcpy(d_key->dk_y, key_ptr, d_key->dk_p_bytes);
|
||||
key_ptr += d_key->dk_p_bytes;
|
||||
|
||||
s_key->dk_id = dst_s_id_calc(key, len);
|
||||
s_key->dk_key_size = d_key->dk_p_bytes * 8;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_cylink_key_to_file_format
|
||||
* Encodes an DSA Key into the portable file format.
|
||||
* Parameters
|
||||
* key DSA KEY structure
|
||||
* buff output buffer
|
||||
* buff_len size of output buffer
|
||||
* Return
|
||||
* 0 Failure - null input rkey
|
||||
* -1 Failure - not enough space in output area
|
||||
* N Success - Length of data returned in buff
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_cylink_key_to_file_format(const DST_KEY *key, char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
char *bp;
|
||||
int len, b_len;
|
||||
DSA_Key *dkey;
|
||||
u_char num[256]; /* More than long enough for DSA keys */
|
||||
|
||||
if (key == NULL || key->dk_KEY_struct == NULL) /* no output */
|
||||
return (0);
|
||||
if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
|
||||
return (-1); /* no OR not enough space in output area */
|
||||
|
||||
dkey = (DSA_Key *) key->dk_KEY_struct;
|
||||
|
||||
memset(buff, 0, buff_len); /* just in case */
|
||||
/* write file header */
|
||||
sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_DSA, "DSA");
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->dk_p, dkey->dk_p_bytes);
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime(p): ",
|
||||
num, dkey->dk_p_bytes)) <= 0)
|
||||
return (-1);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->dk_q, dkey->dk_p_bytes);
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Subprime(q): ",
|
||||
num, SHA_LENGTH)) <= 0)
|
||||
return (-2);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->dk_g, dkey->dk_p_bytes);
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Base(g): ",
|
||||
num, dkey->dk_p_bytes)) <= 0)
|
||||
return (-3);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->dk_x, dkey->dk_p_bytes);
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Private_value(x): ",
|
||||
num, SHA_LENGTH)) <= 0)
|
||||
return (-4);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->dk_y, dkey->dk_p_bytes);
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Public_value(y): ",
|
||||
num, dkey->dk_p_bytes)) <= 0)
|
||||
return (-4);
|
||||
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
return (buff_len - b_len);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_cylink_key_from_file_format
|
||||
* Converts contents of a private key file into a private DSA key.
|
||||
* Parameters
|
||||
* DSA_Key structure to put key into
|
||||
* buff buffer containing the encoded key
|
||||
* buff_len the length of the buffer
|
||||
* Return
|
||||
* n >= 0 Foot print of the key converted
|
||||
* n < 0 Error in conversion
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_cylink_key_from_file_format(DST_KEY *d_key, const char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
u_char s[DSS_LENGTH_MAX];
|
||||
u_char dns[1024];
|
||||
int len, s_len = sizeof(s);
|
||||
int foot = -1, dnslen;
|
||||
const char *p = buff;
|
||||
DSA_Key *dsa_key;
|
||||
|
||||
if (d_key == NULL || buff == NULL || buff_len <= 0)
|
||||
return (-1);
|
||||
|
||||
dsa_key = (DSA_Key *) malloc(sizeof(DSA_Key));
|
||||
if (dsa_key == NULL) {
|
||||
return (-2);
|
||||
}
|
||||
memset(dsa_key, 0, sizeof(*dsa_key));
|
||||
d_key->dk_KEY_struct = (void *) dsa_key;
|
||||
|
||||
if (!dst_s_verify_str(&p, "Prime(p): "))
|
||||
return (-3);
|
||||
memset(s, 0, s_len);
|
||||
if ((len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)) == 0)
|
||||
return (-4);
|
||||
dsa_key->dk_p_bytes = len;
|
||||
if ((dsa_key->dk_p = malloc(len)) == NULL)
|
||||
return (-5);
|
||||
memcpy(dsa_key->dk_p, s + s_len - len, len);
|
||||
|
||||
while (*++p && p < (const char *) &buff[buff_len]) {
|
||||
if (dst_s_verify_str(&p, "Subprime(q): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-6);
|
||||
if ((dsa_key->dk_q = malloc(SHA_LENGTH)) == NULL)
|
||||
return (-7);
|
||||
memcpyend(dsa_key->dk_q, s + s_len - len, len,
|
||||
SHA_LENGTH);
|
||||
} else if (dst_s_verify_str(&p, "Base(g): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-8);
|
||||
if ((dsa_key->dk_g = malloc(dsa_key->dk_p_bytes))
|
||||
== NULL)
|
||||
return (-9);
|
||||
memcpyend(dsa_key->dk_g, s + s_len - len, len,
|
||||
dsa_key->dk_p_bytes);
|
||||
} else if (dst_s_verify_str(&p, "Private_value(x): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-10);
|
||||
if ((dsa_key->dk_x = malloc(SHA_LENGTH)) == NULL)
|
||||
return (-11);
|
||||
memcpyend(dsa_key->dk_x, s + s_len - len, len,
|
||||
SHA_LENGTH);
|
||||
} else if (dst_s_verify_str(&p, "Public_value(y): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-10);
|
||||
if ((dsa_key->dk_y = malloc(dsa_key->dk_p_bytes))
|
||||
== NULL)
|
||||
return (-11);
|
||||
memcpyend(dsa_key->dk_y, s + s_len - len, len,
|
||||
dsa_key->dk_p_bytes);
|
||||
} else {
|
||||
EREPORT(("Decode_DSAKey(): Bad keyword %s\n", p));
|
||||
return (-12);
|
||||
}
|
||||
} /* while p */
|
||||
|
||||
d_key->dk_key_size = dsa_key->dk_p_bytes * 8;
|
||||
dnslen = d_key->dk_func->to_dns_key(d_key, dns, sizeof(dns));
|
||||
foot = dst_s_id_calc(dns, dnslen);
|
||||
|
||||
return (foot);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_cylink_free_key_structure
|
||||
* Frees all dynamicly allocated structures in DSA_Key.
|
||||
*/
|
||||
|
||||
static void *
|
||||
dst_cylink_free_key_structure(void *key)
|
||||
{
|
||||
DSA_Key *d_key = (DSA_Key *) key;
|
||||
if (d_key != NULL) {
|
||||
SAFE_FREE(d_key->dk_signer);
|
||||
SAFE_FREE(d_key->dk_p);
|
||||
SAFE_FREE(d_key->dk_q);
|
||||
SAFE_FREE(d_key->dk_g);
|
||||
SAFE_FREE(d_key->dk_x);
|
||||
SAFE_FREE(d_key->dk_y);
|
||||
SAFE_FREE(d_key);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_cylink_generate_keypair
|
||||
* Generates unique keys that are hard to predict.
|
||||
* Parameters
|
||||
* key generic Key structure
|
||||
* exp the public exponent
|
||||
* Return
|
||||
* 0 Failure
|
||||
* 1 Success
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_cylink_generate_keypair(DST_KEY *key, int nothing)
|
||||
{
|
||||
int status, dnslen, n;
|
||||
DSA_Key *dsa;
|
||||
u_char rand[SHA_LENGTH];
|
||||
u_char dns[1024];
|
||||
|
||||
UNUSED(nothing);
|
||||
|
||||
if (key == NULL || key->dk_alg != KEY_DSA)
|
||||
return (0);
|
||||
|
||||
if ((dsa = (DSA_Key *) malloc(sizeof(DSA_Key))) == NULL) {
|
||||
EREPORT(("dst_cylink_generate_keypair: Memory allocation error 3"));
|
||||
return (0);
|
||||
}
|
||||
memset(dsa, 0, sizeof(*dsa));
|
||||
|
||||
dsa->dk_p_bytes = key->dk_key_size / 8;
|
||||
dsa->dk_p = (uchar *) malloc(dsa->dk_p_bytes);
|
||||
dsa->dk_q = (uchar *) malloc(SHA_LENGTH);
|
||||
dsa->dk_g = (uchar *) malloc(dsa->dk_p_bytes);
|
||||
dsa->dk_x = (uchar *) malloc(SHA_LENGTH);
|
||||
dsa->dk_y = (uchar *) malloc(dsa->dk_p_bytes);
|
||||
if (!dsa->dk_p || !dsa->dk_q || !dsa->dk_g || !dsa->dk_x || !dsa->dk_y) {
|
||||
EREPORT(("dst_cylink_generate_keypair: Memory allocation error 4"));
|
||||
return (0);
|
||||
}
|
||||
n = dst_random(DST_RAND_KEY, sizeof(rand), rand);
|
||||
if (n != sizeof(rand))
|
||||
return (0);
|
||||
status = GenDSSParameters(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q,
|
||||
dsa->dk_g, rand, NULL);
|
||||
if (status != SUCCESS)
|
||||
return (0);
|
||||
|
||||
status = GenDSSKey(dsa->dk_p_bytes, dsa->dk_p, dsa->dk_q, dsa->dk_g,
|
||||
dsa->dk_x, dsa->dk_y, rand);
|
||||
if (status != SUCCESS)
|
||||
return (0);
|
||||
memset(rand, 0, sizeof(rand));
|
||||
key->dk_KEY_struct = (void *) dsa;
|
||||
dnslen = key->dk_func->to_dns_key(key, dns, sizeof(dns));
|
||||
key->dk_id = dst_s_id_calc(dns, dnslen);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_cylink_compare_keys
|
||||
* Compare two keys for equality.
|
||||
* Return
|
||||
* 0 The keys are equal
|
||||
* NON-ZERO The keys are not equal
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_cylink_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
|
||||
{
|
||||
int status;
|
||||
DSA_Key *dkey1 = (DSA_Key *) key1->dk_KEY_struct;
|
||||
DSA_Key *dkey2 = (DSA_Key *) key2->dk_KEY_struct;
|
||||
|
||||
if (dkey1 == NULL && dkey2 == NULL)
|
||||
return (0);
|
||||
else if (dkey1 == NULL)
|
||||
return (2);
|
||||
else if (dkey2 == NULL)
|
||||
return(1);
|
||||
|
||||
if (dkey1->dk_p_bytes != dkey2->dk_p_bytes)
|
||||
return (201);
|
||||
status = memcmp(dkey1->dk_p, dkey2->dk_p, dkey1->dk_p_bytes) ||
|
||||
memcmp(dkey1->dk_q, dkey2->dk_q, SHA_LENGTH) ||
|
||||
memcmp(dkey1->dk_g, dkey2->dk_g, dkey1->dk_p_bytes) ||
|
||||
memcmp(dkey1->dk_y, dkey2->dk_y, dkey1->dk_p_bytes);
|
||||
if (status)
|
||||
return (status);
|
||||
if (dkey1->dk_x || dkey2->dk_x) {
|
||||
if (dkey1->dk_x == NULL || dkey2->dk_x == NULL)
|
||||
return (202);
|
||||
return (memcmp(dkey1->dk_x, dkey2->dk_x, dkey1->dk_p_bytes));
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void *
|
||||
memcpyend(void *dest, const void *src, size_t n, size_t size) {
|
||||
if (n < size)
|
||||
memset(dest, 0, size - n);
|
||||
memcpy((char *)dest + size - n, src, n);
|
||||
return dest;
|
||||
}
|
||||
|
||||
#else
|
||||
int
|
||||
dst_cylink_init()
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif /* CYLINK */
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef LINT
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/dst_api.c,v 1.2 2001/04/02 09:42:20 marka Exp $";
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/dst_api.c,v 1.3 2001/04/03 00:28:10 bwelling Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -121,11 +121,7 @@ dst_init()
|
||||
}
|
||||
memset(dst_t_func, 0, sizeof(dst_t_func));
|
||||
/* first one is selected */
|
||||
dst_bsafe_init();
|
||||
dst_rsaref_init();
|
||||
dst_hmac_md5_init();
|
||||
dst_eay_dss_init();
|
||||
dst_cylink_init();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1027,43 +1023,3 @@ dst_sig_size(DST_KEY *key) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_random
|
||||
* function that multiplexes number of random number generators
|
||||
* Parameters
|
||||
* mode: select the random number generator
|
||||
* wanted is how many bytes of random data are requested
|
||||
* outran is a buffer of size at least wanted for the output data
|
||||
*
|
||||
* Returns
|
||||
* number of bytes written to outran
|
||||
*/
|
||||
int
|
||||
dst_random(const int mode, int wanted, u_char *outran)
|
||||
{
|
||||
u_int32_t *buff = NULL, *bp = NULL;
|
||||
int i;
|
||||
if (wanted <= 0 || outran == NULL)
|
||||
return (0);
|
||||
|
||||
switch (mode) {
|
||||
case DST_RAND_SEMI:
|
||||
bp = buff = (u_int32_t *) malloc(wanted+sizeof(u_int32_t));
|
||||
for (i = 0; i < wanted; i+= sizeof(u_int32_t), bp++) {
|
||||
*bp = dst_s_quick_random(i);
|
||||
}
|
||||
memcpy(outran, buff, wanted);
|
||||
SAFE_FREE(buff);
|
||||
return (wanted);
|
||||
case DST_RAND_STD:
|
||||
return (dst_s_semi_random(outran, wanted));
|
||||
case DST_RAND_KEY:
|
||||
return (dst_s_random(outran, wanted));
|
||||
case DST_RAND_DSS:
|
||||
default:
|
||||
/* need error case here XXX OG */
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,12 +137,6 @@ int dst_s_build_filename( char *filename, const char *name,
|
||||
|
||||
FILE *dst_s_fopen (const char *filename, const char *mode, int perm);
|
||||
|
||||
/* from file prandom.c */
|
||||
int dst_s_random( u_int8_t *output, int size);
|
||||
int dst_s_semi_random( u_int8_t *output, int size);
|
||||
u_int32_t dst_s_quick_random( int inc);
|
||||
void dst_s_quick_random_set( u_int32_t val, u_int32_t cnt);
|
||||
|
||||
/*
|
||||
* read and write network byte order into u_int?_t
|
||||
* all of these should be retired
|
||||
|
||||
@@ -1,638 +0,0 @@
|
||||
#ifdef EAY_DSS
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/eay_dss_link.c,v 1.1 2001/03/29 06:31:31 marka Exp $";
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
* This file contains two components
|
||||
* 1. Interface to the EAY libcrypto library to allow compilation of Bind
|
||||
* with TIS/DNSSEC when EAY libcrypto is not available
|
||||
* all calls to libcrypto are contained inside this file.
|
||||
* 2. The glue to connvert DSA KEYS to and from external formats
|
||||
*/
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
|
||||
#include "crypto.h"
|
||||
#include "bn.h"
|
||||
#include "dsa.h"
|
||||
#include "sha.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
|
||||
static int dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
u_char *signature, const int sig_len);
|
||||
|
||||
static int dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
const u_char *signature, const int sig_len);
|
||||
|
||||
static int dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str,
|
||||
const int out_len);
|
||||
static int dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key,
|
||||
const int len);
|
||||
static int dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff,
|
||||
const int buff_len);
|
||||
static int dst_eay_dss_key_from_file_format(DST_KEY *d_key,
|
||||
const u_char *buff,
|
||||
const int buff_len);
|
||||
static void *dst_eay_dss_free_key_structure(void *key);
|
||||
|
||||
static int dst_eay_dss_generate_keypair(DST_KEY *key, int exp);
|
||||
static int dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2);
|
||||
|
||||
/*
|
||||
* dst_eay_dss_init() Function to answer set up function pointers for
|
||||
* EAY DSS related functions
|
||||
*/
|
||||
int
|
||||
dst_eay_dss_init(void)
|
||||
{
|
||||
if (dst_t_func[KEY_DSA] != NULL)
|
||||
return (1);
|
||||
dst_t_func[KEY_DSA] = malloc(sizeof(struct dst_func));
|
||||
if (dst_t_func[KEY_DSA] == NULL)
|
||||
return (0);
|
||||
memset(dst_t_func[KEY_DSA], 0, sizeof(struct dst_func));
|
||||
dst_t_func[KEY_DSA]->sign = dst_eay_dss_sign;
|
||||
dst_t_func[KEY_DSA]->verify = dst_eay_dss_verify;
|
||||
dst_t_func[KEY_DSA]->compare = dst_eay_dss_compare_keys;
|
||||
dst_t_func[KEY_DSA]->generate = dst_eay_dss_generate_keypair;
|
||||
dst_t_func[KEY_DSA]->destroy = dst_eay_dss_free_key_structure;
|
||||
dst_t_func[KEY_DSA]->from_dns_key = dst_eay_dss_from_dns_key;
|
||||
dst_t_func[KEY_DSA]->to_dns_key = dst_eay_dss_to_dns_key;
|
||||
dst_t_func[KEY_DSA]->from_file_fmt = dst_eay_dss_key_from_file_format;
|
||||
dst_t_func[KEY_DSA]->to_file_fmt = dst_eay_dss_key_to_file_format;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_eay_dss_sign
|
||||
* Call EAY DSS 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 SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* algobj structure holds context for a sign done in multiple calls.
|
||||
* context the context to use for this computation
|
||||
* data data to be signed.
|
||||
* len length in bytes of data.
|
||||
* priv_key key to use for signing.
|
||||
* signature location to store signature.
|
||||
* sig_len size in bytes of signature field.
|
||||
* returns
|
||||
* N Success on SIG_MODE_FINAL = returns signature length in bytes
|
||||
* N is 41 for DNS
|
||||
* 0 Success on SIG_MODE_INIT and UPDATE
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_eay_dss_sign(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
u_char *signature, const int sig_len)
|
||||
{
|
||||
int sign_len = 0;
|
||||
int status;
|
||||
SHA_CTX *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = (SHA_CTX *) malloc(sizeof(SHA_CTX));
|
||||
else if (context)
|
||||
ctx = (SHA_CTX *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
SHA1_Init(ctx);
|
||||
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) {
|
||||
SHA1_Update(ctx, (u_char *) data, len);
|
||||
}
|
||||
if (mode & SIG_MODE_FINAL) {
|
||||
DSA *key;
|
||||
u_char digest[SHA_DIGEST_LENGTH];
|
||||
u_char rand[SHA_DIGEST_LENGTH];
|
||||
u_char r[SHA_DIGEST_LENGTH], s[SHA_DIGEST_LENGTH];
|
||||
|
||||
if (dkey == NULL || dkey->dk_KEY_struct == NULL)
|
||||
return (-1);
|
||||
key = dkey->dk_KEY_struct;
|
||||
if (key == NULL)
|
||||
return(-2);
|
||||
SHA1_Final(digest, ctx);
|
||||
status = DSA_sign(0, digest, SHA_DIGEST_LENGTH,
|
||||
signature, &sign_len, key);
|
||||
if (status != 0)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
|
||||
*signature = (dkey->dk_key_size - 512)/64;
|
||||
sign_len = 1;
|
||||
memcpy(signature + sign_len, r, SHA_DIGEST_LENGTH);
|
||||
sign_len += SHA_DIGEST_LENGTH;
|
||||
memcpy(signature + sign_len, s, SHA_DIGEST_LENGTH);
|
||||
sign_len += SHA_DIGEST_LENGTH;
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
return (sign_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_eay_dss_verify
|
||||
* Calls EAY DSS 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 SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* dkey structure holds context for a verify done in multiple calls.
|
||||
* context algorithm specific context for the current context processing
|
||||
* data data signed.
|
||||
* len length in bytes of data.
|
||||
* pub_key key to use for verify.
|
||||
* signature signature.
|
||||
* sig_len length in bytes of signature.
|
||||
* returns
|
||||
* 0 Success
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_eay_dss_verify(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
const u_char *signature, const int sig_len)
|
||||
{
|
||||
int status;
|
||||
SHA_CTX *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = (SHA_CTX *) malloc(sizeof(SHA_CTX));
|
||||
else if (context)
|
||||
ctx = (SHA_CTX *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
SHA1_Init(ctx);
|
||||
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) {
|
||||
SHA1_Update(ctx, (u_char *) data, len);
|
||||
}
|
||||
if (mode & SIG_MODE_FINAL) {
|
||||
DSA *key;
|
||||
u_char digest[SHA_DIGEST_LENGTH];
|
||||
u_char r[SHA_DIGEST_LENGTH], s[SHA_DIGEST_LENGTH];
|
||||
|
||||
if (dkey == NULL || dkey->dk_KEY_struct == NULL)
|
||||
return (-1);
|
||||
key = (DSA *) dkey->dk_KEY_struct;
|
||||
if (key = NULL)
|
||||
return (-2);
|
||||
if (signature == NULL || sig_len != (2 * SHA_DIGEST_LENGTH +1))
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
SHA1_Final(digest, ctx);
|
||||
SAFE_FREE(ctx);
|
||||
if (status != 0)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
if (((int)*signature) != ((BN_num_bytes(key->p) -64)/8))
|
||||
return(VERIFY_FINAL_FAILURE);
|
||||
|
||||
memcpy(r, signature +1, SHA_DIGEST_LENGTH);
|
||||
memcpy(s, signature + SHA_DIGEST_LENGTH +1, SHA_DIGEST_LENGTH);
|
||||
status = DSA_verify(0, digest, SHA_DIGEST_LENGTH,
|
||||
(u_char *)signature, sig_len, key);
|
||||
if (status != 0)
|
||||
return (VERIFY_FINAL_FAILURE);
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_eay_dss_to_dns_key
|
||||
* Converts key from DSA to DNS distribution format
|
||||
* This function gets in a pointer to the public key and a work area
|
||||
* to write the key into.
|
||||
* Parameters
|
||||
* public KEY structure
|
||||
* out_str buffer to write encoded key into
|
||||
* out_len size of out_str
|
||||
* Return
|
||||
* N >= 0 length of encoded key
|
||||
* n < 0 error
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_eay_dss_to_dns_key(const DST_KEY *in_key, u_char *out_str,
|
||||
const int out_len)
|
||||
{
|
||||
u_char *op = out_str;
|
||||
int t;
|
||||
DSA *key;
|
||||
|
||||
if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
|
||||
out_len <= 0 || out_str == NULL)
|
||||
return (-1);
|
||||
key = (DSA *) in_key->dk_KEY_struct;
|
||||
|
||||
t = (BN_num_bytes(key->p) - 64) / 8;
|
||||
|
||||
*op++ = t;
|
||||
BN_bn2bin(key->q, op);
|
||||
op += BN_num_bytes(key->q);
|
||||
BN_bn2bin(key->p, op);
|
||||
op += BN_num_bytes(key->p);
|
||||
BN_bn2bin(key->g, op);
|
||||
op += BN_num_bytes(key->g);
|
||||
BN_bn2bin(key->pub_key, op);
|
||||
op += BN_num_bytes(key->pub_key);
|
||||
|
||||
return (op - out_str);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_eay_dss_from_dns_key
|
||||
* Converts from a DNS KEY RR format to an RSA KEY.
|
||||
* Parameters
|
||||
* len Length in bytes of DNS key
|
||||
* key DNS key
|
||||
* name Key name
|
||||
* s_key DST structure that will point to the RSA key this routine
|
||||
* will build.
|
||||
* Return
|
||||
* 0 The input key, s_key or name was null.
|
||||
* 1 Success
|
||||
*/
|
||||
static int
|
||||
dst_eay_dss_from_dns_key(DST_KEY *s_key, const u_char *key, const int len)
|
||||
{
|
||||
int t;
|
||||
u_char *key_ptr = (u_char *)key;
|
||||
DSA *d_key;
|
||||
int p_bytes;
|
||||
|
||||
if (s_key == NULL || len < 0 || key == NULL)
|
||||
return (0);
|
||||
|
||||
if (len == 0) /* process null key */
|
||||
return (1);
|
||||
|
||||
if (key_ptr == NULL)
|
||||
return (0);
|
||||
t = (int) *key_ptr++; /* length of exponent in bytes */
|
||||
p_bytes = 64 + 8 * t;
|
||||
|
||||
if ((3 * (t * 8 + 64) + SHA_DIGEST_LENGTH + 1) != len)
|
||||
return (0);
|
||||
|
||||
if ((d_key = (DSA *) malloc(sizeof(DSA))) == NULL) {
|
||||
EREPORT(("dst_eay_dss_from_dns_key(): Memory allocation error 1"));
|
||||
return (0);
|
||||
}
|
||||
memset(d_key, 0, sizeof(DSA));
|
||||
s_key->dk_KEY_struct = (void *) d_key;
|
||||
|
||||
d_key->q = BN_bin2bn(key_ptr, SHA_DIGEST_LENGTH, NULL);
|
||||
key_ptr += SHA_DIGEST_LENGTH;
|
||||
|
||||
d_key->p = BN_bin2bn(key_ptr, p_bytes, NULL);
|
||||
key_ptr += p_bytes;
|
||||
|
||||
d_key->g = BN_bin2bn(key_ptr, p_bytes, NULL);
|
||||
key_ptr += p_bytes;
|
||||
|
||||
d_key->pub_key = BN_bin2bn(key_ptr, p_bytes, NULL);
|
||||
key_ptr += p_bytes;
|
||||
|
||||
s_key->dk_id = dst_s_id_calc(key, len);
|
||||
s_key->dk_key_size = p_bytes * 8;
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_eay_dss_key_to_file_format
|
||||
* Encodes an DSA Key into the portable file format.
|
||||
* Parameters
|
||||
* key DSA KEY structure
|
||||
* buff output buffer
|
||||
* buff_len size of output buffer
|
||||
* Return
|
||||
* 0 Failure - null input rkey
|
||||
* -1 Failure - not enough space in output area
|
||||
* N Success - Length of data returned in buff
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_eay_dss_key_to_file_format(const DST_KEY *key, u_char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
u_char *bp;
|
||||
int len, b_len;
|
||||
DSA *dkey;
|
||||
char num[256]; /* More than long enough for DSA keys */
|
||||
|
||||
if (key == NULL || key->dk_KEY_struct == NULL) /* no output */
|
||||
return (0);
|
||||
if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
|
||||
return (-1); /* no OR not enough space in output area */
|
||||
|
||||
dkey = (DSA *) key->dk_KEY_struct;
|
||||
|
||||
memset(buff, 0, buff_len); /* just in case */
|
||||
/* write file header */
|
||||
sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_DSA, "DSA");
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->p, BN_num_bytes(dkey->p));
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime(p): ", num,
|
||||
BN_num_bytes(dkey->p))) <= 0)
|
||||
return (-1);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->q, BN_num_bytes(dkey->q));
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Subprime(q): ", num,
|
||||
BN_num_bytes(dkey->q))) <= 0)
|
||||
return (-2);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->g, BN_num_bytes(dkey->g));
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Base(g): ", num,
|
||||
BN_num_bytes(dkey->g))) <= 0)
|
||||
return (-3);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->priv_key, BN_num_bytes(dkey->priv_key));
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Private_value(x): ",
|
||||
num,
|
||||
BN_num_bytes(dkey->priv_key)))
|
||||
<= 0)
|
||||
return (-4);
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
memcpy(num, dkey->pub_key, BN_num_bytes(dkey->pub_key));
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Public_value(y): ",
|
||||
num,
|
||||
BN_num_bytes(dkey->pub_key)))
|
||||
<= 0)
|
||||
return (-5);
|
||||
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
return (buff_len - b_len);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_eay_dss_key_from_file_format
|
||||
* Converts contents of a private key file into a private DSA key.
|
||||
* Parameters
|
||||
* d_key structure to put key into
|
||||
* buff buffer containing the encoded key
|
||||
* buff_len the length of the buffer
|
||||
* Return
|
||||
* n >= 0 Foot print of the key converted
|
||||
* n < 0 Error in conversion
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_eay_dss_key_from_file_format(DST_KEY *d_key, const u_char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
char s[128];
|
||||
char dns[1024];
|
||||
int len, s_len = sizeof(s);
|
||||
int foot = -1, dnslen;
|
||||
const char *p = buff;
|
||||
DSA *dsa_key;
|
||||
|
||||
if (d_key == NULL || buff == NULL || buff_len <= 0)
|
||||
return (-1);
|
||||
|
||||
dsa_key = (DSA *) malloc(sizeof(DSA));
|
||||
if (dsa_key == NULL) {
|
||||
return (-2);
|
||||
}
|
||||
memset(dsa_key, 0, sizeof(*dsa_key));
|
||||
d_key->dk_KEY_struct = (void *) dsa_key;
|
||||
|
||||
if (!dst_s_verify_str(&p, "Prime(p): "))
|
||||
return (-3);
|
||||
memset(s, 0, s_len);
|
||||
if ((len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)) == 0)
|
||||
return (-4);
|
||||
dsa_key->p = BN_bin2bn (s, len, NULL);
|
||||
if (dsa_key->p == NULL)
|
||||
return(-5);
|
||||
|
||||
while (*++p && p < (const char *) &buff[buff_len]) {
|
||||
if (dst_s_verify_str(&p, "Subprime(q): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-6);
|
||||
dsa_key->q = BN_bin2bn (s, len, NULL);
|
||||
if (dsa_key->q == NULL)
|
||||
return (-7);
|
||||
} else if (dst_s_verify_str(&p, "Base(g): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-8);
|
||||
dsa_key->g = BN_bin2bn (s, len, NULL);
|
||||
if (dsa_key->g == NULL)
|
||||
return (-9);
|
||||
} else if (dst_s_verify_str(&p, "Private_value(x): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-10);
|
||||
dsa_key->priv_key = BN_bin2bn (s, len, NULL);
|
||||
if (dsa_key->priv_key == NULL)
|
||||
return (-11);
|
||||
} else if (dst_s_verify_str(&p, "Public_value(y): ")) {
|
||||
if (!(len = dst_s_conv_bignum_b64_to_u8(&p, s, s_len)))
|
||||
return (-12);
|
||||
dsa_key->pub_key = BN_bin2bn (s, len, NULL);
|
||||
if (dsa_key->pub_key == NULL)
|
||||
return (-13);
|
||||
} else {
|
||||
EREPORT(("Decode_DSAKey(): Bad keyword %s\n", p));
|
||||
return (-14);
|
||||
}
|
||||
} /* while p */
|
||||
|
||||
d_key->dk_key_size = BN_num_bytes(dsa_key->p);
|
||||
dnslen = d_key->dk_func->to_dns_key(d_key, dns, sizeof(dns));
|
||||
foot = dst_s_id_calc(dns, dnslen);
|
||||
|
||||
return (foot);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_eay_dss_free_key_structure
|
||||
* Frees all dynamicly allocated structures in DSA.
|
||||
*/
|
||||
|
||||
static void *
|
||||
dst_eay_dss_free_key_structure(void *key)
|
||||
{
|
||||
DSA *d_key = (DSA *) key;
|
||||
if (d_key != NULL) {
|
||||
BN_free(d_key->p);
|
||||
BN_free(d_key->q);
|
||||
BN_free(d_key->g);
|
||||
if (d_key->pub_key)
|
||||
BN_free(d_key->pub_key);
|
||||
if (d_key->priv_key)
|
||||
BN_free(d_key->priv_key);
|
||||
SAFE_FREE(d_key);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* dst_eay_dss_generate_keypair
|
||||
* Generates unique keys that are hard to predict.
|
||||
* Parameters
|
||||
* key generic Key structure
|
||||
* exp the public exponent
|
||||
* Return
|
||||
* 0 Failure
|
||||
* 1 Success
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_eay_dss_generate_keypair(DST_KEY *key, int nothing)
|
||||
{
|
||||
int status, dnslen, n;
|
||||
DSA *dsa;
|
||||
u_char rand[SHA_DIGEST_LENGTH];
|
||||
char dns[1024];
|
||||
|
||||
if (key == NULL || key->dk_alg != KEY_DSA)
|
||||
return (0);
|
||||
|
||||
if ((dsa = (DSA *) malloc(sizeof(DSA))) == NULL) {
|
||||
EREPORT(("dst_eay_dss_generate_keypair: Memory allocation error 3"));
|
||||
return (0);
|
||||
}
|
||||
memset(dsa, 0, sizeof(*dsa));
|
||||
|
||||
n = dst_random(DST_RAND_KEY, sizeof(rand), rand);
|
||||
if (n != sizeof(rand))
|
||||
return (0);
|
||||
dsa = DSA_generate_parameters(key->dk_key_size, rand, 20, NULL, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
if (!dsa) {
|
||||
EREPORT(("dst_eay_dss_generate_keypair: Generate Parameters failed"));
|
||||
return (0);
|
||||
}
|
||||
if (DSA_generate_key(dsa) == 0) {
|
||||
EREPORT(("dst_eay_dss_generate_keypair: Generate Key failed"));
|
||||
return(0);
|
||||
}
|
||||
key->dk_KEY_struct = (void *) dsa;
|
||||
dnslen = key->dk_func->to_dns_key(key, dns, sizeof(dns));
|
||||
key->dk_id = dst_s_id_calc(dns, dnslen);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_eay_dss_compare_keys
|
||||
* Compare two keys for equality.
|
||||
* Return
|
||||
* 0 The keys are equal
|
||||
* NON-ZERO The keys are not equal
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_eay_dss_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
|
||||
{
|
||||
int status;
|
||||
DSA *dkey1 = (DSA *) key1->dk_KEY_struct;
|
||||
DSA *dkey2 = (DSA *) key2->dk_KEY_struct;
|
||||
|
||||
if (dkey1 == NULL && dkey2 == NULL)
|
||||
return (0);
|
||||
else if (dkey1 == NULL)
|
||||
return (2);
|
||||
else if (dkey2 == NULL)
|
||||
return(1);
|
||||
|
||||
status = BN_cmp(dkey1->p, dkey2->p) ||
|
||||
BN_cmp(dkey1->q, dkey2->q) ||
|
||||
BN_cmp(dkey1->g, dkey2->g) ||
|
||||
BN_cmp(dkey1->pub_key, dkey2->pub_key);
|
||||
|
||||
if (status)
|
||||
return (status);
|
||||
|
||||
if (dkey1->priv_key || dkey2->priv_key) {
|
||||
if (dkey1->priv_key == NULL || dkey2->priv_key == NULL)
|
||||
return (202);
|
||||
return (BN_cmp(dkey1->priv_key, dkey2->priv_key));
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
#include "port_after.h"
|
||||
int
|
||||
dst_eay_dss_init(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif /* EAY_DSS */
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifdef HMAC_MD5
|
||||
#ifndef LINT
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/hmac_link.c,v 1.1 2001/03/29 06:31:31 marka Exp $";
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/hmac_link.c,v 1.2 2001/04/03 00:28:14 bwelling Exp $";
|
||||
#endif
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
@@ -428,31 +428,9 @@ dst_hmac_md5_free_key_structure(void *key)
|
||||
static int
|
||||
dst_hmac_md5_generate_key(DST_KEY *key, const int nothing)
|
||||
{
|
||||
u_char *buff;
|
||||
int i, n, size;
|
||||
|
||||
i = nothing;
|
||||
|
||||
if (key == NULL || key->dk_alg != KEY_HMAC_MD5)
|
||||
return (0);
|
||||
size = (key->dk_key_size + 7) / 8; /* convert to bytes */
|
||||
if (size <= 0)
|
||||
return(0);
|
||||
|
||||
i = size > 64 ? 64 : size;
|
||||
buff = malloc(i+8);
|
||||
|
||||
n = dst_random(DST_RAND_SEMI, i, buff);
|
||||
n += dst_random(DST_RAND_KEY, i, buff);
|
||||
if (n <= i) { /* failed getting anything */
|
||||
SAFE_FREE2(buff, i);
|
||||
return (-1);
|
||||
}
|
||||
n = dst_buffer_to_hmac_md5(key, buff, i);
|
||||
SAFE_FREE2(buff, i);
|
||||
if (n <= 0)
|
||||
return (n);
|
||||
return (1);
|
||||
(void)key;
|
||||
(void)nothing;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,855 +0,0 @@
|
||||
#ifndef LINT
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/prandom.c,v 1.1 2001/03/29 06:31:33 marka Exp $";
|
||||
#endif
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "port_before.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
#include "prand_conf.h"
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
#ifndef DST_NUM_HASHES
|
||||
#define DST_NUM_HASHES 4
|
||||
#endif
|
||||
#ifndef DST_NUMBER_OF_COUNTERS
|
||||
#define DST_NUMBER_OF_COUNTERS 5 /* 32 * 5 == 160 == SHA(1) > MD5 */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the constant below is a prime number to make fixed data structues like
|
||||
* stat and time wrap over blocks. This adds certain uncertanty to what is
|
||||
* in each digested block.
|
||||
* The prime number 2879 has the special property that when
|
||||
* divided by 2,4 and 6 the result is also a prime numbers
|
||||
*/
|
||||
|
||||
#ifndef DST_RANDOM_BLOCK_SIZE
|
||||
#define DST_RANDOM_BLOCK_SIZE 2879
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This constant dictatates how many bits we shift to the right before using a
|
||||
*/
|
||||
#ifndef DST_SHIFT
|
||||
#define DST_SHIFT 9
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An initalizer that is as bad as any other with half the bits set
|
||||
*/
|
||||
#ifndef DST_RANDOM_PATTERN
|
||||
#define DST_RANDOM_PATTERN 0x8765CA93
|
||||
#endif
|
||||
/*
|
||||
* things must have changed in the last 3600 seconds to be used
|
||||
*/
|
||||
#define MAX_OLD 3600
|
||||
|
||||
|
||||
/*
|
||||
* these two data structure are used to process input data into digests,
|
||||
*
|
||||
* The first structure is containts a pointer to a DST HMAC key
|
||||
* the variables accompanying are used for
|
||||
* step : select every step byte from input data for the hash
|
||||
* block: number of data elements going into each hash
|
||||
* digested: number of data elements digested so far
|
||||
* curr: offset into the next input data for the first byte.
|
||||
*/
|
||||
typedef struct hash {
|
||||
DST_KEY *key;
|
||||
void *ctx;
|
||||
int digested, block, step, curr;
|
||||
} prand_hash;
|
||||
|
||||
/*
|
||||
* This data structure controlls number of hashes and keeps track of
|
||||
* overall progress in generating correct number of bytes of output.
|
||||
* output : array to store the output data in
|
||||
* needed : how many bytes of output are needed
|
||||
* filled : number of bytes in output so far.
|
||||
* bytes : total number of bytes processed by this structure
|
||||
* file_digest : the HMAC key used to digest files.
|
||||
*/
|
||||
typedef struct work {
|
||||
int needed, filled, bytes;
|
||||
u_char *output;
|
||||
prand_hash *hash[DST_NUM_HASHES];
|
||||
DST_KEY *file_digest;
|
||||
} dst_work;
|
||||
|
||||
|
||||
/*
|
||||
* forward function declarations
|
||||
*/
|
||||
static int get_dev_random(u_char *output, int size);
|
||||
static int do_time(dst_work *work);
|
||||
static int do_ls(dst_work *work);
|
||||
static int unix_cmd(dst_work *work);
|
||||
static int digest_file(dst_work *work);
|
||||
|
||||
static void force_hash(dst_work *work, prand_hash *hash);
|
||||
static int do_hash(dst_work *work, prand_hash *hash, const u_char *input,
|
||||
int size);
|
||||
static int my_digest(dst_work *tmp, const u_char *input, int size);
|
||||
static prand_hash *get_hmac_key(int step, int block);
|
||||
|
||||
static int own_random(dst_work *work);
|
||||
|
||||
|
||||
/*
|
||||
* variables used in the quick random number generator
|
||||
*/
|
||||
static u_int32_t ran_val = DST_RANDOM_PATTERN;
|
||||
static u_int32_t ran_cnt = (DST_RANDOM_PATTERN >> 10);
|
||||
|
||||
/*
|
||||
* setting the quick_random generator to particular values or if both
|
||||
* input parameters are 0 then set it to initial vlaues
|
||||
*/
|
||||
|
||||
void
|
||||
dst_s_quick_random_set(u_int32_t val, u_int32_t cnt)
|
||||
{
|
||||
ran_val = (val == 0) ? DST_RANDOM_PATTERN : val;
|
||||
ran_cnt = (cnt == 0) ? (DST_RANDOM_PATTERN >> 10) : cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is a quick and random number generator that seems to generate quite
|
||||
* good distribution of data
|
||||
*/
|
||||
u_int32_t
|
||||
dst_s_quick_random(int inc)
|
||||
{
|
||||
ran_val = ((ran_val >> 13) ^ (ran_val << 19)) ^
|
||||
((ran_val >> 7) ^ (ran_val << 25));
|
||||
if (inc > 0) /* only increasing values accepted */
|
||||
ran_cnt += inc;
|
||||
ran_val += ran_cnt++;
|
||||
return (ran_val);
|
||||
}
|
||||
|
||||
/*
|
||||
* get_dev_random: Function to read /dev/random reliably
|
||||
* this function returns how many bytes where read from the device.
|
||||
* port_after.h should set the control variable HAVE_DEV_RANDOM
|
||||
*/
|
||||
static int
|
||||
get_dev_random(u_char *output, int size)
|
||||
{
|
||||
#ifdef HAVE_DEV_RANDOM
|
||||
struct stat st;
|
||||
int n = 0, fd = -1, s;
|
||||
|
||||
s = stat("/dev/random", &st);
|
||||
if (s == 0 && S_ISCHR(st.st_mode)) {
|
||||
if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) != -1) {
|
||||
if ((n = read(fd, output, size)) < 0)
|
||||
n = 0;
|
||||
close(fd);
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Portable way of getting the time values if gettimeofday is missing
|
||||
* then compile with -DMISSING_GETTIMEOFDAY time() is POSIX compliant but
|
||||
* gettimeofday() is not.
|
||||
* Time of day is predictable, we are looking for the randomness that comes
|
||||
* the last few bits in the microseconds in the timer are hard to predict when
|
||||
* this is invoked at the end of other operations
|
||||
*/
|
||||
struct timeval *mtime;
|
||||
static int
|
||||
do_time(dst_work *work)
|
||||
{
|
||||
int cnt = 0;
|
||||
static u_char tmp[sizeof(struct timeval) + sizeof(struct timezone)];
|
||||
struct timezone *zone;
|
||||
|
||||
zone = (struct timezone *) tmp;
|
||||
mtime = (struct timeval *)(tmp + sizeof(struct timezone));
|
||||
gettimeofday(mtime, zone);
|
||||
cnt = sizeof(tmp);
|
||||
my_digest(work, tmp, sizeof(tmp));
|
||||
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* this function simulates the ls command, but it uses stat which gives more
|
||||
* information and is harder to guess
|
||||
* Each call to this function will visit the next directory on the list of
|
||||
* directories, in a circular manner.
|
||||
* return value is the number of bytes added to the temp buffer
|
||||
*
|
||||
* do_ls() does not visit subdirectories
|
||||
* if attacker has access to machine it can guess most of the values seen
|
||||
* thus it is important to only visit directories that are freqently updated
|
||||
* Attacker that has access to the network can see network traffic
|
||||
* when NFS mounted directories are accessed and know exactly the data used
|
||||
* but may not know exactly in what order data is used.
|
||||
* Returns the number of bytes that where returned in stat structures
|
||||
*/
|
||||
static int
|
||||
do_ls(dst_work *work)
|
||||
{
|
||||
struct dir_info {
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
off_t size;
|
||||
time_t atime, mtime, ctime;
|
||||
};
|
||||
static struct dir_info dir_info;
|
||||
struct stat buf;
|
||||
struct dirent *entry;
|
||||
static int i = 0;
|
||||
static unsigned long d_round = 0;
|
||||
struct timeval tv;
|
||||
int n = 0, dir_len, tb_i = 0, out = 0;
|
||||
|
||||
char file_name[1024];
|
||||
u_char tmp_buff[1024];
|
||||
DIR *dir = NULL;
|
||||
|
||||
if (dirs[i] == NULL) /* if at the end of the list start over */
|
||||
i = 0;
|
||||
if (stat(dirs[i++], &buf)) /* directory does not exist */
|
||||
return (0);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
if (d_round == 0)
|
||||
d_round = tv.tv_sec - MAX_OLD;
|
||||
else if (i==1) /* if starting a new round cut what we accept */
|
||||
d_round += (tv.tv_sec - d_round)/2;
|
||||
|
||||
if (buf.st_atime < (time_t)d_round)
|
||||
return (0);
|
||||
|
||||
EREPORT(("do_ls i %d filled %4d in_temp %4d\n",
|
||||
i-1, work->filled, work->in_temp));
|
||||
memcpy(tmp_buff, &buf, sizeof(buf));
|
||||
tb_i += sizeof(buf);
|
||||
|
||||
|
||||
if ((dir = opendir(dirs[i-1])) == NULL)/* open it for read */
|
||||
return (0);
|
||||
strcpy(file_name, dirs[i-1]);
|
||||
dir_len = strlen(file_name);
|
||||
file_name[dir_len++] = '/';
|
||||
while ((entry = readdir(dir))) {
|
||||
int len = strlen(entry->d_name);
|
||||
out += len;
|
||||
if (my_digest(work, (u_char *)entry->d_name, len))
|
||||
break;
|
||||
|
||||
memcpy(&file_name[dir_len], entry->d_name, len);
|
||||
file_name[dir_len + len] = 0x0;
|
||||
/* for all entries in dir get the stats */
|
||||
if (stat(file_name, &buf) == 0) {
|
||||
n++; /* count successfull stat calls */
|
||||
/* copy non static fields */
|
||||
dir_info.uid += buf.st_uid;
|
||||
dir_info.gid += buf.st_gid;
|
||||
dir_info.size += buf.st_size;
|
||||
dir_info.atime += buf.st_atime;
|
||||
dir_info.mtime += buf.st_mtime;
|
||||
dir_info.ctime += buf.st_ctime;
|
||||
out += sizeof(dir_info);
|
||||
if(my_digest(work, (u_char *)&dir_info,
|
||||
sizeof(dir_info)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir); /* done */
|
||||
out += do_time(work); /* add a time stamp */
|
||||
return (out);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* unix_cmd()
|
||||
* this function executes the a command from the cmds[] list of unix commands
|
||||
* configured in the prand_conf.h file
|
||||
* return value is the number of bytes added to the randomness temp buffer
|
||||
*
|
||||
* it returns the number of bytes that where read in
|
||||
* if more data is needed at the end time is added to the data.
|
||||
* This function maintains a state to selects the next command to run
|
||||
* returns the number of bytes read in from the command
|
||||
*/
|
||||
static int
|
||||
unix_cmd(dst_work *work)
|
||||
{
|
||||
static int cmd_index = 0;
|
||||
int cnt = 0, n;
|
||||
FILE *pipe;
|
||||
u_char buffer[4096];
|
||||
|
||||
if (cmds[cmd_index] == NULL)
|
||||
cmd_index = 0;
|
||||
EREPORT(("unix_cmd() i %d filled %4d in_temp %4d\n",
|
||||
cmd_index, work->filled, work->in_temp));
|
||||
pipe = popen(cmds[cmd_index++], "r"); /* execute the command */
|
||||
|
||||
while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) {
|
||||
cnt += n; /* process the output */
|
||||
if (my_digest(work, buffer, n))
|
||||
break;
|
||||
/* this adds some randomness to the output */
|
||||
cnt += do_time(work);
|
||||
}
|
||||
while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0)
|
||||
(void)NULL; /* drain the pipe */
|
||||
pclose(pipe);
|
||||
return (cnt); /* read how many bytes where read in */
|
||||
}
|
||||
|
||||
/*
|
||||
* digest_file() This function will read a file and run hash over it
|
||||
* input is a file name
|
||||
*/
|
||||
static int
|
||||
digest_file(dst_work *work)
|
||||
{
|
||||
static int f_cnt = 0;
|
||||
static unsigned long f_round = 0;
|
||||
FILE *fp;
|
||||
void *ctx;
|
||||
const char *name;
|
||||
int no, i;
|
||||
struct stat st;
|
||||
struct timeval tv;
|
||||
u_char buf[1024];
|
||||
|
||||
if (f_round == 0 || files[f_cnt] == NULL || work->file_digest == NULL)
|
||||
if (gettimeofday(&tv, NULL)) /* only do this if needed */
|
||||
return (0);
|
||||
if (f_round == 0) /* first time called set to one hour ago */
|
||||
f_round = (tv.tv_sec - MAX_OLD);
|
||||
name = files[f_cnt++];
|
||||
if (files[f_cnt] == NULL) { /* end of list of files */
|
||||
if(f_cnt <= 1) /* list is too short */
|
||||
return (0);
|
||||
f_cnt = 0; /* start again on list */
|
||||
f_round += (tv.tv_sec - f_round)/2; /* set new cutoff */
|
||||
work->file_digest = dst_free_key(work->file_digest);
|
||||
}
|
||||
if (work->file_digest == NULL) {
|
||||
work->file_digest = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0,
|
||||
(u_char *)&tv, sizeof(tv));
|
||||
if (work->file_digest == NULL)
|
||||
return (0);
|
||||
}
|
||||
if (access(name, R_OK) || stat(name, &st))
|
||||
return (0); /* no such file or not allowed to read it */
|
||||
if (strncmp(name, "/proc/", 6) && st.st_mtime < (time_t)f_round)
|
||||
return(0); /* file has not changed recently enough */
|
||||
if (dst_sign_data(SIG_MODE_INIT, work->file_digest, &ctx,
|
||||
NULL, 0, NULL, 0)) {
|
||||
work->file_digest = dst_free_key(work->file_digest);
|
||||
return (0);
|
||||
}
|
||||
if ((fp = fopen(name, "r")) == NULL)
|
||||
return (0);
|
||||
for (no = 0; (i = fread(buf, sizeof(*buf), sizeof(buf), fp)) > 0;
|
||||
no += i)
|
||||
dst_sign_data(SIG_MODE_UPDATE, work->file_digest, &ctx,
|
||||
buf, i, NULL, 0);
|
||||
|
||||
fclose(fp);
|
||||
if (no >= 64) {
|
||||
i = dst_sign_data(SIG_MODE_FINAL, work->file_digest, &ctx,
|
||||
NULL, 0, &work->output[work->filled],
|
||||
DST_HASH_SIZE);
|
||||
if (i > 0)
|
||||
work->filled += i;
|
||||
}
|
||||
else if (i > 0)
|
||||
my_digest(work, buf, i);
|
||||
my_digest(work, (const u_char *)name, strlen(name));
|
||||
return (no + strlen(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* function to perform the FINAL and INIT operation on a hash if allowed
|
||||
*/
|
||||
static void
|
||||
force_hash(dst_work *work, prand_hash *hash)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* if more than half a block then add data to output
|
||||
* otherwise adde the digest to the next hash
|
||||
*/
|
||||
if ((hash->digested * 2) > hash->block) {
|
||||
i = dst_sign_data(SIG_MODE_FINAL, hash->key, &hash->ctx,
|
||||
NULL, 0, &work->output[work->filled],
|
||||
DST_HASH_SIZE);
|
||||
|
||||
hash->digested = 0;
|
||||
dst_sign_data(SIG_MODE_INIT, hash->key, &hash->ctx,
|
||||
NULL, 0, NULL, 0);
|
||||
if (i > 0)
|
||||
work->filled += i;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function takes the input data does the selection of data specified
|
||||
* by the hash control block.
|
||||
* The step varialbe in the work sturcture determines which 1/step bytes
|
||||
* are used,
|
||||
*
|
||||
*/
|
||||
static int
|
||||
do_hash(dst_work *work, prand_hash *hash, const u_char *input, int size)
|
||||
{
|
||||
const u_char *tmp = input;
|
||||
u_char *save = NULL, *tp;
|
||||
int i, cnt = size, n, needed, avail, dig, tmp_size = 0;
|
||||
|
||||
if (cnt <= 0 || input == NULL)
|
||||
return (0);
|
||||
|
||||
if (hash->step > 1) { /* if using subset of input data */
|
||||
tmp_size = size / hash->step + 2;
|
||||
tmp = tp = save = malloc(tmp_size);
|
||||
for (cnt = 0, i = hash->curr; i < size; i += hash->step, cnt++)
|
||||
*(tp++) = input[i];
|
||||
/* calcutate the starting point in the next input set */
|
||||
hash->curr = (hash->step - (i - size)) % hash->step;
|
||||
}
|
||||
/* digest the data in block sizes */
|
||||
for (n = 0; n < cnt; n += needed) {
|
||||
avail = (cnt - n);
|
||||
needed = hash->block - hash->digested;
|
||||
dig = (avail < needed) ? avail : needed;
|
||||
dst_sign_data(SIG_MODE_UPDATE, hash->key, &hash->ctx,
|
||||
&tmp[n], dig, NULL, 0);
|
||||
hash->digested += dig;
|
||||
if (hash->digested >= hash->block)
|
||||
force_hash(work, hash);
|
||||
if (work->needed < work->filled) {
|
||||
if (tmp_size > 0)
|
||||
SAFE_FREE2(save, tmp_size);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
if (tmp_size > 0)
|
||||
SAFE_FREE2(save, tmp_size);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from INPUT for length SIZE into the work-block TMP.
|
||||
* If we fill the work-block, digest it; then,
|
||||
* if work-block needs more data, keep filling with the rest of the input.
|
||||
*/
|
||||
static int
|
||||
my_digest(dst_work *work, const u_char *input, int size)
|
||||
{
|
||||
|
||||
int i, full = 0;
|
||||
static unsigned counter;
|
||||
|
||||
counter += size;
|
||||
/* first do each one of the hashes */
|
||||
for (i = 0; i < DST_NUM_HASHES && full == 0; i++)
|
||||
full = do_hash(work, work->hash[i], input, size) +
|
||||
do_hash(work, work->hash[i], (u_char *) &counter,
|
||||
sizeof(counter));
|
||||
/*
|
||||
* if enough data has be generated do final operation on all hashes
|
||||
* that have enough date for that
|
||||
*/
|
||||
for (i = 0; full && (i < DST_NUM_HASHES); i++)
|
||||
force_hash(work, work->hash[i]);
|
||||
|
||||
return (full);
|
||||
}
|
||||
|
||||
/*
|
||||
* this function gets some semi random data and sets that as an HMAC key
|
||||
* If we get a valid key this function returns that key initalized
|
||||
* otherwise it returns NULL;
|
||||
*/
|
||||
static prand_hash *
|
||||
get_hmac_key(int step, int block)
|
||||
{
|
||||
|
||||
u_char *buff;
|
||||
int temp = 0, n = 0, size = 70;
|
||||
DST_KEY *new_key = NULL;
|
||||
prand_hash *new = NULL;
|
||||
|
||||
/* use key that is larger than digest algorithms (64) for key size */
|
||||
buff = malloc(size);
|
||||
if (buff == NULL)
|
||||
return (NULL);
|
||||
/* do not memset the allocated memory to get random bytes there */
|
||||
/* time of day is somewhat random expecialy in the last bytes */
|
||||
gettimeofday((struct timeval *) &buff[n], NULL);
|
||||
n += sizeof(struct timeval);
|
||||
|
||||
/* get some semi random stuff in here stir it with micro seconds */
|
||||
if (n < size) {
|
||||
temp = dst_s_quick_random((int) buff[n - 1]);
|
||||
memcpy(&buff[n], &temp, sizeof(temp));
|
||||
n += sizeof(temp);
|
||||
}
|
||||
/* get the pid of this process and its parent */
|
||||
if (n < size) {
|
||||
temp = (int) getpid();
|
||||
memcpy(&buff[n], &temp, sizeof(temp));
|
||||
n += sizeof(temp);
|
||||
}
|
||||
if (n < size) {
|
||||
temp = (int) getppid();
|
||||
memcpy(&buff[n], &temp, sizeof(temp));
|
||||
n += sizeof(temp);
|
||||
}
|
||||
/* get the user ID */
|
||||
if (n < size) {
|
||||
temp = (int) getuid();
|
||||
memcpy(&buff[n], &temp, sizeof(temp));
|
||||
n += sizeof(temp);
|
||||
}
|
||||
#ifndef GET_HOST_ID_MISSING
|
||||
if (n < size) {
|
||||
temp = (int) gethostid();
|
||||
memcpy(&buff[n], &temp, sizeof(temp));
|
||||
n += sizeof(temp);
|
||||
}
|
||||
#endif
|
||||
/* get some more random data */
|
||||
if (n < size) {
|
||||
temp = dst_s_quick_random((int) buff[n - 1]);
|
||||
memcpy(&buff[n], &temp, sizeof(temp));
|
||||
n += sizeof(temp);
|
||||
}
|
||||
/* covert this into a HMAC key */
|
||||
new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size);
|
||||
SAFE_FREE(buff);
|
||||
|
||||
/* get the control structure */
|
||||
if ((new = malloc(sizeof(prand_hash))) == NULL)
|
||||
return (NULL);
|
||||
new->digested = new->curr = 0;
|
||||
new->step = step;
|
||||
new->block = block;
|
||||
new->key = new_key;
|
||||
if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0))
|
||||
return (NULL);
|
||||
|
||||
return (new);
|
||||
}
|
||||
|
||||
/*
|
||||
* own_random()
|
||||
* This function goes out and from various sources tries to generate enough
|
||||
* semi random data that a hash function can generate a random data.
|
||||
* This function will iterate between the two main random source sources,
|
||||
* information from programs and directores in random order.
|
||||
* This function return the number of bytes added to the random output buffer.
|
||||
*/
|
||||
static int
|
||||
own_random(dst_work *work)
|
||||
{
|
||||
int dir = 0, b;
|
||||
int bytes, n, cmd = 0, dig = 0;
|
||||
int start =0;
|
||||
/*
|
||||
* now get the initial seed to put into the quick random function from
|
||||
* the address of the work structure
|
||||
*/
|
||||
bytes = (int) getpid();
|
||||
/*
|
||||
* proceed while needed
|
||||
*/
|
||||
while (work->filled < work->needed) {
|
||||
EREPORT(("own_random r %08x b %6d t %6d f %6d\n",
|
||||
ran_val, bytes, work->in_temp, work->filled));
|
||||
/* pick a random number in the range of 0..7 based on that random number
|
||||
* perform some operations that yield random data
|
||||
*/
|
||||
start = work->filled;
|
||||
n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07;
|
||||
switch (n) {
|
||||
case 0:
|
||||
case 3:
|
||||
if (sizeof(cmds) > 2 *sizeof(*cmds)) {
|
||||
b = unix_cmd(work);
|
||||
cmd += b;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 7:
|
||||
if (sizeof(dirs) > 2 *sizeof(*dirs)) {
|
||||
b = do_ls(work);
|
||||
dir += b;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 5:
|
||||
/* retry getting data from /dev/random */
|
||||
b = get_dev_random(&work->output[work->filled],
|
||||
work->needed - work->filled);
|
||||
if (b > 0)
|
||||
work->filled += b;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (sizeof(files) > 2 * sizeof(*files)) {
|
||||
b = digest_file(work);
|
||||
dig += b;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
default: /* to make sure we make some progress */
|
||||
work->output[work->filled++] = 0xff &
|
||||
dst_s_quick_random(bytes);
|
||||
b = 1;
|
||||
break;
|
||||
}
|
||||
if (b > 0)
|
||||
bytes += b;
|
||||
}
|
||||
return (work->filled);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_s_random() This function will return the requested number of bytes
|
||||
* of randomness to the caller it will use the best available sources of
|
||||
* randomness.
|
||||
* The current order is to use /dev/random, precalculated randomness, and
|
||||
* finaly use some system calls and programs to generate semi random data that
|
||||
* is then digested to generate randomness.
|
||||
* This function is thread safe as each thread uses its own context, but
|
||||
* concurrent treads will affect each other as they update shared state
|
||||
* information.
|
||||
* It is strongly recommended that this function be called requesting a size
|
||||
* that is not a multiple of the output of the hash function used.
|
||||
*
|
||||
* If /dev/random is not available this function is not suitable to generate
|
||||
* large ammounts of data, rather it is suitable to seed a pseudo-random
|
||||
* generator
|
||||
* Returns the number of bytes put in the output buffer
|
||||
*/
|
||||
int
|
||||
dst_s_random(u_char *output, int size)
|
||||
{
|
||||
int n = 0, s, i;
|
||||
static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES];
|
||||
static int unused = 0;
|
||||
|
||||
if (size <= 0 || output == NULL)
|
||||
return (0);
|
||||
|
||||
if (size >= 2048)
|
||||
return (-1);
|
||||
/*
|
||||
* Read from /dev/random
|
||||
*/
|
||||
n = get_dev_random(output, size);
|
||||
/*
|
||||
* If old data is available and needed use it
|
||||
*/
|
||||
if (n < size && unused > 0) {
|
||||
int need = size - n;
|
||||
if (unused <= need) {
|
||||
memcpy(output, old_unused, unused);
|
||||
n += unused;
|
||||
unused = 0;
|
||||
} else {
|
||||
memcpy(output, old_unused, need);
|
||||
n += need;
|
||||
unused -= need;
|
||||
memcpy(old_unused, &old_unused[need], unused);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we need more use the simulated randomness here.
|
||||
*/
|
||||
if (n < size) {
|
||||
dst_work *my_work = (dst_work *) malloc(sizeof(dst_work));
|
||||
if (my_work == NULL)
|
||||
return (n);
|
||||
my_work->needed = size - n;
|
||||
my_work->filled = 0;
|
||||
my_work->output = (u_char *) malloc(my_work->needed +
|
||||
DST_HASH_SIZE *
|
||||
DST_NUM_HASHES);
|
||||
my_work->file_digest = NULL;
|
||||
if (my_work->output == NULL)
|
||||
return (n);
|
||||
memset(my_work->output, 0x0, my_work->needed);
|
||||
/* allocate upto 4 different HMAC hash functions out of order */
|
||||
#if DST_NUM_HASHES >= 3
|
||||
my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2);
|
||||
#endif
|
||||
#if DST_NUM_HASHES >= 2
|
||||
my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6);
|
||||
#endif
|
||||
#if DST_NUM_HASHES >= 4
|
||||
my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4);
|
||||
#endif
|
||||
my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE);
|
||||
if (my_work->hash[0] == NULL) /* if failure bail out */
|
||||
return (n);
|
||||
s = own_random(my_work);
|
||||
/* if more generated than needed store it for future use */
|
||||
if (s >= my_work->needed) {
|
||||
EREPORT(("dst_s_random(): More than needed %d >= %d\n",
|
||||
s, my_work->needed));
|
||||
memcpy(&output[n], my_work->output, my_work->needed);
|
||||
n += my_work->needed;
|
||||
/* saving unused data for next time */
|
||||
unused = s - my_work->needed;
|
||||
memcpy(old_unused, &my_work->output[my_work->needed],
|
||||
unused);
|
||||
} else {
|
||||
/* XXXX This should not happen */
|
||||
EREPORT(("Not enough %d >= %d\n", s, my_work->needed));
|
||||
memcpy(&output[n], my_work->output, s);
|
||||
n += my_work->needed;
|
||||
}
|
||||
|
||||
/* delete the allocated work area */
|
||||
for (i = 0; i < DST_NUM_HASHES; i++) {
|
||||
dst_free_key(my_work->hash[i]->key);
|
||||
SAFE_FREE(my_work->hash[i]);
|
||||
}
|
||||
SAFE_FREE(my_work->output);
|
||||
SAFE_FREE(my_work);
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* A random number generator that is fast and strong
|
||||
* this random number generator is based on HASHing data,
|
||||
* the input to the digest function is a collection of <NUMBER_OF_COUNTERS>
|
||||
* counters that is incremented between digest operations
|
||||
* each increment operation amortizes to 2 bits changed in that value
|
||||
* for 5 counters thus the input will amortize to have 10 bits changed
|
||||
* The counters are initaly set using the strong random function above
|
||||
* the HMAC key is selected by the same methold as the HMAC keys for the
|
||||
* strong random function.
|
||||
* Each set of counters is used for 2^25 operations
|
||||
*
|
||||
* returns the number of bytes written to the output buffer
|
||||
* or negative number in case of error
|
||||
*/
|
||||
int
|
||||
dst_s_semi_random(u_char *output, int size)
|
||||
{
|
||||
static u_int32_t counter[DST_NUMBER_OF_COUNTERS];
|
||||
static u_char semi_old[DST_HASH_SIZE];
|
||||
static int semi_loc = 0, cnt = 0, hb_size = 0;
|
||||
static DST_KEY *my_key = NULL;
|
||||
prand_hash *hash;
|
||||
int out = 0, i, n;
|
||||
|
||||
if (output == NULL || size <= 0)
|
||||
return (-2);
|
||||
|
||||
/* check if we need a new key */
|
||||
if (my_key == NULL || cnt > (1 << 25)) { /* get HMAC KEY */
|
||||
if (my_key)
|
||||
my_key->dk_func->destroy(my_key);
|
||||
if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL)
|
||||
return (0);
|
||||
my_key = hash->key;
|
||||
/* check if the key works stir the new key using some old random data */
|
||||
hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
|
||||
(u_char *) counter, sizeof(counter),
|
||||
semi_old, sizeof(semi_old));
|
||||
if (hb_size <= 0) {
|
||||
EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n",
|
||||
my_key->dk_alg, hb_size));
|
||||
return (-1);
|
||||
}
|
||||
/* new set the counters to random values */
|
||||
dst_s_random((u_char *) counter, sizeof(counter));
|
||||
cnt = 0;
|
||||
}
|
||||
/* if old data around use it first */
|
||||
if (semi_loc < hb_size) {
|
||||
if (size <= hb_size - semi_loc) { /* need less */
|
||||
memcpy(output, &semi_old[semi_loc], size);
|
||||
semi_loc += size;
|
||||
return (size); /* DONE */
|
||||
} else {
|
||||
out = hb_size - semi_loc;
|
||||
memcpy(output, &semi_old[semi_loc], out);
|
||||
semi_loc += out;
|
||||
}
|
||||
}
|
||||
/* generate more randome stuff */
|
||||
while (out < size) {
|
||||
/*
|
||||
* modify at least one bit by incrementing at least one counter
|
||||
* based on the last bit of the last counter updated update
|
||||
* the next one.
|
||||
* minimaly this operation will modify at least 1 bit,
|
||||
* amortized 2 bits
|
||||
*/
|
||||
for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++)
|
||||
i = (int) counter[n]++;
|
||||
|
||||
i = dst_sign_data(SIG_MODE_ALL, my_key, NULL,
|
||||
(u_char *) counter, hb_size,
|
||||
semi_old, sizeof(semi_old));
|
||||
#ifdef REPORT_ERRORS
|
||||
if (i != hb_size)
|
||||
EREPORT(("HMAC SIGNATURE FAILURE %d\n", i));
|
||||
#endif
|
||||
cnt++;
|
||||
if (size - out < i) /* Not all data is needed */
|
||||
semi_loc = i = size - out;
|
||||
memcpy(&output[out], semi_old, i);
|
||||
out += i;
|
||||
}
|
||||
return (out);
|
||||
}
|
||||
@@ -1,767 +0,0 @@
|
||||
#ifdef RSAREF
|
||||
static const char rcsid[] = "$Header: /u0/home/explorer/proj/ISC/git-conversion/cvsroot/bind9/lib/bind/dst/Attic/rsaref_link.c,v 1.1 2001/03/29 06:31:33 marka Exp $";
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains two components
|
||||
* 1. Interface to the rsaref library to allow compilation when RSAREF is
|
||||
* not available all calls to RSAREF are contained inside this file.
|
||||
* 2. The glue to connvert RSA{REF} KEYS to and from external formats
|
||||
*/
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
|
||||
# ifdef __STDC__
|
||||
# define PROTOTYPES 1
|
||||
# else
|
||||
# define PROTOTYPES 0
|
||||
# endif
|
||||
|
||||
# include <global.h>
|
||||
# include <rsaref.h>
|
||||
|
||||
#include "port_after.h"
|
||||
|
||||
|
||||
typedef struct rsakey {
|
||||
char *rk_signer;
|
||||
R_RSA_PRIVATE_KEY *rk_Private_Key;
|
||||
R_RSA_PUBLIC_KEY *rk_Public_Key;
|
||||
} RSA_Key;
|
||||
|
||||
|
||||
static int dst_rsaref_sign(const int mode, DST_KEY *key, void **context,
|
||||
const u_char *data, const int len,
|
||||
u_char *signature, const int sig_len);
|
||||
static int dst_rsaref_verify(const int mode, DST_KEY *key, void **context,
|
||||
const u_char *data, const int len,
|
||||
const u_char *signature, const int sig_len);
|
||||
|
||||
static int dst_rsaref_to_dns_key(const DST_KEY *public, u_char *out_str,
|
||||
const int out_len);
|
||||
static int dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key,
|
||||
const int len);
|
||||
|
||||
static int dst_rsaref_key_to_file_format(const DST_KEY *dkey,
|
||||
u_char *buff,
|
||||
const int buff_len);
|
||||
static int dst_rsaref_key_from_file_format(DST_KEY *dkey,
|
||||
const u_char *buff,
|
||||
const int buff_len);
|
||||
|
||||
static int dst_rsaref_compare_keys(const DST_KEY *rkey1,
|
||||
const DST_KEY *rkey2);
|
||||
static void *dst_rsaref_free_key_structure(void *d_key);
|
||||
|
||||
static int dst_rsaref_generate_keypair(DST_KEY *key, const int exp);
|
||||
|
||||
static void dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct);
|
||||
|
||||
/*
|
||||
* dst_rsaref_init() Function to answer set up function pointers for RSAREF
|
||||
* related functions
|
||||
*/
|
||||
int
|
||||
dst_rsaref_init()
|
||||
{
|
||||
if (dst_t_func[KEY_RSA] != NULL)
|
||||
return (1);
|
||||
dst_t_func[KEY_RSA] = malloc(sizeof(struct dst_func));
|
||||
if (dst_t_func[KEY_RSA] == NULL)
|
||||
return (0);
|
||||
memset(dst_t_func[KEY_RSA], 0, sizeof(struct dst_func));
|
||||
dst_t_func[KEY_RSA]->sign = dst_rsaref_sign;
|
||||
dst_t_func[KEY_RSA]->verify = dst_rsaref_verify;
|
||||
dst_t_func[KEY_RSA]->compare = dst_rsaref_compare_keys;
|
||||
dst_t_func[KEY_RSA]->generate = dst_rsaref_generate_keypair;
|
||||
dst_t_func[KEY_RSA]->destroy = dst_rsaref_free_key_structure;
|
||||
dst_t_func[KEY_RSA]->to_dns_key = dst_rsaref_to_dns_key;
|
||||
dst_t_func[KEY_RSA]->from_dns_key = dst_rsaref_from_dns_key;
|
||||
dst_t_func[KEY_RSA]->to_file_fmt = dst_rsaref_key_to_file_format;
|
||||
dst_t_func[KEY_RSA]->from_file_fmt = dst_rsaref_key_from_file_format;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_rsa_sign
|
||||
* Call RSAREF 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 SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* key pointer to a RSA key structure that points to public key
|
||||
* and context to use.
|
||||
* data data to be signed.
|
||||
* len length in bytes of data.
|
||||
* signature location to store signature.
|
||||
* sig_len size of the signature storage area
|
||||
* returns
|
||||
* N Success on SIG_MODE_FINAL = returns signature length in bytes
|
||||
* 0 Success on SIG_MODE_INIT and UPDATE
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
|
||||
static int
|
||||
dst_rsaref_sign(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
u_char *signature, const int sig_len)
|
||||
{
|
||||
int sign_len = 0;
|
||||
R_SIGNATURE_CTX *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = malloc(sizeof(*ctx));
|
||||
else if (context)
|
||||
ctx = (R_SIGNATURE_CTX *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if ((mode & SIG_MODE_INIT) && R_SignInit(ctx, DA_MD5))
|
||||
return (SIGN_INIT_FAILURE);
|
||||
|
||||
/* equivalent of SIG_MODE_UPDATE */
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0) &&
|
||||
R_SignUpdate(ctx, (u_char *) data, len))
|
||||
return (SIGN_UPDATE_FAILURE);
|
||||
|
||||
if (mode & SIG_MODE_FINAL) {
|
||||
RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct;
|
||||
if (signature == NULL ||
|
||||
sig_len < (int)(key->rk_Public_Key->bits + 7) / 8)
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
if(key == NULL || key->rk_Private_Key == NULL)
|
||||
return (-1);
|
||||
if (R_SignFinal(ctx, signature, &sign_len,
|
||||
key->rk_Private_Key))
|
||||
return (SIGN_FINAL_FAILURE);
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
return (sign_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_verify()
|
||||
* Calls RSAREF 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 SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL.
|
||||
* key pointer to a RSA key structure that points to public key
|
||||
* and context to use.
|
||||
* data data signed.
|
||||
* len length in bytes of data.
|
||||
* signature signature.
|
||||
* sig_len length in bytes of signature.
|
||||
* returns
|
||||
* 0 Success
|
||||
* <0 Failure
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_rsaref_verify(const int mode, DST_KEY *dkey, void **context,
|
||||
const u_char *data, const int len,
|
||||
const u_char *signature, const int sig_len)
|
||||
{
|
||||
R_SIGNATURE_CTX *ctx = NULL;
|
||||
|
||||
if (mode & SIG_MODE_INIT)
|
||||
ctx = malloc(sizeof(*ctx));
|
||||
else if (context)
|
||||
ctx = (R_SIGNATURE_CTX *) *context;
|
||||
if (ctx == NULL)
|
||||
return (-1);
|
||||
|
||||
if ((mode & SIG_MODE_INIT) && R_VerifyInit(ctx, DA_MD5))
|
||||
return (VERIFY_INIT_FAILURE);
|
||||
|
||||
if ((mode & SIG_MODE_UPDATE) && (data && len > 0) &&
|
||||
R_VerifyUpdate(ctx, (u_char *) data, len))
|
||||
return (VERIFY_UPDATE_FAILURE);
|
||||
|
||||
if ((mode & SIG_MODE_FINAL)) {
|
||||
RSA_Key *key = (RSA_Key *) dkey->dk_KEY_struct;
|
||||
|
||||
if (key == NULL || key->rk_Public_Key == NULL)
|
||||
return (-1);
|
||||
if (signature == NULL || sig_len <= 0)
|
||||
return (VERIFY_FINAL_FAILURE);
|
||||
if (R_VerifyFinal(ctx, (u_char *) signature, sig_len,
|
||||
key->rk_Public_Key))
|
||||
return (VERIFY_FINAL_FAILURE);
|
||||
}
|
||||
else {
|
||||
if (context == NULL)
|
||||
return (-1);
|
||||
*context = (void *) ctx;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_to_dns_key
|
||||
* Converts key in RSAREF to DNS distribution format
|
||||
* This function gets in a pointer to the public key and a work area
|
||||
* to write the key into.
|
||||
* Parameters
|
||||
* public KEY structure
|
||||
* out_str buffer to write encoded key into
|
||||
* out_len size of out_str
|
||||
* Return
|
||||
* N >= 0 length of encoded key
|
||||
* n < 0 error
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_rsaref_to_dns_key(const DST_KEY *in_key, u_char *out_str,
|
||||
const int out_len)
|
||||
{
|
||||
int n, loc;
|
||||
R_RSA_PUBLIC_KEY *public;
|
||||
u_char *op = (u_char *) out_str;
|
||||
|
||||
if (in_key == NULL || in_key->dk_KEY_struct == NULL ||
|
||||
out_len <= 0 || out_str == NULL)
|
||||
return (-1);
|
||||
public = (R_RSA_PUBLIC_KEY *)
|
||||
((RSA_Key *) in_key->dk_KEY_struct)->rk_Public_Key;
|
||||
if (public == NULL)
|
||||
return (-1);
|
||||
|
||||
memset(op, 0, out_len);
|
||||
|
||||
/* find first non zero */
|
||||
for (n = 0; public->exponent[n] == 0x0; n++) ;
|
||||
|
||||
n = (MAX_RSA_MODULUS_LEN - n); /* find lenght of exponent */
|
||||
*op++ = (u_int8_t) n;
|
||||
|
||||
if (n > (out_len - (op-out_str)))
|
||||
return (-1);
|
||||
memcpy(op, &public->exponent[MAX_RSA_MODULUS_LEN - n], n);
|
||||
op += n;
|
||||
n++; /* include the lenght field in this count */
|
||||
|
||||
/* find first non zero */
|
||||
for (loc = 0; public->modulus[loc] == 0x0; loc++) ;
|
||||
|
||||
/*copy exponent */
|
||||
if ((MAX_RSA_MODULUS_LEN - loc) > (out_len - (op-out_str)))
|
||||
return (-1);
|
||||
memcpy(op, &public->modulus[loc], MAX_RSA_MODULUS_LEN - loc);
|
||||
n += (MAX_RSA_MODULUS_LEN - loc);
|
||||
return (n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_from_dns_key
|
||||
* Converts from a DNS KEY RR format to an RSA KEY.
|
||||
* Parameters
|
||||
* len Length in bytes of DNS key
|
||||
* key DNS key
|
||||
* name Key name
|
||||
* s_key DST structure that will point to the RSA key this routine
|
||||
* will build.
|
||||
* Return
|
||||
* -1 The input key has fields that are larger than this package supports
|
||||
* 0 The input key, s_key or name was null.
|
||||
* 1 Success
|
||||
*/
|
||||
static int
|
||||
dst_rsaref_from_dns_key(DST_KEY *s_key, const u_char *key, const int len)
|
||||
{
|
||||
int bytes;
|
||||
u_char *key_ptr;
|
||||
RSA_Key *r_key;
|
||||
|
||||
if (key == NULL || s_key == NULL || len < 0)
|
||||
return (0);
|
||||
|
||||
if (s_key->dk_KEY_struct) { /* do not reuse */
|
||||
dst_rsaref_free_key_structure(s_key->dk_KEY_struct);
|
||||
s_key->dk_KEY_struct = NULL;
|
||||
}
|
||||
if (len == 0) /* null key no conversion needed */
|
||||
return (1);
|
||||
|
||||
if ((r_key = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) {
|
||||
EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 1\n"));
|
||||
return (0);
|
||||
}
|
||||
memset(r_key, 0, sizeof(RSA_Key));
|
||||
s_key->dk_KEY_struct = (void *) r_key;
|
||||
r_key->rk_signer = strdup(s_key->dk_key_name);
|
||||
r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *)
|
||||
malloc(sizeof(R_RSA_PUBLIC_KEY));
|
||||
if (r_key->rk_Public_Key == NULL) {
|
||||
EREPORT(("dst_rsaref_from_dns_key(): Memory allocation error 3\n"));
|
||||
return (0);
|
||||
}
|
||||
memset(r_key->rk_Public_Key, 0, sizeof(R_RSA_PUBLIC_KEY));
|
||||
key_ptr = (u_char *) key;
|
||||
bytes = (int) *key_ptr++; /* length of exponent in bytes */
|
||||
if (bytes == 0) { /* special case for long exponents */
|
||||
bytes = (int) dst_s_get_int16(key_ptr);
|
||||
key_ptr += sizeof(u_int16_t);
|
||||
}
|
||||
if (bytes > MAX_RSA_MODULUS_LEN) {
|
||||
dst_rsaref_free_key_structure(r_key);
|
||||
return (-1);
|
||||
}
|
||||
memcpy(&r_key->rk_Public_Key->exponent[MAX_RSA_MODULUS_LEN - bytes],
|
||||
key_ptr, bytes);
|
||||
|
||||
key_ptr += bytes; /* beginning of modulus */
|
||||
bytes = len - bytes - 1; /* length of modulus */
|
||||
if (bytes > MAX_RSA_MODULUS_LEN) {
|
||||
dst_rsaref_free_key_structure(r_key);
|
||||
return (-1);
|
||||
}
|
||||
memcpy(&r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - bytes],
|
||||
key_ptr, bytes);
|
||||
r_key->rk_Public_Key->bits = bytes * 8;
|
||||
s_key->dk_id = (u_int16_t) dst_s_get_int16((u_char *)
|
||||
&r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]);
|
||||
s_key->dk_key_size = r_key->rk_Public_Key->bits;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_key_to_file_format
|
||||
* Encodes an RSA Key into the portable file format.
|
||||
* Parameters
|
||||
* rkey RSA KEY structure
|
||||
* buff output buffer
|
||||
* buff_len size of output buffer
|
||||
* Return
|
||||
* 0 Failure - null input rkey
|
||||
* -1 Failure - not enough space in output area
|
||||
* N Success - Length of data returned in buff
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_rsaref_key_to_file_format(const DST_KEY *in_key, u_char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
u_char *bp;
|
||||
int len, b_len;
|
||||
R_RSA_PRIVATE_KEY *rkey;
|
||||
|
||||
if (in_key == NULL || in_key->dk_KEY_struct == NULL)
|
||||
return (-1);
|
||||
rkey = (R_RSA_PRIVATE_KEY *)
|
||||
((RSA_Key *) in_key->dk_KEY_struct)->rk_Private_Key;
|
||||
if (rkey == NULL) /* no output */
|
||||
return (0);
|
||||
if (buff == NULL || buff_len <= (int) strlen(key_file_fmt_str))
|
||||
return (-1); /* no OR not enough space in output area */
|
||||
|
||||
memset(buff, 0, buff_len); /* just in case */
|
||||
/* write file header */
|
||||
sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_RSA, "RSA");
|
||||
|
||||
bp = (char *) strchr(buff, '\0');
|
||||
b_len = buff_len - (bp - buff);
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Modulus: ",
|
||||
rkey->modulus,
|
||||
MAX_RSA_MODULUS_LEN)) <= 0)
|
||||
return (-1);
|
||||
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PublicExponent: ",
|
||||
rkey->publicExponent,
|
||||
MAX_RSA_MODULUS_LEN)) <= 0)
|
||||
return (-2);
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "PrivateExponent: ",
|
||||
rkey->exponent,
|
||||
MAX_RSA_MODULUS_LEN)) <= 0)
|
||||
return (-3);
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime1: ",
|
||||
rkey->prime[0],
|
||||
MAX_RSA_PRIME_LEN)) < 0)
|
||||
return (-4);
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Prime2: ",
|
||||
rkey->prime[1],
|
||||
MAX_RSA_PRIME_LEN)) < 0)
|
||||
return (-5);
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent1: ",
|
||||
rkey->primeExponent[0],
|
||||
MAX_RSA_PRIME_LEN)) < 0)
|
||||
return (-6);
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Exponent2: ",
|
||||
rkey->primeExponent[1],
|
||||
MAX_RSA_PRIME_LEN)) < 0)
|
||||
return (-7);
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
if ((len = dst_s_conv_bignum_u8_to_b64(bp, b_len, "Coefficient: ",
|
||||
rkey->coefficient,
|
||||
MAX_RSA_PRIME_LEN)) < 0)
|
||||
return (-8);
|
||||
bp += len;
|
||||
b_len -= len;
|
||||
return (buff_len - b_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_key_from_file_format
|
||||
* Converts contents of a private key file into a private RSA key.
|
||||
* Parameters
|
||||
* r_key structure to put key into
|
||||
* buff buffer containing the encoded key
|
||||
* buff_len the length of the buffer
|
||||
* Return
|
||||
* n >= 0 Foot print of the key converted
|
||||
* n < 0 Error in conversion
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_rsaref_key_from_file_format(DST_KEY *d_key, const u_char *buff,
|
||||
const int buff_len)
|
||||
{
|
||||
const char *p = (char *) buff;
|
||||
R_RSA_PRIVATE_KEY key;
|
||||
int foot = -1;
|
||||
RSA_Key *r_key;
|
||||
|
||||
if (d_key == NULL || buff == NULL || buff_len < 0)
|
||||
return (-1);
|
||||
|
||||
memset(&key, 0, sizeof(key));
|
||||
|
||||
if (!dst_s_verify_str(&p, "Modulus: "))
|
||||
return (-3);
|
||||
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p, key.modulus, MAX_RSA_MODULUS_LEN))
|
||||
return (-4);
|
||||
|
||||
key.bits = dst_s_calculate_bits(key.modulus, MAX_RSA_MODULUS_BITS);
|
||||
|
||||
while (*++p && p < (char *) &buff[buff_len]) {
|
||||
if (dst_s_verify_str(&p, "PublicExponent: ")) {
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p,
|
||||
key.publicExponent,
|
||||
MAX_RSA_MODULUS_LEN))
|
||||
return (-5);
|
||||
} else if (dst_s_verify_str(&p, "PrivateExponent: ")) {
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p, key.exponent,
|
||||
MAX_RSA_MODULUS_LEN))
|
||||
return (-6);
|
||||
} else if (dst_s_verify_str(&p, "Prime1: ")) {
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[0],
|
||||
MAX_RSA_PRIME_LEN))
|
||||
return (-7);
|
||||
} else if (dst_s_verify_str(&p, "Prime2: ")) {
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p, key.prime[1],
|
||||
MAX_RSA_PRIME_LEN))
|
||||
return (-8);
|
||||
} else if (dst_s_verify_str(&p, "Exponent1: ")) {
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p,
|
||||
key.primeExponent[0],
|
||||
MAX_RSA_PRIME_LEN))
|
||||
return (-9);
|
||||
} else if (dst_s_verify_str(&p, "Exponent2: ")) {
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p,
|
||||
key.primeExponent[1],
|
||||
MAX_RSA_PRIME_LEN))
|
||||
return (-10);
|
||||
} else if (dst_s_verify_str(&p, "Coefficient: ")) {
|
||||
if (!dst_s_conv_bignum_b64_to_u8(&p, key.coefficient,
|
||||
MAX_RSA_PRIME_LEN))
|
||||
return (-11);
|
||||
} else {
|
||||
EREPORT(("dst_rsaref_key_from_file_format: Bad keyword %s\n", p));
|
||||
return (-12);
|
||||
}
|
||||
} /* while p */
|
||||
|
||||
r_key = (RSA_Key *) malloc(sizeof(RSA_Key));
|
||||
if (r_key == NULL) {
|
||||
return (-2);
|
||||
}
|
||||
memset(r_key, 0, sizeof(*r_key));
|
||||
|
||||
r_key->rk_Private_Key =
|
||||
(R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY));
|
||||
if (r_key->rk_Private_Key == NULL) {
|
||||
EREPORT(("dst_rsaref_key_from_file_format: Memory allocation error\n"));
|
||||
return (-13);
|
||||
}
|
||||
r_key->rk_Public_Key = (R_RSA_PUBLIC_KEY *) r_key->rk_Private_Key;
|
||||
memcpy(r_key->rk_Private_Key, &key, sizeof(R_RSA_PRIVATE_KEY));
|
||||
|
||||
r_key->rk_signer = strdup(d_key->dk_key_name);
|
||||
d_key->dk_KEY_struct = (void *) r_key;
|
||||
d_key->dk_key_size = r_key->rk_Private_Key->bits;
|
||||
d_key->dk_id = (u_int16_t) dst_s_get_int16((u_char *)
|
||||
&r_key->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]);
|
||||
foot = (int) d_key->dk_id;
|
||||
return (foot);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_compare_keys
|
||||
* Compare two keys for equality.
|
||||
* Return
|
||||
* 0 The keys are equal
|
||||
* NON-ZERO The keys are not equal
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_rsaref_compare_keys(const DST_KEY *dkey1, const DST_KEY *dkey2)
|
||||
{
|
||||
RSA_Key *rkey1 = (RSA_Key *) dkey1->dk_KEY_struct;
|
||||
RSA_Key *rkey2 = (RSA_Key *) dkey2->dk_KEY_struct;
|
||||
|
||||
if (rkey1 == NULL && rkey2 == NULL)
|
||||
return (0); /* same */
|
||||
else if (rkey1 == NULL)
|
||||
return (1);
|
||||
else if (rkey2 == NULL)
|
||||
return (2);
|
||||
return (memcmp(rkey1->rk_Public_Key, rkey2->rk_Public_Key,
|
||||
sizeof(R_RSA_PUBLIC_KEY)));
|
||||
}
|
||||
|
||||
/*
|
||||
* dst_rsaref_generate_keypair
|
||||
* Generates unique keys that are hard to predict.
|
||||
* Parameters
|
||||
* key generic Key structure
|
||||
* exp the public exponent
|
||||
* Return
|
||||
* 0 Failure
|
||||
* 1 Success
|
||||
*/
|
||||
|
||||
static int
|
||||
dst_rsaref_generate_keypair(DST_KEY *key, const int exp)
|
||||
{
|
||||
R_RSA_PUBLIC_KEY *public;
|
||||
R_RSA_PRIVATE_KEY *private;
|
||||
R_RSA_PROTO_KEY proto;
|
||||
R_RANDOM_STRUCT randomStruct;
|
||||
RSA_Key *rsa;
|
||||
int status;
|
||||
|
||||
if (key == NULL || key->dk_alg != KEY_RSA)
|
||||
return (0);
|
||||
if (key->dk_key_size < MIN_RSA_MODULUS_BITS ||
|
||||
key->dk_key_size > MAX_RSA_MODULUS_BITS) {
|
||||
EREPORT(("dst_rsaref_generate_keypair: Invalid key size\n"));
|
||||
return (0); /* these are the limits on key size in RSAREF */
|
||||
}
|
||||
/* allocate space */
|
||||
if ((public = (R_RSA_PUBLIC_KEY *) malloc(sizeof(R_RSA_PUBLIC_KEY)))
|
||||
== NULL) {
|
||||
EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 1\n"));
|
||||
return (0);
|
||||
}
|
||||
if ((private = (R_RSA_PRIVATE_KEY *) malloc(sizeof(R_RSA_PRIVATE_KEY)))
|
||||
== NULL) {
|
||||
EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 2\n"));
|
||||
return (0);
|
||||
}
|
||||
if ((rsa = (RSA_Key *) malloc(sizeof(RSA_Key))) == NULL) {
|
||||
EREPORT(("dst_rsaref_generate_keypair: Memory allocation error 3\n"));
|
||||
return (0);
|
||||
}
|
||||
memset(public, 0, sizeof(*public));
|
||||
memset(private, 0, sizeof(*private));
|
||||
|
||||
proto.bits = key->dk_key_size;
|
||||
proto.useFermat4 = exp ? 0x1 : 0x0; /* 1 for f4=65537, 0 for f0=3 */
|
||||
EREPORT(("\ndst_rsaref_generate_keypair: Generating KEY for %s Please wait\n",
|
||||
key->dk_key_name));
|
||||
|
||||
/* set up random seed */
|
||||
dst_rsaref_init_random_struct(&randomStruct);
|
||||
|
||||
/* generate keys */
|
||||
status = R_GeneratePEMKeys(public, private, &proto, &randomStruct);
|
||||
if (status) {
|
||||
EREPORT(("dst_rsaref_generate_keypair: No Key Pair generated %d\n",
|
||||
status));
|
||||
SAFE_FREE(public);
|
||||
SAFE_FREE(private);
|
||||
SAFE_FREE(rsa);
|
||||
return (0);
|
||||
}
|
||||
memset(rsa, 0, sizeof(*rsa));
|
||||
rsa->rk_signer = key->dk_key_name;
|
||||
rsa->rk_Private_Key = private;
|
||||
rsa->rk_Public_Key = public;
|
||||
key->dk_KEY_struct = (void *) rsa;
|
||||
|
||||
key->dk_id = (u_int16_t) dst_s_get_int16((u_char *)
|
||||
&rsa->rk_Public_Key->modulus[MAX_RSA_MODULUS_LEN - 3]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_free_key_structure
|
||||
* Frees all dynamicly allocated structures in r_key
|
||||
*/
|
||||
|
||||
static void *
|
||||
dst_rsaref_free_key_structure(void *v_key)
|
||||
{
|
||||
RSA_Key *r_key = (RSA_Key *) v_key;
|
||||
|
||||
if (r_key != NULL) {
|
||||
if ((void *) r_key->rk_Private_Key == (void *) r_key->rk_Public_Key)
|
||||
r_key->rk_Public_Key = NULL;
|
||||
SAFE_FREE(r_key->rk_Private_Key);
|
||||
SAFE_FREE(r_key->rk_Public_Key);
|
||||
SAFE_FREE(r_key->rk_signer);
|
||||
SAFE_FREE(r_key);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* dst_rsaref_init_random_struct
|
||||
* A random seed value is used in key generation.
|
||||
* This routine gets a bunch of system values to randomize the
|
||||
* randomstruct. A number of system calls are used to get somewhat
|
||||
* unpredicable values, then a special function dst_s_prandom() is called
|
||||
* that will do some magic depending on the system used.
|
||||
* If this function is executed on reasonably busy machine then the values
|
||||
* that prandom uses are hard to
|
||||
* 1. Predict
|
||||
* 2. Regenerate
|
||||
* 3. Hard to spy on as nothing is stored to disk and data is consumed
|
||||
* as fast as it is generated.
|
||||
*/
|
||||
|
||||
static void
|
||||
dst_rsaref_init_random_struct(R_RANDOM_STRUCT * randomstruct)
|
||||
{
|
||||
unsigned bytesNeeded;
|
||||
struct timeval tv;
|
||||
u_char *array;
|
||||
int n;
|
||||
|
||||
R_RandomInit(randomstruct);
|
||||
|
||||
/* The runtime of the script is unpredictable within some range
|
||||
* thus I'm getting the time of day again as this is an hard to guess
|
||||
* value and the number of characters of the output from the script is
|
||||
* hard to guess.
|
||||
* This must be the FIRST CALL
|
||||
*/
|
||||
gettimeofday(&tv, 0);
|
||||
R_RandomUpdate(randomstruct, (u_char *) &tv,
|
||||
sizeof(struct timeval));
|
||||
|
||||
/*
|
||||
* first find out how many bytes I need
|
||||
*/
|
||||
R_GetRandomBytesNeeded(&bytesNeeded, randomstruct);
|
||||
|
||||
/*
|
||||
* get a storage area for it addjust the area for the possible
|
||||
* side effects of digest functions writing out in blocks
|
||||
*/
|
||||
array = (u_char *) malloc(bytesNeeded);
|
||||
|
||||
/* extract the random data from /dev/random if present, generate
|
||||
* it if not present
|
||||
* first fill the buffer with semi random data
|
||||
* then fill as much as possible with good random data
|
||||
*/
|
||||
n = dst_random(DST_RAND_SEMI, bytesNeeded, array);
|
||||
n += dst_random(DST_RAND_KEY, bytesNeeded, array);
|
||||
if (n <= bytesNeeded) {
|
||||
SAFE_FREE(array);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* supply the random data (even if it is larger than requested) */
|
||||
R_RandomUpdate(randomstruct, array, bytesNeeded);
|
||||
|
||||
SAFE_FREE(array);
|
||||
|
||||
R_GetRandomBytesNeeded(&bytesNeeded, randomstruct);
|
||||
if (bytesNeeded) {
|
||||
EREPORT(("InitRandomStruct() didn't initialize enough randomness\n"));
|
||||
exit(33);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
#include "port_before.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dst_internal.h"
|
||||
#include "port_after.h"
|
||||
int /* rsaref is not available */
|
||||
dst_rsaref_init()
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
#endif /* RSAREF */
|
||||
Reference in New Issue
Block a user