| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 |
- /*
- ** 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;
- }
- }
|