Skip to content

Commit

Permalink
Update to v1.3.2.
Browse files Browse the repository at this point in the history
* Removed trailing whitespaces in the codebase.
* Added boot0 Mask ROM dumping (as requested by @MasterLuma).
  • Loading branch information
DarkMatterCore committed Jul 18, 2022
1 parent 848fe96 commit 8d61b44
Show file tree
Hide file tree
Showing 14 changed files with 414 additions and 294 deletions.
13 changes: 6 additions & 7 deletions .gitignore
@@ -1,8 +1,7 @@
build
/*.elf
/*.dol

# Clion files
.idea
cmake-build-debug
CMakeLists.txt
output
*.elf
*.dol
*.bin
*.cert
*.txt
Binary file removed HBC/boot.dol
Binary file not shown.
Binary file removed HBC/boot.elf
Binary file not shown.
9 changes: 5 additions & 4 deletions HBC/meta.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<app version="1.1">
<name>Xyzzy</name>
<version>1.3.1</version>
<release_date>20220713022030</release_date>
<version>1.3.2</version>
<release_date>20220718184500</release_date>
<coder>Bushing, DarkMatterCore</coder>
<short_description>Extract your Wii console keys!</short_description>
<long_description>Xyzzy is a homebrew application that allows the extraction of the OTP and SEEPROM Encryption Keys.
Expand All @@ -15,9 +15,10 @@ Other changes include:
* Support for GCN controllers and newer WiiMotes.
* Retrieves SD IV, MD5 Blanker and MAC address.
* Besides generating a "keys.txt" file with a hexdump of every dumped key, which follows the format required by wad2bin (https://github.com/DarkMatterCore/wad2bin), these files are also created:
* "bootmii_keys.bin" (follows the BootMii keys.bin format).
* "device.cert" (raw device certificate dump).
* "otp.bin" (raw OTP memory dump).
* "seeprom.bin" (raw SEEPROM memory dump) (Wii only).</long_description>
* "seeprom.bin" (raw SEEPROM memory dump) (Wii only).
* "bootmii_keys.bin" (follows the BootMii keys.bin format) (Wii only).
* "boot0.bin" (raw boot0 Mask ROM dump) (Wii only).</long_description>
<ahb_access/>
</app>
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -11,7 +11,8 @@ Other changes include:
* Support for GCN controllers and newer WiiMotes.
* Retrieves SD IV, MD5 Blanker and MAC address.
* Besides generating a "keys.txt" file with a hexdump of every dumped key, which follows the format required by [wad2bin](https://github.com/DarkMatterCore/wad2bin), these files are also created:
* "bootmii_keys.bin" (follows the BootMii keys.bin format).
* "device.cert" (raw device certificate dump).
* "otp.bin" (raw OTP memory dump).
* "seeprom.bin" (raw SEEPROM memory dump) (Wii only).
* "bootmii_keys.bin" (follows the BootMii keys.bin format) (Wii only).
* "boot0.bin" (raw boot0 Mask ROM dump) (Wii only).
59 changes: 29 additions & 30 deletions source/aes.c
Expand Up @@ -19,7 +19,6 @@
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <gctypes.h>

Expand Down Expand Up @@ -748,7 +747,7 @@ void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
rk[1] = GETU32(cipherKey + 4);
rk[2] = GETU32(cipherKey + 8);
rk[3] = GETU32(cipherKey + 12);

for (i = 0; i < 10; i++)
{
temp = rk[3];
Expand All @@ -770,7 +769,7 @@ void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])

/* expand the cipher key: */
rijndaelKeySetupEnc(rk, cipherKey);

/* invert the order of the round keys: */
for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4)
{
Expand All @@ -779,7 +778,7 @@ void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[])
temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
}

/* apply the inverse MixColumn transform to all round keys but the first and the last: */
for (i = 1; i < Nr; i++)
{
Expand Down Expand Up @@ -808,15 +807,15 @@ void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16])
s1 = GETU32(pt + 4) ^ rk[1];
s2 = GETU32(pt + 8) ^ rk[2];
s3 = GETU32(pt + 12) ^ rk[3];

#define ROUND(i,d,s) \
d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]

#ifdef FULL_UNROLL

ROUND(1,t,s);
ROUND(2,s,t);
ROUND(3,t,s);
Expand All @@ -826,11 +825,11 @@ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
ROUND(7,t,s);
ROUND(8,s,t);
ROUND(9,t,s);

rk += Nr << 2;

#else /* !FULL_UNROLL */

/* Nr - 1 full rounds: */
r = Nr >> 1;
for (;;)
Expand All @@ -840,11 +839,11 @@ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
if (--r == 0) break;
ROUND(0,s,t);
}

#endif /* ?FULL_UNROLL */

#undef ROUND

/*
* apply last round and
* map cipher state to byte array block:
Expand Down Expand Up @@ -875,15 +874,15 @@ void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16])
s1 = GETU32(ct + 4) ^ rk[1];
s2 = GETU32(ct + 8) ^ rk[2];
s3 = GETU32(ct + 12) ^ rk[3];

#define ROUND(i,d,s) \
d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]

#ifdef FULL_UNROLL

ROUND(1,t,s);
ROUND(2,s,t);
ROUND(3,t,s);
Expand All @@ -895,9 +894,9 @@ d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
ROUND(9,t,s);

rk += Nr << 2;

#else /* !FULL_UNROLL */

/* Nr - 1 full rounds: */
r = Nr >> 1;
for (;;)
Expand All @@ -907,11 +906,11 @@ d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
if (--r == 0) break;
ROUND(0,s,t);
}

#endif /* ?FULL_UNROLL */

#undef ROUND

