/* R_RANDOM.C - random objects for RSAREF
*/
/* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data
Security, Inc. All rights reserved.
*/
#include "global.h"
#include "rsaref.h"
#include "r_random.h"
#include "md5.h"
#define RANDOM_BYTES_NEEDED 256
int R_RandomInit (randomStruct)
R_RANDOM_STRUCT *randomStruct; /* new random structure */
{
randomStruct->bytesNeeded = RANDOM_BYTES_NEEDED;
R_memset ((POINTER)randomStruct->state, 0, sizeof (randomStruct->state));
randomStruct->outputAvailable = 0;
return (0);
}
int R_RandomUpdate (randomStruct, block, blockLen)
R_RANDOM_STRUCT *randomStruct; /* random structure */
unsigned char *block; /* block of values to mix in */
unsigned int blockLen; /* length of block */
{
MD5_CTX context;
unsigned char digest[16];
unsigned int i, x;
MD5Init (&context);
MD5Update (&context, block, blockLen);
MD5Final (digest, &context);
/* add digest to state */
x = 0;
for (i = 0; i < 16; i++) {
x += randomStruct->state[15-i] + digest[15-i];
randomStruct->state[15-i] = (unsigned char)x;
x >>= 8;
}
if (randomStruct->bytesNeeded < blockLen)
randomStruct->bytesNeeded = 0;
else
randomStruct->bytesNeeded -= blockLen;
/* Zeroize sensitive information.
*/
R_memset ((POINTER)digest, 0, sizeof (digest));
x = 0;
return (0);
}
int R_GetRandomBytesNeeded (bytesNeeded, randomStruct)
unsigned int *bytesNeeded; /* number of mix-in bytes needed */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
*bytesNeeded = randomStruct->bytesNeeded;
return (0);
}
int R_GenerateBytes (block, blockLen, randomStruct)
unsigned char *block; /* block */
unsigned int blockLen; /* length of block */
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
MD5_CTX context;
unsigned int available, i;
if (randomStruct->bytesNeeded)
return (RE_NEED_RANDOM);
available = randomStruct->outputAvailable;
while (blockLen > available) {
R_memcpy
((POINTER)block, (POINTER)&randomStruct->output[16-available],
available);
block += available;
blockLen -= available;
/* generate new output */
MD5Init (&context);
MD5Update (&context, randomStruct->state, 16);
MD5Final (randomStruct->output, &context);
available = 16;
/* increment state */
for (i = 0; i < 16; i++)
if (randomStruct->state[15-i]++)
break;
}
R_memcpy
((POINTER)block, (POINTER)&randomStruct->output[16-available], blockLen);
randomStruct->outputAvailable = available - blockLen;
return (0);
}
void R_RandomFinal (randomStruct)
R_RANDOM_STRUCT *randomStruct; /* random structure */
{
R_memset ((POINTER)randomStruct, 0, sizeof (*randomStruct));
}
|