]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/rand/rand_unix.c
Add --with-rand-seed
[thirdparty/openssl.git] / crypto / rand / rand_unix.c
1 /*
2 * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11
12 #include "e_os.h"
13 #include "internal/cryptlib.h"
14 #include <openssl/rand.h>
15 #include "rand_lcl.h"
16 #include <stdio.h>
17
18 #if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI))
19
20 # if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
21 !defined(OPENSSL_RAND_SEED_NONE)
22 # error "UEFI and VXWorks only support seeding NONE"
23 # endif
24
25 # if defined(OPENSSL_SYS_VOS)
26
27 # ifndef OPENSSL_RAND_SEED_OS
28 # error "Unsupported seeding method configured; must be os"
29 # endif
30
31 # if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
32 # error "Unsupported HP-PA and IA32 at the same time."
33 # endif
34 # if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
35 # error "Must have one of HP-PA or IA32"
36 # endif
37
38 /*
39 * The following algorithm repeatedly samples the real-time clock (RTC) to
40 * generate a sequence of unpredictable data. The algorithm relies upon the
41 * uneven execution speed of the code (due to factors such as cache misses,
42 * interrupts, bus activity, and scheduling) and upon the rather large
43 * relative difference between the speed of the clock and the rate at which
44 * it can be read.
45 *
46 * If this code is ported to an environment where execution speed is more
47 * constant or where the RTC ticks at a much slower rate, or the clock can be
48 * read with fewer instructions, it is likely that the results would be far
49 * more predictable.
50 *
51 * As a precaution, we generate 4 times the minimum required amount of seed
52 * data.
53 */
54 int RAND_poll(void)
55 {
56 short int code;
57 gid_t curr_gid;
58 pid_t curr_pid;
59 uid_t curr_uid;
60 int i, k;
61 struct timespec ts;
62 unsigned char v;
63 # ifdef OPENSSL_SYS_VOS_HPPA
64 long duration;
65 extern void s$sleep(long *_duration, short int *_code);
66 # else
67 long long duration;
68 extern void s$sleep2(long long *_duration, short int *_code);
69 # endif
70
71 /*
72 * Seed with the gid, pid, and uid, to ensure *some* variation between
73 * different processes.
74 */
75 curr_gid = getgid();
76 RAND_add(&curr_gid, sizeof curr_gid, 0);
77 curr_pid = getpid();
78 RAND_add(&curr_pid, sizeof curr_pid, 0);
79 curr_uid = getuid();
80 RAND_add(&curr_uid, sizeof curr_uid, 0);
81
82 for (i = 0; i < (RANDOMNESS_NEEDED * 4); i++) {
83 /*
84 * burn some cpu; hope for interrupts, cache collisions, bus
85 * interference, etc.
86 */
87 for (k = 0; k < 99; k++)
88 ts.tv_nsec = random();
89
90 # ifdef OPENSSL_SYS_VOS_HPPA
91 /* sleep for 1/1024 of a second (976 us). */
92 duration = 1;
93 s$sleep(&duration, &code);
94 # else
95 /* sleep for 1/65536 of a second (15 us). */
96 duration = 1;
97 s$sleep2(&duration, &code);
98 # endif
99
100 /* Get wall clock time, take 8 bits. */
101 clock_gettime(CLOCK_REALTIME, &ts);
102 v = (unsigned char)(ts.tv_nsec & 0xFF);
103 RAND_add(&v, sizeof v, 1);
104 }
105 return 1;
106 }
107
108 # else
109
110 # if defined(OPENSSL_RAND_SEED_EGD) && \
111 (defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
112 # error "Seeding uses EGD but EGD is turned off or no device given"
113 # endif
114
115 # if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
116 # error "Seeding uses urandom but DEVRANDOM is not configured"
117 # endif
118
119 # if defined(OPENSSL_RAND_SEED_OS)
120 # if defined(DEVRANDOM)
121 # define OPENSSL_RAND_SEED_DEVRANDOM
122 # else
123 # error "OS seeding requires DEVRANDOM to be configured"
124 # endif
125 # endif
126
127 # if defined(OPENSSL_RAND_SEED_LIBRANDOM)
128 # error "librandom not (yet) supported"
129 # endif
130
131 int RAND_poll(void)
132 {
133 # ifdef OPENSSL_RAND_SEED_NONE
134 return 0;
135 # else
136 int ok = 0;
137 char temp[RANDOMNESS_NEEDED];
138 # define TEMPSIZE (int)sizeof(temp)
139
140 # ifdef OPENSSL_RAND_SEED_RDTSC
141 rand_rdtsc();
142 # endif
143
144 # ifdef OPENSSL_RAND_SEED_RDCPU
145 if (rand_rdcpu())
146 ok++;
147 # endif
148
149 # ifdef OPENSSL_RAND_SEED_EGD
150 {
151 static const char *paths[] = { DEVRANDOM_EGD, NULL };
152 int i;
153
154 for (i = 0; paths[i] != NULL; i++) {
155 if (RAND_query_egd_bytes(paths[i], temp, TEMPSIZE) == TEMPSIZE) {
156 RAND_add(temp, TEMPSIZE, TEMPSIZE);
157 ok++;
158 break;
159 }
160 }
161 }
162 # endif
163
164 # ifdef OPENSSL_RAND_SEED_DEVRANDOM
165 {
166 static const char *paths[] = { DEVRANDOM, NULL };
167 FILE *fp;
168 int i;
169
170 for (i = 0; paths[i] != NULL; i++) {
171 if ((fp = fopen(paths[i], "rb")) == NULL)
172 continue;
173 setbuf(fp, NULL);
174 if (fread(temp, 1, TEMPSIZE, fp) == TEMPSIZE) {
175 RAND_add(temp, TEMPSIZE, TEMPSIZE);
176 ok++;
177 fclose(fp);
178 break;
179 }
180 }
181 }
182 # endif
183
184 # ifdef OPENSSL_RAND_SEED_GETRANDOM
185 {
186 int i = getrandom(temp, TEMPSIZE, 0);
187
188 if (i >= 0) {
189 RAND_add(temp, i, i);
190 if (i == TEMPSIZE)
191 ok++;
192 }
193 }
194 # endif
195
196 OPENSSL_cleanse(temp, TEMPSIZE);
197 return ok > 0 ? 1 : 0;
198 # endif
199 }
200 # endif
201
202 #endif