freebsd-dev/contrib/bind/lib/dst/rsaref_link.c
Peter Wemm 6b6ac9438f Import bind v8.2.2.p5, minus the crypto for the time being. The bind
package does have BXA export approval, but the licensing strings on the
dnssafe code are a bit unpleasant.  The crypto is easy to restore and bind
will run without it - just without full dnssec support.

Obtained from:	The Internet Software Consortium (www.isc.org)
1999-11-30 02:43:11 +00:00

755 lines
21 KiB
C

#ifdef RSAREF
static const char rcsid[] = "$Header: /proj/cvs/isc/bind/src/lib/dst/rsaref_link.c,v 1.6 1999/10/13 16:39:24 vixie 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
int /* rsaref is not available */
dst_rsaref_init()
{
return (0);
}
#endif /* RSAREF */