summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/rand
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/rand')
-rw-r--r--src/lib/libcrypto/rand/Makefile.ssl17
-rw-r--r--src/lib/libcrypto/rand/md_rand.c312
-rw-r--r--src/lib/libcrypto/rand/md_rand_munged.c515
-rw-r--r--src/lib/libcrypto/rand/rand.h29
-rw-r--r--src/lib/libcrypto/rand/rand_egd.c110
-rw-r--r--src/lib/libcrypto/rand/rand_err.c93
-rw-r--r--src/lib/libcrypto/rand/rand_lib.c18
-rw-r--r--src/lib/libcrypto/rand/randfile.c108
-rw-r--r--src/lib/libcrypto/rand/randtest.c2
9 files changed, 1093 insertions, 111 deletions
diff --git a/src/lib/libcrypto/rand/Makefile.ssl b/src/lib/libcrypto/rand/Makefile.ssl
index 014356cb18..be8eea34a2 100644
--- a/src/lib/libcrypto/rand/Makefile.ssl
+++ b/src/lib/libcrypto/rand/Makefile.ssl
@@ -22,8 +22,8 @@ TEST= randtest.c
22APPS= 22APPS=
23 23
24LIB=$(TOP)/libcrypto.a 24LIB=$(TOP)/libcrypto.a
25LIBSRC=md_rand.c randfile.c rand_lib.c 25LIBSRC=md_rand.c randfile.c rand_lib.c rand_err.c rand_egd.c
26LIBOBJ=md_rand.o randfile.o rand_lib.o 26LIBOBJ=md_rand.o randfile.o rand_lib.o rand_err.o rand_egd.o
27 27
28SRC= $(LIBSRC) 28SRC= $(LIBSRC)
29 29
@@ -79,9 +79,14 @@ clean:
79# DO NOT DELETE THIS LINE -- make depend depends on it. 79# DO NOT DELETE THIS LINE -- make depend depends on it.
80 80
81md_rand.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h 81md_rand.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h
82md_rand.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h 82md_rand.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
83md_rand.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h 83md_rand.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
84md_rand.o: ../../include/openssl/rand.h ../../include/openssl/safestack.h
84md_rand.o: ../../include/openssl/sha.h ../../include/openssl/stack.h 85md_rand.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
86rand_egd.o: ../../include/openssl/opensslconf.h ../../include/openssl/rand.h
87rand_err.o: ../../include/openssl/err.h ../../include/openssl/rand.h
85rand_lib.o: ../../include/openssl/rand.h 88rand_lib.o: ../../include/openssl/rand.h
86randfile.o: ../../include/openssl/e_os.h ../../include/openssl/e_os2.h 89randfile.o: ../../include/openssl/crypto.h ../../include/openssl/e_os.h
87randfile.o: ../../include/openssl/opensslconf.h ../../include/openssl/rand.h 90randfile.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
91randfile.o: ../../include/openssl/opensslv.h ../../include/openssl/rand.h
92randfile.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
diff --git a/src/lib/libcrypto/rand/md_rand.c b/src/lib/libcrypto/rand/md_rand.c
index c9a071bd22..6b158f0349 100644
--- a/src/lib/libcrypto/rand/md_rand.c
+++ b/src/lib/libcrypto/rand/md_rand.c
@@ -56,15 +56,23 @@
56 * [including the GNU Public Licence.] 56 * [including the GNU Public Licence.]
57 */ 57 */
58 58
59#define ENTROPY_NEEDED 16 /* require 128 bits = 16 bytes of randomness */
60
61#ifndef MD_RAND_DEBUG
62# ifndef NDEBUG
63# define NDEBUG
64# endif
65#endif
66
67#include <assert.h>
59#include <stdio.h> 68#include <stdio.h>
60#include <sys/types.h>
61#include <fcntl.h>
62#include <time.h> 69#include <time.h>
63#include <string.h> 70#include <string.h>
64 71
65#include "openssl/e_os.h" 72#include "openssl/e_os.h"
66 73
67#include <openssl/crypto.h> 74#include <openssl/crypto.h>
75#include <openssl/err.h>
68 76
69#if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND) 77#if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND)
70#if !defined(NO_SHA) && !defined(NO_SHA1) 78#if !defined(NO_SHA) && !defined(NO_SHA1)
@@ -130,17 +138,23 @@ static int state_num=0,state_index=0;
130static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH]; 138static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH];
131static unsigned char md[MD_DIGEST_LENGTH]; 139static unsigned char md[MD_DIGEST_LENGTH];
132static long md_count[2]={0,0}; 140static long md_count[2]={0,0};
141static double entropy=0;
142static int initialized=0;
133 143
134const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT; 144const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT;
135 145
136static void ssleay_rand_cleanup(void); 146static void ssleay_rand_cleanup(void);
137static void ssleay_rand_seed(const void *buf, int num); 147static void ssleay_rand_seed(const void *buf, int num);
138static void ssleay_rand_bytes(unsigned char *buf, int num); 148static void ssleay_rand_add(const void *buf, int num, double add_entropy);
149static int ssleay_rand_bytes(unsigned char *buf, int num);
150static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num);
139 151
140RAND_METHOD rand_ssleay_meth={ 152RAND_METHOD rand_ssleay_meth={
141 ssleay_rand_seed, 153 ssleay_rand_seed,
142 ssleay_rand_bytes, 154 ssleay_rand_bytes,
143 ssleay_rand_cleanup, 155 ssleay_rand_cleanup,
156 ssleay_rand_add,
157 ssleay_rand_pseudo_bytes,
144 }; 158 };
145 159
146RAND_METHOD *RAND_SSLeay(void) 160RAND_METHOD *RAND_SSLeay(void)
@@ -156,22 +170,49 @@ static void ssleay_rand_cleanup(void)
156 memset(md,0,MD_DIGEST_LENGTH); 170 memset(md,0,MD_DIGEST_LENGTH);
157 md_count[0]=0; 171 md_count[0]=0;
158 md_count[1]=0; 172 md_count[1]=0;
173 entropy=0;
159 } 174 }
160 175
161static void ssleay_rand_seed(const void *buf, int num) 176static void ssleay_rand_add(const void *buf, int num, double add)
162 { 177 {
163 int i,j,k,st_idx,st_num; 178 int i,j,k,st_idx;
179 long md_c[2];
180 unsigned char local_md[MD_DIGEST_LENGTH];
164 MD_CTX m; 181 MD_CTX m;
165 182
166#ifdef NORAND 183#ifdef NORAND
167 return; 184 return;
168#endif 185#endif
169 186
187 /*
188 * (Based on the rand(3) manpage)
189 *
190 * The input is chopped up into units of 20 bytes (or less for
191 * the last block). Each of these blocks is run through the hash
192 * function as follows: The data passed to the hash function
193 * is the current 'md', the same number of bytes from the 'state'
194 * (the location determined by in incremented looping index) as
195 * the current 'block', the new key data 'block', and 'count'
196 * (which is incremented after each use).
197 * The result of this is kept in 'md' and also xored into the
198 * 'state' at the same locations that were used as input into the
199 * hash function.
200 */
201
170 CRYPTO_w_lock(CRYPTO_LOCK_RAND); 202 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
171 st_idx=state_index; 203 st_idx=state_index;
172 st_num=state_num;
173 204
174 state_index=(state_index+num); 205 /* use our own copies of the counters so that even
206 * if a concurrent thread seeds with exactly the
207 * same data and uses the same subarray there's _some_
208 * difference */
209 md_c[0] = md_count[0];
210 md_c[1] = md_count[1];
211
212 memcpy(local_md, md, sizeof md);
213
214 /* state_index <= state_num <= STATE_SIZE */
215 state_index += num;
175 if (state_index >= STATE_SIZE) 216 if (state_index >= STATE_SIZE)
176 { 217 {
177 state_index%=STATE_SIZE; 218 state_index%=STATE_SIZE;
@@ -182,6 +223,14 @@ static void ssleay_rand_seed(const void *buf, int num)
182 if (state_index > state_num) 223 if (state_index > state_num)
183 state_num=state_index; 224 state_num=state_index;
184 } 225 }
226 /* state_index <= state_num <= STATE_SIZE */
227
228 /* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE]
229 * are what we will use now, but other threads may use them
230 * as well */
231
232 md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
233
185 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 234 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
186 235
187 for (i=0; i<num; i+=MD_DIGEST_LENGTH) 236 for (i=0; i<num; i+=MD_DIGEST_LENGTH)
@@ -190,7 +239,7 @@ static void ssleay_rand_seed(const void *buf, int num)
190 j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j; 239 j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j;
191 240
192 MD_Init(&m); 241 MD_Init(&m);
193 MD_Update(&m,md,MD_DIGEST_LENGTH); 242 MD_Update(&m,local_md,MD_DIGEST_LENGTH);
194 k=(st_idx+j)-STATE_SIZE; 243 k=(st_idx+j)-STATE_SIZE;
195 if (k > 0) 244 if (k > 0)
196 { 245 {
@@ -201,33 +250,107 @@ static void ssleay_rand_seed(const void *buf, int num)
201 MD_Update(&m,&(state[st_idx]),j); 250 MD_Update(&m,&(state[st_idx]),j);
202 251
203 MD_Update(&m,buf,j); 252 MD_Update(&m,buf,j);
204 MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count)); 253 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
205 MD_Final(md,&m); 254 MD_Final(local_md,&m);
206 md_count[1]++; 255 md_c[1]++;
207 256
208 buf=(const char *)buf + j; 257 buf=(const char *)buf + j;
209 258
210 for (k=0; k<j; k++) 259 for (k=0; k<j; k++)
211 { 260 {
212 state[st_idx++]^=md[k]; 261 /* Parallel threads may interfere with this,
262 * but always each byte of the new state is
263 * the XOR of some previous value of its
264 * and local_md (itermediate values may be lost).
265 * Alway using locking could hurt performance more
266 * than necessary given that conflicts occur only
267 * when the total seeding is longer than the random
268 * state. */
269 state[st_idx++]^=local_md[k];
213 if (st_idx >= STATE_SIZE) 270 if (st_idx >= STATE_SIZE)
214 {
215 st_idx=0; 271 st_idx=0;
216 st_num=STATE_SIZE;
217 }
218 } 272 }
219 } 273 }
220 memset((char *)&m,0,sizeof(m)); 274 memset((char *)&m,0,sizeof(m));
275
276 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
277 /* Don't just copy back local_md into md -- this could mean that
278 * other thread's seeding remains without effect (except for
279 * the incremented counter). By XORing it we keep at least as
280 * much entropy as fits into md. */
281 for (k = 0; k < sizeof md; k++)
282 {
283 md[k] ^= local_md[k];
284 }
285 if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
286 entropy += add;
287 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
288
289#ifndef THREADS
290 assert(md_c[1] == md_count[1]);
291#endif
221 } 292 }
222 293
223static void ssleay_rand_bytes(unsigned char *buf, int num) 294static void ssleay_rand_seed(const void *buf, int num)
295 {
296 ssleay_rand_add(buf, num, num);
297 }
298
299static void ssleay_rand_initialize(void)
224 { 300 {
225 int i,j,k,st_num,st_idx;
226 MD_CTX m;
227 static int init=1;
228 unsigned long l; 301 unsigned long l;
302#ifndef GETPID_IS_MEANINGLESS
303 pid_t curr_pid = getpid();
304#endif
229#ifdef DEVRANDOM 305#ifdef DEVRANDOM
230 int fd; 306 FILE *fh;
307#endif
308
309 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
310 /* put in some default random data, we need more than just this */
311#ifndef GETPID_IS_MEANINGLESS
312 l=curr_pid;
313 RAND_add(&l,sizeof(l),0);
314 l=getuid();
315 RAND_add(&l,sizeof(l),0);
316#endif
317 l=time(NULL);
318 RAND_add(&l,sizeof(l),0);
319
320#ifdef DEVRANDOM
321 /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD
322 * have this. Use /dev/urandom if you can as /dev/random may block
323 * if it runs out of random entries. */
324
325 if ((fh = fopen(DEVRANDOM, "r")) != NULL)
326 {
327 unsigned char tmpbuf[ENTROPY_NEEDED];
328 int n;
329
330 setvbuf(fh, NULL, _IONBF, 0);
331 n=fread((unsigned char *)tmpbuf,1,ENTROPY_NEEDED,fh);
332 fclose(fh);
333 RAND_add(tmpbuf,sizeof tmpbuf,n);
334 memset(tmpbuf,0,n);
335 }
336#endif
337#ifdef PURIFY
338 memset(state,0,STATE_SIZE);
339 memset(md,0,MD_DIGEST_LENGTH);
340#endif
341 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
342 initialized=1;
343 }
344
345static int ssleay_rand_bytes(unsigned char *buf, int num)
346 {
347 int i,j,k,st_num,st_idx;
348 int ok;
349 long md_c[2];
350 unsigned char local_md[MD_DIGEST_LENGTH];
351 MD_CTX m;
352#ifndef GETPID_IS_MEANINGLESS
353 pid_t curr_pid = getpid();
231#endif 354#endif
232 355
233#ifdef PREDICT 356#ifdef PREDICT
@@ -236,65 +359,63 @@ static void ssleay_rand_bytes(unsigned char *buf, int num)
236 359
237 for (i=0; i<num; i++) 360 for (i=0; i<num; i++)
238 buf[i]=val++; 361 buf[i]=val++;
239 return; 362 return(1);
240 } 363 }
241#endif 364#endif
242 365
366 /*
367 * (Based on the rand(3) manpage:)
368 *
369 * For each group of 10 bytes (or less), we do the following:
370 *
371 * Input into the hash function the top 10 bytes from the
372 * local 'md' (which is initialized from the global 'md'
373 * before any bytes are generated), the bytes that are
374 * to be overwritten by the random bytes, and bytes from the
375 * 'state' (incrementing looping index). From this digest output
376 * (which is kept in 'md'), the top (up to) 10 bytes are
377 * returned to the caller and the bottom (up to) 10 bytes are xored
378 * into the 'state'.
379 * Finally, after we have finished 'num' random bytes for the
380 * caller, 'count' (which is incremented) and the local and global 'md'
381 * are fed into the hash function and the results are kept in the
382 * global 'md'.
383 */
384
243 CRYPTO_w_lock(CRYPTO_LOCK_RAND); 385 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
244 386
245 if (init) 387 if (!initialized)
388 ssleay_rand_initialize();
389
390 ok = (entropy >= ENTROPY_NEEDED);
391 if (!ok)
246 { 392 {
247 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 393 /* If the PRNG state is not yet unpredictable, then seeing
248 /* put in some default random data, we need more than 394 * the PRNG output may help attackers to determine the new
249 * just this */ 395 * state; thus we have to decrease the entropy estimate.
250 RAND_seed(&m,sizeof(m)); 396 * Once we've had enough initial seeding we don't bother to
251#ifndef MSDOS 397 * adjust the entropy count, though, because we're not ambitious
252 l=getpid(); 398 * to provide *information-theoretic* randomness.
253 RAND_seed(&l,sizeof(l));
254 l=getuid();
255 RAND_seed(&l,sizeof(l));
256#endif
257 l=time(NULL);
258 RAND_seed(&l,sizeof(l));
259
260/* #ifdef DEVRANDOM */
261 /*
262 * Use a random entropy pool device.
263 * Linux 1.3.x, OpenBSD, and FreeBSD have
264 * this. Use /dev/urandom if you can
265 * as /dev/random will block if it runs out
266 * of random entries.
267 */ 399 */
268 if ((fd = open(DEVRANDOM, O_RDONLY)) != NULL) 400 entropy -= num;
269 { 401 if (entropy < 0)
270 unsigned char tmpbuf[32]; 402 entropy = 0;
271
272 read(fd, tmpbuf, sizeof(tmpbuf));
273 /* we don't care how many bytes we read,
274 * we will just copy the 'stack' if there is
275 * nothing else :-) */
276 /* the above comment is EVIL. Security software
277 * RELIES ON THESE PRIMITIVES HAVING MORE SECURE
278 * BEHAVIOUR! Secure entropy is required in
279 * many cases! */
280 RAND_seed(tmpbuf,32);
281 memset(tmpbuf,0,32);
282 }
283/* #endif */
284#ifdef PURIFY
285 memset(state,0,STATE_SIZE);
286 memset(md,0,MD_DIGEST_LENGTH);
287#endif
288 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
289 init=0;
290 } 403 }
291 404
292 st_idx=state_index; 405 st_idx=state_index;
293 st_num=state_num; 406 st_num=state_num;
407 md_c[0] = md_count[0];
408 md_c[1] = md_count[1];
409 memcpy(local_md, md, sizeof md);
410
294 state_index+=num; 411 state_index+=num;
295 if (state_index > state_num) 412 if (state_index > state_num)
296 state_index=(state_index%state_num); 413 state_index %= state_num;
414
415 /* state[st_idx], ..., state[(st_idx + num - 1) % st_num]
416 * are now ours (but other threads may use them too) */
297 417
418 md_count[0] += 1;
298 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 419 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
299 420
300 while (num > 0) 421 while (num > 0)
@@ -302,8 +423,15 @@ static void ssleay_rand_bytes(unsigned char *buf, int num)
302 j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num; 423 j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num;
303 num-=j; 424 num-=j;
304 MD_Init(&m); 425 MD_Init(&m);
305 MD_Update(&m,&(md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2); 426#ifndef GETPID_IS_MEANINGLESS
306 MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count)); 427 if (curr_pid) /* just in the first iteration to save time */
428 {
429 MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid);
430 curr_pid = 0;
431 }
432#endif
433 MD_Update(&m,&(local_md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2);
434 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
307#ifndef PURIFY 435#ifndef PURIFY
308 MD_Update(&m,buf,j); /* purify complains */ 436 MD_Update(&m,buf,j); /* purify complains */
309#endif 437#endif
@@ -315,23 +443,57 @@ static void ssleay_rand_bytes(unsigned char *buf, int num)
315 } 443 }
316 else 444 else
317 MD_Update(&m,&(state[st_idx]),j); 445 MD_Update(&m,&(state[st_idx]),j);
318 MD_Final(md,&m); 446 MD_Final(local_md,&m);
319 447
320 for (i=0; i<j; i++) 448 for (i=0; i<j; i++)
321 { 449 {
450 state[st_idx++]^=local_md[i]; /* may compete with other threads */
451 *(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
322 if (st_idx >= st_num) 452 if (st_idx >= st_num)
323 st_idx=0; 453 st_idx=0;
324 state[st_idx++]^=md[i];
325 *(buf++)=md[i+MD_DIGEST_LENGTH/2];
326 } 454 }
327 } 455 }
328 456
329 MD_Init(&m); 457 MD_Init(&m);
330 MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count)); 458 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
331 md_count[0]++; 459 MD_Update(&m,local_md,MD_DIGEST_LENGTH);
460 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
332 MD_Update(&m,md,MD_DIGEST_LENGTH); 461 MD_Update(&m,md,MD_DIGEST_LENGTH);
333 MD_Final(md,&m); 462 MD_Final(md,&m);
463 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
464
334 memset(&m,0,sizeof(m)); 465 memset(&m,0,sizeof(m));
466 if (ok)
467 return(1);
468 else
469 {
470 RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
471 return(0);
472 }
473 }
474
475/* pseudo-random bytes that are guaranteed to be unique but not
476 unpredictable */
477static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num)
478 {
479 int ret, err;
480
481 ret = RAND_bytes(buf, num);
482 if (ret == 0)
483 {
484 err = ERR_peek_error();
485 if (ERR_GET_LIB(err) == ERR_LIB_RAND &&
486 ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED)
487 (void)ERR_get_error();
488 }
489 return (ret);
490 }
491
492int RAND_status(void)
493 {
494 if (!initialized)
495 ssleay_rand_initialize();
496 return (entropy >= ENTROPY_NEEDED);
335 } 497 }
336 498
337#ifdef WINDOWS 499#ifdef WINDOWS
@@ -358,12 +520,12 @@ static void ssleay_rand_bytes(unsigned char *buf, int num)
358 */ 520 */
359/* 521/*
360 * I have modified the loading of bytes via RAND_seed() mechanism since 522 * I have modified the loading of bytes via RAND_seed() mechanism since
361 * the origional would have been very very CPU intensive since RAND_seed() 523 * the original would have been very very CPU intensive since RAND_seed()
362 * does an MD5 per 16 bytes of input. The cost to digest 16 bytes is the same 524 * does an MD5 per 16 bytes of input. The cost to digest 16 bytes is the same
363 * as that to digest 56 bytes. So under the old system, a screen of 525 * as that to digest 56 bytes. So under the old system, a screen of
364 * 1024*768*256 would have been CPU cost of approximatly 49,000 56 byte MD5 526 * 1024*768*256 would have been CPU cost of approximately 49,000 56 byte MD5
365 * digests or digesting 2.7 mbytes. What I have put in place would 527 * digests or digesting 2.7 mbytes. What I have put in place would
366 * be 48 16k MD5 digests, or efectivly 48*16+48 MD5 bytes or 816 kbytes 528 * be 48 16k MD5 digests, or effectively 48*16+48 MD5 bytes or 816 kbytes
367 * or about 3.5 times as much. 529 * or about 3.5 times as much.
368 * - eric 530 * - eric
369 */ 531 */
diff --git a/src/lib/libcrypto/rand/md_rand_munged.c b/src/lib/libcrypto/rand/md_rand_munged.c
new file mode 100644
index 0000000000..1611bf335b
--- /dev/null
+++ b/src/lib/libcrypto/rand/md_rand_munged.c
@@ -0,0 +1,515 @@
1/* crypto/rand/md_rand.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 <sys/types.h>
61#include <fcntl.h>
62#include <time.h>
63#include <string.h>
64
65#include "openssl/e_os.h"
66
67#include <openssl/crypto.h>
68
69#if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND)
70#if !defined(NO_SHA) && !defined(NO_SHA1)
71#define USE_SHA1_RAND
72#elif !defined(NO_MD5)
73#define USE_MD5_RAND
74#elif !defined(NO_MDC2) && !defined(NO_DES)
75#define USE_MDC2_RAND
76#elif !defined(NO_MD2)
77#define USE_MD2_RAND
78#else
79#error No message digest algorithm available
80#endif
81#endif
82
83/* Changed how the state buffer used. I now attempt to 'wrap' such
84 * that I don't run over the same locations the next time go through
85 * the 1023 bytes - many thanks to
86 * Robert J. LeBlanc <rjl@renaissoft.com> for his comments
87 */
88
89#if defined(USE_MD5_RAND)
90#include <openssl/md5.h>
91#define MD_DIGEST_LENGTH MD5_DIGEST_LENGTH
92#define MD_CTX MD5_CTX
93#define MD_Init(a) MD5_Init(a)
94#define MD_Update(a,b,c) MD5_Update(a,b,c)
95#define MD_Final(a,b) MD5_Final(a,b)
96#define MD(a,b,c) MD5(a,b,c)
97#elif defined(USE_SHA1_RAND)
98#include <openssl/sha.h>
99#define MD_DIGEST_LENGTH SHA_DIGEST_LENGTH
100#define MD_CTX SHA_CTX
101#define MD_Init(a) SHA1_Init(a)
102#define MD_Update(a,b,c) SHA1_Update(a,b,c)
103#define MD_Final(a,b) SHA1_Final(a,b)
104#define MD(a,b,c) SHA1(a,b,c)
105#elif defined(USE_MDC2_RAND)
106#include <openssl/mdc2.h>
107#define MD_DIGEST_LENGTH MDC2_DIGEST_LENGTH
108#define MD_CTX MDC2_CTX
109#define MD_Init(a) MDC2_Init(a)
110#define MD_Update(a,b,c) MDC2_Update(a,b,c)
111#define MD_Final(a,b) MDC2_Final(a,b)
112#define MD(a,b,c) MDC2(a,b,c)
113#elif defined(USE_MD2_RAND)
114#include <openssl/md2.h>
115#define MD_DIGEST_LENGTH MD2_DIGEST_LENGTH
116#define MD_CTX MD2_CTX
117#define MD_Init(a) MD2_Init(a)
118#define MD_Update(a,b,c) MD2_Update(a,b,c)
119#define MD_Final(a,b) MD2_Final(a,b)
120#define MD(a,b,c) MD2(a,b,c)
121#endif
122
123#include <openssl/rand.h>
124
125/* #define NORAND 1 */
126/* #define PREDICT 1 */
127
128#define STATE_SIZE 1023
129static int state_num=0,state_index=0;
130static unsigned char state[STATE_SIZE+MD_DIGEST_LENGTH];
131static unsigned char md[MD_DIGEST_LENGTH];
132static long md_count[2]={0,0};
133static double entropy=0;
134static int initialized=0;
135
136const char *RAND_version="RAND" OPENSSL_VERSION_PTEXT;
137
138static void ssleay_rand_cleanup(void);
139static void ssleay_rand_seed(const void *buf, int num);
140static void ssleay_rand_add(const void *buf, int num, double add_entropy);
141static int ssleay_rand_bytes(unsigned char *buf, int num);
142static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num);
143
144RAND_METHOD rand_ssleay_meth={
145 ssleay_rand_seed,
146 ssleay_rand_bytes,
147 ssleay_rand_cleanup,
148 ssleay_rand_add,
149 ssleay_rand_pseudo_bytes,
150 };
151
152RAND_METHOD *RAND_SSLeay(void)
153 {
154 return(&rand_ssleay_meth);
155 }
156
157static void ssleay_rand_cleanup(void)
158 {
159 memset(state,0,sizeof(state));
160 state_num=0;
161 state_index=0;
162 memset(md,0,MD_DIGEST_LENGTH);
163 md_count[0]=0;
164 md_count[1]=0;
165 entropy=0;
166 }
167
168static void ssleay_rand_add(const void *buf, int num, double add)
169 {
170 int i,j,k,st_idx;
171 long md_c[2];
172 unsigned char local_md[MD_DIGEST_LENGTH];
173 MD_CTX m;
174
175#ifdef NORAND
176 return;
177#endif
178
179 /*
180 * (Based on the rand(3) manpage)
181 *
182 * The input is chopped up into units of 20 bytes (or less for
183 * the last block). Each of these blocks is run through the hash
184 * function as follows: The data passed to the hash function
185 * is the current 'md', the same number of bytes from the 'state'
186 * (the location determined by in incremented looping index) as
187 * the current 'block', the new key data 'block', and 'count'
188 * (which is incremented after each use).
189 * The result of this is kept in 'md' and also xored into the
190 * 'state' at the same locations that were used as input into the
191 * hash function.
192 */
193
194 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
195 st_idx=state_index;
196
197 /* use our own copies of the counters so that even
198 * if a concurrent thread seeds with exactly the
199 * same data and uses the same subarray there's _some_
200 * difference */
201 md_c[0] = md_count[0];
202 md_c[1] = md_count[1];
203
204 memcpy(local_md, md, sizeof md);
205
206 /* state_index <= state_num <= STATE_SIZE */
207 state_index += num;
208 if (state_index >= STATE_SIZE)
209 {
210 state_index%=STATE_SIZE;
211 state_num=STATE_SIZE;
212 }
213 else if (state_num < STATE_SIZE)
214 {
215 if (state_index > state_num)
216 state_num=state_index;
217 }
218 /* state_index <= state_num <= STATE_SIZE */
219
220 /* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE]
221 * are what we will use now, but other threads may use them
222 * as well */
223
224 md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
225
226 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
227
228 for (i=0; i<num; i+=MD_DIGEST_LENGTH)
229 {
230 j=(num-i);
231 j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j;
232
233 MD_Init(&m);
234 MD_Update(&m,local_md,MD_DIGEST_LENGTH);
235 k=(st_idx+j)-STATE_SIZE;
236 if (k > 0)
237 {
238 MD_Update(&m,&(state[st_idx]),j-k);
239 MD_Update(&m,&(state[0]),k);
240 }
241 else
242 MD_Update(&m,&(state[st_idx]),j);
243
244 MD_Update(&m,buf,j);
245 MD_Update(&m,(unsigned char *)&(md_count[0]),sizeof(md_count));
246 MD_Final(md,&m);
247 md_count[1]++;
248
249 buf=(const char *)buf + j;
250
251 for (k=0; k<j; k++)
252 {
253 state[st_idx++]^=md[k];
254 if (st_idx >= STATE_SIZE)
255 {
256 st_idx=0;
257 st_num=STATE_SIZE;
258 }
259 }
260 }
261 memset((char *)&m,0,sizeof(m));
262 }
263
264static void ssleay_rand_bytes(unsigned char *buf, int num)
265 {
266 int i,j,k,st_num,st_idx;
267 MD_CTX m;
268 static int init=1;
269 unsigned long l;
270#ifdef DEVRANDOM
271 int fd;
272#endif
273
274#ifdef PREDICT
275 {
276 static unsigned char val=0;
277
278 for (i=0; i<num; i++)
279 buf[i]=val++;
280 return;
281 }
282#endif
283
284 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
285
286 if (init)
287 {
288 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
289 /* put in some default random data, we need more than
290 * just this */
291 RAND_seed(&m,sizeof(m));
292#ifndef MSDOS
293 l=getpid();
294 RAND_seed(&l,sizeof(l));
295 l=getuid();
296 RAND_seed(&l,sizeof(l));
297#endif
298 l=time(NULL);
299 RAND_seed(&l,sizeof(l));
300
301/* #ifdef DEVRANDOM */
302 /*
303 * Use a random entropy pool device.
304 * Linux 1.3.x, OpenBSD, and FreeBSD have
305 * this. Use /dev/urandom if you can
306 * as /dev/random will block if it runs out
307 * of random entries.
308 */
309 if ((fd = open(DEVRANDOM, O_RDONLY)) != NULL)
310 {
311 unsigned char tmpbuf[32];
312
313 read(fd, tmpbuf, sizeof(tmpbuf));
314 /* we don't care how many bytes we read,
315 * we will just copy the 'stack' if there is
316 * nothing else :-) */
317 /* the above comment is EVIL. Security software
318 * RELIES ON THESE PRIMITIVES HAVING MORE SECURE
319 * BEHAVIOUR! Secure entropy is required in
320 * many cases! */
321 RAND_seed(tmpbuf,32);
322 memset(tmpbuf,0,32);
323 }
324/* #endif */
325#ifdef PURIFY
326 memset(state,0,STATE_SIZE);
327 memset(md,0,MD_DIGEST_LENGTH);
328#endif
329 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
330 init=0;
331 }
332
333 st_idx=state_index;
334 st_num=state_num;
335 state_index+=num;
336 if (state_index > state_num)
337 state_index=(state_index%state_num);
338
339 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
340
341 while (num > 0)
342 {
343 j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num;
344 num-=j;
345 MD_Init(&m);
346#ifndef GETPID_IS_MEANINGLESS
347 if (curr_pid) /* just in the first iteration to save time */
348 {
349 MD_Update(&m,(unsigned char*)&curr_pid,sizeof curr_pid);
350 curr_pid = 0;
351 }
352#endif
353 MD_Update(&m,&(local_md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2);
354 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
355#ifndef PURIFY
356 MD_Update(&m,buf,j); /* purify complains */
357#endif
358 k=(st_idx+j)-st_num;
359 if (k > 0)
360 {
361 MD_Update(&m,&(state[st_idx]),j-k);
362 MD_Update(&m,&(state[0]),k);
363 }
364 else
365 MD_Update(&m,&(state[st_idx]),j);
366 MD_Final(local_md,&m);
367
368 for (i=0; i<j; i++)
369 {
370 state[st_idx++]^=local_md[i]; /* may compete with other threads */
371 *(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
372 if (st_idx >= st_num)
373 st_idx=0;
374 }
375 }
376
377 MD_Init(&m);
378 MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
379 MD_Update(&m,local_md,MD_DIGEST_LENGTH);
380 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
381 MD_Update(&m,md,MD_DIGEST_LENGTH);
382 MD_Final(md,&m);
383 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
384
385 memset(&m,0,sizeof(m));
386 if (ok)
387 return(1);
388 else
389 {
390 RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
391 return(0);
392 }
393 }
394
395/* pseudo-random bytes that are guaranteed to be unique but not
396 unpredictable */
397static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num)
398 {
399 int ret, err;
400
401 ret = RAND_bytes(buf, num);
402 if (ret == 0)
403 {
404 err = ERR_peek_error();
405 if (ERR_GET_LIB(err) == ERR_LIB_RAND &&
406 ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED)
407 (void)ERR_get_error();
408 }
409 return (ret);
410 }
411
412int RAND_status(void)
413 {
414 if (!initialized)
415 ssleay_rand_initialize();
416 return (entropy >= ENTROPY_NEEDED);
417 }
418
419#ifdef WINDOWS
420#include <windows.h>
421#include <openssl/rand.h>
422
423/*****************************************************************************
424 * Initialisation function for the SSL random generator. Takes the contents
425 * of the screen as random seed.
426 *
427 * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
428 *
429 * Code adapted from
430 * <URL:http://www.microsoft.com/kb/developr/win_dk/q97193.htm>;
431 * the original copyright message is:
432 *
433 * (C) Copyright Microsoft Corp. 1993. All rights reserved.
434 *
435 * You have a royalty-free right to use, modify, reproduce and
436 * distribute the Sample Files (and/or any modified version) in
437 * any way you find useful, provided that you agree that
438 * Microsoft has no warranty obligations or liability for any
439 * Sample Application Files which are modified.
440 */
441/*
442 * I have modified the loading of bytes via RAND_seed() mechanism since
443 * the original would have been very very CPU intensive since RAND_seed()
444 * does an MD5 per 16 bytes of input. The cost to digest 16 bytes is the same
445 * as that to digest 56 bytes. So under the old system, a screen of
446 * 1024*768*256 would have been CPU cost of approximately 49,000 56 byte MD5
447 * digests or digesting 2.7 mbytes. What I have put in place would
448 * be 48 16k MD5 digests, or effectively 48*16+48 MD5 bytes or 816 kbytes
449 * or about 3.5 times as much.
450 * - eric
451 */
452void RAND_screen(void)
453{
454 HDC hScrDC; /* screen DC */
455 HDC hMemDC; /* memory DC */
456 HBITMAP hBitmap; /* handle for our bitmap */
457 HBITMAP hOldBitmap; /* handle for previous bitmap */
458 BITMAP bm; /* bitmap properties */
459 unsigned int size; /* size of bitmap */
460 char *bmbits; /* contents of bitmap */
461 int w; /* screen width */
462 int h; /* screen height */
463 int y; /* y-coordinate of screen lines to grab */
464 int n = 16; /* number of screen lines to grab at a time */
465
466 /* Create a screen DC and a memory DC compatible to screen DC */
467 hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
468 hMemDC = CreateCompatibleDC(hScrDC);
469
470 /* Get screen resolution */
471 w = GetDeviceCaps(hScrDC, HORZRES);
472 h = GetDeviceCaps(hScrDC, VERTRES);
473
474 /* Create a bitmap compatible with the screen DC */
475 hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
476
477 /* Select new bitmap into memory DC */
478 hOldBitmap = SelectObject(hMemDC, hBitmap);
479
480 /* Get bitmap properties */
481 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
482 size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
483
484 bmbits = Malloc(size);
485 if (bmbits) {
486 /* Now go through the whole screen, repeatedly grabbing n lines */
487 for (y = 0; y < h-n; y += n)
488 {
489 unsigned char md[MD_DIGEST_LENGTH];
490
491 /* Bitblt screen DC to memory DC */
492 BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
493
494 /* Copy bitmap bits from memory DC to bmbits */
495 GetBitmapBits(hBitmap, size, bmbits);
496
497 /* Get the MD5 of the bitmap */
498 MD(bmbits,size,md);
499
500 /* Seed the random generator with the MD5 digest */
501 RAND_seed(md, MD_DIGEST_LENGTH);
502 }
503
504 Free(bmbits);
505 }
506
507 /* Select old bitmap back into memory DC */
508 hBitmap = SelectObject(hMemDC, hOldBitmap);
509
510 /* Clean up */
511 DeleteObject(hBitmap);
512 DeleteDC(hMemDC);
513 DeleteDC(hScrDC);
514}
515#endif
diff --git a/src/lib/libcrypto/rand/rand.h b/src/lib/libcrypto/rand/rand.h
index fd8ee38366..28f45ec052 100644
--- a/src/lib/libcrypto/rand/rand.h
+++ b/src/lib/libcrypto/rand/rand.h
@@ -66,24 +66,45 @@ extern "C" {
66typedef struct rand_meth_st 66typedef struct rand_meth_st
67 { 67 {
68 void (*seed)(const void *buf, int num); 68 void (*seed)(const void *buf, int num);
69 void (*bytes)(unsigned char *buf, int num); 69 int (*bytes)(unsigned char *buf, int num);
70 void (*cleanup)(void); 70 void (*cleanup)(void);
71 void (*add)(const void *buf, int num, double entropy);
72 int (*pseudorand)(unsigned char *buf, int num);
71 } RAND_METHOD; 73 } RAND_METHOD;
72 74
73void RAND_set_rand_method(RAND_METHOD *meth); 75void RAND_set_rand_method(RAND_METHOD *meth);
74RAND_METHOD *RAND_get_rand_method(void ); 76RAND_METHOD *RAND_get_rand_method(void );
75RAND_METHOD *RAND_SSLeay(void); 77RAND_METHOD *RAND_SSLeay(void);
76void RAND_cleanup(void ); 78void RAND_cleanup(void );
77void RAND_bytes(unsigned char *buf,int num); 79int RAND_bytes(unsigned char *buf,int num);
80int RAND_pseudo_bytes(unsigned char *buf,int num);
78void RAND_seed(const void *buf,int num); 81void RAND_seed(const void *buf,int num);
82void RAND_add(const void *buf,int num,double entropy);
79int RAND_load_file(const char *file,long max_bytes); 83int RAND_load_file(const char *file,long max_bytes);
80int RAND_write_file(const char *file); 84int RAND_write_file(const char *file);
81char *RAND_file_name(char *file,int num); 85const char *RAND_file_name(char *file,int num);
86int RAND_status(void);
87int RAND_egd(const char *path);
82#ifdef WINDOWS 88#ifdef WINDOWS
83void RAND_screen(void); 89void RAND_screen(void);
84#endif 90#endif
91void ERR_load_RAND_strings(void);
92
93/* BEGIN ERROR CODES */
94/* The following lines are auto generated by the script mkerr.pl. Any changes
95 * made after this point may be overwritten when the script is next run.
96 */
97
98/* Error codes for the RAND functions. */
99
100/* Function codes. */
101#define RAND_F_SSLEAY_RAND_BYTES 100
102
103/* Reason codes. */
104#define RAND_R_PRNG_NOT_SEEDED 100
105
85#ifdef __cplusplus 106#ifdef __cplusplus
86} 107}
87#endif 108#endif
88
89#endif 109#endif
110
diff --git a/src/lib/libcrypto/rand/rand_egd.c b/src/lib/libcrypto/rand/rand_egd.c
new file mode 100644
index 0000000000..d834408bd4
--- /dev/null
+++ b/src/lib/libcrypto/rand/rand_egd.c
@@ -0,0 +1,110 @@
1/* crypto/rand/rand_egd.c */
2/* Written by Ulf Moeller for the OpenSSL project. */
3/* ====================================================================
4 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * 3. All advertising materials mentioning features or use of this
19 * software must display the following acknowledgment:
20 * "This product includes software developed by the OpenSSL Project
21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22 *
23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
24 * endorse or promote products derived from this software without
25 * prior written permission. For written permission, please contact
26 * openssl-core@openssl.org.
27 *
28 * 5. Products derived from this software may not be called "OpenSSL"
29 * nor may "OpenSSL" appear in their names without prior written
30 * permission of the OpenSSL Project.
31 *
32 * 6. Redistributions of any form whatsoever must retain the following
33 * acknowledgment:
34 * "This product includes software developed by the OpenSSL Project
35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48 * OF THE POSSIBILITY OF SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This product includes cryptographic software written by Eric Young
52 * (eay@cryptsoft.com). This product includes software written by Tim
53 * Hudson (tjh@cryptsoft.com).
54 *
55 */
56
57#include <openssl/rand.h>
58
59/* Query the EGD <URL: http://www.lothar.com/tech/crypto/>.
60 */
61
62#if defined(WIN32) || defined(VMS) || defined(__VMS)
63int RAND_egd(const char *path)
64 {
65 return(-1);
66 }
67#else
68#include <openssl/opensslconf.h>
69#include OPENSSL_UNISTD
70#include <sys/types.h>
71#include <sys/socket.h>
72#include <sys/un.h>
73#include <string.h>
74
75#ifndef offsetof
76# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
77#endif
78
79int RAND_egd(const char *path)
80 {
81 int ret = -1;
82 struct sockaddr_un addr;
83 int len, num;
84 int fd = -1;
85 unsigned char buf[256];
86
87 memset(&addr, 0, sizeof(addr));
88 addr.sun_family = AF_UNIX;
89 if (strlen(path) > sizeof(addr.sun_path))
90 return (-1);
91 strcpy(addr.sun_path,path);
92 len = offsetof(struct sockaddr_un, sun_path) + strlen(path);
93 fd = socket(AF_UNIX, SOCK_STREAM, 0);
94 if (fd == -1) return (-1);
95 if (connect(fd, (struct sockaddr *)&addr, len) == -1) goto err;
96 buf[0] = 1;
97 buf[1] = 255;
98 write(fd, buf, 2);
99 if (read(fd, buf, 1) != 1) goto err;
100 if (buf[0] == 0) goto err;
101 num = read(fd, buf, 255);
102 if (num < 1) goto err;
103 RAND_seed(buf, num);
104 if (RAND_status() == 1)
105 ret = num;
106 err:
107 if (fd != -1) close(fd);
108 return(ret);
109 }
110#endif
diff --git a/src/lib/libcrypto/rand/rand_err.c b/src/lib/libcrypto/rand/rand_err.c
new file mode 100644
index 0000000000..d1263edf80
--- /dev/null
+++ b/src/lib/libcrypto/rand/rand_err.c
@@ -0,0 +1,93 @@
1/* crypto/rand/rand_err.c */
2/* ====================================================================
3 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. All advertising materials mentioning features or use of this
18 * software must display the following acknowledgment:
19 * "This product includes software developed by the OpenSSL Project
20 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21 *
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 * endorse or promote products derived from this software without
24 * prior written permission. For written permission, please contact
25 * openssl-core@OpenSSL.org.
26 *
27 * 5. Products derived from this software may not be called "OpenSSL"
28 * nor may "OpenSSL" appear in their names without prior written
29 * permission of the OpenSSL Project.
30 *
31 * 6. Redistributions of any form whatsoever must retain the following
32 * acknowledgment:
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
49 *
50 * This product includes cryptographic software written by Eric Young
51 * (eay@cryptsoft.com). This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
53 *
54 */
55
56/* NOTE: this file was auto generated by the mkerr.pl script: any changes
57 * made to it will be overwritten when the script next updates this file.
58 */
59
60#include <stdio.h>
61#include <openssl/err.h>
62#include <openssl/rand.h>
63
64/* BEGIN ERROR CODES */
65#ifndef NO_ERR
66static ERR_STRING_DATA RAND_str_functs[]=
67 {
68{ERR_PACK(0,RAND_F_SSLEAY_RAND_BYTES,0), "SSLEAY_RAND_BYTES"},
69{0,NULL}
70 };
71
72static ERR_STRING_DATA RAND_str_reasons[]=
73 {
74{RAND_R_PRNG_NOT_SEEDED ,"prng not seeded"},
75{0,NULL}
76 };
77
78#endif
79
80void ERR_load_RAND_strings(void)
81 {
82 static int init=1;
83
84 if (init)
85 {
86 init=0;
87#ifndef NO_ERR
88 ERR_load_strings(ERR_LIB_RAND,RAND_str_functs);
89 ERR_load_strings(ERR_LIB_RAND,RAND_str_reasons);
90#endif
91
92 }
93 }
diff --git a/src/lib/libcrypto/rand/rand_lib.c b/src/lib/libcrypto/rand/rand_lib.c
index 34c6d5b968..b09a300c46 100644
--- a/src/lib/libcrypto/rand/rand_lib.c
+++ b/src/lib/libcrypto/rand/rand_lib.c
@@ -57,7 +57,6 @@
57 */ 57 */
58 58
59#include <stdio.h> 59#include <stdio.h>
60#include <sys/types.h>
61#include <time.h> 60#include <time.h>
62#include <openssl/rand.h> 61#include <openssl/rand.h>
63 62
@@ -90,9 +89,22 @@ void RAND_seed(const void *buf, int num)
90 rand_meth->seed(buf,num); 89 rand_meth->seed(buf,num);
91 } 90 }
92 91
93void RAND_bytes(unsigned char *buf, int num) 92void RAND_add(const void *buf, int num, double entropy)
94 { 93 {
95 if (rand_meth != NULL) 94 if (rand_meth != NULL)
96 rand_meth->bytes(buf,num); 95 rand_meth->add(buf,num,entropy);
97 } 96 }
98 97
98int RAND_bytes(unsigned char *buf, int num)
99 {
100 if (rand_meth != NULL)
101 return rand_meth->bytes(buf,num);
102 return(-1);
103 }
104
105int RAND_pseudo_bytes(unsigned char *buf, int num)
106 {
107 if (rand_meth != NULL)
108 return rand_meth->pseudorand(buf,num);
109 return(-1);
110 }
diff --git a/src/lib/libcrypto/rand/randfile.c b/src/lib/libcrypto/rand/randfile.c
index 6829d4ec37..658a8d6b65 100644
--- a/src/lib/libcrypto/rand/randfile.c
+++ b/src/lib/libcrypto/rand/randfile.c
@@ -60,22 +60,35 @@
60#include <stdio.h> 60#include <stdio.h>
61#include <stdlib.h> 61#include <stdlib.h>
62#include <string.h> 62#include <string.h>
63#include <sys/types.h>
64#include <sys/stat.h>
65#include <sys/types.h>
66 63
67#include "openssl/e_os.h" 64#include "openssl/e_os.h"
68 65
66#ifdef VMS
67#include <unixio.h>
68#endif
69#ifndef NO_SYS_TYPES_H
70# include <sys/types.h>
71#endif
72#ifdef MAC_OS_pre_X
73# include <stat.h>
74#else
75# include <sys/stat.h>
76#endif
77
78#include <openssl/crypto.h>
69#include <openssl/rand.h> 79#include <openssl/rand.h>
70 80
71#undef BUFSIZE 81#undef BUFSIZE
72#define BUFSIZE 1024 82#define BUFSIZE 1024
73#define RAND_DATA 1024 83#define RAND_DATA 1024
74 84
75/* #define RFILE ".rand" - defined in ../../e_os.h */ 85/* #define RFILE ".rnd" - defined in ../../e_os.h */
76 86
77int RAND_load_file(const char *file, long bytes) 87int RAND_load_file(const char *file, long bytes)
78 { 88 {
89 /* If bytes >= 0, read up to 'bytes' bytes.
90 * if bytes == -1, read complete file. */
91
79 MS_STATIC unsigned char buf[BUFSIZE]; 92 MS_STATIC unsigned char buf[BUFSIZE];
80 struct stat sb; 93 struct stat sb;
81 int i,ret=0,n; 94 int i,ret=0,n;
@@ -85,23 +98,28 @@ int RAND_load_file(const char *file, long bytes)
85 98
86 i=stat(file,&sb); 99 i=stat(file,&sb);
87 /* If the state fails, put some crap in anyway */ 100 /* If the state fails, put some crap in anyway */
88 RAND_seed(&sb,sizeof(sb)); 101 RAND_add(&sb,sizeof(sb),0);
89 ret+=sizeof(sb);
90 if (i < 0) return(0); 102 if (i < 0) return(0);
91 if (bytes <= 0) return(ret); 103 if (bytes == 0) return(ret);
92 104
93 in=fopen(file,"rb"); 105 in=fopen(file,"rb");
94 if (in == NULL) goto err; 106 if (in == NULL) goto err;
95 for (;;) 107 for (;;)
96 { 108 {
97 n=(bytes < BUFSIZE)?(int)bytes:BUFSIZE; 109 if (bytes > 0)
110 n = (bytes < BUFSIZE)?(int)bytes:BUFSIZE;
111 else
112 n = BUFSIZE;
98 i=fread(buf,1,n,in); 113 i=fread(buf,1,n,in);
99 if (i <= 0) break; 114 if (i <= 0) break;
100 /* even if n != i, use the full array */ 115 /* even if n != i, use the full array */
101 RAND_seed(buf,n); 116 RAND_add(buf,n,i);
102 ret+=i; 117 ret+=i;
103 bytes-=n; 118 if (bytes > 0)
104 if (bytes <= 0) break; 119 {
120 bytes-=n;
121 if (bytes == 0) break;
122 }
105 } 123 }
106 fclose(in); 124 fclose(in);
107 memset(buf,0,BUFSIZE); 125 memset(buf,0,BUFSIZE);
@@ -112,29 +130,48 @@ err:
112int RAND_write_file(const char *file) 130int RAND_write_file(const char *file)
113 { 131 {
114 unsigned char buf[BUFSIZE]; 132 unsigned char buf[BUFSIZE];
115 int i,ret=0; 133 int i,ret=0,err=0;
116 FILE *out; 134 FILE *out = NULL;
117 int n; 135 int n;
118 136
119 /* Under VMS, fopen(file, "wb") will craete a new version of the 137#ifdef VMS
138 /* Under VMS, fopen(file, "wb") will create a new version of the
120 same file. This is not good, so let's try updating an existing 139 same file. This is not good, so let's try updating an existing
121 one, and create file only if it doesn't already exist. This 140 one, and create file only if it doesn't already exist. */
122 should be completely harmless on system that have no file 141 /* At the same time, if we just update a file, we also need to
123 versions. -- Richard Levitte */ 142 truncate it, and unfortunately, ftruncate() and truncate() do
143 not exist everywhere. All that remains is to delete old versions
144 of the random data file (done at the end). */
145#if 0
124 out=fopen(file,"rb+"); 146 out=fopen(file,"rb+");
125 if (out == NULL && errno == ENOENT) 147 if (out == NULL && errno != ENOENT)
148 goto err;
149#endif
150#endif
151
152 if (out == NULL)
126 { 153 {
127 errno = 0; 154#if defined O_CREAT && defined O_EXCL
155 /* chmod(..., 0600) is too late to protect the file,
156 * permissions should be restrictive from the start */
157 int fd = open(file, O_CREAT | O_EXCL, 0600);
158 if (fd != -1)
159 out = fdopen(fd, "wb");
160#else
128 out=fopen(file,"wb"); 161 out=fopen(file,"wb");
162#endif
129 } 163 }
130 if (out == NULL) goto err; 164 if (out == NULL) goto err;
165#ifndef NO_CHMOD
131 chmod(file,0600); 166 chmod(file,0600);
167#endif
132 n=RAND_DATA; 168 n=RAND_DATA;
133 for (;;) 169 for (;;)
134 { 170 {
135 i=(n > BUFSIZE)?BUFSIZE:n; 171 i=(n > BUFSIZE)?BUFSIZE:n;
136 n-=BUFSIZE; 172 n-=BUFSIZE;
137 RAND_bytes(buf,i); 173 if (RAND_bytes(buf,i) <= 0)
174 err=1;
138 i=fwrite(buf,1,i,out); 175 i=fwrite(buf,1,i,out);
139 if (i <= 0) 176 if (i <= 0)
140 { 177 {
@@ -144,13 +181,40 @@ int RAND_write_file(const char *file)
144 ret+=i; 181 ret+=i;
145 if (n <= 0) break; 182 if (n <= 0) break;
146 } 183 }
184#ifdef VMS
185 /* We may have updated an existing file using mode "rb+",
186 * now remove any old extra bytes */
187#if 0
188 if (ret > 0)
189 ftruncate(fileno(out), ret);
190#else
191 /* Try to delete older versions of the file, until there aren't
192 any */
193 {
194 char *tmpf;
195
196 tmpf = Malloc(strlen(file) + 4); /* to add ";-1" and a nul */
197 if (tmpf)
198 {
199 strcpy(tmpf, file);
200 strcat(tmpf, ";-1");
201 while(delete(tmpf) == 0)
202 ;
203 rename(file,";1"); /* Make sure it's version 1, or we
204 will reach the limit (32767) at
205 some point... */
206 }
207 }
208#endif
209#endif
210
147 fclose(out); 211 fclose(out);
148 memset(buf,0,BUFSIZE); 212 memset(buf,0,BUFSIZE);
149err: 213err:
150 return(ret); 214 return(err ? -1 : ret);
151 } 215 }
152 216
153char *RAND_file_name(char *buf, int size) 217const char *RAND_file_name(char *buf, int size)
154 { 218 {
155 char *s; 219 char *s;
156 char *ret=NULL; 220 char *ret=NULL;
diff --git a/src/lib/libcrypto/rand/randtest.c b/src/lib/libcrypto/rand/randtest.c
index f0706d779a..da96e3f695 100644
--- a/src/lib/libcrypto/rand/randtest.c
+++ b/src/lib/libcrypto/rand/randtest.c
@@ -73,7 +73,7 @@ int main()
73 /*double d; */ 73 /*double d; */
74 long d; 74 long d;
75 75
76 RAND_bytes(buf,2500); 76 RAND_pseudo_bytes(buf,2500);
77 77
78 n1=0; 78 n1=0;
79 for (i=0; i<16; i++) n2[i]=0; 79 for (i=0; i<16; i++) n2[i]=0;