Annotation of embedaddon/sqlite3/src/random.c, revision 1.1.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>