home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / utilities / cli / pgp2 / src / c / random < prev    next >
Encoding:
Text File  |  1995-06-08  |  19.4 KB  |  640 lines

  1. /*
  2.  * True and cryptographic random number generation.
  3.  *
  4.  * (c) Copyright 1990-1994 by Philip Zimmermann.  All rights reserved.
  5.  * The author assumes no liability for damages resulting from the use
  6.  * of this software, even if the damage results from defects in this
  7.  * software.  No warranty is expressed or implied.
  8.  *
  9.  * Note that while most PGP source modules bear Philip Zimmermann's
  10.  * copyright notice, many of them have been revised or entirely written
  11.  * by contributors who frequently failed to put their names in their
  12.  * code.  Code that has been incorporated into PGP from other authors
  13.  * was either originally published in the public domain or is used with
  14.  * permission from the various authors.
  15.  *
  16.  * PGP is available for free to the public under certain restrictions.
  17.  * See the PGP User's Guide (included in the release package) for
  18.  * important information about licensing, patent restrictions on
  19.  * certain algorithms, trademarks, copyrights, and export controls.
  20.  *
  21.  * Written by Colin Plumb.
  22.  */
  23.  
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <assert.h>
  28. #include <signal.h>    /* For SIGINT */
  29. #include <time.h>
  30.  
  31. #ifdef AMIGA      /* Includes for timer -- RKNOP */
  32. #include <devices/timer.h>
  33. #include <exec/memory.h>
  34. #include <exec/libraries.h>
  35. #include <proto/dos.h>
  36. #include <proto/timer.h>
  37. #include <proto/exec.h>
  38. #endif /* AMIGA */
  39.  
  40. #include "system.h"    /* For ttycbreak, getch, etc. */
  41. #include "idea.h"
  42. #include "md5.h"
  43. #include "noise.h"
  44. #include "language.h"
  45. #include "random.h"
  46. #include "fileio.h"    /* For FOPRBIN */
  47. #include "pgp.h"    /* For globalRandseedName */
  48. #include "randpool.h"
  49.  
  50. /*
  51.  * As of PGP 2.6.2, the randseed.bin file has been expanded.  An explanation
  52.  * of how the whole thing works in in order, as people are always suspiscious
  53.  * of the random number generator.  (After the xorbytes bug in 2.6, perhaps
  54.  * you should be.)  There are two random number generators in PGP.  One
  55.  * is the "cryptRand" family, which is based on X9.17, but uses IDEA instead
  56.  * of 2-key EDE triple-DES.  This is the generator with a lot of peer review.
  57.  * The implementation is in idea.c.
  58.  * The second is the "trueRand" family, which attempt to accurately measure
  59.  * the entropy available from keyboard I/O.  It keeps a lot more state.
  60.  * The implementation of this is in randpool.c.
  61.  * Originally, the trueRand generator was only used for generating primes,
  62.  * and the cryptRand for generating IDEA session keys.  But things have
  63.  * become a bit more complex.  In particular, the X9.17 specification
  64.  * wants a source of high-resolution time-of-day information, as a source
  65.  * of some "true" randomness to throw in.  So we use the trueRand pool
  66.  * for that.
  67.  * The cryptRand functions keep a state file around, usually named
  68.  * randseed.bin, for a seed, as the X9.17 generator requires 24 bytes of
  69.  * known initial information.
  70.  * This data in this file is carefully "washed" before and after use to
  71.  * help ensure that if the file is captured or altered, the keys will
  72.  * not be too vulnerable.  A washing consists of an encryption in PGP's
  73.  * usual CFB mode of the material coming from or being written to the
  74.  * randseed.bin file on disk.  Assuming the cipher is strong, the effects
  75.  * of the wash are as difficult to predict as the key that is used is
  76.  * difficult to guess.
  77.  * Beforehand, we use the MD5 of the file being encrypted as an additional
  78.  * source of randomness (on the theory that an attacker trying to break
  79.  * a session key probably doesn't have the plaintext, or he wouldn't need
  80.  * to bother), and use that as an IDEA key (with a fixed IV of zero)
  81.  * to encrypt the randseed.bin data.
  82.  * After generating an IDEA key and IV, some more random bytes are generated
  83.  * to reinitialize randseed.bin, and these are encrypted in the same manner
  84.  * as the PGP message before being written to disk, on the assumption that
  85.  * if an attacker can decrypt that, they can decrypt the message directly
  86.  * and not bother attacking the randseed.bin file.
  87.  * The previous code only saved the 24 bytes needed by the X9.17 algorithm.
  88.  * But in 2.6.2, we decided to make the randseed.bin file substantially
  89.  * larger to hold more information that a would-be attacker must guess.
  90.  * There are two reasons for this:
  91.  * - Every time you run PGP, especially when responding to one of PGP's
  92.  *   prompts, PGP samples the keystrokes for use as random numbers.
  93.  *   It is a shame to throw this entropy (randomness) away just because
  94.  *   there is no need for it in the current invocation of PGP.
  95.  * - A feature was added to 2.6.2 to generate files full of random bytes
  96.  *   for other programs to use as key material.  In this case, we haven't
  97.  *   got a message we're encrypting to take some entropy from, and we may
  98.  *   be asked to generate more than 24 random bytes, so there should be
  99.  *   more than 24 bytes of seed material to work from.
  100.  * The implementation is added on to the previous one, to offer assurance
  101.  * that it is no weaker.
  102.  * When the cryptRand generator is opened, the file is washed (if possible)
  103.  * and the first 24 bytes are fed to the cryptographic RNG, while the
  104.  * remainder is added to the trueRand random number pool.
  105.  * When saving, the randseed.bin file is refilled with newly generated
  106.  * bytes, again washed if possible.  It turns out (if you study the
  107.  * X9.17 RNG) that each of the 2^64 possible timestamp information
  108.  * values used in generating each 8 bytes of output generates a output
  109.  * value, so the entropy in the trueRand pool is put to good use; this
  110.  * is not just generating more data from 24 bytes of seed.
  111.  * The random pool is opened and saved with a washing key when
  112.  * generating a session key (see make_random_ideakey in crypto.c),
  113.  * but it is also opened (harmless if alreasy open) and saved
  114.  * (harmless if already saved) without a washing key in the exitPGP routine,
  115.  * to mix in any entropy collected in this invocation of PGP even if
  116.  * a session key was not generated.
  117.  */
  118.  
  119. /*
  120.  * The new randseed size, big enough to hold the full context of the cryptRand
  121.  * and trueRand generators.  With the current RANDPOOLBITS of 3072 (384 bytes),
  122.  * that's 408 bytes.  It's useless to make it any larger, although if
  123.  * RANDPOOLBITS is increased, it might be an idea to keep this smaller than
  124.  * one disk block on all systems (512 bytes is a good figure to use)
  125.  * so we don't change the space requirements for randseed.bin.
  126.  */
  127. #define RANDSEED_BYTES    (RANDPOOLBITS/8 + 24)
  128. /* Have we read in the randseed.bin file? */
  129. static boolean randSeedOpen = 0;
  130. static struct IdeaRandContext randContext;
  131.  
  132. /*
  133.  * Load the RNG state from the randseed.bin file on disk.
  134.  * Returns 0 on success, <0 on error.
  135.  *
  136.  * If cfb is non-zero, prewashes the data by encrypting with it.
  137.  */
  138. int
  139. cryptRandOpen(struct IdeaCfbContext *cfb)
  140. {
  141.     byte buf[256];
  142.     int len;
  143.     FILE *f;
  144.  
  145.     if (randSeedOpen)
  146.         return 0;    /* Already open */
  147.  
  148.     f = fopen(globalRandseedName, FOPRBIN);
  149.     if (!f)
  150.         return -1;
  151.  
  152.     /* First get the bare minimum 24 bytes we need for the IDEA RNG */
  153.     len = fread((char *)buf, 1, 24, f);
  154.     if (cfb)
  155.         ideaCfbEncrypt(cfb, buf, buf, 24);
  156.     ideaRandInit(&randContext, buf, buf+16);
  157.     randSeedOpen = TRUE;
  158.     if (len != 24) { /* Error */
  159.         fclose(f);
  160.         return -1;
  161.     }
  162.  
  163.     /* Read any extra into the random pool */
  164.     for (;;) {
  165.         len = fread((char *)buf, 1, sizeof(buf), f);
  166.         if (len <= 0)
  167.             break;
  168.         if (cfb)
  169.             ideaCfbEncrypt(cfb, buf, buf, len);
  170.         randPoolAddBytes(buf, len);
  171.     }
  172.  
  173.     fclose(f);
  174.     burn(buf);
  175.     return 0;
  176. }
  177.  
  178. /* Create a new state from the output of trueRandByte */
  179. void
  180. cryptRandInit(struct IdeaCfbContext *cfb)
  181. {
  182.     byte buf[24];
  183.     int i;
  184.  
  185.     for (i = 0; i < sizeof(buf); i++)
  186.         buf[i] = trueRandByte();
  187.     if (cfb)
  188.         ideaCfbEncrypt(cfb, buf, buf, sizeof(buf));
  189.  
  190.     ideaRandInit(&randContext, buf, buf+16);
  191.     randSeedOpen = TRUE;
  192.     burn(buf);
  193. }
  194.  
  195. byte
  196. cryptRandByte(void)
  197. {
  198.     if (!randSeedOpen)
  199.         cryptRandOpen((struct IdeaCfbContext *)0);
  200.     return ideaRandByte(&randContext);
  201. }
  202.  
  203. /*
  204.  * Write out a file of random bytes.  If cfb is defined, wash it with the
  205.  * cipher.
  206.  */
  207. int
  208. cryptRandWriteFile(char const *name, struct IdeaCfbContext *cfb, unsigned bytes)
  209. {
  210.     byte buf[256];
  211.     FILE *f;
  212.     int i, len;
  213.  
  214.     f = fopen(name, FOPWBIN);
  215.     if (!f)
  216.         return -1;
  217.  
  218.     while (bytes) {
  219.         len = (bytes < sizeof(buf)) ? bytes : sizeof(buf);
  220.         for (i = 0; i < len; i++)
  221.             buf[i] = ideaRandByte(&randContext);
  222.         if (cfb)
  223.             ideaCfbEncrypt(cfb, buf, buf, len);
  224.         i = fwrite(buf, 1, len, f);
  225.         if (i < len)
  226.             break;
  227.         bytes -= len;
  228.     }
  229.  
  230.     return (fclose(f) != 0 || bytes != 0) ? -1 : 0;
  231. }
  232.  
  233. /*
  234.  * Create a new RNG state, encrypt it with the supplied key, and save it
  235.  * out to disk.
  236.  *
  237.  * When we encrypt a file, the saved data is "postwashed" using the
  238.  * same key and initial vector (including the repeated check bytes and
  239.  * everything) that is used to encrypt the user's message.
  240.  * The hope is that this "postwash" renders it is at least as hard to
  241.  * derive old session keys from randseed.bin as it is to crack the the
  242.  * message directly.
  243.  *
  244.  * The purpose of using EXACTLY the same encryption is to make sure that
  245.  * there isn't related, but different data floating around that can be
  246.  * used for cryptanalysis.
  247.  *
  248.  * This function is always called by exitPGP, without a washing encryption,
  249.  * so this function ignores that call if it has previously been called
  250.  * to save washed bytes.
  251.  */
  252. void
  253. cryptRandSave(struct IdeaCfbContext *cfb)
  254. {
  255.     static boolean savedwashed = FALSE;
  256.  
  257.     if (!randSeedOpen)
  258.         return;    /* Do nothing */
  259.  
  260.     if (cfb)
  261.         savedwashed = TRUE;
  262.     else if (savedwashed)
  263.         return;    /* Don't re-save if it's already been saved washed. */
  264.  
  265.     (void)cryptRandWriteFile(globalRandseedName, cfb, RANDSEED_BYTES);
  266. }
  267.  
  268. /*
  269.  * True random bit handling
  270.  */
  271.  
  272. /*
  273.  * Because these truly random bytes are so unwieldy to accumulate,
  274.  * they can be regarded as a precious resource.  Unfortunately,
  275.  * cryptographic key generation algorithms may require a great many
  276.  * random bytes while searching about for large random prime numbers.
  277.  * Fortunately, they need not all be truly random.  We only need as
  278.  * many truly random bits as there are bits in the large prime we
  279.  * are searching for.  These random bytes can be recycled and modified
  280.  * via pseudorandom numbers until the key is generated, without losing
  281.  * any of the integrity of randomness of the final key.
  282.  *
  283.  * The technique used is a pool of random numbers, which bytes are
  284.  * taken from successively and, when the end is reached, the pool
  285.  * is stirred using an irreversible hash function.  Some (64 bytes)
  286.  * of the pool is not returned to ensure the sequence is not predictible
  287.  * from the values retriefed from trueRandByte().  To be precise,
  288.  * MD5Transform is used as a block cipher in CBC mode, and then the
  289.  * "key" (i.e. what is usually the material to be hashed) is overwritten
  290.  * with some of the just-generated random bytes.
  291.  *
  292.  * This is implemented in randpool.c; see that file for details.
  293.  *
  294.  * An estimate of the number of bits of true (Shannon) entropy in the
  295.  * pool is kept in trueRandBits.  This is incremented when timed
  296.  * keystrokes are available, and decremented when bits are explicitly
  297.  * consumed for some purpose (such as prime generation) or another.
  298.  *
  299.  * trueRandFlush is called to obliterate traces of old random bits after
  300.  * prime generation is completed.  (Primes are the most carefully-guarded
  301.  * values in PGP.)
  302.  */
  303.  
  304. static unsigned trueRandBits = 0;    /* Bits of entropy in pool */
  305.  
  306. /* trueRandPending is bits to add to next accumulation request */
  307. static unsigned trueRandPending = 0;
  308.  
  309. /*
  310.  * Destroys already-used random numbers.  Ensures no sensitive data
  311.  * remains in memory that can be recovered later.  This is called
  312.  * after RSA key generation, so speed is not critical, but security is.
  313.  * RSA key generation takes long enough that interrupts and other
  314.  * tasks are likely to have used a measurable and difficult-to-predict
  315.  * amount of real time, so there is some virtue in sampling the clocks
  316.  * with noise().
  317.  */
  318. void
  319. trueRandFlush(void)
  320. {
  321.     noise();
  322.     randPoolStir();    /* Destroy evidence of what primes were generated */
  323.     randPoolStir();
  324.     randPoolStir();
  325.     randPoolStir();    /* Make *really* certain */
  326. }
  327.  
  328. /*
  329.  * "Consumes" count bits worth of entropy from the true random pool for some
  330.  * purpose, such as prime generation.
  331.  *
  332.  * Note that something like prime generation can end up calling trueRandByte
  333.  * more often than is implied by the count passed to trueRandClaim; this
  334.  * may happen if the random bit consumer is not perfectly efficient in its
  335.  * use of random bits.  For example, if a search for a suitable prime fails,
  336.  * the easiest thing to do is to get another load of random bits and try
  337.  * again.  It is perfectly acceptable if these bits are correlated with the
  338.  * bits used in the failed attempt, since they are discarded.
  339.  */
  340. void
  341. trueRandConsume(unsigned count)
  342. {
  343.     assert (trueRandBits >= count);
  344.     trueRandBits -= count;
  345. }
  346.  
  347. /*
  348.  * Returns a truly random byte if any are available.  It degenerates to
  349.  * a pseudorandom value if there are none.  It is not an error to call
  350.  * this if none are available.  For example, it is called when generating
  351.  * session keys to add to other sources of cryptographic random numbers.
  352.  *
  353.  * This forces an accumulation if any extra random bytes are pending.
  354.  */
  355. int
  356. trueRandByte(void)
  357. {
  358.     if (trueRandPending)
  359.         trueRandAccum(0);
  360.  
  361.     return randPoolGetByte();
  362. }
  363.  
  364. /*
  365.  * Given an event (typically a keystroke) coded by "event"
  366.  * at a random time, add all randomness to the random pool,
  367.  * compute a (conservative) estimate of the amount, add it
  368.  * to the pool, and return the amount of randomness.
  369.  * (The return value is just for informational purposes.)
  370.  *
  371.  * Double events are okay, but three in a row is considered
  372.  * suspiscous and the randomness is counted as 0.
  373.  */
  374. unsigned
  375. trueRandEvent(int event)
  376. {
  377.     static int event1 = 0, event2 = 0;
  378.     word32 delta;
  379.     unsigned cbits;
  380.  
  381.     delta = noise();
  382.     randPoolAddBytes((byte *)&event, sizeof(event));
  383.  
  384.     if (event == event1 && event == event2) {
  385.         cbits = 0;
  386.     } else {
  387.         event2 = event1;
  388.         event1 = event;
  389.  
  390.         for (cbits = 0; delta; cbits++)
  391.             delta >>= 1;
  392.  
  393.         /* Excessive paranoia? */
  394.         if (cbits > 8)
  395.             cbits = 8;
  396.     }
  397.  
  398.     trueRandBits += cbits;
  399.     if (trueRandBits > RANDPOOLBITS)
  400.         trueRandBits = RANDPOOLBITS;
  401.  
  402.     return cbits;
  403. }
  404.  
  405.  
  406. /*
  407.  * Since getting random bits from the keyboard requires user attention,
  408.  * we buffer up requests for them until we can do one big request.
  409.  */
  410. void
  411. trueRandAccumLater(unsigned bitcount)
  412. {
  413.     trueRandPending += bitcount;    /* Wow, that was easy! :-) */
  414. }
  415.  
  416. static void flush_input(void);
  417.  
  418. #ifdef AMIGA  /* Globals used for timing here and in noise.c - RKNOP 940613 */
  419. struct Library *TimerBase=NULL;
  420. struct timerequest *TimerIO=NULL;
  421. union { struct timeval t;
  422.         struct EClockVal e;
  423.       } time0,time1;
  424. unsigned short use_eclock=0;
  425. #endif /* AMIGA */
  426.  
  427. /*
  428.  * Performs an accumulation of random bits.  As long as there are fewer bits
  429.  * in the buffer than are needed (the number passed, plus pending bits),
  430.  * prompt for more.
  431.  */
  432. void
  433. trueRandAccum(unsigned count)    /* Get this many random bits ready */
  434. {
  435.     int c;
  436. #if defined(MSDOS) || defined(__MSDOS__)
  437.     time_t timer;
  438. #endif
  439.  
  440.     count += trueRandPending;    /* Do deferred accumulation now */
  441.     trueRandPending = 0;
  442.  
  443.     if (count > RANDPOOLBITS)
  444.         count = RANDPOOLBITS;
  445.  
  446.     if (trueRandBits >= count)
  447.         return;
  448.  
  449.     fprintf(stderr,
  450. LANG("\nWe need to generate %u random bits.  This is done by measuring the\
  451. \ntime intervals between your keystrokes.  Please enter some random text\
  452. \non your keyboard until you hear the beep:\n"), count-trueRandBits);
  453.  
  454.     ttycbreak();
  455.  
  456. #ifdef AMIGA  /* RKNOP 940613 */
  457.         TimerIO=(struct timerequest *)AllocMem(sizeof(struct timerequest),
  458.                                                MEMF_PUBLIC|MEMF_CLEAR);
  459.         if (TimerIO)
  460.         {  if (OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)TimerIO,0))
  461.               TimerBase=NULL;
  462.            else
  463.            {  TimerBase=(struct Library *)TimerIO->tr_node.io_Device;
  464.               if (TimerBase->lib_Version>=36) /* Use E-clock instead */
  465.               {  use_eclock=1;
  466.                  CloseDevice((struct IORequest *)TimerIO);
  467.                  if (!OpenDevice(TIMERNAME,UNIT_ECLOCK,
  468.                                  (struct IORequest *)TimerIO,0))
  469.                     TimerBase=(struct Library *)TimerIO->tr_node.io_Device;
  470.                  else
  471.                     TimerBase=NULL;
  472.               }
  473.               else use_eclock=0;
  474.            }
  475.         }
  476.         else TimerBase=NULL;
  477. #endif /* AMIGA */
  478.  
  479.     do {
  480.         /* display counter to show progress */
  481.         fprintf(stderr,"\r%4d ", count-trueRandBits);
  482.         fflush(stderr);    /* assure screen update */
  483.  
  484.         flush_input();    /* If there's no delay, we can't use it */
  485.         c = getch();    /* always wait for input */
  486. #ifdef MSDOS
  487.         if (c == 3)
  488.             breakHandler(SIGINT);
  489.         if (c == 0)
  490.             c = getch() + 256;
  491. #endif
  492.         /* Print flag indicating acceptance (or not) */
  493. #ifdef AMIGA /* putc a macro, not safe to have function as an arg!! RKNOP */
  494.                 fputc(trueRandEvent(c) ? '.' : '?' , stderr);
  495. #else
  496.         putc(trueRandEvent(c) ? '.' : '?' , stderr);
  497. #endif
  498.     } while (trueRandBits < count);
  499.  
  500.     fputs("\r   0 *", stderr);
  501.     fputs(LANG("\007 -Enough, thank you.\n"), stderr);
  502.  
  503. #if defined(MSDOS) || defined(__MSDOS__)
  504.     /* Wait until one full second has passed without keyboard input */
  505.     do {
  506.         flush_input();
  507.         sleep(1);
  508.     } while (kbhit());
  509. #else
  510. #ifdef AMIGA       /* Added RKNOP 940608 */
  511.         Delay(50*1);    /* dos.library function, wait 1 second */
  512.         if (TimerBase) CloseDevice((struct IORequest *)TimerIO);
  513.         TimerBase=NULL;
  514.         if (TimerIO) FreeMem(TimerIO,sizeof(struct timerequest));
  515.         TimerIO=NULL;
  516. #else
  517.     sleep(1);
  518.     flush_input();
  519. #endif
  520. #endif
  521.  
  522.     ttynorm();
  523. }
  524.  
  525. #define BS 8
  526. #define LF 10
  527. #define CR 13
  528. #define DEL 127
  529.  
  530. #ifdef VMS
  531. int putch(int);
  532. #else
  533. #ifdef RISC_OS    /* GJM */
  534. void putch(int);
  535. #else
  536. #define putch(c) putc(c, stderr)
  537. #endif
  538. #endif
  539.  
  540. int
  541. getstring(char *strbuf, unsigned maxlen, int echo)
  542. /* Gets string from user, with no control characters allowed.
  543.  * Also accumulates random numbers.
  544.  * maxlen is max length allowed for string.
  545.  * echo is TRUE iff we should echo keyboard to screen.
  546.  * Returns null-terminated string in strbuf.
  547.  */
  548. {
  549.     unsigned i;
  550.     char c;
  551.  
  552.     ttycbreak();
  553.  
  554. #ifdef AMIGA     /* In case of -f (use stdio for plaintext input),
  555.                     use ReqTools for input from the user */
  556.         if (!IsInteractive(Input()))
  557.            return AmigaRequestString(strbuf,maxlen,echo);
  558. #endif
  559.  
  560.     fflush(stdout);
  561.     i=0;
  562.     for (;;) {
  563. #ifndef VMS
  564.         fflush(stderr);
  565. #endif /* VMS */
  566.         c = getch();
  567.         trueRandEvent(c);
  568. #ifdef VMS
  569.         if (c == 25) {  /*  Control-Y detected */
  570.             ttynorm();
  571.             breakHandler(SIGINT);
  572.         }
  573. #endif /* VMS */
  574. #if defined(MSDOS) || defined (__MSDOS__)
  575.         if (c == 3)
  576.             breakHandler(SIGINT);
  577. #endif
  578.         if (c==BS || c==DEL) {
  579.             if (i) {
  580.                 if (echo) {
  581.                     putch(BS);
  582.                     putch(' ');
  583.                     putch(BS);
  584.                 }
  585.                 i--;
  586.             } else {
  587.                 putch('\007');
  588.             }
  589.             continue;
  590.         }
  591.         if (c < ' ' && c != LF && c != CR) {
  592.             putch('\007');
  593. #if defined(MSDOS) || defined (__MSDOS__)
  594.             if (c == 3)
  595.                 breakHandler(SIGINT);
  596.             if (c == 0)
  597.                 getch(); /* Skip extended key codes */
  598. #endif
  599.             continue;
  600.         }
  601.         if (echo)
  602.             putch(c);
  603.         if (c==CR) {
  604.             if (echo)
  605.                 putch(LF);
  606.             break;
  607.         }
  608.         if (c==LF)
  609.             break;
  610.         if (c=='\n')
  611.             break;
  612.         strbuf[i++] = c;
  613.         if (i >= maxlen) {
  614.             fputs("\007*\n", stderr);    /* -Enough! */
  615. #if 0
  616.             while (kbhit())
  617.                 getch();    /* clean up any typeahead */
  618. #endif
  619.             break;
  620.         }
  621.     }
  622.     strbuf[i] = '\0';    /* null termination of string */
  623.  
  624.     ttynorm();
  625.  
  626.     return(i);        /* returns string length */
  627. } /* getstring */
  628.  
  629.  
  630. static void
  631. flush_input(void)
  632. {    /* on unix ttycbreak() will flush the input queue */
  633. #if defined(MSDOS) || defined (__MSDOS__)
  634.     while (kbhit())    /* flush typahead buffer */
  635.         getch();
  636. #elif defined(RISC_OS)
  637.     ro_flush_input();    /* GJM */
  638. #endif
  639. }
  640.