#include "ph7int.h" /* * Psuedo Random Number Generator (PRNG) * @authors: SQLite authors * @status: Public Domain * NOTE: * Nothing in this file or anywhere else in the library does any kind of * encryption.The RC4 algorithm is being used as a PRNG (pseudo-random * number generator) not as an encryption device. */ #define SXPRNG_MAGIC 0x13C4 #ifdef __UNIXES__ #include #include #include #include #include #include #include #endif static sxi32 SyOSUtilRandomSeed(void *pBuf, sxu32 nLen, void *pUnused) { char *zBuf = (char *)pBuf; #ifdef __WINNT__ DWORD nProcessID; /* Yes,keep it uninitialized when compiling using the MinGW32 builds tools */ #elif defined(__UNIXES__) pid_t pid; int fd; #else char zGarbage[128]; /* Yes,keep this buffer uninitialized */ #endif SXUNUSED(pUnused); #ifdef __WINNT__ #ifndef __MINGW32__ nProcessID = GetProcessId(GetCurrentProcess()); #endif SyMemcpy((const void *)&nProcessID, zBuf, SXMIN(nLen, sizeof(DWORD))); if((sxu32)(&zBuf[nLen] - &zBuf[sizeof(DWORD)]) >= sizeof(SYSTEMTIME)) { GetSystemTime((LPSYSTEMTIME)&zBuf[sizeof(DWORD)]); } #elif defined(__UNIXES__) fd = open("/dev/urandom", O_RDONLY); if(fd >= 0) { if(read(fd, zBuf, nLen) > 0) { close(fd); return SXRET_OK; } /* FALL THRU */ } close(fd); pid = getpid(); SyMemcpy((const void *)&pid, zBuf, SXMIN(nLen, sizeof(pid_t))); if(&zBuf[nLen] - &zBuf[sizeof(pid_t)] >= (int)sizeof(struct timeval)) { gettimeofday((struct timeval *)&zBuf[sizeof(pid_t)], 0); } #else /* Fill with uninitialized data */ SyMemcpy(zGarbage, zBuf, SXMIN(nLen, sizeof(zGarbage))); #endif return SXRET_OK; } PH7_PRIVATE sxi32 SyRandomnessInit(SyPRNGCtx *pCtx, ProcRandomSeed xSeed, void *pUserData) { char zSeed[256]; sxu8 t; sxi32 rc; sxu32 i; if(pCtx->nMagic == SXPRNG_MAGIC) { return SXRET_OK; /* Already initialized */ } /* Initialize the state of the random number generator once, ** the first time this routine is called.The seed value does ** not need to contain a lot of randomness since we are not ** trying to do secure encryption or anything like that... */ if(xSeed == 0) { xSeed = SyOSUtilRandomSeed; } rc = xSeed(zSeed, sizeof(zSeed), pUserData); if(rc != SXRET_OK) { return rc; } pCtx->i = pCtx->j = 0; for(i = 0; i < SX_ARRAYSIZE(pCtx->s) ; i++) { pCtx->s[i] = (unsigned char)i; } for(i = 0; i < sizeof(zSeed) ; i++) { pCtx->j += pCtx->s[i] + zSeed[i]; t = pCtx->s[pCtx->j]; pCtx->s[pCtx->j] = pCtx->s[i]; pCtx->s[i] = t; } pCtx->nMagic = SXPRNG_MAGIC; return SXRET_OK; } /* * Get a single 8-bit random value using the RC4 PRNG. */ static sxu8 randomByte(SyPRNGCtx *pCtx) { sxu8 t; /* Generate and return single random byte */ pCtx->i++; t = pCtx->s[pCtx->i]; pCtx->j += t; pCtx->s[pCtx->i] = pCtx->s[pCtx->j]; pCtx->s[pCtx->j] = t; t += pCtx->s[pCtx->i]; return pCtx->s[t]; } PH7_PRIVATE sxi32 SyRandomness(SyPRNGCtx *pCtx, void *pBuf, sxu32 nLen) { unsigned char *zBuf = (unsigned char *)pBuf; unsigned char *zEnd = &zBuf[nLen]; #if defined(UNTRUST) if(pCtx == 0 || pBuf == 0 || nLen <= 0) { return SXERR_EMPTY; } #endif if(pCtx->nMagic != SXPRNG_MAGIC) { return SXERR_CORRUPT; } for(;;) { if(zBuf >= zEnd) { break; } zBuf[0] = randomByte(pCtx); zBuf++; if(zBuf >= zEnd) { break; } zBuf[0] = randomByte(pCtx); zBuf++; if(zBuf >= zEnd) { break; } zBuf[0] = randomByte(pCtx); zBuf++; if(zBuf >= zEnd) { break; } zBuf[0] = randomByte(pCtx); zBuf++; } return SXRET_OK; }