Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "secerr.h"
#include "secrng.h"
#include "prprf.h"
#include <sys/random.h>
#include "prinit.h"
#ifndef GRND_RANDOM
/* if you don't have get random, you'll need to add your platform specific
* support for FIPS 104-3 compliant random seed source here */
PR_STATIC_ASSERT("You'll need to add our platform specific solution for FIPS 140-3 RNG" == NULL);
#endif
/* syscall getentropy() is limited to retrieving 256 bytes */
#define GETENTROPY_MAX_BYTES 256
void
RNG_SystemInfoForRNG(void)
{
PRUint8 bytes[SYSTEM_RNG_SEED_COUNT];
size_t numBytes = RNG_SystemRNG(bytes, SYSTEM_RNG_SEED_COUNT);
if (!numBytes) {
/* error is set */
return;
}
RNG_RandomUpdate(bytes, numBytes);
PORT_SaveZero(bytes, sizeof(bytes));
}
static unsigned int rng_grndFlags = 0;
static PRCallOnceType rng_KernelFips;
static PRStatus
rng_getKernelFips()
{
if (NSS_GetSystemFIPSEnabled()) {
rng_grndFlags = GRND_RANDOM;
}
return PR_SUCCESS;
}
size_t
RNG_SystemRNG(void *dest, size_t maxLen)
{
size_t fileBytes = 0;
unsigned char *buffer = dest;
ssize_t result;
PR_CallOnce(&rng_KernelFips, rng_getKernelFips);
while (fileBytes < maxLen) {
size_t getBytes = maxLen - fileBytes;
if (getBytes > GETENTROPY_MAX_BYTES) {
getBytes = GETENTROPY_MAX_BYTES;
}
/* FIP 140-3 requires full kernel reseeding for chained entropy sources
* so we need to use getrandom with GRND_RANDOM.
* getrandom returns -1 on failure, otherwise returns
* the number of bytes, which can be less than getBytes */
result = getrandom(buffer, getBytes, rng_grndFlags);
if (result < 0) {
break;
}
fileBytes += result;
buffer += result;
}
if (fileBytes == maxLen) { /* success */
return maxLen;
}
/* in FIPS 104-3 we don't fallback, just fail */
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return 0;
}