/* 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 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include "secerr.h" #include "secrng.h" #include "prprf.h" #include #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; }