mirror of
https://github.com/jakcron/nstool
synced 2024-11-23 05:59:29 +00:00
919 lines
No EOL
47 KiB
C++
919 lines
No EOL
47 KiB
C++
#include "KeyBag.h"
|
|
|
|
#include "util.h"
|
|
#include <tc/cli/FormatUtil.h>
|
|
|
|
#include <nn/hac/define/types.h>
|
|
#include <nn/hac/define/gc.h>
|
|
#include <nn/hac/AesKeygen.h>
|
|
|
|
#include <nn/pki/SignUtils.h>
|
|
#include <nn/pki/SignedData.h>
|
|
#include <nn/pki/CertificateBody.h>
|
|
#include <nn/es/TicketBody_V2.h>
|
|
|
|
nstool::KeyBagInitializer::KeyBagInitializer(bool isDev, const tc::Optional<tc::io::Path>& keyfile_path, const tc::Optional<tc::io::Path>& tik_path, const tc::Optional<tc::io::Path>& cert_path)
|
|
{
|
|
if (keyfile_path.isSet())
|
|
{
|
|
importBaseKeyFile(keyfile_path.get(), isDev);
|
|
}
|
|
if (cert_path.isSet())
|
|
{
|
|
importCertificateChain(cert_path.get());
|
|
}
|
|
if (tik_path.isSet())
|
|
{
|
|
importTicket(tik_path.get());
|
|
}
|
|
|
|
// this will populate known keys if they aren't supplied by the user provided keyfiles.
|
|
importKnownKeys(isDev);
|
|
}
|
|
|
|
void nstool::KeyBagInitializer::importBaseKeyFile(const tc::io::Path& keyfile_path, bool isDev)
|
|
{
|
|
std::shared_ptr<tc::io::FileStream> keyfile_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(keyfile_path, tc::io::FileMode::Open, tc::io::FileAccess::Read));
|
|
|
|
// import keyfile into a dictionary
|
|
std::map<std::string, std::string> keyfile_dict;
|
|
processResFile(keyfile_stream, keyfile_dict);
|
|
|
|
// sources for key derivation
|
|
std::map<byte_t, aes128_key_t> master_key;
|
|
tc::Optional<aes128_key_t> package2_key_source;
|
|
tc::Optional<aes128_key_t> ticket_titlekek_source;
|
|
std::array<tc::Optional<aes128_key_t>, 3> key_area_key_source;
|
|
tc::Optional<aes128_key_t> aes_kek_generation_source;
|
|
tc::Optional<aes128_key_t> aes_key_generation_source;
|
|
tc::Optional<aes128_key_t> nca_header_kek_source;
|
|
tc::Optional<aes128_xtskey_t> nca_header_key_source;
|
|
tc::Optional<rsa_key_t> pki_root_sign_key;
|
|
|
|
// macros for importing
|
|
|
|
#define _SAVE_AES128KEY(key_name, dst) \
|
|
{ \
|
|
std::string key,val; \
|
|
tc::ByteData dec_val; \
|
|
aes128_key_t tmp_aes128_key; \
|
|
key = (key_name); \
|
|
val = keyfile_dict[key]; \
|
|
if (val.empty() == false) { \
|
|
dec_val = tc::cli::FormatUtil::hexStringToBytes(val); \
|
|
if (dec_val.size() != tmp_aes128_key.size()) \
|
|
throw tc::ArgumentException("nstool::KeyBagInitializer", "Key: \"" + key_name + "\" has incorrect length"); \
|
|
memcpy(tmp_aes128_key.data(), dec_val.data(), tmp_aes128_key.size()); \
|
|
(dst) = tmp_aes128_key; \
|
|
} \
|
|
}
|
|
|
|
#define _SAVE_AES128XTSKEY(key_name, dst) \
|
|
{ \
|
|
std::string key,val; \
|
|
tc::ByteData dec_val; \
|
|
aes128_xtskey_t tmp_aes128_xtskey; \
|
|
key = (key_name); \
|
|
val = keyfile_dict[key]; \
|
|
if (val.empty() == false) { \
|
|
dec_val = tc::cli::FormatUtil::hexStringToBytes(val); \
|
|
if (dec_val.size() != sizeof(tmp_aes128_xtskey)) \
|
|
throw tc::ArgumentException("nstool::KeyBagInitializer", "Key: \"" + key_name + "\" has incorrect length"); \
|
|
memcpy(tmp_aes128_xtskey[0].data(), dec_val.data(), tmp_aes128_xtskey[0].size()); \
|
|
memcpy(tmp_aes128_xtskey[1].data(), dec_val.data()+tmp_aes128_xtskey[0].size(), tmp_aes128_xtskey[1].size()); \
|
|
(dst) = tmp_aes128_xtskey; \
|
|
} \
|
|
}
|
|
|
|
#define _SAVE_RSAKEY(key_name, dst, bitsize) \
|
|
{ \
|
|
std::string key_mod,key_prv,val_mod,val_prv; \
|
|
tc::ByteData dec_val; \
|
|
rsa_key_t tmp_rsa_key; \
|
|
key_mod = fmt::format("{:s}_modulus", (key_name)); \
|
|
key_prv = fmt::format("{:s}_private", (key_name)); \
|
|
val_mod = keyfile_dict[key_mod]; \
|
|
val_prv = keyfile_dict[key_prv]; \
|
|
if (val_mod.empty() == false) { \
|
|
dec_val = tc::cli::FormatUtil::hexStringToBytes(val_mod); \
|
|
if (dec_val.size() == (bitsize) >> 3) { \
|
|
tmp_rsa_key.n = dec_val; \
|
|
if (val_prv.empty() == false) { \
|
|
dec_val = tc::cli::FormatUtil::hexStringToBytes(val_prv); \
|
|
if (dec_val.size() == (bitsize) >> 3) { \
|
|
tmp_rsa_key.d = dec_val; \
|
|
(dst) = tc::crypto::RsaPrivateKey(tmp_rsa_key.n.data(), tmp_rsa_key.n.size(), tmp_rsa_key.d.data(), tmp_rsa_key.d.size()); \
|
|
} \
|
|
else { \
|
|
fmt::print("[WARNING] Key: \"{:s}\" has incorrect length (was: {:d}, expected {:d})\n", key_prv, val_prv.size(), ((bitsize) >> 3)*2); \
|
|
} \
|
|
} \
|
|
else { \
|
|
(dst) = tc::crypto::RsaPublicKey(tmp_rsa_key.n.data(), tmp_rsa_key.n.size()); \
|
|
} \
|
|
} \
|
|
else {\
|
|
fmt::print("[WARNING] Key: \"{:s}\" has incorrect length (was: {:d}, expected {:d})\n", key_mod, val_mod.size(), ((bitsize) >> 3)*2); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
// keynames
|
|
enum NameVariantIndex
|
|
{
|
|
NNTOOLS,
|
|
LEGACY_HACTOOL,
|
|
LEGACY_0
|
|
};
|
|
|
|
static const size_t kNameVariantNum = 3;
|
|
|
|
std::vector<std::string> kMasterBase = { "master" };
|
|
std::vector<std::string> kPkg1Base = { "package1" };
|
|
std::vector<std::string> kPkg2Base = { "package2" };
|
|
std::vector<std::string> kXciHeaderBase = { "xci_header" };
|
|
std::vector<std::string> kXciInitialDataBase = { "xci_initial_data" };
|
|
std::vector<std::string> kXciCertBase = { "xci_cert" };
|
|
std::vector<std::string> kContentArchiveHeaderBase = { "nca_header", "header" };
|
|
std::vector<std::string> kAcidBase = { "acid" };
|
|
std::vector<std::string> kNrrCertBase = { "nrr_certificate" };
|
|
std::vector<std::string> kPkiRootBase = { "pki_root" };
|
|
std::vector<std::string> kTicketCommonKeyBase = { "ticket_commonkey", "titlekek" };
|
|
std::vector<std::string> kNcaKeyAreaEncKeyBase = { "nca_key_area_key", "key_area_key", "nca_body_keak" };
|
|
std::vector<std::string> kNcaKeyAreaEncKeyHwBase = { "nca_key_area_key_hw", "key_area_hw_key" };
|
|
std::vector<std::string> kKekGenBase = { "aes_kek_generation" };
|
|
std::vector<std::string> kKeyGenBase = { "aes_key_generation" };
|
|
|
|
// misc str
|
|
const std::string kKeyStr = "key";
|
|
const std::string kKekStr = "kek";
|
|
const std::string kSourceStr = "source";
|
|
const std::string kSignKey = "sign_key";
|
|
const std::string kModulusStr = "modulus";
|
|
const std::string kPrivateStr = "private";
|
|
std::vector<std::string> kNcaKeyAreaKeyIndexStr = { "application", "ocean", "system" };
|
|
|
|
static const size_t kMasterKeyMax = 0x20;
|
|
/**/
|
|
|
|
// import key data
|
|
for (size_t name_idx = 0; name_idx < kNameVariantNum; name_idx++)
|
|
{
|
|
/* internal key sources */
|
|
if (name_idx < kMasterBase.size())
|
|
{
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
// std::map<byte_t, aes128_key_t> master_key;
|
|
//fmt::print("{:s}_key_{:02x}\n", kMasterBase[name_idx], mkey_rev);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:02x}", kMasterBase[name_idx], kKeyStr, mkey_rev), master_key[mkey_rev]);
|
|
}
|
|
}
|
|
|
|
if (name_idx < kPkg2Base.size())
|
|
{
|
|
// tc::Optional<aes128_key_t> package2_key_source;
|
|
//fmt::print("{:s}_key_source\n", kPkg2Base[name_idx]);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:s}", kPkg2Base[name_idx], kKeyStr, kSourceStr), package2_key_source);
|
|
}
|
|
|
|
if (name_idx < kTicketCommonKeyBase.size())
|
|
{
|
|
// tc::Optional<aes128_key_t> ticket_titlekek_source;
|
|
//fmt::print("{:s}_source\n", kTicketCommonKeyBase[name_idx]);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}", kTicketCommonKeyBase[name_idx], kSourceStr), ticket_titlekek_source);
|
|
}
|
|
|
|
if (name_idx < kNcaKeyAreaEncKeyBase.size())
|
|
{
|
|
// std::array<tc::Optional<aes128_key_t>, 3> key_area_key_source;
|
|
|
|
for (size_t keak_idx = 0; keak_idx < kNcaKeyAreaKeyIndexStr.size(); keak_idx++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_source\n", kNcaKeyAreaEncKeyBase[name_idx], kNcaKeyAreaKeyIndexStr[keak_idx]);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:s}", kNcaKeyAreaEncKeyBase[name_idx], kNcaKeyAreaKeyIndexStr[keak_idx], kSourceStr), key_area_key_source[keak_idx]);
|
|
}
|
|
}
|
|
|
|
if (name_idx < kKekGenBase.size())
|
|
{
|
|
// tc::Optional<aes128_key_t> aes_kek_generation_source;
|
|
//fmt::print("{:s}_source\n", kKekGenBase[name_idx]);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}", kKekGenBase[name_idx], kSourceStr), aes_kek_generation_source);
|
|
}
|
|
|
|
if (name_idx < kKeyGenBase.size())
|
|
{
|
|
// tc::Optional<aes128_key_t> aes_key_generation_source;
|
|
//fmt::print("{:s}_source\n", kKeyGenBase[name_idx]);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}", kKeyGenBase[name_idx], kSourceStr), aes_key_generation_source);
|
|
}
|
|
|
|
if (name_idx < kContentArchiveHeaderBase.size())
|
|
{
|
|
// tc::Optional<aes128_key_t> nca_header_kek_source;
|
|
//fmt::print("{:s}_kek_source\n", kContentArchiveHeaderBase[name_idx]);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:s}", kContentArchiveHeaderBase[name_idx], kKekStr, kSourceStr), nca_header_kek_source);
|
|
}
|
|
|
|
if (name_idx < kContentArchiveHeaderBase.size())
|
|
{
|
|
// tc::Optional<aes128_xtskey_t> nca_header_key_source;
|
|
//fmt::print("{:s}_key_source\n", kContentArchiveHeaderBase[name_idx]);
|
|
_SAVE_AES128XTSKEY(fmt::format("{:s}_{:s}_{:s}", kContentArchiveHeaderBase[name_idx], kKeyStr, kSourceStr), nca_header_key_source);
|
|
}
|
|
|
|
/* package1 */
|
|
// package1_key_xx
|
|
if (name_idx < kPkg1Base.size())
|
|
{
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
//fmt::print("{:s}_key_{:02x}\n", kPkg1Base[name_idx], mkey_rev);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:02x}", kPkg1Base[name_idx], kKeyStr, mkey_rev), pkg1_key[mkey_rev]);
|
|
}
|
|
}
|
|
|
|
/* package2 */
|
|
if (name_idx < kPkg2Base.size())
|
|
{
|
|
// package2_key_xx
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
//fmt::print("{:s}_key_{:02x}\n", kPkg2Base[name_idx], mkey_rev);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:02x}", kPkg2Base[name_idx], kKeyStr, mkey_rev), pkg2_key[mkey_rev]);
|
|
}
|
|
|
|
// package2_sign_key
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kPkg2Base[name_idx], kSignKey, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kPkg2Base[name_idx], kSignKey, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}", kPkg2Base[name_idx], kSignKey), pkg2_sign_key, 2048);
|
|
}
|
|
|
|
/* eticket */
|
|
// ticket common key
|
|
if (name_idx < kTicketCommonKeyBase.size())
|
|
{
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
//fmt::print("{:s}_{:02x}\n", kTicketCommonKeyBase[name_idx], mkey_rev);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:02x}", kTicketCommonKeyBase[name_idx], mkey_rev), etik_common_key[mkey_rev]);
|
|
}
|
|
}
|
|
|
|
/* NCA keys */
|
|
if (name_idx < kContentArchiveHeaderBase.size())
|
|
{
|
|
// nca header key
|
|
//fmt::print("{:s}_{:s}\n", kContentArchiveHeaderBase[name_idx], kKeyStr);
|
|
//_SAVE_AES128XTSKEY(fmt::format("{:s}_{:s}", kContentArchiveHeaderBase[name_idx], kKeyStr), nca_header_key);
|
|
|
|
// nca header sign0 key (generations)
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_{:02x}_{:s}\n", kContentArchiveHeaderBase[name_idx], kSignKey, mkey_rev, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:02x}_{:s}\n", kContentArchiveHeaderBase[name_idx], kSignKey, mkey_rev, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}_{:02x}", kContentArchiveHeaderBase[name_idx], kSignKey, mkey_rev), nca_header_sign0_key[mkey_rev], 2048);
|
|
}
|
|
// nca header sign0 key (generation 0)
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kContentArchiveHeaderBase[name_idx], kSignKey, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kContentArchiveHeaderBase[name_idx], kSignKey, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}", kContentArchiveHeaderBase[name_idx], kSignKey), nca_header_sign0_key[0], 2048);
|
|
|
|
}
|
|
|
|
// nca body key (unused since prototype format)
|
|
|
|
// nca key area encryption keys
|
|
if (name_idx < kNcaKeyAreaEncKeyBase.size())
|
|
{
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
for (size_t keak_idx = 0; keak_idx < kNcaKeyAreaKeyIndexStr.size(); keak_idx++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_{:02x}\n", kNcaKeyAreaEncKeyBase[name_idx], kNcaKeyAreaKeyIndexStr[keak_idx], mkey_rev);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:02x}", kNcaKeyAreaEncKeyBase[name_idx], kNcaKeyAreaKeyIndexStr[keak_idx], mkey_rev), nca_key_area_encryption_key[keak_idx][mkey_rev]);
|
|
}
|
|
}
|
|
}
|
|
// nca key area "hw" encryption keys
|
|
if (name_idx < kNcaKeyAreaEncKeyHwBase.size())
|
|
{
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
for (size_t keak_idx = 0; keak_idx < kNcaKeyAreaKeyIndexStr.size(); keak_idx++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_{:02x}\n", kNcaKeyAreaEncKeyHwBase[name_idx], kNcaKeyAreaKeyIndexStr[keak_idx], mkey_rev);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:02x}", kNcaKeyAreaEncKeyHwBase[name_idx], kNcaKeyAreaKeyIndexStr[keak_idx], mkey_rev), nca_key_area_encryption_key_hw[keak_idx][mkey_rev]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ACID */
|
|
if (name_idx < kAcidBase.size())
|
|
{
|
|
// acid sign key (generations)
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_{:02x}_{:s}\n", kAcidBase[name_idx], kSignKey, mkey_rev, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:02x}_{:s}\n", kAcidBase[name_idx], kSignKey, mkey_rev, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}_{:02x}", kAcidBase[name_idx], kSignKey, mkey_rev), acid_sign_key[mkey_rev], 2048);
|
|
}
|
|
// acid sign key (generation 0)
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kAcidBase[name_idx], kSignKey, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kAcidBase[name_idx], kSignKey, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}", kAcidBase[name_idx], kSignKey), acid_sign_key[0], 2048);
|
|
}
|
|
|
|
/* NRR certificate */
|
|
if (name_idx < kNrrCertBase.size())
|
|
{
|
|
// nrr certificate sign key (generations)
|
|
for (size_t mkey_rev = 0; mkey_rev < kMasterKeyMax; mkey_rev++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_{:02x}_{:s}\n", kNrrCertBase[name_idx], kSignKey, mkey_rev, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:02x}_{:s}\n", kNrrCertBase[name_idx], kSignKey, mkey_rev, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}_{:02x}", kNrrCertBase[name_idx], kSignKey, mkey_rev), nrr_certificate_sign_key[mkey_rev], 2048);
|
|
}
|
|
// nrr certificate sign key (generation 0)
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kNrrCertBase[name_idx], kSignKey, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kNrrCertBase[name_idx], kSignKey, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}", kNrrCertBase[name_idx], kSignKey), nrr_certificate_sign_key[0], 2048);
|
|
}
|
|
|
|
/* XCI header */
|
|
if (name_idx < kXciHeaderBase.size())
|
|
{
|
|
// xci header key (based on index)
|
|
for (size_t kek_index = 0; kek_index < 8; kek_index++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_{:02x}\n", kXciHeaderBase[name_idx], kKeyStr, kek_index);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:02x}", kXciHeaderBase[name_idx], kKeyStr, kek_index), xci_header_key[kek_index]);
|
|
}
|
|
// xci header key (old label, prod/dev keys are actually a fake distinction, the are different key indexes available to both?, so select correct index when importing)
|
|
//fmt::print("{:s}_{:s}\n", kXciHeaderBase[name_idx], kKeyStr);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}", kXciHeaderBase[name_idx], kKeyStr), xci_header_key[isDev ? nn::hac::gc::KEK_DEV : nn::hac::gc::KEK_PROD]);
|
|
|
|
// xci header sign key
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kXciHeaderBase[name_idx], kSignKey, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kXciHeaderBase[name_idx], kSignKey, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}", kXciHeaderBase[name_idx], kSignKey), xci_header_sign_key, 2048);
|
|
}
|
|
|
|
/* XCI InitialData */
|
|
if (name_idx < kXciInitialDataBase.size())
|
|
{
|
|
// xci initial data key (based on index)
|
|
for (size_t kek_index = 0; kek_index < 8; kek_index++)
|
|
{
|
|
//fmt::print("{:s}_{:s}_{:02x}\n", kXciInitialDataBase[name_idx], kKekStr, kek_index);
|
|
_SAVE_AES128KEY(fmt::format("{:s}_{:s}_{:02x}", kXciInitialDataBase[name_idx], kKekStr, kek_index), xci_initial_data_kek[kek_index]);
|
|
}
|
|
}
|
|
|
|
/* XCI cert */
|
|
if (name_idx < kXciCertBase.size())
|
|
{
|
|
// xci cert sign key
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}", kXciCertBase[name_idx], kSignKey), xci_cert_sign_key, 2048);
|
|
}
|
|
|
|
/* PKI */
|
|
if (name_idx < kPkiRootBase.size())
|
|
{
|
|
// tc::Optional<rsa_key_t> pki_root_sign_key;
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kPkiRootBase[name_idx], kSignKey, kPrivateStr);
|
|
//fmt::print("{:s}_{:s}_{:s}\n", kPkiRootBase[name_idx], kSignKey, kModulusStr);
|
|
_SAVE_RSAKEY(fmt::format("{:s}_{:s}", kPkiRootBase[name_idx], kSignKey), pki_root_sign_key, 4096);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
#undef _SAVE_RSAKEY
|
|
#undef _SAVE_AES128XTSKEY
|
|
#undef _SAVE_AES128KEY
|
|
|
|
// Derive Keys
|
|
for (auto itr = master_key.begin(); itr != master_key.end(); itr++)
|
|
{
|
|
if (aes_kek_generation_source.isSet() && aes_key_generation_source.isSet())
|
|
{
|
|
if (itr->first == 0 && nca_header_kek_source.isSet() && nca_header_key_source.isSet())
|
|
{
|
|
if (nca_header_key.isNull())
|
|
{
|
|
aes128_key_t nca_header_kek_tmp;
|
|
nn::hac::AesKeygen::generateKey(nca_header_kek_tmp.data(), aes_kek_generation_source.get().data(), nca_header_kek_source.get().data(), aes_key_generation_source.get().data(), itr->second.data());
|
|
|
|
aes128_xtskey_t nca_header_key_tmp;
|
|
nn::hac::AesKeygen::generateKey(nca_header_key_tmp[0].data(), nca_header_key_source.get()[0].data(), nca_header_kek_tmp.data());
|
|
nn::hac::AesKeygen::generateKey(nca_header_key_tmp[1].data(), nca_header_key_source.get()[1].data(), nca_header_kek_tmp.data());
|
|
|
|
nca_header_key = nca_header_key_tmp;
|
|
}
|
|
}
|
|
|
|
for (size_t keak_idx = 0; keak_idx < nn::hac::nca::kKeyAreaEncryptionKeyNum; keak_idx++)
|
|
{
|
|
if (key_area_key_source[keak_idx].isSet() && nca_key_area_encryption_key[keak_idx].find(itr->first) != nca_key_area_encryption_key[keak_idx].end())
|
|
{
|
|
aes128_key_t nca_key_area_encryption_key_tmp;
|
|
nn::hac::AesKeygen::generateKey(nca_key_area_encryption_key_tmp.data(), aes_kek_generation_source.get().data(), key_area_key_source[keak_idx].get().data(), aes_key_generation_source.get().data(), itr->second.data());
|
|
nca_key_area_encryption_key[keak_idx][itr->first] = nca_key_area_encryption_key_tmp;
|
|
}
|
|
}
|
|
}
|
|
if (ticket_titlekek_source.isSet() && etik_common_key.find(itr->first) == etik_common_key.end())
|
|
{
|
|
aes128_key_t etik_common_key_tmp;
|
|
nn::hac::AesKeygen::generateKey(etik_common_key_tmp.data(), ticket_titlekek_source.get().data(), itr->second.data());
|
|
etik_common_key[itr->first] = etik_common_key_tmp;
|
|
}
|
|
if (package2_key_source.isSet() && pkg2_key.find(itr->first) == pkg2_key.end())
|
|
{
|
|
aes128_key_t pkg2_key_tmp;
|
|
nn::hac::AesKeygen::generateKey(pkg2_key_tmp.data(), package2_key_source.get().data(), itr->second.data());
|
|
pkg2_key[itr->first] = pkg2_key_tmp;
|
|
}
|
|
}
|
|
|
|
// Save PKI Root Key
|
|
if (pki_root_sign_key.isSet())
|
|
{
|
|
broadon_signer["Root"] = { tc::ByteData(), nn::pki::sign::SIGN_ALGO_RSA4096, pki_root_sign_key.get() };
|
|
}
|
|
}
|
|
|
|
void nstool::KeyBagInitializer::importTitleKeyFile(const tc::io::Path& keyfile_path)
|
|
{
|
|
|
|
}
|
|
|
|
void nstool::KeyBagInitializer::importCertificateChain(const tc::io::Path& cert_path)
|
|
{
|
|
// save file path string for error messages
|
|
std::string cert_path_str;
|
|
tc::io::PathUtil::pathToUnixUTF8(cert_path, cert_path_str);
|
|
|
|
// open cert file
|
|
std::shared_ptr<tc::io::FileStream> certfile_stream;
|
|
try {
|
|
certfile_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(cert_path, tc::io::FileMode::Open, tc::io::FileAccess::Read));
|
|
}
|
|
catch (tc::io::FileNotFoundException& e) {
|
|
fmt::print("[WARNING] Failed to open certificate file \"{:s}\" ({:s}).\n", cert_path_str, e.error());
|
|
return;
|
|
}
|
|
|
|
// check size
|
|
size_t cert_raw_size = tc::io::IOUtil::castInt64ToSize(certfile_stream->length());
|
|
if (cert_raw_size > 0x10000)
|
|
{
|
|
fmt::print("[WARNING] Certificate file \"{:s}\" was too large.\n", cert_path_str);
|
|
return;
|
|
}
|
|
|
|
// import cert data
|
|
tc::ByteData cert_raw = tc::ByteData(cert_raw_size);
|
|
certfile_stream->seek(0, tc::io::SeekOrigin::Begin);
|
|
certfile_stream->read(cert_raw.data(), cert_raw.size());
|
|
|
|
nn::pki::SignedData<nn::pki::CertificateBody> cert;
|
|
try {
|
|
for (size_t f_pos = 0; f_pos < cert_raw.size(); f_pos += cert.getBytes().size())
|
|
{
|
|
cert.fromBytes(cert_raw.data() + f_pos, cert_raw.size() - f_pos);
|
|
|
|
std::string cert_identity = fmt::format("{:s}-{:s}", cert.getBody().getIssuer(), cert.getBody().getSubject());
|
|
|
|
switch (cert.getBody().getPublicKeyType()) {
|
|
case nn::pki::cert::PublicKeyType::RSA2048:
|
|
broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_RSA2048, cert.getBody().getRsa2048PublicKey() };
|
|
break;
|
|
case nn::pki::cert::PublicKeyType::RSA4096:
|
|
broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_RSA4096, cert.getBody().getRsa4096PublicKey() };
|
|
break;
|
|
case nn::pki::cert::PublicKeyType::ECDSA240:
|
|
// broadon_signer[cert_identity] = { cert.getBytes(), nn::pki::sign::SIGN_ALGO_ECDSA240, cert.getBody().getRsa4096PublicKey() };
|
|
fmt::print("[WARNING] Certificate {:s} will not be imported. ecc233 public keys are not supported yet.\n", cert_identity);
|
|
break;
|
|
default:
|
|
fmt::print("[WARNING] Certificate {:s} will not be imported. Unknown public key type.\n", cert_identity);
|
|
}
|
|
}
|
|
}
|
|
catch (tc::Exception& e) {
|
|
fmt::print("[WARNING] Certificate file \"{:s}\" is corrupted ({:s}).\n", cert_path_str, e.error());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void nstool::KeyBagInitializer::importTicket(const tc::io::Path& tik_path)
|
|
{
|
|
// save file path string for error messages
|
|
std::string tik_path_str;
|
|
tc::io::PathUtil::pathToUnixUTF8(tik_path, tik_path_str);
|
|
|
|
// open cert file
|
|
std::shared_ptr<tc::io::FileStream> tik_stream;
|
|
try {
|
|
tik_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(tik_path, tc::io::FileMode::Open, tc::io::FileAccess::Read));
|
|
}
|
|
catch (tc::io::FileNotFoundException& e) {
|
|
fmt::print("[WARNING] Failed to open ticket \"{:s}\" ({:s}).\n", tik_path_str, e.error());
|
|
return;
|
|
}
|
|
|
|
// check size
|
|
size_t tik_raw_size = tc::io::IOUtil::castInt64ToSize(tik_stream->length());
|
|
if (tik_raw_size > 0x10000)
|
|
{
|
|
fmt::print("[WARNING] Ticket \"{:s}\" was too large.\n", tik_path_str);
|
|
return;
|
|
}
|
|
|
|
// import cert data
|
|
tc::ByteData tik_raw = tc::ByteData(tik_raw_size);
|
|
tik_stream->seek(0, tc::io::SeekOrigin::Begin);
|
|
tik_stream->read(tik_raw.data(), tik_raw.size());
|
|
|
|
nn::pki::SignedData<nn::es::TicketBody_V2> tik;
|
|
try {
|
|
// de serialise ticket
|
|
tik.fromBytes(tik_raw.data(), tik_raw.size());
|
|
|
|
// save rights id
|
|
rights_id_t rights_id;
|
|
memcpy(rights_id.data(), tik.getBody().getRightsId(), rights_id.size());
|
|
|
|
// check ticket is not personalised
|
|
if (tik.getBody().getTitleKeyEncType() != nn::es::ticket::AES128_CBC)
|
|
{
|
|
fmt::print("[WARNING] Ticket \"{:s}\" will not be imported. Personalised tickets are not supported.\n", tc::cli::FormatUtil::formatBytesAsString(rights_id.data(), rights_id.size(), true, ""));
|
|
return;
|
|
}
|
|
|
|
// save enc title key
|
|
aes128_key_t enc_title_key;
|
|
memcpy(enc_title_key.data(), tik.getBody().getEncTitleKey(), enc_title_key.size());
|
|
|
|
// save the encrypted title key as the fallback enc content key incase the ticket was malformed and workarounds to decrypt it in isolation fail
|
|
if (fallback_enc_content_key.isNull())
|
|
{
|
|
fallback_enc_content_key = enc_title_key;
|
|
}
|
|
|
|
// determine key to decrypt title key
|
|
byte_t common_key_index = tik.getBody().getCommonKeyId();
|
|
|
|
// work around for bad scene tickets where they don't set the commonkey id field (detect scene ticket with ffff.... signature)
|
|
if (common_key_index != rights_id[15] && tik.getSignature().getBytes()[0x00] == 0xff && tik.getSignature().getBytes()[0x01] == 0xff)
|
|
{
|
|
common_key_index = rights_id[15];
|
|
}
|
|
if (etik_common_key.find(tik.getBody().getCommonKeyId()) == etik_common_key.end())
|
|
{
|
|
fmt::print("[WARNING] Ticket \"{:s}\" will not be imported. Could not decrypt title key.\n", tc::cli::FormatUtil::formatBytesAsString(rights_id.data(), rights_id.size(), true, ""));
|
|
return;
|
|
}
|
|
|
|
// decrypt title key
|
|
aes128_key_t dec_title_key;
|
|
tc::crypto::DecryptAes128Ecb(dec_title_key.data(), enc_title_key.data(), sizeof(aes128_key_t), etik_common_key[common_key_index].data(), sizeof(aes128_key_t));
|
|
|
|
// add to key dict
|
|
external_content_keys[rights_id] = dec_title_key;
|
|
|
|
}
|
|
catch (tc::Exception& e) {
|
|
fmt::print("[WARNING] Ticket \"{:s}\" is corrupted ({:s}).\n", tik_path_str, e.error());
|
|
return;
|
|
}
|
|
}
|
|
|
|
void nstool::KeyBagInitializer::importKnownKeys(bool isDev)
|
|
{
|
|
static const nn::hac::detail::rsa2048_block_t kXciHeaderSignModulus = {
|
|
0x98, 0xC7, 0x26, 0xB6, 0x0D, 0x0A, 0x50, 0xA7, 0x39, 0x21, 0x0A, 0xE3, 0x2F, 0xE4, 0x3E, 0x2E,
|
|
0x5B, 0xA2, 0x86, 0x75, 0xAA, 0x5C, 0xEE, 0x34, 0xF1, 0xA3, 0x3A, 0x7E, 0xBD, 0x90, 0x4E, 0xF7,
|
|
0x8D, 0xFA, 0x17, 0xAA, 0x6B, 0xC6, 0x36, 0x6D, 0x4C, 0x9A, 0x6D, 0x57, 0x2F, 0x80, 0xA2, 0xBC,
|
|
0x38, 0x4D, 0xDA, 0x99, 0xA1, 0xD8, 0xC3, 0xE2, 0x99, 0x79, 0x36, 0x71, 0x90, 0x20, 0x25, 0x9D,
|
|
0x4D, 0x11, 0xB8, 0x2E, 0x63, 0x6B, 0x5A, 0xFA, 0x1E, 0x9C, 0x04, 0xD1, 0xC5, 0xF0, 0x9C, 0xB1,
|
|
0x0F, 0xB8, 0xC1, 0x7B, 0xBF, 0xE8, 0xB0, 0xD2, 0x2B, 0x47, 0x01, 0x22, 0x6B, 0x23, 0xC9, 0xD0,
|
|
0xBC, 0xEB, 0x75, 0x6E, 0x41, 0x7D, 0x4C, 0x26, 0xA4, 0x73, 0x21, 0xB4, 0xF0, 0x14, 0xE5, 0xD9,
|
|
0x8D, 0xB3, 0x64, 0xEE, 0xA8, 0xFA, 0x84, 0x1B, 0xB8, 0xB8, 0x7C, 0x88, 0x6B, 0xEF, 0xCC, 0x97,
|
|
0x04, 0x04, 0x9A, 0x67, 0x2F, 0xDF, 0xEC, 0x0D, 0xB2, 0x5F, 0xB5, 0xB2, 0xBD, 0xB5, 0x4B, 0xDE,
|
|
0x0E, 0x88, 0xA3, 0xBA, 0xD1, 0xB4, 0xE0, 0x91, 0x81, 0xA7, 0x84, 0xEB, 0x77, 0x85, 0x8B, 0xEF,
|
|
0xA5, 0xE3, 0x27, 0xB2, 0xF2, 0x82, 0x2B, 0x29, 0xF1, 0x75, 0x2D, 0xCE, 0xCC, 0xAE, 0x9B, 0x8D,
|
|
0xED, 0x5C, 0xF1, 0x8E, 0xDB, 0x9A, 0xD7, 0xAF, 0x42, 0x14, 0x52, 0xCD, 0xE3, 0xC5, 0xDD, 0xCE,
|
|
0x08, 0x12, 0x17, 0xD0, 0x7F, 0x1A, 0xAA, 0x1F, 0x7D, 0xE0, 0x93, 0x54, 0xC8, 0xBC, 0x73, 0x8A,
|
|
0xCB, 0xAD, 0x6E, 0x93, 0xE2, 0x19, 0x72, 0x6B, 0xD3, 0x45, 0xF8, 0x73, 0x3D, 0x2B, 0x6A, 0x55,
|
|
0xD2, 0x3A, 0x8B, 0xB0, 0x8A, 0x42, 0xE3, 0x3D, 0xF1, 0x92, 0x23, 0x42, 0x2E, 0xBA, 0xCC, 0x9C,
|
|
0x9A, 0xC1, 0xDD, 0x62, 0x86, 0x9C, 0x2E, 0xE1, 0x2D, 0x6F, 0x62, 0x67, 0x51, 0x08, 0x0E, 0xCF
|
|
};
|
|
|
|
static const nn::hac::detail::rsa2048_block_t kXciCertSignModulus = {
|
|
0xCD, 0xF3, 0x2C, 0xB0, 0xF5, 0x14, 0x78, 0x34, 0xE5, 0x02, 0xD0, 0x29, 0x6A, 0xA5, 0xFD, 0x97,
|
|
0x6A, 0xE0, 0xB0, 0xBB, 0xB0, 0x3B, 0x1A, 0x80, 0xB7, 0xD7, 0x58, 0x92, 0x79, 0x84, 0xC0, 0x36,
|
|
0xB1, 0x55, 0x23, 0xD8, 0xA5, 0x60, 0x91, 0x26, 0x48, 0x1A, 0x80, 0x4A, 0xEA, 0x00, 0x98, 0x2A,
|
|
0xEC, 0x52, 0x17, 0x72, 0x92, 0x4D, 0xF5, 0x42, 0xA7, 0x8A, 0x6F, 0x7F, 0xD2, 0x48, 0x51, 0x8E,
|
|
0xDF, 0xCB, 0xBF, 0x77, 0xF6, 0x18, 0xBD, 0xE5, 0x00, 0xD9, 0x70, 0x8C, 0xEF, 0x57, 0xB2, 0x96,
|
|
0xD0, 0x36, 0x83, 0x88, 0x9C, 0xC5, 0xFB, 0xA0, 0x33, 0x81, 0xA2, 0x12, 0x23, 0xC6, 0xC7, 0x86,
|
|
0x0A, 0x98, 0x57, 0x4D, 0x2E, 0xB5, 0xAE, 0x64, 0xE4, 0x6F, 0xC2, 0xC5, 0xAC, 0x6A, 0x1D, 0xDB,
|
|
0xA5, 0xAF, 0x12, 0x22, 0xAB, 0x1F, 0x51, 0xC8, 0x0E, 0x0D, 0xC9, 0xF5, 0x03, 0xE8, 0xD2, 0xFC,
|
|
0x84, 0x62, 0x26, 0x55, 0xA4, 0xC3, 0xE2, 0xA8, 0x98, 0x05, 0x67, 0x23, 0xFD, 0xA5, 0x46, 0x40,
|
|
0x78, 0x51, 0x09, 0x3D, 0x91, 0x74, 0xD6, 0xD0, 0x54, 0x23, 0x0D, 0xA0, 0xFB, 0x07, 0xD0, 0xAA,
|
|
0x9D, 0x50, 0x4E, 0x2B, 0x26, 0x9A, 0x14, 0xE5, 0x6C, 0x73, 0x66, 0x24, 0x18, 0xA1, 0x93, 0x9C,
|
|
0x2A, 0x40, 0x40, 0x05, 0x6B, 0xF1, 0x45, 0xDF, 0x22, 0x8B, 0x40, 0x61, 0xA4, 0x11, 0x06, 0x03,
|
|
0xA5, 0x53, 0x84, 0xC0, 0x12, 0xE1, 0x88, 0x9D, 0x55, 0x55, 0x07, 0x40, 0x88, 0x01, 0x8C, 0xAB,
|
|
0xA2, 0xFD, 0xFD, 0x19, 0x48, 0x25, 0xAB, 0x59, 0x59, 0x28, 0x63, 0x68, 0x69, 0x1B, 0x99, 0x73,
|
|
0x8D, 0xAB, 0x5A, 0xFA, 0x71, 0x60, 0x1B, 0x12, 0xE7, 0x99, 0x70, 0xF1, 0x99, 0x2A, 0x50, 0x18,
|
|
0x8B, 0x6B, 0x61, 0x90, 0xE2, 0x7E, 0x8B, 0x90, 0xD4, 0xD5, 0xC0, 0xCB, 0x7C, 0x08, 0x06, 0xD9
|
|
};
|
|
|
|
/* Keydata for very early beta NCA0 archives' RSA-OAEP. */
|
|
/*
|
|
static const nn::hac::detail::rsa2048_block_t beta_nca0_modulus = {
|
|
0xAD, 0x58, 0xEE, 0x97, 0xF9, 0x47, 0x90, 0x7D, 0xF9, 0x29, 0x5F, 0x1F, 0x39, 0x68, 0xEE, 0x49,
|
|
0x4C, 0x1E, 0x8D, 0x84, 0x91, 0x31, 0x5D, 0xE5, 0x96, 0x27, 0xB2, 0xB3, 0x59, 0x7B, 0xDE, 0xFD,
|
|
0xB7, 0xEB, 0x40, 0xA1, 0xE7, 0xEB, 0xDC, 0x60, 0xD0, 0x3D, 0xC5, 0x50, 0x92, 0xAD, 0x3D, 0xC4,
|
|
0x8C, 0x17, 0xD2, 0x37, 0x66, 0xE3, 0xF7, 0x14, 0x34, 0x38, 0x6B, 0xA7, 0x2B, 0x21, 0x10, 0x9B,
|
|
0x73, 0x49, 0x15, 0xD9, 0x2A, 0x90, 0x86, 0x76, 0x81, 0x6A, 0x10, 0xBD, 0x74, 0xC4, 0x20, 0x55,
|
|
0x25, 0xA8, 0x02, 0xC5, 0xA0, 0x34, 0x36, 0x7B, 0x66, 0x47, 0x2C, 0x7E, 0x47, 0x82, 0xA5, 0xD4,
|
|
0xA3, 0x42, 0x45, 0xE8, 0xFD, 0x65, 0x72, 0x48, 0xA1, 0xB0, 0x44, 0x10, 0xEF, 0xAC, 0x1D, 0x0F,
|
|
0xB5, 0x12, 0x19, 0xA8, 0x41, 0x0B, 0x76, 0x3B, 0xBC, 0xF1, 0x4A, 0x10, 0x46, 0x22, 0xB8, 0xF1,
|
|
0xBC, 0x21, 0x81, 0x69, 0x9B, 0x63, 0x6F, 0xD7, 0xB9, 0x60, 0x2A, 0x9A, 0xE5, 0x2C, 0x47, 0x72,
|
|
0x59, 0x65, 0xA2, 0x21, 0x60, 0xC4, 0xFC, 0xB0, 0xD7, 0x6F, 0x42, 0xC9, 0x0C, 0xF5, 0x76, 0x7D,
|
|
0xF2, 0x5C, 0xE0, 0x80, 0x0F, 0xEE, 0x45, 0x7E, 0x4E, 0x3A, 0x8D, 0x9C, 0x5B, 0x5B, 0xD9, 0xD1,
|
|
0x43, 0x94, 0x2C, 0xC7, 0x2E, 0xB9, 0x4A, 0xE5, 0x3E, 0x15, 0xDD, 0x43, 0x00, 0xF7, 0x78, 0xE7,
|
|
0x7C, 0x39, 0xB0, 0x4D, 0xC5, 0xD1, 0x1C, 0xF2, 0xB4, 0x7A, 0x2A, 0xEA, 0x0A, 0x8E, 0xB9, 0x13,
|
|
0xB4, 0x4F, 0xD7, 0x5B, 0x4D, 0x7B, 0x43, 0xB0, 0x3A, 0x9A, 0x60, 0x22, 0x47, 0x91, 0x78, 0xC7,
|
|
0x10, 0x64, 0xE0, 0x2C, 0x69, 0xD1, 0x66, 0x3C, 0x42, 0x2E, 0xEF, 0x19, 0x21, 0x89, 0x8E, 0xE1,
|
|
0xB0, 0xB4, 0xD0, 0x17, 0xA1, 0x0F, 0x73, 0x98, 0x5A, 0xF6, 0xEE, 0xC0, 0x2F, 0x9E, 0xCE, 0xC5
|
|
};
|
|
|
|
static const nn::hac::detail::sha256_hash_t beta_nca0_label_hash = {
|
|
0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
|
|
0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55
|
|
};
|
|
*/
|
|
|
|
struct sRsaKeyForGeneration {
|
|
byte_t generation;
|
|
nn::hac::detail::rsa2048_block_t modulus;
|
|
};
|
|
|
|
static const nn::hac::detail::rsa2048_block_t kProdPackage2HeaderModulus = {
|
|
0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, 0x20, 0x69, 0x59,
|
|
0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE,
|
|
0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5,
|
|
0x6C, 0x39, 0x7F, 0x41, 0xF2, 0xFF, 0x24, 0x20, 0xC3, 0x95, 0xA6, 0xF7, 0x9D, 0x4A, 0x45, 0x74,
|
|
0x8B, 0x5D, 0x28, 0x8A, 0xC6, 0x99, 0x35, 0x68, 0x85, 0xA5, 0x64, 0x32, 0x80, 0x9F, 0xD3, 0x48,
|
|
0x39, 0xA2, 0x1D, 0x24, 0x67, 0x69, 0xDF, 0x75, 0xAC, 0x12, 0xB5, 0xBD, 0xC3, 0x29, 0x90, 0xBE,
|
|
0x37, 0xE4, 0xA0, 0x80, 0x9A, 0xBE, 0x36, 0xBF, 0x1F, 0x2C, 0xAB, 0x2B, 0xAD, 0xF5, 0x97, 0x32,
|
|
0x9A, 0x42, 0x9D, 0x09, 0x8B, 0x08, 0xF0, 0x63, 0x47, 0xA3, 0xE9, 0x1B, 0x36, 0xD8, 0x2D, 0x8A,
|
|
0xD7, 0xE1, 0x54, 0x11, 0x95, 0xE4, 0x45, 0x88, 0x69, 0x8A, 0x2B, 0x35, 0xCE, 0xD0, 0xA5, 0x0B,
|
|
0xD5, 0x5D, 0xAC, 0xDB, 0xAF, 0x11, 0x4D, 0xCA, 0xB8, 0x1E, 0xE7, 0x01, 0x9E, 0xF4, 0x46, 0xA3,
|
|
0x8A, 0x94, 0x6D, 0x76, 0xBD, 0x8A, 0xC8, 0x3B, 0xD2, 0x31, 0x58, 0x0C, 0x79, 0xA8, 0x26, 0xE9,
|
|
0xD1, 0x79, 0x9C, 0xCB, 0xD4, 0x2B, 0x6A, 0x4F, 0xC6, 0xCC, 0xCF, 0x90, 0xA7, 0xB9, 0x98, 0x47,
|
|
0xFD, 0xFA, 0x4C, 0x6C, 0x6F, 0x81, 0x87, 0x3B, 0xCA, 0xB8, 0x50, 0xF6, 0x3E, 0x39, 0x5D, 0x4D,
|
|
0x97, 0x3F, 0x0F, 0x35, 0x39, 0x53, 0xFB, 0xFA, 0xCD, 0xAB, 0xA8, 0x7A, 0x62, 0x9A, 0x3F, 0xF2,
|
|
0x09, 0x27, 0x96, 0x3F, 0x07, 0x9A, 0x91, 0xF7, 0x16, 0xBF, 0xC6, 0x3A, 0x82, 0x5A, 0x4B, 0xCF,
|
|
0x49, 0x50, 0x95, 0x8C, 0x55, 0x80, 0x7E, 0x39, 0xB1, 0x48, 0x05, 0x1E, 0x21, 0xC7, 0x24, 0x4F
|
|
};
|
|
|
|
static const std::vector<sRsaKeyForGeneration> kProdNcaHeaderSign0Modulus =
|
|
{
|
|
{
|
|
0x00,
|
|
{0xBF, 0xBE, 0x40, 0x6C, 0xF4, 0xA7, 0x80, 0xE9, 0xF0, 0x7D, 0x0C, 0x99, 0x61, 0x1D, 0x77, 0x2F,
|
|
0x96, 0xBC, 0x4B, 0x9E, 0x58, 0x38, 0x1B, 0x03, 0xAB, 0xB1, 0x75, 0x49, 0x9F, 0x2B, 0x4D, 0x58,
|
|
0x34, 0xB0, 0x05, 0xA3, 0x75, 0x22, 0xBE, 0x1A, 0x3F, 0x03, 0x73, 0xAC, 0x70, 0x68, 0xD1, 0x16,
|
|
0xB9, 0x04, 0x46, 0x5E, 0xB7, 0x07, 0x91, 0x2F, 0x07, 0x8B, 0x26, 0xDE, 0xF6, 0x00, 0x07, 0xB2,
|
|
0xB4, 0x51, 0xF8, 0x0D, 0x0A, 0x5E, 0x58, 0xAD, 0xEB, 0xBC, 0x9A, 0xD6, 0x49, 0xB9, 0x64, 0xEF,
|
|
0xA7, 0x82, 0xB5, 0xCF, 0x6D, 0x70, 0x13, 0xB0, 0x0F, 0x85, 0xF6, 0xA9, 0x08, 0xAA, 0x4D, 0x67,
|
|
0x66, 0x87, 0xFA, 0x89, 0xFF, 0x75, 0x90, 0x18, 0x1E, 0x6B, 0x3D, 0xE9, 0x8A, 0x68, 0xC9, 0x26,
|
|
0x04, 0xD9, 0x80, 0xCE, 0x3F, 0x5E, 0x92, 0xCE, 0x01, 0xFF, 0x06, 0x3B, 0xF2, 0xC1, 0xA9, 0x0C,
|
|
0xCE, 0x02, 0x6F, 0x16, 0xBC, 0x92, 0x42, 0x0A, 0x41, 0x64, 0xCD, 0x52, 0xB6, 0x34, 0x4D, 0xAE,
|
|
0xC0, 0x2E, 0xDE, 0xA4, 0xDF, 0x27, 0x68, 0x3C, 0xC1, 0xA0, 0x60, 0xAD, 0x43, 0xF3, 0xFC, 0x86,
|
|
0xC1, 0x3E, 0x6C, 0x46, 0xF7, 0x7C, 0x29, 0x9F, 0xFA, 0xFD, 0xF0, 0xE3, 0xCE, 0x64, 0xE7, 0x35,
|
|
0xF2, 0xF6, 0x56, 0x56, 0x6F, 0x6D, 0xF1, 0xE2, 0x42, 0xB0, 0x83, 0x40, 0xA5, 0xC3, 0x20, 0x2B,
|
|
0xCC, 0x9A, 0xAE, 0xCA, 0xED, 0x4D, 0x70, 0x30, 0xA8, 0x70, 0x1C, 0x70, 0xFD, 0x13, 0x63, 0x29,
|
|
0x02, 0x79, 0xEA, 0xD2, 0xA7, 0xAF, 0x35, 0x28, 0x32, 0x1C, 0x7B, 0xE6, 0x2F, 0x1A, 0xAA, 0x40,
|
|
0x7E, 0x32, 0x8C, 0x27, 0x42, 0xFE, 0x82, 0x78, 0xEC, 0x0D, 0xEB, 0xE6, 0x83, 0x4B, 0x6D, 0x81,
|
|
0x04, 0x40, 0x1A, 0x9E, 0x9A, 0x67, 0xF6, 0x72, 0x29, 0xFA, 0x04, 0xF0, 0x9D, 0xE4, 0xF4, 0x03,}
|
|
},
|
|
{
|
|
0x01,
|
|
{0xAD, 0xE3, 0xE1, 0xFA, 0x04, 0x35, 0xE5, 0xB6, 0xDD, 0x49, 0xEA, 0x89, 0x29, 0xB1, 0xFF, 0xB6,
|
|
0x43, 0xDF, 0xCA, 0x96, 0xA0, 0x4A, 0x13, 0xDF, 0x43, 0xD9, 0x94, 0x97, 0x96, 0x43, 0x65, 0x48,
|
|
0x70, 0x58, 0x33, 0xA2, 0x7D, 0x35, 0x7B, 0x96, 0x74, 0x5E, 0x0B, 0x5C, 0x32, 0x18, 0x14, 0x24,
|
|
0xC2, 0x58, 0xB3, 0x6C, 0x22, 0x7A, 0xA1, 0xB7, 0xCB, 0x90, 0xA7, 0xA3, 0xF9, 0x7D, 0x45, 0x16,
|
|
0xA5, 0xC8, 0xED, 0x8F, 0xAD, 0x39, 0x5E, 0x9E, 0x4B, 0x51, 0x68, 0x7D, 0xF8, 0x0C, 0x35, 0xC6,
|
|
0x3F, 0x91, 0xAE, 0x44, 0xA5, 0x92, 0x30, 0x0D, 0x46, 0xF8, 0x40, 0xFF, 0xD0, 0xFF, 0x06, 0xD2,
|
|
0x1C, 0x7F, 0x96, 0x18, 0xDC, 0xB7, 0x1D, 0x66, 0x3E, 0xD1, 0x73, 0xBC, 0x15, 0x8A, 0x2F, 0x94,
|
|
0xF3, 0x00, 0xC1, 0x83, 0xF1, 0xCD, 0xD7, 0x81, 0x88, 0xAB, 0xDF, 0x8C, 0xEF, 0x97, 0xDD, 0x1B,
|
|
0x17, 0x5F, 0x58, 0xF6, 0x9A, 0xE9, 0xE8, 0xC2, 0x2F, 0x38, 0x15, 0xF5, 0x21, 0x07, 0xF8, 0x37,
|
|
0x90, 0x5D, 0x2E, 0x02, 0x40, 0x24, 0x15, 0x0D, 0x25, 0xB7, 0x26, 0x5D, 0x09, 0xCC, 0x4C, 0xF4,
|
|
0xF2, 0x1B, 0x94, 0x70, 0x5A, 0x9E, 0xEE, 0xED, 0x77, 0x77, 0xD4, 0x51, 0x99, 0xF5, 0xDC, 0x76,
|
|
0x1E, 0xE3, 0x6C, 0x8C, 0xD1, 0x12, 0xD4, 0x57, 0xD1, 0xB6, 0x83, 0xE4, 0xE4, 0xFE, 0xDA, 0xE9,
|
|
0xB4, 0x3B, 0x33, 0xE5, 0x37, 0x8A, 0xDF, 0xB5, 0x7F, 0x89, 0xF1, 0x9B, 0x9E, 0xB0, 0x15, 0xB2,
|
|
0x3A, 0xFE, 0xEA, 0x61, 0x84, 0x5B, 0x7D, 0x4B, 0x23, 0x12, 0x0B, 0x83, 0x12, 0xF2, 0x22, 0x6B,
|
|
0xB9, 0x22, 0x96, 0x4B, 0x26, 0x0B, 0x63, 0x5E, 0x96, 0x57, 0x52, 0xA3, 0x67, 0x64, 0x22, 0xCA,
|
|
0xD0, 0x56, 0x3E, 0x74, 0xB5, 0x98, 0x1F, 0x0D, 0xF8, 0xB3, 0x34, 0xE6, 0x98, 0x68, 0x5A, 0xAD,}
|
|
},
|
|
};
|
|
|
|
static const std::vector<sRsaKeyForGeneration> kProdAcidSignModulus =
|
|
{
|
|
{
|
|
0x00,
|
|
{0xDD, 0xC8, 0xDD, 0xF2, 0x4E, 0x6D, 0xF0, 0xCA, 0x9E, 0xC7, 0x5D, 0xC7, 0x7B, 0xAD, 0xFE, 0x7D,
|
|
0x23, 0x89, 0x69, 0xB6, 0xF2, 0x06, 0xA2, 0x02, 0x88, 0xE1, 0x55, 0x91, 0xAB, 0xCB, 0x4D, 0x50,
|
|
0x2E, 0xFC, 0x9D, 0x94, 0x76, 0xD6, 0x4C, 0xD8, 0xFF, 0x10, 0xFA, 0x5E, 0x93, 0x0A, 0xB4, 0x57,
|
|
0xAC, 0x51, 0xC7, 0x16, 0x66, 0xF4, 0x1A, 0x54, 0xC2, 0xC5, 0x04, 0x3D, 0x1B, 0xFE, 0x30, 0x20,
|
|
0x8A, 0xAC, 0x6F, 0x6F, 0xF5, 0xC7, 0xB6, 0x68, 0xB8, 0xC9, 0x40, 0x6B, 0x42, 0xAD, 0x11, 0x21,
|
|
0xE7, 0x8B, 0xE9, 0x75, 0x01, 0x86, 0xE4, 0x48, 0x9B, 0x0A, 0x0A, 0xF8, 0x7F, 0xE8, 0x87, 0xF2,
|
|
0x82, 0x01, 0xE6, 0xA3, 0x0F, 0xE4, 0x66, 0xAE, 0x83, 0x3F, 0x4E, 0x9F, 0x5E, 0x01, 0x30, 0xA4,
|
|
0x00, 0xB9, 0x9A, 0xAE, 0x5F, 0x03, 0xCC, 0x18, 0x60, 0xE5, 0xEF, 0x3B, 0x5E, 0x15, 0x16, 0xFE,
|
|
0x1C, 0x82, 0x78, 0xB5, 0x2F, 0x47, 0x7C, 0x06, 0x66, 0x88, 0x5D, 0x35, 0xA2, 0x67, 0x20, 0x10,
|
|
0xE7, 0x6C, 0x43, 0x68, 0xD3, 0xE4, 0x5A, 0x68, 0x2A, 0x5A, 0xE2, 0x6D, 0x73, 0xB0, 0x31, 0x53,
|
|
0x1C, 0x20, 0x09, 0x44, 0xF5, 0x1A, 0x9D, 0x22, 0xBE, 0x12, 0xA1, 0x77, 0x11, 0xE2, 0xA1, 0xCD,
|
|
0x40, 0x9A, 0xA2, 0x8B, 0x60, 0x9B, 0xEF, 0xA0, 0xD3, 0x48, 0x63, 0xA2, 0xF8, 0xA3, 0x2C, 0x08,
|
|
0x56, 0x52, 0x2E, 0x60, 0x19, 0x67, 0x5A, 0xA7, 0x9F, 0xDC, 0x3F, 0x3F, 0x69, 0x2B, 0x31, 0x6A,
|
|
0xB7, 0x88, 0x4A, 0x14, 0x84, 0x80, 0x33, 0x3C, 0x9D, 0x44, 0xB7, 0x3F, 0x4C, 0xE1, 0x75, 0xEA,
|
|
0x37, 0xEA, 0xE8, 0x1E, 0x7C, 0x77, 0xB7, 0xC6, 0x1A, 0xA2, 0xF0, 0x9F, 0x10, 0x61, 0xCD, 0x7B,
|
|
0x5B, 0x32, 0x4C, 0x37, 0xEF, 0xB1, 0x71, 0x68, 0x53, 0x0A, 0xED, 0x51, 0x7D, 0x35, 0x22, 0xFD,}
|
|
},
|
|
{
|
|
0x01,
|
|
{0xE7, 0xAA, 0x25, 0xC8, 0x01, 0xA5, 0x14, 0x6B, 0x01, 0x60, 0x3E, 0xD9, 0x96, 0x5A, 0xBF, 0x90,
|
|
0xAC, 0xA7, 0xFD, 0x9B, 0x5B, 0xBD, 0x8A, 0x26, 0xB0, 0xCB, 0x20, 0x28, 0x9A, 0x72, 0x12, 0xF5,
|
|
0x20, 0x65, 0xB3, 0xB9, 0x84, 0x58, 0x1F, 0x27, 0xBC, 0x7C, 0xA2, 0xC9, 0x9E, 0x18, 0x95, 0xCF,
|
|
0xC2, 0x73, 0x2E, 0x74, 0x8C, 0x66, 0xE5, 0x9E, 0x79, 0x2B, 0xB8, 0x07, 0x0C, 0xB0, 0x4E, 0x8E,
|
|
0xAB, 0x85, 0x21, 0x42, 0xC4, 0xC5, 0x6D, 0x88, 0x9C, 0xDB, 0x15, 0x95, 0x3F, 0x80, 0xDB, 0x7A,
|
|
0x9A, 0x7D, 0x41, 0x56, 0x25, 0x17, 0x18, 0x42, 0x4D, 0x8C, 0xAC, 0xA5, 0x7B, 0xDB, 0x42, 0x5D,
|
|
0x59, 0x35, 0x45, 0x5D, 0x8A, 0x02, 0xB5, 0x70, 0xC0, 0x72, 0x35, 0x46, 0xD0, 0x1D, 0x60, 0x01,
|
|
0x4A, 0xCC, 0x1C, 0x46, 0xD3, 0xD6, 0x35, 0x52, 0xD6, 0xE1, 0xF8, 0x3B, 0x5D, 0xEA, 0xDD, 0xB8,
|
|
0xFE, 0x7D, 0x50, 0xCB, 0x35, 0x23, 0x67, 0x8B, 0xB6, 0xE4, 0x74, 0xD2, 0x60, 0xFC, 0xFD, 0x43,
|
|
0xBF, 0x91, 0x08, 0x81, 0xC5, 0x4F, 0x5D, 0x16, 0x9A, 0xC4, 0x9A, 0xC6, 0xF6, 0xF3, 0xE1, 0xF6,
|
|
0x5C, 0x07, 0xAA, 0x71, 0x6C, 0x13, 0xA4, 0xB1, 0xB3, 0x66, 0xBF, 0x90, 0x4C, 0x3D, 0xA2, 0xC4,
|
|
0x0B, 0xB8, 0x3D, 0x7A, 0x8C, 0x19, 0xFA, 0xFF, 0x6B, 0xB9, 0x1F, 0x02, 0xCC, 0xB6, 0xD3, 0x0C,
|
|
0x7D, 0x19, 0x1F, 0x47, 0xF9, 0xC7, 0x40, 0x01, 0xFA, 0x46, 0xEA, 0x0B, 0xD4, 0x02, 0xE0, 0x3D,
|
|
0x30, 0x9A, 0x1A, 0x0F, 0xEA, 0xA7, 0x66, 0x55, 0xF7, 0xCB, 0x28, 0xE2, 0xBB, 0x99, 0xE4, 0x83,
|
|
0xC3, 0x43, 0x03, 0xEE, 0xDC, 0x1F, 0x02, 0x23, 0xDD, 0xD1, 0x2D, 0x39, 0xA4, 0x65, 0x75, 0x03,
|
|
0xEF, 0x37, 0x9C, 0x06, 0xD6, 0xFA, 0xA1, 0x15, 0xF0, 0xDB, 0x17, 0x47, 0x26, 0x4F, 0x49, 0x03}
|
|
},
|
|
};
|
|
|
|
static const nn::hac::detail::rsa2048_block_t kDevPackage2HeaderModulus = {
|
|
0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, 0xBA, 0x96, 0x99,
|
|
0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7,
|
|
0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6,
|
|
0xF3, 0xBB, 0x77, 0x87, 0x46, 0x7A, 0xD6, 0x4E, 0x47, 0x4A, 0xD1, 0x41, 0xB7, 0x79, 0x4A, 0x38,
|
|
0x06, 0x6E, 0xCF, 0x61, 0x8F, 0xCD, 0xC1, 0x40, 0x0B, 0xFA, 0x26, 0xDC, 0xC0, 0x34, 0x51, 0x83,
|
|
0xD9, 0x3B, 0x11, 0x54, 0x3B, 0x96, 0x27, 0x32, 0x9A, 0x95, 0xBE, 0x1E, 0x68, 0x11, 0x50, 0xA0,
|
|
0x6B, 0x10, 0xA8, 0x83, 0x8B, 0xF5, 0xFC, 0xBC, 0x90, 0x84, 0x7A, 0x5A, 0x5C, 0x43, 0x52, 0xE6,
|
|
0xC8, 0x26, 0xE9, 0xFE, 0x06, 0xA0, 0x8B, 0x53, 0x0F, 0xAF, 0x1E, 0xC4, 0x1C, 0x0B, 0xCF, 0x50,
|
|
0x1A, 0xA4, 0xF3, 0x5C, 0xFB, 0xF0, 0x97, 0xE4, 0xDE, 0x32, 0x0A, 0x9F, 0xE3, 0x5A, 0xAA, 0xB7,
|
|
0x44, 0x7F, 0x5C, 0x33, 0x60, 0xB9, 0x0F, 0x22, 0x2D, 0x33, 0x2A, 0xE9, 0x69, 0x79, 0x31, 0x42,
|
|
0x8F, 0xE4, 0x3A, 0x13, 0x8B, 0xE7, 0x26, 0xBD, 0x08, 0x87, 0x6C, 0xA6, 0xF2, 0x73, 0xF6, 0x8E,
|
|
0xA7, 0xF2, 0xFE, 0xFB, 0x6C, 0x28, 0x66, 0x0D, 0xBD, 0xD7, 0xEB, 0x42, 0xA8, 0x78, 0xE6, 0xB8,
|
|
0x6B, 0xAE, 0xC7, 0xA9, 0xE2, 0x40, 0x6E, 0x89, 0x20, 0x82, 0x25, 0x8E, 0x3C, 0x6A, 0x60, 0xD7,
|
|
0xF3, 0x56, 0x8E, 0xEC, 0x8D, 0x51, 0x8A, 0x63, 0x3C, 0x04, 0x78, 0x23, 0x0E, 0x90, 0x0C, 0xB4,
|
|
0xE7, 0x86, 0x3B, 0x4F, 0x8E, 0x13, 0x09, 0x47, 0x32, 0x0E, 0x04, 0xB8, 0x4D, 0x5B, 0xB0, 0x46,
|
|
0x71, 0xB0, 0x5C, 0xF4, 0xAD, 0x63, 0x4F, 0xC5, 0xE2, 0xAC, 0x1E, 0xC4, 0x33, 0x96, 0x09, 0x7B
|
|
};
|
|
|
|
static const std::vector<sRsaKeyForGeneration> kDevNcaHeaderSign0Modulus =
|
|
{
|
|
{
|
|
0x00,
|
|
{0xD8, 0xF1, 0x18, 0xEF, 0x32, 0x72, 0x4C, 0xA7, 0x47, 0x4C, 0xB9, 0xEA, 0xB3, 0x04, 0xA8, 0xA4,
|
|
0xAC, 0x99, 0x08, 0x08, 0x04, 0xBF, 0x68, 0x57, 0xB8, 0x43, 0x94, 0x2B, 0xC7, 0xB9, 0x66, 0x49,
|
|
0x85, 0xE5, 0x8A, 0x9B, 0xC1, 0x00, 0x9A, 0x6A, 0x8D, 0xD0, 0xEF, 0xCE, 0xFF, 0x86, 0xC8, 0x5C,
|
|
0x5D, 0xE9, 0x53, 0x7B, 0x19, 0x2A, 0xA8, 0xC0, 0x22, 0xD1, 0xF3, 0x22, 0x0A, 0x50, 0xF2, 0x2B,
|
|
0x65, 0x05, 0x1B, 0x9E, 0xEC, 0x61, 0xB5, 0x63, 0xA3, 0x6F, 0x3B, 0xBA, 0x63, 0x3A, 0x53, 0xF4,
|
|
0x49, 0x2F, 0xCF, 0x03, 0xCC, 0xD7, 0x50, 0x82, 0x1B, 0x29, 0x4F, 0x08, 0xDE, 0x1B, 0x6D, 0x47,
|
|
0x4F, 0xA8, 0xB6, 0x6A, 0x26, 0xA0, 0x83, 0x3F, 0x1A, 0xAF, 0x83, 0x8F, 0x0E, 0x17, 0x3F, 0xFE,
|
|
0x44, 0x1C, 0x56, 0x94, 0x2E, 0x49, 0x83, 0x83, 0x03, 0xE9, 0xB6, 0xAD, 0xD5, 0xDE, 0xE3, 0x2D,
|
|
0xA1, 0xD9, 0x66, 0x20, 0x5D, 0x1F, 0x5E, 0x96, 0x5D, 0x5B, 0x55, 0x0D, 0xD4, 0xB4, 0x77, 0x6E,
|
|
0xAE, 0x1B, 0x69, 0xF3, 0xA6, 0x61, 0x0E, 0x51, 0x62, 0x39, 0x28, 0x63, 0x75, 0x76, 0xBF, 0xB0,
|
|
0xD2, 0x22, 0xEF, 0x98, 0x25, 0x02, 0x05, 0xC0, 0xD7, 0x6A, 0x06, 0x2C, 0xA5, 0xD8, 0x5A, 0x9D,
|
|
0x7A, 0xA4, 0x21, 0x55, 0x9F, 0xF9, 0x3E, 0xBF, 0x16, 0xF6, 0x07, 0xC2, 0xB9, 0x6E, 0x87, 0x9E,
|
|
0xB5, 0x1C, 0xBE, 0x97, 0xFA, 0x82, 0x7E, 0xED, 0x30, 0xD4, 0x66, 0x3F, 0xDE, 0xD8, 0x1B, 0x4B,
|
|
0x15, 0xD9, 0xFB, 0x2F, 0x50, 0xF0, 0x9D, 0x1D, 0x52, 0x4C, 0x1C, 0x4D, 0x8D, 0xAE, 0x85, 0x1E,
|
|
0xEA, 0x7F, 0x86, 0xF3, 0x0B, 0x7B, 0x87, 0x81, 0x98, 0x23, 0x80, 0x63, 0x4F, 0x2F, 0xB0, 0x62,
|
|
0xCC, 0x6E, 0xD2, 0x46, 0x13, 0x65, 0x2B, 0xD6, 0x44, 0x33, 0x59, 0xB5, 0x8F, 0xB9, 0x4A, 0xA9,}
|
|
},
|
|
{
|
|
0x01,
|
|
{0x9A, 0xBC, 0x88, 0xBD, 0x0A, 0xBE, 0xD7, 0x0C, 0x9B, 0x42, 0x75, 0x65, 0x38, 0x5E, 0xD1, 0x01,
|
|
0xCD, 0x12, 0xAE, 0xEA, 0xE9, 0x4B, 0xDB, 0xB4, 0x5E, 0x36, 0x10, 0x96, 0xDA, 0x3D, 0x2E, 0x66,
|
|
0xD3, 0x99, 0x13, 0x8A, 0xBE, 0x67, 0x41, 0xC8, 0x93, 0xD9, 0x3E, 0x42, 0xCE, 0x34, 0xCE, 0x96,
|
|
0xFA, 0x0B, 0x23, 0xCC, 0x2C, 0xDF, 0x07, 0x3F, 0x3B, 0x24, 0x4B, 0x12, 0x67, 0x3A, 0x29, 0x36,
|
|
0xA3, 0xAA, 0x06, 0xF0, 0x65, 0xA5, 0x85, 0xBA, 0xFD, 0x12, 0xEC, 0xF1, 0x60, 0x67, 0xF0, 0x8F,
|
|
0xD3, 0x5B, 0x01, 0x1B, 0x1E, 0x84, 0xA3, 0x5C, 0x65, 0x36, 0xF9, 0x23, 0x7E, 0xF3, 0x26, 0x38,
|
|
0x64, 0x98, 0xBA, 0xE4, 0x19, 0x91, 0x4C, 0x02, 0xCF, 0xC9, 0x6D, 0x86, 0xEC, 0x1D, 0x41, 0x69,
|
|
0xDD, 0x56, 0xEA, 0x5C, 0xA3, 0x2A, 0x58, 0xB4, 0x39, 0xCC, 0x40, 0x31, 0xFD, 0xFB, 0x42, 0x74,
|
|
0xF8, 0xEC, 0xEA, 0x00, 0xF0, 0xD9, 0x28, 0xEA, 0xFA, 0x2D, 0x00, 0xE1, 0x43, 0x53, 0xC6, 0x32,
|
|
0xF4, 0xA2, 0x07, 0xD4, 0x5F, 0xD4, 0xCB, 0xAC, 0xCA, 0xFF, 0xDF, 0x84, 0xD2, 0x86, 0x14, 0x3C,
|
|
0xDE, 0x22, 0x75, 0xA5, 0x73, 0xFF, 0x68, 0x07, 0x4A, 0xF9, 0x7C, 0x2C, 0xCC, 0xDE, 0x45, 0xB6,
|
|
0x54, 0x82, 0x90, 0x36, 0x1F, 0x2C, 0x51, 0x96, 0xC5, 0x0A, 0x53, 0x5B, 0xF0, 0x8B, 0x4A, 0xAA,
|
|
0x3B, 0x68, 0x97, 0x19, 0x17, 0x1F, 0x01, 0xB8, 0xED, 0xB9, 0x9A, 0x5E, 0x08, 0xC5, 0x20, 0x1E,
|
|
0x6A, 0x09, 0xF0, 0xE9, 0x73, 0xA3, 0xBE, 0x10, 0x06, 0x02, 0xE9, 0xFB, 0x85, 0xFA, 0x5F, 0x01,
|
|
0xAC, 0x60, 0xE0, 0xED, 0x7D, 0xB9, 0x49, 0xA8, 0x9E, 0x98, 0x7D, 0x91, 0x40, 0x05, 0xCF, 0xF9,
|
|
0x1A, 0xFC, 0x40, 0x22, 0xA8, 0x96, 0x5B, 0xB0, 0xDC, 0x7A, 0xF5, 0xB7, 0xE9, 0x91, 0x4C, 0x49,}
|
|
},
|
|
};
|
|
|
|
static const std::vector<sRsaKeyForGeneration> kDevAcidSignModulus =
|
|
{
|
|
{
|
|
0x00,
|
|
{0xD6, 0x34, 0xA5, 0x78, 0x6C, 0x68, 0xCE, 0x5A, 0xC2, 0x37, 0x17, 0xF3, 0x82, 0x45, 0xC6, 0x89,
|
|
0xE1, 0x2D, 0x06, 0x67, 0xBF, 0xB4, 0x06, 0x19, 0x55, 0x6B, 0x27, 0x66, 0x0C, 0xA4, 0xB5, 0x87,
|
|
0x81, 0x25, 0xF4, 0x30, 0xBC, 0x53, 0x08, 0x68, 0xA2, 0x48, 0x49, 0x8C, 0x3F, 0x38, 0x40, 0x9C,
|
|
0xC4, 0x26, 0xF4, 0x79, 0xE2, 0xA1, 0x85, 0xF5, 0x5C, 0x7F, 0x58, 0xBA, 0xA6, 0x1C, 0xA0, 0x8B,
|
|
0x84, 0x16, 0x14, 0x6F, 0x85, 0xD9, 0x7C, 0xE1, 0x3C, 0x67, 0x22, 0x1E, 0xFB, 0xD8, 0xA7, 0xA5,
|
|
0x9A, 0xBF, 0xEC, 0x0E, 0xCF, 0x96, 0x7E, 0x85, 0xC2, 0x1D, 0x49, 0x5D, 0x54, 0x26, 0xCB, 0x32,
|
|
0x7C, 0xF6, 0xBB, 0x58, 0x03, 0x80, 0x2B, 0x5D, 0xF7, 0xFB, 0xD1, 0x9D, 0xC7, 0xC6, 0x2E, 0x53,
|
|
0xC0, 0x6F, 0x39, 0x2C, 0x1F, 0xA9, 0x92, 0xF2, 0x4D, 0x7D, 0x4E, 0x74, 0xFF, 0xE4, 0xEF, 0xE4,
|
|
0x7C, 0x3D, 0x34, 0x2A, 0x71, 0xA4, 0x97, 0x59, 0xFF, 0x4F, 0xA2, 0xF4, 0x66, 0x78, 0xD8, 0xBA,
|
|
0x99, 0xE3, 0xE6, 0xDB, 0x54, 0xB9, 0xE9, 0x54, 0xA1, 0x70, 0xFC, 0x05, 0x1F, 0x11, 0x67, 0x4B,
|
|
0x26, 0x8C, 0x0C, 0x3E, 0x03, 0xD2, 0xA3, 0x55, 0x5C, 0x7D, 0xC0, 0x5D, 0x9D, 0xFF, 0x13, 0x2F,
|
|
0xFD, 0x19, 0xBF, 0xED, 0x44, 0xC3, 0x8C, 0xA7, 0x28, 0xCB, 0xE5, 0xE0, 0xB1, 0xA7, 0x9C, 0x33,
|
|
0x8D, 0xB8, 0x6E, 0xDE, 0x87, 0x18, 0x22, 0x60, 0xC4, 0xAE, 0xF2, 0x87, 0x9F, 0xCE, 0x09, 0x5C,
|
|
0xB5, 0x99, 0xA5, 0x9F, 0x49, 0xF2, 0xD7, 0x58, 0xFA, 0xF9, 0xC0, 0x25, 0x7D, 0xD6, 0xCB, 0xF3,
|
|
0xD8, 0x6C, 0xA2, 0x69, 0x91, 0x68, 0x73, 0xB1, 0x94, 0x6F, 0xA3, 0xF3, 0xB9, 0x7D, 0xF8, 0xE0,
|
|
0x72, 0x9E, 0x93, 0x7B, 0x7A, 0xA2, 0x57, 0x60, 0xB7, 0x5B, 0xA9, 0x84, 0xAE, 0x64, 0x88, 0x69}
|
|
},
|
|
{
|
|
0x01,
|
|
{0xBC, 0xA5, 0x6A, 0x7E, 0xEA, 0x38, 0x34, 0x62, 0xA6, 0x10, 0x18, 0x3C, 0xE1, 0x63, 0x7B, 0xF0,
|
|
0xD3, 0x08, 0x8C, 0xF5, 0xC5, 0xC4, 0xC7, 0x93, 0xE9, 0xD9, 0xE6, 0x32, 0xF3, 0xA0, 0xF6, 0x6E,
|
|
0x8A, 0x98, 0x76, 0x47, 0x33, 0x47, 0x65, 0x02, 0x70, 0xDC, 0x86, 0x5F, 0x3D, 0x61, 0x5A, 0x70,
|
|
0xBC, 0x5A, 0xCA, 0xCA, 0x50, 0xAD, 0x61, 0x7E, 0xC9, 0xEC, 0x27, 0xFF, 0xE8, 0x64, 0x42, 0x9A,
|
|
0xEE, 0xBE, 0xC3, 0xD1, 0x0B, 0xC0, 0xE9, 0xBF, 0x83, 0x8D, 0xC0, 0x0C, 0xD8, 0x00, 0x5B, 0x76,
|
|
0x90, 0xD2, 0x4B, 0x30, 0x84, 0x35, 0x8B, 0x1E, 0x20, 0xB7, 0xE4, 0xDC, 0x63, 0xE5, 0xDF, 0xCD,
|
|
0x00, 0x5F, 0x81, 0x5F, 0x67, 0xC5, 0x8B, 0xDF, 0xFC, 0xE1, 0x37, 0x5F, 0x07, 0xD9, 0xDE, 0x4F,
|
|
0xE6, 0x7B, 0xF1, 0xFB, 0xA1, 0x5A, 0x71, 0x40, 0xFE, 0xBA, 0x1E, 0xAE, 0x13, 0x22, 0xD2, 0xFE,
|
|
0x37, 0xA2, 0xB6, 0x8B, 0xAB, 0xEB, 0x84, 0x81, 0x4E, 0x7C, 0x1E, 0x02, 0xD1, 0xFB, 0xD7, 0x5D,
|
|
0x11, 0x84, 0x64, 0xD2, 0x4D, 0xBB, 0x50, 0x00, 0x67, 0x54, 0xE2, 0x77, 0x89, 0xBA, 0x0B, 0xE7,
|
|
0x05, 0x57, 0x9A, 0x22, 0x5A, 0xEC, 0x76, 0x1C, 0xFD, 0xE8, 0xA8, 0x18, 0x16, 0x41, 0x65, 0x03,
|
|
0xFA, 0xC4, 0xA6, 0x31, 0x5C, 0x1A, 0x7F, 0xAB, 0x11, 0xC8, 0x4A, 0x99, 0xB9, 0xE6, 0xCF, 0x62,
|
|
0x21, 0xA6, 0x72, 0x47, 0xDB, 0xBA, 0x96, 0x26, 0x4E, 0x2E, 0xD4, 0x8C, 0x46, 0xD6, 0xA7, 0x1A,
|
|
0x6C, 0x32, 0xA7, 0xDF, 0x85, 0x1C, 0x03, 0xC3, 0x6D, 0xA9, 0xE9, 0x68, 0xF4, 0x17, 0x1E, 0xB2,
|
|
0x70, 0x2A, 0xA1, 0xE5, 0xE1, 0xF3, 0x8F, 0x6F, 0x63, 0xAC, 0xEB, 0x72, 0x0B, 0x4C, 0x4A, 0x36,
|
|
0x3C, 0x60, 0x91, 0x9F, 0x6E, 0x1C, 0x71, 0xEA, 0xD0, 0x78, 0x78, 0xA0, 0x2E, 0xC6, 0x32, 0x6B}
|
|
},
|
|
};
|
|
|
|
if (isDev)
|
|
{
|
|
if (xci_header_sign_key.isNull())
|
|
xci_header_sign_key = tc::crypto::RsaPublicKey(kXciHeaderSignModulus.data(), kXciHeaderSignModulus.size());
|
|
|
|
if (xci_cert_sign_key.isNull())
|
|
xci_cert_sign_key = tc::crypto::RsaPublicKey(kXciCertSignModulus.data(), kXciCertSignModulus.size());
|
|
|
|
if (pkg2_sign_key.isNull())
|
|
pkg2_sign_key = tc::crypto::RsaPublicKey(kDevPackage2HeaderModulus.data(), kDevPackage2HeaderModulus.size());
|
|
|
|
for (auto itr = kDevNcaHeaderSign0Modulus.begin(); itr != kDevNcaHeaderSign0Modulus.end(); itr++)
|
|
{
|
|
if (nca_header_sign0_key.find(itr->generation) == nca_header_sign0_key.end())
|
|
nca_header_sign0_key[itr->generation] = tc::crypto::RsaPublicKey(itr->modulus.data(), itr->modulus.size());
|
|
}
|
|
|
|
for (auto itr = kDevAcidSignModulus.begin(); itr != kDevAcidSignModulus.end(); itr++)
|
|
{
|
|
if (acid_sign_key.find(itr->generation) == acid_sign_key.end())
|
|
acid_sign_key[itr->generation] = tc::crypto::RsaPublicKey(itr->modulus.data(), itr->modulus.size());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (xci_header_sign_key.isNull())
|
|
xci_header_sign_key = tc::crypto::RsaPublicKey(kXciHeaderSignModulus.data(), kXciHeaderSignModulus.size());
|
|
|
|
if (xci_cert_sign_key.isNull())
|
|
xci_cert_sign_key = tc::crypto::RsaPublicKey(kXciCertSignModulus.data(), kXciCertSignModulus.size());
|
|
|
|
if (pkg2_sign_key.isNull())
|
|
pkg2_sign_key = tc::crypto::RsaPublicKey(kProdPackage2HeaderModulus.data(), kProdPackage2HeaderModulus.size());
|
|
|
|
for (auto itr = kProdNcaHeaderSign0Modulus.begin(); itr != kProdNcaHeaderSign0Modulus.end(); itr++)
|
|
{
|
|
if (nca_header_sign0_key.find(itr->generation) == nca_header_sign0_key.end())
|
|
nca_header_sign0_key[itr->generation] = tc::crypto::RsaPublicKey(itr->modulus.data(), itr->modulus.size());
|
|
}
|
|
|
|
for (auto itr = kProdAcidSignModulus.begin(); itr != kProdAcidSignModulus.end(); itr++)
|
|
{
|
|
if (acid_sign_key.find(itr->generation) == acid_sign_key.end())
|
|
acid_sign_key[itr->generation] = tc::crypto::RsaPublicKey(itr->modulus.data(), itr->modulus.size());
|
|
}
|
|
}
|
|
} |