/*
* apply last round and
* map cipher state to byte array block:
Expand All @@ -930,14 +929,14 @@ void *aes_init(const u8 *key, bool Enc)
{
u32 *rk = malloc(AES_PRIV_SIZE);
if (rk == NULL) return NULL;

if (Enc)
{
rijndaelKeySetupEnc(rk, key);
} else {
rijndaelKeySetupDec(rk, key);
}

return rk;
}

Expand All @@ -961,12 +960,12 @@ int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
u8 cbc[AES_BLOCK_SIZE];
u8 *pos = data;
int i, j, blocks;

ctx = aes_init(key, true);
if (ctx == NULL) return -1;

memcpy(cbc, iv, AES_BLOCK_SIZE);

blocks = data_len / AES_BLOCK_SIZE;
for (i = 0; i < blocks; i++)
{
Expand All @@ -975,7 +974,7 @@ int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
memcpy(pos, cbc, AES_BLOCK_SIZE);
pos += AES_BLOCK_SIZE;
}

aes_deinit(ctx);
return 0;
}
Expand All @@ -994,12 +993,12 @@ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
u8 *pos = data;
int i, j, blocks;

ctx = aes_init(key, false);
if (ctx == NULL) return -1;

memcpy(cbc, iv, AES_BLOCK_SIZE);

blocks = data_len / AES_BLOCK_SIZE;
for (i = 0; i < blocks; i++)
{
Expand All @@ -1009,7 +1008,7 @@ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
memcpy(cbc, tmp, AES_BLOCK_SIZE);
pos += AES_BLOCK_SIZE;
}

aes_deinit(ctx);
return 0;
}
78 changes: 78 additions & 0 deletions source/boot0.c
@@ -0,0 +1,78 @@
#include <ogc/machine/processor.h>
#include <unistd.h>
#include <string.h>

#include "boot0.h"
#include "tools.h"

#define SRAM_MIRROR 0xD400000

#define HW_SRNPROT 0xD800060
#define SRAM_MASK 0x20

#define HW_BOOT0 0xD80018C
#define BOOT0_MASK 0x1000

#define BOOT0_BLK_SIZE 4

u16 boot0_read(void *dst, u16 offset, u16 size)
{
if (!dst || offset >= BOOT0_SIZE || !size || (offset + size) > BOOT0_SIZE) return 0;

u8 *ptr = (u8*)dst;
u8 val[BOOT0_BLK_SIZE] = {0};
u16 cur_offset = 0;
bool disable_sram_mirror = false;

// Calculate block offsets and sizes
u32 start_addr = (SRAM_MIRROR + ALIGN_DOWN(offset, BOOT0_BLK_SIZE));
u8 start_addr_offset = (offset % BOOT0_BLK_SIZE);

u32 end_addr = (SRAM_MIRROR + ALIGN_UP(offset + size, BOOT0_BLK_SIZE));
u8 end_addr_size = ((offset + size) % BOOT0_BLK_SIZE);

// Make sure the SRAM mirror is enabled (unlikely to be disabled, but let's play it safe)
if (!(read32(HW_SRNPROT) & SRAM_MASK))
{
// Enable SRAM mirror
mask32(HW_SRNPROT, 0, SRAM_MASK);
disable_sram_mirror = true;
}

// Enable boot0
mask32(HW_BOOT0, BOOT0_MASK, 0);

for(u32 addr = start_addr; addr < end_addr; addr += BOOT0_BLK_SIZE)
{
if (cur_offset >= size) break;

// Read SRAM mirror (actually holds boot0 data)
*((u32*)val) = read32(addr);

// Copy data to destination buffer
if (addr == start_addr && start_addr_offset != 0)
{
// Handle unaligned read at start address
memcpy(ptr + cur_offset, val + start_addr_offset, BOOT0_BLK_SIZE - start_addr_offset);
cur_offset += (BOOT0_BLK_SIZE - start_addr_offset);
} else
if (addr >= (end_addr - BOOT0_BLK_SIZE) && end_addr_size != 0)
{
// Handle unaligned read at end address
memcpy(ptr + cur_offset, val, end_addr_size);
cur_offset += end_addr_size;
} else {
// Normal read
memcpy(ptr + cur_offset, val, BOOT0_BLK_SIZE);
cur_offset += BOOT0_BLK_SIZE;
}
}

// Disable boot0
mask32(HW_BOOT0, 0, BOOT0_MASK);

// Disable SRAM mirror, if needed
if (disable_sram_mirror) mask32(HW_SRNPROT, SRAM_MASK, 0);

return cur_offset;
}
8 changes: 8 additions & 0 deletions source/boot0.h
@@ -0,0 +1,8 @@
#ifndef __BOOT0_H__
#define __BOOT0_H__

#define BOOT0_SIZE 0x1000

u16 boot0_read(void *dst, u16 offset, u16 size);

#endif /* __BOOT0_H__ */
17 changes: 8 additions & 9 deletions source/main.c
@@ -1,4 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gccore.h>
Expand All @@ -13,16 +12,16 @@ int XyzzyGetKeys(bool vWii);
int main(int argc, char **argv)
{
__exception_setreload(10);

int ret = 0;

InitConsole();
InitPads();

bool vWii = IsWiiU();

PrintHeadline();

/* HW_AHBPROT check */
if (AHBPROT_DISABLED)
{
Expand All @@ -48,10 +47,10 @@ int main(int argc, char **argv)
printf("without full hardware access rights.\n");
printf("\nProcess cannot continue. Press any button to exit.");
}

if (ret != -2) WaitForButtonPress(NULL, NULL);

Reboot();

return 0;
}

0 comments on commit 8d61b44

Please sign in to comment.