diff --git a/README.md b/README.md index d3a7ed8..e8fec5b 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,15 @@ Lockpick = Lockpick is a ground-up C++17 rewrite of homebrew key derivation software, namely [kezplez-nx](https://github.com/tesnos/kezplez-nx). It also dumps titlekeys. This will dump all keys through `*_key_05` on firmwares below `6.2.0` and through `*_key_06` on `6.2.0`. +Due to key generation changes introduced in `7.0.0`, Lockpick is not able to dump keys ending in 07 at all. Furthermore, unfortunately the public method to dump `tsec_root_key` is only available on firmware `6.2.0` so `7.x` consoles can only dump through keys ending in 05. + What this software does differently = * Dumps `titlekeys` and SD seed * Dumps all keys through `6.2.0` * Uses the superfast `xxHash` instead of `sha256` when searching exefs for keys for a ~5x speed improvement * Gets all possible keys from running process memory - this means no need to decrypt `Package2` at all, let alone decompress `KIP`s -* Gets `header_key` without `tsec`, `sbk`, `master_key_00` or `aes` sources - which may or may not be the same way `ChoiDujourNX` does it :eyes: (and I'm gonna issue a challenge to homebrew title installers to implement similar code so you don't need your users to use separate software like this :stuck_out_tongue_winking_eye: it's up to you to figure out if the same can be done for `key_area_keys` if needed) +* Gets bis keys and `header_key` without `tsec`, `sbk`, `master_key_00` or `aes` sources. Shoutout to exelix11 for using this method in [SwitchThemeInjector](https://github.com/exelix11/SwitchThemeInjector)! Homebrew devs should be doing this instead of requiring users to provide key files! Usage = diff --git a/changelog.md b/changelog.md index 2710825..6a1aeab 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,11 @@ # Changelog +## Version 1.2.1 +* Generate bis keys without master keys +* Update file size check to support Hekate v4.8 TSEC dump +* Fixed prod.keys alphabetization error +* Fixed build warning for ff.c +* Added in-app disclaimer about which keys can be dumped + ## Version 1.2 * Update for libnx v2.0.0 compatibility and still runs when built with v1.6.0 * The binary got even smaller! diff --git a/source/Common.cpp b/source/Common.cpp index 41cc702..a77c0fe 100644 --- a/source/Common.cpp +++ b/source/Common.cpp @@ -141,7 +141,9 @@ namespace Common { framebuf = (u32 *)gfxGetFramebuffer(&framebuf_width, NULL); memset(framebuf, 0, gfxGetFramebufferSize()); #endif - draw_text(0x10, 0x020, YELLOW, "Lockpick! by shchmue"); + draw_text(0x010, 0x020, YELLOW, "Lockpick! by shchmue"); + draw_text(0x190, 0x020, YELLOW, "Note: Only dumps keys 00-06 on 6.2.0"); + draw_text(0x190, 0x040, YELLOW, " and keys 00-05 on all other firmwares including 7.0.0+"); draw_set_rect(814, 452 + 42 * 0, 450, 42, FLAG_RED); draw_set_rect(814, 452 + 42 * 1, 450, 42, FLAG_ORANGE); @@ -185,7 +187,7 @@ namespace Common { sbk = Key("secure_boot_key", 0x10, temp_key); fclose(fuse_file); } - else if (!tsec.found() && (p.file_size() == 0x30) && + else if (!tsec.found() && (p.file_size() == 0x20 || p.file_size() == 0x30) && (std::string("tsec").compare(std::string(p.path().filename()).substr(0, 4)) == 0)) { FILE *tsec_file = fopen(p.path().c_str(), "rb"); diff --git a/source/KeyCollection.cpp b/source/KeyCollection.cpp index ed87816..6ffe971 100644 --- a/source/KeyCollection.cpp +++ b/source/KeyCollection.cpp @@ -369,10 +369,32 @@ void KeyCollection::derive_keys() { header_key = {"header_key", 0x20, {}}; if (header_kek_source.found() && header_key_source.found()) { u8 tempheaderkek[0x10], tempheaderkey[0x20]; + splCryptoInitialize(); splCryptoGenerateAesKek(header_kek_source.key.data(), 0, 0, tempheaderkek); - splCryptoGenerateAesKey(tempheaderkek, header_key_source.key.data(), tempheaderkey); + splCryptoGenerateAesKey(tempheaderkek, header_key_source.key.data() + 0x00, tempheaderkey + 0x00); splCryptoGenerateAesKey(tempheaderkek, header_key_source.key.data() + 0x10, tempheaderkey + 0x10); - header_key = {"header_key", 0x20, byte_vector(&tempheaderkey[0], &tempheaderkey[0x20])}; + header_key = {"header_key", 0x20, byte_vector(tempheaderkey, tempheaderkey + 0x20)}; + splCryptoExit(); + } + + if (bis_key_source_00.found() && bis_key_source_01.found() && bis_key_source_02.found()) { + u8 tempbiskek[0x10], tempbiskey[0x20]; + splFsInitialize(); + splFsGenerateSpecificAesKey(bis_key_source_00.key.data() + 0x00, 0, 0, tempbiskey + 0x00); + splFsGenerateSpecificAesKey(bis_key_source_00.key.data() + 0x10, 0, 0, tempbiskey + 0x10); + bis_key.push_back(Key {"bis_key_00", 0x20, byte_vector(tempbiskey, tempbiskey + 0x20)}); + splFsExit(); + + splCryptoInitialize(); + splCryptoGenerateAesKek(bis_kek_source.key.data(), 0, 1, tempbiskek); + splCryptoGenerateAesKey(tempbiskek, bis_key_source_01.key.data() + 0x00, tempbiskey + 0x00); + splCryptoGenerateAesKey(tempbiskek, bis_key_source_01.key.data() + 0x10, tempbiskey + 0x10); + bis_key.push_back(Key {"bis_key_01", 0x20, byte_vector(tempbiskey, tempbiskey + 0x20)}); + splCryptoGenerateAesKey(tempbiskek, bis_key_source_02.key.data() + 0x00, tempbiskey + 0x00); + splCryptoGenerateAesKey(tempbiskek, bis_key_source_02.key.data() + 0x10, tempbiskey + 0x10); + bis_key.push_back(Key {"bis_key_02", 0x20, byte_vector(tempbiskey, tempbiskey + 0x20)}); + bis_key.push_back(Key {"bis_key_03", 0x20, bis_key[2].key}); + splCryptoExit(); } for (u8 i = 0; i < aes_kek_generation_source.key.size(); i++) { @@ -390,15 +412,6 @@ void KeyCollection::derive_keys() { save_mac_key = Key {"save_mac_key", 0x10, kek.aes_decrypt_ecb(save_mac_key_source.key)}; } - if (device_key.found()) { - Key kek = {device_key.aes_decrypt_ecb(retail_specific_aes_key_source.key), 0x10}; - bis_key.push_back(Key {"bis_key_00", 0x20, kek.aes_decrypt_ecb(bis_key_source_00.key)}); - kek = Key {bis_kek_source.generate_kek(device_key, aes_kek_generation_source, aes_key_generation_source), 0x10}; - bis_key.push_back(Key {"bis_key_01", 0x20, kek.aes_decrypt_ecb(bis_key_source_01.key)}); - bis_key.push_back(Key {"bis_key_02", 0x20, kek.aes_decrypt_ecb(bis_key_source_02.key)}); - bis_key.push_back(Key {"bis_key_03", 0x20, bis_key[2].key});\ - } - char keynum[] = "00"; for (u8 i = 0; i < master_key.size(); i++) { if (!master_key[i].found()) @@ -467,11 +480,11 @@ void KeyCollection::save_keys() { aes_kek_generation_source.save_key(key_file); aes_key_generation_source.save_key(key_file); bis_kek_source.save_key(key_file); + for (auto k : bis_key) + k.save_key(key_file); bis_key_source_00.save_key(key_file); bis_key_source_01.save_key(key_file); bis_key_source_02.save_key(key_file); - for (auto k : bis_key) - k.save_key(key_file); device_key.save_key(key_file); eticket_rsa_kek.save_key(key_file); for (auto k : es_keys) @@ -516,11 +529,11 @@ void KeyCollection::save_keys() { save_mac_kek_source.save_key(key_file); save_mac_key.save_key(key_file); save_mac_key_source.save_key(key_file); - sbk.save_key(key_file); sd_card_kek_source.save_key(key_file); sd_card_nca_key_source.save_key(key_file); sd_card_save_key_source.save_key(key_file); sd_seed.save_key(key_file); + sbk.save_key(key_file); ssl_rsa_kek.save_key(key_file); for (auto k : ssl_keys) k->save_key(key_file); diff --git a/source/fatfs/ffconf.h b/source/fatfs/ffconf.h index 50f641e..911069a 100644 --- a/source/fatfs/ffconf.h +++ b/source/fatfs/ffconf.h @@ -15,7 +15,7 @@ / and optional writing functions as well. */ -#define FF_FS_MINIMIZE 2 +#define FF_FS_MINIMIZE 1 /* This option defines minimization level to remove some basic API functions. / / 0: Basic functions are fully enabled. diff --git a/source/main.cpp b/source/main.cpp index 1095739..c98f2c6 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -23,7 +23,6 @@ extern "C" void userAppInit() { plInitialize(); pmdmntInitialize(); - splCryptoInitialize(); splInitialize(); } @@ -31,7 +30,6 @@ extern "C" void userAppExit() { plExit(); pmdmntExit(); - splCryptoExit(); splExit(); }