mirror of
https://github.com/Decscots/Lockpick_RCM
synced 2024-11-15 06:36:34 +00:00
Move key offsets to struct for cleaner code
This commit is contained in:
parent
1c82665901
commit
6ad7192199
3 changed files with 52 additions and 157 deletions
|
@ -22,20 +22,25 @@
|
||||||
#include "pkg1.h"
|
#include "pkg1.h"
|
||||||
#include "../sec/se.h"
|
#include "../sec/se.h"
|
||||||
|
|
||||||
|
#define HASH_ORDER_100_100 {2, 3, 4, 0, 5, 6, 1}
|
||||||
|
#define HASH_ORDER_200_510 {2, 3, 4, 0, 5, 7, 10, 12, 11, 6, 8, 1}
|
||||||
|
#define HASH_ORDER_600_620 {6, 5, 10, 7, 8, 2, 3, 4, 0, 12, 11, 1}
|
||||||
|
#define HASH_ORDER_700_9xx {6, 5, 10, 7, 8, 2, 3, 4, 0, 12, 11, 9, 1}
|
||||||
|
|
||||||
static const pkg1_id_t _pkg1_ids[] = {
|
static const pkg1_id_t _pkg1_ids[] = {
|
||||||
{ "20161121183008", 0 }, //1.0.0
|
{ "20161121183008", 0, {0x1b517, 0x125bc2, 1, 16, 6, HASH_ORDER_100_100, 0, 0x449dc} }, //1.0.0
|
||||||
{ "20170210155124", 0 }, //2.0.0 - 2.3.0
|
{ "20170210155124", 0, {0x1d226, 0x26fe, 0, 16, 11, HASH_ORDER_200_510, 0x557b, 0x3d41a} }, //2.0.0 - 2.3.0
|
||||||
{ "20170519101410", 1 }, //3.0.0
|
{ "20170519101410", 1, {0x1ffa6, 0x298b, 0, 16, 11, HASH_ORDER_200_510, 0x552d, 0x3cb81} }, //3.0.0
|
||||||
{ "20170710161758", 2 }, //3.0.1 - 3.0.2
|
{ "20170710161758", 2, {0x20026, 0x29ab, 0, 16, 11, HASH_ORDER_200_510, 0x552d, 0x3cb81} }, //3.0.1 - 3.0.2
|
||||||
{ "20170921172629", 3 }, //4.0.0 - 4.1.0
|
{ "20170921172629", 3, {0x1c64c, 0x37eb, 0, 16, 11, HASH_ORDER_200_510, 0x5382, 0x3711c} }, //4.0.0 - 4.1.0
|
||||||
{ "20180220163747", 4 }, //5.0.0 - 5.1.0
|
{ "20180220163747", 4, {0x1f3b4, 0x465b, 0, 16, 11, HASH_ORDER_200_510, 0x5a63, 0x37901} }, //5.0.0 - 5.1.0
|
||||||
{ "20180802162753", 5 }, //6.0.0 - 6.1.0
|
{ "20180802162753", 5, {0x27350, 0x17ff5, 1, 8, 11, HASH_ORDER_600_620, 0x5674, 0x1d5be} }, //6.0.0 - 6.1.0
|
||||||
{ "20181107105733", 6 }, //6.2.0
|
{ "20181107105733", 6, {0x27350, 0x17ff5, 1, 8, 11, HASH_ORDER_600_620, 0x5674, 0x1d5be} }, //6.2.0
|
||||||
{ "20181218175730", 7 }, //7.0.0
|
{ "20181218175730", 7, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_9xx, 0x5563, 0x1d437} }, //7.0.0
|
||||||
{ "20190208150037", 7 }, //7.0.1
|
{ "20190208150037", 7, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_9xx, 0x5563, 0x1d437} }, //7.0.1
|
||||||
{ "20190314172056", 7 }, //8.0.0 - 8.0.1
|
{ "20190314172056", 7, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_9xx, 0x5563, 0x1d437} }, //8.0.0 - 8.0.1
|
||||||
{ "20190531152432", 8 }, //8.1.0
|
{ "20190531152432", 8, {0x29c50, 0x6a73, 0, 8, 12, HASH_ORDER_700_9xx, 0x5563, 0x1d437} }, //8.1.0
|
||||||
{ "20190809135709", 9 }, //9.0.0 - 9.0.1
|
{ "20190809135709", 9, {0x2ec10, 0x5573, 0, 1, 12, HASH_ORDER_700_9xx, 0x6495, 0x1d807} }, //9.0.0 - 9.0.1
|
||||||
{ NULL } //End.
|
{ NULL } //End.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,23 @@
|
||||||
|
|
||||||
#include "../utils/types.h"
|
#include "../utils/types.h"
|
||||||
|
|
||||||
|
typedef struct _key_info_t
|
||||||
|
{
|
||||||
|
u32 start_offset;
|
||||||
|
u32 hks_offset;
|
||||||
|
bool hks_offset_is_from_end;
|
||||||
|
u32 alignment;
|
||||||
|
u32 hash_max;
|
||||||
|
u8 hash_order[13];
|
||||||
|
u32 es_offset;
|
||||||
|
u32 ssl_offset;
|
||||||
|
} key_info_t;
|
||||||
|
|
||||||
typedef struct _pkg1_id_t
|
typedef struct _pkg1_id_t
|
||||||
{
|
{
|
||||||
const char *id;
|
const char *id;
|
||||||
u32 kb;
|
u32 kb;
|
||||||
|
key_info_t key_info;
|
||||||
} pkg1_id_t;
|
} pkg1_id_t;
|
||||||
|
|
||||||
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
const pkg1_id_t *pkg1_identify(u8 *pkg1);
|
||||||
|
|
|
@ -453,96 +453,33 @@ get_tsec: ;
|
||||||
pkg2_decompress_kip(ki, 2 | 4); // we only need .rodata and .data
|
pkg2_decompress_kip(ki, 2 | 4); // we only need .rodata and .data
|
||||||
TPRINTFARGS("%kDecompress FS...", colors[(color_idx++) % 6]);
|
TPRINTFARGS("%kDecompress FS...", colors[(color_idx++) % 6]);
|
||||||
|
|
||||||
u8 hash_index = 0, hash_max = 11, hash_order[13],
|
u8 hash_index = 0;
|
||||||
key_lengths[13] = {0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x20, 0x20};
|
const u8 key_lengths[13] = {0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x20, 0x20};
|
||||||
u32 start_offset = 0, hks_offset_from_end = ki->kip1->sections[2].size_decomp, alignment = 0x10;
|
|
||||||
|
|
||||||
// the FS keys appear in different orders
|
|
||||||
if (!memcmp(pkg1_id->id, "2016", 4)) {
|
if (!memcmp(pkg1_id->id, "2016", 4)) {
|
||||||
// 1.0.0 doesn't have SD keys at all
|
// 1.0.0 doesn't have SD keys at all and the first key isn't aligned with the rest
|
||||||
hash_max = 6;
|
|
||||||
// the first key isn't aligned with the rest
|
|
||||||
memcpy(fs_keys[2], ki->kip1->data + ki->kip1->sections[0].size_comp + 0x1ae0e, 0x10);
|
memcpy(fs_keys[2], ki->kip1->data + ki->kip1->sections[0].size_comp + 0x1ae0e, 0x10);
|
||||||
hash_index = 1;
|
hash_index = 1;
|
||||||
start_offset = 0x1b517;
|
|
||||||
hks_offset_from_end = 0x125bc2;
|
|
||||||
u8 temp[7] = {2, 3, 4, 0, 5, 6, 1};
|
|
||||||
memcpy(hash_order, temp, 7);
|
|
||||||
} else {
|
|
||||||
// 2.0.0 - 8.0.0
|
|
||||||
switch (pkg1_id->kb) {
|
|
||||||
case KB_FIRMWARE_VERSION_100_200:
|
|
||||||
start_offset = 0x1d226;
|
|
||||||
hks_offset_from_end -= 0x26fe;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_300:
|
|
||||||
start_offset = 0x1ffa6;
|
|
||||||
hks_offset_from_end -= 0x298b;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_301:
|
|
||||||
start_offset = 0x20026;
|
|
||||||
hks_offset_from_end -= 0x29ab;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_400:
|
|
||||||
start_offset = 0x1c64c;
|
|
||||||
hks_offset_from_end -= 0x37eb;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_500:
|
|
||||||
start_offset = 0x1f3b4;
|
|
||||||
hks_offset_from_end -= 0x465b;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_600:
|
|
||||||
case KB_FIRMWARE_VERSION_620:
|
|
||||||
start_offset = 0x27350;
|
|
||||||
hks_offset_from_end = 0x17ff5;
|
|
||||||
alignment = 8;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_700:
|
|
||||||
case KB_FIRMWARE_VERSION_810:
|
|
||||||
start_offset = 0x29c50;
|
|
||||||
hks_offset_from_end -= 0x6a73;
|
|
||||||
alignment = 8;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_900:
|
|
||||||
start_offset = 0x2ec10;
|
|
||||||
hks_offset_from_end -= 0x5573;
|
|
||||||
alignment = 1; // RIP
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pkg1_id->kb <= KB_FIRMWARE_VERSION_500) {
|
|
||||||
u8 temp[12] = {2, 3, 4, 0, 5, 7, 10, 12, 11, 6, 8, 1};
|
|
||||||
memcpy(hash_order, temp, 12);
|
|
||||||
} else if (pkg1_id->kb <= KB_FIRMWARE_VERSION_620) {
|
|
||||||
u8 temp[12] = {6, 5, 10, 7, 8, 2, 3, 4, 0, 12, 11, 1};
|
|
||||||
memcpy(hash_order, temp, 12);
|
|
||||||
} else {
|
|
||||||
u8 temp[13] = {6, 5, 10, 7, 8, 2, 3, 4, 0, 12, 11, 9, 1};
|
|
||||||
memcpy(hash_order, temp, 13);
|
|
||||||
hash_max = 12;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 temp_hash[0x20];
|
u8 temp_hash[0x20];
|
||||||
for (u32 i = ki->kip1->sections[0].size_comp + start_offset; i < ki->size - 0x20; ) {
|
for (u32 i = ki->kip1->sections[0].size_comp + pkg1_id->key_info.start_offset; i < ki->size - 0x20; ) {
|
||||||
minerva_periodic_training();
|
minerva_periodic_training();
|
||||||
se_calc_sha256(temp_hash, ki->kip1->data + i, key_lengths[hash_order[hash_index]]);
|
se_calc_sha256(temp_hash, ki->kip1->data + i, key_lengths[pkg1_id->key_info.hash_order[hash_index]]);
|
||||||
if (!memcmp(temp_hash, fs_hashes_sha256[hash_order[hash_index]], 0x20)) {
|
if (!memcmp(temp_hash, fs_hashes_sha256[pkg1_id->key_info.hash_order[hash_index]], 0x20)) {
|
||||||
memcpy(fs_keys[hash_order[hash_index]], ki->kip1->data + i, key_lengths[hash_order[hash_index]]);
|
memcpy(fs_keys[pkg1_id->key_info.hash_order[hash_index]], ki->kip1->data + i, key_lengths[pkg1_id->key_info.hash_order[hash_index]]);
|
||||||
/*if (hash_index == hash_max) {
|
i += key_lengths[pkg1_id->key_info.hash_order[hash_index]];
|
||||||
TPRINTFARGS("%d: %x end -%x", hash_index, (*(ki->kip1->data + i)), ki->size - i);
|
if (hash_index == pkg1_id->key_info.hash_max - 1) {
|
||||||
} else {
|
if (pkg1_id->key_info.hks_offset_is_from_end)
|
||||||
TPRINTFARGS("%d: %x rodata +%x", hash_index, (*(ki->kip1->data + i)), i - ki->kip1->sections[0].size_comp);
|
i = ki->size - pkg1_id->key_info.hks_offset;
|
||||||
}*/
|
else
|
||||||
i += key_lengths[hash_order[hash_index]];
|
i = ki->size - (ki->kip1->sections[2].size_decomp - pkg1_id->key_info.hks_offset);
|
||||||
if (hash_index == hash_max - 1) {
|
} else if (hash_index == pkg1_id->key_info.hash_max) {
|
||||||
i = ki->size - hks_offset_from_end;
|
|
||||||
} else if (hash_index == hash_max) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hash_index++;
|
hash_index++;
|
||||||
} else {
|
} else {
|
||||||
i += alignment;
|
i += pkg1_id->key_info.alignment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pkg2_done:
|
pkg2_done:
|
||||||
|
@ -632,7 +569,6 @@ pkg2_done:
|
||||||
}
|
}
|
||||||
|
|
||||||
path[25] = '/';
|
path[25] = '/';
|
||||||
start_offset = 0;
|
|
||||||
while (!f_readdir(&dir, &fno) && fno.fname[0] && titles_found < title_limit) {
|
while (!f_readdir(&dir, &fno) && fno.fname[0] && titles_found < title_limit) {
|
||||||
minerva_periodic_training();
|
minerva_periodic_training();
|
||||||
memcpy(path + 26, fno.fname, 36);
|
memcpy(path + 26, fno.fname, 36);
|
||||||
|
@ -647,44 +583,14 @@ pkg2_done:
|
||||||
se_aes_xts_crypt(5, 4, 0, 1, dec_header + 0x200, dec_header, 32, 1);
|
se_aes_xts_crypt(5, 4, 0, 1, dec_header + 0x200, dec_header, 32, 1);
|
||||||
// es doesn't contain es key sources on 1.0.0
|
// es doesn't contain es key sources on 1.0.0
|
||||||
if (memcmp(pkg1_id->id, "2016", 4) && *(u32*)(dec_header + 0x210) == 0x33 && dec_header[0x205] == 0) {
|
if (memcmp(pkg1_id->id, "2016", 4) && *(u32*)(dec_header + 0x210) == 0x33 && dec_header[0x205] == 0) {
|
||||||
// es (offset 0x210 is lower half of titleid, 0x205 == 0 means it's program nca, not meta)
|
u8 hash_order[3] = {0, 1, 2};
|
||||||
switch (pkg1_id->kb) {
|
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500) {
|
||||||
case KB_FIRMWARE_VERSION_100_200:
|
|
||||||
start_offset = 0x557b;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_300:
|
|
||||||
case KB_FIRMWARE_VERSION_301:
|
|
||||||
start_offset = 0x552d;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_400:
|
|
||||||
start_offset = 0x5382;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_500:
|
|
||||||
start_offset = 0x5a63;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_600:
|
|
||||||
case KB_FIRMWARE_VERSION_620:
|
|
||||||
start_offset = 0x5674;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_700:
|
|
||||||
case KB_FIRMWARE_VERSION_810:
|
|
||||||
start_offset = 0x5563;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_900:
|
|
||||||
start_offset = 0x6495;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
hash_order[2] = 2;
|
|
||||||
if (pkg1_id->kb < KB_FIRMWARE_VERSION_500) {
|
|
||||||
hash_order[0] = 0;
|
|
||||||
hash_order[1] = 1;
|
|
||||||
} else {
|
|
||||||
hash_order[0] = 1;
|
hash_order[0] = 1;
|
||||||
hash_order[1] = 0;
|
hash_order[1] = 0;
|
||||||
}
|
}
|
||||||
hash_index = 0;
|
hash_index = 0;
|
||||||
// decrypt only what is needed to locate needed keys
|
// decrypt only what is needed to locate needed keys
|
||||||
temp_file = (u8*)_nca_process(5, 4, &fp, start_offset, 0xc0, key_area_key);
|
temp_file = (u8*)_nca_process(5, 4, &fp, pkg1_id->key_info.es_offset, 0xc0, key_area_key);
|
||||||
for (u32 i = 0; i <= 0xb0; ) {
|
for (u32 i = 0; i <= 0xb0; ) {
|
||||||
se_calc_sha256(temp_hash, temp_file + i, 0x10);
|
se_calc_sha256(temp_hash, temp_file + i, 0x10);
|
||||||
if (!memcmp(temp_hash, es_hashes_sha256[hash_order[hash_index]], 0x10)) {
|
if (!memcmp(temp_hash, es_hashes_sha256[hash_order[hash_index]], 0x10)) {
|
||||||
|
@ -701,36 +607,7 @@ pkg2_done:
|
||||||
temp_file = NULL;
|
temp_file = NULL;
|
||||||
titles_found++;
|
titles_found++;
|
||||||
} else if (*(u32*)(dec_header + 0x210) == 0x24 && dec_header[0x205] == 0) {
|
} else if (*(u32*)(dec_header + 0x210) == 0x24 && dec_header[0x205] == 0) {
|
||||||
// ssl
|
temp_file = (u8*)_nca_process(5, 4, &fp, pkg1_id->key_info.ssl_offset, 0x70, key_area_key);
|
||||||
switch (pkg1_id->kb) {
|
|
||||||
case KB_FIRMWARE_VERSION_100_200:
|
|
||||||
start_offset = 0x3d41a;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_300:
|
|
||||||
case KB_FIRMWARE_VERSION_301:
|
|
||||||
start_offset = 0x3cb81;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_400:
|
|
||||||
start_offset = 0x3711c;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_500:
|
|
||||||
start_offset = 0x37901;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_600:
|
|
||||||
case KB_FIRMWARE_VERSION_620:
|
|
||||||
start_offset = 0x1d5be;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_700:
|
|
||||||
case KB_FIRMWARE_VERSION_810:
|
|
||||||
start_offset = 0x1d437;
|
|
||||||
break;
|
|
||||||
case KB_FIRMWARE_VERSION_900:
|
|
||||||
start_offset = 0x1d807;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!memcmp(pkg1_id->id, "2016", 4))
|
|
||||||
start_offset = 0x449dc;
|
|
||||||
temp_file = (u8*)_nca_process(5, 4, &fp, start_offset, 0x70, key_area_key);
|
|
||||||
for (u32 i = 0; i <= 0x60; i++) {
|
for (u32 i = 0; i <= 0x60; i++) {
|
||||||
se_calc_sha256(temp_hash, temp_file + i, 0x10);
|
se_calc_sha256(temp_hash, temp_file + i, 0x10);
|
||||||
if (!memcmp(temp_hash, ssl_hashes_sha256[1], 0x10)) {
|
if (!memcmp(temp_hash, ssl_hashes_sha256[1], 0x10)) {
|
||||||
|
@ -1150,8 +1027,8 @@ static void _save_key(const char *name, const void *data, u32 len, char *outbuf)
|
||||||
|
|
||||||
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) {
|
static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) {
|
||||||
char temp_name[0x40] = {0};
|
char temp_name[0x40] = {0};
|
||||||
for (u32 i = start_key; i < num_keys + start_key; i++) {
|
for (u32 i = 0; i < num_keys; i++) {
|
||||||
sprintf(temp_name, "%s_%02x", name, i);
|
sprintf(temp_name, "%s_%02x", name, i + start_key);
|
||||||
_save_key(temp_name, data + i * len, len, outbuf);
|
_save_key(temp_name, data + i * len, len, outbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue