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

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

unix.superglobalmegacorp.com

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