Bugzilla Bug 355297: added new function RNG_SystemRNG, which gets random

bits from the system RNG, and use it for the very first RNG_RandomUpdate
call in rng_init so that we initialize the RNG's XKEY with high quality
entropy. r=jpierre,relyea.
Modified Files:
	os2_rand.c prng_fips1861.c secrng.h unix_rand.c win_rand.c


git-svn-id: svn://10.0.0.236/trunk@213528 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
wtchang%redhat.com
2006-10-12 02:23:49 +00:00
parent 42f64f4a73
commit 98af12d8cd
5 changed files with 177 additions and 9 deletions

View File

@@ -37,7 +37,8 @@
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#include <secrng.h>
#include "secrng.h"
#include "prerror.h"
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
@@ -331,3 +332,9 @@ void RNG_FileForRNG(const char *filename)
nBytes = RNG_GetNoise(buffer, 20);
RNG_RandomUpdate(buffer, nBytes);
}
size_t RNG_SystemRNG(void *dest, size_t maxLen)
{
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
return 0;
}

View File

@@ -35,7 +35,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* $Id: prng_fips1861.c,v 1.25 2006-09-26 22:20:18 julien.pierre.bugs%sun.com Exp $ */
/* $Id: prng_fips1861.c,v 1.26 2006-10-12 02:23:49 wtchang%redhat.com Exp $ */
#include "prerr.h"
#include "secerr.h"
@@ -347,7 +347,7 @@ static const PRCallOnceType pristineCallOnce;
static PRCallOnceType coRNGInit;
static PRStatus rng_init(void)
{
unsigned char bytes[120];
unsigned char bytes[SYSTEM_RNG_SEED_COUNT];
unsigned int numBytes;
if (globalrng == NULL) {
/* create a new global RNG context */
@@ -362,7 +362,31 @@ static PRStatus rng_init(void)
}
/* the RNG is in a valid state */
globalrng->isValid = PR_TRUE;
/* Try to get some seed data for the RNG */
/*
* Try to get some seed data for the RNG.
*
* The very first RNG_RandomUpdate call initializes all FIPS_B
* bits of the RNG's seed-key. Subsequent RNG_RandomUpdate calls
* only modify the low FIPS_G bits of the seed-key. So it's
* important to pass high entropy to the first RNG_RandomUpdate
* call.
*
* RNG_GetNoise only reads the high-resolution clocks, which
* have low entropy. So if RNG_SystemRNG fails, the RNG will
* have at most slightly more than FIPS_G bits of entropy.
*/
numBytes = RNG_SystemRNG(bytes, sizeof bytes);
PORT_Assert(numBytes == 0 || numBytes == sizeof bytes);
if (numBytes != 0) {
RNG_RandomUpdate(bytes, numBytes);
memset(bytes, 0, numBytes);
} else if (PORT_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
PZ_DestroyLock(globalrng->lock);
globalrng->lock = NULL;
globalrng->isValid = PR_FALSE;
globalrng = NULL;
return PR_FAILURE;
}
numBytes = RNG_GetNoise(bytes, sizeof bytes);
RNG_RandomUpdate(bytes, numBytes);
}

View File

@@ -40,7 +40,7 @@
* secrng.h - public data structures and prototypes for the secure random
* number generator
*
* $Id: secrng.h,v 1.5 2004-04-25 15:03:08 gerv%gerv.net Exp $
* $Id: secrng.h,v 1.6 2006-10-12 02:23:49 wtchang%redhat.com Exp $
*/
/******************************************/
@@ -51,11 +51,14 @@
#include "blapi.h"
/* the number of bytes to read from the system random number generator */
#define SYSTEM_RNG_SEED_COUNT 1024
SEC_BEGIN_PROTOS
/*
** The following 3 functions are provided by the security library
** but are differently implemented for the UNIX, Mac and Win
** The following functions are provided by the security library
** but are differently implemented for the UNIX, Win, and OS/2
** versions
*/
@@ -80,6 +83,17 @@ extern void RNG_SystemInfoForRNG(void);
*/
extern void RNG_FileForRNG(const char *filename);
/*
** Get maxbytes bytes of random data from the system random number
** generator.
** Returns the number of bytes copied into buf -- maxbytes if success
** or zero if error.
** Errors:
** PR_NOT_IMPLEMENTED_ERROR There is no system RNG on the platform.
** SEC_ERROR_NEED_RANDOM The system RNG failed.
*/
extern size_t RNG_SystemRNG(void *buf, size_t maxbytes);
SEC_END_PROTOS
#endif /* _SECRNG_H_ */

View File

