OpenSSL implementation

This commit is contained in:
Lucas 2024-09-27 01:39:33 +02:00
parent df5fd8b05b
commit f1988072a4
8 changed files with 74 additions and 119 deletions

View file

@ -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

View file

@ -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()
{ {
} }

View file

@ -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
} }

View file

@ -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);

View file

@ -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;
}

View file

@ -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()

View file

@ -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

View file

@ -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 ...
} }
); );