diff --git a/ios_mcp/source/imports.h b/ios_mcp/source/imports.h index 6ce0b9a..e5688a2 100644 --- a/ios_mcp/source/imports.h +++ b/ios_mcp/source/imports.h @@ -130,8 +130,8 @@ int IOSC_DeleteObject(int keyHandle); int IOSC_GenerateRand(uint8_t* randBytes, uint32_t numBytes); int IOSC_ImportSecretKey(IOSCSecretKeyHandle importedHandle, IOSCSecretKeyHandle verifyHandle, IOSCSecretKeyHandle decryptHandle, IOSCSecretKeySecurity flag, uint8_t* signbuffer, uint32_t signbufferSize, uint8_t* ivData, uint32_t ivSize, uint8_t* keybuffer, uint32_t keybufferSize); int IOSC_ImportPublicKey(uint8_t* publicKeyData, uint32_t dataSize, uint8_t* exponent, uint32_t exponentSize, IOSCPublicKeyHandle publicKeyHandle); -int IOSC_Decrypt(IOSCSecretKeyHandle decryptHandle, uint8_t* ivData, uint32_t ivSize, uint8_t* inputData, uint32_t inputSize, uint8_t* outputData, uint32_t outputSize); -int IOSC_Encrypt(IOSCSecretKeyHandle encryptHandle, uint8_t* ivData, uint32_t ivSize, uint8_t* inputData, uint32_t inputSize, uint8_t* outputData, uint32_t outputSize); +int IOSC_Decrypt(IOSCSecretKeyHandle decryptHandle, void* ivData, uint32_t ivSize, void* inputData, uint32_t inputSize, void* outputData, uint32_t outputSize); +int IOSC_Encrypt(IOSCSecretKeyHandle encryptHandle, void* ivData, uint32_t ivSize, void* inputData, uint32_t inputSize, void* outputData, uint32_t outputSize); #define WUP_CERT_SIGTYPE_ECC_SHA1 0x00010002 /* ECC with SHA-1 */ #define WUP_CERT_SIGTYPE_ECC_SHA256 0x00010005 /* ECC with SHA-256 */ diff --git a/ios_mcp/source/menu.c b/ios_mcp/source/menu.c index c542717..fa554f0 100644 --- a/ios_mcp/source/menu.c +++ b/ios_mcp/source/menu.c @@ -918,7 +918,7 @@ int read_otp_seeprom(void *buf, int index) return 0; } -static int preparePrshHax(void) +static int preparePrshHax(uint32_t boootInfoPtr) { // RAM vars uint32_t ram_start_addr = 0x10000000; @@ -943,7 +943,7 @@ static int preparePrshHax(void) } // Change boot_info to point inside boot1 memory - *(uint32_t *) boot_info_ptr_addr = 0x0D40AC6D; + *(uint32_t *) boot_info_ptr_addr = boootInfoPtr; // Re-calculate PRSH checksum uint32_t checksum = 0; @@ -983,6 +983,8 @@ typedef struct { uint16_t reserved[4]; uint32_t crc; } Boot1Params; +static_assert(sizeof(Boot1Params) == 0x10); + Boot1Params boot1Params[2] __attribute__ ((aligned (0x10))); static int decryptBoot1Params(int index) @@ -999,12 +1001,12 @@ static int readBoot1Params(void) { int ret; - ret = EEPROM_Read(0xe8, 8, &boot1Params[0]); + ret = EEPROM_Read(0xe8, 8, (uint16_t*)&boot1Params[0]); if (ret != 0) { return ret; } - ret = EEPROM_Read(0xf0, 8, &boot1Params[1]); + ret = EEPROM_Read(0xf0, 8, (uint16_t*)&boot1Params[1]); if (ret != 0) { return ret; } @@ -1021,7 +1023,7 @@ static int determineActiveBoot1Slot(void) // Calculate crcs uint32_t validMask = 0; for (int i = 0; i < 2; i++) { - if (crc32(0xffffffff, &boot1Params[i], 0xc) == boot1Params[i].crc) { + if (~crc32(0xffffffff, &boot1Params[i], 0xc) == boot1Params[i].crc) { validMask |= 1 << i; } } @@ -1068,19 +1070,34 @@ static void option_LoadBoot1Payload(void) return; gfx_printf(16, index, 0, "Checking BOOT1 version..."); + index += CHAR_SIZE_DRC_Y + 4; + + if (!readBoot1Params()) { + gfx_set_font_color(COLOR_ERROR); + gfx_printf(16, index, 0, "Failed to read boot1 parameters"); + waitButtonInput(); + return; + } int activeSlot; - if (readBoot1Params() != 1 || (activeSlot = determineActiveBoot1Slot()) < 0) { + if ((activeSlot = determineActiveBoot1Slot()) < 0) { gfx_set_font_color(COLOR_ERROR); - gfx_printf(16, index, 0, "Failed to determine boot1 version"); + gfx_printf(16, index, 0, "Failed to determine active boot1 version"); waitButtonInput(); return; } uint16_t activeVersion = boot1Params[activeSlot].version; + gfx_printf(16, index, 0, "Active BOOT1 version: %d (slot %d)", activeVersion, activeSlot); + index += CHAR_SIZE_DRC_Y + 4; - // TODO we could probably support more versions - if (activeVersion != 8377) { + // TODO support more versions / check for dev/retail + uint32_t boootInfoPtr; + switch (activeVersion) { + case 8377: + boootInfoPtr = 0x0D40AC6D; + break; + default: gfx_set_font_color(COLOR_ERROR); gfx_printf(16, index, 0, "Unsupported BOOT1 version: %d", activeVersion); waitButtonInput(); @@ -1119,7 +1136,7 @@ static void option_LoadBoot1Payload(void) // Check ancast magic if (dataBuffer[0] != 0xEFA282D9) { gfx_set_font_color(COLOR_ERROR); - gfx_printf(16, index, 0, "Invalid ancast header magic: %08x", dataBuffer[0]); + gfx_printf(16, index, 0, "Invalid ancast header magic: %08lx", dataBuffer[0]); waitButtonInput(); IOS_HeapFree(CROSS_PROCESS_HEAP_ID, dataBuffer); FSA_CloseFile(fsaHandle, fileHandle); @@ -1127,7 +1144,7 @@ static void option_LoadBoot1Payload(void) } // Check unencrypted flag - if (((dataBuffer[0x68] >> 2) & 1) == 0) { + if (((dataBuffer[0x68] >> 16) & 1) == 0) { gfx_set_font_color(COLOR_ERROR); gfx_printf(16, index, 0, "Ancast image is encrypted!"); waitButtonInput(); @@ -1136,6 +1153,8 @@ static void option_LoadBoot1Payload(void) return; } + uint32_t bodySize = dataBuffer[0x6B]; + // read and write payload to mem1 uint32_t payloadOffset = 0x00000050; int bytesRead = 0; @@ -1147,7 +1166,8 @@ static void option_LoadBoot1Payload(void) } } - gfx_printf(16, index, 0, "Read %d bytes", bytesRead); + gfx_printf(16, index, 0, "Read %d / %ld bytes", bytesRead, bodySize); + index += CHAR_SIZE_DRC_Y + 4; IOS_HeapFree(CROSS_PROCESS_HEAP_ID, dataBuffer); FSA_CloseFile(fsaHandle, fileHandle); @@ -1159,15 +1179,15 @@ static void option_LoadBoot1Payload(void) return; } - // Check payload size - if (dataBuffer[0x6B] != bytesRead) { + // Check body size + if (bytesRead < bodySize) { gfx_set_font_color(COLOR_ERROR); - gfx_printf(16, index, 0, "Failed to read ancast image (%d / %d bytes)", bytesRead, dataBuffer[0x6B]); + gfx_printf(16, index, 0, "Failed to read ancast body (%d / %ld bytes)", bytesRead, bodySize); waitButtonInput(); return; } - res = preparePrshHax(); + res = preparePrshHax(boootInfoPtr); if (res < 0) { gfx_set_font_color(COLOR_ERROR); gfx_printf(16, index, 0, "Failed to prepare prshhax: %x", res); @@ -1175,8 +1195,8 @@ static void option_LoadBoot1Payload(void) return; } - // Setup branch to MEM1 payload (skip ancast header) - kernWrite32(0x00000000, 0xEA000092); // b #0x250 + // Setup branch to MEM1 payload + kernWrite32(0x00000000, 0xEA000012); // b #0x50 kernWrite32(0x00000004, 0xDEADC0DE); kernWrite32(0x00000008, 0xDEADC0DE);