blob: 19b284f94f0d3aee19a5bbe32dd073f97bfe0504 [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**
drh51fc3472007-08-21 13:51:23 +000018** $Id: random.c,v 1.20 2007/08/21 13:51:23 drh Exp $
drhae85dc82001-01-13 14:34:05 +000019*/
20#include "sqliteInt.h"
drhae85dc82001-01-13 14:34:05 +000021
drhaf9ff332002-01-16 21:00:27 +000022
drhae85dc82001-01-13 14:34:05 +000023/*
drhad75e982001-10-09 04:19:46 +000024** Get a single 8-bit random value from the RC4 PRNG. The Mutex
25** must be held while executing this routine.
drhaf9ff332002-01-16 21:00:27 +000026**
27** Why not just use a library random generator like lrand48() for this?
drhf0863fe2005-06-12 21:35:51 +000028** Because the OP_NewRowid opcode in the VDBE depends on having a very
drhaf9ff332002-01-16 21:00:27 +000029** good source of random numbers. The lrand48() library function may
30** well be good enough. But maybe not. Or maybe lrand48() has some
31** subtle problems on some systems that could cause problems. It is hard
32** to know. To minimize the risk of problems due to bad lrand48()
drhaaab5722002-02-19 13:39:21 +000033** implementations, SQLite uses this random number generator based
drhaf9ff332002-01-16 21:00:27 +000034** on RC4, which we know works very well.
drhf0863fe2005-06-12 21:35:51 +000035**
36** (Later): Actually, OP_NewRowid does not depend on a good source of
37** randomness any more. But we will leave this code in all the same.
drhae85dc82001-01-13 14:34:05 +000038*/
drhaedd8922007-01-05 14:38:54 +000039static int randomByte(void){
drhbbd82df2004-02-11 09:46:30 +000040 unsigned char t;
drhae85dc82001-01-13 14:34:05 +000041
drhad75e982001-10-09 04:19:46 +000042 /* All threads share a single random number generator.
43 ** This structure is the current state of the generator.
44 */
45 static struct {
drhbbd82df2004-02-11 09:46:30 +000046 unsigned char isInit; /* True if initialized */
47 unsigned char i, j; /* State variables */
48 unsigned char s[256]; /* State variables */
drhad75e982001-10-09 04:19:46 +000049 } prng;
50
drh90bfcda2001-09-23 19:46:51 +000051 /* Initialize the state of the random number generator once,
52 ** the first time this routine is called. The seed value does
53 ** not need to contain a lot of randomness since we are not
54 ** trying to do secure encryption or anything like that...
drhae85dc82001-01-13 14:34:05 +000055 **
56 ** Nothing in this file or anywhere else in SQLite does any kind of
57 ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
58 ** number generator) not as an encryption device.
59 */
drhad75e982001-10-09 04:19:46 +000060 if( !prng.isInit ){
drhae85dc82001-01-13 14:34:05 +000061 int i;
drhae85dc82001-01-13 14:34:05 +000062 char k[256];
drhad75e982001-10-09 04:19:46 +000063 prng.j = 0;
64 prng.i = 0;
drhd677b3d2007-08-20 22:48:41 +000065 sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
drhae85dc82001-01-13 14:34:05 +000066 for(i=0; i<256; i++){
drhad75e982001-10-09 04:19:46 +000067 prng.s[i] = i;
drhae85dc82001-01-13 14:34:05 +000068 }
69 for(i=0; i<256; i++){
drhbbd82df2004-02-11 09:46:30 +000070 prng.j += prng.s[i] + k[i];
drhad75e982001-10-09 04:19:46 +000071 t = prng.s[prng.j];
72 prng.s[prng.j] = prng.s[i];
73 prng.s[i] = t;
drhae85dc82001-01-13 14:34:05 +000074 }
drhad75e982001-10-09 04:19:46 +000075 prng.isInit = 1;
drhae85dc82001-01-13 14:34:05 +000076 }
77
78 /* Generate and return single random byte
79 */
drhbbd82df2004-02-11 09:46:30 +000080 prng.i++;
drhad75e982001-10-09 04:19:46 +000081 t = prng.s[prng.i];
drhbbd82df2004-02-11 09:46:30 +000082 prng.j += t;
drhad75e982001-10-09 04:19:46 +000083 prng.s[prng.i] = prng.s[prng.j];
84 prng.s[prng.j] = t;
drhbbd82df2004-02-11 09:46:30 +000085 t += prng.s[prng.i];
86 return prng.s[t];
drhad75e982001-10-09 04:19:46 +000087}
88
89/*
drhbbd82df2004-02-11 09:46:30 +000090** Return N random bytes.
drhad75e982001-10-09 04:19:46 +000091*/
danielk19774adee202004-05-08 08:23:19 +000092void sqlite3Randomness(int N, void *pBuf){
drhbbd82df2004-02-11 09:46:30 +000093 unsigned char *zBuf = pBuf;
drh51fc3472007-08-21 13:51:23 +000094 static sqlite3_mutex *mutex = 0;
95 if( mutex==0 ){
96 mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG);
97 }
98 sqlite3_mutex_enter(mutex);
drhbbd82df2004-02-11 09:46:30 +000099 while( N-- ){
100 *(zBuf++) = randomByte();
drhae85dc82001-01-13 14:34:05 +0000101 }
drh51fc3472007-08-21 13:51:23 +0000102 sqlite3_mutex_leave(mutex);
drhae85dc82001-01-13 14:34:05 +0000103}