CnC_Remastered_Collection

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

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 }