unix_fips140_3.c (2242B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <errno.h> 8 #include "secerr.h" 9 #include "secrng.h" 10 #include "prprf.h" 11 #include <sys/random.h> 12 #include "prinit.h" 13 14 #ifndef GRND_RANDOM 15 /* if you don't have get random, you'll need to add your platform specific 16 * support for FIPS 104-3 compliant random seed source here */ 17 PR_STATIC_ASSERT("You'll need to add our platform specific solution for FIPS 140-3 RNG" == NULL); 18 #endif 19 20 /* syscall getentropy() is limited to retrieving 256 bytes */ 21 #define GETENTROPY_MAX_BYTES 256 22 23 void 24 RNG_SystemInfoForRNG(void) 25 { 26 PRUint8 bytes[SYSTEM_RNG_SEED_COUNT]; 27 size_t numBytes = RNG_SystemRNG(bytes, SYSTEM_RNG_SEED_COUNT); 28 if (!numBytes) { 29 /* error is set */ 30 return; 31 } 32 RNG_RandomUpdate(bytes, numBytes); 33 PORT_SafeZero(bytes, sizeof(bytes)); 34 } 35 36 static unsigned int rng_grndFlags = 0; 37 static PRCallOnceType rng_KernelFips; 38 39 static PRStatus 40 rng_getKernelFips() 41 { 42 if (NSS_GetSystemFIPSEnabled()) { 43 rng_grndFlags = GRND_RANDOM; 44 } 45 return PR_SUCCESS; 46 } 47 48 size_t 49 RNG_SystemRNG(void *dest, size_t maxLen) 50 { 51 52 size_t fileBytes = 0; 53 unsigned char *buffer = dest; 54 ssize_t result; 55 56 PR_CallOnce(&rng_KernelFips, rng_getKernelFips); 57 58 while (fileBytes < maxLen) { 59 size_t getBytes = maxLen - fileBytes; 60 if (getBytes > GETENTROPY_MAX_BYTES) { 61 getBytes = GETENTROPY_MAX_BYTES; 62 } 63 /* FIP 140-3 requires full kernel reseeding for chained entropy sources 64 * so we need to use getrandom with GRND_RANDOM. 65 * getrandom returns -1 on failure, otherwise returns 66 * the number of bytes, which can be less than getBytes */ 67 result = getrandom(buffer, getBytes, rng_grndFlags); 68 if (result < 0) { 69 break; 70 } 71 fileBytes += result; 72 buffer += result; 73 } 74 if (fileBytes == maxLen) { /* success */ 75 return maxLen; 76 } 77 /* in FIPS 104-3 we don't fallback, just fail */ 78 PORT_SetError(SEC_ERROR_NEED_RANDOM); 79 return 0; 80 }