@@ -43,8 +43,9 @@
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <assert.h>
#include "secrng.h"
#include "secerr.h"
#include "prerror.h"
size_t RNG_FileUpdate(const char *fileName, size_t limit);
@@ -955,7 +956,7 @@ for the small amount of entropy it provides.
GiveSystemInfo();
/* grab some data from system's PRNG before any other files. */
bytes = RNG_FileUpdate("/dev/urandom", 1024);
bytes = RNG_FileUpdate("/dev/urandom", SYSTEM_RNG_SEED_COUNT);
/* If the user points us to a random file, pass it through the rng */
randfile = getenv("NSRANDFILE");
@@ -1130,3 +1131,31 @@ void RNG_FileForRNG(const char *fileName)
{
RNG_FileUpdate(fileName, TOTAL_FILE_LIMIT);
}
size_t RNG_SystemRNG(void *dest, size_t maxLen)
{
FILE *file;
size_t bytes;
size_t fileBytes = 0;
unsigned char *buffer = dest;
file = fopen("/dev/urandom", "r");
if (file == NULL) {
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
return fileBytes;
}
while (maxLen > fileBytes) {
bytes = maxLen - fileBytes;
bytes = fread(buffer, 1, bytes, file);
if (bytes == 0)
break;
fileBytes += bytes;
buffer += bytes;
}
fclose(file);
if (fileBytes != maxLen) {
PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */
fileBytes = 0;
}
return fileBytes;
}

View File

@@ -35,6 +35,7 @@
* ***** END LICENSE BLOCK ***** */
#include "secrng.h"
#include "secerr.h"
#ifdef XP_WIN
#include <windows.h>
@@ -56,6 +57,7 @@
#endif
#include "prio.h"
#include "prerror.h"
static PRInt32 filesToRead;
static DWORD totalFileBytes;
@@ -544,4 +546,96 @@ void RNG_FileForRNG(const char *filename)
}
#endif /* not WinCE */
/*
* CryptoAPI requires Windows NT 4.0 or Windows 95 OSR2 and later.
* Until we drop support for Windows 95, we need to emulate some
* definitions and declarations in <wincrypt.h> and look up the
* functions in advapi32.dll at run time.
*/
typedef unsigned long HCRYPTPROV;
#define CRYPT_VERIFYCONTEXT 0xF0000000
#define PROV_RSA_FULL 1
typedef BOOL
(WINAPI *CryptAcquireContextAFn)(
HCRYPTPROV *phProv,
LPCSTR pszContainer,
LPCSTR pszProvider,
DWORD dwProvType,
DWORD dwFlags);
typedef BOOL
(WINAPI *CryptReleaseContextFn)(
HCRYPTPROV hProv,
DWORD dwFlags);
typedef BOOL
(WINAPI *CryptGenRandomFn)(
HCRYPTPROV hProv,
DWORD dwLen,
BYTE *pbBuffer);
/*
* Windows XP and Windows Server 2003 and later have RtlGenRandom,
* which must be looked up by the name SystemFunction036.
*/
typedef BOOLEAN
(APIENTRY *RtlGenRandomFn)(
PVOID RandomBuffer,
ULONG RandomBufferLength);
size_t RNG_SystemRNG(void *dest, size_t maxLen)
{
HMODULE hModule;
RtlGenRandomFn pRtlGenRandom;
CryptAcquireContextAFn pCryptAcquireContextA;
CryptReleaseContextFn pCryptReleaseContext;
CryptGenRandomFn pCryptGenRandom;
HCRYPTPROV hCryptProv;
size_t bytes = 0;
hModule = LoadLibrary("advapi32.dll");
if (hModule == NULL) {
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
return 0;
}
pRtlGenRandom = (RtlGenRandomFn)
GetProcAddress(hModule, "SystemFunction036");
if (pRtlGenRandom) {
if (pRtlGenRandom(dest, maxLen)) {
bytes = maxLen;
} else {
PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */
}
goto done;
}
pCryptAcquireContextA = (CryptAcquireContextAFn)
GetProcAddress(hModule, "CryptAcquireContextA");
pCryptReleaseContext = (CryptReleaseContextFn)
GetProcAddress(hModule, "CryptReleaseContext");
pCryptGenRandom = (CryptGenRandomFn)
GetProcAddress(hModule, "CryptGenRandom");
if (!pCryptAcquireContextA || !pCryptReleaseContext || !pCryptGenRandom) {
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
goto done;
}
if (pCryptAcquireContextA(&hCryptProv, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
if (pCryptGenRandom(hCryptProv, maxLen, dest)) {
bytes = maxLen;
}
pCryptReleaseContext(hCryptProv, 0);
}
if (bytes == 0) {
PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */
}
done:
FreeLibrary(hModule);
return bytes;
}
#endif /* is XP_WIN */