mirror of
https://github.com/shchmue/Lockpick.git
synced 2024-11-22 08:09:22 +01:00
Update for Hekate 4.8 + bis keys without master key
This commit is contained in:
parent
d4b4f868b1
commit
9deeefee9d
@ -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`.
|
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
|
What this software does differently
|
||||||
=
|
=
|
||||||
* Dumps `titlekeys` and SD seed
|
* Dumps `titlekeys` and SD seed
|
||||||
* Dumps all keys through `6.2.0`
|
* Dumps all keys through `6.2.0`
|
||||||
* Uses the superfast `xxHash` instead of `sha256` when searching exefs for keys for a ~5x speed improvement
|
* 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 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
|
Usage
|
||||||
=
|
=
|
||||||
|
@ -1,4 +1,11 @@
|
|||||||
# Changelog
|
# 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
|
## Version 1.2
|
||||||
* Update for libnx v2.0.0 compatibility and still runs when built with v1.6.0
|
* Update for libnx v2.0.0 compatibility and still runs when built with v1.6.0
|
||||||
* The binary got even smaller!
|
* The binary got even smaller!
|
||||||
|
@ -141,7 +141,9 @@ namespace Common {
|
|||||||
framebuf = (u32 *)gfxGetFramebuffer(&framebuf_width, NULL);
|
framebuf = (u32 *)gfxGetFramebuffer(&framebuf_width, NULL);
|
||||||
memset(framebuf, 0, gfxGetFramebufferSize());
|
memset(framebuf, 0, gfxGetFramebufferSize());
|
||||||
#endif
|
#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 * 0, 450, 42, FLAG_RED);
|
||||||
draw_set_rect(814, 452 + 42 * 1, 450, 42, FLAG_ORANGE);
|
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);
|
sbk = Key("secure_boot_key", 0x10, temp_key);
|
||||||
fclose(fuse_file);
|
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))
|
(std::string("tsec").compare(std::string(p.path().filename()).substr(0, 4)) == 0))
|
||||||
{
|
{
|
||||||
FILE *tsec_file = fopen(p.path().c_str(), "rb");
|
FILE *tsec_file = fopen(p.path().c_str(), "rb");
|
||||||
|
@ -369,10 +369,32 @@ void KeyCollection::derive_keys() {
|
|||||||
header_key = {"header_key", 0x20, {}};
|
header_key = {"header_key", 0x20, {}};
|
||||||
if (header_kek_source.found() && header_key_source.found()) {
|
if (header_kek_source.found() && header_key_source.found()) {
|
||||||
u8 tempheaderkek[0x10], tempheaderkey[0x20];
|
u8 tempheaderkek[0x10], tempheaderkey[0x20];
|
||||||
|
splCryptoInitialize();
|
||||||
splCryptoGenerateAesKek(header_kek_source.key.data(), 0, 0, tempheaderkek);
|
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);
|
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++) {
|
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)};
|
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";
|
char keynum[] = "00";
|
||||||
for (u8 i = 0; i < master_key.size(); i++) {
|
for (u8 i = 0; i < master_key.size(); i++) {
|
||||||
if (!master_key[i].found())
|
if (!master_key[i].found())
|
||||||
@ -467,11 +480,11 @@ void KeyCollection::save_keys() {
|
|||||||
aes_kek_generation_source.save_key(key_file);
|
aes_kek_generation_source.save_key(key_file);
|
||||||
aes_key_generation_source.save_key(key_file);
|
aes_key_generation_source.save_key(key_file);
|
||||||
bis_kek_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_00.save_key(key_file);
|
||||||
bis_key_source_01.save_key(key_file);
|
bis_key_source_01.save_key(key_file);
|
||||||
bis_key_source_02.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);
|
device_key.save_key(key_file);
|
||||||
eticket_rsa_kek.save_key(key_file);
|
eticket_rsa_kek.save_key(key_file);
|
||||||
for (auto k : es_keys)
|
for (auto k : es_keys)
|
||||||
@ -516,11 +529,11 @@ void KeyCollection::save_keys() {
|
|||||||
save_mac_kek_source.save_key(key_file);
|
save_mac_kek_source.save_key(key_file);
|
||||||
save_mac_key.save_key(key_file);
|
save_mac_key.save_key(key_file);
|
||||||
save_mac_key_source.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_kek_source.save_key(key_file);
|
||||||
sd_card_nca_key_source.save_key(key_file);
|
sd_card_nca_key_source.save_key(key_file);
|
||||||
sd_card_save_key_source.save_key(key_file);
|
sd_card_save_key_source.save_key(key_file);
|
||||||
sd_seed.save_key(key_file);
|
sd_seed.save_key(key_file);
|
||||||
|
sbk.save_key(key_file);
|
||||||
ssl_rsa_kek.save_key(key_file);
|
ssl_rsa_kek.save_key(key_file);
|
||||||
for (auto k : ssl_keys)
|
for (auto k : ssl_keys)
|
||||||
k->save_key(key_file);
|
k->save_key(key_file);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
/ and optional writing functions as well. */
|
/ 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.
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
/
|
/
|
||||||
/ 0: Basic functions are fully enabled.
|
/ 0: Basic functions are fully enabled.
|
||||||
|
@ -23,7 +23,6 @@ extern "C" void userAppInit()
|
|||||||
{
|
{
|
||||||
plInitialize();
|
plInitialize();
|
||||||
pmdmntInitialize();
|
pmdmntInitialize();
|
||||||
splCryptoInitialize();
|
|
||||||
splInitialize();
|
splInitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +30,6 @@ extern "C" void userAppExit()
|
|||||||
{
|
{
|
||||||
plExit();
|
plExit();
|
||||||
pmdmntExit();
|
pmdmntExit();
|
||||||
splCryptoExit();
|
|
||||||
splExit();
|
splExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user