mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-18 08:22:04 +00:00
fusee: fix support for mariko key derivation/package1 parsing
This commit is contained in:
parent
52c7932f1f
commit
a968d0be32
8 changed files with 165 additions and 41 deletions
|
@ -305,21 +305,6 @@ void fuse_get_hardware_info(void *dst) {
|
||||||
|
|
||||||
memcpy(dst, hw_info, 0x10);
|
memcpy(dst, hw_info, 0x10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if have a new ODM fuse format. */
|
|
||||||
bool fuse_is_new_format(void) {
|
|
||||||
return ((fuse_get_reserved_odm(4) & 0x800) && (fuse_get_reserved_odm(0) == 0x8E61ECAE) && (fuse_get_reserved_odm(1) == 0xF2BA3BB2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the DeviceUniqueKeyGeneration. */
|
|
||||||
uint32_t fuse_get_device_unique_key_generation(void) {
|
|
||||||
if (fuse_is_new_format()) {
|
|
||||||
return (fuse_get_reserved_odm(2) & 0x1F);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the SocType from the HardwareType. */
|
/* Get the SocType from the HardwareType. */
|
||||||
uint32_t fuse_get_soc_type(void) {
|
uint32_t fuse_get_soc_type(void) {
|
||||||
switch (fuse_get_hardware_type()) {
|
switch (fuse_get_hardware_type()) {
|
||||||
|
@ -336,6 +321,21 @@ uint32_t fuse_get_soc_type(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if have a new ODM fuse format. */
|
||||||
|
bool fuse_is_new_format(void) {
|
||||||
|
return ((fuse_get_reserved_odm(4) & 0x800) && (fuse_get_reserved_odm(0) == 0x8E61ECAE) && (fuse_get_reserved_odm(1) == 0xF2BA3BB2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the DeviceUniqueKeyGeneration. */
|
||||||
|
uint32_t fuse_get_device_unique_key_generation(void) {
|
||||||
|
if (fuse_get_soc_type() != 0 || fuse_is_new_format()) {
|
||||||
|
return (fuse_get_reserved_odm(2) & 0x1F);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get the Regulator type. */
|
/* Get the Regulator type. */
|
||||||
uint32_t fuse_get_regulator(void) {
|
uint32_t fuse_get_regulator(void) {
|
||||||
if (fuse_get_soc_type() == 1) {
|
if (fuse_get_soc_type() == 1) {
|
||||||
|
|
|
@ -61,13 +61,8 @@ static const uint8_t AL16 new_master_kek_seeds[MASTERKEY_REVISION_700_800 - MAST
|
||||||
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* MasterKek seed 07. */
|
{0x9A, 0x3E, 0xA9, 0xAB, 0xFD, 0x56, 0x46, 0x1C, 0x9B, 0xF6, 0x48, 0x7F, 0x5C, 0xFA, 0x09, 0x5C}, /* MasterKek seed 07. */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t AL16 master_kek_seeds_mariko[MASTERKEY_REVISION_910_CURRENT - MASTERKEY_REVISION_500_510][0x10] = {
|
static const uint8_t AL16 master_kek_seed_mariko[0x10] = { /* TODO: Update on next change of keys. */
|
||||||
{0x77, 0x60, 0x5A, 0xD2, 0xEE, 0x6E, 0xF8, 0x3C, 0x3F, 0x72, 0xE2, 0x59, 0x9D, 0xAC, 0x5E, 0x56}, /* Mariko MasterKek seed 05. */
|
0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82, /* Mariko MasterKek seed 0A. */
|
||||||
{0x1E, 0x80, 0xB8, 0x17, 0x3E, 0xC0, 0x60, 0xAA, 0x11, 0xBE, 0x1A, 0x4A, 0xA6, 0x6F, 0xE4, 0xAE}, /* Mariko MasterKek seed 06. */
|
|
||||||
{0x94, 0x08, 0x67, 0xBD, 0x0A, 0x00, 0x38, 0x84, 0x11, 0xD3, 0x1A, 0xDB, 0xDD, 0x8D, 0xF1, 0x8A}, /* Mariko MasterKek seed 07. */
|
|
||||||
{0x5C, 0x24, 0xE3, 0xB8, 0xB4, 0xF7, 0x00, 0xC2, 0x3C, 0xFD, 0x0A, 0xCE, 0x13, 0xC3, 0xDC, 0x23}, /* Mariko MasterKek seed 08. */
|
|
||||||
{0x86, 0x69, 0xF0, 0x09, 0x87, 0xC8, 0x05, 0xAE, 0xB5, 0x7B, 0x48, 0x74, 0xDE, 0x62, 0xA6, 0x13}, /* Mariko MasterKek seed 09. */
|
|
||||||
{0x0E, 0x44, 0x0C, 0xED, 0xB4, 0x36, 0xC0, 0x3F, 0xAA, 0x1D, 0xAE, 0xBF, 0x62, 0xB1, 0x09, 0x82}, /* Mariko MasterKek seed 0A. */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static nx_dec_keyblob_t AL16 g_dec_keyblobs[32];
|
static nx_dec_keyblob_t AL16 g_dec_keyblobs[32];
|
||||||
|
@ -227,7 +222,7 @@ int derive_nx_keydata_mariko(uint32_t target_firmware) {
|
||||||
/* Derive the device and master keys. */
|
/* Derive the device and master keys. */
|
||||||
/* NOTE: Keyslots 7 and 10 are chosen here so we don't overwrite critical key material (KEK, BEK, SBK and SSK). */
|
/* NOTE: Keyslots 7 and 10 are chosen here so we don't overwrite critical key material (KEK, BEK, SBK and SSK). */
|
||||||
decrypt_data_into_keyslot(0xA, 0xE, devicekey_4x_seed, 0x10);
|
decrypt_data_into_keyslot(0xA, 0xE, devicekey_4x_seed, 0x10);
|
||||||
decrypt_data_into_keyslot(0x7, 0xC, &master_kek_seeds_mariko[target_firmware - MASTERKEY_REVISION_600_610], 0x10);
|
decrypt_data_into_keyslot(0x7, 0xC, master_kek_seed_mariko, 0x10);
|
||||||
decrypt_data_into_keyslot(0x7, 0x7, masterkey_seed, 0x10);
|
decrypt_data_into_keyslot(0x7, 0x7, masterkey_seed, 0x10);
|
||||||
|
|
||||||
/* Setup master key revision, derive older master keys for use. */
|
/* Setup master key revision, derive older master keys for use. */
|
||||||
|
@ -237,7 +232,7 @@ int derive_nx_keydata_mariko(uint32_t target_firmware) {
|
||||||
static void generate_specific_aes_key(void *dst, const void *wrapped_key, bool should_mask, uint32_t target_firmware, uint32_t generation) {
|
static void generate_specific_aes_key(void *dst, const void *wrapped_key, bool should_mask, uint32_t target_firmware, uint32_t generation) {
|
||||||
unsigned int keyslot = devkey_get_keyslot(generation);
|
unsigned int keyslot = devkey_get_keyslot(generation);
|
||||||
|
|
||||||
if (fuse_get_bootrom_patch_version() < 0x7F) {
|
if (fuse_get_soc_type() == 0 && fuse_get_bootrom_patch_version() < 0x7F) {
|
||||||
/* On dev units, use a fixed "all-zeroes" seed. */
|
/* On dev units, use a fixed "all-zeroes" seed. */
|
||||||
/* Yes, this data really is all-zero in actual TrustZone .rodata. */
|
/* Yes, this data really is all-zero in actual TrustZone .rodata. */
|
||||||
static const uint8_t AL16 dev_specific_aes_key_source[0x10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
static const uint8_t AL16 dev_specific_aes_key_source[0x10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
|
@ -80,7 +80,7 @@ static const uint8_t new_device_keygen_sources[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x
|
||||||
{0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */
|
{0x86, 0x61, 0xB0, 0x16, 0xFA, 0x7A, 0x9A, 0xEA, 0xF6, 0xF5, 0xBE, 0x1A, 0x13, 0x5B, 0x6D, 0x9E}, /* 7.0.0 New Device Keygen Source. */
|
||||||
{0xA6, 0x81, 0x71, 0xE7, 0xB5, 0x23, 0x74, 0xB0, 0x39, 0x8C, 0xB7, 0xFF, 0xA0, 0x62, 0x9F, 0x8D}, /* 8.1.0 New Device Keygen Source. */
|
{0xA6, 0x81, 0x71, 0xE7, 0xB5, 0x23, 0x74, 0xB0, 0x39, 0x8C, 0xB7, 0xFF, 0xA0, 0x62, 0x9F, 0x8D}, /* 8.1.0 New Device Keygen Source. */
|
||||||
{0x03, 0xE7, 0xEB, 0x43, 0x1B, 0xCF, 0x5F, 0xB5, 0xED, 0xDC, 0x97, 0xAE, 0x21, 0x8D, 0x19, 0xED}, /* 9.0.0 New Device Keygen Source. */
|
{0x03, 0xE7, 0xEB, 0x43, 0x1B, 0xCF, 0x5F, 0xB5, 0xED, 0xDC, 0x97, 0xAE, 0x21, 0x8D, 0x19, 0xED}, /* 9.0.0 New Device Keygen Source. */
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
|
{0xCE, 0xFE, 0x41, 0x0F, 0x46, 0x9A, 0x30, 0xD6, 0xF2, 0xE9, 0x0C, 0x6B, 0xB7, 0x15, 0x91, 0x36}, /* 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
|
static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS][0x10] = {
|
||||||
|
@ -91,7 +91,7 @@ static const uint8_t new_device_keygen_sources_dev[MASTERKEY_NUM_NEW_DEVICE_KEYS
|
||||||
{0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 7.0.0 New Device Keygen Source. */
|
{0x60, 0xAE, 0x56, 0x68, 0x11, 0xE2, 0x0C, 0x99, 0xDE, 0x05, 0xAE, 0x68, 0x78, 0x85, 0x04, 0xAE}, /* 7.0.0 New Device Keygen Source. */
|
||||||
{0x94, 0xD6, 0xA8, 0xC0, 0x95, 0xAF, 0xD0, 0xA6, 0x27, 0x53, 0x5E, 0xE5, 0x8E, 0x70, 0x1F, 0x87}, /* 8.1.0 New Device Keygen Source. */
|
{0x94, 0xD6, 0xA8, 0xC0, 0x95, 0xAF, 0xD0, 0xA6, 0x27, 0x53, 0x5E, 0xE5, 0x8E, 0x70, 0x1F, 0x87}, /* 8.1.0 New Device Keygen Source. */
|
||||||
{0x61, 0x6A, 0x88, 0x21, 0xA3, 0x52, 0xB0, 0x19, 0x16, 0x25, 0xA4, 0xE3, 0x4C, 0x54, 0x02, 0x0F}, /* 9.0.0 New Device Keygen Source. */
|
{0x61, 0x6A, 0x88, 0x21, 0xA3, 0x52, 0xB0, 0x19, 0x16, 0x25, 0xA4, 0xE3, 0x4C, 0x54, 0x02, 0x0F}, /* 9.0.0 New Device Keygen Source. */
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* TODO: 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
|
{0x9D, 0xB1, 0xAE, 0xCB, 0xF6, 0xF6, 0xE3, 0xFE, 0xAB, 0x6F, 0xCB, 0xAF, 0x38, 0x03, 0xFC, 0x7B}, /* 9.1.0 New Device Keygen Source to be added on next change-of-keys. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Determine the current SoC for Mariko specific code. */
|
/* Determine the current SoC for Mariko specific code. */
|
||||||
|
@ -158,7 +158,7 @@ unsigned int mkey_get_keyslot(unsigned int revision) {
|
||||||
if (revision > g_mkey_revision) {
|
if (revision > g_mkey_revision) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (revision == g_mkey_revision) {
|
if (revision == g_mkey_revision) {
|
||||||
return (is_soc_mariko() ? KEYSLOT_SWITCH_MASTERKEY_MARIKO : KEYSLOT_SWITCH_MASTERKEY);
|
return (is_soc_mariko() ? KEYSLOT_SWITCH_MASTERKEY_MARIKO : KEYSLOT_SWITCH_MASTERKEY);
|
||||||
} else {
|
} else {
|
||||||
|
@ -169,6 +169,8 @@ unsigned int mkey_get_keyslot(unsigned int revision) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigned int target_firmware) {
|
void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigned int target_firmware) {
|
||||||
|
const bool is_mariko = is_soc_mariko();
|
||||||
|
|
||||||
uint8_t work_buffer[0x10];
|
uint8_t work_buffer[0x10];
|
||||||
for (unsigned int revision = 0; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS; revision++) {
|
for (unsigned int revision = 0; revision < MASTERKEY_NUM_NEW_DEVICE_KEYS; revision++) {
|
||||||
const unsigned int relative_revision = revision + MASTERKEY_REVISION_400_410;
|
const unsigned int relative_revision = revision + MASTERKEY_REVISION_400_410;
|
||||||
|
@ -178,13 +180,17 @@ void derive_new_device_keys(bool is_retail, unsigned int keygen_keyslot, unsigne
|
||||||
if (relative_revision > mkey_get_revision()) {
|
if (relative_revision > mkey_get_revision()) {
|
||||||
break;
|
break;
|
||||||
} else if (relative_revision == mkey_get_revision()) {
|
} else if (relative_revision == mkey_get_revision()) {
|
||||||
/* On 7.0.0, sept will have derived this key for us already. */
|
/* On 7.0.0 erista, sept will have derived this key for us already. */
|
||||||
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0) {
|
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_7_0_0 || is_mariko) {
|
||||||
decrypt_data_into_keyslot(KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10);
|
decrypt_data_into_keyslot(is_mariko ? KEYSLOT_SWITCH_DEVICEKEY_MARIKO : KEYSLOT_SWITCH_DEVICEKEY, KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10, work_buffer, 0x10);
|
se_aes_ecb_decrypt_block(KEYSLOT_SWITCH_TEMPKEY, work_buffer, 0x10, work_buffer, 0x10);
|
||||||
set_old_devkey(relative_revision, work_buffer);
|
set_old_devkey(relative_revision, work_buffer);
|
||||||
|
|
||||||
|
if (revision == 0 && is_mariko) {
|
||||||
|
set_aes_keyslot(KEYSLOT_SWITCH_4XOLDDEVICEKEY, work_buffer, 0x10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,6 +215,6 @@ unsigned int devkey_get_keyslot(unsigned int revision) {
|
||||||
set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], 0x10);
|
set_aes_keyslot(KEYSLOT_SWITCH_TEMPKEY, g_old_devicekeys[revision - MASTERKEY_REVISION_400_410], 0x10);
|
||||||
return KEYSLOT_SWITCH_TEMPKEY;
|
return KEYSLOT_SWITCH_TEMPKEY;
|
||||||
} else {
|
} else {
|
||||||
return KEYSLOT_SWITCH_DEVICEKEY;
|
return is_soc_mariko() ? KEYSLOT_SWITCH_DEVICEKEY_MARIKO : KEYSLOT_SWITCH_DEVICEKEY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -907,9 +907,7 @@ uint32_t nxboot_main(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Derive new device keys. */
|
/* Derive new device keys. */
|
||||||
if (!is_mariko) {
|
derive_new_device_keys(fuse_get_hardware_state() != 0, KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, target_firmware);
|
||||||
derive_new_device_keys(fuse_get_hardware_state() != 0, KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY, target_firmware);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the system partition's keys. */
|
/* Set the system partition's keys. */
|
||||||
if (fsdev_register_keys("system", target_firmware, BisPartition_UserSystem) != 0) {
|
if (fsdev_register_keys("system", target_firmware, BisPartition_UserSystem) != 0) {
|
||||||
|
@ -1001,7 +999,7 @@ uint32_t nxboot_main(void) {
|
||||||
/* Copy the warmboot firmware and set the address in PMC if necessary. */
|
/* Copy the warmboot firmware and set the address in PMC if necessary. */
|
||||||
if (warmboot_fw && (warmboot_fw_size > 0)) {
|
if (warmboot_fw && (warmboot_fw_size > 0)) {
|
||||||
memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size);
|
memcpy(warmboot_memaddr, warmboot_fw, warmboot_fw_size);
|
||||||
if (!is_mariko && (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0)) {
|
if (!is_mariko && (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_4_0_0)) {
|
||||||
pmc->scratch1 = (uint32_t)warmboot_memaddr;
|
pmc->scratch1 = (uint32_t)warmboot_memaddr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1009,7 @@ uint32_t nxboot_main(void) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
} else {
|
} else {
|
||||||
/* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */
|
/* Set 3.0.0/3.0.1/3.0.2 warmboot security check. */
|
||||||
if (MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware == ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
|
if (target_firmware == ATMOSPHERE_TARGET_FIRMWARE_3_0_0) {
|
||||||
const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader;
|
const package1loader_header_t *package1loader_header = (const package1loader_header_t *)package1loader;
|
||||||
if (!strcmp(package1loader_header->build_timestamp, "20170519101410")) {
|
if (!strcmp(package1loader_header->build_timestamp, "20170519101410")) {
|
||||||
pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/
|
pmc->secure_scratch32 = 0xE3; /* Warmboot 3.0.0 security check.*/
|
||||||
|
|
|
@ -13,15 +13,43 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "../../../fusee/common/log.h"
|
||||||
#include "package1.h"
|
#include "package1.h"
|
||||||
#include "bct.h"
|
#include "bct.h"
|
||||||
#include "se.h"
|
#include "se.h"
|
||||||
|
|
||||||
|
static const uint8_t custom_public_key[0x100] = {
|
||||||
|
0x59, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||||
|
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0xFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool is_custom_public_key_erista(const void *bct) {
|
||||||
|
return memcmp((const uint8_t *)bct + 0x210, custom_public_key, sizeof(custom_public_key)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static bool is_custom_public_key_mariko(const void *bct) {
|
||||||
|
// return memcmp((const uint8_t *)bct + 0x10, custom_public_key, sizeof(custom_public_key)) == 0;
|
||||||
|
//}
|
||||||
|
|
||||||
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0) {
|
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0) {
|
||||||
nvboot_config_table *bct; /* Normal firmware BCT, primary. TODO: check? */
|
nvboot_config_table *bct; /* Normal firmware BCT, primary. TODO: check? */
|
||||||
nv_bootloader_info *pk1l_info; /* TODO: check? */
|
nv_bootloader_info *pk1l_info; /* TODO: check? */
|
||||||
|
@ -50,6 +78,19 @@ int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1
|
||||||
free(bct);
|
free(bct);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If custom public key, use bct-2 instead of bct 0. */
|
||||||
|
if (is_custom_public_key_erista(bct)) {
|
||||||
|
if (fseek(boot0, fpos + 0x4000 * 2, SEEK_SET) != 0) {
|
||||||
|
free(bct);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fread(bct, sizeof(nvboot_config_table), 1, boot0) == 0) {
|
||||||
|
free(bct);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bct->bootloader_used < 1 || pk1l_info->version < 1) {
|
if (bct->bootloader_used < 1 || pk1l_info->version < 1) {
|
||||||
free(bct);
|
free(bct);
|
||||||
errno = EILSEQ;
|
errno = EILSEQ;
|
||||||
|
@ -91,7 +132,59 @@ int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1
|
||||||
}
|
}
|
||||||
|
|
||||||
int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0) {
|
int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0) {
|
||||||
/* TODO */
|
/* TODO: Actually parse BOOT0 to locate package1ldr. */
|
||||||
|
size_t fpos, pk1l_offset;
|
||||||
|
|
||||||
|
fpos = ftell(boot0);
|
||||||
|
pk1l_offset = 0x100000;
|
||||||
|
|
||||||
|
/* Read the OEM header. */
|
||||||
|
pk11_mariko_oem_header_t oem_header;
|
||||||
|
if (fseek(boot0, fpos + pk1l_offset, SEEK_SET) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fread(&oem_header, sizeof(oem_header), 1, boot0) == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity check the size. */
|
||||||
|
if (oem_header.bl_size < 2 * sizeof(package1loader_header_t)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the size. */
|
||||||
|
*package1loader_size = oem_header.bl_size;
|
||||||
|
|
||||||
|
/* Allocate pk11. */
|
||||||
|
(*package1loader) = memalign(0x10000, *package1loader_size);
|
||||||
|
|
||||||
|
if (*package1loader == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read pk11. */
|
||||||
|
if (fread(*package1loader, *package1loader_size, 1, boot0) == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the plaintext header. */
|
||||||
|
package1loader_header_t dec_header;
|
||||||
|
memcpy(&dec_header, *package1loader, sizeof(dec_header));
|
||||||
|
|
||||||
|
/* Decrypt the binary. */
|
||||||
|
const uint8_t __attribute__((aligned(16))) iv[16] = {0};
|
||||||
|
se_aes_128_cbc_decrypt(KEYSLOT_SWITCH_BEK_MARIKO, *package1loader, *package1loader_size, *package1loader, *package1loader_size, iv);
|
||||||
|
|
||||||
|
/* Validate the decryption. */
|
||||||
|
if (memcmp(&dec_header, (const uint8_t *)*package1loader + sizeof(dec_header), sizeof(dec_header)) != 0) {
|
||||||
|
print(SCREEN_LOG_LEVEL_DEBUG, "Decrypted package1loader is invalid...\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy out the first header. */
|
||||||
|
memcpy(*package1loader, &dec_header, sizeof(dec_header));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +199,7 @@ bool package1_get_tsec_fw(void **tsec_fw, const void *package1loader, size_t pac
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +222,7 @@ bool package1_decrypt(package1_header_t *package1, size_t package1_size, const u
|
||||||
}
|
}
|
||||||
|
|
||||||
void *package1_get_warmboot_fw(const package1_header_t *package1) {
|
void *package1_get_warmboot_fw(const package1_header_t *package1) {
|
||||||
/*
|
/*
|
||||||
The layout of pk1 changes between versions.
|
The layout of pk1 changes between versions.
|
||||||
|
|
||||||
However, the secmon always starts by this erratum code:
|
However, the secmon always starts by this erratum code:
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FUSEE_PACKAGE1_H
|
#ifndef FUSEE_PACKAGE1_H
|
||||||
#define FUSEE_PACKAGE1_H
|
#define FUSEE_PACKAGE1_H
|
||||||
|
|
||||||
|
@ -44,6 +44,19 @@ typedef struct {
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
} package1_header_t;
|
} package1_header_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t aes_mac[0x10];
|
||||||
|
uint8_t rsa_sig[0x100];
|
||||||
|
uint8_t salt[0x20];
|
||||||
|
uint8_t hash[0x20];
|
||||||
|
uint32_t bl_version;
|
||||||
|
uint32_t bl_size;
|
||||||
|
uint32_t bl_load_addr;
|
||||||
|
uint32_t bl_entrypoint;
|
||||||
|
uint8_t _0x160[0x10];
|
||||||
|
uint8_t data[];
|
||||||
|
} pk11_mariko_oem_header_t;
|
||||||
|
|
||||||
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0);
|
int package1_read_and_parse_boot0_erista(void **package1loader, size_t *package1loader_size, nx_keyblob_t *keyblobs, uint32_t *revision, FILE *boot0);
|
||||||
int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0);
|
int package1_read_and_parse_boot0_mariko(void **package1loader, size_t *package1loader_size, FILE *boot0);
|
||||||
|
|
||||||
|
|
|
@ -591,6 +591,20 @@ void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, co
|
||||||
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv) {
|
||||||
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
||||||
|
if (keyslot >= KEYSLOT_AES_MAX || src_size < 0x10) {
|
||||||
|
generic_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
se->SE_CONFIG = (ALG_AES_DEC | DST_MEMORY) | (0x000 << 16);
|
||||||
|
se->SE_CRYPTO_CONFIG = (keyslot << 24) | 0x66;
|
||||||
|
set_aes_keyslot_iv(keyslot, iv, 0x10);
|
||||||
|
se->SE_CRYPTO_LAST_BLOCK = (src_size >> 4) - 1;
|
||||||
|
trigger_se_blocking_op(OP_START, dst, dst_size, src, src_size);
|
||||||
|
}
|
||||||
|
|
||||||
/* SHA256 Implementation. */
|
/* SHA256 Implementation. */
|
||||||
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
void se_calculate_sha256(void *dst, const void *src, size_t src_size) {
|
||||||
volatile tegra_se_t *se = se_get_regs();
|
volatile tegra_se_t *se = se_get_regs();
|
||||||
|
|
|
@ -38,8 +38,12 @@
|
||||||
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
|
#define KEYSLOT_SWITCH_5XNEWDEVICEKEYGENKEY 0xA
|
||||||
|
|
||||||
/* Mariko keyslots. */
|
/* Mariko keyslots. */
|
||||||
|
#define KEYSLOT_SWITCH_DEVICEKEY_MARIKO 0x6
|
||||||
#define KEYSLOT_SWITCH_MASTERKEY_MARIKO 0x7
|
#define KEYSLOT_SWITCH_MASTERKEY_MARIKO 0x7
|
||||||
|
|
||||||
|
#define KEYSLOT_SWITCH_KEK_MARIKO 0xC
|
||||||
|
#define KEYSLOT_SWITCH_BEK_MARIKO 0xD
|
||||||
|
|
||||||
#define KEYSLOT_AES_MAX 0x10
|
#define KEYSLOT_AES_MAX 0x10
|
||||||
#define KEYSLOT_RSA_MAX 0x2
|
#define KEYSLOT_RSA_MAX 0x2
|
||||||
|
|
||||||
|
@ -194,6 +198,7 @@ void se_aes_256_ecb_encrypt_block(unsigned int keyslot, void *dst, size_t dst_si
|
||||||
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size);
|
void se_aes_ctr_crypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *ctr, size_t ctr_size);
|
||||||
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
void se_aes_ecb_decrypt_block(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size);
|
||||||
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
|
void se_aes_256_cbc_encrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
|
||||||
|
void se_aes_128_cbc_decrypt(unsigned int keyslot, void *dst, size_t dst_size, const void *src, size_t src_size, const void *iv);
|
||||||
|
|
||||||
/* Hash API */
|
/* Hash API */
|
||||||
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
void se_calculate_sha256(void *dst, const void *src, size_t src_size);
|
||||||
|
|
Loading…
Reference in a new issue