| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2018-02-27 21:37:28 +08:00
										 |  |  |  * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2001-01-08 18:59:26 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  |  * Licensed under the OpenSSL license (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							| 
									
										
										
										
											2001-01-08 18:59:26 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2016-05-18 02:52:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  | #define _GNU_SOURCE
 | 
					
						
							| 
									
										
										
										
											2002-06-21 01:32:04 +08:00
										 |  |  | #include "e_os.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-24 07:05:07 +08:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2015-05-14 22:56:48 +08:00
										 |  |  | #include "internal/cryptlib.h"
 | 
					
						
							| 
									
										
										
										
											2001-01-08 18:59:26 +08:00
										 |  |  | #include <openssl/rand.h>
 | 
					
						
							|  |  |  | #include "rand_lcl.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  | #include "internal/rand_int.h"
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  | #if defined(__linux)
 | 
					
						
							|  |  |  | # include <sys/syscall.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if defined(__FreeBSD__)
 | 
					
						
							|  |  |  | # include <sys/types.h>
 | 
					
						
							|  |  |  | # include <sys/sysctl.h>
 | 
					
						
							|  |  |  | # include <sys/param.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if defined(__OpenBSD__)
 | 
					
						
							|  |  |  | # include <sys/param.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-04-10 16:22:52 +08:00
										 |  |  | #ifdef OPENSSL_SYS_UNIX
 | 
					
						
							|  |  |  | # include <sys/types.h>
 | 
					
						
							|  |  |  | # include <unistd.h>
 | 
					
						
							|  |  |  | # include <sys/time.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint64_t get_time_stamp(void); | 
					
						
							|  |  |  | static uint64_t get_timer_bits(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Macro to convert two thirty two bit values into a sixty four bit one */ | 
					
						
							|  |  |  | # define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Check for the existence and support of POSIX timers.  The standard | 
					
						
							|  |  |  |  * says that the _POSIX_TIMERS macro will have a positive value if they | 
					
						
							|  |  |  |  * are available. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * However, we want an additional constraint: that the timer support does | 
					
						
							|  |  |  |  * not require an extra library dependency.  Early versions of glibc | 
					
						
							|  |  |  |  * require -lrt to be specified on the link line to access the timers, | 
					
						
							|  |  |  |  * so this needs to be checked for. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * It is worse because some libraries define __GLIBC__ but don't | 
					
						
							|  |  |  |  * support the version testing macro (e.g. uClibc).  This means | 
					
						
							|  |  |  |  * an extra check is needed. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The final condition is: | 
					
						
							|  |  |  |  *      "have posix timers and either not glibc or glibc without -lrt" | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The nested #if sequences are required to avoid using a parameterised | 
					
						
							|  |  |  |  * macro that might be undefined. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | # undef OSSL_POSIX_TIMER_OKAY
 | 
					
						
							|  |  |  | # if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
 | 
					
						
							|  |  |  | #  if defined(__GLIBC__)
 | 
					
						
							|  |  |  | #   if defined(__GLIBC_PREREQ)
 | 
					
						
							|  |  |  | #    if __GLIBC_PREREQ(2, 17)
 | 
					
						
							|  |  |  | #     define OSSL_POSIX_TIMER_OKAY
 | 
					
						
							|  |  |  | #    endif
 | 
					
						
							|  |  |  | #   endif
 | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  | #   define OSSL_POSIX_TIMER_OKAY
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2001-01-08 18:59:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  | int syscall_random(void *buf, size_t buflen); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  | #if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |         !defined(OPENSSL_RAND_SEED_NONE) | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  | # error "UEFI and VXWorks only support seeding NONE"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
 | 
					
						
							|  |  |  |     || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \ | 
					
						
							|  |  |  |     || defined(OPENSSL_SYS_UEFI)) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | # if defined(OPENSSL_SYS_VOS)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  ifndef OPENSSL_RAND_SEED_OS
 | 
					
						
							|  |  |  | #   error "Unsupported seeding method configured; must be os"
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
 | 
					
						
							|  |  |  | #   error "Unsupported HP-PA and IA32 at the same time."
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | #  if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
 | 
					
						
							|  |  |  | #   error "Must have one of HP-PA or IA32"
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * The following algorithm repeatedly samples the real-time clock (RTC) to | 
					
						
							|  |  |  |  * generate a sequence of unpredictable data.  The algorithm relies upon the | 
					
						
							|  |  |  |  * uneven execution speed of the code (due to factors such as cache misses, | 
					
						
							|  |  |  |  * interrupts, bus activity, and scheduling) and upon the rather large | 
					
						
							|  |  |  |  * relative difference between the speed of the clock and the rate at which | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |  * it can be read.  If it is ported to an environment where execution speed | 
					
						
							|  |  |  |  * is more constant or where the RTC ticks at a much slower rate, or the | 
					
						
							|  |  |  |  * clock can be read with fewer instructions, it is likely that the results | 
					
						
							|  |  |  |  * would be far more predictable.  This should only be used for legacy | 
					
						
							|  |  |  |  * platforms. | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |  * As a precaution, we assume only 2 bits of entropy per byte. | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  | size_t rand_pool_acquire_entropy(RAND_POOL *pool) | 
					
						
							| 
									
										
										
										
											2009-04-08 00:33:26 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     short int code; | 
					
						
							|  |  |  |     int i, k; | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     size_t bytes_needed; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     struct timespec ts; | 
					
						
							|  |  |  |     unsigned char v; | 
					
						
							|  |  |  | #  ifdef OPENSSL_SYS_VOS_HPPA
 | 
					
						
							|  |  |  |     long duration; | 
					
						
							|  |  |  |     extern void s$sleep(long *_duration, short int *_code); | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  |     long long duration; | 
					
						
							|  |  |  |     extern void s$sleep2(long long *_duration, short int *_code); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |     bytes_needed = rand_pool_bytes_needed(pool, 2 /*entropy_per_byte*/); | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < bytes_needed; i++) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * burn some cpu; hope for interrupts, cache collisions, bus | 
					
						
							|  |  |  |          * interference, etc. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         for (k = 0; k < 99; k++) | 
					
						
							|  |  |  |             ts.tv_nsec = random(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  ifdef OPENSSL_SYS_VOS_HPPA
 | 
					
						
							|  |  |  |         /* sleep for 1/1024 of a second (976 us).  */ | 
					
						
							|  |  |  |         duration = 1; | 
					
						
							|  |  |  |         s$sleep(&duration, &code); | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  |         /* sleep for 1/65536 of a second (15 us).  */ | 
					
						
							|  |  |  |         duration = 1; | 
					
						
							|  |  |  |         s$sleep2(&duration, &code); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |         /* Get wall clock time, take 8 bits. */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         clock_gettime(CLOCK_REALTIME, &ts); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |         v = (unsigned char)(ts.tv_nsec & 0xFF); | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |         rand_pool_add(pool, arg, &v, sizeof(v) , 2); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |     return rand_pool_entropy_available(pool); | 
					
						
							| 
									
										
										
										
											2009-04-08 00:33:26 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-15 01:53:01 +08:00
										 |  |  | # else
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #  if defined(OPENSSL_RAND_SEED_EGD) && \
 | 
					
						
							|  |  |  |         (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD)) | 
					
						
							|  |  |  | #   error "Seeding uses EGD but EGD is turned off or no device given"
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
 | 
					
						
							|  |  |  | #   error "Seeding uses urandom but DEVRANDOM is not configured"
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  | #  if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
 | 
					
						
							|  |  |  | #   if __GLIBC_PREREQ(2, 25)
 | 
					
						
							|  |  |  | #    define OPENSSL_HAVE_GETRANDOM
 | 
					
						
							|  |  |  | #   endif
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  if (defined(__FreeBSD__) && __FreeBSD_version >= 1200061)
 | 
					
						
							|  |  |  | #   define OPENSSL_HAVE_GETRANDOM
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  if defined(OPENSSL_HAVE_GETRANDOM)
 | 
					
						
							|  |  |  | #   include <sys/random.h>
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  if defined(OPENSSL_RAND_SEED_OS)
 | 
					
						
							| 
									
										
										
										
											2018-02-10 07:30:29 +08:00
										 |  |  | #   if !defined(DEVRANDOM)
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #    error "OS seeding requires DEVRANDOM to be configured"
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #   endif
 | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  | #   define OPENSSL_RAND_SEED_GETRANDOM
 | 
					
						
							| 
									
										
										
										
											2018-02-10 07:30:29 +08:00
										 |  |  | #   define OPENSSL_RAND_SEED_DEVRANDOM
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  if defined(OPENSSL_RAND_SEED_LIBRANDOM)
 | 
					
						
							|  |  |  | #   error "librandom not (yet) supported"
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  | #  if defined(__FreeBSD__) && defined(KERN_ARND)
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * sysctl_random(): Use sysctl() to read a random number from the kernel | 
					
						
							|  |  |  |  * Returns the size on success, 0 on failure. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static size_t sysctl_random(char *buf, size_t buflen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int mib[2]; | 
					
						
							|  |  |  |     size_t done = 0; | 
					
						
							|  |  |  |     size_t len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Old implementations returned longs, newer versions support variable | 
					
						
							|  |  |  |      * sizes up to 256 byte. The code below would not work properly when | 
					
						
							|  |  |  |      * the sysctl returns long and we want to request something not a multiple | 
					
						
							|  |  |  |      * of longs, which should never be the case. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2018-04-23 04:04:25 +08:00
										 |  |  |     if (!ossl_assert(buflen % sizeof(long) == 0)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     mib[0] = CTL_KERN; | 
					
						
							|  |  |  |     mib[1] = KERN_ARND; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         len = buflen; | 
					
						
							|  |  |  |         if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) | 
					
						
							|  |  |  |             return done; | 
					
						
							|  |  |  |         done += len; | 
					
						
							|  |  |  |         buf += len; | 
					
						
							|  |  |  |         buflen -= len; | 
					
						
							|  |  |  |     } while (buflen > 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return done; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * syscall_random(): Try to get random data using a system call | 
					
						
							|  |  |  |  * returns the number of bytes returned in buf, or <= 0 on error. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | int syscall_random(void *buf, size_t buflen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #  if defined(OPENSSL_HAVE_GETRANDOM)
 | 
					
						
							|  |  |  |     return (int)getrandom(buf, buflen, 0); | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  if defined(__linux) && defined(SYS_getrandom)
 | 
					
						
							|  |  |  |     return (int)syscall(SYS_getrandom, buf, buflen, 0); | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  if defined(__FreeBSD__) && defined(KERN_ARND)
 | 
					
						
							|  |  |  |     return (int)sysctl_random(buf, buflen); | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* Supported since OpenBSD 5.6 */ | 
					
						
							|  |  |  | #  if defined(__OpenBSD__) && OpenBSD >= 201411
 | 
					
						
							|  |  |  |     return getentropy(buf, buflen); | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |  * Try the various seeding methods in turn, exit when successful. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * TODO(DRBG): If more than one entropy source is available, is it | 
					
						
							|  |  |  |  * preferable to stop as soon as enough entropy has been collected | 
					
						
							|  |  |  |  * (as favored by @rsalz) or should one rather be defensive and add | 
					
						
							|  |  |  |  * more entropy than requested and/or from different sources? | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Currently, the user can select multiple entropy sources in the | 
					
						
							|  |  |  |  * configure step, yet in practice only the first available source | 
					
						
							|  |  |  |  * will be used. A more flexible solution has been requested, but | 
					
						
							|  |  |  |  * currently it is not clear how this can be achieved without | 
					
						
							|  |  |  |  * overengineering the problem. There are many parameters which | 
					
						
							|  |  |  |  * could be taken into account when selecting the order and amount | 
					
						
							|  |  |  |  * of input from the different entropy sources (trust, quality, | 
					
						
							|  |  |  |  * possibility of blocking). | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  | size_t rand_pool_acquire_entropy(RAND_POOL *pool) | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | { | 
					
						
							|  |  |  | #  ifdef OPENSSL_RAND_SEED_NONE
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |     return rand_pool_entropy_available(pool); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #  else
 | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     size_t bytes_needed; | 
					
						
							|  |  |  |     size_t entropy_available = 0; | 
					
						
							|  |  |  |     unsigned char *buffer; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  | #   ifdef OPENSSL_RAND_SEED_GETRANDOM
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |     bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/); | 
					
						
							|  |  |  |     buffer = rand_pool_add_begin(pool, bytes_needed); | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     if (buffer != NULL) { | 
					
						
							|  |  |  |         size_t bytes = 0; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-09 02:20:25 +08:00
										 |  |  |         if (syscall_random(buffer, bytes_needed) == (int)bytes_needed) | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |             bytes = bytes_needed; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-05 00:31:50 +08:00
										 |  |  |         rand_pool_add_end(pool, bytes, 8 * bytes); | 
					
						
							|  |  |  |         entropy_available = rand_pool_entropy_available(pool); | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     if (entropy_available > 0) | 
					
						
							|  |  |  |         return entropy_available; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #   endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  | #   if defined(OPENSSL_RAND_SEED_LIBRANDOM)
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |         /* Not yet implemented. */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #   endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #   ifdef OPENSSL_RAND_SEED_DEVRANDOM
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |     bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/); | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     if (bytes_needed > 0) { | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |         static const char *paths[] = { DEVRANDOM, NULL }; | 
					
						
							|  |  |  |         FILE *fp; | 
					
						
							|  |  |  |         int i; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |         for (i = 0; paths[i] != NULL; i++) { | 
					
						
							|  |  |  |             if ((fp = fopen(paths[i], "rb")) == NULL) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             setbuf(fp, NULL); | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |             buffer = rand_pool_add_begin(pool, bytes_needed); | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |             if (buffer != NULL) { | 
					
						
							|  |  |  |                 size_t bytes = 0; | 
					
						
							|  |  |  |                 if (fread(buffer, 1, bytes_needed, fp) == bytes_needed) | 
					
						
							|  |  |  |                     bytes = bytes_needed; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-05 00:31:50 +08:00
										 |  |  |                 rand_pool_add_end(pool, bytes, 8 * bytes); | 
					
						
							|  |  |  |                 entropy_available = rand_pool_entropy_available(pool); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |             fclose(fp); | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |             if (entropy_available > 0) | 
					
						
							|  |  |  |                 return entropy_available; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |             bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/); | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | #   endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  | #   ifdef OPENSSL_RAND_SEED_RDTSC
 | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     entropy_available = rand_acquire_entropy_from_tsc(pool); | 
					
						
							|  |  |  |     if (entropy_available > 0) | 
					
						
							|  |  |  |         return entropy_available; | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  | #   endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #   ifdef OPENSSL_RAND_SEED_RDCPU
 | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     entropy_available = rand_acquire_entropy_from_cpu(pool); | 
					
						
							|  |  |  |     if (entropy_available > 0) | 
					
						
							|  |  |  |         return entropy_available; | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  | #   endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #   ifdef OPENSSL_RAND_SEED_EGD
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |     bytes_needed = rand_pool_bytes_needed(pool, 8 /*entropy_per_byte*/); | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |     if (bytes_needed > 0) { | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |         static const char *paths[] = { DEVRANDOM_EGD, NULL }; | 
					
						
							|  |  |  |         int i; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |         for (i = 0; paths[i] != NULL; i++) { | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |             buffer = rand_pool_add_begin(pool, bytes_needed); | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |             if (buffer != NULL) { | 
					
						
							|  |  |  |                 size_t bytes = 0; | 
					
						
							|  |  |  |                 int num = RAND_query_egd_bytes(paths[i], | 
					
						
							|  |  |  |                                                buffer, (int)bytes_needed); | 
					
						
							|  |  |  |                 if (num == (int)bytes_needed) | 
					
						
							|  |  |  |                     bytes = bytes_needed; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-05 00:31:50 +08:00
										 |  |  |                 rand_pool_add_end(pool, bytes, 8 * bytes); | 
					
						
							|  |  |  |                 entropy_available = rand_pool_entropy_available(pool); | 
					
						
							| 
									
										
										
										
											2017-08-03 21:23:28 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-09-01 05:16:22 +08:00
										 |  |  |             if (entropy_available > 0) | 
					
						
							|  |  |  |                 return entropy_available; | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #   endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 06:45:44 +08:00
										 |  |  |     return rand_pool_entropy_available(pool); | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2001-01-08 18:59:26 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-07-18 21:39:21 +08:00
										 |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2018-04-10 16:22:52 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef OPENSSL_SYS_UNIX
 | 
					
						
							|  |  |  | int rand_pool_add_nonce_data(RAND_POOL *pool) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct { | 
					
						
							|  |  |  |         pid_t pid; | 
					
						
							|  |  |  |         CRYPTO_THREAD_ID tid; | 
					
						
							|  |  |  |         uint64_t time; | 
					
						
							|  |  |  |     } data = { 0 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Add process id, thread id, and a high resolution timestamp to | 
					
						
							|  |  |  |      * ensure that the nonce is unique whith high probability for | 
					
						
							|  |  |  |      * different process instances. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     data.pid = getpid(); | 
					
						
							|  |  |  |     data.tid = CRYPTO_THREAD_get_current_id(); | 
					
						
							|  |  |  |     data.time = get_time_stamp(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int rand_pool_add_additional_data(RAND_POOL *pool) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     struct { | 
					
						
							|  |  |  |         CRYPTO_THREAD_ID tid; | 
					
						
							|  |  |  |         uint64_t time; | 
					
						
							|  |  |  |     } data = { 0 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Add some noise from the thread id and a high resolution timer. | 
					
						
							|  |  |  |      * The thread id adds a little randomness if the drbg is accessed | 
					
						
							|  |  |  |      * concurrently (which is the case for the <master> drbg). | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     data.tid = CRYPTO_THREAD_get_current_id(); | 
					
						
							|  |  |  |     data.time = get_timer_bits(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Get the current time with the highest possible resolution | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The time stamp is added to the nonce, so it is optimized for not repeating. | 
					
						
							|  |  |  |  * The current time is ideal for this purpose, provided the computer's clock | 
					
						
							|  |  |  |  * is synchronized. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static uint64_t get_time_stamp(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | # if defined(OSSL_POSIX_TIMER_OKAY)
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         struct timespec ts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (clock_gettime(CLOCK_REALTIME, &ts) == 0) | 
					
						
							|  |  |  |             return TWO32TO64(ts.tv_sec, ts.tv_nsec); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  | # if defined(__unix__) \
 | 
					
						
							|  |  |  |      || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         struct timeval tv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (gettimeofday(&tv, NULL) == 0) | 
					
						
							|  |  |  |             return TWO32TO64(tv.tv_sec, tv.tv_usec); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  |     return time(NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Get an arbitrary timer value of the highest possible resolution | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The timer value is added as random noise to the additional data, | 
					
						
							|  |  |  |  * which is not considered a trusted entropy sourec, so any result | 
					
						
							|  |  |  |  * is acceptable. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static uint64_t get_timer_bits(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint64_t res = OPENSSL_rdtsc(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (res != 0) | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # if defined(__sun) || defined(__hpux)
 | 
					
						
							|  |  |  |     return gethrtime(); | 
					
						
							|  |  |  | # elif defined(_AIX)
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         timebasestruct_t t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         read_wall_time(&t, TIMEBASE_SZ); | 
					
						
							|  |  |  |         return TWO32TO64(t.tb_high, t.tb_low); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # elif defined(OSSL_POSIX_TIMER_OKAY)
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         struct timespec ts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  ifdef CLOCK_BOOTTIME
 | 
					
						
							|  |  |  | #   define CLOCK_TYPE CLOCK_BOOTTIME
 | 
					
						
							|  |  |  | #  elif defined(_POSIX_MONOTONIC_CLOCK)
 | 
					
						
							|  |  |  | #   define CLOCK_TYPE CLOCK_MONOTONIC
 | 
					
						
							|  |  |  | #  else
 | 
					
						
							|  |  |  | #   define CLOCK_TYPE CLOCK_REALTIME
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (clock_gettime(CLOCK_TYPE, &ts) == 0) | 
					
						
							|  |  |  |             return TWO32TO64(ts.tv_sec, ts.tv_nsec); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  | # if defined(__unix__) \
 | 
					
						
							|  |  |  |      || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         struct timeval tv; | 
					
						
							| 
									
										
										
										
											2001-01-08 18:59:26 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 16:22:52 +08:00
										 |  |  |         if (gettimeofday(&tv, NULL) == 0) | 
					
						
							|  |  |  |             return TWO32TO64(tv.tv_sec, tv.tv_usec); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  |     return time(NULL); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-14 17:44:57 +08:00
										 |  |  | #endif
 |