mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
197
Code/wwlib/srandom.cpp
Normal file
197
Code/wwlib/srandom.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
** 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//
|
||||
// SecureRandomClass - Generate random values
|
||||
//
|
||||
|
||||
#pragma warning(disable : 4514) // unreferenced inline function removed....
|
||||
|
||||
#include "srandom.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _UNIX
|
||||
#include "osdep.h"
|
||||
#else
|
||||
#include "win.h"
|
||||
#include <process.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#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<length; i++)
|
||||
{
|
||||
Seeds[0]^=values[i];
|
||||
|
||||
// Rotate the seeds to the left
|
||||
unsigned char uctemp=Seeds[SeedLength-1];
|
||||
for (int j=SeedLength-1; j>=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<SeedLength; i++)
|
||||
Seeds[i]^=fgetc(in);
|
||||
fclose(in);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
#else
|
||||
|
||||
//
|
||||
// Get free drive space
|
||||
//
|
||||
DWORD spc, bps, nfc, tnc; // various drive attributes (we don't care what they mean)
|
||||
GetDiskFreeSpace(NULL, &spc, &bps, &nfc, &tnc);
|
||||
int_seeds[0]^=spc;
|
||||
int_seeds[1 % int_seed_length]^=bps;
|
||||
int_seeds[2 % int_seed_length]^=nfc;
|
||||
int_seeds[3 % int_seed_length]^=tnc;
|
||||
|
||||
//
|
||||
// Get computer & user name
|
||||
//
|
||||
char comp_name[128];
|
||||
char user_name[128];
|
||||
DWORD comp_len=128;
|
||||
DWORD name_len=128;
|
||||
|
||||
GetComputerName(comp_name, &comp_len);
|
||||
GetUserName(user_name, &name_len);
|
||||
for (i=0; i<128; i++)
|
||||
{
|
||||
// Offset in case user_name == comp_name
|
||||
Seeds[(i+0) % SeedLength]^=comp_name[i];
|
||||
Seeds[(i+2) % SeedLength]^=user_name[i];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for (i=0; i<int_seed_length; i++)
|
||||
{
|
||||
if ((i % 4) == 0)
|
||||
int_seeds[i]^=time(NULL);
|
||||
else if ((i % 4) == 1)
|
||||
int_seeds[i]^=getpid();
|
||||
else if ((i % 4) == 2)
|
||||
int_seeds[i]^=GetTickCount();
|
||||
else if ((i % 4) == 3)
|
||||
int_seeds[i]^=i;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user