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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user