PKSTRAW.CPP (17216B)
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/PKSTRAW.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 : PKSTRAW.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 07/08/96 * 28 * * 29 * Last Update : July 11, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length. * 34 * PKStraw::Get -- Fetch data and process it accordingly. * 35 * PKStraw::Get_From -- Chains one straw to another. * 36 * PKStraw::Key -- Assign a key to the cipher process straw. * 37 * PKStraw::PKStraw -- Initialize the public key straw object. * 38 * PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key. * 39 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 40 41 42 #include "pkstraw.h" 43 #include "rndstraw.h" 44 #include "blwstraw.h" 45 46 47 /*********************************************************************************************** 48 * PKStraw::PKStraw -- Initialize the public key straw object. * 49 * * 50 * This constructs the public key straw object. The operation to perform (encrypt or * 51 * decrypt) as well as a random number generator must be provided. * 52 * * 53 * INPUT: control -- What operation to perform on the data. Pass in either ENCRYPT or * 54 * DECRYPT. * 55 * * 56 * rnd -- Reference to a random number straw that is used internally to * 57 * generate the sub-key. The final strength of the cipher depends on * 58 * quality of this random number generator. * 59 * * 60 * OUTPUT: none * 61 * * 62 * WARNINGS: none * 63 * * 64 * HISTORY: * 65 * 07/11/1996 JLB : Created. * 66 *=============================================================================================*/ 67 PKStraw::PKStraw(CryptControl control, RandomStraw & rnd) : 68 IsGettingKey(true), 69 Rand(rnd), 70 BF((control == ENCRYPT) ? BlowStraw::ENCRYPT : BlowStraw::DECRYPT), 71 Control(control), 72 CipherKey(NULL), 73 Counter(0), 74 BytesLeft(0) 75 { 76 Straw::Get_From(BF); 77 } 78 79 80 /*********************************************************************************************** 81 * PKStraw::Get_From -- Chains one straw to another. * 82 * * 83 * This routine handles the special case of this straw object in that there is an * 84 * embedded blowfish straw segment. It must be chained on correctly. * 85 * * 86 * INPUT: straw -- Pointer to the straw segment that this segment is to receive data from. * 87 * * 88 * OUTPUT: none * 89 * * 90 * WARNINGS: none * 91 * * 92 * HISTORY: * 93 * 07/11/1996 JLB : Created. * 94 *=============================================================================================*/ 95 void PKStraw::Get_From(Straw * straw) 96 { 97 if (BF.ChainTo != straw) { 98 if (straw != NULL && straw->ChainFrom != NULL) { 99 straw->ChainFrom->Get_From(NULL); 100 straw->ChainFrom = NULL; 101 } 102 103 if (BF.ChainTo != NULL) { 104 BF.ChainTo->ChainFrom = NULL; 105 } 106 107 BF.ChainTo = straw; 108 BF.ChainFrom = this; 109 ChainTo = &BF; 110 if (BF.ChainTo != NULL) { 111 BF.ChainTo->ChainFrom = this; 112 } 113 } 114 } 115 116 117 118 /*********************************************************************************************** 119 * PKStraw::Key -- Assign a key to the cipher process straw. * 120 * * 121 * This routine will assign the key (or NULL if the current key is to be removed) to the * 122 * cipher stream process. When a key has been assigned, encryption or decryption will * 123 * take place. In the absence (NULL key pointer) of a key, the data passes through * 124 * unchanged. * 125 * * 126 * INPUT: key -- Pointer to the key to assign to the stream. If the key pointer is NULL, * 127 * then this causes the cipher stream to stop processing the data and will * 128 * pass the data through unchanged. * 129 * * 130 * OUTPUT: none * 131 * * 132 * WARNINGS: Be sure that the key passed to this routine is the opposite key to that used * 133 * to process the stream originally (when decrypting). * 134 * * 135 * HISTORY: * 136 * 07/08/1996 JLB : Created. * 137 *=============================================================================================*/ 138 void PKStraw::Key(PKey const * key) 139 { 140 CipherKey = key; 141 if (key != NULL) { 142 IsGettingKey = true; 143 } 144 Counter = 0; 145 BytesLeft = 0; 146 } 147 148 149 /*********************************************************************************************** 150 * PKStraw::Get -- Fetch data and process it accordingly. * 151 * * 152 * This routine will fetch the number of bytes requested. If a valid key has been assigned * 153 * to this stream, then the data will be processed as it passes through. * 154 * * 155 * INPUT: source -- Pointer to the buffer that will hold the requested data. * 156 * * 157 * length -- The number of data bytes requested. * 158 * * 159 * OUTPUT: Returns with the actual number of data bytes stored to the destination buffer. If * 160 * this number is less than that requested, then it indicates that the data source * 161 * has been exhausted. * 162 * * 163 * WARNINGS: none * 164 * * 165 * HISTORY: * 166 * 07/08/1996 JLB : Created. * 167 *=============================================================================================*/ 168 int PKStraw::Get(void * source, int length) 169 { 170 /* 171 ** If the parameters seem invalid, then pass the request on so that someone 172 ** else can deal with it. 173 */ 174 if (source == NULL || length < 1 || CipherKey == NULL) { 175 return(Straw::Get(source, length)); 176 } 177 178 int total = 0; 179 180 /* 181 ** The first part of the data flow must process the special key. After the special 182 ** key has been processed, the data flows through this straw without direct 183 ** modification (the blowfish straw will process the data). 184 */ 185 if (IsGettingKey) { 186 187 if (Control == DECRYPT) { 188 189 /* 190 ** Retrieve the pk encrypted blowfish key block. 191 */ 192 char cbuffer[MAX_KEY_BLOCK_SIZE]; 193 int got = Straw::Get(cbuffer, Encrypted_Key_Length()); 194 195 /* 196 ** If the entire key block could not be retrieved, then this indicates 197 ** a major data flow error -- just return with no action performed. 198 */ 199 if (got != Encrypted_Key_Length()) return(0); 200 201 /* 202 ** Decrypt the blowfish key and then activate the blowfish straw 203 ** with that key. 204 */ 205 CipherKey->Decrypt(cbuffer, got, Buffer); 206 BF.Key(Buffer, BLOWFISH_KEY_SIZE); 207 208 } else { 209 210 /* 211 ** Generate the blowfish key by using random numbers. 212 */ 213 char buffer[MAX_KEY_BLOCK_SIZE]; 214 memset(buffer, '\0', sizeof(buffer)); 215 Rand.Get(buffer, BLOWFISH_KEY_SIZE); 216 217 /* 218 ** Encrypt the blowfish key (along with any necessary pad bytes). 219 */ 220 Counter = BytesLeft = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer); 221 BF.Key(buffer, BLOWFISH_KEY_SIZE); 222 } 223 224 /* 225 ** The first phase of getting the special key has been accomplished. Now, all 226 ** subsequent data is passed (unmodified) though this straw segment. The blowfish 227 ** straw takes over the compression/decompression from this point forward. 228 */ 229 IsGettingKey = false; 230 } 231 232 /* 233 ** If there are any pending bytes in the buffer, then pass 234 ** these on first. The only time this should be is when the blowfish 235 ** key has first been generated. 236 */ 237 if (BytesLeft > 0) { 238 int tocopy = (length < BytesLeft) ? length : BytesLeft; 239 memmove(source, &Buffer[Counter-BytesLeft], tocopy); 240 source = (char *)source + tocopy; 241 BytesLeft -= tocopy; 242 length -= tocopy; 243 total += tocopy; 244 } 245 246 /* 247 ** Any requested bytes that haven't been satisfied are copied over now by 248 ** drawing the data through the blowfish engine. The blowfish engine happens 249 ** to be linked to the chain so a normal Get() operation is sufficient. 250 */ 251 total += Straw::Get(source, length); 252 253 return(total); 254 } 255 256 257 /*********************************************************************************************** 258 * PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length. * 259 * * 260 * This returns the total number of bytes (after encryption) that the blowfish key will * 261 * consume. It should be possible to get a block of this size, then pass it to the * 262 * public key decrypter and the result will be the full blowfish key. * 263 * * 264 * INPUT: none * 265 * * 266 * OUTPUT: Returns with the number of bytes that the encrypted blowfish key required. * 267 * * 268 * WARNINGS: none * 269 * * 270 * HISTORY: * 271 * 07/11/1996 JLB : Created. * 272 *=============================================================================================*/ 273 int PKStraw::Encrypted_Key_Length(void) const 274 { 275 if (CipherKey == NULL) return(0); 276 return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size()); 277 } 278 279 280 /*********************************************************************************************** 281 * PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key. * 282 * * 283 * This is the number of plain (unencrypted) bytes that the blowfish key will take up. This * 284 * is actually the number of plain blocks minimum that can contain the full blowfish * 285 * key. The public key cryptography system encrypts in whole blocks only. * 286 * * 287 * INPUT: none * 288 * * 289 * OUTPUT: Returns with the total number of bytes that will contain the full blowfish key * 290 * and still be an even block size for the public key cryptography process. * 291 * * 292 * WARNINGS: This value is probably be larger than the actual blowfish key length. * 293 * * 294 * HISTORY: * 295 * 07/11/1996 JLB : Created. * 296 *=============================================================================================*/ 297 int PKStraw::Plain_Key_Length(void) const 298 { 299 if (CipherKey == NULL) return(0); 300 return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size()); 301 }