summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/rand/md_rand.c
diff options
context:
space:
mode:
authorbeck <>2000-03-19 11:13:58 +0000
committerbeck <>2000-03-19 11:13:58 +0000
commit796d609550df3a33fc11468741c5d2f6d3df4c11 (patch)
tree6c6d539061caa20372dad0ac4ddb1dfae2fbe7fe /src/lib/libcrypto/rand/md_rand.c
parent5be3114c1fd7e0dfea1e38d3abb4cbba75244419 (diff)
downloadopenbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.gz
openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.bz2
openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.zip
OpenSSL 0.9.5 merge
*warning* this bumps shared lib minors for libssl and libcrypto from 2.1 to 2.2 if you are using the ssl26 packages for ssh and other things to work you will need to get new ones (see ~beck/libsslsnap/<arch>) on cvs or ~beck/src-patent.tar.gz on cvs
Diffstat (limited to 'src/lib/libcrypto/rand/md_rand.c')
-rw-r--r--src/lib/libcrypto/rand/md_rand.c312
1 files changed, 237 insertions, 75 deletions
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 */