mirror of
https://github.com/d0k3/GodMode9.git
synced 2026-05-31 06:46:56 +00:00
Dump cart ID2 properly in private header (#862)
* Add cart_id2 to gamecart.h This prepares changes to fix private header dumps. The name ID2 matches Lotus3 (see Switchbrew) since it's evident Lotus3 is just a continuation of the 3DS cart controller * Add Cart_GetID2() to protocol.h This prepares changes to fix private header dumps. The name ID2 matches Lotus3 (see Switchbrew) since it's evident Lotus3 is just a continuation of the 3DS cart controller. * gc protocol: Add support to get ID2 This renames the unknowna0_cmd to its proper name and the A0_Response to CartID2, matching Lotus3 terminology. * Store ID2 in private header at +0x44 The ID2 contains important information that in particular determines the cryptographic keys used. It is impossible to decrypt a dump of cart<->controller communications without knowing the ID2 or trying all possible keys. This behavior matches Gateway. I suppose that it was presumed that Gateway would always store zeroes there because regular cartridges on retail would always report zero and then everybody just copied this false assumption. * fix build (gamecart.c): memset->memcpy * fix build (protocol.c): Fix dupe definition of Cart_GetID()
This commit is contained in:
parent
9310455cac
commit
65b55f9d60
@ -22,6 +22,7 @@ typedef struct {
|
|||||||
u8 unused[0x4000 + 0x8000 - PRIV_HDR_SIZE]; // 0xFF
|
u8 unused[0x4000 + 0x8000 - PRIV_HDR_SIZE]; // 0xFF
|
||||||
u32 cart_type;
|
u32 cart_type;
|
||||||
u32 cart_id;
|
u32 cart_id;
|
||||||
|
u32 cart_id2;
|
||||||
u64 cart_size;
|
u64 cart_size;
|
||||||
u64 data_size;
|
u64 data_size;
|
||||||
u32 save_size;
|
u32 save_size;
|
||||||
@ -37,6 +38,7 @@ typedef struct {
|
|||||||
u8 modcrypt_area[0x4000];
|
u8 modcrypt_area[0x4000];
|
||||||
u32 cart_type;
|
u32 cart_type;
|
||||||
u32 cart_id;
|
u32 cart_id;
|
||||||
|
u32 cart_id2; // meaningless on TWL
|
||||||
u64 cart_size;
|
u64 cart_size;
|
||||||
u64 data_size;
|
u64 data_size;
|
||||||
u32 save_size;
|
u32 save_size;
|
||||||
@ -190,6 +192,7 @@ u32 InitCartRead(CartData* cdata) {
|
|||||||
// init, NCCH header
|
// init, NCCH header
|
||||||
static u32 sec_keys[4];
|
static u32 sec_keys[4];
|
||||||
u8* ncch_header = cdata->header + 0x1000;
|
u8* ncch_header = cdata->header + 0x1000;
|
||||||
|
cdata->cart_id2 = Cart_GetID2();
|
||||||
CTR_CmdReadHeader(ncch_header);
|
CTR_CmdReadHeader(ncch_header);
|
||||||
Cart_Secure_Init((u32*) (void*) ncch_header, sec_keys);
|
Cart_Secure_Init((u32*) (void*) ncch_header, sec_keys);
|
||||||
|
|
||||||
@ -214,7 +217,7 @@ u32 InitCartRead(CartData* cdata) {
|
|||||||
u8* priv_header = cdata->header + 0x4000;
|
u8* priv_header = cdata->header + 0x4000;
|
||||||
CTR_CmdReadUniqueID(priv_header);
|
CTR_CmdReadUniqueID(priv_header);
|
||||||
memcpy(priv_header + 0x40, &(cdata->cart_id), 4);
|
memcpy(priv_header + 0x40, &(cdata->cart_id), 4);
|
||||||
memset(priv_header + 0x44, 0x00, 4);
|
memcpy(priv_header + 0x44, &(cdata->cart_id2), 4);
|
||||||
memset(priv_header + 0x48, 0xFF, 8);
|
memset(priv_header + 0x48, 0xFF, 8);
|
||||||
|
|
||||||
// save data
|
// save data
|
||||||
|
|||||||
@ -23,6 +23,7 @@ typedef struct {
|
|||||||
u8 storage[0x8000]; // encrypted secure area + modcrypt area / unused
|
u8 storage[0x8000]; // encrypted secure area + modcrypt area / unused
|
||||||
u32 cart_type;
|
u32 cart_type;
|
||||||
u32 cart_id;
|
u32 cart_id;
|
||||||
|
u32 cart_id2; // crypto type, some special dev stuff, normally all-0 for retail
|
||||||
u64 cart_size;
|
u64 cart_size;
|
||||||
u64 data_size;
|
u64 data_size;
|
||||||
u32 save_size;
|
u32 save_size;
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
u32 CartID = 0xFFFFFFFFu;
|
u32 CartID = 0xFFFFFFFFu;
|
||||||
u32 CartType = 0;
|
u32 CartType = 0;
|
||||||
|
|
||||||
static u32 A0_Response = 0xFFFFFFFFu;
|
static u32 CartID2 = 0xFFFFFFFFu;
|
||||||
static u32 rand1 = 0;
|
static u32 rand1 = 0;
|
||||||
static u32 rand2 = 0;
|
static u32 rand2 = 0;
|
||||||
|
|
||||||
@ -85,6 +85,11 @@ u32 Cart_GetID(void)
|
|||||||
return CartID;
|
return CartID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 Cart_GetID2(void)
|
||||||
|
{
|
||||||
|
return CartID2;
|
||||||
|
}
|
||||||
|
|
||||||
void Cart_Init(void)
|
void Cart_Init(void)
|
||||||
{
|
{
|
||||||
ResetCardSlot(); //Seems to reset the cart slot?
|
ResetCardSlot(); //Seems to reset the cart slot?
|
||||||
@ -95,8 +100,8 @@ void Cart_Init(void)
|
|||||||
|
|
||||||
// 3ds
|
// 3ds
|
||||||
if (CartID & 0x10000000) {
|
if (CartID & 0x10000000) {
|
||||||
u32 unknowna0_cmd[2] = { 0xA0000000, 0x00000000 };
|
u32 getid2_cmd[2] = { 0xA0000000, 0x00000000 };
|
||||||
NTR_SendCommand(unknowna0_cmd, 0x4, 0, &A0_Response);
|
NTR_SendCommand(getid2_cmd, 0x4, 0, &CartID2);
|
||||||
|
|
||||||
NTR_CmdEnter16ByteMode();
|
NTR_CmdEnter16ByteMode();
|
||||||
SwitchToCTRCARD();
|
SwitchToCTRCARD();
|
||||||
@ -120,7 +125,7 @@ static u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignore
|
|||||||
|
|
||||||
//const u8 is_dev_unit = *(vu8*)0x10010010;
|
//const u8 is_dev_unit = *(vu8*)0x10010010;
|
||||||
//if(is_dev_unit) //Dev unit
|
//if(is_dev_unit) //Dev unit
|
||||||
const u8 is_dev_cart = (A0_Response&3)==3;
|
const u8 is_dev_cart = (CartID2&3)==3;
|
||||||
if(is_dev_cart) //Dev unit
|
if(is_dev_cart) //Dev unit
|
||||||
{
|
{
|
||||||
AES_SetKeyControl(0x11);
|
AES_SetKeyControl(0x11);
|
||||||
@ -180,7 +185,7 @@ void Cart_Secure_Init(u32 *buf, u32 *out)
|
|||||||
|
|
||||||
ARM_WaitCycles(0xF0000 * 8);
|
ARM_WaitCycles(0xF0000 * 8);
|
||||||
|
|
||||||
CTR_SetSecKey(A0_Response);
|
CTR_SetSecKey(CartID2);
|
||||||
CTR_SetSecSeed(out, true);
|
CTR_SetSecSeed(out, true);
|
||||||
|
|
||||||
rand1 = 0x42434445;//*((vu32*)0x10011000);
|
rand1 = 0x42434445;//*((vu32*)0x10011000);
|
||||||
@ -200,7 +205,7 @@ void Cart_Secure_Init(u32 *buf, u32 *out)
|
|||||||
const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 };
|
const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 };
|
||||||
CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2);
|
CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2);
|
||||||
|
|
||||||
if(test==CartID && test2==A0_Response)
|
if(test==CartID && test2==CartID2)
|
||||||
{
|
{
|
||||||
const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 };
|
const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 };
|
||||||
CTR_SendCommand(C5_cmd, 0, 1, 0x100002C, NULL);
|
CTR_SendCommand(C5_cmd, 0, 1, 0x100002C, NULL);
|
||||||
|
|||||||
@ -18,5 +18,6 @@
|
|||||||
void Cart_Init(void);
|
void Cart_Init(void);
|
||||||
int Cart_IsInserted(void);
|
int Cart_IsInserted(void);
|
||||||
u32 Cart_GetID(void);
|
u32 Cart_GetID(void);
|
||||||
|
u32 Cart_GetID2(void);
|
||||||
void Cart_Secure_Init(u32* buf, u32* out);
|
void Cart_Secure_Init(u32* buf, u32* out);
|
||||||
void Cart_Dummy(void);
|
void Cart_Dummy(void);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user