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();