Annotation of embedaddon/sqlite3/src/random.c, revision 1.1
1.1 ! misho 1: /*
! 2: ** 2001 September 15
! 3: **
! 4: ** The author disclaims copyright to this source code. In place of
! 5: ** a legal notice, here is a blessing:
! 6: **
! 7: ** May you do good and not evil.
! 8: ** May you find forgiveness for yourself and forgive others.
! 9: ** May you share freely, never taking more than you give.
! 10: **
! 11: *************************************************************************
! 12: ** This file contains code to implement a pseudo-random number
! 13: ** generator (PRNG) for SQLite.
! 14: **
! 15: ** Random numbers are used by some of the database backends in order
! 16: ** to generate random integer keys for tables or random filenames.
! 17: */
! 18: #include "sqliteInt.h"
! 19:
! 20:
! 21: /* All threads share a single random number generator.
! 22: ** This structure is the current state of the generator.
! 23: */
! 24: static SQLITE_WSD struct sqlite3PrngType {
! 25: unsigned char isInit; /* True if initialized */
! 26: unsigned char i, j; /* State variables */
! 27: unsigned char s[256]; /* State variables */
! 28: } sqlite3Prng;
! 29:
! 30: /*
! 31: ** Get a single 8-bit random value from the RC4 PRNG. The Mutex
! 32: ** must be held while executing this routine.
! 33: **
! 34: ** Why not just use a library random generator like lrand48() for this?
! 35: ** Because the OP_NewRowid opcode in the VDBE depends on having a very
! 36: ** good source of random numbers. The lrand48() library function may
! 37: ** well be good enough. But maybe not. Or maybe lrand48() has some
! 38: ** subtle problems on some systems that could cause problems. It is hard
! 39: ** to know. To minimize the risk of problems due to bad lrand48()
! 40: ** implementations, SQLite uses this random number generator based
! 41: ** on RC4, which we know works very well.
! 42: **
! 43: ** (Later): Actually, OP_NewRowid does not depend on a good source of
! 44: ** randomness any more. But we will leave this code in all the same.
! 45: */
! 46: static u8 randomByte(void){
! 47: unsigned char t;
! 48:
! 49:
! 50: /* The "wsdPrng" macro will resolve to the pseudo-random number generator
! 51: ** state vector. If writable static data is unsupported on the target,
! 52: ** we have to locate the state vector at run-time. In the more common
! 53: ** case where writable static data is supported, wsdPrng can refer directly
! 54: ** to the "sqlite3Prng" state vector declared above.
! 55: */
! 56: #ifdef SQLITE_OMIT_WSD
! 57: struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
! 58: # define wsdPrng p[0]
! 59: #else
! 60: # define wsdPrng sqlite3Prng
! 61: #endif
! 62:
! 63:
! 64: /* Initialize the state of the random number generator once,
! 65: ** the first time this routine is called. The seed value does
! 66: ** not need to contain a lot of randomness since we are not
! 67: ** trying to do secure encryption or anything like that...
! 68: **
! 69: ** Nothing in this file or anywhere else in SQLite does any kind of
! 70: ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
! 71: ** number generator) not as an encryption device.
! 72: */
! 73: if( !wsdPrng.isInit ){
! 74: int i;
! 75: char k[256];
! 76: wsdPrng.j = 0;
! 77: wsdPrng.i = 0;
! 78: sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
! 79: for(i=0; i<256; i++){
! 80: wsdPrng.s[i] = (u8)i;
! 81: }
! 82: for(i=0; i<256; i++){
! 83: wsdPrng.j += wsdPrng.s[i] + k[i];
! 84: t = wsdPrng.s[wsdPrng.j];
! 85: wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
! 86: wsdPrng.s[i] = t;
! 87: }
! 88: wsdPrng.isInit = 1;
! 89: }
! 90:
! 91: /* Generate and return single random byte
! 92: */
! 93: wsdPrng.i++;
! 94: t = wsdPrng.s[wsdPrng.i];
! 95: wsdPrng.j += t;
! 96: wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
! 97: wsdPrng.s[wsdPrng.j] = t;
! 98: t += wsdPrng.s[wsdPrng.i];
! 99: return wsdPrng.s[t];
! 100: }
! 101:
! 102: /*
! 103: ** Return N random bytes.
! 104: */
! 105: void sqlite3_randomness(int N, void *pBuf){
! 106: unsigned char *zBuf = pBuf;
! 107: #if SQLITE_THREADSAFE
! 108: sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
! 109: #endif
! 110: sqlite3_mutex_enter(mutex);
! 111: while( N-- ){
! 112: *(zBuf++) = randomByte();
! 113: }
! 114: sqlite3_mutex_leave(mutex);
! 115: }
! 116:
! 117: #ifndef SQLITE_OMIT_BUILTIN_TEST
! 118: /*
! 119: ** For testing purposes, we sometimes want to preserve the state of
! 120: ** PRNG and restore the PRNG to its saved state at a later time, or
! 121: ** to reset the PRNG to its initial state. These routines accomplish
! 122: ** those tasks.
! 123: **
! 124: ** The sqlite3_test_control() interface calls these routines to
! 125: ** control the PRNG.
! 126: */
! 127: static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
! 128: void sqlite3PrngSaveState(void){
! 129: memcpy(
! 130: &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
! 131: &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
! 132: sizeof(sqlite3Prng)
! 133: );
! 134: }
! 135: void sqlite3PrngRestoreState(void){
! 136: memcpy(
! 137: &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
! 138: &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
! 139: sizeof(sqlite3Prng)
! 140: );
! 141: }
! 142: void sqlite3PrngResetState(void){
! 143: GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
! 144: }
! 145: #endif /* SQLITE_OMIT_BUILTIN_TEST */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>