/* ** 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