Home | History | Annotate | Download | only in rand
      1 /* Copyright (c) 2014, Google Inc.
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     14 
     15 #if !defined(_GNU_SOURCE)
     16 #define _GNU_SOURCE  // needed for syscall() on Linux.
     17 #endif
     18 
     19 #include <openssl/rand.h>
     20 
     21 #if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_FUCHSIA) && \
     22     !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE) && !defined(OPENSSL_TRUSTY)
     23 
     24 #include <assert.h>
     25 #include <errno.h>
     26 #include <fcntl.h>
     27 #include <stdio.h>
     28 #include <string.h>
     29 #include <unistd.h>
     30 
     31 #if defined(OPENSSL_LINUX)
     32 #if defined(BORINGSSL_FIPS)
     33 #include <linux/random.h>
     34 #include <sys/ioctl.h>
     35 #endif
     36 #include <sys/syscall.h>
     37 
     38 #if !defined(OPENSSL_ANDROID)
     39 #define OPENSSL_HAS_GETAUXVAL
     40 #endif
     41 // glibc prior to 2.16 does not have getauxval and sys/auxv.h. Android has some
     42 // host builds (i.e. not building for Android itself, so |OPENSSL_ANDROID| is
     43 // unset) which are still using a 2.15 sysroot.
     44 //
     45 // TODO(davidben): Remove this once Android updates their sysroot.
     46 #if defined(__GLIBC_PREREQ)
     47 #if !__GLIBC_PREREQ(2, 16)
     48 #undef OPENSSL_HAS_GETAUXVAL
     49 #endif
     50 #endif
     51 #if defined(OPENSSL_HAS_GETAUXVAL)
     52 #include <sys/auxv.h>
     53 #endif
     54 #endif  // OPENSSL_LINUX
     55 
     56 #include <openssl/thread.h>
     57 #include <openssl/mem.h>
     58 
     59 #include "internal.h"
     60 #include "../delocate.h"
     61 #include "../../internal.h"
     62 
     63 
     64 #if defined(OPENSSL_LINUX)
     65 
     66 #if defined(OPENSSL_X86_64)
     67 #define EXPECTED_NR_getrandom 318
     68 #elif defined(OPENSSL_X86)
     69 #define EXPECTED_NR_getrandom 355
     70 #elif defined(OPENSSL_AARCH64)
     71 #define EXPECTED_NR_getrandom 278
     72 #elif defined(OPENSSL_ARM)
     73 #define EXPECTED_NR_getrandom 384
     74 #elif defined(OPENSSL_PPC64LE)
     75 #define EXPECTED_NR_getrandom 359
     76 #endif
     77 
     78 #if defined(EXPECTED_NR_getrandom)
     79 #define USE_NR_getrandom
     80 
     81 #if defined(__NR_getrandom)
     82 
     83 #if __NR_getrandom != EXPECTED_NR_getrandom
     84 #error "system call number for getrandom is not the expected value"
     85 #endif
     86 
     87 #else  // __NR_getrandom
     88 
     89 #define __NR_getrandom EXPECTED_NR_getrandom
     90 
     91 #endif  // __NR_getrandom
     92 
     93 #if defined(OPENSSL_MSAN)
     94 void __msan_unpoison(void *, size_t);
     95 #endif
     96 
     97 static ssize_t boringssl_getrandom(void *buf, size_t buf_len, unsigned flags) {
     98   ssize_t ret;
     99   do {
    100     ret = syscall(__NR_getrandom, buf, buf_len, flags);
    101   } while (ret == -1 && errno == EINTR);
    102 
    103 #if defined(OPENSSL_MSAN)
    104   if (ret > 0) {
    105     // MSAN doesn't recognise |syscall| and thus doesn't notice that we have
    106     // initialised the output buffer.
    107     __msan_unpoison(buf, ret);
    108   }
    109 #endif  // OPENSSL_MSAN
    110 
    111   return ret;
    112 }
    113 
    114 #endif  // EXPECTED_NR_getrandom
    115 
    116 #if !defined(GRND_NONBLOCK)
    117 #define GRND_NONBLOCK 1
    118 #endif
    119 
    120 #endif  // OPENSSL_LINUX
    121 
    122 // rand_lock is used to protect the |*_requested| variables.
    123 DEFINE_STATIC_MUTEX(rand_lock)
    124 
    125 // The following constants are magic values of |urandom_fd|.
    126 static const int kUnset = 0;
    127 static const int kHaveGetrandom = -3;
    128 
    129 // urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by
    130 // |rand_lock|.
    131 DEFINE_BSS_GET(int, urandom_fd_requested)
    132 
    133 // urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|.
    134 DEFINE_BSS_GET(int, urandom_fd)
    135 
    136 DEFINE_STATIC_ONCE(rand_once)
    137 
    138 // init_once initializes the state of this module to values previously
    139 // requested. This is the only function that modifies |urandom_fd| and
    140 // |urandom_buffering|, whose values may be read safely after calling the
    141 // once.
    142 static void init_once(void) {
    143   CRYPTO_STATIC_MUTEX_lock_read(rand_lock_bss_get());
    144   int fd = *urandom_fd_requested_bss_get();
    145   CRYPTO_STATIC_MUTEX_unlock_read(rand_lock_bss_get());
    146 
    147 #if defined(USE_NR_getrandom)
    148   uint8_t dummy;
    149   ssize_t getrandom_ret =
    150       boringssl_getrandom(&dummy, sizeof(dummy), GRND_NONBLOCK);
    151 
    152   if (getrandom_ret == -1 && errno == EAGAIN) {
    153     // Attempt to get the path of the current process to aid in debugging when
    154     // something blocks.
    155     const char *current_process = "<unknown>";
    156 #if defined(OPENSSL_HAS_GETAUXVAL)
    157     const unsigned long getauxval_ret = getauxval(AT_EXECFN);
    158     if (getauxval_ret != 0) {
    159       current_process = (const char *)getauxval_ret;
    160     }
    161 #endif
    162 
    163     fprintf(stderr,
    164             "%s: getrandom indicates that the entropy pool has not been "
    165             "initialized. Rather than continue with poor entropy, this process "
    166             "will block until entropy is available.\n",
    167             current_process);
    168 
    169     getrandom_ret =
    170         boringssl_getrandom(&dummy, sizeof(dummy), 0 /* no flags */);
    171   }
    172 
    173   if (getrandom_ret == 1) {
    174     *urandom_fd_bss_get() = kHaveGetrandom;
    175     return;
    176   }
    177 
    178   // Ignore ENOSYS and fallthrough to using /dev/urandom, below. Otherwise it's
    179   // a fatal error.
    180   if (getrandom_ret != -1 || errno != ENOSYS) {
    181     perror("getrandom");
    182     abort();
    183   }
    184 #endif  // USE_NR_getrandom
    185 
    186   if (fd == kUnset) {
    187     do {
    188       fd = open("/dev/urandom", O_RDONLY);
    189     } while (fd == -1 && errno == EINTR);
    190   }
    191 
    192   if (fd < 0) {
    193     perror("failed to open /dev/urandom");
    194     abort();
    195   }
    196 
    197   assert(kUnset == 0);
    198   if (fd == kUnset) {
    199     // Because we want to keep |urandom_fd| in the BSS, we have to initialise
    200     // it to zero. But zero is a valid file descriptor too. Thus if open
    201     // returns zero for /dev/urandom, we dup it to get a non-zero number.
    202     fd = dup(fd);
    203     close(kUnset);
    204 
    205     if (fd <= 0) {
    206       perror("failed to dup /dev/urandom fd");
    207       abort();
    208     }
    209   }
    210 
    211 #if defined(BORINGSSL_FIPS)
    212   // In FIPS mode we ensure that the kernel has sufficient entropy before
    213   // continuing. This is automatically handled by getrandom, which requires
    214   // that the entropy pool has been initialised, but for urandom we have to
    215   // poll.
    216   for (;;) {
    217     int entropy_bits;
    218     if (ioctl(fd, RNDGETENTCNT, &entropy_bits)) {
    219       fprintf(stderr,
    220               "RNDGETENTCNT on /dev/urandom failed. We cannot continue in this "
    221               "case when in FIPS mode.\n");
    222       abort();
    223     }
    224 
    225     static const int kBitsNeeded = 256;
    226     if (entropy_bits >= kBitsNeeded) {
    227       break;
    228     }
    229 
    230     usleep(250000);
    231   }
    232 #endif
    233 
    234   int flags = fcntl(fd, F_GETFD);
    235   if (flags == -1) {
    236     // Native Client doesn't implement |fcntl|.
    237     if (errno != ENOSYS) {
    238       perror("failed to get flags from urandom fd");
    239       abort();
    240     }
    241   } else {
    242     flags |= FD_CLOEXEC;
    243     if (fcntl(fd, F_SETFD, flags) == -1) {
    244       perror("failed to set FD_CLOEXEC on urandom fd");
    245       abort();
    246     }
    247   }
    248   *urandom_fd_bss_get() = fd;
    249 }
    250 
    251 void RAND_set_urandom_fd(int fd) {
    252   fd = dup(fd);
    253   if (fd < 0) {
    254     perror("failed to dup supplied urandom fd");
    255     abort();
    256   }
    257 
    258   assert(kUnset == 0);
    259   if (fd == kUnset) {
    260     // Because we want to keep |urandom_fd| in the BSS, we have to initialise
    261     // it to zero. But zero is a valid file descriptor too. Thus if dup
    262     // returned zero we dup it again to get a non-zero number.
    263     fd = dup(fd);
    264     close(kUnset);
    265 
    266     if (fd <= 0) {
    267       perror("failed to dup supplied urandom fd");
    268       abort();
    269     }
    270   }
    271 
    272   CRYPTO_STATIC_MUTEX_lock_write(rand_lock_bss_get());
    273   *urandom_fd_requested_bss_get() = fd;
    274   CRYPTO_STATIC_MUTEX_unlock_write(rand_lock_bss_get());
    275 
    276   CRYPTO_once(rand_once_bss_get(), init_once);
    277   if (*urandom_fd_bss_get() == kHaveGetrandom) {
    278     close(fd);
    279   } else if (*urandom_fd_bss_get() != fd) {
    280     fprintf(stderr, "RAND_set_urandom_fd called after initialisation.\n");
    281     abort();
    282   }
    283 }
    284 
    285 // fill_with_entropy writes |len| bytes of entropy into |out|. It returns one
    286 // on success and zero on error.
    287 static char fill_with_entropy(uint8_t *out, size_t len) {
    288   while (len > 0) {
    289     ssize_t r;
    290 
    291     if (*urandom_fd_bss_get() == kHaveGetrandom) {
    292 #if defined(USE_NR_getrandom)
    293       r = boringssl_getrandom(out, len, 0 /* no flags */);
    294 #else  // USE_NR_getrandom
    295       fprintf(stderr, "urandom fd corrupt.\n");
    296       abort();
    297 #endif
    298     } else {
    299       do {
    300         r = read(*urandom_fd_bss_get(), out, len);
    301       } while (r == -1 && errno == EINTR);
    302     }
    303 
    304     if (r <= 0) {
    305       return 0;
    306     }
    307     out += r;
    308     len -= r;
    309   }
    310 
    311   return 1;
    312 }
    313 
    314 // CRYPTO_sysrand puts |requested| random bytes into |out|.
    315 void CRYPTO_sysrand(uint8_t *out, size_t requested) {
    316   if (requested == 0) {
    317     return;
    318   }
    319 
    320   CRYPTO_once(rand_once_bss_get(), init_once);
    321 
    322   if (!fill_with_entropy(out, requested)) {
    323     perror("entropy fill failed");
    324     abort();
    325   }
    326 
    327 #if defined(BORINGSSL_FIPS_BREAK_CRNG)
    328   // This breaks the "continuous random number generator test" defined in FIPS
    329   // 140-2, section 4.9.2, and implemented in rand_get_seed().
    330   OPENSSL_memset(out, 0, requested);
    331 #endif
    332 }
    333 
    334 #endif /* !OPENSSL_WINDOWS && !defined(OPENSSL_FUCHSIA) && \
    335           !BORINGSSL_UNSAFE_DETERMINISTIC_MODE && !OPENSSL_TRUSTY */
    336