summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/rand/md_rand.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/rand/md_rand.c')
-rw-r--r--src/lib/libcrypto/rand/md_rand.c331
1 files changed, 65 insertions, 266 deletions
diff --git a/src/lib/libcrypto/rand/md_rand.c b/src/lib/libcrypto/rand/md_rand.c
index da4258c479..d167dea77d 100644
--- a/src/lib/libcrypto/rand/md_rand.c
+++ b/src/lib/libcrypto/rand/md_rand.c
@@ -109,9 +109,7 @@
109 * 109 *
110 */ 110 */
111 111
112#define ENTROPY_NEEDED 16 /* require 128 bits = 16 bytes of randomness */ 112#ifdef MD_RAND_DEBUG
113
114#ifndef MD_RAND_DEBUG
115# ifndef NDEBUG 113# ifndef NDEBUG
116# define NDEBUG 114# define NDEBUG
117# endif 115# endif
@@ -119,75 +117,20 @@
119 117
120#include <assert.h> 118#include <assert.h>
121#include <stdio.h> 119#include <stdio.h>
122#include <time.h>
123#include <string.h> 120#include <string.h>
124 121
125#include "openssl/e_os.h" 122#include "openssl/e_os.h"
126 123
124#include <openssl/rand.h>
125#include "rand_lcl.h"
126
127#include <openssl/crypto.h> 127#include <openssl/crypto.h>
128#include <openssl/err.h> 128#include <openssl/err.h>
129 129
130#if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND)
131#if !defined(NO_SHA) && !defined(NO_SHA1)
132#define USE_SHA1_RAND
133#elif !defined(NO_MD5)
134#define USE_MD5_RAND
135#elif !defined(NO_MDC2) && !defined(NO_DES)
136#define USE_MDC2_RAND
137#elif !defined(NO_MD2)
138#define USE_MD2_RAND
139#else
140#error No message digest algorithm available
141#endif
142#endif
143
144/* Changed how the state buffer used. I now attempt to 'wrap' such
145 * that I don't run over the same locations the next time go through
146 * the 1023 bytes - many thanks to
147 * Robert J. LeBlanc <rjl@renaissoft.com> for his comments
148 */
149
150#if defined(USE_MD5_RAND)
151#include <openssl/md5.h>
152#define MD_DIGEST_LENGTH MD5_DIGEST_LENGTH
153#define MD_CTX MD5_CTX
154#define MD_Init(a) MD5_Init(a)
155#define MD_Update(a,b,c) MD5_Update(a,b,c)
156#define MD_Final(a,b) MD5_Final(a,b)
157#define MD(a,b,c) MD5(a,b,c)
158#elif defined(USE_SHA1_RAND)
159#include <openssl/sha.h>
160#define MD_DIGEST_LENGTH SHA_DIGEST_LENGTH
161#define MD_CTX SHA_CTX
162#define MD_Init(a) SHA1_Init(a)
163#define MD_Update(a,b,c) SHA1_Update(a,b,c)
164#define MD_Final(a,b) SHA1_Final(a,b)
165#define MD(a,b,c) SHA1(a,b,c)
166#elif defined(USE_MDC2_RAND)
167#include <openssl/mdc2.h>
168#define MD_DIGEST_LENGTH MDC2_DIGEST_LENGTH
169#define MD_CTX MDC2_CTX
170#define MD_Init(a) MDC2_Init(a)
171#define MD_Update(a,b,c) MDC2_Update(a,b,c)
172#define MD_Final(a,b) MDC2_Final(a,b)
173#define MD(a,b,c) MDC2(a,b,c)
174#elif defined(USE_MD2_RAND)
175#include <openssl/md2.h>
176#define MD_DIGEST_LENGTH MD2_DIGEST_LENGTH
177#define MD_CTX MD2_CTX
178#define MD_Init(a) MD2_Init(a)
179#define MD_Update(a,b,c) MD2_Update(a,b,c)
180#define MD_Final(a,b) MD2_Final(a,b)
181#define MD(a,b,c) MD2(a,b,c)
182#endif
183
184#include <openssl/rand.h>
185
186#ifdef BN_DEBUG 130#ifdef BN_DEBUG
187# define PREDICT 131# define PREDICT
188#endif 132#endif
189 133
190/* #define NORAND 1 */
191/* #define PREDICT 1 */ 134/* #define PREDICT 1 */
192 135
193#define STATE_SIZE 1023 136#define STATE_SIZE 1023
@@ -198,6 +141,11 @@ static long md_count[2]={0,0};
198static double entropy=0; 141static double entropy=0;
199static int initialized=0; 142static int initialized=0;
200 143
144/* This should be set to 1 only when ssleay_rand_add() is called inside
145 an already locked state, so it doesn't try to lock and thereby cause
146 a hang. And it should always be reset back to 0 before unlocking. */
147static int add_do_not_lock=0;
148
201#ifdef PREDICT 149#ifdef PREDICT
202int rand_predictable=0; 150int rand_predictable=0;
203#endif 151#endif
@@ -234,6 +182,7 @@ static void ssleay_rand_cleanup(void)
234 md_count[0]=0; 182 md_count[0]=0;
235 md_count[1]=0; 183 md_count[1]=0;
236 entropy=0; 184 entropy=0;
185 initialized=0;
237 } 186 }
238 187
239static void ssleay_rand_add(const void *buf, int num, double add) 188static void ssleay_rand_add(const void *buf, int num, double add)
@@ -243,10 +192,6 @@ static void ssleay_rand_add(const void *buf, int num, double add)
243 unsigned char local_md[MD_DIGEST_LENGTH]; 192 unsigned char local_md[MD_DIGEST_LENGTH];
244 MD_CTX m; 193 MD_CTX m;
245 194
246#ifdef NORAND
247 return;
248#endif
249
250 /* 195 /*
251 * (Based on the rand(3) manpage) 196 * (Based on the rand(3) manpage)
252 * 197 *
@@ -262,7 +207,7 @@ static void ssleay_rand_add(const void *buf, int num, double add)
262 * hash function. 207 * hash function.
263 */ 208 */
264 209
265 CRYPTO_w_lock(CRYPTO_LOCK_RAND); 210 if (!add_do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
266 st_idx=state_index; 211 st_idx=state_index;
267 212
268 /* use our own copies of the counters so that even 213 /* use our own copies of the counters so that even
@@ -294,7 +239,7 @@ static void ssleay_rand_add(const void *buf, int num, double add)
294 239
295 md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0); 240 md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
296 241
297 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 242 if (!add_do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
298 243
299 for (i=0; i<num; i+=MD_DIGEST_LENGTH) 244 for (i=0; i<num; i+=MD_DIGEST_LENGTH)
300 { 245 {
@@ -336,7 +281,7 @@ static void ssleay_rand_add(const void *buf, int num, double add)
336 } 281 }
337 memset((char *)&m,0,sizeof(m)); 282 memset((char *)&m,0,sizeof(m));
338 283
339 CRYPTO_w_lock(CRYPTO_LOCK_RAND); 284 if (!add_do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
340 /* Don't just copy back local_md into md -- this could mean that 285 /* Don't just copy back local_md into md -- this could mean that
341 * other thread's seeding remains without effect (except for 286 * other thread's seeding remains without effect (except for
342 * the incremented counter). By XORing it we keep at least as 287 * the incremented counter). By XORing it we keep at least as
@@ -347,9 +292,9 @@ static void ssleay_rand_add(const void *buf, int num, double add)
347 } 292 }
348 if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */ 293 if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
349 entropy += add; 294 entropy += add;
350 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 295 if (!add_do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
351 296
352#ifndef THREADS 297#if !defined(THREADS) && !defined(WIN32)
353 assert(md_c[1] == md_count[1]); 298 assert(md_c[1] == md_count[1]);
354#endif 299#endif
355 } 300 }
@@ -359,58 +304,9 @@ static void ssleay_rand_seed(const void *buf, int num)
359 ssleay_rand_add(buf, num, num); 304 ssleay_rand_add(buf, num, num);
360 } 305 }
361 306
362static void ssleay_rand_initialize(void)
363 {
364 unsigned long l;
365#ifndef GETPID_IS_MEANINGLESS
366 pid_t curr_pid = getpid();
367#endif
368#ifdef DEVRANDOM
369 FILE *fh;
370#endif
371
372#ifdef NORAND
373 return;
374#endif
375
376 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
377 /* put in some default random data, we need more than just this */
378#ifndef GETPID_IS_MEANINGLESS
379 l=curr_pid;
380 RAND_add(&l,sizeof(l),0);
381 l=getuid();
382 RAND_add(&l,sizeof(l),0);
383#endif
384 l=time(NULL);
385 RAND_add(&l,sizeof(l),0);
386
387#ifdef DEVRANDOM
388 /* Use a random entropy pool device. Linux, FreeBSD and OpenBSD
389 * have this. Use /dev/urandom if you can as /dev/random may block
390 * if it runs out of random entries. */
391
392 if ((fh = fopen(DEVRANDOM, "r")) != NULL)
393 {
394 unsigned char tmpbuf[ENTROPY_NEEDED];
395 int n;
396
397 setvbuf(fh, NULL, _IONBF, 0);
398 n=fread((unsigned char *)tmpbuf,1,ENTROPY_NEEDED,fh);
399 fclose(fh);
400 RAND_add(tmpbuf,sizeof tmpbuf,n);
401 memset(tmpbuf,0,n);
402 }
403#endif
404#ifdef PURIFY
405 memset(state,0,STATE_SIZE);
406 memset(md,0,MD_DIGEST_LENGTH);
407#endif
408 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
409 initialized=1;
410 }
411
412static int ssleay_rand_bytes(unsigned char *buf, int num) 307static int ssleay_rand_bytes(unsigned char *buf, int num)
413 { 308 {
309 static volatile int stirred_pool = 0;
414 int i,j,k,st_num,st_idx; 310 int i,j,k,st_num,st_idx;
415 int ok; 311 int ok;
416 long md_c[2]; 312 long md_c[2];
@@ -419,6 +315,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
419#ifndef GETPID_IS_MEANINGLESS 315#ifndef GETPID_IS_MEANINGLESS
420 pid_t curr_pid = getpid(); 316 pid_t curr_pid = getpid();
421#endif 317#endif
318 int do_stir_pool = 0;
422 319
423#ifdef PREDICT 320#ifdef PREDICT
424 if (rand_predictable) 321 if (rand_predictable)
@@ -450,11 +347,17 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
450 * global 'md'. 347 * global 'md'.
451 */ 348 */
452 349
453 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
454
455 if (!initialized) 350 if (!initialized)
456 ssleay_rand_initialize(); 351 RAND_poll();
352
353 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
354 add_do_not_lock = 1; /* Since we call ssleay_rand_add while in
355 this locked state. */
457 356
357 initialized = 1;
358 if (!stirred_pool)
359 do_stir_pool = 1;
360
458 ok = (entropy >= ENTROPY_NEEDED); 361 ok = (entropy >= ENTROPY_NEEDED);
459 if (!ok) 362 if (!ok)
460 { 363 {
@@ -464,12 +367,42 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
464 * Once we've had enough initial seeding we don't bother to 367 * Once we've had enough initial seeding we don't bother to
465 * adjust the entropy count, though, because we're not ambitious 368 * adjust the entropy count, though, because we're not ambitious
466 * to provide *information-theoretic* randomness. 369 * to provide *information-theoretic* randomness.
370 *
371 * NOTE: This approach fails if the program forks before
372 * we have enough entropy. Entropy should be collected
373 * in a separate input pool and be transferred to the
374 * output pool only when the entropy limit has been reached.
467 */ 375 */
468 entropy -= num; 376 entropy -= num;
469 if (entropy < 0) 377 if (entropy < 0)
470 entropy = 0; 378 entropy = 0;
471 } 379 }
472 380
381 if (do_stir_pool)
382 {
383 /* Our output function chains only half of 'md', so we better
384 * make sure that the required entropy gets 'evenly distributed'
385 * through 'state', our randomness pool. The input function
386 * (ssleay_rand_add) chains all of 'md', which makes it more
387 * suitable for this purpose.
388 */
389
390 int n = STATE_SIZE; /* so that the complete pool gets accessed */
391 while (n > 0)
392 {
393#if MD_DIGEST_LENGTH > 20
394# error "Please adjust DUMMY_SEED."
395#endif
396#define DUMMY_SEED "...................." /* at least MD_DIGEST_LENGTH */
397 /* Note that the seed does not matter, it's just that
398 * ssleay_rand_add expects to have something to hash. */
399 ssleay_rand_add(DUMMY_SEED, MD_DIGEST_LENGTH, 0.0);
400 n -= MD_DIGEST_LENGTH;
401 }
402 if (ok)
403 stirred_pool = 1;
404 }
405
473 st_idx=state_index; 406 st_idx=state_index;
474 st_num=state_num; 407 st_num=state_num;
475 md_c[0] = md_count[0]; 408 md_c[0] = md_count[0];
@@ -484,6 +417,9 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
484 * are now ours (but other threads may use them too) */ 417 * are now ours (but other threads may use them too) */
485 418
486 md_count[0] += 1; 419 md_count[0] += 1;
420
421 add_do_not_lock = 0; /* If this would ever be forgotten, we can
422 expect any evil god to eat our souls. */
487 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 423 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
488 424
489 while (num > 0) 425 while (num > 0)
@@ -536,6 +472,8 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
536 else 472 else
537 { 473 {
538 RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED); 474 RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
475 ERR_add_error_data(1, "You need to read the OpenSSL FAQ, "
476 "http://www.openssl.org/support/faq.html");
539 return(0); 477 return(0);
540 } 478 }
541 } 479 }
@@ -561,152 +499,13 @@ static int ssleay_rand_status(void)
561 { 499 {
562 int ret; 500 int ret;
563 501
564 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
565
566 if (!initialized) 502 if (!initialized)
567 ssleay_rand_initialize(); 503 RAND_poll();
568 ret = entropy >= ENTROPY_NEEDED;
569 504
505 CRYPTO_w_lock(CRYPTO_LOCK_RAND);
506 initialized = 1;
507 ret = entropy >= ENTROPY_NEEDED;
570 CRYPTO_w_unlock(CRYPTO_LOCK_RAND); 508 CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
571 509
572 return ret; 510 return ret;
573 } 511 }
574
575#ifdef WINDOWS
576#include <windows.h>
577#include <openssl/rand.h>
578
579int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam)
580 {
581 double add_entropy=0;
582 SYSTEMTIME t;
583
584 switch (iMsg)
585 {
586 case WM_KEYDOWN:
587 {
588 static WPARAM key;
589 if (key != wParam)
590 add_entropy = 0.05;
591 key = wParam;
592 }
593 break;
594 case WM_MOUSEMOVE:
595 {
596 static int lastx,lasty,lastdx,lastdy;
597 int x,y,dx,dy;
598
599 x=LOWORD(lParam);
600 y=HIWORD(lParam);
601 dx=lastx-x;
602 dy=lasty-y;
603 if (dx != 0 && dy != 0 && dx-lastdx != 0 && dy-lastdy != 0)
604 add_entropy=.2;
605 lastx=x, lasty=y;
606 lastdx=dx, lastdy=dy;
607 }
608 break;
609 }
610
611 GetSystemTime(&t);
612 RAND_add(&iMsg, sizeof(iMsg), add_entropy);
613 RAND_add(&wParam, sizeof(wParam), 0);
614 RAND_add(&lParam, sizeof(lParam), 0);
615 RAND_add(&t, sizeof(t), 0);
616
617 return (RAND_status());
618 }
619
620/*****************************************************************************
621 * Initialisation function for the SSL random generator. Takes the contents
622 * of the screen as random seed.
623 *
624 * Created 960901 by Gertjan van Oosten, gertjan@West.NL, West Consulting B.V.
625 *
626 * Code adapted from
627 * <URL:http://www.microsoft.com/kb/developr/win_dk/q97193.htm>;
628 * the original copyright message is:
629 *
630 * (C) Copyright Microsoft Corp. 1993. All rights reserved.
631 *
632 * You have a royalty-free right to use, modify, reproduce and
633 * distribute the Sample Files (and/or any modified version) in
634 * any way you find useful, provided that you agree that
635 * Microsoft has no warranty obligations or liability for any
636 * Sample Application Files which are modified.
637 */
638/*
639 * I have modified the loading of bytes via RAND_seed() mechanism since
640 * the original would have been very very CPU intensive since RAND_seed()
641 * does an MD5 per 16 bytes of input. The cost to digest 16 bytes is the same
642 * as that to digest 56 bytes. So under the old system, a screen of
643 * 1024*768*256 would have been CPU cost of approximately 49,000 56 byte MD5
644 * digests or digesting 2.7 mbytes. What I have put in place would
645 * be 48 16k MD5 digests, or effectively 48*16+48 MD5 bytes or 816 kbytes
646 * or about 3.5 times as much.
647 * - eric
648 */
649void RAND_screen(void)
650{
651 HDC hScrDC; /* screen DC */
652 HDC hMemDC; /* memory DC */
653 HBITMAP hBitmap; /* handle for our bitmap */
654 HBITMAP hOldBitmap; /* handle for previous bitmap */
655 BITMAP bm; /* bitmap properties */
656 unsigned int size; /* size of bitmap */
657 char *bmbits; /* contents of bitmap */
658 int w; /* screen width */
659 int h; /* screen height */
660 int y; /* y-coordinate of screen lines to grab */
661 int n = 16; /* number of screen lines to grab at a time */
662
663 /* Create a screen DC and a memory DC compatible to screen DC */
664 hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
665 hMemDC = CreateCompatibleDC(hScrDC);
666
667 /* Get screen resolution */
668 w = GetDeviceCaps(hScrDC, HORZRES);
669 h = GetDeviceCaps(hScrDC, VERTRES);
670
671 /* Create a bitmap compatible with the screen DC */
672 hBitmap = CreateCompatibleBitmap(hScrDC, w, n);
673
674 /* Select new bitmap into memory DC */
675 hOldBitmap = SelectObject(hMemDC, hBitmap);
676
677 /* Get bitmap properties */
678 GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bm);
679 size = (unsigned int)bm.bmWidthBytes * bm.bmHeight * bm.bmPlanes;
680
681 bmbits = Malloc(size);
682 if (bmbits) {
683 /* Now go through the whole screen, repeatedly grabbing n lines */
684 for (y = 0; y < h-n; y += n)
685 {
686 unsigned char md[MD_DIGEST_LENGTH];
687
688 /* Bitblt screen DC to memory DC */
689 BitBlt(hMemDC, 0, 0, w, n, hScrDC, 0, y, SRCCOPY);
690
691 /* Copy bitmap bits from memory DC to bmbits */
692 GetBitmapBits(hBitmap, size, bmbits);
693
694 /* Get the MD5 of the bitmap */
695 MD(bmbits,size,md);
696
697 /* Seed the random generator with the MD5 digest */
698 RAND_seed(md, MD_DIGEST_LENGTH);
699 }
700
701 Free(bmbits);
702 }
703
704 /* Select old bitmap back into memory DC */
705 hBitmap = SelectObject(hMemDC, hOldBitmap);
706
707 /* Clean up */
708 DeleteObject(hBitmap);
709 DeleteDC(hMemDC);
710 DeleteDC(hScrDC);
711}
712#endif