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|. */
urandom_get_fd_locked(void)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. */
RAND_cleanup(void)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. */
read_full(int fd,uint8_t * out,size_t len)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|. */
CRYPTO_sysrand(uint8_t * out,size_t requested)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