/src/libgcrypt/random/jitterentropy-noise.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Jitter RNG: Noise Sources |
2 | | * |
3 | | * Copyright (C) 2021, Stephan Mueller <smueller@chronox.de> |
4 | | * |
5 | | * License: see LICENSE file in root directory |
6 | | * |
7 | | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED |
8 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
9 | | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF |
10 | | * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE |
11 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
12 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
13 | | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
14 | | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
15 | | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
16 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
17 | | * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH |
18 | | * DAMAGE. |
19 | | */ |
20 | | |
21 | | #include "jitterentropy-noise.h" |
22 | | #include "jitterentropy-health.h" |
23 | | #include "jitterentropy-timer.h" |
24 | | #include "jitterentropy-sha3.h" |
25 | | |
26 | 0 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) |
27 | | |
28 | | /*************************************************************************** |
29 | | * Noise sources |
30 | | ***************************************************************************/ |
31 | | |
32 | | /** |
33 | | * Update of the loop count used for the next round of |
34 | | * an entropy collection. |
35 | | * |
36 | | * @ec [in] entropy collector struct -- may be NULL |
37 | | * @bits [in] is the number of low bits of the timer to consider |
38 | | * @min [in] is the number of bits we shift the timer value to the right at |
39 | | * the end to make sure we have a guaranteed minimum value |
40 | | * |
41 | | * @return Newly calculated loop counter |
42 | | */ |
43 | | static uint64_t jent_loop_shuffle(struct rand_data *ec, |
44 | | unsigned int bits, unsigned int min) |
45 | 0 | { |
46 | 0 | #ifdef JENT_CONF_DISABLE_LOOP_SHUFFLE |
47 | |
|
48 | 0 | (void)ec; |
49 | 0 | (void)bits; |
50 | |
|
51 | 0 | return (UINT64_C(1)<<min); |
52 | |
|
53 | | #else /* JENT_CONF_DISABLE_LOOP_SHUFFLE */ |
54 | | |
55 | | uint64_t time = 0; |
56 | | uint64_t shuffle = 0; |
57 | | uint64_t mask = (UINT64_C(1)<<bits) - 1; |
58 | | unsigned int i = 0; |
59 | | |
60 | | /* |
61 | | * Mix the current state of the random number into the shuffle |
62 | | * calculation to balance that shuffle a bit more. |
63 | | */ |
64 | | if (ec) { |
65 | | jent_get_nstime_internal(ec, &time); |
66 | | time ^= ec->data[0]; |
67 | | } |
68 | | |
69 | | /* |
70 | | * We fold the time value as much as possible to ensure that as many |
71 | | * bits of the time stamp are included as possible. |
72 | | */ |
73 | | for (i = 0; ((DATA_SIZE_BITS + bits - 1) / bits) > i; i++) { |
74 | | shuffle ^= time & mask; |
75 | | time = time >> bits; |
76 | | } |
77 | | |
78 | | /* |
79 | | * We add a lower boundary value to ensure we have a minimum |
80 | | * RNG loop count. |
81 | | */ |
82 | | return (shuffle + (UINT64_C(1)<<min)); |
83 | | |
84 | | #endif /* JENT_CONF_DISABLE_LOOP_SHUFFLE */ |
85 | 0 | } |
86 | | |
87 | | /** |
88 | | * CPU Jitter noise source -- this is the noise source based on the CPU |
89 | | * execution time jitter |
90 | | * |
91 | | * This function injects the individual bits of the time value into the |
92 | | * entropy pool using a hash. |
93 | | * |
94 | | * @ec [in] entropy collector struct -- may be NULL |
95 | | * @time [in] time stamp to be injected |
96 | | * @loop_cnt [in] if a value not equal to 0 is set, use the given value as |
97 | | * number of loops to perform the hash operation |
98 | | * @stuck [in] Is the time stamp identified as stuck? |
99 | | * |
100 | | * Output: |
101 | | * updated hash context |
102 | | */ |
103 | | static void jent_hash_time(struct rand_data *ec, uint64_t time, |
104 | | uint64_t loop_cnt, unsigned int stuck) |
105 | 0 | { |
106 | 0 | HASH_CTX_ON_STACK(ctx); |
107 | 0 | uint8_t itermediary[SHA3_256_SIZE_DIGEST]; |
108 | 0 | uint64_t j = 0; |
109 | 0 | uint64_t hash_loop_cnt; |
110 | 0 | #define MAX_HASH_LOOP 3 |
111 | 0 | #define MIN_HASH_LOOP 0 |
112 | | |
113 | | /* Ensure that macros cannot overflow jent_loop_shuffle() */ |
114 | 0 | BUILD_BUG_ON((MAX_HASH_LOOP + MIN_HASH_LOOP) > 63); |
115 | 0 | hash_loop_cnt = |
116 | 0 | jent_loop_shuffle(ec, MAX_HASH_LOOP, MIN_HASH_LOOP); |
117 | |
|
118 | 0 | sha3_256_init(&ctx); |
119 | | |
120 | | /* |
121 | | * testing purposes -- allow test app to set the counter, not |
122 | | * needed during runtime |
123 | | */ |
124 | 0 | if (loop_cnt) |
125 | 0 | hash_loop_cnt = loop_cnt; |
126 | | |
127 | | /* |
128 | | * This loop basically slows down the SHA-3 operation depending |
129 | | * on the hash_loop_cnt. Each iteration of the loop generates the |
130 | | * same result. |
131 | | */ |
132 | 0 | for (j = 0; j < hash_loop_cnt; j++) { |
133 | 0 | sha3_update(&ctx, ec->data, SHA3_256_SIZE_DIGEST); |
134 | 0 | sha3_update(&ctx, (uint8_t *)&time, sizeof(uint64_t)); |
135 | 0 | sha3_update(&ctx, (uint8_t *)&j, sizeof(uint64_t)); |
136 | | |
137 | | /* |
138 | | * If the time stamp is stuck, do not finally insert the value |
139 | | * into the entropy pool. Although this operation should not do |
140 | | * any harm even when the time stamp has no entropy, SP800-90B |
141 | | * requires that any conditioning operation to have an identical |
142 | | * amount of input data according to section 3.1.5. |
143 | | */ |
144 | | |
145 | | /* |
146 | | * The sha3_final operations re-initialize the context for the |
147 | | * next loop iteration. |
148 | | */ |
149 | 0 | if (stuck || (j < hash_loop_cnt - 1)) |
150 | 0 | sha3_final(&ctx, itermediary); |
151 | 0 | else |
152 | 0 | sha3_final(&ctx, ec->data); |
153 | 0 | } |
154 | |
|
155 | 0 | jent_memset_secure(&ctx, SHA_MAX_CTX_SIZE); |
156 | 0 | jent_memset_secure(itermediary, sizeof(itermediary)); |
157 | 0 | } |
158 | | |
159 | 0 | #define MAX_ACC_LOOP_BIT 7 |
160 | 0 | #define MIN_ACC_LOOP_BIT 0 |
161 | | #ifdef JENT_RANDOM_MEMACCESS |
162 | | |
163 | | static inline uint32_t uint32rotl(const uint32_t x, int k) |
164 | 0 | { |
165 | 0 | return (x << k) | (x >> (32 - k)); |
166 | 0 | } |
167 | | |
168 | | static inline uint32_t xoshiro128starstar(uint32_t *s) |
169 | 0 | { |
170 | 0 | const uint32_t result = uint32rotl(s[1] * 5, 7) * 9; |
171 | 0 | const uint32_t t = s[1] << 9; |
172 | |
|
173 | 0 | s[2] ^= s[0]; |
174 | 0 | s[3] ^= s[1]; |
175 | 0 | s[1] ^= s[2]; |
176 | 0 | s[0] ^= s[3]; |
177 | |
|
178 | 0 | s[2] ^= t; |
179 | |
|
180 | 0 | s[3] = uint32rotl(s[3], 11); |
181 | |
|
182 | 0 | return result; |
183 | 0 | } |
184 | | |
185 | | static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt) |
186 | 0 | { |
187 | 0 | uint64_t i = 0; |
188 | 0 | union { |
189 | 0 | uint32_t u[4]; |
190 | 0 | uint8_t b[sizeof(uint32_t) * 4]; |
191 | 0 | } prngState = { .u = {0x8e93eec0, 0xce65608a, 0xa8d46b46, 0xe83cef69} }; |
192 | 0 | uint32_t addressMask; |
193 | 0 | uint64_t acc_loop_cnt; |
194 | |
|
195 | 0 | if (NULL == ec || NULL == ec->mem) |
196 | 0 | return; |
197 | | |
198 | 0 | addressMask = ec->memmask; |
199 | | |
200 | | /* Ensure that macros cannot overflow jent_loop_shuffle() */ |
201 | 0 | BUILD_BUG_ON((MAX_ACC_LOOP_BIT + MIN_ACC_LOOP_BIT) > 63); |
202 | 0 | acc_loop_cnt = |
203 | 0 | jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); |
204 | | |
205 | | /* |
206 | | * Mix the current data into prngState |
207 | | * |
208 | | * Any time you see a PRNG in a noise source, you should be concerned. |
209 | | * |
210 | | * The PRNG doesn't directly produce the raw noise, it just adjusts the |
211 | | * location being updated. The timing of the update is part of the raw |
212 | | * sample. The main thing this process gets you isn't better |
213 | | * "per-update: timing, it gets you mostly independent "per-update" |
214 | | * timing, so we can now benefit from the Central Limit Theorem! |
215 | | */ |
216 | 0 | for (i = 0; i < sizeof(prngState); i++) |
217 | 0 | prngState.b[i] ^= ec->data[i]; |
218 | | |
219 | | /* |
220 | | * testing purposes -- allow test app to set the counter, not |
221 | | * needed during runtime |
222 | | */ |
223 | 0 | if (loop_cnt) |
224 | 0 | acc_loop_cnt = loop_cnt; |
225 | |
|
226 | 0 | for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) { |
227 | | /* Take PRNG output to find the memory location to update. */ |
228 | 0 | unsigned char *tmpval = ec->mem + |
229 | 0 | (xoshiro128starstar(prngState.u) & |
230 | 0 | addressMask); |
231 | | |
232 | | /* |
233 | | * memory access: just add 1 to one byte, |
234 | | * wrap at 255 -- memory access implies read |
235 | | * from and write to memory location |
236 | | */ |
237 | 0 | *tmpval = (unsigned char)((*tmpval + 1) & 0xff); |
238 | 0 | } |
239 | 0 | } |
240 | | |
241 | | #else /* JENT_RANDOM_MEMACCESS */ |
242 | | |
243 | | /** |
244 | | * Memory Access noise source -- this is a noise source based on variations in |
245 | | * memory access times |
246 | | * |
247 | | * This function performs memory accesses which will add to the timing |
248 | | * variations due to an unknown amount of CPU wait states that need to be |
249 | | * added when accessing memory. The memory size should be larger than the L1 |
250 | | * caches as outlined in the documentation and the associated testing. |
251 | | * |
252 | | * The L1 cache has a very high bandwidth, albeit its access rate is usually |
253 | | * slower than accessing CPU registers. Therefore, L1 accesses only add minimal |
254 | | * variations as the CPU has hardly to wait. Starting with L2, significant |
255 | | * variations are added because L2 typically does not belong to the CPU any more |
256 | | * and therefore a wider range of CPU wait states is necessary for accesses. |
257 | | * L3 and real memory accesses have even a wider range of wait states. However, |
258 | | * to reliably access either L3 or memory, the ec->mem memory must be quite |
259 | | * large which is usually not desirable. |
260 | | * |
261 | | * @ec [in] Reference to the entropy collector with the memory access data -- if |
262 | | * the reference to the memory block to be accessed is NULL, this noise |
263 | | * source is disabled |
264 | | * @loop_cnt [in] if a value not equal to 0 is set, use the given value as |
265 | | * number of loops to perform the hash operation |
266 | | */ |
267 | | static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt) |
268 | | { |
269 | | unsigned int wrap = 0; |
270 | | uint64_t i = 0; |
271 | | |
272 | | /* Ensure that macros cannot overflow jent_loop_shuffle() */ |
273 | | BUILD_BUG_ON((MAX_ACC_LOOP_BIT + MIN_ACC_LOOP_BIT) > 63); |
274 | | uint64_t acc_loop_cnt = |
275 | | jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); |
276 | | |
277 | | if (NULL == ec || NULL == ec->mem) |
278 | | return; |
279 | | wrap = ec->memblocksize * ec->memblocks; |
280 | | |
281 | | /* |
282 | | * testing purposes -- allow test app to set the counter, not |
283 | | * needed during runtime |
284 | | */ |
285 | | if (loop_cnt) |
286 | | acc_loop_cnt = loop_cnt; |
287 | | for (i = 0; i < (ec->memaccessloops + acc_loop_cnt); i++) { |
288 | | unsigned char *tmpval = ec->mem + ec->memlocation; |
289 | | /* |
290 | | * memory access: just add 1 to one byte, |
291 | | * wrap at 255 -- memory access implies read |
292 | | * from and write to memory location |
293 | | */ |
294 | | *tmpval = (unsigned char)((*tmpval + 1) & 0xff); |
295 | | /* |
296 | | * Addition of memblocksize - 1 to pointer |
297 | | * with wrap around logic to ensure that every |
298 | | * memory location is hit evenly |
299 | | */ |
300 | | ec->memlocation = ec->memlocation + ec->memblocksize - 1; |
301 | | ec->memlocation = ec->memlocation % wrap; |
302 | | } |
303 | | } |
304 | | |
305 | | #endif /* JENT_RANDOM_MEMACCESS */ |
306 | | |
307 | | /*************************************************************************** |
308 | | * Start of entropy processing logic |
309 | | ***************************************************************************/ |
310 | | |
311 | | /** |
312 | | * This is the heart of the entropy generation: calculate time deltas and |
313 | | * use the CPU jitter in the time deltas. The jitter is injected into the |
314 | | * entropy pool. |
315 | | * |
316 | | * WARNING: ensure that ->prev_time is primed before using the output |
317 | | * of this function! This can be done by calling this function |
318 | | * and not using its result. |
319 | | * |
320 | | * @ec [in] Reference to entropy collector |
321 | | * @loop_cnt [in] see jent_hash_time |
322 | | * @ret_current_delta [out] Test interface: return time delta - may be NULL |
323 | | * |
324 | | * @return: result of stuck test |
325 | | */ |
326 | | unsigned int jent_measure_jitter(struct rand_data *ec, |
327 | | uint64_t loop_cnt, |
328 | | uint64_t *ret_current_delta) |
329 | 0 | { |
330 | 0 | uint64_t time = 0; |
331 | 0 | uint64_t current_delta = 0; |
332 | 0 | unsigned int stuck; |
333 | | |
334 | | /* Invoke one noise source before time measurement to add variations */ |
335 | 0 | jent_memaccess(ec, loop_cnt); |
336 | | |
337 | | /* |
338 | | * Get time stamp and calculate time delta to previous |
339 | | * invocation to measure the timing variations |
340 | | */ |
341 | 0 | jent_get_nstime_internal(ec, &time); |
342 | 0 | current_delta = jent_delta(ec->prev_time, time) / |
343 | 0 | ec->jent_common_timer_gcd; |
344 | 0 | ec->prev_time = time; |
345 | | |
346 | | /* Check whether we have a stuck measurement. */ |
347 | 0 | stuck = jent_stuck(ec, current_delta); |
348 | | |
349 | | /* Now call the next noise sources which also injects the data */ |
350 | 0 | jent_hash_time(ec, current_delta, loop_cnt, stuck); |
351 | | |
352 | | /* return the raw entropy value */ |
353 | 0 | if (ret_current_delta) |
354 | 0 | *ret_current_delta = current_delta; |
355 | |
|
356 | 0 | return stuck; |
357 | 0 | } |
358 | | |
359 | | /** |
360 | | * Generator of one 256 bit random number |
361 | | * Function fills rand_data->data |
362 | | * |
363 | | * @ec [in] Reference to entropy collector |
364 | | */ |
365 | | void jent_random_data(struct rand_data *ec) |
366 | 0 | { |
367 | 0 | unsigned int k = 0, safety_factor = ENTROPY_SAFETY_FACTOR; |
368 | |
|
369 | 0 | if (!ec->fips_enabled) |
370 | 0 | safety_factor = 0; |
371 | | |
372 | | /* priming of the ->prev_time value */ |
373 | 0 | jent_measure_jitter(ec, 0, NULL); |
374 | |
|
375 | 0 | while (1) { |
376 | | /* If a stuck measurement is received, repeat measurement */ |
377 | 0 | if (jent_measure_jitter(ec, 0, NULL)) |
378 | 0 | continue; |
379 | | |
380 | | /* |
381 | | * We multiply the loop value with ->osr to obtain the |
382 | | * oversampling rate requested by the caller |
383 | | */ |
384 | 0 | if (++k >= ((DATA_SIZE_BITS + safety_factor) * ec->osr)) |
385 | 0 | break; |
386 | 0 | } |
387 | 0 | } |