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