]>
Commit | Line | Data |
---|---|---|
b1322259 RS |
1 | /* |
2 | * Copyright 1995-2016 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> |
f3cd81d6 | 14 | #include "internal/rand.h" |
3c27208f | 15 | #include <openssl/engine.h> |
87975cfa | 16 | #include "internal/thread_once.h" |
dfeab068 | 17 | |
0b13e9f0 | 18 | #ifndef OPENSSL_NO_ENGINE |
cb78486d | 19 | /* non-NULL if default_RAND_meth is ENGINE-provided */ |
0f113f3e | 20 | static ENGINE *funct_ref = NULL; |
87975cfa | 21 | static CRYPTO_RWLOCK *rand_engine_lock = NULL; |
0b13e9f0 | 22 | #endif |
cb78486d | 23 | static const RAND_METHOD *default_RAND_meth = NULL; |
87975cfa RL |
24 | static CRYPTO_RWLOCK *rand_meth_lock = NULL; |
25 | static CRYPTO_ONCE rand_lock_init = CRYPTO_ONCE_STATIC_INIT; | |
26 | ||
27 | DEFINE_RUN_ONCE_STATIC(do_rand_lock_init) | |
28 | { | |
2f881d2d | 29 | int ret = 1; |
87975cfa RL |
30 | #ifndef OPENSSL_NO_ENGINE |
31 | rand_engine_lock = CRYPTO_THREAD_lock_new(); | |
2f881d2d | 32 | ret &= rand_engine_lock != NULL; |
87975cfa RL |
33 | #endif |
34 | rand_meth_lock = CRYPTO_THREAD_lock_new(); | |
2f881d2d RL |
35 | ret &= rand_meth_lock != NULL; |
36 | return ret; | |
87975cfa | 37 | } |
dfeab068 | 38 | |
cb78486d | 39 | int RAND_set_rand_method(const RAND_METHOD *meth) |
0f113f3e | 40 | { |
87975cfa RL |
41 | if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) |
42 | return 0; | |
43 | ||
44 | CRYPTO_THREAD_write_lock(rand_meth_lock); | |
0b13e9f0 | 45 | #ifndef OPENSSL_NO_ENGINE |
7c96dbcd RS |
46 | ENGINE_finish(funct_ref); |
47 | funct_ref = NULL; | |
0b13e9f0 | 48 | #endif |
0f113f3e | 49 | default_RAND_meth = meth; |
87975cfa | 50 | CRYPTO_THREAD_unlock(rand_meth_lock); |
0f113f3e MC |
51 | return 1; |
52 | } | |
dfeab068 | 53 | |
a4a9d97a | 54 | const RAND_METHOD *RAND_get_rand_method(void) |
0f113f3e | 55 | { |
87975cfa RL |
56 | const RAND_METHOD *tmp_meth = NULL; |
57 | ||
58 | if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) | |
59 | return NULL; | |
60 | ||
61 | CRYPTO_THREAD_write_lock(rand_meth_lock); | |
0f113f3e | 62 | if (!default_RAND_meth) { |
0b13e9f0 | 63 | #ifndef OPENSSL_NO_ENGINE |
0f113f3e MC |
64 | ENGINE *e = ENGINE_get_default_RAND(); |
65 | if (e) { | |
66 | default_RAND_meth = ENGINE_get_RAND(e); | |
7c96dbcd | 67 | if (default_RAND_meth == NULL) { |
0f113f3e MC |
68 | ENGINE_finish(e); |
69 | e = NULL; | |
70 | } | |
71 | } | |
72 | if (e) | |
73 | funct_ref = e; | |
74 | else | |
0b13e9f0 | 75 | #endif |
b0700d2c | 76 | default_RAND_meth = RAND_OpenSSL(); |
0f113f3e | 77 | } |
87975cfa RL |
78 | tmp_meth = default_RAND_meth; |
79 | CRYPTO_THREAD_unlock(rand_meth_lock); | |
80 | return tmp_meth; | |
0f113f3e | 81 | } |
cb78486d | 82 | |
0b13e9f0 | 83 | #ifndef OPENSSL_NO_ENGINE |
cb78486d | 84 | int RAND_set_rand_engine(ENGINE *engine) |
0f113f3e MC |
85 | { |
86 | const RAND_METHOD *tmp_meth = NULL; | |
87975cfa RL |
87 | |
88 | if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init)) | |
89 | return 0; | |
90 | ||
0f113f3e MC |
91 | if (engine) { |
92 | if (!ENGINE_init(engine)) | |
93 | return 0; | |
94 | tmp_meth = ENGINE_get_RAND(engine); | |
7c96dbcd | 95 | if (tmp_meth == NULL) { |
0f113f3e MC |
96 | ENGINE_finish(engine); |
97 | return 0; | |
98 | } | |
99 | } | |
87975cfa | 100 | CRYPTO_THREAD_write_lock(rand_engine_lock); |
0f113f3e MC |
101 | /* This function releases any prior ENGINE so call it first */ |
102 | RAND_set_rand_method(tmp_meth); | |
103 | funct_ref = engine; | |
87975cfa | 104 | CRYPTO_THREAD_unlock(rand_engine_lock); |
0f113f3e MC |
105 | return 1; |
106 | } | |
0b13e9f0 | 107 | #endif |
dfeab068 | 108 | |
b3599dbb | 109 | void rand_cleanup_int(void) |
0f113f3e | 110 | { |
5006b37b | 111 | const RAND_METHOD *meth = default_RAND_meth; |
0f113f3e MC |
112 | if (meth && meth->cleanup) |
113 | meth->cleanup(); | |
114 | RAND_set_rand_method(NULL); | |
87975cfa | 115 | CRYPTO_THREAD_lock_free(rand_meth_lock); |
ce57ac43 | 116 | #ifndef OPENSSL_NO_ENGINE |
87975cfa | 117 | CRYPTO_THREAD_lock_free(rand_engine_lock); |
ce57ac43 | 118 | #endif |
0f113f3e | 119 | } |
dfeab068 | 120 | |
6343829a | 121 | void RAND_seed(const void *buf, int num) |
0f113f3e MC |
122 | { |
123 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
124 | if (meth && meth->seed) | |
125 | meth->seed(buf, num); | |
126 | } | |
dfeab068 | 127 | |
6343829a | 128 | void RAND_add(const void *buf, int num, double entropy) |
0f113f3e MC |
129 | { |
130 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
131 | if (meth && meth->add) | |
132 | meth->add(buf, num, entropy); | |
133 | } | |
eb952088 | 134 | |
6343829a | 135 | int RAND_bytes(unsigned char *buf, int num) |
0f113f3e MC |
136 | { |
137 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
138 | if (meth && meth->bytes) | |
139 | return meth->bytes(buf, num); | |
140 | return (-1); | |
141 | } | |
dfeab068 | 142 | |
98186eb4 | 143 | #if OPENSSL_API_COMPAT < 0x10100000L |
6343829a | 144 | int RAND_pseudo_bytes(unsigned char *buf, int num) |
0f113f3e MC |
145 | { |
146 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
147 | if (meth && meth->pseudorand) | |
148 | return meth->pseudorand(buf, num); | |
149 | return (-1); | |
150 | } | |
302d38e3 | 151 | #endif |
5eb8ca4d BM |
152 | |
153 | int RAND_status(void) | |
0f113f3e MC |
154 | { |
155 | const RAND_METHOD *meth = RAND_get_rand_method(); | |
156 | if (meth && meth->status) | |
157 | return meth->status(); | |
158 | return 0; | |
159 | } |