/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
//
// SecureRandomClass - Generate random values
//
#pragma warning(disable : 4514) // unreferenced inline function removed....
#include "srandom.h"
#include
#include
#ifdef _UNIX
#include "osdep.h"
#else
#include "win.h"
#include
#endif
#include
#include
#include "sha.h"
// Static class variables
unsigned char SecureRandomClass::Seeds[SecureRandomClass::SeedLength];
bool SecureRandomClass::Initialized=false;
unsigned int SecureRandomClass::RandomCache[SecureRandomClass::SHADigestBytes / sizeof(unsigned int)];
int SecureRandomClass::RandomCacheEntries=0;
unsigned int SecureRandomClass::Counter=0;
Random3Class SecureRandomClass::RandomHelper;
SecureRandomClass::SecureRandomClass()
{
if (Initialized == false)
{
Generate_Seed();
Initialized=true;
}
}
SecureRandomClass::~SecureRandomClass()
{
}
//
// Add seed values to our pool of randomness
//
void SecureRandomClass::Add_Seeds(unsigned char *values, int length)
{
for (int i=0; i=1; j--)
Seeds[j]=Seeds[j-1];
Seeds[0]=uctemp;
}
// We have a better seed pool now so trigger new random values
RandomCacheEntries=0;
}
//
// Get a 32bit random value
//
unsigned long SecureRandomClass::Randval(void)
{
if (RandomCacheEntries == 0)
{
SHAEngine sha;
char digest[SHADigestBytes]; // SHA produces a 20 byte hash
sha.Hash(Seeds, SeedLength);
sha.Result(digest);
memcpy(RandomCache, digest, SHADigestBytes);
RandomCacheEntries=(SHADigestBytes / sizeof(unsigned int));
unsigned int *int_seeds=(unsigned int *)Seeds;
int_seeds[0]^=Counter; // remove the last counter (double xor)
int_seeds[0]^=(Counter+1); // put the new counter in place
int_seeds[(SeedLength/sizeof(int))-1]^=Counter; // remove the last counter (double xor)
int_seeds[(SeedLength/sizeof(int))-1]^=(Counter+1); // put the new counter in place
Counter++; // increment counter
}
unsigned long retval=RandomCache[--RandomCacheEntries];
// SHA doesn't have the best distribution properties in the world
// We'll XOR the result with the output of another random number
unsigned long helperval=RandomHelper();
retval^=helperval;
return(retval);
}
/////////////////////////////// Private Methods ///////////////////////////////////////
//
// Seed the random number generator.
// The seed is what makes each run of random numbers unique. If an observer
// can guess your seed they can predict your random numbers.
//
// Note the use of XORs everywhere. The XOR of a good random number and a bad random
// number is still a good random number.
//
// Caution: Under windows this isn't nearly as safe as under UNIX!
//
void SecureRandomClass::Generate_Seed(void)
{
int i;
// Start with some garbage values
memset(Seeds, 0xAA, SeedLength);
unsigned int *int_seeds=(unsigned int *)Seeds;
int int_seed_length=SeedLength/sizeof(unsigned int);
#ifdef _UNIX
//
// On UNIX we've already got a great random number souce.
// This should be used only for a seed since it's slow.
//
FILE *in=fopen("/dev/random","r");
if (in)
{
for (i=0; i