|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.