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