Bug 457045 - (drbg) Implement one of the DRBGs (PRNGs) specified in

NIST SP 800-90

1) fix Win64 warnings.
2) don't read directories in Unix Jitter.
3) Fix bug in count environment variable which read in files to the rng automatically
4) Add clarifying comments.

r=wtc sr=nelson


git-svn-id: svn://10.0.0.236/trunk@256258 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rrelyea%redhat.com 2009-02-20 01:00:55 +00:00
parent be52a525c6
commit d3d7f43c88
5 changed files with 74 additions and 52 deletions

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: blapi.h,v 1.30 2009-02-12 22:48:43 rrelyea%redhat.com Exp $ */
/* $Id: blapi.h,v 1.31 2009-02-20 01:00:55 rrelyea%redhat.com Exp $ */
#ifndef _BLAPI_H_
#define _BLAPI_H_
@ -1107,17 +1107,17 @@ FIPS186Change_ReduceModQForDSA(const unsigned char *w,
* testing.
*/
extern SECStatus
PRNGTEST_Instantiate(const PRUint8 *entropy, int entropy_len,
const PRUint8 *nonce, int nonce_len,
const PRUint8 *personal_string, int ps_len);
PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *nonce, unsigned int nonce_len,
const PRUint8 *personal_string, unsigned int ps_len);
extern SECStatus
PRNGTEST_Reseed(PRUint8 *entropy, int entropy_len,
const PRUint8 *additional, int additional_len);
PRNGTEST_Reseed(PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *additional, unsigned int additional_len);
extern SECStatus
PRNGTEST_Generate(PRUint8 *bytes, int byte_Len,
const PRUint8 *additional, int additional_len);
PRNGTEST_Generate(PRUint8 *bytes, unsigned int byte_Len,
const PRUint8 *additional, unsigned int additional_len);
extern SECStatus
PRNGTEST_Uninstantiate(void);

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: drbg.c,v 1.2 2009-02-17 02:35:32 wtc%google.com Exp $ */
/* $Id: drbg.c,v 1.3 2009-02-20 01:00:55 rrelyea%redhat.com Exp $ */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
@ -158,9 +158,9 @@ static RNGContext theGlobalRng;
* if input_string_2 is not supplied, NULL should be passed for this parameter.
*/
static SECStatus
prng_Hash_df(PRUint8 *requested_bytes, int no_of_bytes_to_return,
const PRUint8 *input_string_1, int input_string_1_len,
const PRUint8 *input_string_2, int input_string_2_len)
prng_Hash_df(PRUint8 *requested_bytes, unsigned int no_of_bytes_to_return,
const PRUint8 *input_string_1, unsigned int input_string_1_len,
const PRUint8 *input_string_2, unsigned int input_string_2_len)
{
SHA256Context ctx;
PRUint32 tmp;
@ -193,7 +193,7 @@ prng_Hash_df(PRUint8 *requested_bytes, int no_of_bytes_to_return,
* normal operation, NSS calculates them all together in a single call.
*/
static SECStatus
prng_instantiate(RNGContext *rng, PRUint8 *bytes, int len)
prng_instantiate(RNGContext *rng, PRUint8 *bytes, unsigned int len)
{
prng_Hash_df(V(rng), VSize(rng), bytes, len, NULL, 0);
rng->V_type = prngCGenerateType;
@ -214,16 +214,16 @@ prng_instantiate(RNGContext *rng, PRUint8 *bytes, int len)
*/
static
SECStatus
prng_reseed(RNGContext *rng, const PRUint8 *entropy, int entropy_len,
const PRUint8 *additional_input, int additional_input_len)
prng_reseed(RNGContext *rng, const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *additional_input, unsigned int additional_input_len)
{
PRUint8 noiseData[(sizeof rng->V_Data)+PRNG_SEEDLEN];
PRUint8 *noise = &noiseData[0];
/* if entropy wasn't supplied, fetch it. (normal operationg case) */
if (entropy == NULL) {
entropy_len = RNG_SystemRNG(&noiseData[sizeof rng->V_Data],
PRNG_SEEDLEN);
entropy_len = (unsigned int) RNG_SystemRNG(
&noiseData[sizeof rng->V_Data], PRNG_SEEDLEN);
} else {
/* NOTE: this code is only available for testing, not to applications */
/* if entropy was too big for the stack variable, get it from malloc */
@ -285,7 +285,7 @@ prng_reseed(RNGContext *rng, const PRUint8 *entropy, int entropy_len,
*/
static void
prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
int no_of_returned_bytes)
unsigned int no_of_returned_bytes)
{
PRUint8 data[VSize(rng)];
@ -301,7 +301,9 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
SHA256_End(&ctx, returned_bytes, &len, no_of_returned_bytes);
returned_bytes += len;
no_of_returned_bytes -= len;
PRNG_ADD_CARRY_ONLY(data, (sizeof data) -1, no_of_returned_bytes);
/* The carry parameter is a bool (increment or not).
* This increments data if no_of_returned_bytes is not zero */
PRNG_ADD_CARRY_ONLY(data, (sizeof data)- 1, no_of_returned_bytes);
}
PORT_Memset(data, 0, sizeof data);
}
@ -314,8 +316,9 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes,
*/
static SECStatus
prng_generateNewBytes(RNGContext *rng,
PRUint8 *returned_bytes, int no_of_returned_bytes,
const PRUint8 *additional_input,int additional_input_len)
PRUint8 *returned_bytes, unsigned int no_of_returned_bytes,
const PRUint8 *additional_input,
unsigned int additional_input_len)
{
PRUint8 H[SHA256_LENGTH]; /* both H and w since they
* aren't used concurrently */
@ -378,7 +381,7 @@ static const PRCallOnceType pristineCallOnce;
static PRCallOnceType coRNGInit;
static PRStatus rng_init(void)
{
PRUint8 bytes[PRNG_SEEDLEN];
PRUint8 bytes[PRNG_SEEDLEN*2]; /* entropy + nonce */
unsigned int numBytes;
if (globalrng == NULL) {
/* create a new global RNG context */
@ -393,7 +396,7 @@ static PRStatus rng_init(void)
}
/* Try to get some seed data for the RNG */
numBytes = RNG_SystemRNG(bytes, sizeof bytes);
numBytes = (unsigned int) RNG_SystemRNG(bytes, sizeof bytes);
PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
if (numBytes != 0) {
/* if this is our first call, instantiate, otherwise reseed
@ -405,7 +408,7 @@ static PRStatus rng_init(void)
prng_reseed(globalrng, bytes, numBytes, NULL, 0);
}
memset(bytes, 0, numBytes);
} else if (PORT_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
} else {
PZ_DestroyLock(globalrng->lock);
globalrng->lock = NULL;
globalrng->isValid = PR_FALSE;
@ -514,13 +517,13 @@ RNG_RandomUpdate(const void *data, size_t bytes)
/* if we're passed more than our additionalCache, simply
* call reseed with that data */
if (bytes > sizeof (globalrng->additionalDataCache)) {
rv = prng_reseed(globalrng, NULL, 0, data, bytes);
rv = prng_reseed(globalrng, NULL, 0, data, (unsigned int) bytes);
/* if we aren't going to overflow the buffer, just cache it */
} else if (bytes < ((sizeof globalrng->additionalDataCache)
- globalrng->additionalAvail)) {
PORT_Memcpy(globalrng->additionalDataCache+globalrng->additionalAvail,
data, bytes);
globalrng->additionalAvail += bytes;
globalrng->additionalAvail += (PRUint32) bytes;
rv = SECSuccess;
} else {
/* we are going to overflow the buffer. In this case we will fill
@ -544,7 +547,7 @@ RNG_RandomUpdate(const void *data, size_t bytes)
/* copy the rest into the cache */
PORT_Memcpy(globalrng->additionalDataCache, data, bytes);
globalrng->additionalAvail = bytes;
globalrng->additionalAvail = (PRUint32) bytes;
}
PZ_Unlock(globalrng->lock);
@ -764,9 +767,9 @@ RNGContext testContext;
* other NIST SP 800 algorithms may used in the future.
*/
SECStatus
PRNGTEST_Instantiate(const PRUint8 *entropy, int entropy_len,
const PRUint8 *nonce, int nonce_len,
const PRUint8 *personal_string, int ps_len)
PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *nonce, unsigned int nonce_len,
const PRUint8 *personal_string, unsigned int ps_len)
{
int byte_len = entropy_len + nonce_len + ps_len;
PRUint8 *bytes = PORT_Alloc(byte_len);
@ -794,8 +797,8 @@ PRNGTEST_Instantiate(const PRUint8 *entropy, int entropy_len,
}
SECStatus
PRNGTEST_Reseed(PRUint8 *entropy, int entropy_len,
const PRUint8 *additional, int additional_len)
PRNGTEST_Reseed(PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *additional, unsigned int additional_len)
{
if (!testContext.isValid) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
@ -807,8 +810,8 @@ PRNGTEST_Reseed(PRUint8 *entropy, int entropy_len,
}
SECStatus
PRNGTEST_Generate(PRUint8 *bytes, int byte_len,
const PRUint8 *additional, int additional_len)
PRNGTEST_Generate(PRUint8 *bytes, unsigned int byte_len,
const PRUint8 *additional, unsigned int additional_len)
{
if (!testContext.isValid) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: loader.c,v 1.42 2009-02-12 22:48:43 rrelyea%redhat.com Exp $ */
/* $Id: loader.c,v 1.43 2009-02-20 01:00:55 rrelyea%redhat.com Exp $ */
#include "loader.h"
#include "prmem.h"
@ -1657,9 +1657,9 @@ void BL_SetForkState(PRBool forked)
}
SECStatus
PRNGTEST_Instantiate(const PRUint8 *entropy, int entropy_len,
const PRUint8 *nonce, int nonce_len,
const PRUint8 *personal_string, int ps_len)
PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *nonce, unsigned int nonce_len,
const PRUint8 *personal_string, unsigned int ps_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
@ -1669,8 +1669,8 @@ PRNGTEST_Instantiate(const PRUint8 *entropy, int entropy_len,
}
SECStatus
PRNGTEST_Reseed(PRUint8 *entropy, int entropy_len,
const PRUint8 *additional, int additional_len)
PRNGTEST_Reseed(PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *additional, unsigned int additional_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;
@ -1679,8 +1679,8 @@ PRNGTEST_Reseed(PRUint8 *entropy, int entropy_len,
}
SECStatus
PRNGTEST_Generate(PRUint8 *bytes, int byte_Len,
const PRUint8 *additional, int additional_len)
PRNGTEST_Generate(PRUint8 *bytes, unsigned int byte_Len,
const PRUint8 *additional, unsigned int additional_len)
{
if (!vector && PR_SUCCESS != freebl_RunLoaderOnce())
return SECFailure;

View File

@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: loader.h,v 1.24 2009-02-12 22:48:44 rrelyea%redhat.com Exp $ */
/* $Id: loader.h,v 1.25 2009-02-20 01:00:55 rrelyea%redhat.com Exp $ */
#ifndef _LOADER_H_
#define _LOADER_H_ 1
@ -522,21 +522,21 @@ struct FREEBLVectorStr {
void ( * p_BL_SetForkState)(PRBool);
SECStatus (* p_PRNGTEST_Instantiate)(const PRUint8 *entropy,
int entropy_len,
unsigned int entropy_len,
const PRUint8 *nonce,
int nonce_len,
unsigned int nonce_len,
const PRUint8 *personal_string,
int ps_len);
unsigned int ps_len);
SECStatus (* p_PRNGTEST_Reseed)(PRUint8 *entropy,
int entropy_len,
unsigned int entropy_len,
const PRUint8 *additional,
int additional_len);
unsigned int additional_len);
SECStatus (* p_PRNGTEST_Generate)(PRUint8 *bytes,
int byte_Len,
unsigned int byte_Len,
const PRUint8 *additional,
int additional_len);
unsigned int additional_len);
SECStatus (* p_PRNGTEST_Uninstantiate)(void);
/* Version 3.011 came to here */

View File

@ -965,7 +965,7 @@ void RNG_SystemInfoForRNG(void)
if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {
char *randCountString = getenv("NSRANDCOUNT");
int randCount = randCountString ? atoi(randCountString) : 0;
if (randCount == 0) {
if (randCount != 0) {
RNG_FileUpdate(randfile, randCount);
} else {
RNG_FileForRNG(randfile);
@ -1152,6 +1152,22 @@ void ReadSingleFile(const char *fileName)
#define _POSIX_PTHREAD_SEMANTICS
#include <dirent.h>
PRBool
ReadFileOK(char *dir, char *file)
{
struct stat stat_buf;
char filename[PATH_MAX];
int count = snprintf(filename, sizeof filename, "%s/%s",dir, file);
if (count <= 0) {
return PR_FALSE; /* name too long, can't read it anyway */
}
if (stat(filename, &stat_buf) < 0)
return PR_FALSE; /* can't stat, probably can't read it then as well */
return S_ISREG(stat_buf.st_mode) ? PR_TRUE : PR_FALSE;
}
/*
* read one file out of either /etc or the user's home directory.
* fileToRead tells which file to read.
@ -1191,7 +1207,10 @@ int ReadOneFile(int fileToRead)
for (i=0; i <= fileToRead; i++) {
struct dirent *result = NULL;
error = readdir_r(fd, &entry_dir, &result);
do {
error = readdir_r(fd, &entry_dir, &result);
} while (error == 0 && result != NULL &&
!ReadFileOK(dir,&result->d_name[0]));
if (error != 0 || result == NULL) {
resetCount = 1; /* read to the end, start again at the beginning */
if (i != 0) {