OpenSSL implementation
This commit is contained in:
parent
df5fd8b05b
commit
f1988072a4
8 changed files with 74 additions and 119 deletions
|
@ -14,6 +14,10 @@ void FSkyPortalModule::ShutdownModule()
|
||||||
{
|
{
|
||||||
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
|
||||||
// we call this function before unloading the module.
|
// we call this function before unloading the module.
|
||||||
|
|
||||||
|
if (GEngine->GetEngineSubsystem<USkyPortalSubsystem>()) {
|
||||||
|
GEngine->GetEngineSubsystem<USkyPortalSubsystem>()->Deinitialize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef LOCTEXT_NAMESPACE
|
#undef LOCTEXT_NAMESPACE
|
||||||
|
|
|
@ -9,7 +9,7 @@ uint32 FigureData::GetFigureID()
|
||||||
int16_t OutFigureID = 0;
|
int16_t OutFigureID = 0;
|
||||||
|
|
||||||
// The figure ID is stored in Block 1 of Sector 0 (i.e., data[1]), bytes 0 and 1 (16-bit integer, little-endian)
|
// The figure ID is stored in Block 1 of Sector 0 (i.e., data[1]), bytes 0 and 1 (16-bit integer, little-endian)
|
||||||
OutFigureID = data[1][0] | // Least significant byte
|
OutFigureID = decryptedData[1][0] | // Least significant byte
|
||||||
(data[1][1] << 8); // Most significant byte, shifted left by 8 bits
|
(data[1][1] << 8); // Most significant byte, shifted left by 8 bits
|
||||||
|
|
||||||
ID = OutFigureID;// Return the 16-bit figure ID
|
ID = OutFigureID;// Return the 16-bit figure ID
|
||||||
|
@ -25,64 +25,6 @@ uint32 FigureData::GetFigureID()
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
void FigureData::ReadData(uint8 index)
|
|
||||||
{
|
|
||||||
ClearData();
|
|
||||||
for (uint8 i = 0; i < 64; i++)
|
|
||||||
{
|
|
||||||
GEngine->GetEngineSubsystem<USkyPortalSubsystem>();
|
|
||||||
TArray<uint8> output = SkySubsystem->QueryBlock(index, i);
|
|
||||||
|
|
||||||
uint8[] blockData = new uint8[0x10];
|
|
||||||
Array.Copy(output, 3, blockData, 0, 16);
|
|
||||||
|
|
||||||
// block 1 is sometimes a duplicate of block 0
|
|
||||||
if (i == 1)
|
|
||||||
{
|
|
||||||
if (blockData.SequenceEqual(data[0]))
|
|
||||||
{
|
|
||||||
i -= 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Array.Copy(blockData, 0, data[i], 0, 16);
|
|
||||||
|
|
||||||
if (((i + 1) % 4 == 0) || i < 8)
|
|
||||||
{
|
|
||||||
Array.Copy(data[i], 0, decryptedData[i], 0, 16);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8[] hashIn = new byte[0x56];
|
|
||||||
data[0].CopyTo(hashIn, 0);
|
|
||||||
data[1].CopyTo(hashIn, 0x10);
|
|
||||||
hashIn[0x20] = i;
|
|
||||||
HASH_CONST.CopyTo(hashIn, 0x21);
|
|
||||||
|
|
||||||
uint8[] key = MD5.Create().ComputeHash(hashIn);
|
|
||||||
|
|
||||||
uint8[] decrypted = new byte[0x10];
|
|
||||||
|
|
||||||
using (Aes aesAlg = Aes.Create())
|
|
||||||
{
|
|
||||||
aesAlg.Key = key;
|
|
||||||
aesAlg.Mode = CipherMode.ECB;
|
|
||||||
aesAlg.Padding = PaddingMode.Zeros;
|
|
||||||
|
|
||||||
ICryptoTransform decryptor = aesAlg.CreateDecryptor();
|
|
||||||
|
|
||||||
decrypted = decryptor.TransformFinalBlock(data[i], 0, data[i].Length);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Array.Copy(decrypted, 0, decryptedData[i], 0, 16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void FigureData::ClearData()
|
void FigureData::ClearData()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#include "SkyPortalIO.h"
|
#include "SkyPortalIO.h"
|
||||||
#include "Misc/AES.h"
|
#include "Misc/AES.h"
|
||||||
#include "Misc/ArchiveMD5.h"
|
|
||||||
#include "Misc/ScopeLock.h"
|
|
||||||
#include "HAL/UnrealMemory.h"
|
#include "HAL/UnrealMemory.h"
|
||||||
|
#include "openssl/aes.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_LOG_CATEGORY(LogHIDApi);
|
DEFINE_LOG_CATEGORY(LogHIDApi);
|
||||||
|
@ -281,12 +282,21 @@ FPortalStatusData ParsePortalStatus(const uint8* StatusResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DecryptAES128(uint8* OutData, const uint8* InData, const uint8* Key)
|
||||||
|
{
|
||||||
|
AES_KEY AesKey;
|
||||||
|
// Set the decryption key (16 bytes for AES-128)
|
||||||
|
AES_set_decrypt_key(Key, 128, &AesKey);
|
||||||
|
|
||||||
|
// Perform AES-128 decryption (ECB mode)
|
||||||
|
AES_ecb_encrypt(InData, OutData, &AesKey, AES_DECRYPT);
|
||||||
|
}
|
||||||
|
|
||||||
FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex)
|
FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex)
|
||||||
{
|
{
|
||||||
|
|
||||||
FigureData FigureData;
|
FigureData TempFigureData;
|
||||||
FigureData.dataError = false; // Initialize error flag
|
TempFigureData.dataError = false; // Initialize error flag
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -297,12 +307,12 @@ FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex)
|
||||||
uint8* output = QueryBlock(FigureIndex, BlockIndex);
|
uint8* output = QueryBlock(FigureIndex, BlockIndex);
|
||||||
|
|
||||||
// Copy 16 bytes from the output, starting at the third byte
|
// Copy 16 bytes from the output, starting at the third byte
|
||||||
FMemory::Memcpy(FigureData.data, output + 3, FIGURE_BLOCK_SIZE);
|
FMemory::Memcpy(TempFigureData.data, output + 3, FIGURE_BLOCK_SIZE);
|
||||||
|
|
||||||
// Block 1 is sometimes a duplicate of block 0
|
// Block 1 is sometimes a duplicate of block 0
|
||||||
if (BlockIndex == 1)
|
if (BlockIndex == 1)
|
||||||
{
|
{
|
||||||
if (FMemory::Memcmp(FigureData.data, FigureData.data[0], FIGURE_BLOCK_SIZE) == 0)
|
if (FMemory::Memcmp(TempFigureData.data, TempFigureData.data[0], FIGURE_BLOCK_SIZE) == 0)
|
||||||
{
|
{
|
||||||
--BlockIndex; // Decrement index to reprocess
|
--BlockIndex; // Decrement index to reprocess
|
||||||
continue;
|
continue;
|
||||||
|
@ -312,15 +322,15 @@ FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex)
|
||||||
if (((BlockIndex + 1) % 4 == 0) || BlockIndex < 8)
|
if (((BlockIndex + 1) % 4 == 0) || BlockIndex < 8)
|
||||||
{
|
{
|
||||||
// Direct copy from data to decryptedData for certain blocks
|
// Direct copy from data to decryptedData for certain blocks
|
||||||
FMemory::Memcpy(FigureData.decryptedData[BlockIndex], FigureData.data[BlockIndex], FIGURE_BLOCK_SIZE);
|
FMemory::Memcpy(TempFigureData.decryptedData[BlockIndex], TempFigureData.data[BlockIndex], FIGURE_BLOCK_SIZE);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/***** MD5 Hash Calculation *****/
|
/***** MD5 Hash Calculation *****/
|
||||||
// Prepare the hash input buffer
|
// Prepare the hash input buffer
|
||||||
uint8 hashIn[0x56];
|
uint8 hashIn[0x56];
|
||||||
FMemory::Memcpy(hashIn, FigureData.data[0], 16);
|
FMemory::Memcpy(hashIn, TempFigureData.data[0], 16);
|
||||||
FMemory::Memcpy(hashIn + 0x10, FigureData.data[1], 16);
|
FMemory::Memcpy(hashIn + 0x10, TempFigureData.data[1], 16);
|
||||||
hashIn[0x20] = BlockIndex;
|
hashIn[0x20] = BlockIndex;
|
||||||
// Append the 35-byte constant
|
// Append the 35-byte constant
|
||||||
FMemory::Memcpy(hashIn + 0x21, HASH_CONST, sizeof(HASH_CONST));
|
FMemory::Memcpy(hashIn + 0x21, HASH_CONST, sizeof(HASH_CONST));
|
||||||
|
@ -337,39 +347,14 @@ FigureData USkyPortalIO::ReadFigureBlocks(uint8 FigureIndex)
|
||||||
FMemory::Memcpy(AesKey.Key, key, 16);
|
FMemory::Memcpy(AesKey.Key, key, 16);
|
||||||
|
|
||||||
//TODO: FAES implementation in Unreal is AES-256. We need AES-128
|
//TODO: FAES implementation in Unreal is AES-256. We need AES-128
|
||||||
//FAES::DecryptData(FigureData.decryptedData[BlockIndex], FigureData.data[BlockIndex], 16, AesKey);
|
//FAES::DecryptData(TempFigureData.decryptedData[BlockIndex], TempFigureData.data[BlockIndex], 16, AesKey);
|
||||||
|
DecryptAES128(TempFigureData.decryptedData[BlockIndex], TempFigureData.data[BlockIndex], key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if (output[1] == (0x10 + 'Q')) // Successful query
|
|
||||||
{
|
|
||||||
// Extract the 16 bytes of block data
|
|
||||||
for (int i = 3; i < 19; i++)
|
|
||||||
{
|
|
||||||
FigureData.data[BlockIndex][i] = output[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (output[0] == 0x01) {
|
|
||||||
FigureData.dataError = true;
|
|
||||||
UE_LOG(LogSkyportalIO, Warning, TEXT("Error querying block %d from figure %d"), BlockIndex, FigureIndex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the block index matches the requested block
|
|
||||||
uint8 ReturnedBlockIndex = output[3];
|
|
||||||
if (ReturnedBlockIndex != BlockIndex)
|
|
||||||
{
|
|
||||||
FigureData.dataError = true;
|
|
||||||
UE_LOG(LogSkyportalIO, Warning, TEXT("Mismatched block index. Expected %d, got %d"), BlockIndex, ReturnedBlockIndex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy block data into FigureData
|
|
||||||
//memcpy(FigureData.blockdata[BlockIndex], &res.buf[4], FIGURE_BLOCK_SIZE);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some verifications should happen. Like if dataError is set.
|
// Some verifications should happen. Like if dataError is set.
|
||||||
|
|
||||||
return FigureData; // Return the complete figure data
|
return TempFigureData; // Return the complete figure data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,15 +72,11 @@ void FPortalStatusChecker::CheckPortalStatus()
|
||||||
switch (CurrentStatusData.StatusArray[i])
|
switch (CurrentStatusData.StatusArray[i])
|
||||||
{
|
{
|
||||||
case EFigureStatus::NOT_PRESENT:
|
case EFigureStatus::NOT_PRESENT:
|
||||||
|
|
||||||
break;
|
|
||||||
case EFigureStatus::PRESENT:
|
case EFigureStatus::PRESENT:
|
||||||
//FigureData = ReadFigureBlocks(i);
|
|
||||||
//subref->OnSkylanderAdded.Broadcast(GetFigureID(FigureData), i);
|
|
||||||
break;
|
break;
|
||||||
case EFigureStatus::ADDED:
|
case EFigureStatus::ADDED:
|
||||||
figData = PortalHandleRef->ReadFigureBlocks(i);
|
//figData = PortalHandleRef->ReadFigureBlocks(i);
|
||||||
subref->OnSkylanderAdded.Broadcast(figData.GetFigureID(), i);
|
subref->OnSkylanderAdded.Broadcast(00, i);
|
||||||
break;
|
break;
|
||||||
case EFigureStatus::REMOVED:
|
case EFigureStatus::REMOVED:
|
||||||
subref->OnSkylanderRemoved.Broadcast(00, i);
|
subref->OnSkylanderRemoved.Broadcast(00, i);
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
|
|
||||||
#include "SkyPortalSubsystem.h"
|
#include "SkyPortalSubsystem.h"
|
||||||
#include "Engine/Engine.h"
|
#include "Engine/Engine.h"
|
||||||
#include "SkyPortal.h"
|
|
||||||
|
|
||||||
#include "HAL/RunnableThread.h"
|
#include "HAL/RunnableThread.h"
|
||||||
#include "Misc/ScopeLock.h"
|
#include "SkyPortalFigure.h"
|
||||||
|
|
||||||
|
|
||||||
void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
void USkyPortalSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
||||||
|
@ -213,7 +212,7 @@ void USkyPortalSubsystem::Sleep(int sleepMs) {
|
||||||
bool USkyPortalSubsystem::PortalConnect()
|
bool USkyPortalSubsystem::PortalConnect()
|
||||||
{
|
{
|
||||||
PortalHandle = NewObject<USkyPortalIO>();
|
PortalHandle = NewObject<USkyPortalIO>();
|
||||||
if (IsValid(PortalHandle)) {
|
if (IsValid(PortalHandle) && PortalHandle->bPortalReady) {
|
||||||
UE_LOG(LogSkyportalIO, Log, TEXT("Portal connected: "));
|
UE_LOG(LogSkyportalIO, Log, TEXT("Portal connected: "));
|
||||||
PortalReady();
|
PortalReady();
|
||||||
PortalActivate(1);
|
PortalActivate(1);
|
||||||
|
@ -234,7 +233,22 @@ bool USkyPortalSubsystem::IsPortalReady()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SKYPORTAL_API void USkyPortalSubsystem::PortalMusic(const USoundWave* Sound)
|
void USkyPortalSubsystem::PortalMusic(const USoundWave* Sound)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void USkyPortalSubsystem::PortalAnalyze(const uint8 index)
|
||||||
|
{
|
||||||
|
FigureArray[index] = PortalHandle->ReadFigureBlocks(index);
|
||||||
|
UE_LOG(LogSkyportalIO, Log, TEXT("Reading figure..."));
|
||||||
|
UE_LOG(LogSkyportalIO, Log, TEXT("decrypted Figure ID : %d"), FigureArray[index].GetFigureID());
|
||||||
|
}
|
||||||
|
|
||||||
|
void USkyPortalSubsystem::GetFigureArray() {
|
||||||
|
FigureArray;
|
||||||
|
for (int i = 0; 16; i++) {
|
||||||
|
FigureArray[i] = PortalHandle->ReadFigureBlocks(i);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
|
@ -12,10 +12,11 @@ static const uint8 HASH_CONST[] = {
|
||||||
#define FIGURE_TOTAL_BLOCKS 64
|
#define FIGURE_TOTAL_BLOCKS 64
|
||||||
#define FIGURE_BLOCK_SIZE 16
|
#define FIGURE_BLOCK_SIZE 16
|
||||||
|
|
||||||
|
/*
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned char blockdata[FIGURE_TOTAL_BLOCKS][FIGURE_BLOCK_SIZE]; bool error;
|
unsigned char blockdata[FIGURE_TOTAL_BLOCKS][FIGURE_BLOCK_SIZE]; bool error;
|
||||||
} FigureDataBlock;
|
} FigureDataBlock;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
class FigureData {
|
class FigureData {
|
||||||
|
@ -38,8 +39,8 @@ public:
|
||||||
uint64 FullToyCodeNumber;
|
uint64 FullToyCodeNumber;
|
||||||
FString ToyCode;
|
FString ToyCode;
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
int16 ID;
|
int16 ID; //Skylander ID
|
||||||
int16 VariantID;
|
int16 VariantID; //Skylander Variant ID
|
||||||
#pragma region counters
|
#pragma region counters
|
||||||
uint8 counter1;
|
uint8 counter1;
|
||||||
uint8 couter2;
|
uint8 couter2;
|
||||||
|
@ -53,10 +54,7 @@ public:
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure"))
|
|
||||||
uint32 GetFigureID();
|
uint32 GetFigureID();
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Category = "SkyPortal|Figure"))
|
|
||||||
uint32 GetFigureIdByIndex(uint32 index);
|
uint32 GetFigureIdByIndex(uint32 index);
|
||||||
|
|
||||||
//UFUNCTION()
|
//UFUNCTION()
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Subsystems/EngineSubsystem.h"
|
#include "CoreMinimal.h"
|
||||||
#include "SkyPortalRunner.h"
|
#include "SkyPortalFigure.h"
|
||||||
#include "SkyPortalIO.h"
|
#include "SkyPortalIO.h"
|
||||||
|
#include "SkyPortalRunner.h"
|
||||||
|
#include "Subsystems/EngineSubsystem.h"
|
||||||
|
#include "Delegates/DelegateCombinations.h"
|
||||||
|
#include <Containers/Array.h>
|
||||||
|
|
||||||
#include "SkyPortalSubsystem.generated.h"
|
#include "SkyPortalSubsystem.generated.h"
|
||||||
|
|
||||||
|
|
||||||
#pragma region Definitions
|
#pragma region Definitions
|
||||||
|
|
||||||
//// Delegates
|
//// Delegates
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderAddedDelegate, int32, SkylanderID, int32, Index);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderAddedDelegate, int32, SkylanderID, int32, Index);
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, SkylanderID, int32, Index);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSkylanderRemovedDelegate, int32, SkylanderID, int32, Index);
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
@ -74,6 +81,12 @@ public:
|
||||||
UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING"))
|
UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|NOT FUNCTIONING"))
|
||||||
SKYPORTAL_API void PortalMusic(const USoundWave* Sound);
|
SKYPORTAL_API void PortalMusic(const USoundWave* Sound);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|Figure|Debug"))
|
||||||
|
SKYPORTAL_API void PortalAnalyze(const uint8 index);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (Category = "SkyPortal|Commands|Figure"))
|
||||||
|
SKYPORTAL_API void GetFigureArray();
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands"))
|
UFUNCTION(BlueprintCallable, CallInEditor, meta = (Category = "SkyPortal|Commands"))
|
||||||
SKYPORTAL_API FPortalStatusData PortalStatus();
|
SKYPORTAL_API FPortalStatusData PortalStatus();
|
||||||
|
@ -104,6 +117,8 @@ public:
|
||||||
UPROPERTY(BlueprintReadOnly)
|
UPROPERTY(BlueprintReadOnly)
|
||||||
FPortalStatusData StatusData;
|
FPortalStatusData StatusData;
|
||||||
|
|
||||||
|
TArray<FigureData> FigureArray;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite)
|
UPROPERTY(BlueprintReadWrite)
|
||||||
float RunnerInterval = 0.01f; //In seconds
|
float RunnerInterval = 0.01f; //In seconds
|
||||||
|
|
||||||
|
|
|
@ -62,9 +62,10 @@ public class SkyPortal : ModuleRules
|
||||||
{
|
{
|
||||||
"Core",
|
"Core",
|
||||||
"CoreUObject",
|
"CoreUObject",
|
||||||
"Engine"
|
"Engine",
|
||||||
// ... add other public dependencies that you statically link with here ...
|
"OpenSSL",
|
||||||
}
|
"SSL"
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ public class SkyPortal : ModuleRules
|
||||||
"Engine",
|
"Engine",
|
||||||
"Slate",
|
"Slate",
|
||||||
"SlateCore",
|
"SlateCore",
|
||||||
// ... add private dependencies that you statically link with here ...
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue