Annotation of pgp/src/randpool.c, revision 1.1.1.3

1.1.1.2   root        1: /*
                      2:  * True random number computation and storage
                      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: #include <stdlib.h>
                     24: #include <string.h>
                     25: 
                     26: #include "randpool.h"
                     27: #include "usuals.h"
                     28: #include "md5.h"
                     29: 
                     30: /* The pool must be a multiple of the 16-byte (128-bit) MD5 block size */
                     31: #define RANDPOOLWORDS ((RANDPOOLBITS+127 & ~127) >> 5)
                     32: #if RANDPOOLWORDS <= 16
1.1.1.3 ! root       33: /* #error is not portable, this has the same effect */
        !            34: #include "Random pool too small - please increase RANDPOOLBITS in randpool.h"
1.1.1.2   root       35: #endif
                     36: 
                     37: /* Must be word-aligned, so make it words.  Cast to bytes as needed. */
                     38: static word32 randPool[RANDPOOLWORDS]; /* Random pool */
                     39: static unsigned randPoolGetPos = sizeof(randPool); /* Position to get from */
                     40: static unsigned randPoolAddPos = 0;    /* Position to add to */
                     41: 
                     42: static void
                     43: xorbytes(byte *dest, byte const *src, unsigned len)
                     44: {
                     45:        while (len--)
1.1.1.3 ! root       46:                *dest++ ^= *src++;
1.1.1.2   root       47: }
                     48: 
                     49: /*
                     50:  * Destroys already-used random numbers.  Ensures no sensitive data
                     51:  * remains in memory that can be recovered later.  This is also
                     52:  * called to "stir in" newly acquired environmental noise bits before
                     53:  * removing any random bytes.
                     54:  *
                     55:  * The transformation is carried out by "encrypting" the data in CFB
                     56:  * mode with MD5 as the block cipher.  Then, to make certain the stirring
                     57:  * operation is strictly one-way, we destroy the key, getting 64 bytes
                     58:  * from the beginning of the pool and using them to reinitialize the
                     59:  * key.  These bytes are not returned by randPoolGetBytes().
                     60:  *
                     61:  * The stirring operation is done twice, to ensure that each bit in the
                     62:  * pool depends on each bit of entropy XORed in after each call to
                     63:  * randPoolStir().
                     64:  *
                     65:  * To make this useful for pseudo-random (that is, repeatable) operations,
                     66:  * the MD5 transformation is always done with a consistent byte order.
                     67:  * MD5Transform itself works with 32-bit words, not bytes, so the pool,
                     68:  * usually an array of bytes, is transformed into an array of 32-bit words,
                     69:  * taking each group of 4 bytes in big-endian order.  At the end of the
                     70:  * stirring, the transformation is reversed.
                     71:  */
                     72: void
                     73: randPoolStir(void)
                     74: {
                     75:        int i;
                     76:        byte *p;
                     77:        word32 t;
                     78:        word32 iv[4];
                     79:        static word32 randPoolKey[16] = {0};
                     80: 
                     81:        /* Convert to word32s for stirring operation */
                     82:        p = (byte *)randPool;
                     83:        for (i = 0; i < RANDPOOLWORDS; i++) {
                     84:                t = (word32)((unsigned)p[3]<<8 | p[2]) << 16 |
                     85:                             (unsigned)p[1]<<8 | p[0];
                     86:                randPool[i] = t;
                     87:                p += 4;
                     88:        }
                     89: 
                     90:        /* Start IV from last block of randPool */
                     91:        memcpy(iv, randPool+RANDPOOLWORDS-4, sizeof(iv));
                     92: 
                     93:        /* First CFB pass */
                     94:        for (i = 0; i < RANDPOOLWORDS; i += 4) {
                     95:                MD5Transform(iv, randPoolKey);
                     96:                iv[0] = randPool[i  ] ^= iv[0];
                     97:                iv[1] = randPool[i+1] ^= iv[1];
                     98:                iv[2] = randPool[i+2] ^= iv[2];
                     99:                iv[3] = randPool[i+3] ^= iv[3];
                    100:        }
                    101: 
                    102:        /* Get new key */
                    103:        memcpy(randPoolKey, randPool, sizeof(randPoolKey));
                    104: 
                    105:        /* Second CFB pass */
                    106:        for (i = 0; i < RANDPOOLWORDS; i += 4) {
                    107:                MD5Transform(iv, randPoolKey);
                    108:                iv[0] = randPool[i  ] ^= iv[0];
                    109:                iv[1] = randPool[i+1] ^= iv[1];
                    110:                iv[2] = randPool[i+2] ^= iv[2];
                    111:                iv[3] = randPool[i+3] ^= iv[3];
                    112:        }
                    113: 
                    114:        /* Get new key */
                    115:        memcpy(randPoolKey, randPool, sizeof(randPoolKey));
                    116: 
                    117:        /* Wipe iv from memory */
                    118:        memset(iv, 0, sizeof(iv));
                    119: 
                    120:        /* Convert randPool back to bytes for further use */
                    121:        p = (byte *)randPool;
                    122:        for (i = 0; i < RANDPOOLWORDS; i++) {
                    123:                t = randPool[i];
                    124:                p[0] = t>>24;
                    125:                p[1] = t>>16;
                    126:                p[2] = t>>8;
                    127:                p[3] = t;
                    128:                p += 4;
                    129:        }
                    130: 
                    131:        /* Set up pointers for future addition or removal of random bytes */
                    132:        randPoolAddPos = 0;
                    133:        randPoolGetPos = sizeof(randPoolKey);
                    134: }
                    135: 
                    136: /*
                    137:  * Make a deposit of information (entropy) into the pool.  The bits
                    138:  * deposited need not have any particular distribution; the stirring
                    139:  * operation transformes them to uniformly-distributed bits.
                    140:  */
                    141: void
                    142: randPoolAddBytes(byte const *buf, unsigned len)
                    143: {
                    144:        unsigned t;
                    145: 
                    146:        while (len > (t = sizeof(randPool) - randPoolAddPos)) {
                    147:                xorbytes((byte *)randPool+randPoolAddPos, buf, t);
                    148:                buf += t;
                    149:                len -= t;
                    150:                randPoolStir();
                    151:        }
                    152: 
                    153:        if (len) {
                    154:                xorbytes((byte *)randPool+randPoolAddPos, buf, len);
                    155:                randPoolAddPos += len;
                    156:                randPoolGetPos = sizeof(randPool); /* Force stir on get */
                    157:        }
                    158: }
                    159: 
                    160: /*
                    161:  * Withdraw some bits from the pool.  Regardless of the distribution of the
                    162:  * input bits, the bits returned are uniformly distributed, although they
                    163:  * cannot, of course, contain more Shannon entropy than the input bits.
                    164:  */
                    165: void
                    166: randPoolGetBytes(byte *buf, unsigned len)
                    167: {
                    168:        unsigned t;
                    169: 
                    170:        while (len > (t = sizeof(randPool) - randPoolGetPos)) {
                    171:                memcpy(buf, (byte *)randPool+randPoolGetPos, t);
                    172:                buf += t;
                    173:                len -= t;
                    174:                randPoolStir();
                    175:        }
                    176: 
                    177:        if (len) {
                    178:                memcpy(buf, (byte *)randPool+randPoolGetPos, len);
                    179:                randPoolGetPos += len;
                    180:        }
                    181: }
                    182: 
                    183: byte
                    184: randPoolGetByte(void)
                    185: {
                    186:        if (randPoolGetPos == sizeof(randPool))
                    187:                randPoolStir();
                    188: 
                    189:        return (((byte *)randPool)[randPoolGetPos++]);
                    190: }

unix.superglobalmegacorp.com

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