2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include "internal/cryptlib.h"
13 #include <openssl/opensslconf.h>
14 #include "internal/rand_int.h"
15 #include <openssl/engine.h>
16 #include "internal/thread_once.h"
19 #ifndef OPENSSL_NO_ENGINE
20 /* non-NULL if default_RAND_meth is ENGINE-provided */
21 static ENGINE *funct_ref;
22 static CRYPTO_RWLOCK *rand_engine_lock;
24 static CRYPTO_RWLOCK *rand_meth_lock;
25 static const RAND_METHOD *default_RAND_meth;
26 static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
28 #ifdef OPENSSL_RAND_SEED_RDTSC
30 * IMPORTANT NOTE: It is not currently possible to use this code
31 * because we are not sure about the amount of randomness. Some
32 * SP900 tests have been run, but there is internal skepticism.
33 * So for now this code is not used.
35 # error "RDTSC enabled? Should not be possible!"
38 * Since we get some randomness from the low-order bits of the
39 * high-speec clock, it can help. But don't return a status since
40 * it's not sufficient to indicate whether or not the seeding was
48 for (i = 0; i < 10; i++) {
49 c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
55 #ifdef OPENSSL_RAND_SEED_RDCPU
56 size_t OPENSSL_ia32_rdseed(void);
57 size_t OPENSSL_ia32_rdrand(void);
59 extern unsigned int OPENSSL_ia32cap_P[];
65 /* If RDSEED is available, use that. */
66 if ((OPENSSL_ia32cap_P[1] & (1 << 18)) != 0) {
67 for (i = 0; i < RANDOMNESS_NEEDED; i += sizeof(s)) {
68 s = OPENSSL_ia32_rdseed();
71 RAND_add(&s, (int)sizeof(s), sizeof(s));
73 if (i >= RANDOMNESS_NEEDED)
77 /* Second choice is RDRAND. */
78 if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) {
79 for (i = 0; i < RANDOMNESS_NEEDED; i += sizeof(s)) {
80 s = OPENSSL_ia32_rdrand();
83 RAND_add(&s, (int)sizeof(s), sizeof(s));
85 if (i >= RANDOMNESS_NEEDED)
93 DEFINE_RUN_ONCE_STATIC(do_rand_init)
96 #ifndef OPENSSL_NO_ENGINE
97 rand_engine_lock = CRYPTO_THREAD_lock_new();
98 ret &= rand_engine_lock != NULL;
100 rand_meth_lock = CRYPTO_THREAD_lock_new();
101 ret &= rand_meth_lock != NULL;
105 void rand_cleanup_int(void)
107 const RAND_METHOD *meth = default_RAND_meth;
109 if (meth != NULL && meth->cleanup != NULL)
111 RAND_set_rand_method(NULL);
112 #ifndef OPENSSL_NO_ENGINE
113 CRYPTO_THREAD_lock_free(rand_engine_lock);
115 CRYPTO_THREAD_lock_free(rand_meth_lock);
119 int RAND_set_rand_method(const RAND_METHOD *meth)
121 if (!RUN_ONCE(&rand_init, do_rand_init))
124 CRYPTO_THREAD_write_lock(rand_meth_lock);
125 #ifndef OPENSSL_NO_ENGINE
126 ENGINE_finish(funct_ref);
129 default_RAND_meth = meth;
130 CRYPTO_THREAD_unlock(rand_meth_lock);
134 const RAND_METHOD *RAND_get_rand_method(void)
136 const RAND_METHOD *tmp_meth = NULL;
138 if (!RUN_ONCE(&rand_init, do_rand_init))
141 CRYPTO_THREAD_write_lock(rand_meth_lock);
142 if (default_RAND_meth == NULL) {
143 #ifndef OPENSSL_NO_ENGINE
146 /* If we have an engine that can do RAND, use it. */
147 if ((e = ENGINE_get_default_RAND()) != NULL
148 && (tmp_meth = ENGINE_get_RAND(e)) != NULL) {
150 default_RAND_meth = tmp_meth;
153 default_RAND_meth = &openssl_rand_meth;
156 default_RAND_meth = &openssl_rand_meth;
159 tmp_meth = default_RAND_meth;
160 CRYPTO_THREAD_unlock(rand_meth_lock);
164 #ifndef OPENSSL_NO_ENGINE
165 int RAND_set_rand_engine(ENGINE *engine)
167 const RAND_METHOD *tmp_meth = NULL;
169 if (!RUN_ONCE(&rand_init, do_rand_init))
172 if (engine != NULL) {
173 if (!ENGINE_init(engine))
175 tmp_meth = ENGINE_get_RAND(engine);
176 if (tmp_meth == NULL) {
177 ENGINE_finish(engine);
181 CRYPTO_THREAD_write_lock(rand_engine_lock);
182 /* This function releases any prior ENGINE so call it first */
183 RAND_set_rand_method(tmp_meth);
185 CRYPTO_THREAD_unlock(rand_engine_lock);
190 void RAND_seed(const void *buf, int num)
192 const RAND_METHOD *meth = RAND_get_rand_method();
194 if (meth->seed != NULL)
195 meth->seed(buf, num);
198 void RAND_add(const void *buf, int num, double randomness)
200 const RAND_METHOD *meth = RAND_get_rand_method();
202 if (meth->add != NULL)
203 meth->add(buf, num, randomness);
206 int RAND_bytes(unsigned char *buf, int num)
208 const RAND_METHOD *meth = RAND_get_rand_method();
210 if (meth->bytes != NULL)
211 return meth->bytes(buf, num);
212 RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
216 #if OPENSSL_API_COMPAT < 0x10100000L
217 int RAND_pseudo_bytes(unsigned char *buf, int num)
219 const RAND_METHOD *meth = RAND_get_rand_method();
221 if (meth->pseudorand != NULL)
222 return meth->pseudorand(buf, num);
227 int RAND_status(void)
229 const RAND_METHOD *meth = RAND_get_rand_method();
231 if (meth->status != NULL)
232 return meth->status();