/src/openssl/crypto/rand/rand_lib.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* crypto/rand/rand_lib.c */ |
2 | | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | | * All rights reserved. |
4 | | * |
5 | | * This package is an SSL implementation written |
6 | | * by Eric Young (eay@cryptsoft.com). |
7 | | * The implementation was written so as to conform with Netscapes SSL. |
8 | | * |
9 | | * This library is free for commercial and non-commercial use as long as |
10 | | * the following conditions are aheared to. The following conditions |
11 | | * apply to all code found in this distribution, be it the RC4, RSA, |
12 | | * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 | | * included with this distribution is covered by the same copyright terms |
14 | | * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 | | * |
16 | | * Copyright remains Eric Young's, and as such any Copyright notices in |
17 | | * the code are not to be removed. |
18 | | * If this package is used in a product, Eric Young should be given attribution |
19 | | * as the author of the parts of the library used. |
20 | | * This can be in the form of a textual message at program startup or |
21 | | * in documentation (online or textual) provided with the package. |
22 | | * |
23 | | * Redistribution and use in source and binary forms, with or without |
24 | | * modification, are permitted provided that the following conditions |
25 | | * are met: |
26 | | * 1. Redistributions of source code must retain the copyright |
27 | | * notice, this list of conditions and the following disclaimer. |
28 | | * 2. Redistributions in binary form must reproduce the above copyright |
29 | | * notice, this list of conditions and the following disclaimer in the |
30 | | * documentation and/or other materials provided with the distribution. |
31 | | * 3. All advertising materials mentioning features or use of this software |
32 | | * must display the following acknowledgement: |
33 | | * "This product includes cryptographic software written by |
34 | | * Eric Young (eay@cryptsoft.com)" |
35 | | * The word 'cryptographic' can be left out if the rouines from the library |
36 | | * being used are not cryptographic related :-). |
37 | | * 4. If you include any Windows specific code (or a derivative thereof) from |
38 | | * the apps directory (application code) you must include an acknowledgement: |
39 | | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 | | * |
41 | | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 | | * SUCH DAMAGE. |
52 | | * |
53 | | * The licence and distribution terms for any publically available version or |
54 | | * derivative of this code cannot be changed. i.e. this code cannot simply be |
55 | | * copied and put under another distribution licence |
56 | | * [including the GNU Public Licence.] |
57 | | */ |
58 | | |
59 | | #include <stdio.h> |
60 | | #include <time.h> |
61 | | #include "cryptlib.h" |
62 | | #include <openssl/rand.h> |
63 | | |
64 | | #ifndef OPENSSL_NO_ENGINE |
65 | | # include <openssl/engine.h> |
66 | | #endif |
67 | | |
68 | | #ifdef OPENSSL_FIPS |
69 | | # include <openssl/fips.h> |
70 | | # include <openssl/fips_rand.h> |
71 | | # include "rand_lcl.h" |
72 | | #endif |
73 | | |
74 | | #ifndef OPENSSL_NO_ENGINE |
75 | | /* non-NULL if default_RAND_meth is ENGINE-provided */ |
76 | | static ENGINE *funct_ref = NULL; |
77 | | #endif |
78 | | static const RAND_METHOD *default_RAND_meth = NULL; |
79 | | |
80 | | int RAND_set_rand_method(const RAND_METHOD *meth) |
81 | 0 | { |
82 | 0 | #ifndef OPENSSL_NO_ENGINE |
83 | 0 | if (funct_ref) { |
84 | 0 | ENGINE_finish(funct_ref); |
85 | 0 | funct_ref = NULL; |
86 | 0 | } |
87 | 0 | #endif |
88 | 0 | default_RAND_meth = meth; |
89 | 0 | return 1; |
90 | 0 | } |
91 | | |
92 | | const RAND_METHOD *RAND_get_rand_method(void) |
93 | 49.6k | { |
94 | 49.6k | if (!default_RAND_meth) { |
95 | 18 | #ifndef OPENSSL_NO_ENGINE |
96 | 18 | ENGINE *e = ENGINE_get_default_RAND(); |
97 | 18 | if (e) { |
98 | 0 | default_RAND_meth = ENGINE_get_RAND(e); |
99 | 0 | if (!default_RAND_meth) { |
100 | 0 | ENGINE_finish(e); |
101 | 0 | e = NULL; |
102 | 0 | } |
103 | 0 | } |
104 | 18 | if (e) |
105 | 0 | funct_ref = e; |
106 | 18 | else |
107 | 18 | #endif |
108 | 18 | default_RAND_meth = RAND_SSLeay(); |
109 | 18 | } |
110 | 49.6k | return default_RAND_meth; |
111 | 49.6k | } |
112 | | |
113 | | #ifndef OPENSSL_NO_ENGINE |
114 | | int RAND_set_rand_engine(ENGINE *engine) |
115 | 0 | { |
116 | 0 | const RAND_METHOD *tmp_meth = NULL; |
117 | 0 | if (engine) { |
118 | 0 | if (!ENGINE_init(engine)) |
119 | 0 | return 0; |
120 | 0 | tmp_meth = ENGINE_get_RAND(engine); |
121 | 0 | if (!tmp_meth) { |
122 | 0 | ENGINE_finish(engine); |
123 | 0 | return 0; |
124 | 0 | } |
125 | 0 | } |
126 | | /* This function releases any prior ENGINE so call it first */ |
127 | 0 | RAND_set_rand_method(tmp_meth); |
128 | 0 | funct_ref = engine; |
129 | 0 | return 1; |
130 | 0 | } |
131 | | #endif |
132 | | |
133 | | void RAND_cleanup(void) |
134 | 0 | { |
135 | 0 | const RAND_METHOD *meth = RAND_get_rand_method(); |
136 | 0 | if (meth && meth->cleanup) |
137 | 0 | meth->cleanup(); |
138 | 0 | RAND_set_rand_method(NULL); |
139 | 0 | } |
140 | | |
141 | | void RAND_seed(const void *buf, int num) |
142 | 0 | { |
143 | 0 | const RAND_METHOD *meth = RAND_get_rand_method(); |
144 | 0 | if (meth && meth->seed) |
145 | 0 | meth->seed(buf, num); |
146 | 0 | } |
147 | | |
148 | | void RAND_add(const void *buf, int num, double entropy) |
149 | 72 | { |
150 | 72 | const RAND_METHOD *meth = RAND_get_rand_method(); |
151 | 72 | if (meth && meth->add) |
152 | 72 | meth->add(buf, num, entropy); |
153 | 72 | } |
154 | | |
155 | | int RAND_bytes(unsigned char *buf, int num) |
156 | 30.3k | { |
157 | 30.3k | const RAND_METHOD *meth = RAND_get_rand_method(); |
158 | 30.3k | if (meth && meth->bytes) |
159 | 30.3k | return meth->bytes(buf, num); |
160 | 0 | return (-1); |
161 | 30.3k | } |
162 | | |
163 | | int RAND_pseudo_bytes(unsigned char *buf, int num) |
164 | 0 | { |
165 | 0 | const RAND_METHOD *meth = RAND_get_rand_method(); |
166 | 0 | if (meth && meth->pseudorand) |
167 | 0 | return meth->pseudorand(buf, num); |
168 | 0 | return (-1); |
169 | 0 | } |
170 | | |
171 | | int RAND_status(void) |
172 | 19.2k | { |
173 | 19.2k | const RAND_METHOD *meth = RAND_get_rand_method(); |
174 | 19.2k | if (meth && meth->status) |
175 | 19.2k | return meth->status(); |
176 | 0 | return 0; |
177 | 19.2k | } |
178 | | |
179 | | #ifdef OPENSSL_FIPS |
180 | | |
181 | | /* |
182 | | * FIPS DRBG initialisation code. This sets up the DRBG for use by the rest |
183 | | * of OpenSSL. |
184 | | */ |
185 | | |
186 | | /* |
187 | | * Entropy gatherer: use standard OpenSSL PRNG to seed (this will gather |
188 | | * entropy internally through RAND_poll(). |
189 | | */ |
190 | | |
191 | | static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout, |
192 | | int entropy, size_t min_len, size_t max_len) |
193 | | { |
194 | | /* Round up request to multiple of block size */ |
195 | | min_len = ((min_len + 19) / 20) * 20; |
196 | | *pout = OPENSSL_malloc(min_len); |
197 | | if (!*pout) |
198 | | return 0; |
199 | | if (ssleay_rand_bytes(*pout, min_len, 0, 0) <= 0) { |
200 | | OPENSSL_free(*pout); |
201 | | *pout = NULL; |
202 | | return 0; |
203 | | } |
204 | | return min_len; |
205 | | } |
206 | | |
207 | | static void drbg_free_entropy(DRBG_CTX *ctx, unsigned char *out, size_t olen) |
208 | | { |
209 | | if (out) { |
210 | | OPENSSL_cleanse(out, olen); |
211 | | OPENSSL_free(out); |
212 | | } |
213 | | } |
214 | | |
215 | | /* |
216 | | * Set "additional input" when generating random data. This uses the current |
217 | | * PID, a time value and a counter. |
218 | | */ |
219 | | |
220 | | static size_t drbg_get_adin(DRBG_CTX *ctx, unsigned char **pout) |
221 | | { |
222 | | /* Use of static variables is OK as this happens under a lock */ |
223 | | static unsigned char buf[16]; |
224 | | static unsigned long counter; |
225 | | FIPS_get_timevec(buf, &counter); |
226 | | *pout = buf; |
227 | | return sizeof(buf); |
228 | | } |
229 | | |
230 | | /* |
231 | | * RAND_add() and RAND_seed() pass through to OpenSSL PRNG so it is |
232 | | * correctly seeded by RAND_poll(). |
233 | | */ |
234 | | |
235 | | static int drbg_rand_add(DRBG_CTX *ctx, const void *in, int inlen, |
236 | | double entropy) |
237 | | { |
238 | | RAND_SSLeay()->add(in, inlen, entropy); |
239 | | return 1; |
240 | | } |
241 | | |
242 | | static int drbg_rand_seed(DRBG_CTX *ctx, const void *in, int inlen) |
243 | | { |
244 | | RAND_SSLeay()->seed(in, inlen); |
245 | | return 1; |
246 | | } |
247 | | |
248 | | # ifndef OPENSSL_DRBG_DEFAULT_TYPE |
249 | | # define OPENSSL_DRBG_DEFAULT_TYPE NID_aes_256_ctr |
250 | | # endif |
251 | | # ifndef OPENSSL_DRBG_DEFAULT_FLAGS |
252 | | # define OPENSSL_DRBG_DEFAULT_FLAGS DRBG_FLAG_CTR_USE_DF |
253 | | # endif |
254 | | |
255 | | static int fips_drbg_type = OPENSSL_DRBG_DEFAULT_TYPE; |
256 | | static int fips_drbg_flags = OPENSSL_DRBG_DEFAULT_FLAGS; |
257 | | |
258 | | void RAND_set_fips_drbg_type(int type, int flags) |
259 | | { |
260 | | fips_drbg_type = type; |
261 | | fips_drbg_flags = flags; |
262 | | } |
263 | | |
264 | | int RAND_init_fips(void) |
265 | | { |
266 | | DRBG_CTX *dctx; |
267 | | size_t plen; |
268 | | unsigned char pers[32], *p; |
269 | | # ifndef OPENSSL_ALLOW_DUAL_EC_DRBG |
270 | | if (fips_drbg_type >> 16) { |
271 | | RANDerr(RAND_F_RAND_INIT_FIPS, RAND_R_DUAL_EC_DRBG_DISABLED); |
272 | | return 0; |
273 | | } |
274 | | # endif |
275 | | |
276 | | dctx = FIPS_get_default_drbg(); |
277 | | if (FIPS_drbg_init(dctx, fips_drbg_type, fips_drbg_flags) <= 0) { |
278 | | RANDerr(RAND_F_RAND_INIT_FIPS, RAND_R_ERROR_INITIALISING_DRBG); |
279 | | return 0; |
280 | | } |
281 | | |
282 | | FIPS_drbg_set_callbacks(dctx, |
283 | | drbg_get_entropy, drbg_free_entropy, 20, |
284 | | drbg_get_entropy, drbg_free_entropy); |
285 | | FIPS_drbg_set_rand_callbacks(dctx, drbg_get_adin, 0, |
286 | | drbg_rand_seed, drbg_rand_add); |
287 | | /* Personalisation string: a string followed by date time vector */ |
288 | | strcpy((char *)pers, "OpenSSL DRBG2.0"); |
289 | | plen = drbg_get_adin(dctx, &p); |
290 | | memcpy(pers + 16, p, plen); |
291 | | |
292 | | if (FIPS_drbg_instantiate(dctx, pers, sizeof(pers)) <= 0) { |
293 | | RANDerr(RAND_F_RAND_INIT_FIPS, RAND_R_ERROR_INSTANTIATING_DRBG); |
294 | | return 0; |
295 | | } |
296 | | FIPS_rand_set_method(FIPS_drbg_method()); |
297 | | return 1; |
298 | | } |
299 | | |
300 | | #endif |