Skip to content

Commit

Permalink
Update to v1.1.2.
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkMatterCore committed Jun 24, 2019
1 parent 655c856 commit 6d435a2
Show file tree
Hide file tree
Showing 11 changed files with 1,634 additions and 685 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ include $(DEVKITPRO)/libnx/switch_rules

VERSION_MAJOR := 1
VERSION_MINOR := 1
VERSION_MICRO := 1
VERSION_MICRO := 2

APP_TITLE := nxdumptool
APP_AUTHOR := MCMrARM, DarkMatterCore
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,26 @@ If you like my work and you'd like to support me in any way, it's not necessary,
Changelog
--------------

**v1.1.2:**
* Delta fragment NCAs are now included in update NSPs dumped from SD/eMMC if the "Generate ticket-less dump" option is disabled.
* It is now possible to generate ticket-less NSP dumps from bundled updates in gamecards. Please bear in mind that this option requires the external "sdmc:/switch/prod.keys" file.
* UI tweaks:
* The application now keeps track of the selected title in SD/eMMC and "orphan" content modes when entering a menu and then going back to the list.
* After selecting a title in the SD/eMMC menu, information about content already dumped related to the selected title will now be displayed (BASE / UPD / DLC).
* Likewise, after selecting a title in the "orphan" title list (Y button), an additional line will now display if the selected title has been dumped or not.
* This also informs the user if the dumps contain console-specific data.
* Three additional entries will now be displayed in the "orphan" title list.
* Upwards and downwards arrows will now be displayed for lists that exceed the max element count.
* Because of this change, max element count for the SD/eMMC title list had to be reduced from 4 to 3.
* Leftwards and rightwards arrowheads are now displayed in menus with options.
* A "hint" message is now displayed in the "orphan" content mode to let the user know they'll be able to find gamecard updates in that section.
* If a file has been already dumped, the application will display a prompt asking the user if they want to proceed anyway or not. This doesn't apply to full HFS0/ExeFS/RomFS data dumps.
* It is now possible to jump from the first list element to the last one and viceversa using the D-Pad Up/Down and Left Stick Up/Down. The Right Stick is still used exclusively for fast scrolling and won't be affected by this change.
* Fixed a bug where NSP/ExeFS/RomFS dumping would fail if the written entry count returned by `ncmContentMetaDatabaseListApplication()` didn't match the total entry count for the selected NSP dump type.
* Fixed a bug where NSP/ExeFS/RomFS dumping would fail if an invalid title index was used with `ncmContentMetaDatabaseGet()`.

Thanks to [Maschell](https://github.com/Maschell), [DuIslingr](https://github.com/DuIslingr) and MUXI from PSXTools forums for reporting these bugs and providing with testing!

**v1.1.1:**
* Project name changed to `nxdumptool`. This is no longer a gamecard-only tool.
* Added ExeFS dumping/browsing support. This feature, along with the already available RomFS options, makes the application an excellent tool for modders!
Expand Down
1,187 changes: 716 additions & 471 deletions source/dumper.c

Large diffs are not rendered by default.

65 changes: 36 additions & 29 deletions source/keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ bool findFSRodataKeys(keyLocation *location)
return true;
}

bool getNcaKeys()
bool loadMemoryKeys()
{
if (nca_keyset.memory_key_cnt > 0) return true;

Expand Down Expand Up @@ -630,7 +630,7 @@ int parse_hex_key(unsigned char *key, const char *hex, unsigned int len)
return 1;
}

int loadExternalKeys(FILE *f)
int readKeysFromFile(FILE *f)
{
u32 i;
int ret;
Expand Down Expand Up @@ -695,6 +695,38 @@ int loadExternalKeys(FILE *f)
return 1;
}

bool loadExternalKeys()
{
// Check if the keyset has been already loaded
if (nca_keyset.ext_key_cnt > 0) return true;

// Open keys file
FILE *keysFile = fopen(keysFilePath, "rb");
if (!keysFile)
{
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Error: unable to open \"%s\" to retrieve \"eticket_rsa_kek\", titlekeks and KAEKs!", keysFilePath);
uiDrawString(strbuf, 8, (breaks * (font_height + (font_height / 4))) + (font_height / 8), 255, 0, 0);
return false;
}

// Load keys
int ret = readKeysFromFile(keysFile);
fclose(keysFile);

if (ret < 1)
{
if (ret == -1)
{
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Error: unable to parse necessary keys from \"%s\"! (keys file empty?)", keysFilePath);
uiDrawString(strbuf, 8, (breaks * (font_height + (font_height / 4))) + (font_height / 8), 255, 0, 0);
}

return false;
}

return true;
}

