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 #include <openssl/rand.h>
     16 
     17 #if !defined(OPENSSL_WINDOWS)
     18 
     19 #include <assert.h>
     20 #include <errno.h>
     21 #include <fcntl.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <unistd.h>
     25 
     26 #include <openssl/thread.h>
     27 #include <openssl/mem.h>
     28 
     29 
     30 /* This file implements a PRNG by reading from /dev/urandom, optionally with a
     31  * fork-safe buffer.
     32  *
     33  * If buffering is enabled then it maintains a global, linked list of buffers.
     34  * Threads which need random bytes grab a buffer from the list under a lock and
     35  * copy out the bytes that they need. In the rare case that the buffer is
     36  * empty, it's refilled from /dev/urandom outside of the lock.
     37  *
     38  * Large requests are always serviced from /dev/urandom directly.
     39  *
     40  * Each buffer contains the PID of the process that created it and it's tested
     41  * against the current PID each time. Thus processes that fork will discard all
     42  * the buffers filled by the parent process. There are two problems with this:
     43  *
     44  * 1) glibc maintains a cache of the current PID+PPID and, if this cache isn't
     45  *    correctly invalidated, the getpid() will continue to believe that
     46  *    it's the old process. Glibc depends on the glibc wrappers for fork,
     47  *    vfork and clone being used in order to invalidate the getpid() cache.
     48  *
     49  * 2) If a process forks, dies and then its child forks, it's possible that
     50  *    the third process will end up with the same PID as the original process.
     51  *    If the second process never used any random values then this will mean
     52  *    that the third process has stale, cached values and won't notice.
     53  */
     54 
     55 /* BUF_SIZE is intended to be a 4K allocation with malloc overhead. struct
     56  * rand_buffer also fits in this space and the remainder is entropy. */
     57 #define BUF_SIZE (4096 - 16)
     58 
     59 /* rand_buffer contains unused, random bytes. These structures form a linked
     60  * list via the |next| pointer, which is NULL in the final element. */
     61 struct rand_buffer {
     62   size_t used; /* used contains the number of bytes of |rand| that have
     63                   been consumed. */
     64   struct rand_buffer *next;
     65   pid_t pid; /* pid contains the pid at the time that the buffer was
     66                 created so that data is not duplicated after a fork. */
     67   pid_t ppid; /* ppid contains the parent pid in order to try and reduce
     68                  the possibility of duplicated PID confusing the
     69                  detection of a fork. */
     70   uint8_t rand[];
     71 };
     72 
     73 /* rand_bytes_per_buf is the number of actual entropy bytes in a buffer. */
     74 static const size_t rand_bytes_per_buf = BUF_SIZE - sizeof(struct rand_buffer);
     75 
     76 /* list_head is the start of a global, linked-list of rand_buffer objects. It's
     77  * protected by CRYPTO_LOCK_RAND. */
     78 static struct rand_buffer *list_head;
     79 
     80 /* urandom_fd is a file descriptor to /dev/urandom. It's protected by
     81  * CRYPTO_LOCK_RAND. */
     82 static int urandom_fd = -2;
     83 
     84 /* urandom_buffering controls whether buffering is enabled (1) or not (0). This
     85  * is protected by CRYPTO_LOCK_RAND. */
     86 static int urandom_buffering = 0;
     87 
     88 /* urandom_get_fd_locked returns a file descriptor to /dev/urandom. The caller
     89  * of this function must hold CRYPTO_LOCK_RAND. */
     90 static int urandom_get_fd_locked(void) {
     91   if (urandom_fd != -2)
     92     return urandom_fd;
     93 
     94   urandom_fd = open("/dev/urandom", O_RDONLY);
     95   return urandom_fd;
     96 }
     97 
     98 /* RAND_cleanup frees all buffers, closes any cached file descriptor
     99  * and resets the global state. */
    100 void RAND_cleanup(void) {
    101   struct rand_buffer *cur;
    102 
    103   CRYPTO_w_lock(CRYPTO_LOCK_RAND);
    104   while ((cur = list_head)) {
    105     list_head = cur->next;
    106     OPENSSL_free(cur);
    107   }
    108   if (urandom_fd >= 0) {
    109     close(urandom_fd);
    110   }
    111   urandom_fd = -2;
    112   list_head = NULL;
    113   CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
    114 }
    115 
    116 /* read_full reads exactly |len| bytes from |fd| into |out| and returns 1. In
    117  * the case of an error it returns 0. */
    118 static char read_full(int fd, uint8_t *out, size_t len) {
    119   ssize_t r;
    120 
    121   while (len > 0) {
    122     do {
    123       r = read(fd, out, len);
    124     } while (r == -1 && errno == EINTR);
    125 
    126     if (r <= 0) {
    127       return 0;
    128     }
    129     out += r;
    130     len -= r;
    131   }
    132 
    133   return 1;
    134 }
    135 
    136 /* urandom_rand_pseudo_bytes puts |num| random bytes into |out|. It returns
    137  * one on success and zero otherwise. */
    138 int RAND_bytes(uint8_t *out, size_t requested) {
    139   int fd;
    140   struct rand_buffer *buf;
    141   size_t todo;
    142   pid_t pid, ppid;
    143 
    144   if (requested == 0) {
    145     return 1;
    146   }
    147 
    148   CRYPTO_w_lock(CRYPTO_LOCK_RAND);
    149   fd = urandom_get_fd_locked();
    150 
    151   if (fd < 0) {
    152     CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
    153     abort();
    154     return 0;
    155   }
    156 
    157   /* If buffering is not enabled, or if the request is large, then the
    158    * result comes directly from urandom. */
    159   if (!urandom_buffering || requested > BUF_SIZE / 2) {
    160     CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
    161     if (!read_full(fd, out, requested)) {
    162       abort();
    163       return 0;
    164     }
    165     return 1;
    166   }
    167 
    168   pid = getpid();
    169   ppid = getppid();
    170 
    171   for (;;) {
    172     buf = list_head;
    173     if (buf && buf->pid == pid && buf->ppid == ppid &&
    174         rand_bytes_per_buf - buf->used >= requested) {
    175       memcpy(out, &buf->rand[buf->used], requested);
    176       buf->used += requested;
    177       CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
    178       return 1;
    179     }
    180 
    181     /* If we don't immediately have enough entropy with the correct
    182      * PID, remove the buffer from the list in order to gain
    183      * exclusive access and unlock. */
    184     if (buf) {
    185       list_head = buf->next;
    186     }
    187     CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
    188 
    189     if (!buf) {
    190       buf = (struct rand_buffer *)OPENSSL_malloc(BUF_SIZE);
    191       /* The buffer doesn't contain any random bytes yet
    192        * so we mark it as fully used so that it will be
    193        * filled below. */
    194       buf->used = rand_bytes_per_buf;
    195       buf->next = NULL;
    196       buf->pid = pid;
    197       buf->ppid = ppid;
    198     }
    199 
    200     if (buf->pid == pid && buf->ppid == ppid) {
    201       break;
    202     }
    203 
    204     /* We have forked and so cannot use these bytes as they
    205      * may have been used in another process. */
    206     OPENSSL_free(buf);
    207     CRYPTO_w_lock(CRYPTO_LOCK_RAND);
    208   }
    209 
    210   while (requested > 0) {
    211     todo = rand_bytes_per_buf - buf->used;
    212     if (todo > requested) {
    213       todo = requested;
    214     }
    215     memcpy(out, &buf->rand[buf->used], todo);
    216     requested -= todo;
    217     out += todo;
    218     buf->used += todo;
    219 
    220     if (buf->used < rand_bytes_per_buf) {
    221       break;
    222     }
    223 
    224     if (!read_full(fd, buf->rand, rand_bytes_per_buf)) {
    225       OPENSSL_free(buf);
    226       abort();
    227       return 0;
    228     }
    229 
    230     buf->used = 0;
    231   }
    232 
    233   CRYPTO_w_lock(CRYPTO_LOCK_RAND);
    234   assert(list_head != buf);
    235   buf->next = list_head;
    236   list_head = buf;
    237   CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
    238   return 1;
    239 }
    240 
    241 #endif  /* !OPENSSL_WINDOWS */
    242