RNDSTRAW.CPP (20973B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: /CounterStrike/RNDSTRAW.CPP 1 3/03/97 10:25a Joe_bostic $ */ 17 /*********************************************************************************************** 18 *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *** 19 *********************************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : RNDSTRAW.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 07/04/96 * 28 * * 29 * Last Update : July 10, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * RandomStraw::Get -- Fetch random data. * 34 * RandomStraw::RandomStraw -- Constructor for the random straw class. * 35 * RandomStraw::Reset -- Reset the data to known initial state. * 36 * RandomStraw::Scramble_Seed -- Masks any coorelation between the seed bits. * 37 * RandomStraw::Seed_Bit -- Add a random bit to the accumulated seed value. * 38 * RandomStraw::Seed_Bits_Needed -- Fetches the number of seed bits needed. * 39 * RandomStraw::Seed_Byte -- Submit 8 bits to the random number seed. * 40 * RandomStraw::Seed_Long -- Submit 32 bits to the random number seed. * 41 * RandomStraw::Seed_Short -- Submit 16 bits to the random number seed. * 42 * RandomStraw::~RandomStraw -- Destructor for random straw class. * 43 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 44 45 #include <limits.h> 46 #include <string.h> 47 #include "rndstraw.h" 48 #include "sha.h" 49 50 51 /*********************************************************************************************** 52 * RandomStraw::RandomStraw -- Constructor for the random straw class. * 53 * * 54 * This will initialize the random straw into a known state. The initial state is useless * 55 * for cryptographic purposes. It must be seeded before it should be used. * 56 * * 57 * INPUT: none * 58 * * 59 * OUTPUT: none * 60 * * 61 * WARNINGS: none * 62 * * 63 * HISTORY: * 64 * 07/10/1996 JLB : Created. * 65 *=============================================================================================*/ 66 RandomStraw::RandomStraw(void) : 67 SeedBits(0), 68 Current(0) 69 { 70 Reset(); 71 } 72 73 74 /*********************************************************************************************** 75 * RandomStraw::~RandomStraw -- Destructor for random straw class. * 76 * * 77 * This destructor will clear out the seed data so that there won't be any sensitive * 78 * information left over in the memory this object occupied. * 79 * * 80 * INPUT: none * 81 * * 82 * OUTPUT: none * 83 * * 84 * WARNINGS: none * 85 * * 86 * HISTORY: * 87 * 07/10/1996 JLB : Created. * 88 *=============================================================================================*/ 89 RandomStraw::~RandomStraw(void) 90 { 91 Reset(); 92 } 93 94 95 /*********************************************************************************************** 96 * RandomStraw::Reset -- Reset the data to known initial state. * 97 * * 98 * This routine is functionally equivalent to performing an placement new on the object. It * 99 * clears out all the seed data. * 100 * * 101 * INPUT: none * 102 * * 103 * OUTPUT: none * 104 * * 105 * WARNINGS: You must reseed it before fetching random numbers. * 106 * * 107 * HISTORY: * 108 * 07/10/1996 JLB : Created. * 109 *=============================================================================================*/ 110 void RandomStraw::Reset(void) 111 { 112 SeedBits = 0; 113 Current = 0; 114 memset(Random, '\0', sizeof(Random)); 115 } 116 117 118 /*********************************************************************************************** 119 * RandomStraw::Seed_Bits_Needed -- Fetches the number of seed bits needed. * 120 * * 121 * This routine is used when seeding the random straw. Keep feeding random bits to this * 122 * class until the Seed_Bits_Needed value returns zero. Random bits should be gathered from * 123 * sources external to the immediate program. Examples would be the system clock (good for * 124 * a few bits), the delay between player keystrokes (good for a few bits per keystroke), * 125 * etc. When gathering random bits from integers, use the low order bits (since they * 126 * characteristically are less predictable and more 'random' than the others). * 127 * * 128 * INPUT: none * 129 * * 130 * OUTPUT: Returns with the number of bits required in order to fully seed this random * 131 * number generator. * 132 * * 133 * WARNINGS: Even if this routine returns zero, you are still allowed and encouraged to feed * 134 * more random bits when the opportunity arrises. * 135 * * 136 * HISTORY: * 137 * 07/10/1996 JLB : Created. * 138 *=============================================================================================*/ 139 int RandomStraw::Seed_Bits_Needed(void) const 140 { 141 const int total = sizeof(Random) * CHAR_BIT; 142 if (SeedBits < total) { 143 return(total - SeedBits); 144 } 145 return(0); 146 } 147 148 149 /*********************************************************************************************** 150 * RandomStraw::Seed_Bit -- Add a random bit to the accumulated seed value. * 151 * * 152 * This routine should be called to feed a single random bit to the random straw object. * 153 * You must feed as many bits as requested by the Seed_Bits_Needed() function. Submitting * 154 * additional bits is not only allowed, but encouraged. * 155 * * 156 * INPUT: seed -- The bit (lowest order bit) to feed to the random number seed. * 157 * * 158 * OUTPUT: none * 159 * * 160 * WARNINGS: none * 161 * * 162 * HISTORY: * 163 * 07/10/1996 JLB : Created. * 164 *=============================================================================================*/ 165 void RandomStraw::Seed_Bit(int seed) 166 { 167 char * ptr = ((char *)&Random[0]) + ((SeedBits / CHAR_BIT) % sizeof(Random)); 168 char frac = (char)(1 << (SeedBits & (CHAR_BIT-1))); 169 170 if (seed & 0x01) { 171 *ptr ^= frac; 172 } 173 SeedBits++; 174 175 if (SeedBits == (sizeof(Random) * CHAR_BIT)) { 176 Scramble_Seed(); 177 } 178 } 179 180 181 /*********************************************************************************************** 182 * RandomStraw::Seed_Byte -- Submit 8 bits to the random number seed. * 183 * * 184 * This will submit 8 bits (as specified) to the random number seed. * 185 * * 186 * INPUT: seed -- The seed bits to submit. * 187 * * 188 * OUTPUT: none * 189 * * 190 * WARNINGS: none * 191 * * 192 * HISTORY: * 193 * 07/10/1996 JLB : Created. * 194 *=============================================================================================*/ 195 void RandomStraw::Seed_Byte(char seed) 196 { 197 for (int index = 0; index < CHAR_BIT; index++) { 198 Seed_Bit(seed); 199 seed >>= 1; 200 } 201 } 202 203 204 /*********************************************************************************************** 205 * RandomStraw::Seed_Short -- Submit 16 bits to the random number seed. * 206 * * 207 * This will submit 16 bits to the accumulated seed. * 208 * * 209 * INPUT: seed -- The 16 bits to submit to the seed. * 210 * * 211 * OUTPUT: none * 212 * * 213 * WARNINGS: none * 214 * * 215 * HISTORY: * 216 * 07/10/1996 JLB : Created. * 217 *=============================================================================================*/ 218 void RandomStraw::Seed_Short(short seed) 219 { 220 for (int index = 0; index < (sizeof(seed)*CHAR_BIT); index++) { 221 Seed_Bit(seed); 222 seed >>= 1; 223 } 224 } 225 226 227 /*********************************************************************************************** 228 * RandomStraw::Seed_Long -- Submit 32 bits to the random number seed. * 229 * * 230 * This will submit a full 32 bits to the accumulated seed value. * 231 * * 232 * INPUT: seed -- The 32 bits to submit. * 233 * * 234 * OUTPUT: none * 235 * * 236 * WARNINGS: none * 237 * * 238 * HISTORY: * 239 * 07/10/1996 JLB : Created. * 240 *=============================================================================================*/ 241 void RandomStraw::Seed_Long(long seed) 242 { 243 for (int index = 0; index < (sizeof(seed)*CHAR_BIT); index++) { 244 Seed_Bit(seed); 245 seed >>= 1; 246 } 247 } 248 249 250 /*********************************************************************************************** 251 * RandomStraw::Scramble_Seed -- Masks any coorelation between the seed bits. * 252 * * 253 * This routine is called when a full set of seed bits has been accumulated. It will take * 254 * the existing seed and scramble the bits. An effective way of doing this is to use the * 255 * Secure Hash Algorithm. It is necessary to have this routine because there might be * 256 * some coorelation in the seed bits. Even more important is that this routine will result * 257 * in every bit of the seed having a scrambling effect on every other bit. * 258 * * 259 * INPUT: none * 260 * * 261 * OUTPUT: none * 262 * * 263 * WARNINGS: none * 264 * * 265 * HISTORY: * 266 * 07/10/1996 JLB : Created. * 267 *=============================================================================================*/ 268 void RandomStraw::Scramble_Seed(void) 269 { 270 SHAEngine sha; 271 272 for (int index = 0; index < sizeof(Random); index++) { 273 char digest[20]; 274 275 sha.Hash(&Random[0], sizeof(Random)); 276 sha.Result(digest); 277 278 int tocopy = sizeof(digest) < (sizeof(Random)-index) ? sizeof(digest) : (sizeof(Random)-index); 279 memmove(((char *)&Random[0]) + index, digest, tocopy); 280 } 281 } 282 283 284 /*********************************************************************************************** 285 * RandomStraw::Get -- Fetch random data. * 286 * * 287 * This routine will fetch random data and store it into the buffer specified. * 288 * * 289 * INPUT: source -- Pointer to the buffer to fill with random data. * 290 * * 291 * length -- The number of bytes to store into the buffer. * 292 * * 293 * OUTPUT: Returns with the actual number of bytes stored into the buffer. This will always * 294 * be the number of bytes requested since random numbers are unexhaustible. * 295 * * 296 * WARNINGS: none * 297 * * 298 * HISTORY: * 299 * 07/04/1996 JLB : Created. * 300 * 07/10/1996 JLB : Revamped to make cryptographically secure. * 301 *=============================================================================================*/ 302 int RandomStraw::Get(void * source, int slen) 303 { 304 if (source == NULL || slen < 1) { 305 return(Straw::Get(source, slen)); 306 } 307 308 int total = 0; 309 while (slen > 0) { 310 *(char *)source = (char)Random[Current++]; 311 Current = Current % (sizeof(Random) / sizeof(Random[0])); 312 source = (char*)source + sizeof(char); 313 slen--; 314 total++; 315 } 316 return(total); 317 }