Annotation of pgp/src/random.c, revision 1.1.1.4

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.