PK.CPP (21799B)
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/PK.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 : PK.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 * PKey::Decode_Exponent -- Decodes the exponent back into the key. * 34 * PKey::Decode_Modulus -- Decodes the modulus value back into the key. * 35 * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext. * 36 * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer. * 37 * PKey::Encode_Modulus -- Encode the modulus portion of the key. * 38 * PKey::Encrypt -- Encrypt blocks of plaintext. * 39 * PKey::Generate -- Generate a public and private key. * 40 * PKey::PKey -- Construct a key using encoded strings. * 41 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 42 43 #include "pk.h" 44 #include "rndstraw.h" 45 46 47 /*********************************************************************************************** 48 * PKey::PKey -- Construct a key using encoded strings. * 49 * * 50 * This constructor will construct a key based on the encoded strings supplied. * 51 * * 52 * INPUT: exponent -- The encoded string for the exponent portion of the key. * 53 * * 54 * modulus -- The encoded string for the modulus portion of the key. * 55 * * 56 * OUTPUT: none * 57 * * 58 * WARNINGS: none * 59 * * 60 * HISTORY: * 61 * 07/08/1996 JLB : Created. * 62 *=============================================================================================*/ 63 PKey::PKey(void const * exponent, void const * modulus) 64 { 65 Modulus.DERDecode((unsigned char *)modulus); 66 Exponent.DERDecode((unsigned char *)exponent); 67 BitPrecision = Modulus.BitCount()-1; 68 } 69 70 71 /*********************************************************************************************** 72 * PKey::Encode_Modulus -- Encode the modulus portion of the key. * 73 * * 74 * This will store the modulus portion of the key into a buffer. The number of bytes * 75 * stored into the buffer depends on the value of the key. * 76 * * 77 * INPUT: buffer -- Pointer to the buffer that will hold the encoded modulus value. * 78 * * 79 * OUTPUT: Returns with the number of bytes stored to the buffer. * 80 * * 81 * WARNINGS: Be sure that the buffer can hold the encoded bytes. This is normally around the * 82 * same size as the Crypt_Block_Size() (plus a byte or two). * 83 * * 84 * HISTORY: * 85 * 07/08/1996 JLB : Created. * 86 *=============================================================================================*/ 87 int PKey::Encode_Modulus(void * buffer) const 88 { 89 if (buffer == NULL) { 90 return(0); 91 } 92 return(Modulus.DEREncode((unsigned char *)buffer)); 93 } 94 95 96 /*********************************************************************************************** 97 * PKey::Encode_Exponent -- Encode the exponent portion of the key into a buffer. * 98 * * 99 * This routine will encode the exponent portion of the key. This is only necessary for the * 100 * slow key since the fast key always has an exponent of 65537. * 101 * * 102 * INPUT: buffer -- Pointer to the buffer that will be filled with the encoded exponent. * 103 * * 104 * OUTPUT: Returns with the nuber of bytes stored into the buffer. * 105 * * 106 * WARNINGS: Be sure the buffer is big enough to hold the encoded exponent. Usually this is * 107 * about the same size as the Crypt_Block_Size (plus a byte or two). * 108 * * 109 * HISTORY: * 110 * 07/08/1996 JLB : Created. * 111 *=============================================================================================*/ 112 int PKey::Encode_Exponent(void * buffer) const 113 { 114 if (buffer == NULL) { 115 return(0); 116 } 117 return(Exponent.DEREncode((unsigned char *)buffer)); 118 } 119 120 121 /*********************************************************************************************** 122 * PKey::Decode_Modulus -- Decodes the modulus value back into the key. * 123 * * 124 * This is the counterpart to the Encode_Modulus() function. It will initialize the * 125 * modulus portion of the key with the encoded data supplied. * 126 * * 127 * INPUT: buffer -- Pointer to the buffer that holds the previously encoded modulus value. * 128 * * 129 * OUTPUT: void * 130 * * 131 * WARNINGS: void * 132 * * 133 * HISTORY: * 134 * 07/08/1996 JLB : Created. * 135 *=============================================================================================*/ 136 void PKey::Decode_Modulus(void * buffer) 137 { 138 Modulus.DERDecode((unsigned char *)buffer); 139 BitPrecision = Modulus.BitCount()-1; 140 } 141 142 143 /*********************************************************************************************** 144 * PKey::Decode_Exponent -- Decodes the exponent back into the key. * 145 * * 146 * This is the counterpart to the Encode_Exponent function. It will decode a previously * 147 * encoded exponent portion back into the key. * 148 * * 149 * INPUT: buffer -- Pointer to the buffer that holds the encoded exponent value. * 150 * * 151 * OUTPUT: none * 152 * * 153 * WARNINGS: none * 154 * * 155 * HISTORY: * 156 * 07/08/1996 JLB : Created. * 157 *=============================================================================================*/ 158 void PKey::Decode_Exponent(void * buffer) 159 { 160 Exponent.DERDecode((unsigned char *)buffer); 161 } 162 163 164 /*********************************************************************************************** 165 * PKey::Generate -- Generate a public and private key. * 166 * * 167 * Public key cryptography relies on having two paired keys. The key used to encrypt * 168 * data must be decrypted by using the other key. Which key designated as the public or * 169 * private key is arbitrary. However, one is faster than the other. Use the faster key for * 170 * the more common operation. * 171 * * 172 * INPUT: random -- Reference to a source of random data. * 173 * * 174 * bits -- The number of bits to use for key generation. Use a number greater * 175 * than 16 but less than 2048. The ideal bit size is one that is evenly * 176 * divisible by 8 and then add one. Practical numbers range from 65 to * 177 * 1025 bits. * 178 * * 179 * fastkey -- Reference to the key that has fast encryption/decryption properties. * 180 * * 181 * slowkey -- Reference to the mate key of the other. * 182 * * 183 * OUTPUT: none * 184 * * 185 * WARNINGS: This routine can take a very long time. It can take MINUTES to generate a * 186 * 1024 bit key (even on a Pentium Pro 200Mghz machine). * 187 * * 188 * HISTORY: * 189 * 07/05/1996 JLB : Created. * 190 * 07/10/1996 JLB : Must supply source of random data. * 191 *=============================================================================================*/ 192 void PKey::Generate(Straw & random, int bits, PKey & fastkey, PKey & slowkey) 193 { 194 //PG_TO_FIX 195 fastkey; 196 slowkey; 197 #if (0) 198 /* 199 ** Key generation consists of create a key pair and then testing the key 200 ** pair. If the test fails, then repeat the process. The test and repeat 201 ** method is required since the prime number generating process can't 202 ** guarantee the generation of a prime number -- it can only generate a 203 ** highly likely prime number. 204 */ 205 for (;;) { 206 /* 207 ** Generate the two random prime numbers. This is the longest 208 ** step. 209 */ 210 BigInt p = Generate_Prime(random, bits, &p); 211 BigInt q = Generate_Prime(random, bits, &q); 212 213 /* 214 ** The exponent factors are easy to calculate from the prime numbers. 215 */ 216 BigInt e = Fast_Exponent(); 217 BigInt n = p * q; 218 BigInt pqmin = (p-(unsigned short)1)*(q-(unsigned short)1); 219 BigInt d = e.Inverse(pqmin); 220 221 /* 222 ** Store the data into the key objects. Notice that the modulus is the 223 ** same for both the fast and slow keys. Also notice that the exponent for 224 ** the fast key is ALWAYS 65537. Given this, it is possible to economize the 225 ** fast key into being just the modulus and the slow key to being just the 226 ** exponent (presuming the slow key also has access to the fast key so that 227 ** it can get the modulus). 228 */ 229 fastkey.Exponent = e; 230 fastkey.Modulus = n; 231 fastkey.BitPrecision = n.BitCount()-1; 232 233 slowkey.Exponent = d; 234 slowkey.Modulus = n; 235 slowkey.BitPrecision = fastkey.BitPrecision; 236 237 /* 238 ** Test the keys by encrypting a block of random bytes. If it decrypts 239 ** correctly, then a valid key pair has been generated -- bail. 240 */ 241 char before[256]; 242 char after[256]; 243 244 for (int index = 0; index < fastkey.Plain_Block_Size(); index++) { 245 before[index] = (char)rand(); 246 } 247 fastkey.Encrypt(before, fastkey.Plain_Block_Size(), after); 248 slowkey.Decrypt(after, slowkey.Crypt_Block_Size(), after); 249 250 /* 251 ** Compare the pre and post processing buffer. A match indicates 252 ** a valid key pair. 253 */ 254 if (memcmp(before, after, fastkey.Plain_Block_Size()) == 0) break; 255 } 256 #endif 257 } 258 259 260 /*********************************************************************************************** 261 * PKey::Encrypt -- Encrypt blocks of plaintext. * 262 * * 263 * This routine will encrypt the supplied plaintext into cyphertext by processing the input * 264 * in block. The source is processed in whole blocks. Partial blocks are not supported by * 265 * public key cryptography. * 266 * * 267 * INPUT: source -- Pointer to the source plaintext that will be encrypted. * 268 * * 269 * length -- The length of the plaintext to encrypt. * 270 * * 271 * dest -- Pointer to the buffer that will hold the encrypted data. * 272 * * 273 * OUTPUT: Returns with the number of cypher text bytes placed into the destination buffer. * 274 * * 275 * WARNINGS: Be sure that the destination buffer is big enough to hold the output. * 276 * * 277 * HISTORY: * 278 * 07/05/1996 JLB : Created. * 279 *=============================================================================================*/ 280 int PKey::Encrypt(void const * source, int slen, void * dest) const 281 { 282 int total = 0; 283 284 /* 285 ** Encrypt the source data in full blocks. Partial blocks are not processed and are not 286 ** copied to the destination buffer. 287 */ 288 while (slen >= Plain_Block_Size()) { 289 290 /* 291 ** Perform the encryption of the block. 292 */ 293 BigInt temp = 0; 294 memmove(&temp, source, Plain_Block_Size()); 295 temp = temp.exp_b_mod_c(Exponent, Modulus); 296 297 /* 298 ** Move the cypher block to the destination. 299 */ 300 memmove(dest, &temp, Crypt_Block_Size()); 301 slen -= Plain_Block_Size(); 302 source = (char *)source + Plain_Block_Size(); 303 dest = (char *)dest + Crypt_Block_Size(); 304 total += Crypt_Block_Size(); 305 } 306 307 return(total); 308 } 309 310 311 /*********************************************************************************************** 312 * PKey::Decrypt -- Decrypt supplied cyphertext into its original plaintext. * 313 * * 314 * This routine will process the supplied cyphertext by breaking it up into blocks and * 315 * then decrypting each block in turn. The block size is dependant upon the key. By NOT * 316 * embedding this information into the cypher data, it makes the encryption more secure. * 317 * * 318 * INPUT: source -- Pointer to the cypher text to be decrypted. * 319 * * 320 * length -- The number of cypher text bytes supplied to this routine. * 321 * * 322 * dest -- Pointer to the buffer to hold the plaintext. * 323 * * 324 * OUTPUT: Returns with the number of plaintext bytes output to the destination buffer. * 325 * * 326 * WARNINGS: Only whole blocks are processed. If the source has any partial block sized * 327 * data, then it will be left unprocessed. * 328 * * 329 * HISTORY: * 330 * 07/05/1996 JLB : Created. * 331 *=============================================================================================*/ 332 int PKey::Decrypt(void const * source, int slen, void * dest) const 333 { 334 int total = 0; 335 BigInt temp; 336 337 /* 338 ** Decrypt the source data in full blocks. Partial blocks are not processed in any way. 339 */ 340 while (slen >= Crypt_Block_Size()) { 341 342 /* 343 ** Perform the encryption. 344 */ 345 temp = 0; 346 memmove(&temp, source, Crypt_Block_Size()); 347 temp = temp.exp_b_mod_c(Exponent, Modulus); 348 349 /* 350 ** Move the cypher block to the destination. 351 */ 352 memmove(dest, &temp, Plain_Block_Size()); 353 slen -= Crypt_Block_Size(); 354 source = (char *)source + Crypt_Block_Size(); 355 dest = (char *)dest + Plain_Block_Size(); 356 total += Plain_Block_Size(); 357 } 358 359 return(total); 360 }