CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

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 }