Skip to content

Commit 7519a22

Browse files
authored
Fix nand mounting on dev 3ds (#254)
* Fix nand mounting on dev 3ds * Fix bad Slot 3 Key Y for 3DS Dev TWL partition
1 parent f3160a7 commit 7519a22

File tree

4 files changed

+52
-11
lines changed

4 files changed

+52
-11
lines changed

arm7/source/main.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,17 @@ int main() {
146146
my_i2cWriteRegister(0x4A, 0x71, byteBak);
147147
}
148148

149-
if (isDSiMode() || ((REG_SCFG_EXT & BIT(17)) && (REG_SCFG_EXT & BIT(18)))) {
150-
u8 *out=(u8*)0x02F00000;
151-
memset(out, 0, 16);
149+
u8 *out=(u8*)0x02F00000;
150+
151+
if (isDSiMode()) {
152+
memset(out, 0, 17);
152153

154+
// Save whether this is a dev unit or not. For 3DS NAND reading...
155+
// This does not imply 32 MBs of RAM!
156+
out[16] = (*((uint16_t*)0x04004024)) & 0x13; // Is this a dev unit?
157+
}
158+
159+
if (isDSiMode() || ((REG_SCFG_EXT & BIT(17)) && (REG_SCFG_EXT & BIT(18)))) {
153160
// first check whether we can read the console ID directly and it was not hidden by SCFG
154161
if (((*(vu16*)0x04004000) & (1u << 10)) == 0 && ((*(vu8*)0x04004D08) & 0x1) == 0)
155162
{

arm9/source/crypto.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "sha1.h"
44
#include "crypto.h"
55
//#include "ticket0.h"
6+
#include "tonccpy.h"
67
#include "utils.h"
78

89
// more info:
@@ -13,6 +14,9 @@
1314
static const uint32_t DSi_NAND_KEY_Y[4] =
1415
{0x0ab9dc76u, 0xbd4dc4d3u, 0x202ddd1du, 0xe1a00005u};
1516

17+
static const uint32_t DSi_DEV_3DS_NAND_KEY_Y[4] =
18+
{0xf176bfaau, 0x66e8b87au, 0x266a6497u, 0xe1a00005u};
19+
1620
static const uint32_t DSi_ES_KEY_Y[4] =
1721
{0x8b5acce5u, 0x72c9d056u, 0xdce8179cu, 0xa9361239u};
1822

@@ -78,33 +82,56 @@ static inline void rol42_128(uint32_t *a){
7882
a[0] = (t3 << 10) | (t2 >> 22);
7983
}
8084

85+
void populate_dsi_nand_key_y(uint8_t *out, bool is_dev_3DS) {
86+
if(out == NULL)
87+
return;
88+
89+
const uint32_t* nand_key_y = DSi_NAND_KEY_Y;
90+
if(is_dev_3DS)
91+
nand_key_y = DSi_DEV_3DS_NAND_KEY_Y;
92+
93+
// This would not work in a Big Endian platform...
94+
tonccpy(out, nand_key_y, 16);
95+
}
96+
8197
static void dsi_aes_set_key(uint32_t *rk, const uint32_t *console_id, key_mode_t mode) {
8298
uint32_t key[4];
99+
const uint32_t* dsi_key_y = NULL;
83100
switch (mode) {
84101
case NAND:
85102
key[0] = console_id[0];
86103
key[1] = console_id[0] ^ 0x24ee6906;
87104
key[2] = console_id[1] ^ 0xe65b601d;
88105
key[3] = console_id[1];
106+
dsi_key_y = DSi_NAND_KEY_Y;
89107
break;
90108
case NAND_3DS:
91109
key[0] = console_id[0];
92110
key[1] = 0x544e494e;
93111
key[2] = 0x4f444e45;
94112
key[3] = console_id[1];
113+
dsi_key_y = DSi_NAND_KEY_Y;
114+
break;
115+
case NAND_DEV_3DS:
116+
key[0] = console_id[0];
117+
key[1] = 0xee7a4b1e;
118+
key[2] = 0xaf42c08b;
119+
key[3] = console_id[1];
120+
dsi_key_y = DSi_DEV_3DS_NAND_KEY_Y;
95121
break;
96122
case ES:
97123
key[0] = 0x4e00004a;
98124
key[1] = 0x4a00004e;
99125
key[2] = console_id[1] ^ 0xc80c4b72;
100126
key[3] = console_id[0];
127+
dsi_key_y = DSi_ES_KEY_Y;
101128
break;
102129
default:
103130
break;
104131
}
105132
// Key = ((Key_X XOR Key_Y) + FFFEFB4E295902582A680F5F1A4F3E79h) ROL 42
106133
// equivalent to F_XY in twltool/f_xy.c
107-
xor_128(key, key, mode == ES ? DSi_ES_KEY_Y : DSi_NAND_KEY_Y);
134+
xor_128(key, key, dsi_key_y);
108135
// iprintf("AES KEY: XOR KEY_Y:\n");
109136
// print_bytes(key, 16);
110137
add_128(key, DSi_KEY_MAGIC);
@@ -138,7 +165,7 @@ static uint32_t boot2_rk[RK_LEN];
138165

139166
static int tables_generated = 0;
140167

141-
void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS) {
168+
void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS, bool is_dev_3DS) {
142169
if (tables_generated == 0) {
143170
aes_gen_tables();
144171
tables_generated = 1;
@@ -148,7 +175,7 @@ void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int i
148175
GET_UINT32_BE(console_id[0], console_id_be, 4);
149176
GET_UINT32_BE(console_id[1], console_id_be, 0);
150177

151-
dsi_aes_set_key(nand_rk, console_id, is3DS ? NAND_3DS : NAND);
178+
dsi_aes_set_key(nand_rk, console_id, is_dev_3DS ? NAND_DEV_3DS : (is3DS ? NAND_3DS : NAND));
152179
dsi_aes_set_key(es_rk, console_id, ES);
153180

154181
aes_set_key_enc_128_be(boot2_rk, (uint8_t*)DSi_BOOT2_KEY);

arm9/source/crypto.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ typedef enum {
1414
typedef enum {
1515
NAND,
1616
NAND_3DS,
17+
NAND_DEV_3DS,
1718
ES
1819
} key_mode_t;
1920

21+
void populate_dsi_nand_key_y(uint8_t *out, bool is_dev_3DS);
22+
2023
int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len);
2124

22-
void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS);
25+
void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS, bool is_dev_3DS);
2326

2427
void dsi_nand_crypt_1(uint8_t *out, const uint8_t* in, u32 offset);
2528

arm9/source/nandio.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ static inline void nandio_set_fat_sig_fix(u32 offset) {
2424
fat_sig_fix_offset = offset;
2525
}
2626

27-
void getConsoleID(u8 *consoleID){
27+
void getConsoleID(u8 *consoleID, bool is_dev_3DS){
2828
u8 *fifo=(u8*)0x02F00000; //shared mem address that has our computed key3 stuff
2929
u8 key[16]; //key3 normalkey - keyslot 3 is used for DSi/twln NAND crypto
3030
u8 key_xy[16]; //key3_y ^ key3_x
3131
u8 key_x[16];////key3_x - contains a DSi console id (which just happens to be the LFCS on 3ds)
32-
u8 key_y[16] = {0x76, 0xDC, 0xB9, 0x0A, 0xD3, 0xC4, 0x4D, 0xBD, 0x1D, 0xDD, 0x2D, 0x20, 0x05, 0x00, 0xA0, 0xE1}; //key3_y NAND constant
32+
u8 key_y[16]; //key3_y NAND constant
3333

3434
u8 empty_buff[8] = {0};
3535

@@ -44,6 +44,8 @@ void getConsoleID(u8 *consoleID){
4444

4545
F_XY_reverse((uint32_t*)key, (uint32_t*)key_xy); //work backwards from the normalkey to get key_x that has the consoleID
4646

47+
populate_dsi_nand_key_y(key_y, is_dev_3DS);
48+
4749
for(int i=0;i<16;i++){
4850
key_x[i] = key_xy[i] ^ key_y[i]; //''
4951
}
@@ -114,21 +116,23 @@ bool nandio_startup() {
114116
if (!my_nand_Startup()) return false;
115117

116118
my_nand_ReadSectors(0, 1, sector_buf);
119+
uint8_t* fifo_is_dev = (uint8_t*)(0x02F00000 + 16);
117120
bool isDSi = parse_ncsd(sector_buf, 0) != 0;
121+
bool is_dev_3DS = (!isDSi) && *fifo_is_dev;
118122

119123
loadCid(isDSi);
120124

121125
u8 consoleID[8];
122126
u8 consoleIDfixed[8];
123127

124128
// Get ConsoleID
125-
getConsoleID(consoleID);
129+
getConsoleID(consoleID, is_dev_3DS);
126130
for (int i = 0; i < 8; i++) {
127131
consoleIDfixed[i] = consoleID[7-i];
128132
}
129133

130134
// iprintf("sector 0 is %s\n", is3DS ? "3DS" : "DSi");
131-
dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)0x2FFD7BC, !isDSi);
135+
dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)0x2FFD7BC, !isDSi, is_dev_3DS);
132136
dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE);
133137
parse_mbr(sector_buf, !isDSi, 0);
134138

0 commit comments

Comments
 (0)