xref: /illumos-gate/usr/src/lib/libsqlite/src/random.c (revision 1da57d55)
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 ** $Id: random.c,v 1.11 2004/02/11 09:46:33 drh Exp $
19 */
20 #include "sqliteInt.h"
21 #include "os.h"
22 
23 
24 /*
25 ** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
26 ** must be held while executing this routine.
27 **
28 ** Why not just use a library random generator like lrand48() for this?
29 ** Because the OP_NewRecno opcode in the VDBE depends on having a very
30 ** good source of random numbers.  The lrand48() library function may
31 ** well be good enough.  But maybe not.  Or maybe lrand48() has some
32 ** subtle problems on some systems that could cause problems.  It is hard
33 ** to know.  To minimize the risk of problems due to bad lrand48()
34 ** implementations, SQLite uses this random number generator based
35 ** on RC4, which we know works very well.
36 */
randomByte()37 static int randomByte(){
38   unsigned char t;
39 
40   /* All threads share a single random number generator.
41   ** This structure is the current state of the generator.
42   */
43   static struct {
44     unsigned char isInit;          /* True if initialized */
45     unsigned char i, j;            /* State variables */
46     unsigned char s[256];          /* State variables */
47   } prng;
48 
49   /* Initialize the state of the random number generator once,
50   ** the first time this routine is called.  The seed value does
51   ** not need to contain a lot of randomness since we are not
52   ** trying to do secure encryption or anything like that...
53   **
54   ** Nothing in this file or anywhere else in SQLite does any kind of
55   ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
56   ** number generator) not as an encryption device.
57   */
58   if( !prng.isInit ){
59     int i;
60     char k[256];
61     prng.j = 0;
62     prng.i = 0;
63     sqliteOsRandomSeed(k);
64     for(i=0; i<256; i++){
65       prng.s[i] = i;
66     }
67     for(i=0; i<256; i++){
68       prng.j += prng.s[i] + k[i];
69       t = prng.s[prng.j];
70       prng.s[prng.j] = prng.s[i];
71       prng.s[i] = t;
72     }
73     prng.isInit = 1;
74   }
75 
76   /* Generate and return single random byte
77   */
78   prng.i++;
79   t = prng.s[prng.i];
80   prng.j += t;
81   prng.s[prng.i] = prng.s[prng.j];
82   prng.s[prng.j] = t;
83   t += prng.s[prng.i];
84   return prng.s[t];
85 }
86 
87 /*
88 ** Return N random bytes.
89 */
sqliteRandomness(int N,void * pBuf)90 void sqliteRandomness(int N, void *pBuf){
91   unsigned char *zBuf = pBuf;
92   sqliteOsEnterMutex();
93   while( N-- ){
94     *(zBuf++) = randomByte();
95   }
96   sqliteOsLeaveMutex();
97 }
98