getentropy_linux.c revision 356345
1/*	$OpenBSD: getentropy_linux.c,v 1.46 2018/11/20 08:04:28 deraadt Exp $	*/
2
3/*
4 * Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
5 * Copyright (c) 2014 Bob Beck <beck@obtuse.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * Emulation of getentropy(2) as documented at:
20 * http://man.openbsd.org/getentropy.2
21 */
22
23#include "config.h"
24/*
25#define	_POSIX_C_SOURCE	199309L
26#define	_GNU_SOURCE	1
27*/
28#include <sys/types.h>
29#include <sys/param.h>
30#include <sys/ioctl.h>
31#include <sys/resource.h>
32#include <sys/syscall.h>
33#ifdef SYS__sysctl
34#include <linux/sysctl.h>
35#endif
36#include <sys/statvfs.h>
37#include <sys/socket.h>
38#include <sys/mount.h>
39#include <sys/mman.h>
40#include <sys/stat.h>
41#include <sys/time.h>
42#include <stdlib.h>
43#include <stdint.h>
44#include <stdio.h>
45#include <link.h>
46#include <termios.h>
47#include <fcntl.h>
48#include <signal.h>
49#include <string.h>
50#include <errno.h>
51#include <unistd.h>
52#include <time.h>
53#ifndef HAVE_NETTLE
54#include <openssl/sha.h>
55#else
56#include <nettle/sha.h>
57#define SHA512_CTX		struct sha512_ctx
58#define SHA512_Init(x)		sha512_init(x)
59#define SHA512_Update(x, b, s)	sha512_update(x, s, b)
60#define SHA512_Final(r, c)	sha512_digest(c, SHA512_DIGEST_SIZE, r)
61#endif
62
63#include <linux/types.h>
64#include <linux/random.h>
65#ifdef HAVE_GETAUXVAL
66#include <sys/auxv.h>
67#endif
68#include <sys/vfs.h>
69#ifndef MAP_ANON
70#define MAP_ANON MAP_ANONYMOUS
71#endif
72
73#define REPEAT 5
74#define min(a, b) (((a) < (b)) ? (a) : (b))
75
76#define HX(a, b) \
77	do { \
78		if ((a)) \
79			HD(errno); \
80		else \
81			HD(b); \
82	} while (0)
83
84#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
85#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
86#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
87
88int	getentropy(void *buf, size_t len);
89
90#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
91static int getentropy_getrandom(void *buf, size_t len);
92#endif
93static int getentropy_urandom(void *buf, size_t len);
94#ifdef SYS__sysctl
95static int getentropy_sysctl(void *buf, size_t len);
96#endif
97static int getentropy_fallback(void *buf, size_t len);
98static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
99
100int
101getentropy(void *buf, size_t len)
102{
103	int ret = -1;
104
105	if (len > 256) {
106		errno = EIO;
107		return (-1);
108	}
109
110#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
111	/*
112	 * Try descriptor-less getrandom(), in non-blocking mode.
113	 *
114	 * The design of Linux getrandom is broken.  It has an
115	 * uninitialized phase coupled with blocking behaviour, which
116	 * is unacceptable from within a library at boot time without
117	 * possible recovery. See http://bugs.python.org/issue26839#msg267745
118	 */
119	ret = getentropy_getrandom(buf, len);
120	if (ret != -1)
121		return (ret);
122#endif
123
124	/*
125	 * Try to get entropy with /dev/urandom
126	 *
127	 * This can fail if the process is inside a chroot or if file
128	 * descriptors are exhausted.
129	 */
130	ret = getentropy_urandom(buf, len);
131	if (ret != -1)
132		return (ret);
133
134#ifdef SYS__sysctl
135	/*
136	 * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
137	 * sysctl is a failsafe API, so it guarantees a result.  This
138	 * should work inside a chroot, or when file descriptors are
139	 * exhausted.
140	 *
141	 * However this can fail if the Linux kernel removes support
142	 * for sysctl.  Starting in 2007, there have been efforts to
143	 * deprecate the sysctl API/ABI, and push callers towards use
144	 * of the chroot-unavailable fd-using /proc mechanism --
145	 * essentially the same problems as /dev/urandom.
146	 *
147	 * Numerous setbacks have been encountered in their deprecation
148	 * schedule, so as of June 2014 the kernel ABI still exists on
149	 * most Linux architectures. The sysctl() stub in libc is missing
150	 * on some systems.  There are also reports that some kernels
151	 * spew messages to the console.
152	 */
153	ret = getentropy_sysctl(buf, len);
154	if (ret != -1)
155		return (ret);
156#endif /* SYS__sysctl */
157
158	/*
159	 * Entropy collection via /dev/urandom and sysctl have failed.
160	 *
161	 * No other API exists for collecting entropy.  See the large
162	 * comment block above.
163	 *
164	 * We have very few options:
165	 *     - Even syslog_r is unsafe to call at this low level, so
166	 *	 there is no way to alert the user or program.
167	 *     - Cannot call abort() because some systems have unsafe
168	 *	 corefiles.
169	 *     - Could raise(SIGKILL) resulting in silent program termination.
170	 *     - Return EIO, to hint that arc4random's stir function
171	 *       should raise(SIGKILL)
172	 *     - Do the best under the circumstances....
173	 *
174	 * This code path exists to bring light to the issue that Linux
175	 * still does not provide a failsafe API for entropy collection.
176	 *
177	 * We hope this demonstrates that Linux should either retain their
178	 * sysctl ABI, or consider providing a new failsafe API which
179	 * works in a chroot or when file descriptors are exhausted.
180	 */
181#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
182#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
183	raise(SIGKILL);
184#endif
185	ret = getentropy_fallback(buf, len);
186	if (ret != -1)
187		return (ret);
188
189	errno = EIO;
190	return (ret);
191}
192
193#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
194static int
195getentropy_getrandom(void *buf, size_t len)
196{
197	int pre_errno = errno;
198	int ret;
199	if (len > 256)
200		return (-1);
201	do {
202		ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
203	} while (ret == -1 && errno == EINTR);
204
205	if (ret != (int)len)
206		return (-1);
207	errno = pre_errno;
208	return (0);
209}
210#endif
211
212static int
213getentropy_urandom(void *buf, size_t len)
214{
215	struct stat st;
216	size_t i;
217	int fd, cnt, flags;
218	int save_errno = errno;
219
220start:
221
222	flags = O_RDONLY;
223#ifdef O_NOFOLLOW
224	flags |= O_NOFOLLOW;
225#endif
226#ifdef O_CLOEXEC
227	flags |= O_CLOEXEC;
228#endif
229	fd = open("/dev/urandom", flags, 0);
230	if (fd == -1) {
231		if (errno == EINTR)
232			goto start;
233		goto nodevrandom;
234	}
235#ifndef O_CLOEXEC
236	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
237#endif
238
239	/* Lightly verify that the device node looks sane */
240	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
241		close(fd);
242		goto nodevrandom;
243	}
244	if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
245		close(fd);
246		goto nodevrandom;
247	}
248	for (i = 0; i < len; ) {
249		size_t wanted = len - i;
250		ssize_t ret = read(fd, (char *)buf + i, wanted);
251
252		if (ret == -1) {
253			if (errno == EAGAIN || errno == EINTR)
254				continue;
255			close(fd);
256			goto nodevrandom;
257		}
258		i += ret;
259	}
260	close(fd);
261	errno = save_errno;
262	return (0);		/* satisfied */
263nodevrandom:
264	errno = EIO;
265	return (-1);
266}
267
268#ifdef SYS__sysctl
269static int
270getentropy_sysctl(void *buf, size_t len)
271{
272	static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
273	size_t i;
274	int save_errno = errno;
275
276	for (i = 0; i < len; ) {
277		size_t chunk = min(len - i, 16);
278
279		/* SYS__sysctl because some systems already removed sysctl() */
280		struct __sysctl_args args = {
281			.name = mib,
282			.nlen = 3,
283			.oldval = (char *)buf + i,
284			.oldlenp = &chunk,
285		};
286		if (syscall(SYS__sysctl, &args) != 0)
287			goto sysctlfailed;
288		i += chunk;
289	}
290	errno = save_errno;
291	return (0);			/* satisfied */
292sysctlfailed:
293	errno = EIO;
294	return (-1);
295}
296#endif /* SYS__sysctl */
297
298static const int cl[] = {
299	CLOCK_REALTIME,
300#ifdef CLOCK_MONOTONIC
301	CLOCK_MONOTONIC,
302#endif
303#ifdef CLOCK_MONOTONIC_RAW
304	CLOCK_MONOTONIC_RAW,
305#endif
306#ifdef CLOCK_TAI
307	CLOCK_TAI,
308#endif
309#ifdef CLOCK_VIRTUAL
310	CLOCK_VIRTUAL,
311#endif
312#ifdef CLOCK_UPTIME
313	CLOCK_UPTIME,
314#endif
315#ifdef CLOCK_PROCESS_CPUTIME_ID
316	CLOCK_PROCESS_CPUTIME_ID,
317#endif
318#ifdef CLOCK_THREAD_CPUTIME_ID
319	CLOCK_THREAD_CPUTIME_ID,
320#endif
321};
322
323static int
324getentropy_phdr(struct dl_phdr_info *info, size_t ATTR_UNUSED(size), void *data)
325{
326	SHA512_CTX *ctx = data;
327
328	SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
329	return (0);
330}
331
332static int
333getentropy_fallback(void *buf, size_t len)
334{
335	uint8_t results[SHA512_DIGEST_LENGTH];
336	int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
337	static int cnt;
338	struct timespec ts;
339	struct timeval tv;
340	struct rusage ru;
341	sigset_t sigset;
342	struct stat st;
343	SHA512_CTX ctx;
344	static pid_t lastpid;
345	pid_t pid;
346	size_t i, ii, m;
347	char *p;
348
349	pid = getpid();
350	if (lastpid == pid) {
351		faster = 1;
352		repeat = 2;
353	} else {
354		faster = 0;
355		lastpid = pid;
356		repeat = REPEAT;
357	}
358	for (i = 0; i < len; ) {
359		int j;
360		SHA512_Init(&ctx);
361		for (j = 0; j < repeat; j++) {
362			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
363			if (e != -1) {
364				cnt += (int)tv.tv_sec;
365				cnt += (int)tv.tv_usec;
366			}
367
368			dl_iterate_phdr(getentropy_phdr, &ctx);
369
370			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
371				HX(clock_gettime(cl[ii], &ts) == -1, ts);
372
373			HX((pid = getpid()) == -1, pid);
374			HX((pid = getsid(pid)) == -1, pid);
375			HX((pid = getppid()) == -1, pid);
376			HX((pid = getpgid(0)) == -1, pid);
377			HX((e = getpriority(0, 0)) == -1, e);
378
379			if (!faster) {
380				ts.tv_sec = 0;
381				ts.tv_nsec = 1;
382				(void) nanosleep(&ts, NULL);
383			}
384
385			HX(sigpending(&sigset) == -1, sigset);
386			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
387			    sigset);
388
389			HF(getentropy);	/* an addr in this library */
390			HF(printf);		/* an addr in libc */
391			p = (char *)&p;
392			HD(p);		/* an addr on stack */
393			p = (char *)&errno;
394			HD(p);		/* the addr of errno */
395
396			if (i == 0) {
397				struct sockaddr_storage ss;
398				struct statvfs stvfs;
399				struct termios tios;
400				struct statfs stfs;
401				socklen_t ssl;
402				off_t off;
403
404				/*
405				 * Prime-sized mappings encourage fragmentation;
406				 * thus exposing some address entropy.
407				 */
408				struct mm {
409					size_t	npg;
410					void	*p;
411				} mm[] =	 {
412					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
413					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
414					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
415					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
416					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
417					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
418				};
419
420				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
421					HX(mm[m].p = mmap(NULL,
422					    mm[m].npg * pgs,
423					    PROT_READ|PROT_WRITE,
424					    MAP_PRIVATE|MAP_ANON, -1,
425					    (off_t)0), mm[m].p);
426					if (mm[m].p != MAP_FAILED) {
427						size_t mo;
428
429						/* Touch some memory... */
430						p = mm[m].p;
431						mo = cnt %
432						    (mm[m].npg * pgs - 1);
433						p[mo] = 1;
434						cnt += (int)((long)(mm[m].p)
435						    / pgs);
436					}
437
438					/* Check cnts and times... */
439					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
440					    ii++) {
441						HX((e = clock_gettime(cl[ii],
442						    &ts)) == -1, ts);
443						if (e != -1)
444							cnt += (int)ts.tv_nsec;
445					}
446
447					HX((e = getrusage(RUSAGE_SELF,
448					    &ru)) == -1, ru);
449					if (e != -1) {
450						cnt += (int)ru.ru_utime.tv_sec;
451						cnt += (int)ru.ru_utime.tv_usec;
452					}
453				}
454
455				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
456					if (mm[m].p != MAP_FAILED)
457						munmap(mm[m].p, mm[m].npg * pgs);
458					mm[m].p = MAP_FAILED;
459				}
460
461				HX(stat(".", &st) == -1, st);
462				HX(statvfs(".", &stvfs) == -1, stvfs);
463				HX(statfs(".", &stfs) == -1, stfs);
464
465				HX(stat("/", &st) == -1, st);
466				HX(statvfs("/", &stvfs) == -1, stvfs);
467				HX(statfs("/", &stfs) == -1, stfs);
468
469				HX((e = fstat(0, &st)) == -1, st);
470				if (e == -1) {
471					if (S_ISREG(st.st_mode) ||
472					    S_ISFIFO(st.st_mode) ||
473					    S_ISSOCK(st.st_mode)) {
474						HX(fstatvfs(0, &stvfs) == -1,
475						    stvfs);
476						HX(fstatfs(0, &stfs) == -1,
477						    stfs);
478						HX((off = lseek(0, (off_t)0,
479						    SEEK_CUR)) < 0, off);
480					}
481					if (S_ISCHR(st.st_mode)) {
482						HX(tcgetattr(0, &tios) == -1,
483						    tios);
484					} else if (S_ISSOCK(st.st_mode)) {
485						memset(&ss, 0, sizeof ss);
486						ssl = sizeof(ss);
487						HX(getpeername(0,
488						    (void *)&ss, &ssl) == -1,
489						    ss);
490					}
491				}
492
493				HX((e = getrusage(RUSAGE_CHILDREN,
494				    &ru)) == -1, ru);
495				if (e != -1) {
496					cnt += (int)ru.ru_utime.tv_sec;
497					cnt += (int)ru.ru_utime.tv_usec;
498				}
499			} else {
500				/* Subsequent hashes absorb previous result */
501				HD(results);
502			}
503
504			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
505			if (e != -1) {
506				cnt += (int)tv.tv_sec;
507				cnt += (int)tv.tv_usec;
508			}
509
510			HD(cnt);
511		}
512#ifdef HAVE_GETAUXVAL
513#ifdef AT_RANDOM
514		/* Not as random as you think but we take what we are given */
515		p = (char *) getauxval(AT_RANDOM);
516		if (p)
517			HR(p, 16);
518#endif
519#ifdef AT_SYSINFO_EHDR
520		p = (char *) getauxval(AT_SYSINFO_EHDR);
521		if (p)
522			HR(p, pgs);
523#endif
524#ifdef AT_BASE
525		p = (char *) getauxval(AT_BASE);
526		if (p)
527			HD(p);
528#endif
529#endif
530
531		SHA512_Final(results, &ctx);
532		memcpy((char *)buf + i, results, min(sizeof(results), len - i));
533		i += min(sizeof(results), len - i);
534	}
535	explicit_bzero(&ctx, sizeof ctx);
536	explicit_bzero(results, sizeof results);
537	errno = save_errno;
538	return (0);		/* satisfied */
539}
540