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