bool testKeyPair(const void *E, const void *D, const void *N)
{
if (!E || !D || !N)
Expand Down Expand Up @@ -951,33 +983,8 @@ bool retrieveNcaTikTitleKey(nca_header_t *dec_nca_header, u8 *out_tik, u8 *out_e
return false;
}

// Retrieve external keys
if (!nca_keyset.ext_key_cnt)
{
// Open keys file
FILE *keysFile = fopen(keysFilePath, "rb");
if (!keysFile)
{
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Error: unable to open \"%s\" to retrieve \"eticket_rsa_kek\" and titlekeks!", keysFilePath);
uiDrawString(strbuf, 8, (breaks * (font_height + (font_height / 4))) + (font_height / 8), 255, 0, 0);
return false;
}

// Load keys
int ret = loadExternalKeys(keysFile);
fclose(keysFile);

if (ret < 1)
{
if (ret == -1)
{
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Error: unable to parse necessary keys from \"%s\"! (keys file empty?)", keysFilePath);
uiDrawString(strbuf, 8, (breaks * (font_height + (font_height / 4))) + (font_height / 8), 255, 0, 0);
}

return false;
}
}
// Load external keys
if (!loadExternalKeys()) return false;

// Decrypt eTicket RSA key
memcpy(ctr, eticket_data + ETICKET_DEVKEY_CTR_OFFSET, 0x10);
Expand Down
3 changes: 2 additions & 1 deletion source/keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ typedef struct {
u8 key_area_keys[0x20][3][0x10]; /* Key area encryption keys. */
} PACKED nca_keyset_t;

bool getNcaKeys();
bool loadMemoryKeys();
bool decryptNcaKeyArea(nca_header_t *dec_nca_header, u8 *out);
bool loadExternalKeys();
bool retrieveNcaTikTitleKey(nca_header_t *dec_nca_header, u8 *out_tik, u8 *out_enc_key, u8 *out_dec_key);
bool generateEncryptedNcaKeyAreaWithTitlekey(nca_header_t *dec_nca_header, u8 *decrypted_nca_keys);
bool readCertsFromApplicationRomFs();
Expand Down
10 changes: 6 additions & 4 deletions source/nca.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ void convertU64ToNcaSize(const u64 size, u8 out[0x6])

bool loadNcaKeyset()
{
// Keyset already loaded
// Check if the keyset has been already loaded
if (nca_keyset.total_key_cnt > 0) return true;

if (!(envIsSyscallHinted(0x60) && // svcDebugActiveProcess
Expand All @@ -221,7 +221,7 @@ bool loadNcaKeyset()
return false;
}

return getNcaKeys();
return loadMemoryKeys();
}

size_t aes128XtsNintendoCrypt(Aes128XtsContext *ctx, void *dst, const void *src, size_t size, u32 sector, bool encrypt)
Expand Down Expand Up @@ -297,7 +297,7 @@ bool processNcaCtrSectionBlock(NcmContentStorage *ncmStorage, const NcmNcaId *nc
if (R_FAILED(result = ncmContentStorageReadContentIdFile(ncmStorage, ncaId, block_start_offset, tmp_buf, block_size)))
{
free(tmp_buf);
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Error: ncmContentStorageReadContentIdFile failed for %lu bytes block at offset 0x%016lX from NCA \"%s\"! (0x%08X)", block_size, block_start_offset, nca_id, result);
snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to read encrypted %lu bytes block at offset 0x%016lX from NCA \"%s\"! (0x%08X)", block_size, block_start_offset, nca_id, result);
uiDrawString(strbuf, 8, (breaks * (font_height + (font_height / 4))) + (font_height / 8), 255, 0, 0);
return false;
}
Expand Down Expand Up @@ -481,6 +481,8 @@ bool decryptNcaHeader(const u8 *ncaBuf, u64 ncaBufSize, nca_header_t *out, title

memset(decrypted_nca_keys, 0, NCA_KEY_AREA_SIZE);
memcpy(decrypted_nca_keys + (NCA_KEY_AREA_KEY_SIZE * 2), rights_info->dec_titlekey, 0x10);

rights_info->retrieved_tik = true;
}
} else {
// Copy what we already have
Expand Down Expand Up @@ -2209,7 +2211,7 @@ bool generateNacpXmlFromNca(NcmContentStorage *ncmStorage, const NcmNcaId *ncaId

out:
// Manually free these pointers
// Calling freeRomFsContext() would also close the ncmStorage handle
// Calling freeRomFsContext() would also close the ncmStorage handle and the gamecard IStorage instance (if available)
free(romFsContext.romfs_dir_entries);
romFsContext.romfs_dir_entries = NULL;

Expand Down
1 change: 1 addition & 0 deletions source/nca.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ typedef struct {
u8 dec_titlekey[0x10];
u8 cert_data[ETICKET_CERT_FILE_SIZE];
rsa2048_sha256_ticket tik_data;
bool retrieved_tik;
} PACKED title_rights_ctx;

typedef struct {
Expand Down
Loading

0 comments on commit 6d435a2

Please sign in to comment.