]>
Commit | Line | Data |
---|---|---|
b1322259 | 1 | /* |
f61f62ea | 2 | * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. |
dfeab068 | 3 | * |
b1322259 RS |
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 | |
dfeab068 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
dfeab068 | 11 | #include <time.h> |
b39fc560 | 12 | #include "internal/cryptlib.h" |
98186eb4 | 13 | #include <openssl/opensslconf.h> |
63f483e1 | 14 | #include "internal/rand_int.h" |
3c27208f | 15 | #include <openssl/engine.h> |
87975cfa | 16 | #include "internal/thread_once.h" |
da8fc25a | 17 | #include "rand_lcl.h" |
20928ff6 | 18 | #include "e_os.h" |
dfeab068 | 19 | |
0b13e9f0 | 20 | #ifndef OPENSSL_NO_ENGINE |
cb78486d | 21 | /* non-NULL if default_RAND_meth is ENGINE-provided */ |
da8fc25a RS |
22 | static ENGINE *funct_ref; |
23 | static CRYPTO_RWLOCK *rand_engine_lock; | |
0b13e9f0 | 24 | #endif |
da8fc25a RS |
25 | static CRYPTO_RWLOCK *rand_meth_lock; |
26 | static const RAND_METHOD *default_RAND_meth; | |
27 | static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT; | |
c16de9d8 | 28 | |
a35f607c | 29 | int rand_fork_count; |
87975cfa | 30 | |
5bc6bcf8 DMSP |
31 | static CRYPTO_RWLOCK *rand_nonce_lock; |
32 | static int rand_nonce_count; | |
33 | ||
8389ec4b RS |
34 | #ifdef OPENSSL_RAND_SEED_RDTSC |
35 | /* | |
36 | * IMPORTANT NOTE: It is not currently possible to use this code | |
9ed79d8e RS |
37 | * because we are not sure about the amount of randomness it provides. |
38 | * Some SP900 tests have been run, but there is internal skepticism. | |
8389ec4b RS |
39 | * So for now this code is not used. |
40 | */ | |
41 | # error "RDTSC enabled? Should not be possible!" | |
42 | ||
43 | /* | |
c16de9d8 DMSP |
44 | * Acquire entropy from high-speed clock |
45 | * | |
8389ec4b | 46 | * Since we get some randomness from the low-order bits of the |
c16de9d8 DMSP |
47 | * high-speed clock, it can help. |
48 | * | |
49 | * Returns the total entropy count, if it exceeds the requested | |
50 | * entropy count. Otherwise, returns an entropy count of 0. | |
8389ec4b | 51 | */ |
c16de9d8 | 52 | size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool) |
8389ec4b RS |
53 | { |
54 | unsigned char c; | |
55 | int i; | |
56 | ||
9ed79d8e RS |
57 | if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) { |
58 | for (i = 0; i < TSC_READ_COUNT; i++) { | |
59 | c = (unsigned char)(OPENSSL_rdtsc() & 0xFF); | |
6decf943 | 60 | rand_pool_add(pool, &c, 1, 4); |
9ed79d8e | 61 | } |
8389ec4b | 62 | } |
6decf943 | 63 | return rand_pool_entropy_available(pool); |
8389ec4b RS |
64 | } |
65 | #endif | |
66 | ||
67 | #ifdef OPENSSL_RAND_SEED_RDCPU | |
c16de9d8 DMSP |
68 | size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len); |
69 | size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len); | |
8389ec4b RS |
70 | |
71 | extern unsigned int OPENSSL_ia32cap_P[]; | |
72 | ||
c16de9d8 DMSP |
73 | /* |
74 | * Acquire entropy using Intel-specific cpu instructions | |
75 | * | |
76 | * Uses the RDSEED instruction if available, otherwise uses | |
77 | * RDRAND if available. | |
78 | * | |
79 | * For the differences between RDSEED and RDRAND, and why RDSEED | |
80 | * is the preferred choice, see https://goo.gl/oK3KcN | |
81 | * | |
82 | * Returns the total entropy count, if it exceeds the requested | |
83 | * entropy count. Otherwise, returns an entropy count of 0. | |
84 | */ | |
85 | size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool) | |
8389ec4b | 86 | { |
c16de9d8 DMSP |
87 | size_t bytes_needed; |
88 | unsigned char *buffer; | |
89 | ||
6ebb49f3 | 90 | bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
c16de9d8 | 91 | if (bytes_needed > 0) { |
6decf943 | 92 | buffer = rand_pool_add_begin(pool, bytes_needed); |
c16de9d8 DMSP |
93 | |
94 | if (buffer != NULL) { | |
8e2bec9b | 95 | /* Whichever comes first, use RDSEED, RDRAND or nothing */ |
c16de9d8 DMSP |
96 | if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) { |
97 | if (OPENSSL_ia32_rdseed_bytes(buffer, bytes_needed) | |
8e2bec9b RL |
98 | == bytes_needed) { |
99 | rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); | |
100 | } | |
101 | } else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) { | |
c16de9d8 | 102 | if (OPENSSL_ia32_rdrand_bytes(buffer, bytes_needed) |
8e2bec9b RL |
103 | == bytes_needed) { |
104 | rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed); | |
105 | } | |
106 | } else { | |
107 | rand_pool_add_end(pool, 0, 0); | |
c16de9d8 | 108 | } |
9ed79d8e | 109 | } |
8389ec4b RS |
110 | } |
111 | ||
6decf943 | 112 | return rand_pool_entropy_available(pool); |
8389ec4b RS |
113 | } |
114 | #endif | |
da8fc25a | 115 | |
75e2c877 RS |
116 | |
117 | /* | |
c16de9d8 DMSP |
118 | * Implements the get_entropy() callback (see RAND_DRBG_set_callbacks()) |
119 | * | |
120 | * If the DRBG has a parent, then the required amount of entropy input | |
121 | * is fetched using the parent's RAND_DRBG_generate(). | |
75e2c877 | 122 | * |
c16de9d8 | 123 | * Otherwise, the entropy is polled from the system entropy sources |
6decf943 | 124 | * using rand_pool_acquire_entropy(). |
c16de9d8 DMSP |
125 | * |
126 | * If a random pool has been added to the DRBG using RAND_add(), then | |
127 | * its entropy will be used up first. | |
75e2c877 | 128 | */ |
c16de9d8 | 129 | size_t rand_drbg_get_entropy(RAND_DRBG *drbg, |
eb238134 KR |
130 | unsigned char **pout, |
131 | int entropy, size_t min_len, size_t max_len, | |
132 | int prediction_resistance) | |
75e2c877 | 133 | { |
c16de9d8 DMSP |
134 | size_t ret = 0; |
135 | size_t entropy_available = 0; | |
35503b7c KR |
136 | RAND_POOL *pool; |
137 | ||
138 | if (drbg->parent && drbg->strength > drbg->parent->strength) { | |
139 | /* | |
140 | * We currently don't support the algorithm from NIST SP 800-90C | |
141 | * 10.1.2 to use a weaker DRBG as source | |
142 | */ | |
143 | RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY, RAND_R_PARENT_STRENGTH_TOO_WEAK); | |
144 | return 0; | |
145 | } | |
75e2c877 | 146 | |
6decf943 | 147 | pool = rand_pool_new(entropy, min_len, max_len); |
c16de9d8 DMSP |
148 | if (pool == NULL) |
149 | return 0; | |
150 | ||
151 | if (drbg->pool) { | |
6decf943 DMSP |
152 | rand_pool_add(pool, |
153 | rand_pool_buffer(drbg->pool), | |
154 | rand_pool_length(drbg->pool), | |
155 | rand_pool_entropy(drbg->pool)); | |
156 | rand_pool_free(drbg->pool); | |
c16de9d8 | 157 | drbg->pool = NULL; |
75e2c877 RS |
158 | } |
159 | ||
c16de9d8 | 160 | if (drbg->parent) { |
6ebb49f3 | 161 | size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/); |
6decf943 | 162 | unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed); |
9d951a78 | 163 | |
c16de9d8 DMSP |
164 | if (buffer != NULL) { |
165 | size_t bytes = 0; | |
75e2c877 | 166 | |
2139145b BK |
167 | /* |
168 | * Get random from parent, include our state as additional input. | |
169 | * Our lock is already held, but we need to lock our parent before | |
3ce1c27b DMSP |
170 | * generating bits from it. (Note: taking the lock will be a no-op |
171 | * if locking if drbg->parent->lock == NULL.) | |
2139145b | 172 | */ |
812b1537 | 173 | rand_drbg_lock(drbg->parent); |
c16de9d8 DMSP |
174 | if (RAND_DRBG_generate(drbg->parent, |
175 | buffer, bytes_needed, | |
311276ff | 176 | prediction_resistance, |
7c226dfc | 177 | NULL, 0) != 0) |
c16de9d8 | 178 | bytes = bytes_needed; |
812b1537 | 179 | rand_drbg_unlock(drbg->parent); |
75e2c877 | 180 | |
8e2bec9b RL |
181 | rand_pool_add_end(pool, bytes, 8 * bytes); |
182 | entropy_available = rand_pool_entropy_available(pool); | |
c16de9d8 | 183 | } |
0b14a5b7 | 184 | |
c16de9d8 | 185 | } else { |
311276ff KR |
186 | if (prediction_resistance) { |
187 | /* | |
188 | * We don't have any entropy sources that comply with the NIST | |
189 | * standard to provide prediction resistance (see NIST SP 800-90C, | |
190 | * Section 5.4). | |
191 | */ | |
192 | RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY, | |
193 | RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED); | |
63a65d16 | 194 | goto err; |
311276ff KR |
195 | } |
196 | ||
c16de9d8 | 197 | /* Get entropy by polling system entropy sources. */ |
6decf943 | 198 | entropy_available = rand_pool_acquire_entropy(pool); |
75e2c877 RS |
199 | } |
200 | ||
c16de9d8 | 201 | if (entropy_available > 0) { |
6decf943 DMSP |
202 | ret = rand_pool_length(pool); |
203 | *pout = rand_pool_detach(pool); | |
6969a3f4 | 204 | } |
c16de9d8 | 205 | |
63a65d16 | 206 | err: |
6decf943 | 207 | rand_pool_free(pool); |
c16de9d8 | 208 | return ret; |
75e2c877 RS |
209 | } |
210 | ||
2b66fd57 | 211 | /* |
5bc6bcf8 | 212 | * Implements the cleanup_entropy() callback (see RAND_DRBG_set_callbacks()) |
60595292 | 213 | * |
2b66fd57 | 214 | */ |
5bc6bcf8 DMSP |
215 | void rand_drbg_cleanup_entropy(RAND_DRBG *drbg, |
216 | unsigned char *out, size_t outlen) | |
2b66fd57 | 217 | { |
5bc6bcf8 DMSP |
218 | OPENSSL_secure_clear_free(out, outlen); |
219 | } | |
220 | ||
221 | ||
222 | /* | |
223 | * Implements the get_nonce() callback (see RAND_DRBG_set_callbacks()) | |
224 | * | |
225 | */ | |
226 | size_t rand_drbg_get_nonce(RAND_DRBG *drbg, | |
227 | unsigned char **pout, | |
228 | int entropy, size_t min_len, size_t max_len) | |
229 | { | |
230 | size_t ret = 0; | |
231 | RAND_POOL *pool; | |
232 | ||
233 | struct { | |
234 | void * instance; | |
235 | int count; | |
236 | } data = { 0 }; | |
237 | ||
238 | pool = rand_pool_new(0, min_len, max_len); | |
239 | if (pool == NULL) | |
240 | return 0; | |
241 | ||
242 | if (rand_pool_add_nonce_data(pool) == 0) | |
243 | goto err; | |
244 | ||
245 | data.instance = drbg; | |
246 | CRYPTO_atomic_add(&rand_nonce_count, 1, &data.count, rand_nonce_lock); | |
247 | ||
248 | if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0) | |
249 | goto err; | |
250 | ||
251 | ret = rand_pool_length(pool); | |
252 | *pout = rand_pool_detach(pool); | |
253 | ||
254 | err: | |
255 | rand_pool_free(pool); | |
256 | ||
257 | return ret; | |
258 | } | |
259 | ||
260 | /* | |
261 | * Implements the cleanup_nonce() callback (see RAND_DRBG_set_callbacks()) | |
262 | * | |
263 | */ | |
264 | void rand_drbg_cleanup_nonce(RAND_DRBG *drbg, | |
265 | unsigned char *out, size_t outlen) | |
266 | { | |
267 | OPENSSL_secure_clear_free(out, outlen); | |
2b66fd57 P |
268 | } |
269 | ||
20928ff6 KR |
270 | /* |
271 | * Generate additional data that can be used for the drbg. The data does | |
272 | * not need to contain entropy, but it's useful if it contains at least | |
273 | * some bits that are unpredictable. | |
274 | * | |
275 | * Returns 0 on failure. | |
276 | * | |
277 | * On success it allocates a buffer at |*pout| and returns the length of | |
278 | * the data. The buffer should get freed using OPENSSL_secure_clear_free(). | |
279 | */ | |
280 | size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len) | |
281 | { | |
5bc6bcf8 | 282 | size_t ret = 0; |
20928ff6 | 283 | RAND_POOL *pool; |
20928ff6 | 284 | |
6decf943 | 285 | pool = rand_pool_new(0, 0, max_len); |
20928ff6 KR |
286 | if (pool == NULL) |
287 | return 0; | |
288 | ||
5bc6bcf8 DMSP |
289 | if (rand_pool_add_additional_data(pool) == 0) |
290 | goto err; | |
20928ff6 | 291 | |
5bc6bcf8 DMSP |
292 | ret = rand_pool_length(pool); |
293 | *pout = rand_pool_detach(pool); | |
20928ff6 | 294 | |
5bc6bcf8 | 295 | err: |
6decf943 | 296 | rand_pool_free(pool); |
20928ff6 | 297 | |
5bc6bcf8 | 298 | return ret; |
20928ff6 | 299 | } |
c16de9d8 | 300 | |
5bc6bcf8 | 301 | void rand_drbg_cleanup_additional_data(unsigned char *out, size_t outlen) |
75e2c877 | 302 | { |
c16de9d8 | 303 | OPENSSL_secure_clear_free(out, outlen); |
ddc6a5c8 RS |
304 | } |
305 | ||
3cb7c5cf | 306 | void rand_fork(void) |
a35f607c RS |
307 | { |
308 | rand_fork_count++; | |
309 | } | |
310 | ||
da8fc25a | 311 | DEFINE_RUN_ONCE_STATIC(do_rand_init) |
87975cfa RL |
312 | { |
313 | #ifndef OPENSSL_NO_ENGINE | |
63ab5ea1 | 314 | rand_engine_lock = CRYPTO_THREAD_lock_new(); |
0e5c1a66 BE |
315 | if (rand_engine_lock == NULL) |
316 | return 0; | |
87975cfa | 317 | #endif |
0e5c1a66 | 318 | |
63ab5ea1 | 319 | rand_meth_lock = CRYPTO_THREAD_lock_new(); |
0e5c1a66 BE |
320 | if (rand_meth_lock == NULL) |
321 | goto err1; | |
75e2c877 | 322 | |
5bc6bcf8 | 323 | rand_nonce_lock = CRYPTO_THREAD_lock_new(); |
0e5c1a66 BE |
324 | if (rand_nonce_lock == NULL) |
325 | goto err2; | |
5bc6bcf8 | 326 | |
c7504aeb P |
327 | if (!rand_pool_init()) |
328 | goto err3; | |
329 | ||
0e5c1a66 BE |
330 | return 1; |
331 | ||
c7504aeb P |
332 | err3: |
333 | rand_pool_cleanup(); | |
0e5c1a66 BE |
334 | err2: |
335 | CRYPTO_THREAD_lock_free(rand_meth_lock); | |
336 | rand_meth_lock = NULL; | |
337 | err1: | |
338 | #ifndef OPENSSL_NO_ENGINE | |
339 | CRYPTO_THREAD_lock_free(rand_engine_lock); | |
340 | rand_engine_lock = NULL; | |
341 | #endif | |
342 | return 0; | |
87975cfa | 343 | } |
dfeab068 | 344 | |
da8fc25a RS |
345 | void rand_cleanup_int(void) |
346 | { | |
347 | const RAND_METHOD *meth = default_RAND_meth; | |
348 | ||
349 | if (meth != NULL && meth->cleanup != NULL) | |
350 | meth->cleanup(); | |
c7504aeb | 351 | rand_pool_cleanup(); |
da8fc25a RS |
352 | RAND_set_rand_method(NULL); |
353 | #ifndef OPENSSL_NO_ENGINE | |
354 | CRYPTO_THREAD_lock_free(rand_engine_lock); | |
0e5c1a66 | 355 | rand_engine_lock = NULL; |
da8fc25a RS |
356 | #endif |
357 | CRYPTO_THREAD_lock_free(rand_meth_lock); | |
0e5c1a66 | 358 | rand_meth_lock = NULL; |
5bc6bcf8 | 359 | CRYPTO_THREAD_lock_free(rand_nonce_lock); |
0e5c1a66 | 360 | rand_nonce_lock = NULL; |
75e2c877 RS |
361 | } |
362 | ||
c7504aeb P |
363 | /* |
364 | * RAND_close_seed_files() ensures that any seed file decriptors are | |
365 | * closed after use. | |
366 | */ | |
367 | void RAND_keep_random_devices_open(int keep) | |
368 | { | |
369 | rand_pool_keep_random_devices_open(keep); | |
370 | } | |
371 | ||
75e2c877 | 372 | /* |
c16de9d8 DMSP |
373 | * RAND_poll() reseeds the default RNG using random input |
374 | * | |
375 | * The random input is obtained from polling various entropy | |
376 | * sources which depend on the operating system and are | |
377 | * configurable via the --with-rand-seed configure option. | |
378 | */ | |
379 | int RAND_poll(void) | |
380 | { | |
381 | int ret = 0; | |
382 | ||
383 | RAND_POOL *pool = NULL; | |
384 | ||
385 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
386 | ||
387 | if (meth == RAND_OpenSSL()) { | |
a93ba405 DMSP |
388 | /* fill random pool and seed the master DRBG */ |
389 | RAND_DRBG *drbg = RAND_DRBG_get0_master(); | |
c16de9d8 DMSP |
390 | |
391 | if (drbg == NULL) | |
392 | return 0; | |
393 | ||
812b1537 | 394 | rand_drbg_lock(drbg); |
c16de9d8 | 395 | ret = rand_drbg_restart(drbg, NULL, 0, 0); |
812b1537 | 396 | rand_drbg_unlock(drbg); |
c16de9d8 DMSP |
397 | |
398 | return ret; | |
399 | ||
400 | } else { | |
401 | /* fill random pool and seed the current legacy RNG */ | |
6decf943 | 402 | pool = rand_pool_new(RAND_DRBG_STRENGTH, |
c16de9d8 DMSP |
403 | RAND_DRBG_STRENGTH / 8, |
404 | DRBG_MINMAX_FACTOR * (RAND_DRBG_STRENGTH / 8)); | |
405 | if (pool == NULL) | |
406 | return 0; | |
407 | ||
6decf943 | 408 | if (rand_pool_acquire_entropy(pool) == 0) |
c16de9d8 DMSP |
409 | goto err; |
410 | ||
411 | if (meth->add == NULL | |
6decf943 DMSP |
412 | || meth->add(rand_pool_buffer(pool), |
413 | rand_pool_length(pool), | |
414 | (rand_pool_entropy(pool) / 8.0)) == 0) | |
c16de9d8 DMSP |
415 | goto err; |
416 | ||
417 | ret = 1; | |
418 | } | |
419 | ||
420 | err: | |
6decf943 | 421 | rand_pool_free(pool); |
c16de9d8 DMSP |
422 | return ret; |
423 | } | |
424 | ||
c16de9d8 DMSP |
425 | /* |
426 | * Allocate memory and initialize a new random pool | |
427 | */ | |
428 | ||
6decf943 | 429 | RAND_POOL *rand_pool_new(int entropy, size_t min_len, size_t max_len) |
75e2c877 | 430 | { |
c16de9d8 DMSP |
431 | RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool)); |
432 | ||
433 | if (pool == NULL) { | |
434 | RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE); | |
435 | goto err; | |
436 | } | |
437 | ||
438 | pool->min_len = min_len; | |
439 | pool->max_len = max_len; | |
440 | ||
441 | pool->buffer = OPENSSL_secure_zalloc(pool->max_len); | |
442 | if (pool->buffer == NULL) { | |
443 | RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE); | |
444 | goto err; | |
445 | } | |
446 | ||
447 | pool->requested_entropy = entropy; | |
448 | ||
449 | return pool; | |
450 | ||
451 | err: | |
452 | OPENSSL_free(pool); | |
453 | return NULL; | |
75e2c877 RS |
454 | } |
455 | ||
c16de9d8 DMSP |
456 | /* |
457 | * Free |pool|, securely erasing its buffer. | |
458 | */ | |
6decf943 | 459 | void rand_pool_free(RAND_POOL *pool) |
c16de9d8 DMSP |
460 | { |
461 | if (pool == NULL) | |
462 | return; | |
463 | ||
464 | OPENSSL_secure_clear_free(pool->buffer, pool->max_len); | |
465 | OPENSSL_free(pool); | |
466 | } | |
467 | ||
468 | /* | |
469 | * Return the |pool|'s buffer to the caller (readonly). | |
470 | */ | |
6decf943 | 471 | const unsigned char *rand_pool_buffer(RAND_POOL *pool) |
c16de9d8 DMSP |
472 | { |
473 | return pool->buffer; | |
474 | } | |
475 | ||
476 | /* | |
477 | * Return the |pool|'s entropy to the caller. | |
478 | */ | |
6decf943 | 479 | size_t rand_pool_entropy(RAND_POOL *pool) |
c16de9d8 DMSP |
480 | { |
481 | return pool->entropy; | |
482 | } | |
483 | ||
484 | /* | |
485 | * Return the |pool|'s buffer length to the caller. | |
486 | */ | |
6decf943 | 487 | size_t rand_pool_length(RAND_POOL *pool) |
c16de9d8 DMSP |
488 | { |
489 | return pool->len; | |
490 | } | |
491 | ||
492 | /* | |
493 | * Detach the |pool| buffer and return it to the caller. | |
494 | * It's the responsibility of the caller to free the buffer | |
495 | * using OPENSSL_secure_clear_free(). | |
496 | */ | |
6decf943 | 497 | unsigned char *rand_pool_detach(RAND_POOL *pool) |
c16de9d8 DMSP |
498 | { |
499 | unsigned char *ret = pool->buffer; | |
500 | pool->buffer = NULL; | |
501 | return ret; | |
502 | } | |
503 | ||
504 | ||
505 | /* | |
6ebb49f3 RL |
506 | * If |entropy_factor| bits contain 1 bit of entropy, how many bytes does one |
507 | * need to obtain at least |bits| bits of entropy? | |
c16de9d8 | 508 | */ |
6ebb49f3 RL |
509 | #define ENTROPY_TO_BYTES(bits, entropy_factor) \ |
510 | (((bits) * (entropy_factor) + 7) / 8) | |
c16de9d8 DMSP |
511 | |
512 | ||
513 | /* | |
514 | * Checks whether the |pool|'s entropy is available to the caller. | |
515 | * This is the case when entropy count and buffer length are high enough. | |
516 | * Returns | |
517 | * | |
518 | * |entropy| if the entropy count and buffer size is large enough | |
519 | * 0 otherwise | |
520 | */ | |
6decf943 | 521 | size_t rand_pool_entropy_available(RAND_POOL *pool) |
c16de9d8 DMSP |
522 | { |
523 | if (pool->entropy < pool->requested_entropy) | |
524 | return 0; | |
525 | ||
526 | if (pool->len < pool->min_len) | |
527 | return 0; | |
528 | ||
529 | return pool->entropy; | |
530 | } | |
531 | ||
532 | /* | |
533 | * Returns the (remaining) amount of entropy needed to fill | |
534 | * the random pool. | |
535 | */ | |
536 | ||
6decf943 | 537 | size_t rand_pool_entropy_needed(RAND_POOL *pool) |
c16de9d8 DMSP |
538 | { |
539 | if (pool->entropy < pool->requested_entropy) | |
540 | return pool->requested_entropy - pool->entropy; | |
541 | ||
542 | return 0; | |
543 | } | |
544 | ||
545 | /* | |
546 | * Returns the number of bytes needed to fill the pool, assuming | |
6ebb49f3 | 547 | * the input has 1 / |entropy_factor| entropy bits per data bit. |
c16de9d8 DMSP |
548 | * In case of an error, 0 is returned. |
549 | */ | |
550 | ||
6ebb49f3 | 551 | size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor) |
c16de9d8 DMSP |
552 | { |
553 | size_t bytes_needed; | |
6decf943 | 554 | size_t entropy_needed = rand_pool_entropy_needed(pool); |
c16de9d8 | 555 | |
6ebb49f3 | 556 | if (entropy_factor < 1) { |
c16de9d8 DMSP |
557 | RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_ARGUMENT_OUT_OF_RANGE); |
558 | return 0; | |
559 | } | |
560 | ||
6ebb49f3 | 561 | bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor); |
c16de9d8 DMSP |
562 | |
563 | if (bytes_needed > pool->max_len - pool->len) { | |
564 | /* not enough space left */ | |
565 | RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_RANDOM_POOL_OVERFLOW); | |
566 | return 0; | |
567 | } | |
568 | ||
569 | if (pool->len < pool->min_len && | |
570 | bytes_needed < pool->min_len - pool->len) | |
571 | /* to meet the min_len requirement */ | |
572 | bytes_needed = pool->min_len - pool->len; | |
573 | ||
574 | return bytes_needed; | |
575 | } | |
576 | ||
577 | /* Returns the remaining number of bytes available */ | |
6decf943 | 578 | size_t rand_pool_bytes_remaining(RAND_POOL *pool) |
75e2c877 | 579 | { |
c16de9d8 DMSP |
580 | return pool->max_len - pool->len; |
581 | } | |
582 | ||
583 | /* | |
584 | * Add random bytes to the random pool. | |
585 | * | |
586 | * It is expected that the |buffer| contains |len| bytes of | |
587 | * random input which contains at least |entropy| bits of | |
588 | * randomness. | |
589 | * | |
8e2bec9b | 590 | * Returns 1 if the added amount is adequate, otherwise 0 |
c16de9d8 | 591 | */ |
8e2bec9b RL |
592 | int rand_pool_add(RAND_POOL *pool, |
593 | const unsigned char *buffer, size_t len, size_t entropy) | |
c16de9d8 DMSP |
594 | { |
595 | if (len > pool->max_len - pool->len) { | |
596 | RANDerr(RAND_F_RAND_POOL_ADD, RAND_R_ENTROPY_INPUT_TOO_LONG); | |
597 | return 0; | |
598 | } | |
599 | ||
600 | if (len > 0) { | |
601 | memcpy(pool->buffer + pool->len, buffer, len); | |
602 | pool->len += len; | |
603 | pool->entropy += entropy; | |
604 | } | |
605 | ||
8e2bec9b | 606 | return 1; |
c16de9d8 DMSP |
607 | } |
608 | ||
609 | /* | |
610 | * Start to add random bytes to the random pool in-place. | |
611 | * | |
612 | * Reserves the next |len| bytes for adding random bytes in-place | |
613 | * and returns a pointer to the buffer. | |
614 | * The caller is allowed to copy up to |len| bytes into the buffer. | |
615 | * If |len| == 0 this is considered a no-op and a NULL pointer | |
616 | * is returned without producing an error message. | |
617 | * | |
6decf943 | 618 | * After updating the buffer, rand_pool_add_end() needs to be called |
c16de9d8 DMSP |
619 | * to finish the udpate operation (see next comment). |
620 | */ | |
6decf943 | 621 | unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len) |
c16de9d8 DMSP |
622 | { |
623 | if (len == 0) | |
624 | return NULL; | |
625 | ||
626 | if (len > pool->max_len - pool->len) { | |
627 | RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, RAND_R_RANDOM_POOL_OVERFLOW); | |
628 | return NULL; | |
629 | } | |
630 | ||
631 | return pool->buffer + pool->len; | |
632 | } | |
633 | ||
634 | /* | |
635 | * Finish to add random bytes to the random pool in-place. | |
636 | * | |
637 | * Finishes an in-place update of the random pool started by | |
6decf943 | 638 | * rand_pool_add_begin() (see previous comment). |
c16de9d8 DMSP |
639 | * It is expected that |len| bytes of random input have been added |
640 | * to the buffer which contain at least |entropy| bits of randomness. | |
641 | * It is allowed to add less bytes than originally reserved. | |
642 | */ | |
8e2bec9b | 643 | int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy) |
c16de9d8 DMSP |
644 | { |
645 | if (len > pool->max_len - pool->len) { | |
646 | RANDerr(RAND_F_RAND_POOL_ADD_END, RAND_R_RANDOM_POOL_OVERFLOW); | |
647 | return 0; | |
648 | } | |
649 | ||
650 | if (len > 0) { | |
651 | pool->len += len; | |
652 | pool->entropy += entropy; | |
653 | } | |
654 | ||
8e2bec9b | 655 | return 1; |
da8fc25a RS |
656 | } |
657 | ||
cb78486d | 658 | int RAND_set_rand_method(const RAND_METHOD *meth) |
0f113f3e | 659 | { |
da8fc25a | 660 | if (!RUN_ONCE(&rand_init, do_rand_init)) |
87975cfa RL |
661 | return 0; |
662 | ||
663 | CRYPTO_THREAD_write_lock(rand_meth_lock); | |
0b13e9f0 | 664 | #ifndef OPENSSL_NO_ENGINE |
7c96dbcd RS |
665 | ENGINE_finish(funct_ref); |
666 | funct_ref = NULL; | |
0b13e9f0 | 667 | #endif |
0f113f3e | 668 | default_RAND_meth = meth; |
87975cfa | 669 | CRYPTO_THREAD_unlock(rand_meth_lock); |
0f113f3e MC |
670 | return 1; |
671 | } | |
dfeab068 | 672 | |
a4a9d97a | 673 | const RAND_METHOD *RAND_get_rand_method(void) |
0f113f3e | 674 | { |
87975cfa RL |
675 | const RAND_METHOD *tmp_meth = NULL; |
676 | ||
da8fc25a | 677 | if (!RUN_ONCE(&rand_init, do_rand_init)) |
87975cfa RL |
678 | return NULL; |
679 | ||
680 | CRYPTO_THREAD_write_lock(rand_meth_lock); | |
da8fc25a | 681 | if (default_RAND_meth == NULL) { |
0b13e9f0 | 682 | #ifndef OPENSSL_NO_ENGINE |
da8fc25a RS |
683 | ENGINE *e; |
684 | ||
685 | /* If we have an engine that can do RAND, use it. */ | |
686 | if ((e = ENGINE_get_default_RAND()) != NULL | |
687 | && (tmp_meth = ENGINE_get_RAND(e)) != NULL) { | |
0f113f3e | 688 | funct_ref = e; |
da8fc25a RS |
689 | default_RAND_meth = tmp_meth; |
690 | } else { | |
691 | ENGINE_finish(e); | |
75e2c877 | 692 | default_RAND_meth = &rand_meth; |
da8fc25a RS |
693 | } |
694 | #else | |
75e2c877 | 695 | default_RAND_meth = &rand_meth; |
0b13e9f0 | 696 | #endif |
0f113f3e | 697 | } |
87975cfa RL |
698 | tmp_meth = default_RAND_meth; |
699 | CRYPTO_THREAD_unlock(rand_meth_lock); | |
700 | return tmp_meth; | |
0f113f3e | 701 | } |
cb78486d | 702 | |
0b13e9f0 | 703 | #ifndef OPENSSL_NO_ENGINE |
cb78486d | 704 | int RAND_set_rand_engine(ENGINE *engine) |
0f113f3e MC |
705 | { |
706 | const RAND_METHOD *tmp_meth = NULL; | |
87975cfa | 707 | |
da8fc25a | 708 | if (!RUN_ONCE(&rand_init, do_rand_init)) |
87975cfa RL |
709 | return 0; |
710 | ||
da8fc25a | 711 | if (engine != NULL) { |
0f113f3e MC |
712 | if (!ENGINE_init(engine)) |
713 | return 0; | |
714 | tmp_meth = ENGINE_get_RAND(engine); | |
7c96dbcd | 715 | if (tmp_meth == NULL) { |
0f113f3e MC |
716 | ENGINE_finish(engine); |
717 | return 0; | |
718 | } | |
719 | } | |
87975cfa | 720 | CRYPTO_THREAD_write_lock(rand_engine_lock); |
0f113f3e MC |
721 | /* This function releases any prior ENGINE so call it first */ |
722 | RAND_set_rand_method(tmp_meth); | |
723 | funct_ref = engine; | |
87975cfa | 724 | CRYPTO_THREAD_unlock(rand_engine_lock); |
0f113f3e MC |
725 | return 1; |
726 | } | |
0b13e9f0 | 727 | #endif |
dfeab068 | 728 | |
6343829a | 729 | void RAND_seed(const void *buf, int num) |
0f113f3e MC |
730 | { |
731 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
da8fc25a RS |
732 | |
733 | if (meth->seed != NULL) | |
0f113f3e MC |
734 | meth->seed(buf, num); |
735 | } | |
dfeab068 | 736 | |
da8fc25a | 737 | void RAND_add(const void *buf, int num, double randomness) |
0f113f3e MC |
738 | { |
739 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
da8fc25a RS |
740 | |
741 | if (meth->add != NULL) | |
742 | meth->add(buf, num, randomness); | |
0f113f3e | 743 | } |
eb952088 | 744 | |
ddc6a5c8 RS |
745 | /* |
746 | * This function is not part of RAND_METHOD, so if we're not using | |
747 | * the default method, then just call RAND_bytes(). Otherwise make | |
748 | * sure we're instantiated and use the private DRBG. | |
749 | */ | |
750 | int RAND_priv_bytes(unsigned char *buf, int num) | |
751 | { | |
752 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
0b14a5b7 | 753 | RAND_DRBG *drbg; |
2139145b | 754 | int ret; |
ddc6a5c8 RS |
755 | |
756 | if (meth != RAND_OpenSSL()) | |
757 | return RAND_bytes(buf, num); | |
758 | ||
a93ba405 | 759 | drbg = RAND_DRBG_get0_private(); |
0b14a5b7 | 760 | if (drbg == NULL) |
ddc6a5c8 | 761 | return 0; |
ddc6a5c8 | 762 | |
f61f62ea | 763 | ret = RAND_DRBG_bytes(drbg, buf, num); |
2139145b | 764 | return ret; |
ddc6a5c8 RS |
765 | } |
766 | ||
6343829a | 767 | int RAND_bytes(unsigned char *buf, int num) |
0f113f3e MC |
768 | { |
769 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
da8fc25a RS |
770 | |
771 | if (meth->bytes != NULL) | |
0f113f3e | 772 | return meth->bytes(buf, num); |
0ea155fc | 773 | RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED); |
da8fc25a | 774 | return -1; |
0f113f3e | 775 | } |
dfeab068 | 776 | |
98186eb4 | 777 | #if OPENSSL_API_COMPAT < 0x10100000L |
6343829a | 778 | int RAND_pseudo_bytes(unsigned char *buf, int num) |
0f113f3e MC |
779 | { |
780 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
da8fc25a RS |
781 | |
782 | if (meth->pseudorand != NULL) | |
0f113f3e | 783 | return meth->pseudorand(buf, num); |
da8fc25a | 784 | return -1; |
0f113f3e | 785 | } |
302d38e3 | 786 | #endif |
5eb8ca4d BM |
787 | |
788 | int RAND_status(void) | |
0f113f3e MC |
789 | { |
790 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
da8fc25a RS |
791 | |
792 | if (meth->status != NULL) | |
0f113f3e MC |
793 | return meth->status(); |
794 | return 0; | |
795 | } |