|
|
1.1.1.3 root 1: /**********************************************************************
2: random.c - C source code for random number generation - 19 Nov 86
3: (c) Copyright 1986 by Philip Zimmermann. All rights reserved.
4:
5: Revised Jul 88 by PRZ and again Dec 88 by Allan Hoeltje
6: to use IBM PC 8253 timer0 for a faster counter.
7: Revised Apr 89 by PRZ to recycle random bytes.
8: Revised 29 Jul 91 by PRZ for use in more limited environments.
9: Later revised by several other folks to run in difficult environments
10: such as Unix, VAX/VMS and others.
11: Revised 2 Sep 92 by Peter Gutmann and PRZ to use MD5 to distill
12: high quality randomness down from low-grade random noise.
1.1.1.4 ! root 13: Revised 25 Feb 93 by Colin Plumb to use MD5 much more for
! 14: more secure random numbers. (randstir hacked)
! 15: Revised 4 Mar 93 by Colin Plumb to remove the CRUDE and non-USE_MD5
! 16: options, as no platform currently uses them, they make the code
! 17: hard to read, and they were suffering bit rot. Also added
! 18: NO_ITIMER for the isc port and randaccum_later.
1.1.1.3 root 19:
20: This code generates truly random numbers derived from a counter that is
21: incremented continuously while the keyboard is scanned for user input.
22: Every time the user touches a key, the least significant bits of the
23: counter are pushed on a stack. Later, this supply of random bytes can
24: be popped off the stack by applications requiring stochastic numbers.
25: Cryptographic applications require this kind of randomness.
26:
27: The only requirement to make this work is that keypress must be called
28: frequently, and/or getkey must be called to read the keyboard.
29:
30: Note that you can only get as many random bytes as the number of
31: bytes accumulated by the user touching the keyboard.
32: **********************************************************************/
33:
1.1.1.4 ! root 34: #ifdef UNIX
! 35: #include <sys/types.h>
! 36: #include <sys/time.h>
! 37:
! 38: #ifdef NO_ITIMER /* Some systems lie about itimer */
! 39: #undef ITIMER_REAL
! 40: #endif
! 41:
! 42: #ifndef ITIMER_REAL
! 43: #include <sys/times.h>
! 44: #endif
! 45: #endif /* UNIX */
! 46:
! 47: #if defined(UNIX) || defined(VMS)
! 48: #include <signal.h>
! 49: #endif
! 50:
! 51: #include <stdio.h> /* for putchar() and printf() */
1.1.1.3 root 52: #include <string.h>
1.1.1.4 ! root 53: #ifndef _BSD
1.1.1.3 root 54: #include <time.h>
1.1.1.4 ! root 55: #endif
! 56: #include "system.h"
1.1.1.3 root 57: #include "random.h"
58: #include "language.h"
1.1.1.4 ! root 59:
! 60: static long pseudorand(void); /* 31-bit LCG pseudorandom generator */
! 61:
1.1.1.3 root 62: #ifdef M_XENIX
63: long time();
64: #endif
65: #ifdef UNIX
66: #define clock Clock
67: #endif
68:
69: /* pseudorand() is used mainly for debugging while porting to a new
70: machine-- it makes reproducible sequences, which makes debugging
71: easier. To use it as the source of random numbers, define
72: PSEUDORANDOM. Warning: Don't do this for actual applications.
73: */
1.1.1.4 ! root 74: /**
! 75: ** Minimal Standard Pseudo-Random Number Generator
! 76: **
! 77: ** Author: Fuat C. Baran, Columbia University, 1988
! 78: **
! 79: ** Based on code in "Random Number Generators: Good Ones are Hard to Find",
! 80: ** by Stephen K. Park and Keith W. Miller in Communications of the ACM,
! 81: ** 31, 10 (Oct. 1988) pp. 1192-1201.
! 82: **
! 83: **/
! 84:
! 85: /* some constants we need */
! 86: #define A 16807L
! 87: #define M 2147483647L /* Mersenne prime 2^31 -1 */
! 88: #define Q 127773L /* M div A (M / A) */
! 89: #define R 2836L /* M mod A (M % A) */
! 90:
! 91: static long pseudorand(void)
! 92: {
! 93: long hi, lo;
! 94: #ifdef DEBUG
! 95: static long seed = 1;
! 96: #else
! 97: static long seed = 0;
! 98: #endif
! 99: if (!seed || seed == M)
! 100: #ifdef UNIX
! 101: seed = ((long) getpid() << 16) ^ time(NULL);
! 102: #else
! 103: seed = ((long) clock() << 16) ^ time(NULL);
! 104: #endif
! 105: hi = seed / Q;
! 106: lo = seed % Q;
! 107: if ((seed = A * lo - R * hi) <= 0)
! 108: seed += M;
! 109: return seed;
! 110: }
1.1.1.3 root 111:
112:
113: #ifndef PSEUDORANDOM /* use truly random numbers */
114:
115: /* #define USEPCTIMER */ /* use fast hardware timer on IBM PC or AT or clone */
116: /* #define DEBUG */
117:
118: /* Prototypes for kbhit() (whether the keyboard has been hit) and getch()
119: (like getchar() but no echo, no buffering). Not available under some
120: implementations */
1.1.1.4 ! root 121: #ifdef MSDOS
! 122: #include <conio.h>
! 123: typedef word16 fastcnt_t;
! 124: #else
! 125: typedef word32 fastcnt_t;
! 126: #ifdef VMS
! 127: int putch(int);
! 128: #else
! 129: #define putch(c) putc(c, stderr)
! 130: #endif
! 131: #endif /* !MSDOS */
1.1.1.3 root 132:
133: #ifdef DEBUG
134: #define DEBUGprintf1(x) fprintf(stderr,x)
135: #define DEBUGprintf2(x,y) fprintf(stderr,x,y)
136: #else
137: #define DEBUGprintf1(x)
138: #define DEBUGprintf2(x,y)
139: #endif
140:
1.1.1.4 ! root 141: #define POOLSIZE 256
! 142: static int randcount = 0; /* # of random bytes accumulated in pool */
! 143: static byte randpool[POOLSIZE] = {0} ; /* pool of truly random bytes */
1.1.1.3 root 144: static int recyclecount = 0 ; /* # of recycled random bytes accumulated */
1.1.1.4 ! root 145: static byte recyclepool[POOLSIZE] = {0} ; /* pool of recycled random bytes */
! 146:
! 147: static int accumpending = 0; /* # of random bits to add to next request */
! 148:
! 149: static void randstir(byte *pool);
1.1.1.3 root 150:
151: /* fastcounter is a free-running counter incremented in main event loop. */
1.1.1.4 ! root 152: static fastcnt_t fastcounter = 0; /* not needed if we can use the PC timer. */
! 153: static fastcnt_t lastcounter = 0;
! 154: static int cbits;
1.1.1.3 root 155: static char toofast = 0;
156: /* toofast indicates keystroke rejected because it was typed too fast */
157:
158: #ifdef AMIGA
159: int aecho;
160: #endif
161:
162: /* Information needed by the MD5 code for distilling large quantities of
163: semi-random information into a small amount of highly-random information.
164: This works as follows:
165:
166: Initially we have no random information. Whenever we add more slightly
167: random data, we put it in the MD5 data field and run MD5 over the
168: random byte pool. This propagates the randomness in the data evenly
169: throughout the pool due to the avalanche effect of the MD5 transformation.
170: The randomness transformation is carried out inside capturecounter() when
171: the data is entered, and is transparent to the operation of the rest of
172: the code.
173: */
174:
1.1.1.4 ! root 175: #include "md5.h"
! 176: static byte seedBuffer[ 64 ]; /* Buffer for MD5 seed value */
! 177: static boolean isInitialised = FALSE; /* Whether buffer has been inited */
! 178: static byte iv[ 16 ]; /* IV for MD5 transformation */
1.1.1.3 root 179:
180: #ifdef USEPCTIMER /* we will use fast hardware timer on IBM PC */
181: /* #include <conio.h> */ /* function definitions for inp() and outp() */
182: /* outp() and inp() works only for Microsoft C for IBM PC or AT */
183: /* timer0 on 8253-5 on IBM PC or AT tics every .84 usec. */
184: #define timer0 0x40 /* 8253 timer 0 port */
185: #define timercntl 0x43 /* 8253 control register */
186: #define timer0rwl 0x00 /* read lo/hi bytes of cntr 2 with latch */
187: #define timer0rnl 0x30 /* read lo/hi bytes of cntr 2 w/o latch */
188:
189: static byte latched_hitimer = 0; /* captured by keyboard ISR */
190: static byte latched_lotimer = 0; /* captured by keyboard ISR */
191: /* when kbisr captures timer, timer_latched is set. */
192: static boolean timer_latched = FALSE;
193:
194: static void kbisr(void) /* Keyboard Interrupt Service Routine (ISR) */
195: /*
196: kbisr should be called on the way into, or on the way out of,
197: or from within the DOS keyboard ISR, as long as it gets called
198: at the time of a keyboard interrupt. Assumes that the real
199: DOS keyboard ISR captures the keystroke in the normal way.
200: Only the hardware timer counter is captured by the kbisr routine,
201: leaving the actual keystroke capture to the normal DOS keyboard ISR.
202: We indicate that a timer capture has taken place by setting
203: timer_latched.
204:
205: NOTE: WE STILL NEED TO FIND A WAY to connect this subroutine with the
206: normal keyboard ISR, so that kbisr gets called when there's a keyboard
207: interrupt.
208: */
209: { outp(timercntl,timer0rwl);
210: latched_lotimer = inp(timer0);
211: latched_hitimer = inp(timer0);
212: timer_latched = TRUE;
213: } /* kbisr */
214:
215: static unsigned short pctimer0(void)
216: {
217: /* Reads and returns the hardware 8253 timer0 on the PC or AT
218: ** or clone, shifted right 1 bit.
219: **
220: ** DO NOT SET THE HARDWARE COUNTER TO ZERO. It is already initialized
221: ** by the system to be used by the clock. It is set up in mode 3
222: ** (square wave rate generator) and counts down by 2 from 0 (0xFFFF+1)
223: ** to produce an 18.2 Hz square wave. We may, however, READ the
224: ** lo and hi bytes without causing any problems. BUT just
225: ** remember that the lo byte will always be even (since it is
226: ** counting by two).
227: **
228: ** Note that we can not use counter 1 since it is tied to the
229: ** dynamic RAM refresh hardware. Counter 2 is tied to the 8255
230: ** PPI chip to do things like sound. Though it would be safe to
231: ** use counter 2 it is not desirable since we would have to turn
232: ** the speaker on in order to make the timer count! Normally one
233: ** sets counter 2 to mode 3 (square wave generator) to sound the
234: ** speaker. You can set mode 2 (pulse generator) and the speaker
235: ** hardly makes any sound at all, a click when you turn it on and
236: ** a click when you turn it off. Counter 0 should be safe if
237: ** we only read the counter bytes.
238: **
239: ** WARNING: To use the hardware timer the way it really should be
240: ** used, we ought to capture it via a keyboard interrupt service
241: ** routine (ISR). Otherwise, we may experience weaknesses in randomness
242: ** due to harmonic relationships between the hardware counter frequency
243: ** and the keyboard software polling frequency. Unfortunately, this
244: ** implementation does not currently use keyboard interrupts to
245: ** capture the counter. This is not a problem if we don't use the
246: ** hardware counter, but instead use the software counter fastcounter.
247: ** Thus, the hardware counter should not be used at all, unless we
248: ** support it with an ISR.
249: */
250: unsigned short t ;
251: /* See if timer has been latched by kbisr(). */
252: if (!timer_latched) /* The timer was not already latched. */
253: kbisr(); /* latch timer */
254: /* return latched timer and clear latch */
255: t = ( (((unsigned short) latched_hitimer) << 8) |
256: ((unsigned short) latched_lotimer)
257: ) >> 1 ;
258: timer_latched = FALSE;
259: return (t) ;
260: } /* pctimer0 */
261:
262: #endif /* ifdef USEPCTIMER */
263:
264:
265: /* keybuf is used only by keypress(), getkey(), and capturecounter(). */
266: static short keybuf = 0;
267:
268:
269: #ifdef VMS
270:
271: extern unsigned long vms_clock_bits[2]; /* VMS Hardware Clock */
272: extern const long vms_ticks_per_update; /* Clock update int. */
273:
274: #endif /* VMS */
275:
1.1.1.4 ! root 276: static void capturecounter(void)
1.1.1.3 root 277: /* Push a fast counter on the random stack. Should be called when
278: ** the user touches a key or clicks the mouse.
279: */
280: {
1.1.1.4 ! root 281: fastcnt_t dt;
! 282: #ifndef MSDOS
! 283: byte *random_xtra; /* extra timer info */
! 284: #endif
1.1.1.3 root 285: static byte abits = 0; /* number of accumulated bits in accum */
286: unsigned int accum1;
287:
288: #define cbitsmask ((1 << cbits)-1)
289:
290: /* fastcounter only contains timing information, in the form of a
291: free-running timer, either hardware or software.
292: accum1 contains stuff from fastcounter and other sources,
293: like the actual key the user hit.
294: */
295:
296: #if defined(USEPCTIMER) /* we will use fast hardware timer on IBM PC */
297: fastcounter = pctimer0(); /* capture hardware timer */
1.1.1.4 ! root 298: #endif /* not USEPCTIMER */
! 299:
1.1.1.3 root 300: #ifdef VMS
1.1.1.4 ! root 301: #define HW_TIMER 1 /* using hardware timer */
1.1.1.3 root 302: /* Capture fast system timer: */
303: SYS$GETTIM(vms_clock_bits);
304: #ifdef TEST_COUNTER
305: fprintf(stderr," time %10ol %10ol\n",vms_clock_bits[0],vms_clock_bits[1]);
306: #endif
307: /* vms_clock_bits[0] and vms_ticks_per_update are 32-bits each. */
308: fastcounter = vms_clock_bits[0] / vms_ticks_per_update;
309: #endif /* VMS */
310:
1.1.1.4 ! root 311: #ifdef UNIX
! 312: #define HW_TIMER 1 /* using hardware timer */
! 313: #ifdef ITIMER_REAL
! 314: { static struct itimerval it;
! 315: getitimer(ITIMER_REAL, &it);
! 316: if (it.it_value.tv_sec == 0 && it.it_value.tv_usec == 0)
! 317: { /* start the timer */
! 318: it.it_value.tv_sec = 100000;
! 319: it.it_value.tv_usec = 0;
! 320: it.it_interval.tv_sec = 100000;
! 321: it.it_interval.tv_usec = 0;
! 322: signal(SIGALRM, SIG_IGN); /* just in case.. */
! 323: setitimer(ITIMER_REAL, &it, NULL);
! 324: return;
! 325: }
! 326: /* divide by 64 (we can at least expect a 60Hz clock) */
! 327: fastcounter = 6400000-(it.it_value.tv_usec / (1000000/64)
! 328: + it.it_value.tv_sec * 64);
! 329: random_xtra = (byte *) &it.it_value;
! 330: #define XTRA_BYTES (sizeof(struct timeval))
! 331: }
! 332: #else /* !ITIMER_REAL */
! 333: { static struct tms tms;
! 334: fastcounter = times(&tms);
! 335: random_xtra = (byte *) &tms;
! 336: #define XTRA_BYTES (sizeof(struct tms))
! 337: }
! 338: #endif /* !ITIMER_REAL */
! 339: #endif /* UNIX */
! 340:
1.1.1.3 root 341: dt = fastcounter - lastcounter;
342: #ifdef TEST_COUNTER
1.1.1.4 ! root 343: fprintf(stderr,"%6lu", dt);
! 344: #endif
! 345: #ifndef NO_CBIT_STRIP
! 346: dt /= 6; /* use 2.5 bits less than the actual count */
! 347: #endif
! 348: for (cbits = 0; dt; ++cbits)
! 349: dt >>= 1;
! 350: #if 0 /* I don't think this is necessary - CP */
! 351: if (cbits > 8)
! 352: cbits = 8;
1.1.1.3 root 353: #endif
1.1.1.4 ! root 354:
! 355: #ifdef TEST_COUNTER
! 356: fprintf(stderr,"%6u\n", cbits);
! 357: #endif
! 358: if (cbits <= 0)
1.1.1.3 root 359: {
360: toofast++; /* indicate a too-fast keystroke */
361: return; /* only captures if enough time has passed */
362: }
363:
364: lastcounter = fastcounter; /* latch timer info */
365:
366: /* Initialise the MD5 info if necessary */
367: if( !isInitialised ) /* we probably shouldn't bother */
368: { memset(seedBuffer, 0, 64);
369: memset(iv, 0, 16);
370: isInitialised = TRUE;
371: }
372:
373: /* Add the slightly-random data to the MD5 input buffer. Currently we
374: just add a few bytes of environmental noise, but we could mix in
1.1.1.4 ! root 375: up to 512 bits worth. This should be extended in a system-specific
! 376: manner.
1.1.1.3 root 377: */
378: seedBuffer[ 0 ] = keybuf; /* actual character user typed */
379: seedBuffer[ 1 ] = lastcounter & 0xFF;
380: seedBuffer[ 2 ] = lastcounter >> 8;
1.1.1.4 ! root 381: #ifdef MSDOS
1.1.1.3 root 382: accum1 = ( int ) clock(); /* clock ticks */
383: seedBuffer[ 3 ] = accum1 & 0xFF;
384: seedBuffer[ 4 ] = accum1 >> 8;
1.1.1.4 ! root 385: #endif
1.1.1.3 root 386: accum1 = ( int ) time(NULL); /* seconds */
387: seedBuffer[ 5 ] = accum1 & 0xFF;
388: seedBuffer[ 6 ] = accum1 >> 8;
1.1.1.4 ! root 389: #ifdef XTRA_BYTES /* add some extra "random" stuff */
! 390: memcpy(seedBuffer+16, random_xtra, XTRA_BYTES);
! 391: #endif
1.1.1.3 root 392: /* The preceding "noise quantum" has only cbits worth of randomness. */
1.1.1.4 ! root 393: /* Spread it uniformly across the entire pool */
1.1.1.3 root 394:
1.1.1.4 ! root 395: randstir(randpool);
1.1.1.3 root 396:
397: /*
398: Now the somewhat dubious bit: In order to make this fit in with
399: the existing code, we use the existing mechanism of keeping track
400: of a high-water mark in the buffer. This is actually reasonably
401: realistic, since it keeps a count of what percentage of the full
402: buffer is random enough-- measuring the "molarity" of solution.
403: */
404:
405: abits += cbits; /* Update count of bits of randomness */
406: while (abits >= 8)
407: { /* We've got another byte's worth, increment the buffer pointer */
408: if (randcount < sizeof(randpool))
409: randcount++; /* not a byte counter-- now a molarity of randomness */
410: abits -= 8;
411: }
412: } /* capturecounter */
413:
414:
415: /* Because these truly random bytes are so unwieldy to accumulate,
416: they can be regarded as a precious resource. Unfortunately,
417: cryptographic key generation algorithms may require a great many
418: random bytes while searching about for large random prime numbers.
419: Fortunately, they need not all be truly random. We only need as
420: many truly random bytes as there are bytes in the large prime we
421: are searching for. These random bytes can be recycled and modified
422: via pseudorandom numbers until the key is generated, without losing
423: any of the integrity of randomness of the final key.
424: */
425:
426:
1.1.1.4 ! root 427: static void randstir(byte *pool)
! 428: /* Stir up the recycled random number bin, via a pseudorandom generator
! 429: Any truly random bytes stored into the seedBuffer are hashed into the
! 430: pool, and then destroyed for security reasons. */
1.1.1.3 root 431: { int i;
1.1.1.4 ! root 432: int j;
! 433: /* Now use MD5 to diffuse the randomness in these bits over the random
! 434: byte pool, raising the salinity of randomness in the pool. The
! 435: transformation is carried out by "encrypting" the data in CFB mode
! 436: with MD5 as the block cipher */
! 437: for(i = 0; i < POOLSIZE; i += 16)
! 438: {
! 439: Transform((unsigned long *) iv, (unsigned long *) seedBuffer);
! 440: for(j = 0; j < 16; j++)
! 441: pool[i+j] ^= iv[j];
! 442: memcpy(iv, pool+i, 16);
! 443: }
! 444: /* CFB encryption is reversible; if we want the stirring operation to
! 445: be strictly one-way, we must destroy the key. The operation
! 446: accomplishes that, and increases the end-to-beginning feedback
! 447: in randstir(), in an attempt to make all bytes depend on all
! 448: other bytes. */
! 449: memcpy(seedBuffer, pool+POOLSIZE-sizeof(seedBuffer),
! 450: sizeof(seedBuffer));
1.1.1.3 root 451: } /* randstir */
452:
453:
454: short randload(short bitcount)
455: /* Flushes stale recycled random bits and copies a fresh supply of raw
456: random bits from randpool to recyclepool. Returns actual number of
457: bits transferred. */
458: { int bytecount;
459: bytecount = (bitcount+7)/8;
460: bytecount = min(bytecount,randcount);
461: randflush(); /* reset recyclecount, discarding recyclepool */
462: while (bytecount--)
463: recyclepool[recyclecount++] = randpool[--randcount];
464: DEBUGprintf2("\nAllocating %d recycleable random bytes. ",recyclecount);
1.1.1.4 ! root 465: randstir(recyclepool);
! 466: recyclecount = sizeof(recyclepool);
1.1.1.3 root 467: return(recyclecount*8);
468: } /* randload */
469:
470:
471: void randflush(void) /* destroys pool of recycled random numbers */
472: /* Ensures no sensitive data remains in memory that can be recovered later. */
1.1.1.4 ! root 473: {
! 474: /* We do not actually destroy the random bytes (which would be somewhat
! 475: wasteful); we just stir them so that they are irretrievable. This
! 476: assumes that MD5 is truly one-way. */
! 477: randstir(recyclepool);
! 478: recyclecount = 0;
1.1.1.3 root 479: } /* randflush */
480:
1.1.1.4 ! root 481: short try_randombyte(void)
! 482: /* Returns a truly random byte if any are available, or -1 if none.
! 483: * it is not an error to call this if none are available. For example,
! 484: * make_random_ideakey calls it to add to its other sources of pseudo-random
! 485: * noise.
! 486: */
! 487: {
1.1.1.3 root 488: /* First try to get a cheap recycled random byte, if there are any. */
489: if (recyclecount) /* nonempty recycled pool */
1.1.1.4 ! root 490: {
! 491: byte b;
! 492: b = recyclepool[--recyclecount];
! 493: if (!recyclecount) /* Used them all up? */
! 494: randstir(recyclepool); /* Refresh recycled pool */
! 495: return b;
1.1.1.3 root 496: }
497:
498: /* Empty recycled pool. Try a more expensive fresh random byte. */
1.1.1.4 ! root 499:
1.1.1.3 root 500: if (randcount) /* nonempty random pool--return a very random number */
501: return (randpool[--randcount]);
502:
1.1.1.4 ! root 503: /* No, all is for naught. Return -1. */
! 504: return -1;
! 505: }
! 506:
! 507: short randombyte(void)
! 508: /* Returns truly random byte from pool, or a pseudorandom value
! 509: ** if pool is empty. It is recommended that the caller check
! 510: ** the value of randcount before calling randombyte.
! 511: */
! 512: {
! 513: short r;
! 514:
! 515: r = try_randombyte();
! 516: if (r >= 0)
! 517: return r;
! 518:
! 519: /* Oops! Random pool empty. Were there some unsatisifed deferred
! 520: accumulation requests? */
! 521: randaccum(0);
! 522: r = try_randombyte();
! 523: if (r >= 0)
! 524: return r;
! 525:
! 526: /* Alas, fresh random pool is truly empty. Complain, and return
! 527: a pseudorandom byte. Pseudorandom numbers are bad for
! 528: cryptographic applications. Although we will return a
! 529: pseudorandom byte in the low order byte, indicate error by
! 530: making the result negative in the high byte.
1.1.1.3 root 531: */
1.1.1.4 ! root 532: fprintf(stderr, " \007WARNING: Random pool empty! ");
1.1.1.3 root 533: return ( (pseudorand() & 0xFF) ^ (-1) );
534: } /* randombyte */
535:
536:
1.1.1.4 ! root 537: static boolean keypress(void) /* TRUE iff keyboard input ready */
1.1.1.3 root 538: { /* Accumulates random numbers by timing user keystrokes. */
539: static short lastkey = 0; /* used to detect autorepeat key sequences */
540: static short next_to_lastkey = 0; /* allows a single repeated key */
541:
1.1.1.4 ! root 542: #ifndef HW_TIMER /* no fast hardware timer available */
1.1.1.3 root 543: fastcounter++; /* used in lieu of fast hardware timer counter */
1.1.1.4 ! root 544: #endif /* ifndef HW_TIMER */
1.1.1.3 root 545:
546: if (keybuf & 0x100) /* bit 8 means keybuf contains valid data */
547: return( TRUE ); /* key was hit the last time thru */
548:
1.1.1.4 ! root 549: /*
! 550: * If HW_TIMER is defined we don't need a busy loop, so keypress
! 551: * waits for a key and will always return TRUE.
! 552: */
! 553: #ifndef HW_TIMER
1.1.1.3 root 554: if (kbhit() == 0) /* keyboard was not hit */
555: return( FALSE );
1.1.1.4 ! root 556: #endif
1.1.1.3 root 557:
558: keybuf = getch() | 0x100; /* set data latch bit */
559:
560: /* Keyboard was hit. Decide whether to call capturecounter... */
561:
562: /* Guard against typahead buffer defeating fastcounter's randomness.
563: ** This could be a problem for multicharacter sequences generated
564: ** by a function key expansion or by the user generating keystrokes
565: ** faster than our event loop can handle them. Only the last
566: ** character of a multicharacter sequence will trigger the counter
567: ** capture. Also, don't let the keyboard's autorepeat feature
568: ** produce nonrandom counter capture. However, we do allow a
569: ** single repeated character to trigger counter capture, because
570: ** many english words have double letter combinations, and it's
571: ** unlikely a typist would exploit the autorepeat feature to
572: ** type a simple double letter sequence.
573: ** We have some separate checks in capturecounter() to guard
574: ** against other reasons for characters coming in too fast.
575: */
576:
1.1.1.4 ! root 577: #ifndef HW_TIMER
1.1.1.3 root 578: if (kbhit() == 0) /* nothing in typahead buffer */
1.1.1.4 ! root 579: #endif
1.1.1.3 root 580: { /* don't capture counter if key repeated */
581: if (keybuf != lastkey)
582: capturecounter(); /* read random noise from environment */
583: else if (keybuf != next_to_lastkey) /* allow single repeat */
584: capturecounter();
585: next_to_lastkey = lastkey;
586: lastkey = keybuf;
587: }
588: return( TRUE );
589: } /* keypress */
590:
591:
1.1.1.4 ! root 592: static short getkey(void) /* Returns data from keyboard (no echo). */
1.1.1.3 root 593: { /* Also accumulates random numbers via keypress(). */
1.1.1.4 ! root 594: while(! keypress() ) /* loop until key is pressed. */
! 595: ;
1.1.1.3 root 596: return( keybuf &= 0xff); /* clear latch bit 8 */
597: } /* getkey */
598:
599:
600: #define BS 8 /* ASCII backspace */
601: #define CR 13 /* ASCII carriage return */
602: #define LF 10 /* ASCII linefeed */
603: #define DEL 0177 /* ASCII delete */
604:
1.1.1.4 ! root 605: /* Since getting random bits from the keyboard requires user attention,
! 606: we buffer up requests for them until we can do one big request. */
! 607:
! 608: void randaccum_later(short bitcount)
! 609: {
! 610: accumpending += bitcount; /* Wow, that was easy! :-) */
! 611: }
! 612:
1.1.1.3 root 613: /* We will need a series of truly random bits for key generation.
614: In most implementations, our random number supply is derived from
615: random keyboard delays rather than a hardware random number
616: chip. So we will have to ensure we have a large enough pool of
617: accumulated random numbers from the keyboard. Later, randombyte
618: will return bytes one at a time from the accumulated pool of
619: random numbers. For ergonomic reasons, we may want to prefill
620: this random pool all at once initially. The randaccum function
621: prefills a pool of random bits.
622: */
623:
624: void randaccum(short bitcount) /* Get this many random bits ready */
625: { short nbytes;
1.1.1.4 ! root 626: #ifndef HW_TIMER
1.1.1.3 root 627: unsigned long timer;
1.1.1.4 ! root 628: #endif
1.1.1.3 root 629: int fasts_rejected = 0; /* number of too-fast keystrokes */
630:
1.1.1.4 ! root 631: bitcount += accumpending; /* Do deferred accumulation now */
! 632: accumpending = 0;
1.1.1.3 root 633: nbytes = min((bitcount+7)/8,sizeof(randpool));
634: fasts_rejected = 0; /* number of too-fast keystrokes */
635: toofast = 0; /* clear too-fast latch */
636:
637: if (randcount < nbytes) /* if we don't have enough already */
638: { fprintf(stderr,
639: PSTR("\nWe need to generate %d random bytes. This is done by measuring the\
1.1.1.4 ! root 640: \ntime intervals between your keystrokes. Please enter some random text\
! 641: \non your keyboard until you hear the beep:\n"), nbytes-randcount);
1.1.1.3 root 642: #ifdef NEEDBREAK
643: ttycbreak();
644: #endif
645: /* display counter to show progress */
646:
647: while (randcount < nbytes)
648: {
1.1.1.4 ! root 649: #ifndef TEST_COUNTER
1.1.1.3 root 650: fprintf(stderr,"\r%3d ",nbytes-randcount);
1.1.1.4 ! root 651: #endif
1.1.1.3 root 652: fflush(stderr);
1.1.1.4 ! root 653: getkey();
1.1.1.3 root 654: if (toofast)
655: { fasts_rejected++; /* keep score */
656: toofast = 0; /* reset latch */
657: putc('?', stderr); /* indicate trouble */
658: }
659: else
660: putc('.', stderr);
661: }
662:
663: fprintf(stderr,PSTR("\007*\n-Enough, thank you.\n"));
664:
665: if (fasts_rejected > 2) /* Did user type too fast? */
666: fprintf(stderr,PSTR("(Ignored %d keystrokes that were typed too fast.)\n"),
667: fasts_rejected);
668:
1.1.1.4 ! root 669: #ifdef HW_TIMER /* keypress() would block if using hardware timer */
! 670: sleep(1);
! 671: #else
1.1.1.3 root 672: /* Clean up typeahead for at least 1 full second... */
673: timer = time(NULL) + 1; /* need at least 1 second of quiet */
674: while ((unsigned long) time(NULL) <= timer)
675: { if (keypress()) /* user touched a key, reset timer */
676: { getkey();
677: timer = time(NULL) + 1;
678: }
679: }
1.1.1.4 ! root 680: #endif
1.1.1.3 root 681:
682: #ifdef NEEDBREAK
683: ttynorm();
684: #endif /* !NEEDBREAK */
685: }
686: } /* randaccum */
687:
688:
689: int getstring(char *strbuf, int maxlen, boolean echo)
690: /* Gets string from user, with no control characters allowed.
691: Also accumulates random numbers by calling getkey().
692: maxlen is max length allowed for string.
693: echo is TRUE iff we should echo keyboard to screen.
694: Returns null-terminated string in strbuf.
695: */
696: { short i;
697: char c;
698: #ifdef NEEDBREAK
699: ttycbreak();
700: #endif
701: #ifdef AMIGA
702: aecho = (int)echo;
703: echo = FALSE; /* echo is done in getch */
704: #endif /* AMIGA */
705: fflush(stdout);
706: i=0;
707: while (TRUE)
1.1.1.4 ! root 708: {
! 709: #ifndef VMS
! 710: fflush(stderr);
! 711: #endif /* VMS */
1.1.1.3 root 712: c = getkey();
1.1.1.4 ! root 713: #ifdef VMS
! 714: if (c == 25) { /* Control-Y detected */
! 715: ttynorm();
! 716: breakHandler(SIGINT);
! 717: }
! 718: #endif /* VMS */
1.1.1.3 root 719: if (c==BS || c==DEL)
720: { if (i)
721: { if (echo)
1.1.1.4 ! root 722: { putch(BS);
! 723: putch(' ');
! 724: putch(BS);
1.1.1.3 root 725: }
726: i--;
727: }
728: continue;
729: }
730: if (c < ' ' && c != LF && c != CR)
1.1.1.4 ! root 731: { putch('\007');
1.1.1.3 root 732: continue;
733: }
1.1.1.4 ! root 734: if (echo) putch(c);
1.1.1.3 root 735: if (c==CR)
1.1.1.4 ! root 736: { if (echo) putch(LF);
1.1.1.3 root 737: break;
738: }
739: if (c==LF)
740: break;
741: if (c=='\n')
742: break;
743: strbuf[i++] = c;
744: if (i>=maxlen)
745: { fprintf(stderr,"\007*\n"); /* -Enough! */
746: while (keypress())
747: getkey(); /* clean up any typeahead */
748: break;
749: }
750: }
751: strbuf[i] = '\0'; /* null termination of string */
752: #ifdef NEEDBREAK
753: ttynorm();
754: #endif
755: return(i); /* returns string length */
756: } /* getstring */
757:
758:
759: #endif /* ifndef PSEUDORANDOM */
760:
1.1.1.4 ! root 761: void flush_input(void)
! 762: { /* on unix ttycbreak() will flush the input queue */
! 763: #ifndef HW_TIMER
1.1.1.3 root 764: while (keypress()) /* flush typahead buffer */
765: getkey();
766: #endif
767: }
768:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.