#include "feeRandom.h"
#include "giantIntegers.h"
#include "elliptic.h"
#include "falloc.h"
#include "feeDebug.h"
#include "byteRep.h"
#include <stdlib.h>
#include "platform.h"
#define EXTRA_NEXT_NUM 0
#define RANDBITS 128
#define RAND_GIANT_DIGITS (RANDBITS/GIANT_BITS_PER_DIGIT)
typedef struct {
giant A;
giant C;
giant SEED;
giant x;
} randInst;
#if GIANTS_VIA_STACK
static int giantsInitd = 0;
static void feeRandInitGiants()
{
if(giantsInitd) {
return;
}
curveParamsInitGiants();
giantsInitd = 1;
}
#endif
static void pmod(giant x, int bits) {
int j;
int digits = bits / GIANT_BITS_PER_DIGIT;
for(j = (digits-1); j >= 0; j--) {
if(x->n[j] != 0) break;
}
x->sign = j+1;
}
feeRand feeRandAllocWithSeed(unsigned seed)
{
randInst *rinst = (randInst *) fmalloc(sizeof(randInst));
int digits = RAND_GIANT_DIGITS * 4;
unsigned j;
#if GIANTS_VIA_STACK
feeRandInitGiants();
#endif
rinst->SEED = newGiant(digits);
rinst->C = newGiant(digits);
rinst->A = newGiant(digits);
rinst->x = newGiant(digits);
rinst->C->sign = rinst->A->sign = rinst->SEED->sign = RAND_GIANT_DIGITS;
for(j=0; j<RAND_GIANT_DIGITS; j++) {
rinst->C->n[j] = (giantDigit)(seed + 0xdddddddd - j);
rinst->A->n[j] = (giantDigit)(seed + 0xfff12223 + j);
rinst->SEED->n[j] = (giantDigit)(seed + j);
}
#if EXTRA_NEXT_NUM
feeRandNextNum(rinst);
#endif return rinst;
}
feeRand feeRandAlloc(void)
{
return feeRandAllocWithSeed(createRandomSeed());
}
void feeRandFree(feeRand frand)
{
randInst *rinst = (randInst *) frand;
clearGiant(rinst->A);
freeGiant(rinst->A);
clearGiant(rinst->C);
freeGiant(rinst->C);
clearGiant(rinst->SEED);
freeGiant(rinst->SEED);
clearGiant(rinst->x);
freeGiant(rinst->x);
ffree(rinst);
}
unsigned feeRandNextNum(feeRand frand)
{
randInst *rinst = (randInst *) frand;
unsigned rtn;
mulg(rinst->A, rinst->SEED);
addg(rinst->C, rinst->SEED);
pmod(rinst->SEED, RANDBITS);
gtog(rinst->SEED, rinst->x);
rtn = byteRepToInt((unsigned char *)&rinst->x->n);
return rtn;
}
void feeRandBytes(feeRand frand,
unsigned char *bytes,
unsigned numBytes)
{
randInst *rinst = (randInst *) frand;
int length;
unsigned toCopy;
unsigned char *cp = bytes;
for (length = numBytes; length > 0; length -= RANDBITS/8) {
mulg(rinst->A, rinst->SEED);
addg(rinst->C, rinst->SEED);
pmod(rinst->SEED, RANDBITS);
gtog(rinst->SEED, rinst->x);
toCopy = RANDBITS/8;
if(length < toCopy) {
toCopy = length;
}
bcopy(rinst->x->n, cp, toCopy);
cp += toCopy;
}
}
void feeRandAddEntropy(feeRand frand, unsigned entropy)
{
randInst *rinst = (randInst *) frand;
giant tmp = borrowGiant(RAND_GIANT_DIGITS);
unsigned i;
if(entropy == 0) {
entropy = 0x12345;
}
for(i=0; i<RAND_GIANT_DIGITS; i++) {
tmp->n[i] = (giantDigit)entropy;
}
tmp->sign = RAND_GIANT_DIGITS;
mulg(tmp, rinst->SEED);
addg(rinst->C, rinst->SEED);
pmod(rinst->SEED, RANDBITS);
entropy ^= 0xff0ff0ff;
if(entropy == 0) {
entropy = 0x12345;
}
for(i=0; i<RAND_GIANT_DIGITS; i++) {
tmp->n[i] = (giantDigit)entropy;
}
mulg(tmp, rinst->A);
addg(rinst->C, rinst->A);
pmod(rinst->A, RANDBITS);
returnGiant(tmp);
}