From 4932283d81f45bb096c3cdae12bcb1d2cbb0da4c Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Tue, 22 Sep 2020 18:51:33 -0400 Subject: [PATCH] Update to v1.1.11. --- Makefile | 2 +- README.md | 8 ++++++ source/keys.c | 79 +++++++++++++++++++++++++++------------------------ source/nca.c | 8 +++++- source/util.c | 2 +- 5 files changed, 59 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index cf556bb..08036c1 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ include $(DEVKITPRO)/libnx/switch_rules VERSION_MAJOR := 1 VERSION_MINOR := 1 -VERSION_MICRO := 10 +VERSION_MICRO := 11 APP_TITLE := nxdumptool APP_AUTHOR := DarkMatterCore diff --git a/README.md b/README.md index ea5fd36..c74f9cc 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,14 @@ Thanks to Changelog -------------- +**v1.1.11:** + +* Built using libnx `f01fb21`. +* The application will now only attempt to decrypt the eTicket device RSA keypair if the target title uses a ticket with personalized titlekey crypto, instead of always decrypting it regardless of the ticket crypto type. +* Fixed a NSP dumping issue where the decrypted titlekey wasn't being set for the current NCA if both the ticket and the decrypted titlekey were retrieved while parsing a previous NCA. Big thanks to [sadboys2001](https://github.com/sadboys2001) for reporting it. + +This is only a bugfix release. I don't expect to release any new versions until the rewrite is finished - the only exception being fixing some kind of feature-breaking bug. Please understand. + **v1.1.10:** * Built using libnx v3.1.0. diff --git a/source/keys.c b/source/keys.c index 2d34294..b4a08fe 100644 --- a/source/keys.c +++ b/source/keys.c @@ -930,6 +930,7 @@ int retrieveNcaTikTitleKey(nca_header_t *dec_nca_header, u8 *out_tik, u8 *out_en if (!foundRightsId || (rightsIdType != 1 && rightsIdType != 2)) { uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: NCA rights ID unavailable in this console!", __func__); + breaks++; ret = -2; return ret; } @@ -937,50 +938,53 @@ int retrieveNcaTikTitleKey(nca_header_t *dec_nca_header, u8 *out_tik, u8 *out_en // Load external keys if (!loadExternalKeys()) return ret; - if (!setcal_eticket_retrieved) + if (rightsIdType == 2) { - // Get extended eTicket RSA key from PRODINFO - memset(&eticket_data, 0, sizeof(SetCalRsa2048DeviceKey)); - - result = setcalInitialize(); - if (R_FAILED(result)) + if (!setcal_eticket_retrieved) { - uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to initialize the set:cal service! (0x%08X)", __func__, result); - return ret; + // Get extended eTicket RSA key from PRODINFO + memset(&eticket_data, 0, sizeof(SetCalRsa2048DeviceKey)); + + result = setcalInitialize(); + if (R_FAILED(result)) + { + uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: failed to initialize the set:cal service! (0x%08X)", __func__, result); + return ret; + } + + result = setcalGetEticketDeviceKey(&eticket_data); + + setcalExit(); + + if (R_FAILED(result)) + { + uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: setcalGetEticketDeviceKey failed! (0x%08X)", __func__, result); + return ret; + } + + // Decrypt eTicket RSA key + memcpy(ctr, eticket_data.key, ETICKET_DEVKEY_RSA_CTR_SIZE); + aes128CtrContextCreate(&eticket_aes_ctx, nca_keyset.eticket_rsa_kek, ctr); + aes128CtrCrypt(&eticket_aes_ctx, eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET, eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET, ETICKET_DEVKEY_RSA_SIZE); + + // Public exponent must use RSA-2048 SHA-1 signature method + // The value is stored use big endian byte order + if (__builtin_bswap32(*((u32*)(eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET + 0x200))) != SIGTYPE_RSA2048_SHA1) + { + uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid public RSA exponent for eTicket data! Wrong keys?\nTry running Lockpick_RCM to generate the keys file from scratch.", __func__); + return ret; + } } - result = setcalGetEticketDeviceKey(&eticket_data); + D = (eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET); + N = (eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET + 0x100); + E = (eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET + 0x200); - setcalExit(); - - if (R_FAILED(result)) + if (!setcal_eticket_retrieved) { - uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: setcalGetEticketDeviceKey failed! (0x%08X)", __func__, result); - return ret; + if (!testKeyPair(E, D, N)) return ret; + setcal_eticket_retrieved = true; } - - // Decrypt eTicket RSA key - memcpy(ctr, eticket_data.key, ETICKET_DEVKEY_RSA_CTR_SIZE); - aes128CtrContextCreate(&eticket_aes_ctx, nca_keyset.eticket_rsa_kek, ctr); - aes128CtrCrypt(&eticket_aes_ctx, eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET, eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET, ETICKET_DEVKEY_RSA_SIZE); - - // Public exponent must use RSA-2048 SHA-1 signature method - // The value is stored use big endian byte order - if (__builtin_bswap32(*((u32*)(eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET + 0x200))) != SIGTYPE_RSA2048_SHA1) - { - uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: invalid public RSA exponent for eTicket data! Wrong keys?\nTry running Lockpick_RCM to generate the keys file from scratch.", __func__); - return ret; - } - } - - D = (eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET); - N = (eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET + 0x100); - E = (eticket_data.key + ETICKET_DEVKEY_RSA_OFFSET + 0x200); - - if (!setcal_eticket_retrieved) - { - if (!testKeyPair(E, D, N)) return ret; - setcal_eticket_retrieved = true; } eTicketSave = calloc(1, sizeof(FIL)); @@ -1122,6 +1126,7 @@ int retrieveNcaTikTitleKey(nca_header_t *dec_nca_header, u8 *out_tik, u8 *out_en if (!foundEticket) { uiDrawString(STRING_X_POS, STRING_Y_POS(breaks), FONT_COLOR_ERROR_RGB, "%s: unable to find a matching eTicket entry for NCA rights ID!", __func__); + breaks++; ret = -2; return ret; } diff --git a/source/nca.c b/source/nca.c index 3f82d2c..36a3696 100644 --- a/source/nca.c +++ b/source/nca.c @@ -837,7 +837,13 @@ bool retrieveTitleKeyFromGameCardTicket(title_rights_ctx *rights_info, u8 *decry } // Check if the ticket has already been retrieved from the HFS0 partition in the gamecard - if (rights_info->retrieved_tik) return true; + if (rights_info->retrieved_tik) + { + // Save the decrypted NCA key area keys + memset(decrypted_nca_keys, 0, NCA_KEY_AREA_SIZE); + memcpy(decrypted_nca_keys + (NCA_KEY_AREA_KEY_SIZE * 2), rights_info->dec_titlekey, 0x10); + return true; + } // Load external keys if (!loadExternalKeys()) return false; diff --git a/source/util.c b/source/util.c index ecc75ce..06e0787 100644 --- a/source/util.c +++ b/source/util.c @@ -908,7 +908,7 @@ static bool initServices() initPmdmnt = true; /* Initialize pl service */ - result = plInitialize(); + result = plInitialize(PlServiceType_User); if (R_FAILED(result)) { consoleErrorScreen("%s: failed to initialize pl service! (0x%08X)", __func__, result);