Files
UnrealEngineUWP/Engine/Source/Runtime/PacketHandlers/EncryptionComponents/RSAKeyAESEncryption/Private/RSAKeyAESEncryptionHandlerComponent.cpp

619 lines
17 KiB
C++
Raw Normal View History

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
Copying //UE4/Dev-Networking to //UE4/Dev-Main (Source: //UE4/Dev-Networking @ 3495493) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3302759 on 2017/02/14 by John.Pollard Remove invalid replay samples that can occur due to oversampling (sampling at higher rate than physics is being ticked) Change 3306072 on 2017/02/16 by John.Barrett Minor NetcodeUnitTest updates/fixes. Improved assignment for some types, using FVMReflection - added assignment to enum by name. Change 3322165 on 2017/02/24 by John.Barrett Fixed issue where Steam would block unit tests. #JIRA UENET-537 Change 3323917 on 2017/02/27 by John.Barrett Added better unit test log file management. #JIRA UENET-535 Unit test logs are now stored in subfolders in the game log folder, with one main folder for the current UE4 session, and one subfolder for every unit test run during that session. Logs are purged occasionally, in line with how the main game logs are purged. Change 3326307 on 2017/02/28 by John.Pollard Remove unused cvar Change 3327907 on 2017/03/01 by John.Barrett Merged some old NetcodeUnitTest debug features: - Added command for bit-based log dumping of data (for debugging bit-based netcode) - Added exported function, for allowing access to console commands, in modules which don't import Engine Change 3332710 on 2017/03/05 by John.Barrett Updated unit test flags to expect a disconnect when expecting a server crash. Change 3332715 on 2017/03/05 by John.Barrett Wrapped all CreateChannelBunch pointers with a nullptr check (used to not be required). Replaced old/duplicate unit test code (using CreateChannelBunch) for marking 'exploit failure', with the current centralized function calls. #JIRA UENET-539 Change 3336258 on 2017/03/07 by John.Pollard Add more info to history overflow logging Change 3336259 on 2017/03/07 by John.Pollard Don't pause replication for replay connections Change 3341288 on 2017/03/10 by John.Barrett Fixed invalid access to GLog during game shutdown. #JIRA UE-42394 Change 3341736 on 2017/03/10 by John.Pollard Get reliability packet handler working again (but still disabled by default) Change 3349298 on 2017/03/16 by John.Barrett Fixed issues/potential-issues with the timing of global variable destruction, based on Graeme Thornton's fix. #JIRA UE-42394 Change 3349393 on 2017/03/16 by John.Pollard Reliability handler cleanup Change 3350029 on 2017/03/16 by John.Barrett Updated PacketHandler to support an optional handshaking stage for HandlerComponents, where each handshake must execute sequentially starting at the component closest to the socket. Change 3350030 on 2017/03/16 by John.Barrett Updated Asymetric Encryption to support updated PacketHandler system, to perform a key handshake that is compatible with other HandlerComponent's, and fixed some serialization security issues by setting proper limits on values. Change 3350032 on 2017/03/16 by John.Barrett Minor corrections to variable types and constructor initializer lists, for the rest of the encryption code. Change 3355536 on 2017/03/20 by John.Barrett Added new PacketAudit debug feature, which uses inter-process-communication, to audit the integrity of incoming/outgoing packets at various stages of serialization, between a client and server. This is critically useful for low level netcode development, particularly with the PacketHandler. See PacketAudit.h for more information. Change 3355570 on 2017/03/20 by John.Barrett Added a small number packet auditing checks to key areas of low level netcode. Change 3355584 on 2017/03/20 by John.Barrett Updated ReliabilityHandlerComponent, to support packet reliability during the PacketHandler handshaking stage, and fixed ReliabilityHandlerComponent serializing based on a packets byte size, rather than bit size. Change 3373389 on 2017/03/30 by John.Barrett Added check for HandlerComponent's that require reliability. Change 3373390 on 2017/03/30 by John.Barrett Added TLS-like encryption handler component, which exchanges a secret key using asymmetric encryption (RSA), and implements symmetric encryption using that key (AES). Based on RSA encryption component, and John Pollard's AES changes. Enable in *Engine.ini, using: [PacketHandlerComponents] Components=RSAKeyAESEncryption bEnableReliability=true Change 3394518 on 2017/04/14 by Ryan.Gerleve Fix memory leak in FRepChangelistState: added destructor that properly destroys the properties in the shadow state buffer. Change 3432955 on 2017/05/10 by John.Barrett Randomized the initial packet sequence numbers for UNetConnection's and for reliable packets - using the stateless handshake cookie. Also added hooks to determine when PacketHandler level handshaking has completed, so that the initial connection packets can be delayed until this stage (required now, in order to exchange the sequence numbers first). Change 3464528 on 2017/05/29 by John.Barrett Fixed connection failure during unreliable network conditions, caused by a bad interaction between the stateless handshake and sequence initialization code. Added a new 'ack' stage to the stateless handshake, to ensure the client/server sequence is properly synchronised. Expanded the timeout/retry handling for the stateless handshake, so it is more robust, and fixed some bugs in this code. Change 3464537 on 2017/05/29 by John.Barrett Fixed an incompatibility between the asymmetric encryption, and the new PacketHandler handshake code. Change 3464543 on 2017/05/29 by John.Barrett Updated CryptoPP to 5.6.5. Change 3467529 on 2017/05/31 by Jon.Nabozny Add comments to FPacketSimulationSettings vars. Change 3469584 on 2017/06/01 by Ryan.Gerleve Log bunch ChSequence on reliable channel open along with other info. Change 3471329 on 2017/06/02 by John.Barrett Fixed PacketHandlerLog type not being exported. Change 3471875 on 2017/06/02 by John.Barrett Fixed code that was trying to send NetConnection packets from the server to the client, too early - and tidied up related checks. #JIRA UE-45637 Change 3473030 on 2017/06/04 by John.Barrett Fixed replay incomaptibility with recent sequence/handshake changes. Change 3476313 on 2017/06/06 by Ryan.Gerleve Add initial reliable sequence numbers to the log in UNetConnection::InitSequence. Change 3478649 on 2017/06/07 by Ryan.Gerleve Add additional logging for the case where a channel open command is received by a channel that's already opened locally. Change 3482926 on 2017/06/09 by John.Barrett First pass at Minimal Client refactor for NetcodeUnitTest - split basic/minimal client code out of ClientUnitTest, into its own class - while preserving existing ClientUnitTest interface. This will allow multiple minimal clients per unit test, where only one could be used before (necessary for games that require a beacon + game connection). Added reflection support for weak UObject properties. Added MCP requirements flag for unit tests. Process pipe reading tweaks, to avoid UI freezes. Change 3485179 on 2017/06/12 by Ryan.Gerleve Add backwards-compatibility macros for random initial packet sequence changes so that game plugins can check them. Change 3489040 on 2017/06/14 by John.Barrett Removed OnlineSubsystem dependencies. [CL 3495525 by Ryan Gerleve in Main branch]
2017-06-16 14:10:35 -04:00
#include "RSAKeyAESEncryptionHandlerComponent.h"
#include "PacketAudit.h"
#include "PacketHandler.h"
#include "Modules/ModuleManager.h"
#include "UObject/CoreNet.h"
IMPLEMENT_MODULE(FRSAKeyAESEncryptionModuleInterface, RSAKeyAESEncryption);
// @todo #JohnB: IMPORTANT: See if you can replace CryptoPP with OpenSSL API's instead, as that makes it easier for platform teams
// @todo #JohnB: Add/test support for CanReadUnaligned.
// @todo #JohnB: The entire encryption implementation should be very carefully audited, and something like DTLS reviewed,
// and a new document written up on how encryption would be implemented from scratch
// (starting from the stateless handshake code), and then compared against this
// @todo #JohnB: Add supporting for increasing 'AsymmetricKeySize' to 4096 - currently, this triggers a limit with MaxOutgoingBits,
// and thus is limited to 2048, until the code is expanded to support values greater than this.
// Defines
/** Puts a limit on the maximum size of the exponent. */
// @todo: This should be limited further, as a high exponent could potentially be used for performing a DoS attack,
// by making it very costly to decrypt packets. The limit is only this high temporarily.
#define MAX_EXPONENT_BITS 1024
#define AES_BLOCK_SIZE 16
/** The maximum size for a packet being compressed */
// @todo #JohnB: This actually overshoots the maximum, and should probably be refined further
#define MAX_COMPRESSED_PACKET_SIZE (MAX_PACKET_SIZE * 8)
/**
* Handshake sequence:
* Server Client
*
* AsymmetricKey = Rand()
*
* [AsymmetricKey] ->
*
* SessionKey = Rand()
* EncryptedSessionKey = Encrypt(SessionKey, AsymmetricKey)
*
* <- [EncryptedSessionKey]
*
* *Handshake Complete*
*
* SessionKey=Decrypt(SessionKey, AsymmetricKey)
*
* *Handshake Complete*
*/
/**
* RSAKeyAESEncryptionHandlerComponent
*/
RSAKeyAESEncryptionHandlerComponent::RSAKeyAESEncryptionHandlerComponent(uint32 InAsymmetricKeySize, uint32 InSessionKeySize)
: AsymmetricKeyMaxPlaintextLength(0)
, AsymmetricKeyFixedCiphertextLength(0)
, AsymmetricKeySize(InAsymmetricKeySize)
, SessionKeySize(InSessionKeySize)
, State(ERSAKeyAESEncryptionHandler::State::UnInitialized)
, AsymmetricRng()
, Params()
, AsymmetricEncrypt()
, AsymmetricDecrypt()
, PublicKey()
, PrivateKey()
, SymmetricEncrypt()
, SymmetricDecrypt()
{
SetActive(true);
bRequiresHandshake = true;
bRequiresReliability = true;
}
void RSAKeyAESEncryptionHandlerComponent::Initialize()
{
Params.GenerateRandomWithKeySize(AsymmetricRng, AsymmetricKeySize);
PublicKey = CryptoPP::RSA::PublicKey(Params);
PrivateKey = CryptoPP::RSA::PrivateKey(Params);
AsymmetricEncrypt = CryptoPP::RSAES_OAEP_SHA_Encryptor(PrivateKey);
AsymmetricDecrypt = CryptoPP::RSAES_OAEP_SHA_Decryptor(PrivateKey);
AsymmetricKeyMaxPlaintextLength = static_cast<uint32>(AsymmetricEncrypt.FixedMaxPlaintextLength());
AsymmetricKeyFixedCiphertextLength = static_cast<uint32>(AsymmetricEncrypt.FixedCiphertextLength());
}
void RSAKeyAESEncryptionHandlerComponent::NotifyHandshakeBegin()
{
// The server sends the asymmetric key
if (Handler->Mode == Handler::Mode::Server)
{
FBitWriter OutPacket;
FOutPacketTraits Traits;
Copying //UE4/Dev-Networking to //UE4/Dev-Main (Source: //UE4/Dev-Networking @ 3495493) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3302759 on 2017/02/14 by John.Pollard Remove invalid replay samples that can occur due to oversampling (sampling at higher rate than physics is being ticked) Change 3306072 on 2017/02/16 by John.Barrett Minor NetcodeUnitTest updates/fixes. Improved assignment for some types, using FVMReflection - added assignment to enum by name. Change 3322165 on 2017/02/24 by John.Barrett Fixed issue where Steam would block unit tests. #JIRA UENET-537 Change 3323917 on 2017/02/27 by John.Barrett Added better unit test log file management. #JIRA UENET-535 Unit test logs are now stored in subfolders in the game log folder, with one main folder for the current UE4 session, and one subfolder for every unit test run during that session. Logs are purged occasionally, in line with how the main game logs are purged. Change 3326307 on 2017/02/28 by John.Pollard Remove unused cvar Change 3327907 on 2017/03/01 by John.Barrett Merged some old NetcodeUnitTest debug features: - Added command for bit-based log dumping of data (for debugging bit-based netcode) - Added exported function, for allowing access to console commands, in modules which don't import Engine Change 3332710 on 2017/03/05 by John.Barrett Updated unit test flags to expect a disconnect when expecting a server crash. Change 3332715 on 2017/03/05 by John.Barrett Wrapped all CreateChannelBunch pointers with a nullptr check (used to not be required). Replaced old/duplicate unit test code (using CreateChannelBunch) for marking 'exploit failure', with the current centralized function calls. #JIRA UENET-539 Change 3336258 on 2017/03/07 by John.Pollard Add more info to history overflow logging Change 3336259 on 2017/03/07 by John.Pollard Don't pause replication for replay connections Change 3341288 on 2017/03/10 by John.Barrett Fixed invalid access to GLog during game shutdown. #JIRA UE-42394 Change 3341736 on 2017/03/10 by John.Pollard Get reliability packet handler working again (but still disabled by default) Change 3349298 on 2017/03/16 by John.Barrett Fixed issues/potential-issues with the timing of global variable destruction, based on Graeme Thornton's fix. #JIRA UE-42394 Change 3349393 on 2017/03/16 by John.Pollard Reliability handler cleanup Change 3350029 on 2017/03/16 by John.Barrett Updated PacketHandler to support an optional handshaking stage for HandlerComponents, where each handshake must execute sequentially starting at the component closest to the socket. Change 3350030 on 2017/03/16 by John.Barrett Updated Asymetric Encryption to support updated PacketHandler system, to perform a key handshake that is compatible with other HandlerComponent's, and fixed some serialization security issues by setting proper limits on values. Change 3350032 on 2017/03/16 by John.Barrett Minor corrections to variable types and constructor initializer lists, for the rest of the encryption code. Change 3355536 on 2017/03/20 by John.Barrett Added new PacketAudit debug feature, which uses inter-process-communication, to audit the integrity of incoming/outgoing packets at various stages of serialization, between a client and server. This is critically useful for low level netcode development, particularly with the PacketHandler. See PacketAudit.h for more information. Change 3355570 on 2017/03/20 by John.Barrett Added a small number packet auditing checks to key areas of low level netcode. Change 3355584 on 2017/03/20 by John.Barrett Updated ReliabilityHandlerComponent, to support packet reliability during the PacketHandler handshaking stage, and fixed ReliabilityHandlerComponent serializing based on a packets byte size, rather than bit size. Change 3373389 on 2017/03/30 by John.Barrett Added check for HandlerComponent's that require reliability. Change 3373390 on 2017/03/30 by John.Barrett Added TLS-like encryption handler component, which exchanges a secret key using asymmetric encryption (RSA), and implements symmetric encryption using that key (AES). Based on RSA encryption component, and John Pollard's AES changes. Enable in *Engine.ini, using: [PacketHandlerComponents] Components=RSAKeyAESEncryption bEnableReliability=true Change 3394518 on 2017/04/14 by Ryan.Gerleve Fix memory leak in FRepChangelistState: added destructor that properly destroys the properties in the shadow state buffer. Change 3432955 on 2017/05/10 by John.Barrett Randomized the initial packet sequence numbers for UNetConnection's and for reliable packets - using the stateless handshake cookie. Also added hooks to determine when PacketHandler level handshaking has completed, so that the initial connection packets can be delayed until this stage (required now, in order to exchange the sequence numbers first). Change 3464528 on 2017/05/29 by John.Barrett Fixed connection failure during unreliable network conditions, caused by a bad interaction between the stateless handshake and sequence initialization code. Added a new 'ack' stage to the stateless handshake, to ensure the client/server sequence is properly synchronised. Expanded the timeout/retry handling for the stateless handshake, so it is more robust, and fixed some bugs in this code. Change 3464537 on 2017/05/29 by John.Barrett Fixed an incompatibility between the asymmetric encryption, and the new PacketHandler handshake code. Change 3464543 on 2017/05/29 by John.Barrett Updated CryptoPP to 5.6.5. Change 3467529 on 2017/05/31 by Jon.Nabozny Add comments to FPacketSimulationSettings vars. Change 3469584 on 2017/06/01 by Ryan.Gerleve Log bunch ChSequence on reliable channel open along with other info. Change 3471329 on 2017/06/02 by John.Barrett Fixed PacketHandlerLog type not being exported. Change 3471875 on 2017/06/02 by John.Barrett Fixed code that was trying to send NetConnection packets from the server to the client, too early - and tidied up related checks. #JIRA UE-45637 Change 3473030 on 2017/06/04 by John.Barrett Fixed replay incomaptibility with recent sequence/handshake changes. Change 3476313 on 2017/06/06 by Ryan.Gerleve Add initial reliable sequence numbers to the log in UNetConnection::InitSequence. Change 3478649 on 2017/06/07 by Ryan.Gerleve Add additional logging for the case where a channel open command is received by a channel that's already opened locally. Change 3482926 on 2017/06/09 by John.Barrett First pass at Minimal Client refactor for NetcodeUnitTest - split basic/minimal client code out of ClientUnitTest, into its own class - while preserving existing ClientUnitTest interface. This will allow multiple minimal clients per unit test, where only one could be used before (necessary for games that require a beacon + game connection). Added reflection support for weak UObject properties. Added MCP requirements flag for unit tests. Process pipe reading tweaks, to avoid UI freezes. Change 3485179 on 2017/06/12 by Ryan.Gerleve Add backwards-compatibility macros for random initial packet sequence changes so that game plugins can check them. Change 3489040 on 2017/06/14 by John.Barrett Removed OnlineSubsystem dependencies. [CL 3495525 by Ryan Gerleve in Main branch]
2017-06-16 14:10:35 -04:00
PackAsymmetricKey(OutPacket);
SetState(ERSAKeyAESEncryptionHandler::State::SentKey);
FPacketAudit::AddStage(TEXT("RSAHandshake"), OutPacket);
Handler->SendHandlerPacket(this, OutPacket, Traits);
Copying //UE4/Dev-Networking to //UE4/Dev-Main (Source: //UE4/Dev-Networking @ 3495493) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3302759 on 2017/02/14 by John.Pollard Remove invalid replay samples that can occur due to oversampling (sampling at higher rate than physics is being ticked) Change 3306072 on 2017/02/16 by John.Barrett Minor NetcodeUnitTest updates/fixes. Improved assignment for some types, using FVMReflection - added assignment to enum by name. Change 3322165 on 2017/02/24 by John.Barrett Fixed issue where Steam would block unit tests. #JIRA UENET-537 Change 3323917 on 2017/02/27 by John.Barrett Added better unit test log file management. #JIRA UENET-535 Unit test logs are now stored in subfolders in the game log folder, with one main folder for the current UE4 session, and one subfolder for every unit test run during that session. Logs are purged occasionally, in line with how the main game logs are purged. Change 3326307 on 2017/02/28 by John.Pollard Remove unused cvar Change 3327907 on 2017/03/01 by John.Barrett Merged some old NetcodeUnitTest debug features: - Added command for bit-based log dumping of data (for debugging bit-based netcode) - Added exported function, for allowing access to console commands, in modules which don't import Engine Change 3332710 on 2017/03/05 by John.Barrett Updated unit test flags to expect a disconnect when expecting a server crash. Change 3332715 on 2017/03/05 by John.Barrett Wrapped all CreateChannelBunch pointers with a nullptr check (used to not be required). Replaced old/duplicate unit test code (using CreateChannelBunch) for marking 'exploit failure', with the current centralized function calls. #JIRA UENET-539 Change 3336258 on 2017/03/07 by John.Pollard Add more info to history overflow logging Change 3336259 on 2017/03/07 by John.Pollard Don't pause replication for replay connections Change 3341288 on 2017/03/10 by John.Barrett Fixed invalid access to GLog during game shutdown. #JIRA UE-42394 Change 3341736 on 2017/03/10 by John.Pollard Get reliability packet handler working again (but still disabled by default) Change 3349298 on 2017/03/16 by John.Barrett Fixed issues/potential-issues with the timing of global variable destruction, based on Graeme Thornton's fix. #JIRA UE-42394 Change 3349393 on 2017/03/16 by John.Pollard Reliability handler cleanup Change 3350029 on 2017/03/16 by John.Barrett Updated PacketHandler to support an optional handshaking stage for HandlerComponents, where each handshake must execute sequentially starting at the component closest to the socket. Change 3350030 on 2017/03/16 by John.Barrett Updated Asymetric Encryption to support updated PacketHandler system, to perform a key handshake that is compatible with other HandlerComponent's, and fixed some serialization security issues by setting proper limits on values. Change 3350032 on 2017/03/16 by John.Barrett Minor corrections to variable types and constructor initializer lists, for the rest of the encryption code. Change 3355536 on 2017/03/20 by John.Barrett Added new PacketAudit debug feature, which uses inter-process-communication, to audit the integrity of incoming/outgoing packets at various stages of serialization, between a client and server. This is critically useful for low level netcode development, particularly with the PacketHandler. See PacketAudit.h for more information. Change 3355570 on 2017/03/20 by John.Barrett Added a small number packet auditing checks to key areas of low level netcode. Change 3355584 on 2017/03/20 by John.Barrett Updated ReliabilityHandlerComponent, to support packet reliability during the PacketHandler handshaking stage, and fixed ReliabilityHandlerComponent serializing based on a packets byte size, rather than bit size. Change 3373389 on 2017/03/30 by John.Barrett Added check for HandlerComponent's that require reliability. Change 3373390 on 2017/03/30 by John.Barrett Added TLS-like encryption handler component, which exchanges a secret key using asymmetric encryption (RSA), and implements symmetric encryption using that key (AES). Based on RSA encryption component, and John Pollard's AES changes. Enable in *Engine.ini, using: [PacketHandlerComponents] Components=RSAKeyAESEncryption bEnableReliability=true Change 3394518 on 2017/04/14 by Ryan.Gerleve Fix memory leak in FRepChangelistState: added destructor that properly destroys the properties in the shadow state buffer. Change 3432955 on 2017/05/10 by John.Barrett Randomized the initial packet sequence numbers for UNetConnection's and for reliable packets - using the stateless handshake cookie. Also added hooks to determine when PacketHandler level handshaking has completed, so that the initial connection packets can be delayed until this stage (required now, in order to exchange the sequence numbers first). Change 3464528 on 2017/05/29 by John.Barrett Fixed connection failure during unreliable network conditions, caused by a bad interaction between the stateless handshake and sequence initialization code. Added a new 'ack' stage to the stateless handshake, to ensure the client/server sequence is properly synchronised. Expanded the timeout/retry handling for the stateless handshake, so it is more robust, and fixed some bugs in this code. Change 3464537 on 2017/05/29 by John.Barrett Fixed an incompatibility between the asymmetric encryption, and the new PacketHandler handshake code. Change 3464543 on 2017/05/29 by John.Barrett Updated CryptoPP to 5.6.5. Change 3467529 on 2017/05/31 by Jon.Nabozny Add comments to FPacketSimulationSettings vars. Change 3469584 on 2017/06/01 by Ryan.Gerleve Log bunch ChSequence on reliable channel open along with other info. Change 3471329 on 2017/06/02 by John.Barrett Fixed PacketHandlerLog type not being exported. Change 3471875 on 2017/06/02 by John.Barrett Fixed code that was trying to send NetConnection packets from the server to the client, too early - and tidied up related checks. #JIRA UE-45637 Change 3473030 on 2017/06/04 by John.Barrett Fixed replay incomaptibility with recent sequence/handshake changes. Change 3476313 on 2017/06/06 by Ryan.Gerleve Add initial reliable sequence numbers to the log in UNetConnection::InitSequence. Change 3478649 on 2017/06/07 by Ryan.Gerleve Add additional logging for the case where a channel open command is received by a channel that's already opened locally. Change 3482926 on 2017/06/09 by John.Barrett First pass at Minimal Client refactor for NetcodeUnitTest - split basic/minimal client code out of ClientUnitTest, into its own class - while preserving existing ClientUnitTest interface. This will allow multiple minimal clients per unit test, where only one could be used before (necessary for games that require a beacon + game connection). Added reflection support for weak UObject properties. Added MCP requirements flag for unit tests. Process pipe reading tweaks, to avoid UI freezes. Change 3485179 on 2017/06/12 by Ryan.Gerleve Add backwards-compatibility macros for random initial packet sequence changes so that game plugins can check them. Change 3489040 on 2017/06/14 by John.Barrett Removed OnlineSubsystem dependencies. [CL 3495525 by Ryan Gerleve in Main branch]
2017-06-16 14:10:35 -04:00
}
}
bool RSAKeyAESEncryptionHandlerComponent::IsValid() const
{
return AsymmetricKeyMaxPlaintextLength > 0;
}
void RSAKeyAESEncryptionHandlerComponent::SetState(ERSAKeyAESEncryptionHandler::State InState)
{
State = InState;
}
void RSAKeyAESEncryptionHandlerComponent::Outgoing(FBitWriter& Packet, FOutPacketTraits& Traits)
Copying //UE4/Dev-Networking to //UE4/Dev-Main (Source: //UE4/Dev-Networking @ 3495493) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3302759 on 2017/02/14 by John.Pollard Remove invalid replay samples that can occur due to oversampling (sampling at higher rate than physics is being ticked) Change 3306072 on 2017/02/16 by John.Barrett Minor NetcodeUnitTest updates/fixes. Improved assignment for some types, using FVMReflection - added assignment to enum by name. Change 3322165 on 2017/02/24 by John.Barrett Fixed issue where Steam would block unit tests. #JIRA UENET-537 Change 3323917 on 2017/02/27 by John.Barrett Added better unit test log file management. #JIRA UENET-535 Unit test logs are now stored in subfolders in the game log folder, with one main folder for the current UE4 session, and one subfolder for every unit test run during that session. Logs are purged occasionally, in line with how the main game logs are purged. Change 3326307 on 2017/02/28 by John.Pollard Remove unused cvar Change 3327907 on 2017/03/01 by John.Barrett Merged some old NetcodeUnitTest debug features: - Added command for bit-based log dumping of data (for debugging bit-based netcode) - Added exported function, for allowing access to console commands, in modules which don't import Engine Change 3332710 on 2017/03/05 by John.Barrett Updated unit test flags to expect a disconnect when expecting a server crash. Change 3332715 on 2017/03/05 by John.Barrett Wrapped all CreateChannelBunch pointers with a nullptr check (used to not be required). Replaced old/duplicate unit test code (using CreateChannelBunch) for marking 'exploit failure', with the current centralized function calls. #JIRA UENET-539 Change 3336258 on 2017/03/07 by John.Pollard Add more info to history overflow logging Change 3336259 on 2017/03/07 by John.Pollard Don't pause replication for replay connections Change 3341288 on 2017/03/10 by John.Barrett Fixed invalid access to GLog during game shutdown. #JIRA UE-42394 Change 3341736 on 2017/03/10 by John.Pollard Get reliability packet handler working again (but still disabled by default) Change 3349298 on 2017/03/16 by John.Barrett Fixed issues/potential-issues with the timing of global variable destruction, based on Graeme Thornton's fix. #JIRA UE-42394 Change 3349393 on 2017/03/16 by John.Pollard Reliability handler cleanup Change 3350029 on 2017/03/16 by John.Barrett Updated PacketHandler to support an optional handshaking stage for HandlerComponents, where each handshake must execute sequentially starting at the component closest to the socket. Change 3350030 on 2017/03/16 by John.Barrett Updated Asymetric Encryption to support updated PacketHandler system, to perform a key handshake that is compatible with other HandlerComponent's, and fixed some serialization security issues by setting proper limits on values. Change 3350032 on 2017/03/16 by John.Barrett Minor corrections to variable types and constructor initializer lists, for the rest of the encryption code. Change 3355536 on 2017/03/20 by John.Barrett Added new PacketAudit debug feature, which uses inter-process-communication, to audit the integrity of incoming/outgoing packets at various stages of serialization, between a client and server. This is critically useful for low level netcode development, particularly with the PacketHandler. See PacketAudit.h for more information. Change 3355570 on 2017/03/20 by John.Barrett Added a small number packet auditing checks to key areas of low level netcode. Change 3355584 on 2017/03/20 by John.Barrett Updated ReliabilityHandlerComponent, to support packet reliability during the PacketHandler handshaking stage, and fixed ReliabilityHandlerComponent serializing based on a packets byte size, rather than bit size. Change 3373389 on 2017/03/30 by John.Barrett Added check for HandlerComponent's that require reliability. Change 3373390 on 2017/03/30 by John.Barrett Added TLS-like encryption handler component, which exchanges a secret key using asymmetric encryption (RSA), and implements symmetric encryption using that key (AES). Based on RSA encryption component, and John Pollard's AES changes. Enable in *Engine.ini, using: [PacketHandlerComponents] Components=RSAKeyAESEncryption bEnableReliability=true Change 3394518 on 2017/04/14 by Ryan.Gerleve Fix memory leak in FRepChangelistState: added destructor that properly destroys the properties in the shadow state buffer. Change 3432955 on 2017/05/10 by John.Barrett Randomized the initial packet sequence numbers for UNetConnection's and for reliable packets - using the stateless handshake cookie. Also added hooks to determine when PacketHandler level handshaking has completed, so that the initial connection packets can be delayed until this stage (required now, in order to exchange the sequence numbers first). Change 3464528 on 2017/05/29 by John.Barrett Fixed connection failure during unreliable network conditions, caused by a bad interaction between the stateless handshake and sequence initialization code. Added a new 'ack' stage to the stateless handshake, to ensure the client/server sequence is properly synchronised. Expanded the timeout/retry handling for the stateless handshake, so it is more robust, and fixed some bugs in this code. Change 3464537 on 2017/05/29 by John.Barrett Fixed an incompatibility between the asymmetric encryption, and the new PacketHandler handshake code. Change 3464543 on 2017/05/29 by John.Barrett Updated CryptoPP to 5.6.5. Change 3467529 on 2017/05/31 by Jon.Nabozny Add comments to FPacketSimulationSettings vars. Change 3469584 on 2017/06/01 by Ryan.Gerleve Log bunch ChSequence on reliable channel open along with other info. Change 3471329 on 2017/06/02 by John.Barrett Fixed PacketHandlerLog type not being exported. Change 3471875 on 2017/06/02 by John.Barrett Fixed code that was trying to send NetConnection packets from the server to the client, too early - and tidied up related checks. #JIRA UE-45637 Change 3473030 on 2017/06/04 by John.Barrett Fixed replay incomaptibility with recent sequence/handshake changes. Change 3476313 on 2017/06/06 by Ryan.Gerleve Add initial reliable sequence numbers to the log in UNetConnection::InitSequence. Change 3478649 on 2017/06/07 by Ryan.Gerleve Add additional logging for the case where a channel open command is received by a channel that's already opened locally. Change 3482926 on 2017/06/09 by John.Barrett First pass at Minimal Client refactor for NetcodeUnitTest - split basic/minimal client code out of ClientUnitTest, into its own class - while preserving existing ClientUnitTest interface. This will allow multiple minimal clients per unit test, where only one could be used before (necessary for games that require a beacon + game connection). Added reflection support for weak UObject properties. Added MCP requirements flag for unit tests. Process pipe reading tweaks, to avoid UI freezes. Change 3485179 on 2017/06/12 by Ryan.Gerleve Add backwards-compatibility macros for random initial packet sequence changes so that game plugins can check them. Change 3489040 on 2017/06/14 by John.Barrett Removed OnlineSubsystem dependencies. [CL 3495525 by Ryan Gerleve in Main branch]
2017-06-16 14:10:35 -04:00
{
if (State == ERSAKeyAESEncryptionHandler::State::Initialized)
{
int32 PacketNumBytes = Packet.GetNumBytes();
if (PacketNumBytes > 0)
{
// Pad along 16 byte boundary, in order to encrypt properly
// @todo: Review the 16 byte boundary requirement
uint32 NumberOfBitsInPlaintext = Packet.GetNumBits();
int32 PaddedSize = (PacketNumBytes + 15) / 16 * 16;
TArray<uint8> PaddedPlainText;
TArray<uint8> CipherText;
PaddedPlainText.AddUninitialized(PaddedSize);
CipherText.AddUninitialized(PaddedSize);
FMemory::Memcpy(PaddedPlainText.GetData(), Packet.GetData(), PacketNumBytes);
if (PaddedSize > PacketNumBytes)
{
FMemory::Memzero(PaddedPlainText.GetData() + PacketNumBytes, (PaddedSize - PacketNumBytes));
}
SymmetricEncrypt.ProcessData(CipherText.GetData(), PaddedPlainText.GetData(), PaddedSize);
// @todo: Optimize this.
Packet.Reset();
NumberOfBitsInPlaintext--;
Packet.SerializeInt(NumberOfBitsInPlaintext, MAX_COMPRESSED_PACKET_SIZE);
Packet.Serialize(CipherText.GetData(), PaddedSize);
}
}
else
{
UE_LOG(PacketHandlerLog, Warning, TEXT("RSAEncryptionHandlerComponent: Got outgoing packet when not yet initialized."));
#if !UE_BUILD_SHIPPING
check(false);
#endif
Packet.SetError();
}
}
void RSAKeyAESEncryptionHandlerComponent::Incoming(FBitReader& Packet)
{
if (State == ERSAKeyAESEncryptionHandler::State::Initialized)
{
uint32 NumberOfBitsInPlaintext = 0;
Packet.SerializeInt(NumberOfBitsInPlaintext, MAX_COMPRESSED_PACKET_SIZE);
NumberOfBitsInPlaintext++;
if (!Packet.IsError())
{
if (NumberOfBitsInPlaintext <= MAX_COMPRESSED_PACKET_SIZE)
{
int32 NumberOfBytesInPlaintext = (NumberOfBitsInPlaintext + 7) >> 3;
int32 PaddedSize = (NumberOfBytesInPlaintext + 15) / 16 * 16;
TArray<uint8> CipherText;
TArray<uint8> PlainText;
CipherText.AddUninitialized(PaddedSize);
PlainText.AddUninitialized(PaddedSize);
Packet.Serialize(CipherText.GetData(), PaddedSize);
if (!Packet.IsError())
{
SymmetricDecrypt.ProcessData(PlainText.GetData(), CipherText.GetData(), PaddedSize);
// @todo: Could do with optimization
FBitReader Copy(PlainText.GetData(), NumberOfBitsInPlaintext);
Packet = Copy;
}
else
{
UE_LOG(PacketHandlerLog, Error, TEXT("AES: Error serializing PlainText."));
#if !UE_BUILD_SHIPPING
check(false);
#endif
}
}
else
{
Packet.SetError();
UE_LOG(PacketHandlerLog, Error, TEXT("AES: Specified PlainText size exceeds MAX_COMPRESSED_PACKET_SIZE."));
#if !UE_BUILD_SHIPPING
check(false);
#endif
}
}
else
{
UE_LOG(PacketHandlerLog, Error, TEXT("AES: Error serializing incoming packet."));
#if !UE_BUILD_SHIPPING
check(false);
#endif
}
}
else
{
IncomingHandshake(Packet);
}
}
void RSAKeyAESEncryptionHandlerComponent::IncomingHandshake(FBitReader& Packet)
{
bool bHandledPacket = true;
if (Handler->Mode == Handler::Mode::Server)
{
if (State == ERSAKeyAESEncryptionHandler::State::SentKey)
{
FPacketAudit::CheckStage(TEXT("SessionKeyExchangeEncrypt"), Packet);
AsymmetricDecryptPacket(Packet);
FPacketAudit::CheckStage(TEXT("SessionKeyExchangeDecrypt"), Packet);
uint32 KeySizeBytes = SessionKeySize / 8;
TArray<uint8> InitializationVector;
InitializationVector.SetNumUninitialized(AES_BLOCK_SIZE);
SessionKey.SetNumUninitialized(KeySizeBytes);
Packet.Serialize(InitializationVector.GetData(), AES_BLOCK_SIZE);
Packet.Serialize(SessionKey.GetData(), KeySizeBytes);
if (!Packet.IsError())
{
SymmetricEncrypt.SetKeyWithIV(SessionKey.GetData(), KeySizeBytes, InitializationVector.GetData(), AES_BLOCK_SIZE);
SymmetricDecrypt.SetKeyWithIV(SessionKey.GetData(), KeySizeBytes, InitializationVector.GetData(), AES_BLOCK_SIZE);
// Now mark as initialized
SetState(ERSAKeyAESEncryptionHandler::State::Initialized);
Initialized();
}
else
{
UE_LOG(PacketHandlerLog, Error, TEXT("RSA: Failed to initialize symmetric encryption."));
#if !UE_BUILD_SHIPPING
check(false);
#endif
}
}
else
{
bHandledPacket = false;
}
}
else if (Handler->Mode == Handler::Mode::Client)
{
if (State == ERSAKeyAESEncryptionHandler::State::UnInitialized)
{
FPacketAudit::CheckStage(TEXT("RSAHandshake"), Packet);
UnPackAsymmetricKey(Packet);
// Generate/send the session key and initialization vector, and setup the symmetric encryption locally
if (!Packet.IsError())
{
check(AES_BLOCK_SIZE == CryptoPP::AES::BLOCKSIZE);
check((SessionKeySize % 8) == 0);
CryptoPP::AutoSeededRandomPool SessionRng;
TArray<uint8> InitializationVector;
uint32 KeySizeBytes = SessionKeySize / 8;
SessionKey.SetNumUninitialized(KeySizeBytes);
InitializationVector.SetNumUninitialized(AES_BLOCK_SIZE);
SessionRng.GenerateBlock(SessionKey.GetData(), KeySizeBytes);
SessionRng.GenerateBlock(InitializationVector.GetData(), AES_BLOCK_SIZE);
SymmetricEncrypt.SetKeyWithIV(SessionKey.GetData(), KeySizeBytes, InitializationVector.GetData(), AES_BLOCK_SIZE);
SymmetricDecrypt.SetKeyWithIV(SessionKey.GetData(), KeySizeBytes, InitializationVector.GetData(), AES_BLOCK_SIZE);
// Now send the initialization vector and session key
FBitWriter OutPacket((AES_BLOCK_SIZE + KeySizeBytes) * 8, true);
FOutPacketTraits Traits;
Copying //UE4/Dev-Networking to //UE4/Dev-Main (Source: //UE4/Dev-Networking @ 3495493) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3302759 on 2017/02/14 by John.Pollard Remove invalid replay samples that can occur due to oversampling (sampling at higher rate than physics is being ticked) Change 3306072 on 2017/02/16 by John.Barrett Minor NetcodeUnitTest updates/fixes. Improved assignment for some types, using FVMReflection - added assignment to enum by name. Change 3322165 on 2017/02/24 by John.Barrett Fixed issue where Steam would block unit tests. #JIRA UENET-537 Change 3323917 on 2017/02/27 by John.Barrett Added better unit test log file management. #JIRA UENET-535 Unit test logs are now stored in subfolders in the game log folder, with one main folder for the current UE4 session, and one subfolder for every unit test run during that session. Logs are purged occasionally, in line with how the main game logs are purged. Change 3326307 on 2017/02/28 by John.Pollard Remove unused cvar Change 3327907 on 2017/03/01 by John.Barrett Merged some old NetcodeUnitTest debug features: - Added command for bit-based log dumping of data (for debugging bit-based netcode) - Added exported function, for allowing access to console commands, in modules which don't import Engine Change 3332710 on 2017/03/05 by John.Barrett Updated unit test flags to expect a disconnect when expecting a server crash. Change 3332715 on 2017/03/05 by John.Barrett Wrapped all CreateChannelBunch pointers with a nullptr check (used to not be required). Replaced old/duplicate unit test code (using CreateChannelBunch) for marking 'exploit failure', with the current centralized function calls. #JIRA UENET-539 Change 3336258 on 2017/03/07 by John.Pollard Add more info to history overflow logging Change 3336259 on 2017/03/07 by John.Pollard Don't pause replication for replay connections Change 3341288 on 2017/03/10 by John.Barrett Fixed invalid access to GLog during game shutdown. #JIRA UE-42394 Change 3341736 on 2017/03/10 by John.Pollard Get reliability packet handler working again (but still disabled by default) Change 3349298 on 2017/03/16 by John.Barrett Fixed issues/potential-issues with the timing of global variable destruction, based on Graeme Thornton's fix. #JIRA UE-42394 Change 3349393 on 2017/03/16 by John.Pollard Reliability handler cleanup Change 3350029 on 2017/03/16 by John.Barrett Updated PacketHandler to support an optional handshaking stage for HandlerComponents, where each handshake must execute sequentially starting at the component closest to the socket. Change 3350030 on 2017/03/16 by John.Barrett Updated Asymetric Encryption to support updated PacketHandler system, to perform a key handshake that is compatible with other HandlerComponent's, and fixed some serialization security issues by setting proper limits on values. Change 3350032 on 2017/03/16 by John.Barrett Minor corrections to variable types and constructor initializer lists, for the rest of the encryption code. Change 3355536 on 2017/03/20 by John.Barrett Added new PacketAudit debug feature, which uses inter-process-communication, to audit the integrity of incoming/outgoing packets at various stages of serialization, between a client and server. This is critically useful for low level netcode development, particularly with the PacketHandler. See PacketAudit.h for more information. Change 3355570 on 2017/03/20 by John.Barrett Added a small number packet auditing checks to key areas of low level netcode. Change 3355584 on 2017/03/20 by John.Barrett Updated ReliabilityHandlerComponent, to support packet reliability during the PacketHandler handshaking stage, and fixed ReliabilityHandlerComponent serializing based on a packets byte size, rather than bit size. Change 3373389 on 2017/03/30 by John.Barrett Added check for HandlerComponent's that require reliability. Change 3373390 on 2017/03/30 by John.Barrett Added TLS-like encryption handler component, which exchanges a secret key using asymmetric encryption (RSA), and implements symmetric encryption using that key (AES). Based on RSA encryption component, and John Pollard's AES changes. Enable in *Engine.ini, using: [PacketHandlerComponents] Components=RSAKeyAESEncryption bEnableReliability=true Change 3394518 on 2017/04/14 by Ryan.Gerleve Fix memory leak in FRepChangelistState: added destructor that properly destroys the properties in the shadow state buffer. Change 3432955 on 2017/05/10 by John.Barrett Randomized the initial packet sequence numbers for UNetConnection's and for reliable packets - using the stateless handshake cookie. Also added hooks to determine when PacketHandler level handshaking has completed, so that the initial connection packets can be delayed until this stage (required now, in order to exchange the sequence numbers first). Change 3464528 on 2017/05/29 by John.Barrett Fixed connection failure during unreliable network conditions, caused by a bad interaction between the stateless handshake and sequence initialization code. Added a new 'ack' stage to the stateless handshake, to ensure the client/server sequence is properly synchronised. Expanded the timeout/retry handling for the stateless handshake, so it is more robust, and fixed some bugs in this code. Change 3464537 on 2017/05/29 by John.Barrett Fixed an incompatibility between the asymmetric encryption, and the new PacketHandler handshake code. Change 3464543 on 2017/05/29 by John.Barrett Updated CryptoPP to 5.6.5. Change 3467529 on 2017/05/31 by Jon.Nabozny Add comments to FPacketSimulationSettings vars. Change 3469584 on 2017/06/01 by Ryan.Gerleve Log bunch ChSequence on reliable channel open along with other info. Change 3471329 on 2017/06/02 by John.Barrett Fixed PacketHandlerLog type not being exported. Change 3471875 on 2017/06/02 by John.Barrett Fixed code that was trying to send NetConnection packets from the server to the client, too early - and tidied up related checks. #JIRA UE-45637 Change 3473030 on 2017/06/04 by John.Barrett Fixed replay incomaptibility with recent sequence/handshake changes. Change 3476313 on 2017/06/06 by Ryan.Gerleve Add initial reliable sequence numbers to the log in UNetConnection::InitSequence. Change 3478649 on 2017/06/07 by Ryan.Gerleve Add additional logging for the case where a channel open command is received by a channel that's already opened locally. Change 3482926 on 2017/06/09 by John.Barrett First pass at Minimal Client refactor for NetcodeUnitTest - split basic/minimal client code out of ClientUnitTest, into its own class - while preserving existing ClientUnitTest interface. This will allow multiple minimal clients per unit test, where only one could be used before (necessary for games that require a beacon + game connection). Added reflection support for weak UObject properties. Added MCP requirements flag for unit tests. Process pipe reading tweaks, to avoid UI freezes. Change 3485179 on 2017/06/12 by Ryan.Gerleve Add backwards-compatibility macros for random initial packet sequence changes so that game plugins can check them. Change 3489040 on 2017/06/14 by John.Barrett Removed OnlineSubsystem dependencies. [CL 3495525 by Ryan Gerleve in Main branch]
2017-06-16 14:10:35 -04:00
OutPacket.Serialize(InitializationVector.GetData(), AES_BLOCK_SIZE);
OutPacket.Serialize(SessionKey.GetData(), KeySizeBytes);
FPacketAudit::AddStage(TEXT("SessionKeyExchangeDecrypt"), OutPacket);
AsymmetricEncryptPacket(OutPacket);
FPacketAudit::AddStage(TEXT("SessionKeyExchangeEncrypt"), OutPacket);
Handler->SendHandlerPacket(this, OutPacket, Traits);
Copying //UE4/Dev-Networking to //UE4/Dev-Main (Source: //UE4/Dev-Networking @ 3495493) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3302759 on 2017/02/14 by John.Pollard Remove invalid replay samples that can occur due to oversampling (sampling at higher rate than physics is being ticked) Change 3306072 on 2017/02/16 by John.Barrett Minor NetcodeUnitTest updates/fixes. Improved assignment for some types, using FVMReflection - added assignment to enum by name. Change 3322165 on 2017/02/24 by John.Barrett Fixed issue where Steam would block unit tests. #JIRA UENET-537 Change 3323917 on 2017/02/27 by John.Barrett Added better unit test log file management. #JIRA UENET-535 Unit test logs are now stored in subfolders in the game log folder, with one main folder for the current UE4 session, and one subfolder for every unit test run during that session. Logs are purged occasionally, in line with how the main game logs are purged. Change 3326307 on 2017/02/28 by John.Pollard Remove unused cvar Change 3327907 on 2017/03/01 by John.Barrett Merged some old NetcodeUnitTest debug features: - Added command for bit-based log dumping of data (for debugging bit-based netcode) - Added exported function, for allowing access to console commands, in modules which don't import Engine Change 3332710 on 2017/03/05 by John.Barrett Updated unit test flags to expect a disconnect when expecting a server crash. Change 3332715 on 2017/03/05 by John.Barrett Wrapped all CreateChannelBunch pointers with a nullptr check (used to not be required). Replaced old/duplicate unit test code (using CreateChannelBunch) for marking 'exploit failure', with the current centralized function calls. #JIRA UENET-539 Change 3336258 on 2017/03/07 by John.Pollard Add more info to history overflow logging Change 3336259 on 2017/03/07 by John.Pollard Don't pause replication for replay connections Change 3341288 on 2017/03/10 by John.Barrett Fixed invalid access to GLog during game shutdown. #JIRA UE-42394 Change 3341736 on 2017/03/10 by John.Pollard Get reliability packet handler working again (but still disabled by default) Change 3349298 on 2017/03/16 by John.Barrett Fixed issues/potential-issues with the timing of global variable destruction, based on Graeme Thornton's fix. #JIRA UE-42394 Change 3349393 on 2017/03/16 by John.Pollard Reliability handler cleanup Change 3350029 on 2017/03/16 by John.Barrett Updated PacketHandler to support an optional handshaking stage for HandlerComponents, where each handshake must execute sequentially starting at the component closest to the socket. Change 3350030 on 2017/03/16 by John.Barrett Updated Asymetric Encryption to support updated PacketHandler system, to perform a key handshake that is compatible with other HandlerComponent's, and fixed some serialization security issues by setting proper limits on values. Change 3350032 on 2017/03/16 by John.Barrett Minor corrections to variable types and constructor initializer lists, for the rest of the encryption code. Change 3355536 on 2017/03/20 by John.Barrett Added new PacketAudit debug feature, which uses inter-process-communication, to audit the integrity of incoming/outgoing packets at various stages of serialization, between a client and server. This is critically useful for low level netcode development, particularly with the PacketHandler. See PacketAudit.h for more information. Change 3355570 on 2017/03/20 by John.Barrett Added a small number packet auditing checks to key areas of low level netcode. Change 3355584 on 2017/03/20 by John.Barrett Updated ReliabilityHandlerComponent, to support packet reliability during the PacketHandler handshaking stage, and fixed ReliabilityHandlerComponent serializing based on a packets byte size, rather than bit size. Change 3373389 on 2017/03/30 by John.Barrett Added check for HandlerComponent's that require reliability. Change 3373390 on 2017/03/30 by John.Barrett Added TLS-like encryption handler component, which exchanges a secret key using asymmetric encryption (RSA), and implements symmetric encryption using that key (AES). Based on RSA encryption component, and John Pollard's AES changes. Enable in *Engine.ini, using: [PacketHandlerComponents] Components=RSAKeyAESEncryption bEnableReliability=true Change 3394518 on 2017/04/14 by Ryan.Gerleve Fix memory leak in FRepChangelistState: added destructor that properly destroys the properties in the shadow state buffer. Change 3432955 on 2017/05/10 by John.Barrett Randomized the initial packet sequence numbers for UNetConnection's and for reliable packets - using the stateless handshake cookie. Also added hooks to determine when PacketHandler level handshaking has completed, so that the initial connection packets can be delayed until this stage (required now, in order to exchange the sequence numbers first). Change 3464528 on 2017/05/29 by John.Barrett Fixed connection failure during unreliable network conditions, caused by a bad interaction between the stateless handshake and sequence initialization code. Added a new 'ack' stage to the stateless handshake, to ensure the client/server sequence is properly synchronised. Expanded the timeout/retry handling for the stateless handshake, so it is more robust, and fixed some bugs in this code. Change 3464537 on 2017/05/29 by John.Barrett Fixed an incompatibility between the asymmetric encryption, and the new PacketHandler handshake code. Change 3464543 on 2017/05/29 by John.Barrett Updated CryptoPP to 5.6.5. Change 3467529 on 2017/05/31 by Jon.Nabozny Add comments to FPacketSimulationSettings vars. Change 3469584 on 2017/06/01 by Ryan.Gerleve Log bunch ChSequence on reliable channel open along with other info. Change 3471329 on 2017/06/02 by John.Barrett Fixed PacketHandlerLog type not being exported. Change 3471875 on 2017/06/02 by John.Barrett Fixed code that was trying to send NetConnection packets from the server to the client, too early - and tidied up related checks. #JIRA UE-45637 Change 3473030 on 2017/06/04 by John.Barrett Fixed replay incomaptibility with recent sequence/handshake changes. Change 3476313 on 2017/06/06 by Ryan.Gerleve Add initial reliable sequence numbers to the log in UNetConnection::InitSequence. Change 3478649 on 2017/06/07 by Ryan.Gerleve Add additional logging for the case where a channel open command is received by a channel that's already opened locally. Change 3482926 on 2017/06/09 by John.Barrett First pass at Minimal Client refactor for NetcodeUnitTest - split basic/minimal client code out of ClientUnitTest, into its own class - while preserving existing ClientUnitTest interface. This will allow multiple minimal clients per unit test, where only one could be used before (necessary for games that require a beacon + game connection). Added reflection support for weak UObject properties. Added MCP requirements flag for unit tests. Process pipe reading tweaks, to avoid UI freezes. Change 3485179 on 2017/06/12 by Ryan.Gerleve Add backwards-compatibility macros for random initial packet sequence changes so that game plugins can check them. Change 3489040 on 2017/06/14 by John.Barrett Removed OnlineSubsystem dependencies. [CL 3495525 by Ryan Gerleve in Main branch]
2017-06-16 14:10:35 -04:00
// Now mark as initialized
SetState(ERSAKeyAESEncryptionHandler::State::Initialized);
Initialized();
}
else
{
UE_LOG(PacketHandlerLog, Error, TEXT("RSA: Error unpacking the asymmetric key, can't complete handshake."));
#if !UE_BUILD_SHIPPING
check(false);
#endif
}
}
else
{
bHandledPacket = false;
}
}
if (!bHandledPacket)
{
UE_LOG(PacketHandlerLog, Warning, TEXT("RSAEncryptionHandlerComponent: Got incoming packet when not yet initialized."));
#if !UE_BUILD_SHIPPING
check(false);
#endif
Packet.SetError();
}
}
int32 RSAKeyAESEncryptionHandlerComponent::GetReservedPacketBits() const
Copying //UE4/Dev-Networking to //UE4/Dev-Main (Source: //UE4/Dev-Networking @ 3495493) #lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3302759 on 2017/02/14 by John.Pollard Remove invalid replay samples that can occur due to oversampling (sampling at higher rate than physics is being ticked) Change 3306072 on 2017/02/16 by John.Barrett Minor NetcodeUnitTest updates/fixes. Improved assignment for some types, using FVMReflection - added assignment to enum by name. Change 3322165 on 2017/02/24 by John.Barrett Fixed issue where Steam would block unit tests. #JIRA UENET-537 Change 3323917 on 2017/02/27 by John.Barrett Added better unit test log file management. #JIRA UENET-535 Unit test logs are now stored in subfolders in the game log folder, with one main folder for the current UE4 session, and one subfolder for every unit test run during that session. Logs are purged occasionally, in line with how the main game logs are purged. Change 3326307 on 2017/02/28 by John.Pollard Remove unused cvar Change 3327907 on 2017/03/01 by John.Barrett Merged some old NetcodeUnitTest debug features: - Added command for bit-based log dumping of data (for debugging bit-based netcode) - Added exported function, for allowing access to console commands, in modules which don't import Engine Change 3332710 on 2017/03/05 by John.Barrett Updated unit test flags to expect a disconnect when expecting a server crash. Change 3332715 on 2017/03/05 by John.Barrett Wrapped all CreateChannelBunch pointers with a nullptr check (used to not be required). Replaced old/duplicate unit test code (using CreateChannelBunch) for marking 'exploit failure', with the current centralized function calls. #JIRA UENET-539 Change 3336258 on 2017/03/07 by John.Pollard Add more info to history overflow logging Change 3336259 on 2017/03/07 by John.Pollard Don't pause replication for replay connections Change 3341288 on 2017/03/10 by John.Barrett Fixed invalid access to GLog during game shutdown. #JIRA UE-42394 Change 3341736 on 2017/03/10 by John.Pollard Get reliability packet handler working again (but still disabled by default) Change 3349298 on 2017/03/16 by John.Barrett Fixed issues/potential-issues with the timing of global variable destruction, based on Graeme Thornton's fix. #JIRA UE-42394 Change 3349393 on 2017/03/16 by John.Pollard Reliability handler cleanup Change 3350029 on 2017/03/16 by John.Barrett Updated PacketHandler to support an optional handshaking stage for HandlerComponents, where each handshake must execute sequentially starting at the component closest to the socket. Change 3350030 on 2017/03/16 by John.Barrett Updated Asymetric Encryption to support updated PacketHandler system, to perform a key handshake that is compatible with other HandlerComponent's, and fixed some serialization security issues by setting proper limits on values. Change 3350032 on 2017/03/16 by John.Barrett Minor corrections to variable types and constructor initializer lists, for the rest of the encryption code. Change 3355536 on 2017/03/20 by John.Barrett Added new PacketAudit debug feature, which uses inter-process-communication, to audit the integrity of incoming/outgoing packets at various stages of serialization, between a client and server. This is critically useful for low level netcode development, particularly with the PacketHandler. See PacketAudit.h for more information. Change 3355570 on 2017/03/20 by John.Barrett Added a small number packet auditing checks to key areas of low level netcode. Change 3355584 on 2017/03/20 by John.Barrett Updated ReliabilityHandlerComponent, to support packet reliability during the PacketHandler handshaking stage, and fixed ReliabilityHandlerComponent serializing based on a packets byte size, rather than bit size. Change 3373389 on 2017/03/30 by John.Barrett Added check for HandlerComponent's that require reliability. Change 3373390 on 2017/03/30 by John.Barrett Added TLS-like encryption handler component, which exchanges a secret key using asymmetric encryption (RSA), and implements symmetric encryption using that key (AES). Based on RSA encryption component, and John Pollard's AES changes. Enable in *Engine.ini, using: [PacketHandlerComponents] Components=RSAKeyAESEncryption bEnableReliability=true Change 3394518 on 2017/04/14 by Ryan.Gerleve Fix memory leak in FRepChangelistState: added destructor that properly destroys the properties in the shadow state buffer. Change 3432955 on 2017/05/10 by John.Barrett Randomized the initial packet sequence numbers for UNetConnection's and for reliable packets - using the stateless handshake cookie. Also added hooks to determine when PacketHandler level handshaking has completed, so that the initial connection packets can be delayed until this stage (required now, in order to exchange the sequence numbers first). Change 3464528 on 2017/05/29 by John.Barrett Fixed connection failure during unreliable network conditions, caused by a bad interaction between the stateless handshake and sequence initialization code. Added a new 'ack' stage to the stateless handshake, to ensure the client/server sequence is properly synchronised. Expanded the timeout/retry handling for the stateless handshake, so it is more robust, and fixed some bugs in this code. Change 3464537 on 2017/05/29 by John.Barrett Fixed an incompatibility between the asymmetric encryption, and the new PacketHandler handshake code. Change 3464543 on 2017/05/29 by John.Barrett Updated CryptoPP to 5.6.5. Change 3467529 on 2017/05/31 by Jon.Nabozny Add comments to FPacketSimulationSettings vars. Change 3469584 on 2017/06/01 by Ryan.Gerleve Log bunch ChSequence on reliable channel open along with other info. Change 3471329 on 2017/06/02 by John.Barrett Fixed PacketHandlerLog type not being exported. Change 3471875 on 2017/06/02 by John.Barrett Fixed code that was trying to send NetConnection packets from the server to the client, too early - and tidied up related checks. #JIRA UE-45637 Change 3473030 on 2017/06/04 by John.Barrett Fixed replay incomaptibility with recent sequence/handshake changes. Change 3476313 on 2017/06/06 by Ryan.Gerleve Add initial reliable sequence numbers to the log in UNetConnection::InitSequence. Change 3478649 on 2017/06/07 by Ryan.Gerleve Add additional logging for the case where a channel open command is received by a channel that's already opened locally. Change 3482926 on 2017/06/09 by John.Barrett First pass at Minimal Client refactor for NetcodeUnitTest - split basic/minimal client code out of ClientUnitTest, into its own class - while preserving existing ClientUnitTest interface. This will allow multiple minimal clients per unit test, where only one could be used before (necessary for games that require a beacon + game connection). Added reflection support for weak UObject properties. Added MCP requirements flag for unit tests. Process pipe reading tweaks, to avoid UI freezes. Change 3485179 on 2017/06/12 by Ryan.Gerleve Add backwards-compatibility macros for random initial packet sequence changes so that game plugins can check them. Change 3489040 on 2017/06/14 by John.Barrett Removed OnlineSubsystem dependencies. [CL 3495525 by Ryan Gerleve in Main branch]
2017-06-16 14:10:35 -04:00
{
int32 ReturnVal = 0;
// Count the size of the value, representing the packet size in bits
FBitWriter MeasureAr(0, true);
uint32 TestVal = MAX_COMPRESSED_PACKET_SIZE - 1;
MeasureAr.SerializeInt(TestVal, MAX_COMPRESSED_PACKET_SIZE);
check(!MeasureAr.IsError());
ReturnVal += MeasureAr.GetNumBits();
// Count the worst case amount of padding that may be added to a packet
ReturnVal += (16 * 8) - 1;
return ReturnVal;
}
void RSAKeyAESEncryptionHandlerComponent::PackAsymmetricKey(FBitWriter& Packet)
{
FBitWriter Local;
Local.AllowAppend(true);
Local.SetAllowResize(true);
// Save remote public key information
TArray<uint8> ModulusArray;
TArray<uint8> ExponentArray;
SavePublicKeyModulus(ModulusArray);
SavePublicKeyExponent(ExponentArray);
if ((ModulusArray.Num() * 8u) > AsymmetricKeySize || ModulusArray.Num() == 0)
{
LowLevelFatalError(TEXT("Modulus size '%i bits' must be greater than zero, and must not exceed key size '%i'"),
(ModulusArray.Num() * 8), AsymmetricKeySize);
}
if ((ExponentArray.Num() * 8) > MAX_EXPONENT_BITS || ExponentArray.Num() == 0)
{
LowLevelFatalError(TEXT("Exponent size '%i bits' must be greater than zero, and must not exceed MAX_EXPONENT_BITS"),
(ExponentArray.Num() * 8));
}
const uint32 MaxModulusNum = (AsymmetricKeySize + 7) >> 3;
const uint32 MaxExponentNum = (MAX_EXPONENT_BITS + 7) >> 3;
// Decrement by one, to allow serialization of #Num == Max#Num
uint32 ModulusSerializeNum = ModulusArray.Num() - 1;
uint32 ExponentSerializeNum = ExponentArray.Num() - 1;
Local.SerializeInt(ModulusSerializeNum, MaxModulusNum);
Local.Serialize(ModulusArray.GetData(), ModulusArray.Num());
Local.SerializeInt(ExponentSerializeNum, MaxExponentNum);
Local.Serialize(ExponentArray.GetData(), ExponentArray.Num());
Local.Serialize(Packet.GetData(), Packet.GetNumBytes());
Packet = Local;
}
void RSAKeyAESEncryptionHandlerComponent::UnPackAsymmetricKey(FBitReader& Packet)
{
// Save remote public key
TArray<uint8> ModulusArray;
TArray<uint8> ExponentArray;
const uint32 MaxModulusNum = (AsymmetricKeySize + 7) >> 3;
const uint32 MaxExponentNum = (MAX_EXPONENT_BITS + 7) >> 3;
uint32 ModulusNum = 0;
Packet.SerializeInt(ModulusNum, MaxModulusNum);
ModulusNum++;
if ((ModulusNum * 8) > AsymmetricKeySize)
{
UE_LOG(PacketHandlerLog, Warning, TEXT("RSA: Modulus size '%i bits' should not exceed key size '%i'"),
(ModulusNum * 8), AsymmetricKeySize);
Packet.SetError();
}
if (!Packet.IsError())
{
uint32 ExponentNum = 0;
ModulusArray.SetNumUninitialized(ModulusNum);
Packet.Serialize(ModulusArray.GetData(), ModulusNum);
Packet.SerializeInt(ExponentNum, MaxExponentNum);
if (!Packet.IsError())
{
ExponentNum++;
if ((ExponentNum * 8) <= MAX_EXPONENT_BITS)
{
ExponentArray.SetNumUninitialized(ExponentNum);
Packet.Serialize(ExponentArray.GetData(), ExponentNum);
}
else
{
UE_LOG(PacketHandlerLog, Warning, TEXT("RSA: Exponent size '%i bits' should not exceed MAX_EXPONENT_BITS"),
(ExponentNum * 8));
Packet.SetError();
}
}
}
if (!Packet.IsError())
{
// Make sure the packet has no remaining data now
#if !UE_BUILD_SHIPPING
check(Packet.GetBitsLeft() == 0);
#endif
CryptoPP::Integer Modulus;
CryptoPP::Integer Exponent;
for (int32 i = 0; i < ModulusArray.Num(); ++i)
{
Modulus.SetByte(i, ModulusArray[i]);
}
for (int32 i = 0; i < ExponentArray.Num(); ++i)
{
Exponent.SetByte(i, ExponentArray[i]);
}
PublicKey.SetModulus(Modulus);
PublicKey.SetPublicExponent(Exponent);
AsymmetricEncrypt = CryptoPP::RSAES_OAEP_SHA_Encryptor(PublicKey);
AsymmetricKeyMaxPlaintextLength = static_cast<uint32>(AsymmetricEncrypt.FixedMaxPlaintextLength());
AsymmetricKeyFixedCiphertextLength = static_cast<uint32>(AsymmetricEncrypt.FixedCiphertextLength());
}
}
void RSAKeyAESEncryptionHandlerComponent::AsymmetricEncryptPacket(FBitWriter& Packet)
{
// Serialize size of plain text data
uint32 NumberOfBytesInPlaintext = static_cast<uint32>(Packet.GetNumBytes());
TArray<uint8> PlainText;
PlainText.AddUninitialized(NumberOfBytesInPlaintext);
FMemory::Memcpy(PlainText.GetData(), Packet.GetData(), NumberOfBytesInPlaintext);
Packet.Reset();
if (NumberOfBytesInPlaintext == 0 || NumberOfBytesInPlaintext > AsymmetricKeyMaxPlaintextLength)
{
UE_LOG(PacketHandlerLog, Warning, TEXT("RSA: Encryption failed due to invalid plain text size '%i/%i'."),
NumberOfBytesInPlaintext, AsymmetricKeyMaxPlaintextLength);
Packet.SetError();
#if !UE_BUILD_SHIPPING
check(false);
#endif
return;
}
TArray<uint8> CipherText;
CipherText.SetNumUninitialized(AsymmetricKeyFixedCiphertextLength);
AsymmetricEncrypt.Encrypt(AsymmetricRng, PlainText.GetData(), PlainText.Num(), CipherText.GetData());
NumberOfBytesInPlaintext--;
Packet.SerializeInt(NumberOfBytesInPlaintext, AsymmetricKeyMaxPlaintextLength);
Packet.Serialize(CipherText.GetData(), CipherText.Num());
}
void RSAKeyAESEncryptionHandlerComponent::AsymmetricDecryptPacket(FBitReader& Packet)
{
// Serialize size of plain text data
uint32 NumberOfBytesInPlaintext;
Packet.SerializeInt(NumberOfBytesInPlaintext, AsymmetricKeyMaxPlaintextLength);
NumberOfBytesInPlaintext++;
if (NumberOfBytesInPlaintext == 0 || NumberOfBytesInPlaintext > AsymmetricKeyMaxPlaintextLength)
{
UE_LOG(PacketHandlerLog, Warning, TEXT("RSA: Decryption failed due to invalid cipher text size '%i/%i'."),
NumberOfBytesInPlaintext, AsymmetricKeyMaxPlaintextLength);
Packet.SetError();
#if !UE_BUILD_SHIPPING
check(false);
#endif
}
// Copy byte stream to PlainText from Packet; not including the NumOfBytesPT field
if (!Packet.IsError())
{
// @todo #JohnB: This is not bit-safe (but should not matter, since this code is only used during handshake, but still...)
TArray<uint8> PlainText;
int32 StartPos = Packet.GetPosBits() / 8;
PlainText.SetNumUninitialized(AsymmetricKeyMaxPlaintextLength);
AsymmetricDecrypt.Decrypt(AsymmetricRng, (Packet.GetData() + StartPos), (Packet.GetNumBytes() - StartPos), PlainText.GetData());
// @todo #JohnB: Optimize this
FBitReader Copy(PlainText.GetData(), NumberOfBytesInPlaintext * 8);
Packet = Copy;
}
}
void RSAKeyAESEncryptionHandlerComponent::SavePublicKeyModulus(TArray<uint8>& OutModulus)
{
uint32 ModulusSize = static_cast<uint32>(PublicKey.GetModulus().ByteCount());
CryptoPP::Integer Modulus = PublicKey.GetModulus();
for (uint32 i = 0; i < ModulusSize; ++i)
{
OutModulus.Add(Modulus.GetByte(i));
}
}
void RSAKeyAESEncryptionHandlerComponent::SavePublicKeyExponent(TArray<uint8>& OutExponent)
{
uint32 ExponentSize = static_cast<uint32>(PublicKey.GetPublicExponent().ByteCount());
CryptoPP::Integer Exponent = PublicKey.GetPublicExponent();
for (uint32 i = 0; i < ExponentSize; ++i)
{
OutExponent.Add(Exponent.GetByte(i));
}
}
// MODULE INTERFACE
TSharedPtr<HandlerComponent> FRSAKeyAESEncryptionModuleInterface::CreateComponentInstance(FString& Options)
{
return MakeShareable(new RSAKeyAESEncryptionHandlerComponent());
}