305 lines
17 KiB
C++
305 lines
17 KiB
C++
/*
|
|
** Command & Conquer Red Alert(tm)
|
|
** Copyright 2025 Electronic Arts Inc.
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation, either version 3 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* $Header: /CounterStrike/PKSTRAW.CPP 1 3/03/97 10:25a Joe_bostic $ */
|
|
/***********************************************************************************************
|
|
*** 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 ***
|
|
***********************************************************************************************
|
|
* *
|
|
* Project Name : Command & Conquer *
|
|
* *
|
|
* File Name : PKSTRAW.CPP *
|
|
* *
|
|
* Programmer : Joe L. Bostic *
|
|
* *
|
|
* Start Date : 07/08/96 *
|
|
* *
|
|
* Last Update : July 11, 1996 [JLB] *
|
|
* *
|
|
*---------------------------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length. *
|
|
* PKStraw::Get -- Fetch data and process it accordingly. *
|
|
* PKStraw::Get_From -- Chains one straw to another. *
|
|
* PKStraw::Key -- Assign a key to the cipher process straw. *
|
|
* PKStraw::PKStraw -- Initialize the public key straw object. *
|
|
* PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key. *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "pkstraw.h"
|
|
#include "rndstraw.h"
|
|
#include "blwstraw.h"
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PKStraw::PKStraw -- Initialize the public key straw object. *
|
|
* *
|
|
* This constructs the public key straw object. The operation to perform (encrypt or *
|
|
* decrypt) as well as a random number generator must be provided. *
|
|
* *
|
|
* INPUT: control -- What operation to perform on the data. Pass in either ENCRYPT or *
|
|
* DECRYPT. *
|
|
* *
|
|
* rnd -- Reference to a random number straw that is used internally to *
|
|
* generate the sub-key. The final strength of the cipher depends on *
|
|
* quality of this random number generator. *
|
|
* *
|
|
* OUTPUT: none *
|
|
* *
|
|
* WARNINGS: none *
|
|
* *
|
|
* HISTORY: *
|
|
* 07/11/1996 JLB : Created. *
|
|
*=============================================================================================*/
|
|
PKStraw::PKStraw(CryptControl control, RandomStraw & rnd) :
|
|
IsGettingKey(true),
|
|
Rand(rnd),
|
|
BF((control == ENCRYPT) ? BlowStraw::ENCRYPT : BlowStraw::DECRYPT),
|
|
Control(control),
|
|
CipherKey(NULL),
|
|
Counter(0),
|
|
BytesLeft(0)
|
|
{
|
|
Straw::Get_From(BF);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PKStraw::Get_From -- Chains one straw to another. *
|
|
* *
|
|
* This routine handles the special case of this straw object in that there is an *
|
|
* embedded blowfish straw segment. It must be chained on correctly. *
|
|
* *
|
|
* INPUT: straw -- Pointer to the straw segment that this segment is to receive data from. *
|
|
* *
|
|
* OUTPUT: none *
|
|
* *
|
|
* WARNINGS: none *
|
|
* *
|
|
* HISTORY: *
|
|
* 07/11/1996 JLB : Created. *
|
|
*=============================================================================================*/
|
|
void PKStraw::Get_From(Straw * straw)
|
|
{
|
|
if (BF.ChainTo != straw) {
|
|
if (straw != NULL && straw->ChainFrom != NULL) {
|
|
straw->ChainFrom->Get_From(NULL);
|
|
straw->ChainFrom = NULL;
|
|
}
|
|
|
|
if (BF.ChainTo != NULL) {
|
|
BF.ChainTo->ChainFrom = NULL;
|
|
}
|
|
|
|
BF.ChainTo = straw;
|
|
BF.ChainFrom = this;
|
|
ChainTo = &BF;
|
|
if (BF.ChainTo != NULL) {
|
|
BF.ChainTo->ChainFrom = this;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PKStraw::Key -- Assign a key to the cipher process straw. *
|
|
* *
|
|
* This routine will assign the key (or NULL if the current key is to be removed) to the *
|
|
* cipher stream process. When a key has been assigned, encryption or decryption will *
|
|
* take place. In the absence (NULL key pointer) of a key, the data passes through *
|
|
* unchanged. *
|
|
* *
|
|
* INPUT: key -- Pointer to the key to assign to the stream. If the key pointer is NULL, *
|
|
* then this causes the cipher stream to stop processing the data and will *
|
|
* pass the data through unchanged. *
|
|
* *
|
|
* OUTPUT: none *
|
|
* *
|
|
* WARNINGS: Be sure that the key passed to this routine is the opposite key to that used *
|
|
* to process the stream originally (when decrypting). *
|
|
* *
|
|
* HISTORY: *
|
|
* 07/08/1996 JLB : Created. *
|
|
*=============================================================================================*/
|
|
void PKStraw::Key(PKey const * key)
|
|
{
|
|
CipherKey = key;
|
|
if (key != NULL) {
|
|
IsGettingKey = true;
|
|
}
|
|
Counter = 0;
|
|
BytesLeft = 0;
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PKStraw::Get -- Fetch data and process it accordingly. *
|
|
* *
|
|
* This routine will fetch the number of bytes requested. If a valid key has been assigned *
|
|
* to this stream, then the data will be processed as it passes through. *
|
|
* *
|
|
* INPUT: source -- Pointer to the buffer that will hold the requested data. *
|
|
* *
|
|
* length -- The number of data bytes requested. *
|
|
* *
|
|
* OUTPUT: Returns with the actual number of data bytes stored to the destination buffer. If *
|
|
* this number is less than that requested, then it indicates that the data source *
|
|
* has been exhausted. *
|
|
* *
|
|
* WARNINGS: none *
|
|
* *
|
|
* HISTORY: *
|
|
* 07/08/1996 JLB : Created. *
|
|
*=============================================================================================*/
|
|
int PKStraw::Get(void * source, int length)
|
|
{
|
|
/*
|
|
** If the parameters seem invalid, then pass the request on so that someone
|
|
** else can deal with it.
|
|
*/
|
|
if (source == NULL || length < 1 || CipherKey == NULL) {
|
|
return(Straw::Get(source, length));
|
|
}
|
|
|
|
int total = 0;
|
|
|
|
/*
|
|
** The first part of the data flow must process the special key. After the special
|
|
** key has been processed, the data flows through this straw without direct
|
|
** modification (the blowfish straw will process the data).
|
|
*/
|
|
if (IsGettingKey) {
|
|
|
|
if (Control == DECRYPT) {
|
|
|
|
/*
|
|
** Retrieve the pk encrypted blowfish key block.
|
|
*/
|
|
char cbuffer[MAX_KEY_BLOCK_SIZE];
|
|
int got = Straw::Get(cbuffer, Encrypted_Key_Length());
|
|
|
|
/*
|
|
** If the entire key block could not be retrieved, then this indicates
|
|
** a major data flow error -- just return with no action performed.
|
|
*/
|
|
if (got != Encrypted_Key_Length()) return(0);
|
|
|
|
/*
|
|
** Decrypt the blowfish key and then activate the blowfish straw
|
|
** with that key.
|
|
*/
|
|
CipherKey->Decrypt(cbuffer, got, Buffer);
|
|
BF.Key(Buffer, BLOWFISH_KEY_SIZE);
|
|
|
|
} else {
|
|
|
|
/*
|
|
** Generate the blowfish key by using random numbers.
|
|
*/
|
|
char buffer[MAX_KEY_BLOCK_SIZE];
|
|
memset(buffer, '\0', sizeof(buffer));
|
|
Rand.Get(buffer, BLOWFISH_KEY_SIZE);
|
|
|
|
/*
|
|
** Encrypt the blowfish key (along with any necessary pad bytes).
|
|
*/
|
|
Counter = BytesLeft = CipherKey->Encrypt(buffer, Plain_Key_Length(), Buffer);
|
|
BF.Key(buffer, BLOWFISH_KEY_SIZE);
|
|
}
|
|
|
|
/*
|
|
** The first phase of getting the special key has been accomplished. Now, all
|
|
** subsequent data is passed (unmodified) though this straw segment. The blowfish
|
|
** straw takes over the compression/decompression from this point forward.
|
|
*/
|
|
IsGettingKey = false;
|
|
}
|
|
|
|
/*
|
|
** If there are any pending bytes in the buffer, then pass
|
|
** these on first. The only time this should be is when the blowfish
|
|
** key has first been generated.
|
|
*/
|
|
if (BytesLeft > 0) {
|
|
int tocopy = (length < BytesLeft) ? length : BytesLeft;
|
|
memmove(source, &Buffer[Counter-BytesLeft], tocopy);
|
|
source = (char *)source + tocopy;
|
|
BytesLeft -= tocopy;
|
|
length -= tocopy;
|
|
total += tocopy;
|
|
}
|
|
|
|
/*
|
|
** Any requested bytes that haven't been satisfied are copied over now by
|
|
** drawing the data through the blowfish engine. The blowfish engine happens
|
|
** to be linked to the chain so a normal Get() operation is sufficient.
|
|
*/
|
|
total += Straw::Get(source, length);
|
|
|
|
return(total);
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PKStraw::Encrypted_Key_Length -- Fetch the encrypted key length. *
|
|
* *
|
|
* This returns the total number of bytes (after encryption) that the blowfish key will *
|
|
* consume. It should be possible to get a block of this size, then pass it to the *
|
|
* public key decrypter and the result will be the full blowfish key. *
|
|
* *
|
|
* INPUT: none *
|
|
* *
|
|
* OUTPUT: Returns with the number of bytes that the encrypted blowfish key required. *
|
|
* *
|
|
* WARNINGS: none *
|
|
* *
|
|
* HISTORY: *
|
|
* 07/11/1996 JLB : Created. *
|
|
*=============================================================================================*/
|
|
int PKStraw::Encrypted_Key_Length(void) const
|
|
{
|
|
if (CipherKey == NULL) return(0);
|
|
return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Crypt_Block_Size());
|
|
}
|
|
|
|
|
|
/***********************************************************************************************
|
|
* PKStraw::Plain_Key_Length -- Returns the number of bytes to encrypt key. *
|
|
* *
|
|
* This is the number of plain (unencrypted) bytes that the blowfish key will take up. This *
|
|
* is actually the number of plain blocks minimum that can contain the full blowfish *
|
|
* key. The public key cryptography system encrypts in whole blocks only. *
|
|
* *
|
|
* INPUT: none *
|
|
* *
|
|
* OUTPUT: Returns with the total number of bytes that will contain the full blowfish key *
|
|
* and still be an even block size for the public key cryptography process. *
|
|
* *
|
|
* WARNINGS: This value is probably be larger than the actual blowfish key length. *
|
|
* *
|
|
* HISTORY: *
|
|
* 07/11/1996 JLB : Created. *
|
|
*=============================================================================================*/
|
|
int PKStraw::Plain_Key_Length(void) const
|
|
{
|
|
if (CipherKey == NULL) return(0);
|
|
return(CipherKey->Block_Count(BLOWFISH_KEY_SIZE) * CipherKey->Plain_Block_Size());
|
|
}
|