/src/libgcrypt/random/jitterentropy-base-user.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Non-physical true random number generator based on timing jitter. |
3 | | * |
4 | | * Copyright Stephan Mueller <smueller@chronox.de>, 2013 |
5 | | * |
6 | | * License |
7 | | * ======= |
8 | | * |
9 | | * Redistribution and use in source and binary forms, with or without |
10 | | * modification, are permitted provided that the following conditions |
11 | | * are met: |
12 | | * 1. Redistributions of source code must retain the above copyright |
13 | | * notice, and the entire permission notice in its entirety, |
14 | | * including the disclaimer of warranties. |
15 | | * 2. Redistributions in binary form must reproduce the above copyright |
16 | | * notice, this list of conditions and the following disclaimer in the |
17 | | * documentation and/or other materials provided with the distribution. |
18 | | * 3. The name of the author may not be used to endorse or promote |
19 | | * products derived from this software without specific prior |
20 | | * written permission. |
21 | | * |
22 | | * ALTERNATIVELY, this product may be distributed under the terms of |
23 | | * the GNU General Public License, in which case the provisions of the GPL are |
24 | | * required INSTEAD OF the above restrictions. (This clause is |
25 | | * necessary due to a potential bad interaction between the GPL and |
26 | | * the restrictions contained in a BSD-style copyright.) |
27 | | * |
28 | | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
29 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
30 | | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF |
31 | | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE |
32 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
33 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
34 | | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
35 | | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
36 | | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
37 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
38 | | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH |
39 | | * DAMAGE. |
40 | | */ |
41 | | |
42 | | #include <fcntl.h> |
43 | | #include <limits.h> |
44 | | |
45 | | #ifndef GCRYPT_JITTERENTROPY_BASE_USER_H |
46 | | #define GCRYPT_JITTERENTROPY_BASE_USER_H |
47 | | |
48 | | /* |
49 | | * This is Libgcrypt specific platform dependent code. We use a |
50 | | * separate file because jitterentropy.h expects such a file. |
51 | | */ |
52 | | |
53 | | #ifndef USE_JENT |
54 | | # error This file expects to be included from rndjent.c (via jitterentropy.h) |
55 | | #endif |
56 | | #ifndef HAVE_STDINT_H |
57 | | # error This module needs stdint.h - try ./configure --disable-jent-support |
58 | | #endif |
59 | | |
60 | | |
61 | | /* When using the libgcrypt secure memory mechanism, all precautions |
62 | | * are taken to protect our state. If the user disables secmem during |
63 | | * runtime, it is his decision and we thus try not to overrule his |
64 | | * decision for less memory protection. */ |
65 | | #define JENT_CPU_JITTERENTROPY_SECURE_MEMORY 1 |
66 | 0 | #define jent_zalloc(n) _gcry_calloc_secure (1, (n)) |
67 | | |
68 | | |
69 | | static void |
70 | | jent_get_nstime(u64 *out) |
71 | 0 | { |
72 | 0 | #if USE_JENT == JENT_USES_RDTSC |
73 | |
|
74 | 0 | u32 t_eax, t_edx; |
75 | |
|
76 | 0 | asm volatile (".byte 0x0f,0x31\n\t" |
77 | 0 | : "=a" (t_eax), "=d" (t_edx) |
78 | 0 | ); |
79 | 0 | *out = (((u64)t_edx << 32) | t_eax); |
80 | |
|
81 | | #elif USE_JENT == JENT_USES_GETTIME |
82 | | |
83 | | struct timespec tv; |
84 | | u64 tmp; |
85 | | |
86 | | /* On Linux we could use CLOCK_MONOTONIC(_RAW), but with |
87 | | * CLOCK_REALTIME we get some nice extra entropy once in a while |
88 | | * from the NTP actions that we want to use as well... though, we do |
89 | | * not rely on that extra little entropy. */ |
90 | | if (!clock_gettime (CLOCK_REALTIME, &tv)) |
91 | | { |
92 | | tmp = tv.tv_sec; |
93 | | tmp = tmp << 32; |
94 | | tmp = tmp | tv.tv_nsec; |
95 | | } |
96 | | else |
97 | | tmp = 0; |
98 | | *out = tmp; |
99 | | |
100 | | #elif USE_JENT == JENT_USES_READ_REAL_TIME |
101 | | |
102 | | /* clock_gettime() on AIX returns a timer value that increments in |
103 | | * steps of 1000. */ |
104 | | u64 tmp = 0; |
105 | | |
106 | | timebasestruct_t aixtime; |
107 | | read_real_time (&aixtime, TIMEBASE_SZ); |
108 | | tmp = aixtime.tb_high; |
109 | | tmp = tmp << 32; |
110 | | tmp = tmp | aixtime.tb_low; |
111 | | *out = tmp; |
112 | | |
113 | | #else |
114 | | # error No clock available in jent_get_nstime |
115 | | #endif |
116 | 0 | } |
117 | | |
118 | | |
119 | | static GPGRT_INLINE void |
120 | | jent_zfree (void *ptr, unsigned int len) |
121 | 0 | { |
122 | 0 | if (ptr) |
123 | 0 | { |
124 | 0 | wipememory (ptr, len); |
125 | 0 | _gcry_free (ptr); |
126 | 0 | } |
127 | 0 | } |
128 | | |
129 | | |
130 | | static GPGRT_INLINE int |
131 | | jent_fips_enabled(void) |
132 | 0 | { |
133 | 0 | return fips_mode(); |
134 | 0 | } |
135 | | |
136 | | |
137 | | static inline void jent_memset_secure(void *s, size_t n) |
138 | 0 | { |
139 | 0 | wipememory (s, n); |
140 | 0 | } |
141 | | |
142 | | static inline long jent_ncpu(void) |
143 | 0 | { |
144 | 0 | #if defined(_POSIX_SOURCE) |
145 | 0 | long ncpu = sysconf(_SC_NPROCESSORS_ONLN); |
146 | 0 |
|
147 | 0 | if (ncpu == -1) |
148 | 0 | return -errno; |
149 | 0 |
|
150 | 0 | if (ncpu == 0) |
151 | 0 | return -EFAULT; |
152 | 0 |
|
153 | 0 | return ncpu; |
154 | 0 | #elif defined(HAVE_W32_SYSTEM) |
155 | 0 | SYSTEM_INFO sysinfo; |
156 | 0 | long ncpu; |
157 | 0 |
|
158 | 0 | GetNativeSystemInfo (&sysinfo); |
159 | 0 | ncpu = sysinfo.dwNumberOfProcessors; |
160 | 0 | if (ncpu <= 0) { |
161 | 0 | GetSystemInfo (&sysinfo); |
162 | 0 | ncpu = sysinfo.dwNumberOfProcessors; |
163 | 0 | } |
164 | 0 | if (ncpu <= 0) |
165 | 0 | ncpu = 1; |
166 | 0 | return ncpu; |
167 | 0 | #else |
168 | 0 | return 1; |
169 | 0 | #endif |
170 | 0 | } |
171 | | |
172 | | #ifdef __linux__ |
173 | | |
174 | | # if defined(_SC_LEVEL1_DCACHE_SIZE) && \ |
175 | | defined(_SC_LEVEL2_CACHE_SIZE) && \ |
176 | | defined(_SC_LEVEL3_CACHE_SIZE) |
177 | | |
178 | | static inline void jent_get_cachesize(long *l1, long *l2, long *l3) |
179 | 0 | { |
180 | 0 | *l1 = sysconf(_SC_LEVEL1_DCACHE_SIZE); |
181 | 0 | *l2 = sysconf(_SC_LEVEL2_CACHE_SIZE); |
182 | 0 | *l3 = sysconf(_SC_LEVEL3_CACHE_SIZE); |
183 | 0 | } |
184 | | |
185 | | # else |
186 | | |
187 | | static inline void jent_get_cachesize(long *l1, long *l2, long *l3) |
188 | | { |
189 | | #define JENT_SYSFS_CACHE_DIR "/sys/devices/system/cpu/cpu0/cache" |
190 | | long val; |
191 | | unsigned int i; |
192 | | char buf[10], file[50]; |
193 | | int fd = 0; |
194 | | |
195 | | /* Iterate over all caches */ |
196 | | for (i = 0; i < 4; i++) { |
197 | | unsigned int shift = 0; |
198 | | char *ext; |
199 | | |
200 | | /* |
201 | | * Check the cache type - we are only interested in Unified |
202 | | * and Data caches. |
203 | | */ |
204 | | memset(buf, 0, sizeof(buf)); |
205 | | snprintf(file, sizeof(file), "%s/index%u/type", |
206 | | JENT_SYSFS_CACHE_DIR, i); |
207 | | fd = open(file, O_RDONLY); |
208 | | if (fd < 0) |
209 | | continue; |
210 | | while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR); |
211 | | close(fd); |
212 | | buf[sizeof(buf) - 1] = '\0'; |
213 | | |
214 | | if (strncmp(buf, "Data", 4) && strncmp(buf, "Unified", 7)) |
215 | | continue; |
216 | | |
217 | | /* Get size of cache */ |
218 | | memset(buf, 0, sizeof(buf)); |
219 | | snprintf(file, sizeof(file), "%s/index%u/size", |
220 | | JENT_SYSFS_CACHE_DIR, i); |
221 | | |
222 | | fd = open(file, O_RDONLY); |
223 | | if (fd < 0) |
224 | | continue; |
225 | | while (read(fd, buf, sizeof(buf)) < 0 && errno == EINTR); |
226 | | close(fd); |
227 | | buf[sizeof(buf) - 1] = '\0'; |
228 | | |
229 | | ext = strstr(buf, "K"); |
230 | | if (ext) { |
231 | | shift = 10; |
232 | | ext = '\0'; |
233 | | } else { |
234 | | ext = strstr(buf, "M"); |
235 | | if (ext) { |
236 | | shift = 20; |
237 | | ext = '\0'; |
238 | | } |
239 | | } |
240 | | |
241 | | val = strtol(buf, NULL, 10); |
242 | | if (val == LONG_MAX) |
243 | | continue; |
244 | | val <<= shift; |
245 | | |
246 | | if (!*l1) |
247 | | *l1 = val; |
248 | | else if (!*l2) |
249 | | *l2 = val; |
250 | | else { |
251 | | *l3 = val; |
252 | | break; |
253 | | } |
254 | | } |
255 | | #undef JENT_SYSFS_CACHE_DIR |
256 | | } |
257 | | |
258 | | # endif |
259 | | |
260 | | static inline uint32_t jent_cache_size_roundup(void) |
261 | 0 | { |
262 | 0 | static int checked = 0; |
263 | 0 | static uint32_t cache_size = 0; |
264 | |
|
265 | 0 | if (!checked) { |
266 | 0 | long l1 = 0, l2 = 0, l3 = 0; |
267 | |
|
268 | 0 | jent_get_cachesize(&l1, &l2, &l3); |
269 | 0 | checked = 1; |
270 | | |
271 | | /* Cache size reported by system */ |
272 | 0 | if (l1 > 0) |
273 | 0 | cache_size += (uint32_t)l1; |
274 | 0 | if (l2 > 0) |
275 | 0 | cache_size += (uint32_t)l2; |
276 | 0 | if (l3 > 0) |
277 | 0 | cache_size += (uint32_t)l3; |
278 | | |
279 | | /* |
280 | | * Force the output_size to be of the form |
281 | | * (bounding_power_of_2 - 1). |
282 | | */ |
283 | 0 | cache_size |= (cache_size >> 1); |
284 | 0 | cache_size |= (cache_size >> 2); |
285 | 0 | cache_size |= (cache_size >> 4); |
286 | 0 | cache_size |= (cache_size >> 8); |
287 | 0 | cache_size |= (cache_size >> 16); |
288 | |
|
289 | 0 | if (cache_size == 0) |
290 | 0 | return 0; |
291 | | |
292 | | /* |
293 | | * Make the output_size the smallest power of 2 strictly |
294 | | * greater than cache_size. |
295 | | */ |
296 | 0 | cache_size++; |
297 | 0 | } |
298 | | |
299 | 0 | return cache_size; |
300 | 0 | } |
301 | | |
302 | | #else /* __linux__ */ |
303 | | |
304 | | static inline uint32_t jent_cache_size_roundup(void) |
305 | | { |
306 | | return 0; |
307 | | } |
308 | | |
309 | | #endif /* __linux__ */ |
310 | | |
311 | | #ifdef JENT_CONF_ENABLE_INTERNAL_TIMER |
312 | | #include <sched.h> |
313 | | |
314 | | static inline void jent_yield(void) |
315 | | { |
316 | | sched_yield(); |
317 | | } |
318 | | #endif |
319 | | |
320 | | #endif /* GCRYPT_JITTERENTROPY_BASE_USER_H */ |