From bca2cac640e4aff69a97b919411855d0e4b305da Mon Sep 17 00:00:00 2001 From: Matthew Parlane Date: Tue, 29 Jan 2013 01:18:53 +1300 Subject: [PATCH] keys.bin support added. Remove hollywood id from config. Tidy HLE_Device_es.h (maybe) Added const params to crypto stuff. --- Source/Core/Common/Src/Crypto/ec.cpp | 8 +- Source/Core/Common/Src/Crypto/tools.h | 6 +- Source/Core/Core/Src/ConfigManager.cpp | 2 - Source/Core/Core/Src/ConfigManager.h | 1 - .../Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp | 40 ++----- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h | 18 +-- .../Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp | 5 +- Source/Core/Core/Src/ec_wii.cpp | 62 +++++++++- Source/Core/Core/Src/ec_wii.h | 108 +++++++++++++++++- 9 files changed, 193 insertions(+), 57 deletions(-) diff --git a/Source/Core/Common/Src/Crypto/ec.cpp b/Source/Core/Common/Src/Crypto/ec.cpp index 08a632ff7a..e94bb4e3d2 100644 --- a/Source/Core/Common/Src/Crypto/ec.cpp +++ b/Source/Core/Common/Src/Crypto/ec.cpp @@ -40,7 +40,7 @@ static u8 ec_G[60] = printf("\n"); }*/ -static void elt_copy(u8 *d, u8 *a) +static void elt_copy(u8 *d, const u8 *a) { memcpy(d, a, 30); } @@ -303,7 +303,7 @@ static void point_add(u8 *r, u8 *p, u8 *q) elt_add(ry, s, rx); } -void point_mul(u8 *d, u8 *a, u8 *b) // a is bignum +void point_mul(u8 *d, const u8 *a, u8 *b) // a is bignum { u32 i; u8 mask; @@ -330,7 +330,7 @@ void silly_random(u8 * rndArea, u8 count) } } -void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash) +void generate_ecdsa(u8 *R, u8 *S, const u8 *k, u8 *hash) { u8 e[30]; u8 kk[30]; @@ -394,7 +394,7 @@ int check_ecdsa(u8 *Q, u8 *R, u8 *S, u8 *hash) return (bn_compare(r1, R, 30) == 0); } -void ec_priv_to_pub(u8 *k, u8 *Q) +void ec_priv_to_pub(const u8 *k, u8 *Q) { point_mul(Q, k, ec_G); } diff --git a/Source/Core/Common/Src/Crypto/tools.h b/Source/Core/Common/Src/Crypto/tools.h index e3b5dcce58..ef4f8efc80 100644 --- a/Source/Core/Common/Src/Crypto/tools.h +++ b/Source/Core/Common/Src/Crypto/tools.h @@ -13,10 +13,10 @@ void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n); void bn_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n); void bn_inv(u8 *d, u8 *a, u8 *N, u32 n); // only for prime N void bn_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en); -void point_mul(u8 *d, u8 *a, u8 *b); +void point_mul(u8 *d, const u8 *a, u8 *b); -void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash); +void generate_ecdsa(u8 *R, u8 *S, const u8 *k, u8 *hash); -void ec_priv_to_pub(u8 *k, u8 *Q); +void ec_priv_to_pub(const u8 *k, u8 *Q); #endif diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index a9f92c62e5..e67effd607 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -157,7 +157,6 @@ void SConfig::SaveSettings() ini.Set("General", "RecursiveGCMPaths", m_RecursiveISOFolder); ini.Set("General", "NANDRoot", m_NANDPath); ini.Set("General", "WirelessMac", m_WirelessMac); - ini.Set("General", "HollywoodID", m_HollywoodID); #ifdef USE_GDBSTUB ini.Set("General", "GDBPort", m_LocalCoreStartupParameter.iGDBPort); #endif @@ -307,7 +306,6 @@ void SConfig::LoadSettings() DiscIO::cUIDsys::AccessInstance().UpdateLocation(); DiscIO::CSharedContent::AccessInstance().UpdateLocation(); ini.Get("General", "WirelessMac", &m_WirelessMac); - ini.Get("General", "HollywoodID", &m_HollywoodID, "0x21FFFFF"); } { diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index 6b18cef110..e92d29ee65 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -89,7 +89,6 @@ struct SConfig : NonCopyable int m_ListSort2; std::string m_WirelessMac; - std::string m_HollywoodID; bool m_PauseMovie; bool m_ShowLag; std::string m_strMovieAuthor; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 2c844db0c8..4d10077e6b 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -60,7 +60,8 @@ #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "../Movie.h" -#include +#include "ec_wii.h" + #ifdef _WIN32 #include #endif @@ -103,15 +104,6 @@ void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile) m_ContentFile = _rContentFile; } -u32 CWII_IPC_HLE_Device_es::GetHollywoodID() -{ - unsigned int HollywoodID = 0; - std::stringstream ss; - ss << std::hex << SConfig::GetInstance().m_HollywoodID; - ss >> HollywoodID; - return HollywoodID; -} - bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode) { m_pContentLoader = &DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); @@ -184,9 +176,10 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) case IOCTL_ES_GETDEVICEID: { _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETDEVICEID no out buffer"); - - INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICEID %s", SConfig::GetInstance().m_HollywoodID.c_str()); - Memory::Write_U32(GetHollywoodID(), Buffer.PayloadBuffer[0].m_Address); + + EcWii &ec = EcWii::GetInstance(); + INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICEID %08X", ec.getNgId()); + Memory::Write_U32(ec.getNgId(), Buffer.PayloadBuffer[0].m_Address); Memory::Write_U32(0, _CommandAddress + 0x4); return true; } @@ -859,36 +852,23 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) { WARN_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICECERT"); _dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1); - - std::string path = File::GetUserPath(D_WIIUSER_IDX) + "clientcert.bin"; - u8* destination = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); - u32 size = Buffer.PayloadBuffer[0].m_Size; - if (File::Exists(path)) - { - File::IOFile(path, "rb").ReadBytes(destination, size); - } - else - { - ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETDEVICECERT failed: no cert found."); - - } + EcWii &ec = EcWii::GetInstance(); + get_ng_cert(destination, ec.getNgId(), ec.getNgKeyId(), ec.getNgPriv(), ec.getNgSig()); - Memory::Write_U32(0, _CommandAddress + 0x4); break; } case IOCTL_ES_SIGN: { - WARN_LOG(WII_IPC_ES, "IOCTL_ES_SIGN"); u8 *ap_cert_out = Memory::GetPointer(Buffer.PayloadBuffer[1].m_Address); u8 *data = Memory::GetPointer(Buffer.InBuffer[0].m_Address); u32 data_size = Buffer.InBuffer[0].m_Size; u8 *sig_out = Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); - - get_ap_sig_and_cert(sig_out, ap_cert_out, m_TitleID, data, data_size, key_ecc, GetHollywoodID()); + EcWii &ec = EcWii::GetInstance(); + get_ap_sig_and_cert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.getNgPriv(), ec.getNgId()); break; } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h index e07c1e9001..5e148b7478 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h @@ -31,7 +31,6 @@ public: virtual ~CWII_IPC_HLE_Device_es(); void LoadWAD(const std::string& _rContentFile); - static u32 GetHollywoodID(); virtual bool Open(u32 _CommandAddress, u32 _Mode); @@ -49,16 +48,16 @@ private: IOCTL_ES_ADDTICKET = 0x01, IOCTL_ES_ADDTITLESTART = 0x02, IOCTL_ES_ADDCONTENTSTART = 0x03, - IOCTL_ES_ADDCONTENTDATA = 0x04, + IOCTL_ES_ADDCONTENTDATA = 0x04, IOCTL_ES_ADDCONTENTFINISH = 0x05, - IOCTL_ES_ADDTITLEFINISH = 0x06, + IOCTL_ES_ADDTITLEFINISH = 0x06, IOCTL_ES_GETDEVICEID = 0x07, IOCTL_ES_LAUNCH = 0x08, IOCTL_ES_OPENCONTENT = 0x09, IOCTL_ES_READCONTENT = 0x0A, IOCTL_ES_CLOSECONTENT = 0x0B, IOCTL_ES_GETOWNEDTITLECNT = 0x0C, - IOCTL_ES_GETOWNEDTITLES = 0x0D, + IOCTL_ES_GETOWNEDTITLES = 0x0D, IOCTL_ES_GETTITLECNT = 0x0E, IOCTL_ES_GETTITLES = 0x0F, IOCTL_ES_GETTITLECONTENTSCNT = 0x10, @@ -67,7 +66,7 @@ private: IOCTL_ES_GETVIEWS = 0x13, IOCTL_ES_GETTMDVIEWCNT = 0x14, IOCTL_ES_GETTMDVIEWS = 0x15, - IOCTL_ES_GETCONSUMPTION = 0x16, + IOCTL_ES_GETCONSUMPTION = 0x16, IOCTL_ES_DELETETITLE = 0x17, IOCTL_ES_DELETETICKET = 0x18, // IOCTL_ES_DIGETTMDVIEWSIZE = 0x19, @@ -79,20 +78,20 @@ private: IOCTL_ES_IMPORTBOOT = 0x1F, IOCTL_ES_GETTITLEID = 0x20, IOCTL_ES_SETUID = 0x21, - IOCTL_ES_DELETETITLECONTENT = 0x22, + IOCTL_ES_DELETETITLECONTENT = 0x22, IOCTL_ES_SEEKCONTENT = 0x23, IOCTL_ES_OPENTITLECONTENT = 0x24, // IOCTL_ES_LAUNCHBC = 0x25, - // IOCTL_ES_EXPORTTITLEINIT = 0x26, + // IOCTL_ES_EXPORTTITLEINIT = 0x26, // IOCTL_ES_EXPORTCONTENTBEGIN = 0x27, // IOCTL_ES_EXPORTCONTENTDATA = 0x28, // IOCTL_ES_EXPORTCONTENTEND = 0x29, - // IOCTL_ES_EXPORTTITLEDONE = 0x2A, + // IOCTL_ES_EXPORTTITLEDONE = 0x2A, IOCTL_ES_ADDTMD = 0x2B, IOCTL_ES_ENCRYPT = 0x2C, IOCTL_ES_DECRYPT = 0x2D, IOCTL_ES_GETBOOT2VERSION = 0x2E, - IOCTL_ES_ADDTITLECANCEL = 0x2F, + IOCTL_ES_ADDTITLECANCEL = 0x2F, IOCTL_ES_SIGN = 0x30, // IOCTL_ES_VERIFYSIGN = 0x31, IOCTL_ES_GETSTOREDCONTENTCNT = 0x32, @@ -102,6 +101,7 @@ private: IOCTL_ES_GETSHAREDCONTENTCNT = 0x36, IOCTL_ES_GETSHAREDCONTENTS = 0x37, IOCTL_ES_DELETESHAREDCONTENT = 0x38, + IOCTL_ES_CHECKKOREAREGION = 0x45, }; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp index b1e67714fc..fa4c98dac2 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_net.cpp @@ -55,6 +55,7 @@ it failed) #include "ICMP.h" #include "CommonPaths.h" #include "SettingsHandler.h" +#include "ec_wii.h" #ifdef _WIN32 @@ -195,7 +196,9 @@ bool CWII_IPC_HLE_Device_net_kd_request::IOCtl(u32 _CommandAddress) u8 area_code = GetAreaCode(area.c_str()); u8 id_ctr = config.IdGen(); u8 hardware_model = GetHardwareModel(model.c_str()); - u32 HollywoodID = CWII_IPC_HLE_Device_es::GetHollywoodID(); + + EcWii &ec = EcWii::GetInstance(); + u32 HollywoodID = ec.getNgId(); u64 UserID = 0; s32 ret = NWC24MakeUserID(&UserID, HollywoodID, id_ctr, hardware_model, area_code); diff --git a/Source/Core/Core/Src/ec_wii.cpp b/Source/Core/Core/Src/ec_wii.cpp index de1274a632..52deb0faa9 100644 --- a/Source/Core/Core/Src/ec_wii.cpp +++ b/Source/Core/Core/Src/ec_wii.cpp @@ -8,6 +8,7 @@ #include "Crypto/aes.h" #include "Crypto/sha1.h" #include "Crypto/tools.h" +#include "FileUtil.h" #include "ec_wii.h" static u32 default_NG_id = 0x0403AC68; @@ -37,7 +38,7 @@ static u8 default_NG_sig[] = { // NG_sig is the device-unique signature blob (from issuer) to use // if NG_priv iis NULL or NG_sig is NULL or NG_id is 0 or NG_key_id is 0, default values // will be used for all of them -void get_ng_cert(u8* ng_cert_out, u32 NG_id, u32 NG_key_id, u8* NG_priv, u8* NG_sig) +void get_ng_cert(u8* ng_cert_out, u32 NG_id, u32 NG_key_id, const u8* NG_priv, const u8* NG_sig) { char name[64]; if((NG_id==0)||(NG_key_id==0)||(NG_priv==NULL)||(NG_sig==NULL)) @@ -64,7 +65,7 @@ void get_ng_cert(u8* ng_cert_out, u32 NG_id, u32 NG_key_id, u8* NG_priv, u8* NG_ // NG_priv is the device-unique private key to use // NG_id is the device-unique id to use // if NG_priv is NULL or NG_id is 0, it will use builtin defaults -void get_ap_sig_and_cert(u8 *sig_out, u8 *ap_cert_out, u64 title_id, u8 *data, u32 data_size, u8 *NG_priv, u32 NG_id) +void get_ap_sig_and_cert(u8 *sig_out, u8 *ap_cert_out, u64 title_id, u8 *data, u32 data_size, const u8 *NG_priv, u32 NG_id) { u8 hash[20]; u8 ap_priv[30]; @@ -97,7 +98,7 @@ void get_ap_sig_and_cert(u8 *sig_out, u8 *ap_cert_out, u64 title_id, u8 *data, u generate_ecdsa(sig_out, sig_out + 30, ap_priv, hash); } -void make_blanksig_ec_cert(u8 *cert_out, const char *signer, const char *name, u8 *private_key, u32 key_id) +void make_blanksig_ec_cert(u8 *cert_out, const char *signer, const char *name, const u8 *private_key, u32 key_id) { memset(cert_out, 0, 0x180); *(u32*)cert_out = Common::swap32(0x10002); @@ -129,3 +130,58 @@ void get_shared_secret(u8* shared_secret_out, u8* remote_public_key, u8* NG_priv point_mul(shared_secret_out, NG_priv, remote_public_key); } + +EcWii::EcWii() +{ + bool init = true; + std::string keys_path = File::GetUserPath(D_WIIUSER_IDX) + "keys.bin"; + if (File::Exists(keys_path)) + { + File::IOFile keys_f(keys_path, "rb"); + if(keys_f.IsOpen()) + { + if(keys_f.ReadBytes(&BootMiiKeysBin, sizeof(BootMiiKeysBin))) + { + init = false; + + INFO_LOG(WII_IPC_ES, "Successfully loaded keys.bin created by: %s", BootMiiKeysBin.creator); + } + else + { + ERROR_LOG(WII_IPC_ES, "Failed to read keys.bin, check it is the correct size of %08lX bytes.", sizeof(BootMiiKeysBin)); + } + } + else + { + ERROR_LOG(WII_IPC_ES, "Failed to open keys.bin, maybe a permissions error or it is in use?"); + } + } + else + { + ERROR_LOG(WII_IPC_ES, "%s could not be found. Using default values. We recommend you grab keys.bin from BootMii.", keys_path.c_str()); + } + + if(init) + InitDefaults(); +} + +EcWii::~EcWii() +{ +} + +void EcWii::InitDefaults() +{ + memset(&BootMiiKeysBin, 0, sizeof(BootMiiKeysBin)); + + BootMiiKeysBin.ng_id = Common::swap32(default_NG_id); + BootMiiKeysBin.ng_key_id = Common::swap32(default_NG_key_id); + + memcpy(BootMiiKeysBin.ng_priv, default_NG_priv, sizeof(BootMiiKeysBin.ng_priv)); + memcpy(BootMiiKeysBin.ng_sig, default_NG_sig, sizeof(BootMiiKeysBin.ng_sig)); +} + +EcWii& EcWii::GetInstance() +{ + static EcWii m_Instance; + return(m_Instance); +} diff --git a/Source/Core/Core/Src/ec_wii.h b/Source/Core/Core/Src/ec_wii.h index 9cb9dcab1d..36aaf373a2 100644 --- a/Source/Core/Core/Src/ec_wii.h +++ b/Source/Core/Core/Src/ec_wii.h @@ -3,8 +3,108 @@ // Licensed under the terms of the GNU GPL, version 2 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt -void get_ng_cert(u8* ng_cert_out, u32 NG_id, u32 NG_key_id, u8* NG_priv, u8* NG_sig); -void get_ap_sig_and_cert(u8 *sig_out, u8 *ap_cert_out, u64 title_id, u8 *data, u32 data_size, u8 *NG_priv, u32 NG_id); +/* + * + * Structs for keys.bin taken from: + * + * mini - a Free Software replacement for the Nintendo/BroadOn IOS. + * crypto hardware support + * + * Copyright (C) 2008, 2009 Haxx Enterprises + * Copyright (C) 2008, 2009 Sven Peter + * Copyright (C) 2008, 2009 Hector Martin "marcan" + * + * # This code is licensed to you under the terms of the GNU GPL, version 2; + * # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + */ -void make_blanksig_ec_cert(u8 *cert_out, const char *signer, const char *name, u8 *private_key, u32 key_id); -void get_shared_secret(u8* shared_secret_out, u8* remote_public_key, u8* NG_priv); +#ifndef _ECWII_H +#define _ECWII_H + +#include "Common.h" +#include + +void get_ng_cert(u8* ng_cert_out, u32 NG_id, u32 NG_key_id, const u8* NG_priv, const u8* NG_sig); +void get_ap_sig_and_cert(u8 *sig_out, u8 *ap_cert_out, u64 title_id, u8 *data, u32 data_size, const u8 *NG_priv, u32 NG_id); + +void make_blanksig_ec_cert(u8 *cert_out, const char *signer, const char *name, const u8 *private_key, u32 key_id); +void get_shared_secret(u8* shared_secret_out, u8* remote_public_key, const u8* NG_priv); + + + +class EcWii +{ +public: + EcWii(); + ~EcWii(); + static EcWii& GetInstance(); + u32 getNgId() {return Common::swap32(BootMiiKeysBin.ng_id);} + u32 getNgKeyId() {return Common::swap32(BootMiiKeysBin.ng_key_id);} + const u8* getNgPriv() {return BootMiiKeysBin.ng_priv;} + const u8* getNgSig() {return BootMiiKeysBin.ng_sig;}; +private: + void InitDefaults(); + + #pragma pack(push,1) + typedef struct + { + u8 boot2version; + u8 unknown1; + u8 unknown2; + u8 pad; + u32 update_tag; + u16 checksum; + } +#ifndef _WIN32 + __attribute__((packed)) +#endif + eep_ctr_t; + + struct + { + u8 creator [0x100]; // 0x000 + u8 boot1_hash [ 0x14]; // 0x100 + u8 common_key [ 0x10]; // 0x114 + u32 ng_id; // 0x124 + union { + struct { + u8 ng_priv [ 0x1e]; // 0x128 + u8 pad1 [ 0x12]; + }; + struct { + u8 pad2 [ 0x1c]; + u8 nand_hmac [ 0x14]; //0x144 + }; + }; + u8 nand_key [ 0x10]; //0x158 + u8 rng_key [ 0x10]; //0x168 + u32 unk1; //0x178 + u32 unk2; //0x17C + u8 eeprom_pad [ 0x80]; //0x180 + + u32 ms_id; //0x200 + u32 ca_id; //0x204 + u32 ng_key_id; //0x208 + u8 ng_sig [ 0x3c]; //0x20c + eep_ctr_t counters [ 0x02]; //0x248 + u8 fill [ 0x18]; //0x25c + u8 korean_key [ 0x10]; //0x274 + u8 pad3 [ 0x74]; //0x284 + u16 prng_seed [ 0x02]; //0x2F8 + u8 pad4 [ 0x04]; //0x2FC + + u8 crack_pad [0x100]; //0x300 + + } + + #ifndef _WIN32 + __attribute__((packed)) + #endif + + BootMiiKeysBin; + + #pragma pack(pop) + +}; + +#endif