tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }