Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
srandom.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19//
20// SecureRandomClass - Generate random values
21//
22
23#pragma warning(disable : 4514) // unreferenced inline function removed....
24
25#include "srandom.h"
26#include <stdlib.h>
27#include <stdio.h>
28#ifdef _UNIX
29#include "osdep.h"
30#include <linux/kernel.h>
31#include <linux/sys.h>
32
33extern "C" {
34 int sysinfo(struct sysinfo *info);
35}
36
37#else
38
39#include "win.h"
40#include <process.h>
41#endif
42#include <time.h>
43#include <assert.h>
44#include "sha.h"
45
46// Static class variables
47unsigned char SecureRandomClass::Seeds[SecureRandomClass::SeedLength];
48bool SecureRandomClass::Initialized=false;
49unsigned int SecureRandomClass::RandomCache[SecureRandomClass::SHADigestBytes / sizeof(unsigned int)];
50int SecureRandomClass::RandomCacheEntries=0;
51unsigned int SecureRandomClass::Counter=0;
52Random3Class SecureRandomClass::RandomHelper;
53
55{
56 if (Initialized == false)
57 {
58 Generate_Seed();
59 Initialized=true;
60 }
61}
62
66
67
68//
69// Add seed values to our pool of randomness
70//
71void SecureRandomClass::Add_Seeds(unsigned char *values, int length)
72{
73 for (int i=0; i<length; i++)
74 {
75 Seeds[0]^=values[i];
76
77 // Rotate the seeds to the left
78 unsigned char uctemp=Seeds[SeedLength-1];
79 for (int j=SeedLength-1; j>=1; j--)
80 Seeds[j]=Seeds[j-1];
81 Seeds[0]=uctemp;
82 }
83
84 // We have a better seed pool now so trigger new random values
85 RandomCacheEntries=0;
86}
87
88//
89// Get a 32bit random value
90//
91unsigned long SecureRandomClass::Randval(void)
92{
93 if (RandomCacheEntries == 0)
94 {
95 SHAEngine sha;
96 char digest[SHADigestBytes]; // SHA produces a 20 byte hash
97
98 sha.Hash(Seeds, SeedLength);
99 sha.Result(digest);
100
101 memcpy(RandomCache, digest, SHADigestBytes);
102 RandomCacheEntries=(SHADigestBytes / sizeof(unsigned int));
103
104 unsigned int *int_seeds=(unsigned int *)Seeds;
105 int_seeds[0]^=Counter; // remove the last counter (double xor)
106 int_seeds[0]^=(Counter+1); // put the new counter in place
107
108 int_seeds[(SeedLength/sizeof(int))-1]^=Counter; // remove the last counter (double xor)
109 int_seeds[(SeedLength/sizeof(int))-1]^=(Counter+1); // put the new counter in place
110
111 Counter++; // increment counter
112 }
113
114 unsigned long retval=RandomCache[--RandomCacheEntries];
115
116 // SHA doesn't have the best distribution properties in the world
117 // We'll XOR the result with the output of another random number
118 unsigned long helperval=RandomHelper();
119 retval^=helperval;
120
121 return(retval);
122}
123
124
125
127
128//
129// Seed the random number generator.
130// The seed is what makes each run of random numbers unique. If an observer
131// can guess your seed they can predict your random numbers.
132//
133// Note the use of XORs everywhere. The XOR of a good random number and a bad random
134// number is still a good random number.
135//
136// Caution: Under windows this isn't nearly as safe as under UNIX!
137//
138void SecureRandomClass::Generate_Seed(void)
139{
140 int i;
141
142 // Start with some garbage values
143 memset(Seeds, 0xAA, SeedLength);
144
145 unsigned int *int_seeds=(unsigned int *)Seeds;
146 int int_seed_length=SeedLength/sizeof(unsigned int);
147
148#ifdef _USE_DEV_RANDOM
149 //
150 // On UNIX we've already got a great random number souce.
151 // This should be used only for a seed since it's slow.
152 //
153 FILE *in=fopen("/dev/random","r");
154 if (in)
155 {
156 for (i=0; i<SeedLength; i++)
157 Seeds[i]^=fgetc(in);
158 fclose(in);
159 }
160 else
161 assert(0);
162#elif defined(_UNIX)
163 // UNIX without /dev/random (or it's too slow)
164
165 int_seeds[0]^=getuid();
166
167 struct sysinfo info;
168 sysinfo(&info);
169
170 int_seeds[1 % int_seed_length]^=info.loads[0];
171 int_seeds[2 % int_seed_length]^=info.loads[1];
172 int_seeds[3 % int_seed_length]^=info.loads[2];
173 int_seeds[4 % int_seed_length]^=info.freeram;
174 int_seeds[5 % int_seed_length]^=info.freeswap;
175 int_seeds[6 % int_seed_length]^=info.procs;
176 int_seeds[7 % int_seed_length]^=info.bufferram;
177#else
178
179 //
180 // Get free drive space
181 //
182 DWORD spc, bps, nfc, tnc; // various drive attributes (we don't care what they mean)
183 GetDiskFreeSpace(NULL, &spc, &bps, &nfc, &tnc);
184 int_seeds[0]^=spc;
185 int_seeds[1 % int_seed_length]^=bps;
186 int_seeds[2 % int_seed_length]^=nfc;
187 int_seeds[3 % int_seed_length]^=tnc;
188
189 //
190 // Get computer & user name
191 //
192 char comp_name[128];
193 char user_name[128];
194 DWORD comp_len=128;
195 DWORD name_len=128;
196
197 GetComputerName(comp_name, &comp_len);
198 GetUserName(user_name, &name_len);
199 for (i=0; i<128; i++)
200 {
201 // Offset in case user_name == comp_name
202 Seeds[(i+0) % SeedLength]^=comp_name[i];
203 Seeds[(i+2) % SeedLength]^=user_name[i];
204 }
205
206#endif
207
208 for (i=0; i<int_seed_length; i++)
209 {
210 if ((i % 4) == 0)
211 int_seeds[i]^=time(NULL);
212 else if ((i % 4) == 1)
213 int_seeds[i]^=getpid();
214 else if ((i % 4) == 2)
215 int_seeds[i]^=GetTickCount();
216 else if ((i % 4) == 3)
217 int_seeds[i]^=i;
218 }
219}
#define NULL
Definition BaseType.h:92
unsigned long DWORD
Definition bittype.h:57
void Hash(void const *data, long length)
Definition sha.cpp:124
int Result(void *result) const
Definition sha.cpp:179
void Add_Seeds(unsigned char *values, int length)
Definition srandom.cpp:71
unsigned long Randval()
Definition srandom.cpp:91