From 72ae997d3db0d5262c1cbdee2efca8801daa69b8 Mon Sep 17 00:00:00 2001 From: ergo720 Date: Sat, 31 Mar 2018 22:12:36 +0200 Subject: [PATCH] Calculate last missing checksum field in the eeprom --- src/Common/EmuEEPROM.cpp | 46 ++++++++++++++++++++++++++++++-------- src/Common/EmuEEPROM.h | 2 ++ src/CxbxKrnl/EmuKrnlEx.cpp | 4 ++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/Common/EmuEEPROM.cpp b/src/Common/EmuEEPROM.cpp index 97a9e7371..810f2fc07 100644 --- a/src/Common/EmuEEPROM.cpp +++ b/src/Common/EmuEEPROM.cpp @@ -46,12 +46,18 @@ namespace xboxkrnl #include "Cxbx.h" // For DbgPrintf #include "EmuEEPROM.h" // For EEPROMInfo, EEPROMInfos +#include "..\CxbxKrnl\Emu.h" // For EmuWarning +#include "..\..\src\devices\LED.h" // For SetLEDSequence +#include "..\CxbxKrnl\CxbxKrnl.h" xboxkrnl::XBOX_EEPROM *EEPROM = nullptr; // Set using CxbxRestoreEEPROM() // Default value (NA), overwritten with the actual content in the eeprom by CxbxRestoreEEPROM xboxkrnl::ULONG XboxFactoryGameRegion = XC_GAME_REGION_NA; +// Default eeprom key (all zeros). Used to calculate the checksum of the eeprom header and to encrypt it if desired +UCHAR EepromKey[20] = { 0 }; + const EEPROMInfo* EmuFindEEPROMInfo(xboxkrnl::XC_VALUE_INDEX index) { for (int i = 0; EEPROMInfos[i].index != XC_END_MARKER; i++) @@ -130,7 +136,9 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin) } } - // TODO : Make sure EEPROM.bin is at least 256 bytes in size - FileSeek(hFileEEPROM, EEPROM_SIZE, soFromBeginning); + // Make sure EEPROM.bin is at least 256 bytes in size + SetFilePointer(hFileEEPROM, 256, nullptr, FILE_BEGIN); + SetEndOfFile(hFileEEPROM); HANDLE hFileMappingEEPROM = CreateFileMapping( hFileEEPROM, @@ -145,6 +153,15 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin) return nullptr; } + LARGE_INTEGER len_li; + GetFileSizeEx(hFileEEPROM, &len_li); + unsigned int FileSize = len_li.u.LowPart; + if (FileSize != 256) + { + CxbxKrnlCleanup("CxbxRestoreEEPROM : EEPROM.bin file is not 256 bytes large!\n"); + return nullptr; + } + // Map EEPROM.bin contents into memory : pEEPROM = (xboxkrnl::XBOX_EEPROM *)MapViewOfFile( hFileMappingEEPROM, @@ -161,8 +178,6 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin) // so that users do not need to delete their EEPROM.bin from older versions gen_section_CRCs(pEEPROM); - // TODO : Verify checksums - // Check for (and fix) invalid fields that were set by previous versions of Cxbx-Reloaded // Without this, all users would have to delete their EEPROM.bin // The issue was that the AV_FLAG_XXhz was set in the wrong field, we fix it by @@ -174,12 +189,6 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin) pEEPROM->FactorySettings.AVRegion = AV_STANDARD_NTSC_M | AV_FLAGS_60Hz; } - // Initialize XboxFactoryGameRegion from the value stored in the eeprom - /*const EEPROMInfo* info = EmuFindEEPROMInfo(xboxkrnl::XC_ENCRYPTED_SECTION); - if (info != nullptr) { - XboxFactoryGameRegion = (*((xboxkrnl::XBOX_ENCRYPTED_SETTINGS*)((PBYTE)pEEPROM + info->value_offset))).GameRegion; - }*/ - if (NeedsInitialization) { memset(pEEPROM, 0, EEPROM_SIZE); @@ -207,5 +216,24 @@ xboxkrnl::XBOX_EEPROM *CxbxRestoreEEPROM(char *szFilePath_EEPROM_bin) DbgPrintf("INIT: Loaded EEPROM.bin\n"); } + // Update the existing Checksum if it is all zeros. Without this, all users would have to delete their EEPROM.bin + UCHAR Checksum[20] = { 0 }; + if (!memcmp(Checksum, pEEPROM->EncryptedSettings.Checksum, 20)) + { + xboxkrnl::XcHMAC(EepromKey, 16, pEEPROM->EncryptedSettings.Confounder, 8, pEEPROM->EncryptedSettings.HDKey, 20, + pEEPROM->EncryptedSettings.Checksum); + } + else + { + // Verify the checksum of the eeprom header + xboxkrnl::XcHMAC(EepromKey, 16, pEEPROM->EncryptedSettings.Confounder, 8, pEEPROM->EncryptedSettings.HDKey, 20, Checksum); + if (memcmp(Checksum, pEEPROM->EncryptedSettings.Checksum, 20)) + { + // The checksums do not match. Log this error and flash the LED (red, off, red, off) + EmuWarning("Stored and calculated checksums don't match: eeprom corrupted"); + SetLEDSequence(0xA0); + } + } + return pEEPROM; } diff --git a/src/Common/EmuEEPROM.h b/src/Common/EmuEEPROM.h index 2dc9a49c6..6cfc42342 100644 --- a/src/Common/EmuEEPROM.h +++ b/src/Common/EmuEEPROM.h @@ -102,6 +102,8 @@ extern xboxkrnl::ULONG XboxFactoryGameRegion; void gen_section_CRCs(xboxkrnl::XBOX_EEPROM*); +extern UCHAR EepromKey[20]; + #if defined(__cplusplus) } #endif diff --git a/src/CxbxKrnl/EmuKrnlEx.cpp b/src/CxbxKrnl/EmuKrnlEx.cpp index 21eeebb21..1a14cc6ce 100644 --- a/src/CxbxKrnl/EmuKrnlEx.cpp +++ b/src/CxbxKrnl/EmuKrnlEx.cpp @@ -600,6 +600,10 @@ XBSYSAPI EXPORTNUM(29) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExSaveNonVolatileSetti void * value_addr = nullptr; DWORD result_length; + // Don't allow writing to the eeprom encrypted area + if (ValueIndex == XC_ENCRYPTED_SECTION) + RETURN(STATUS_OBJECT_NAME_NOT_FOUND); + // handle eeprom write if (g_bIsDebug || ValueIndex <= XC_MAX_OS || ValueIndex > XC_MAX_FACTORY) {