blob: 03ed7a424b92cfca84b8906a190b9833898d59f6 [file] [log] [blame]
drhae85dc82001-01-13 14:34:05 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhae85dc82001-01-13 14:34:05 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhae85dc82001-01-13 14:34:05 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** 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.
drhae85dc82001-01-13 14:34:05 +000010**
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**
drhaedd8922007-01-05 14:38:54 +000018** $Id: random.c,v 1.16 2007/01/05 14:38:56 drh Exp $
drhae85dc82001-01-13 14:34:05 +000019*/
20#include "sqliteInt.h"
drh8cfbf082001-09-19 13:22:39 +000021#include "os.h"
drhae85dc82001-01-13 14:34:05 +000022
drhaf9ff332002-01-16 21:00:27 +000023
drhae85dc82001-01-13 14:34:05 +000024/*
drhad75e982001-10-09 04:19:46 +000025** Get a single 8-bit random value from the RC4 PRNG. The Mutex
26** must be held while executing this routine.
drhaf9ff332002-01-16 21:00:27 +000027**
28** Why not just use a library random generator like lrand48() for this?
drhf0863fe2005-06-12 21:35:51 +000029** Because the OP_NewRowid opcode in the VDBE depends on having a very
drhaf9ff332002-01-16 21:00:27 +000030** 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()
drhaaab5722002-02-19 13:39:21 +000034** implementations, SQLite uses this random number generator based
drhaf9ff332002-01-16 21:00:27 +000035** on RC4, which we know works very well.
drhf0863fe2005-06-12 21:35:51 +000036**
37** (Later): Actually, OP_NewRowid does not depend on a good source of
38** randomness any more. But we will leave this code in all the same.
drhae85dc82001-01-13 14:34:05 +000039*/
drhaedd8922007-01-05 14:38:54 +000040static int randomByte(void){
drhbbd82df2004-02-11 09:46:30 +000041 unsigned char t;
drhae85dc82001-01-13 14:34:05 +000042
drhad75e982001-10-09 04:19:46 +000043 /* All threads share a single random number generator.
44 ** This structure is the current state of the generator.
45 */
46 static struct {
drhbbd82df2004-02-11 09:46:30 +000047 unsigned char isInit; /* True if initialized */
48 unsigned char i, j; /* State variables */
49 unsigned char s[256]; /* State variables */
drhad75e982001-10-09 04:19:46 +000050 } prng;
51
drh90bfcda2001-09-23 19:46:51 +000052 /* Initialize the state of the random number generator once,
53 ** the first time this routine is called. The seed value does
54 ** not need to contain a lot of randomness since we are not
55 ** trying to do secure encryption or anything like that...
drhae85dc82001-01-13 14:34:05 +000056 **
57 ** Nothing in this file or anywhere else in SQLite does any kind of
58 ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
59 ** number generator) not as an encryption device.
60 */
drhad75e982001-10-09 04:19:46 +000061 if( !prng.isInit ){
drhae85dc82001-01-13 14:34:05 +000062 int i;
drhae85dc82001-01-13 14:34:05 +000063 char k[256];
drhad75e982001-10-09 04:19:46 +000064 prng.j = 0;
65 prng.i = 0;
drh66560ad2006-01-06 14:32:19 +000066 sqlite3OsRandomSeed(k);
drhae85dc82001-01-13 14:34:05 +000067 for(i=0; i<256; i++){
drhad75e982001-10-09 04:19:46 +000068 prng.s[i] = i;
drhae85dc82001-01-13 14:34:05 +000069 }
70 for(i=0; i<256; i++){
drhbbd82df2004-02-11 09:46:30 +000071 prng.j += prng.s[i] + k[i];
drhad75e982001-10-09 04:19:46 +000072 t = prng.s[prng.j];
73 prng.s[prng.j] = prng.s[i];
74 prng.s[i] = t;
drhae85dc82001-01-13 14:34:05 +000075 }
drhad75e982001-10-09 04:19:46 +000076 prng.isInit = 1;
drhae85dc82001-01-13 14:34:05 +000077 }
78
79 /* Generate and return single random byte
80 */
drhbbd82df2004-02-11 09:46:30 +000081 prng.i++;
drhad75e982001-10-09 04:19:46 +000082 t = prng.s[prng.i];
drhbbd82df2004-02-11 09:46:30 +000083 prng.j += t;
drhad75e982001-10-09 04:19:46 +000084 prng.s[prng.i] = prng.s[prng.j];
85 prng.s[prng.j] = t;
drhbbd82df2004-02-11 09:46:30 +000086 t += prng.s[prng.i];
87 return prng.s[t];
drhad75e982001-10-09 04:19:46 +000088}
89
90/*
drhbbd82df2004-02-11 09:46:30 +000091** Return N random bytes.
drhad75e982001-10-09 04:19:46 +000092*/
danielk19774adee202004-05-08 08:23:19 +000093void sqlite3Randomness(int N, void *pBuf){
drhbbd82df2004-02-11 09:46:30 +000094 unsigned char *zBuf = pBuf;
drh66560ad2006-01-06 14:32:19 +000095 sqlite3OsEnterMutex();
drhbbd82df2004-02-11 09:46:30 +000096 while( N-- ){
97 *(zBuf++) = randomByte();
drhae85dc82001-01-13 14:34:05 +000098 }
drh66560ad2006-01-06 14:32:19 +000099 sqlite3OsLeaveMutex();
drhae85dc82001-01-13 14:34:05 +0000100}