diff --git a/source/otp.c b/source/otp.c index eadd9c1..c52d708 100644 --- a/source/otp.c +++ b/source/otp.c @@ -8,14 +8,11 @@ #define HW_OTP_DATA (*(vu32*)0xCD8001F0) #define HW_OTP_BLK_SIZE 4 -#define HW_OTP_BLK_CNT (OTP_BANK_SIZE / HW_OTP_BLK_SIZE) +#define HW_OTP_BLK_CNT (OTP_SIZE / HW_OTP_BLK_SIZE) -u8 otp_read(void *dst, OTPBank bank, u8 offset, u8 size) +u8 otp_read(void *dst, u8 offset, u8 size) { - if (!dst || bank > 7 || offset >= OTP_BANK_SIZE || !size || (offset + size) > OTP_BANK_SIZE) return 0; - - /* This is not a Wii U. */ - if (bank != 0 && read16(0xCD8005A0) != 0xCAFE) return 0; + if (!dst || offset >= OTP_SIZE || !size || (offset + size) > OTP_SIZE) return 0; u8 cur_offset = 0; @@ -42,7 +39,7 @@ u8 otp_read(void *dst, OTPBank bank, u8 offset, u8 size) if (cur_offset >= size) break; // Send command + address - HW_OTP_COMMAND = (0x80000000 | bank << 8 | i); + HW_OTP_COMMAND = (0x80000000 | i); // Receive data *((u32*)val) = HW_OTP_DATA; diff --git a/source/otp.h b/source/otp.h index a5b35a0..d4d9939 100644 --- a/source/otp.h +++ b/source/otp.h @@ -1,19 +1,9 @@ #ifndef __OTP_H__ #define __OTP_H__ -#include +#define OTP_SIZE 0x80 -#define OTP_BANK_SIZE 0x80 - -// I want to add a structure for Bank 1 but the only thing that matters to me is the vWii common key in there. -#define VWII_COMMON_KEY_OFFSET 0x50 -typedef enum -{ - BANK_WII, - BANK_WIIU, -} OTPBank; - -struct OTP +typedef struct { u8 boot1_hash[20]; u8 common_key[16]; @@ -32,9 +22,8 @@ struct OTP u8 rng_key[16]; u32 unk1; u32 unk2; // 0x00000007 -}; -_Static_assert(sizeof(struct OTP) == OTP_BANK_SIZE, "OTP struct size incorrect!"); +} otp_t; -u8 otp_read(void *dst, OTPBank bank, u8 offset, u8 size); +u8 otp_read(void *dst, u8 offset, u8 size); #endif /* __OTP_H__ */ diff --git a/source/sys.h b/source/sys.h index c7990c0..95f5f76 100644 --- a/source/sys.h +++ b/source/sys.h @@ -27,9 +27,12 @@ typedef struct char _padding[16]; } cIOSInfo; -_Static_assert(sizeof(cIOSInfo) == 0x40, "Incorrect cIOSInfo struct size, do i really need to pack this..?"); +// _Static_assert(sizeof(cIOSInfo) == 0x40, "Incorrect cIOSInfo struct size, do i really need to pack this..?"); + +#define IS_WIIU (*(vu16*)0xCD005A0 == 0xCAFE) extern u32 boot2version; + /* Prototypes */ bool isIOSstub(u8 ios_number); bool tmdIsStubIOS(tmd*); diff --git a/source/title.c b/source/title.c index 19abbc3..44d67de 100644 --- a/source/title.c +++ b/source/title.c @@ -3,9 +3,11 @@ #include #include #include +#include #include "sha1.h" #include "utils.h" +#include "otp.h" #include "malloc.h" s32 Title_ZeroSignature(signed_blob *p_sig) @@ -315,3 +317,28 @@ out: return ret; } + +__attribute__((aligned(0x10))) +aeskey WiiCommonKey, vWiiCommonKey; + +void Title_SetupCommonKeys(void) +{ + static bool keys_ok = false; + if (keys_ok) + return; + + // Grab the Wii common key... + otp_read(WiiCommonKey, offsetof(otp_t, common_key), sizeof(aeskey)); + + // ...and decrypt the vWii common key with it. + static const unsigned char vwii_key_enc_bin[0x10] = { 0x6e, 0x18, 0xdb, 0x23, 0x84, 0x7c, 0xba, 0x6c, 0x19, 0x31, 0xa4, 0x17, 0x9b, 0xaf, 0x8e, 0x09 }; + unsigned char iv[0x10] = {}; + + memcpy(vWiiCommonKey, vwii_key_enc_bin, sizeof(vwii_key_enc_bin)); + AES_Init(); + AES_Decrypt(WiiCommonKey, sizeof(aeskey), iv, sizeof(iv), vWiiCommonKey, vWiiCommonKey, sizeof(aeskey)); + AES_Close(); + + keys_ok = true; + return; +}; \ No newline at end of file diff --git a/source/title.h b/source/title.h index c2c802a..44c04ea 100644 --- a/source/title.h +++ b/source/title.h @@ -1,9 +1,14 @@ #ifndef _TITLE_H_ #define _TITLE_H_ +#include + /* Constants */ #define BLOCK_SIZE 0x4000 +/* Variables */ +extern aeskey WiiCommonKey, vWiiCommonKey; + /* Prototypes */ s32 Title_ZeroSignature(signed_blob *); s32 Title_FakesignTik(signed_blob *); diff --git a/source/wad.c b/source/wad.c index 6ea03be..822295e 100644 --- a/source/wad.c +++ b/source/wad.c @@ -578,17 +578,13 @@ bool __Wad_FixTicket(signed_blob *s_tik) iv[0] = p_tik->titleid; iv[1] = 0; - if (!otp_read(commonkey, BANK_WIIU, VWII_COMMON_KEY_OFFSET, sizeof(commonkey))) - return false; - AES_Init(); - AES_Decrypt(commonkey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf)); + AES_Decrypt(vWiiCommonKey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf)); - otp_read(commonkey, BANK_WII, offsetof(struct OTP, common_key), sizeof(commonkey)); iv[0] = p_tik->titleid; iv[1] = 0; - AES_Encrypt(commonkey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf)); + AES_Encrypt(WiiCommonKey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf)); memcpy(p_tik->cipher_title_key, tkeybuf, sizeof(tkeybuf)); AES_Close(); @@ -598,7 +594,7 @@ bool __Wad_FixTicket(signed_blob *s_tik) Title_FakesignTik(s_tik); } - return true; + return fixvWiiKey; } bool __Wad_VerifyHeader(wadHeader* header) @@ -677,13 +673,7 @@ s32 Wad_Install(FILE *fp) if (ret != 1) goto err; - if (!__Wad_FixTicket(p_tik)) - { - printf("\n This WAD is for the vWii (Wii U) only.\n\n"); - - ret = -999; - goto err; - } + bool isvWiiTitle = __Wad_FixTicket(p_tik); offset += round_up(header->tik_len, 64); @@ -699,204 +689,222 @@ s32 Wad_Install(FILE *fp) /* Get TMD info */ tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd); - - if(TITLE_LOWER(tmd_data->sys_version) != 0 && isIOSstub(TITLE_LOWER(tmd_data->sys_version))) + + if (TITLE_UPPER(tmd_data->sys_version) == 0) // IOS { - printf("\n This Title wants IOS%i but the installed version\n is a stub.\n", TITLE_LOWER(tmd_data->sys_version)); - ret = -1036; - goto err; - } - - if(tid == get_title_ios(TITLE_ID(1, 2))) - { - if (tmdIsStubIOS(tmd_data)) + if (isvWiiTitle && !IS_WIIU) { - printf("\n I won't install a stub System Menu IOS\n"); + printf("\n Cannot install vWii IOS on Wii.\n"); ret = -999; goto err; } - else if ((tid == TITLE_ID(1, 70) || tid == TITLE_ID(1, 80))) + if(tid == get_title_ios(TITLE_ID(1, 2))) { - /* Check build tag here */ - } - } - - if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'K'))) - { - if (tmdIsStubIOS(tmd_data)) - { - printf("\n I won't install a stub EULA IOS\n"); - ret = -999; - goto err; - } - } - - if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'K'))) - { - if (tmdIsStubIOS(tmd_data)) - { - printf("\n I won't install a stub rgnsel IOS\n"); - ret = -999; - goto err; - } - } - if (tid == get_title_ios(TITLE_ID(0x10001, 0x48415858)) || tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449))) - { - if (tmdIsStubIOS(tmd_data)) - { - printf("\n Are you sure you wan't to install a stub HBC IOS?\n"); - printf("\n Press A to continue.\n"); - printf(" Press B skip."); - - u32 buttons = WaitButtons(); - - if (!(buttons & WPAD_BUTTON_A)) + if (tmdIsStubIOS(tmd_data)) { - ret = -998; + printf("\n I won't install a stub System Menu IOS\n"); + ret = -999; + goto err; + } + + else if (tid == TITLE_ID(1, 70) || tid == TITLE_ID(1, 80)) + { + /* Check build tag here */ + } + } + + if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'E')) + || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'P')) + || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'J')) + || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'K'))) + { + if (tmdIsStubIOS(tmd_data)) + { + printf("\n I won't install a stub EULA IOS\n"); + ret = -999; goto err; } } + + if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'E')) + || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'P')) + || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'J')) + || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'K'))) + { + if (tmdIsStubIOS(tmd_data)) + { + printf("\n I won't install a stub rgnsel IOS\n"); + ret = -999; + goto err; + } + } + if (tid == get_title_ios(TITLE_ID(0x10001, 0x48415858)) || tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449))) + { + if (tmdIsStubIOS(tmd_data)) + { + printf("\n Are you sure you wan't to install a stub HBC IOS?\n"); + printf("\n Press A to continue.\n"); + printf(" Press B skip."); + + u32 buttons = WaitButtons(); + + if (!(buttons & WPAD_BUTTON_A)) + { + ret = -998; + goto err; + } + } + } } - - if (tid == TITLE_ID(1, 2)) + else // not IOS { - if (skipRegionSafetyCheck || gForcedInstall) - goto skipChecks; - - char region = 0; - u16 version = 0; - - GetSysMenuRegion(&version, ®ion); - - if (tmd_data->vwii_title) + if (isIOSstub(TITLE_LOWER(tmd_data->sys_version))) { - printf("\n I won't install a vWii SM by default.\n\n"); - printf("\n If you're really sure what you're doing, next time\n"); - printf(" select your device using Konami...\n\n"); - - ret = -999; + printf("\n This Title wants IOS%i but the installed version\n is a stub.\n", TITLE_LOWER(tmd_data->sys_version)); + ret = -1036; goto err; } - if(region == 0) + + + if (tid == TITLE_ID(1, 2)) { - printf("\n Unknown System menu region\n Please check the site for updates\n"); + if (skipRegionSafetyCheck || gForcedInstall) + goto skipChecks; + + char region = 0; + u16 version = 0; + + GetSysMenuRegion(&version, ®ion); - ret = -999; - goto err; - } + if (isvWiiTitle || tmd_data->vwii_title) // && !IS_WIIU ? :thinking: + { + printf("\n I won't install a vWii SM by default.\n\n"); + printf("\n If you're really sure what you're doing, next time\n"); + printf(" select your device using Konami...\n\n"); - if (!VersionIsOriginal(tmd_data->title_version)) - { - printf("\n I won't install an unkown SM versions by default.\n\n"); - printf("\n Are you installing a tweaked system menu?\n"); - printf("\n If you're really sure what you're doing, next time\n"); - printf(" select your device using Konami...\n\n"); - - ret = -999; - goto err; - } - - if(region != RegionLookupTable[(tmd_data->title_version & 0x0F)]) - { - printf("\n I won't install the wrong regions SM by default.\n\n"); - printf("\n Are you region changing?\n"); - printf("\n If you're really sure what you're doing, next time\n"); - printf(" select your device using Konami...\n\n"); + ret = -999; + goto err; + } - ret = -999; - goto err; - } + if(region == 0) + { + printf("\n Unknown System menu region\n Please check the site for updates\n"); + + ret = -999; + goto err; + } + if (!VersionIsOriginal(tmd_data->title_version)) + { + printf("\n I won't install an unkown SM versions by default.\n\n"); + printf("\n Are you installing a tweaked system menu?\n"); + printf("\n If you're really sure what you're doing, next time\n"); + printf(" select your device using Konami...\n\n"); + ret = -999; + goto err; + } + + if(region != RegionLookupTable[(tmd_data->title_version & 0x0F)]) + { + printf("\n I won't install the wrong regions SM by default.\n\n"); + printf("\n Are you region changing?\n"); + printf("\n If you're really sure what you're doing, next time\n"); + printf(" select your device using Konami...\n\n"); + + ret = -999; + goto err; + } + + if ((tmd_data->title_version & 0x1F) != 0x6 // 0x6 = KR + && (tmd_data->title_version >> 5) >= 15) // 4.2 or later + { + cIOSInfo ios_info; + + if (!Sys_GetcIOSInfo(TITLE_LOWER(tmd_data->sys_version), &ios_info) || + (ios_info.ios_base != 60 && ES_CheckHasKoreanKey())) + { + printf("\n" + " Installing this System menu will brick your Wii.\n" + " Please remove the Korean key via KoreanKii,\n" + " then try again.\n\n" + ); + + ret = -999; + goto err; + } + } skipChecks: - /* Put this before or after skipChecks? */ - if ((tmd_data->title_version & 0x1F) != 0x6 // 0x6 = KR - && (tmd_data->title_version >> 5) >= 15) // 4.2 or later - { - cIOSInfo ios_info; - - if (!Sys_GetcIOSInfo(TITLE_LOWER(tmd_data->sys_version), &ios_info) || - (ios_info.ios_base != 60 && ES_CheckHasKoreanKey())) + if (tmd_data->title_version < 416) { - printf("\n" - " Installing this System menu will brick your Wii.\n" - " Please remove the Korean key via KoreanKii,\n" - " then try again.\n\n" - ); - - ret = -999; - goto err; - } - } - if (tmd_data->title_version < 416) - { - if(boot2version == 4) - { - printf("\n This version of the System Menu\n is not compatible with your Wii\n"); - ret = -999; - goto err; - } - } - - if (!gForcedInstall && AHBPROT_DISABLED && IsPriiloaderInstalled()) - { - cleanupPriiloader = true; - printf("\n Priiloader is installed next to the system menu.\n\n"); - printf(" It is recommended to retain Priiloader as it can\n"); - printf(" protect your console from being bricked.\n\n"); - printf(" Press A to retain Priiloader or B to remove."); - - u32 buttons = WaitButtons(); - - if ((buttons & WPAD_BUTTON_A)) - { - retainPriiloader = (BackUpPriiloader() && CompareHashes(true)); - if (retainPriiloader) + if(boot2version == 4) { - SetPriiloaderOption(true); - Con_ClearLine(); - printf("\r[+] Priiloader will be retained.\n"); - fflush(stdout); + printf("\n This version of the System Menu\n is not compatible with your Wii\n"); + ret = -999; + goto err; } - else + } + + if (!gForcedInstall && AHBPROT_DISABLED && IsPriiloaderInstalled()) + { + cleanupPriiloader = true; + printf("\n Priiloader is installed next to the system menu.\n\n"); + printf(" It is recommended to retain Priiloader as it can\n"); + printf(" protect your console from being bricked.\n\n"); + printf(" Press A to retain Priiloader or B to remove."); + + u32 buttons = WaitButtons(); + + if ((buttons & WPAD_BUTTON_A)) { - Con_ClearLine(); - printf("\r Couldn't backup Priiloader.\n"); - fflush(stdout); - printf("\n Press A to continue or B to skip"); - - u32 buttons = WaitButtons(); - - if (!(buttons & WPAD_BUTTON_A)) + retainPriiloader = (BackUpPriiloader() && CompareHashes(true)); + if (retainPriiloader) { - ret = -990; - goto err; + SetPriiloaderOption(true); + Con_ClearLine(); + printf("\r[+] Priiloader will be retained.\n"); + fflush(stdout); + } + else + { + Con_ClearLine(); + printf("\r Couldn't backup Priiloader.\n"); + fflush(stdout); + printf("\n Press A to continue or B to skip"); + + u32 buttons = WaitButtons(); + + if (!(buttons & WPAD_BUTTON_A)) + { + ret = -990; + goto err; + } } } - } - if (!retainPriiloader) + if (!retainPriiloader) + { + SetPriiloaderOption(false); + Con_ClearLine(); + printf("\r[+] Priiloader will be removed.\n"); + fflush(stdout); + } + } + else { SetPriiloaderOption(false); - Con_ClearLine(); - printf("\r[+] Priiloader will be removed.\n"); - fflush(stdout); } } - else + + if (gForcedInstall) { - SetPriiloaderOption(false); + gForcedInstall = false; + cleanupPriiloader = true; } } - - if (gForcedInstall) - { - gForcedInstall = false; - cleanupPriiloader = true; - } printf("\t\t>> Installing ticket..."); fflush(stdout);