PKPIPE.CPP (16188B)
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/PKPIPE.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 * Project Name : Command & Conquer * 21 * * 22 * * 23 * File Name : PKPIPE.CPP * 24 * * 25 * Programmer : Joe L. Bostic * 26 * * 27 * Start Date : 07/07/96 * 28 * * 29 * Last Update : July 12, 1996 [JLB] * 30 * * 31 *---------------------------------------------------------------------------------------------* 32 * Functions: * 33 * PKPipe::Encrypted_Key_Length -- Fetch the encrypted key length. * 34 * PKPipe::Key -- Submit a key to enable processing of data flow. * 35 * PKPipe::PKPipe -- Constructor for the public key pipe object. * 36 * PKPipe::Plain_Key_Length -- Returns the number of bytes to encrypt key. * 37 * PKPipe::Put -- Submit data to the pipe for processing. * 38 * PKPipe::Put_To -- Chains one pipe to another. * 39 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 40 41 42 #include "pkpipe.h" 43 44 45 /*********************************************************************************************** 46 * PKPipe::PKPipe -- Constructor for the public key pipe object. * 47 * * 48 * This will construct the public key pipe object. * 49 * * 50 * INPUT: control -- The method used to process the data flow (encrypt or decrypt). * 51 * * 52 * rnd -- Reference to a random number generate used to create the internal * 53 * blowfish key. * 54 * * 55 * OUTPUT: none * 56 * * 57 * WARNINGS: none * 58 * * 59 * HISTORY: * 60 * 07/11/1996 JLB : Created. * 61 *=============================================================================================*/ 62 PKPipe::PKPipe(CryptControl control, RandomStraw & rnd) : 63 IsGettingKey(true), 64 Rand(rnd), 65 BF((control == ENCRYPT) ? BlowPipe::ENCRYPT : BlowPipe::DECRYPT), 66 Control(control), 67 CipherKey(NULL), 68 Counter(0), 69 BytesLeft(0) 70 { 71 } 72 73 74 /*********************************************************************************************** 75 * PKPipe::Put_To -- Chains one pipe to another. * 76 * * 77 * This handles linking of one pipe to this pipe. Data will flow from this PKPipe to the * 78 * pipe segment specified. Special handling is done so that piping actually flows to the * 79 * embedded blowfish pipe and then flows to the designated pipe. * 80 * * 81 * INPUT: pipe -- Pointer to the pipe that this pipe segment is to send data to. * 82 * * 83 * OUTPUT: none * 84 * * 85 * WARNINGS: none * 86 * * 87 * HISTORY: * 88 * 07/12/1996 JLB : Created. * 89 *=============================================================================================*/ 90 void PKPipe::Put_To(Pipe * pipe) 91 { 92 if (BF.ChainTo != pipe) { 93 if (pipe != NULL && pipe->ChainFrom != NULL) { 94 pipe->ChainFrom->Put_To(NULL); 95 pipe->ChainFrom = NULL; 96 } 97 98 if (BF.ChainTo != NULL) { 99 BF.ChainTo->ChainFrom = NULL; 100 } 101 BF.ChainTo = pipe; 102 if (pipe != NULL) { 103 pipe->ChainFrom = &BF; 104 } 105 BF.ChainFrom = this; 106 ChainTo = &BF; 107 } 108 } 109 110 111 /*********************************************************************************************** 112 * PKPipe::Key -- Submit a key to enable processing of data flow. * 113 * * 114 * This routine must be called with a valid key pointer in order for encryption/description * 115 * to be performed on the data stream. Prior to calling this routine or after calling this * 116 * routine with a NULL pointer, the data stream will pass through this pipe without * 117 * modification. * 118 * * 119 * INPUT: key -- Pointer to the key to use for processing. Pass NULL if process is to be * 120 * terminated. * 121 * * 122 * OUTPUT: none * 123 * * 124 * WARNINGS: none * 125 * * 126 * HISTORY: * 127 * 07/07/1996 JLB : Created. * 128 *=============================================================================================*/ 129 void PKPipe::Key(PKey const * key) 130 { 131 if (key == NULL) { 132 Flush(); 133 IsGettingKey = false; 134 } 135 CipherKey = key; 136 137 if (CipherKey != NULL) { 138 IsGettingKey = true; 139 if (Control == DECRYPT) { 140 Counter = BytesLeft = Encrypted_Key_Length(); 141 } 142 } 143 } 144 145 146 /*********************************************************************************************** 147 * PKPipe::Put -- Submit data to the pipe for processing. * 148 * * 149 * This routine (if processing as been enabled by a previous key submission) will * 150 * encrypt or decrypt the data stream that passes through it. When encrypting, the data * 151 * stream will increase in size by about 10% (bit it varies according to the key used). * 152 * * 153 * INPUT: source -- Pointer to the data to be submitted to the pipe stream. * 154 * * 155 * length -- The number of bytes submitted. * 156 * * 157 * OUTPUT: Returns with the actual number of byte output at the final end of the pipe. * 158 * * 159 * WARNINGS: none * 160 * * 161 * HISTORY: * 162 * 07/07/1996 JLB : Created. * 163 *=============================================================================================*/ 164 int PKPipe::Put(void const * source, int length) 165 { 166 /* 167 ** If the parameter seem illegal, then pass the pipe request to the 168 ** next pipe in the chain and let them deal with it. 169 */ 170 if (source == NULL || length < 1 || CipherKey == NULL) { 171 return(Pipe::Put(source, length)); 172 } 173 174 int total = 0; 175 176 /* 177 ** Perform a special process if the this is the first part of the data flow. The special 178 ** key must be processed first. After this initial key processing, the rest of the data flow 179 ** is processed by the blowfish pipe and ignored by the PKPipe. 180 */ 181 if (IsGettingKey) { 182 183 /* 184 ** When encrypting, first make the key block and then pass the data through the 185 ** normal blowfish processor. 186 */ 187 if (Control == ENCRYPT) { 188 189 /* 190 ** Generate the largest blowfish key possible. 191 */ 192 char buffer[MAX_KEY_BLOCK_SIZE]; 193 memset(buffer, '\0', sizeof(buffer)); 194 Rand.Get(buffer, BLOWFISH_KEY_SIZE); 195 196 /* 197 ** Encrypt the blowfish key (along with any necessary pad bytes). 198 */ 199 int didput = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer); 200 total += Pipe::Put(Buffer, didput); 201 BF.Key(buffer, BLOWFISH_KEY_SIZE); 202 203 IsGettingKey = false; 204 205 } else { 206 207 /* 208 ** First try to accumulate a full key. 209 */ 210 int toget = (BytesLeft < length) ? BytesLeft : length; 211 memmove(&Buffer[Counter-BytesLeft], source, toget); 212 length -= toget; 213 BytesLeft -= toget; 214 source = (char *)source + toget; 215 216 /* 217 ** If a full key has been accumulated, then decrypt it and feed the 218 ** key to the blowfish engine. 219 */ 220 if (BytesLeft == 0) { 221 char buffer[MAX_KEY_BLOCK_SIZE]; 222 CipherKey->Decrypt(Buffer, Counter, buffer); 223 BF.Key(buffer, BLOWFISH_KEY_SIZE); 224 225 IsGettingKey = false; 226 } 227 } 228 } 229 230 /* 231 ** If there are any remaining bytes to pipe through, then 232 ** pipe them through now -- they will be processed by the 233 ** blowfish engine. 234 */ 235 total += Pipe::Put(source, length); 236 return(total); 237 } 238 239 240 /*********************************************************************************************** 241 * PKPipe::Encrypted_Key_Length -- Fetch the encrypted key length. * 242 * * 243 * This returns the total number of bytes (after encryption) that the blowfish key will * 244 * consume. It should be possible to get a block of this size, then pass it to the * 245 * public key decrypter and the result will be the full blowfish key. * 246 * * 247 * INPUT: none * 248 * * 249 * OUTPUT: Returns with the number of bytes that the encrypted blowfish key required. * 250 * * 251 * WARNINGS: none * 252 * * 253 * HISTORY: * 254 * 07/11/1996 JLB : Created. * 255 *=============================================================================================*/ 256 int PKPipe::Encrypted_Key_Length(void) const 257 { 258 if (CipherKey == NULL) return(0); 259 return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size()); 260 } 261 262 263 /*********************************************************************************************** 264 * PKPipe::Plain_Key_Length -- Returns the number of bytes to encrypt key. * 265 * * 266 * This is the number of plain (unencrypted) bytes that the blowfish key will take up. This * 267 * is actually the number of plain blocks minimum that can contain the full blowfish * 268 * key. The public key cryptography system encrypts in whole blocks only. * 269 * * 270 * INPUT: none * 271 * * 272 * OUTPUT: Returns with the total number of bytes that will contain the full blowfish key * 273 * and still be an even block size for the public key cryptography process. * 274 * * 275 * WARNINGS: This value is probably be larger than the actual blowfish key length. * 276 * * 277 * HISTORY: * 278 * 07/11/1996 JLB : Created. * 279 *=============================================================================================*/ 280 int PKPipe::Plain_Key_Length(void) const 281 { 282 if (CipherKey == NULL) return(0); 283 return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size()); 284 }