2222#define PRINT_BLOCK (name , x ) RB3E_DEBUG(name ": %08x%08x%08x%08x", *(uint32_t *)&x[0], *(uint32_t *)&x[4], *(uint32_t *)&x[8], *(uint32_t *)&x[12])
2323
2424// to be filled in by the brainslug launcher
25- uint8_t RB3E_ConsolePRNGKey [0x10 ];
25+ uint8_t RB3E_ConsolePRNGKey [0x10 ] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
26+
27+ static uint8_t nullKey [] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
28+
29+ // This is really slow apparently
30+ void IOS_AES_Decrypt (uint8_t * input , uint8_t * key , uint8_t * iv , uint8_t * output )
31+ {
32+ static ios_fd_t aesFd = -1 ;
33+ if (aesFd == -1 )
34+ aesFd = IOS_Open ("/dev/aes" , IPC_OPEN_NONE );
35+
36+ ioctlv vec [4 ] __attribute__((align (32 )));
37+ // input vector
38+ vec [0 ].data = input ;
39+ vec [0 ].len = 0x10 ;
40+ vec [1 ].data = key ;
41+ vec [1 ].len = 0x10 ;
42+ // output vector
43+ vec [2 ].data = output ;
44+ vec [2 ].len = 0x10 ;
45+ vec [3 ].data = iv ;
46+ vec [3 ].len = 0x10 ;
47+ // decrypt
48+ IOS_Ioctlv (aesFd , 0x3 , 2 , 2 , vec );
49+ }
2650
2751uint64_t OSGetTime ();
2852uint64_t timeSpentInAES = 0 ;
@@ -78,13 +102,12 @@ void RB3E_CNTFileReadBlock(RB3E_CNTFileSD *file, int blockIndex)
78102 }
79103 time = OSGetTime ();
80104 // read and decrypt the current block
81- SD_read (file -> fd , file -> lastBlock , 0x10 );
105+ SD_read (file -> fd , file -> lastBlockEnc , 0x10 );
82106 timeSpentInSD += OSGetTime () - time ;
83107
84108 time = OSGetTime ();
85- memcpy (file -> lastBlockEnc , file -> lastBlock , 0x10 ); // keep a copy of the encrypted last block to use as the next IV
86- // TODO(Emma): can we use the hardware AES engine to make this faster?
87- // TODO(Emma): can we
109+ //memcpy(file->lastBlockEnc, file->lastBlock, 0x10); // keep a copy of the encrypted last block to use as the next IV
110+ memcpy (file -> lastBlock , file -> lastBlockEnc , 0x10 );
88111 AES_CBC_decrypt_buffer (file -> aesCtx , file -> lastBlock , 0x10 );
89112 timeSpentInAES += OSGetTime () - time ;
90113 file -> lastBlockIndex = blockIndex ;
@@ -162,7 +185,7 @@ static inline int getFlippedContent(uint8_t *contentFlags)
162185 return index ;
163186}
164187
165- RB3E_CNTFileSD * RB3E_OpenCNTFileSD (const char * filepath )
188+ RB3E_CNTFileSD * RB3E_OpenCNTFileSD (const char * filepath , unsigned long long titleid , unsigned int index )
166189{
167190 // open a handle to the file
168191 int fd = RB3E_OpenFile (filepath , 0 );
@@ -235,16 +258,17 @@ RB3E_CNTFileSD *RB3E_OpenCNTFileSD(const char *filepath)
235258 file -> startOffset = startOfData ;
236259 // try to decrypt it with the NULL PRNG key (sZA-sZG)
237260 RB3E_DEBUG ("Attempting to read with NULLed key" , NULL );
238- static uint8_t nullKey [] = {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
239261 PRINT_BLOCK ("Key" , nullKey );
240262 AES_init_ctx (file -> aesCtx , nullKey );
263+ memcpy (file -> aesKey , nullKey , 0x10 );
241264 RB3E_CNTFileReadBlock (file , 0 );
242265 if (* (uint32_t * )file -> lastBlock != ARC_MAGIC )
243266 {
244267 // that failed - try to decrypt it with the console-specific PRNG key (sZH+)
245268 RB3E_DEBUG ("Trying console specific PRNG key" , NULL );
246269 PRINT_BLOCK ("Key" , RB3E_ConsolePRNGKey );
247270 AES_init_ctx (file -> aesCtx , RB3E_ConsolePRNGKey );
271+ memcpy (file -> aesKey , RB3E_ConsolePRNGKey , 0x10 );
248272 file -> lastBlockIndex = -1 ;
249273 RB3E_CNTFileReadBlock (file , 0 );
250274 if (* (uint32_t * )file -> lastBlock != ARC_MAGIC )
@@ -278,10 +302,10 @@ RB3E_CNTFileSD *RB3E_OpenCNTFileSD(const char *filepath)
278302 {
279303 // untested, just try to handle the ARC file directly
280304 file -> aesCtx = NULL ;
281- file -> contentIndex = 0xFFFF ; // TODO(Emma): get this from the filename and a TMD file
305+ file -> contentIndex = index ;
282306 file -> contentLength = RB3E_FileSize (file -> fd );
283307 file -> startOffset = 0 ;
284- file -> titleId = 0x72423345 ; // 'rB3E'
308+ file -> titleId = ( uint32_t ) titleid ;
285309 // read the ARC file header into RAM
286310 u8_header_t archeader ;
287311 RB3E_CNTFileRead (file , 0 , (uint8_t * )& archeader , sizeof (u8_header_t ));
@@ -305,4 +329,100 @@ RB3E_CNTFileSD *RB3E_OpenCNTFileSD(const char *filepath)
305329 }
306330}
307331
332+ void ParseKeysFile (uint8_t * keys_data , size_t keys_len )
333+ {
334+ RB3E_DEBUG ("0x%x bytes key file" , keys_len );
335+ // check if its a BootMii-style keys.bin
336+ if (keys_len >= 0x400 && * (uint32_t * )& keys_data [0x114 ] == 0xEBE42A22 )
337+ {
338+ memcpy (RB3E_ConsolePRNGKey , keys_data + 0x168 , 0x10 );
339+ }
340+ // check if its an OTP file dump
341+ else if (keys_len >= 0x100 && * (uint32_t * )& keys_data [0x14 ] == 0xEBE42A22 )
342+ {
343+ memcpy (RB3E_ConsolePRNGKey , keys_data + 0x68 , 0x10 );
344+ }
345+ // check if its a straight up key
346+ else if (keys_len == 0x10 )
347+ {
348+ memcpy (RB3E_ConsolePRNGKey , keys_data , 0x10 );
349+ }
350+ else
351+ {
352+ RB3E_DEBUG ("FAILED TO LOAD KEY!" , NULL );
353+ return ;
354+ }
355+ PRINT_BLOCK ("Loaded Key" , RB3E_ConsolePRNGKey );
356+ }
357+
358+ void TryToLoadPRNGKeyFromFile ()
359+ {
360+ uint8_t keys_buffer [0x400 ]; // size of keys.bin file
361+
362+ // check if the loader already loaded a prng key
363+ if (memcmp (RB3E_ConsolePRNGKey , nullKey , 0x10 ) != 0 )
364+ {
365+ RB3E_DEBUG ("PRNG key loaded, not scanning for file" , NULL );
366+ return ;
367+ }
368+
369+ // DOLPHIN ONLY: try to load keys.bin from the NAND
370+ if (RB3E_IsEmulator ())
371+ {
372+ ios_fd_t nandfd = IOS_Open ("/keys.bin" , IPC_OPEN_READ );
373+ if (nandfd >= 0 )
374+ {
375+ RB3E_DEBUG ("Loading keys from NAND" , NULL );
376+ ios_ret_t readret = IOS_Read (nandfd , keys_buffer , sizeof (keys_buffer ));
377+ IOS_Close (nandfd );
378+ if (readret >= IPC_OK )
379+ {
380+ ParseKeysFile (keys_buffer , readret );
381+ }
382+ return ;
383+ }
384+ }
385+
386+ // try a few files on SD
387+ // PRNG key as binary
388+ if (RB3E_FileExists ("sd:/prng_key.bin" ))
389+ {
390+ int keysfd = RB3E_OpenFile ("sd:/prng_key.bin" , 0 );
391+ if (keysfd != -1 )
392+ {
393+ RB3E_DEBUG ("Loading keys from prng_key.bin" , NULL );
394+ int r = RB3E_ReadFile (keysfd , 0 , keys_buffer , 0x10 );
395+ RB3E_CloseFile (keysfd );
396+ ParseKeysFile (keys_buffer , r == 0x10 ? 0x10 : 0 );
397+ return ;
398+ }
399+ }
400+ // vWii/xyzzy OTP backup
401+ if (RB3E_FileExists ("sd:/otp.bin" ))
402+ {
403+ int otpfd = RB3E_OpenFile ("sd:/otp.bin" , 0 );
404+ if (otpfd != -1 )
405+ {
406+ RB3E_DEBUG ("Loading keys from otp.bin" , NULL );
407+ int r = RB3E_ReadFile (otpfd , 0 , keys_buffer , sizeof (keys_buffer ));
408+ RB3E_CloseFile (otpfd );
409+ ParseKeysFile (keys_buffer , r );
410+ return ;
411+ }
412+ }
413+ // BootMii/xyzzy keys.bin backup
414+ if (RB3E_FileExists ("sd:/keys.bin" ))
415+ {
416+ int keysfd = RB3E_OpenFile ("sd:/keys.bin" , 0 );
417+ if (keysfd != -1 )
418+ {
419+ RB3E_DEBUG ("Loading keys from keys.bin" , NULL );
420+ int r = RB3E_ReadFile (keysfd , 0 , keys_buffer , sizeof (keys_buffer ));
421+ RB3E_CloseFile (keysfd );
422+ ParseKeysFile (keys_buffer , r );
423+ return ;
424+ }
425+ }
426+ }
427+
308428#endif // RB3E_WII
0 commit comments