diff --git a/programs/nstool/source/UserSettings.cpp b/programs/nstool/source/UserSettings.cpp index b556caa..a587ede 100644 --- a/programs/nstool/source/UserSettings.cpp +++ b/programs/nstool/source/UserSettings.cpp @@ -1,6 +1,7 @@ #include "UserSettings.h" #include "version.h" #include "PkiValidator.h" +#include "KeyConfiguration.h" #include #include #include @@ -385,36 +386,25 @@ void UserSettings::populateCmdArgs(const std::vector& arg_list, sCm void UserSettings::populateKeyset(sCmdArgs& args) { - fnd::aes::sAes128Key zeros_aes_key; - fnd::aes::sAesXts128Key zeros_aes_xts_key; - memset((void*)&zeros_aes_key, 0, sizeof(fnd::aes::sAes128Key)); - memset((void*)&zeros_aes_xts_key, 0, sizeof(fnd::aes::sAesXts128Key)); memset((void*)&mKeyset, 0, sizeof(sKeyset)); - fnd::ResourceFileReader res; if (args.keyset_path.isSet) { - res.processFile(*args.keyset_path); + mKeyCfg.importHactoolGenericKeyfile(*args.keyset_path); } else { // open other resource files in $HOME/.switch/prod.keys (or $HOME/.switch/dev.keys if -d/--dev is set). - std::string home; - if (home.empty()) fnd::io::getEnvironVar(home, "HOME"); - if (home.empty()) fnd::io::getEnvironVar(home, "USERPROFILE"); - if (home.empty()) return; - - const std::string kKeysetNameStr[2] = {"prod.keys", "dev.keys"}; - const std::string kHomeSwitchDirStr = ".switch"; - std::string keyset_path; - fnd::io::appendToPath(keyset_path, home); - fnd::io::appendToPath(keyset_path, kHomeSwitchDirStr); - fnd::io::appendToPath(keyset_path, kKeysetNameStr[args.devkit_keys.isSet ? *args.devkit_keys : 0]); + getSwitchPath(keyset_path); + if (keyset_path.empty()) + return; + + fnd::io::appendToPath(keyset_path, kGeneralKeyfileName[args.devkit_keys.isSet]); try { - res.processFile(keyset_path); + mKeyCfg.importHactoolGenericKeyfile(keyset_path); } catch (const fnd::Exception&) { @@ -422,132 +412,44 @@ void UserSettings::populateKeyset(sCmdArgs& args) } } - - // suffix - const std::string kKeyStr = "key"; - const std::string kKekStr = "kek"; - const std::string kSourceStr = "source"; - const std::string kRsaKeySuffix[2] = {"sign_key_private", "sign_key_modulus"}; - const std::string kKeyIndex[kMasterKeyNum] = {"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f"}; - // keyname bases - const std::string kMasterBase = "master"; - const std::string kPackage1Base = "package1"; - const std::string kPackage2Base = "package2"; - const std::string kXciHeaderBase = "xci_header"; - const std::string kNcaHeaderBase[2] = {"header", "nca_header"}; - const std::string kKekGenSource = "aes_kek_generation"; - const std::string kKeyGenSource = "aes_key_generation"; - const std::string kAcidBase = "acid"; - const std::string kPkiRootBase = "pki_root"; - const std::string kTicketCommonKeyBase[2] = { "titlekek", "ticket_commonkey" }; - const std::string kNcaBodyBase[2] = {"key_area_key", "nca_body_keak"}; - const std::string kNcaBodyKeakIndexName[3] = {"application", "ocean", "system"}; - - - // sources - fnd::aes::sAes128Key master_key[kMasterKeyNum] = { zeros_aes_key }; - fnd::aes::sAes128Key package2_key_source = zeros_aes_key; - fnd::aes::sAes128Key ticket_titlekek_source = zeros_aes_key; - fnd::aes::sAes128Key key_area_key_source[3] = { zeros_aes_key, zeros_aes_key, zeros_aes_key }; - fnd::aes::sAes128Key aes_kek_generation_source = zeros_aes_key; - fnd::aes::sAes128Key aes_key_generation_source = zeros_aes_key; - fnd::aes::sAes128Key nca_header_kek_source = zeros_aes_key; - fnd::aes::sAesXts128Key nca_header_key_source = zeros_aes_xts_key; - - -#define _CONCAT_2_STRINGS(str1, str2) ((str1) + "_" + (str2)) -#define _CONCAT_3_STRINGS(str1, str2, str3) ((str1) + "_"+ (str2) + "_" + (str3)) - - std::string key,val; - -#define _SAVE_KEYDATA(key_name, array, len) \ - key = (key_name); \ - val = res[key]; \ - if (val.empty() == false) { \ - decodeHexStringToBytes(key, val, (byte_t*)array, len); \ - } - - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPackage2Base, kKeyStr, kSourceStr), package2_key_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[0], kSourceStr), ticket_titlekek_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[1], kSourceStr), ticket_titlekek_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[0], kNcaBodyKeakIndexName[0], kSourceStr), key_area_key_source[0].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[0], kNcaBodyKeakIndexName[1], kSourceStr), key_area_key_source[1].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[0], kNcaBodyKeakIndexName[2], kSourceStr), key_area_key_source[2].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[1], kNcaBodyKeakIndexName[0], kSourceStr), key_area_key_source[0].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[1], kNcaBodyKeakIndexName[1], kSourceStr), key_area_key_source[1].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[1], kNcaBodyKeakIndexName[2], kSourceStr), key_area_key_source[2].key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kKekGenSource, kSourceStr), aes_kek_generation_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kKeyGenSource, kSourceStr), aes_key_generation_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaHeaderBase[0], kKekStr, kSourceStr), nca_header_kek_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaHeaderBase[0], kKeyStr, kSourceStr), nca_header_key_source.key, 0x20); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaHeaderBase[1], kKekStr, kSourceStr), nca_header_kek_source.key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaHeaderBase[1], kKeyStr, kSourceStr), nca_header_key_source.key, 0x20); - - // Store Key Variants/Derivatives - for (size_t i = 0; i < kMasterKeyNum; i++) + mKeyCfg.getPkiRootSignKey(nn::pki::sign::kRootIssuerStr, mKeyset.pki.root_sign_key); + mKeyCfg.getAcidSignKey(mKeyset.acid_sign_key); + mKeyCfg.getNcaHeader0SignKey(mKeyset.nca.header_sign_key); + mKeyCfg.getNcaHeaderKey(mKeyset.nca.header_key); + mKeyCfg.getXciHeaderSignKey(mKeyset.xci.header_sign_key); + mKeyCfg.getXciHeaderKey(mKeyset.xci.header_key); + mKeyCfg.getPkg2SignKey(mKeyset.package2_sign_key); + for (size_t mkeyidx = 0; mkeyidx < 32; mkeyidx++) { - - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kMasterBase, kKeyStr, kKeyIndex[i]), master_key[i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPackage1Base, kKeyStr, kKeyIndex[i]), mKeyset.package1_key[i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kPackage2Base, kKeyStr, kKeyIndex[i]), mKeyset.package2_key[i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[0], kKeyIndex[i]), mKeyset.ticket.titlekey_kek[i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kTicketCommonKeyBase[1], kKeyIndex[i]), mKeyset.ticket.titlekey_kek[i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[0], kNcaBodyKeakIndexName[0], kKeyIndex[i]), mKeyset.nca.key_area_key[0][i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[0], kNcaBodyKeakIndexName[1], kKeyIndex[i]), mKeyset.nca.key_area_key[1][i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[0], kNcaBodyKeakIndexName[2], kKeyIndex[i]), mKeyset.nca.key_area_key[2][i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[1], kNcaBodyKeakIndexName[0], kKeyIndex[i]), mKeyset.nca.key_area_key[0][i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[1], kNcaBodyKeakIndexName[1], kKeyIndex[i]), mKeyset.nca.key_area_key[1][i].key, 0x10); - _SAVE_KEYDATA(_CONCAT_3_STRINGS(kNcaBodyBase[1], kNcaBodyKeakIndexName[2], kKeyIndex[i]), mKeyset.nca.key_area_key[2][i].key, 0x10); + mKeyCfg.getPkg1Key(mkeyidx, mKeyset.package1_key[mkeyidx]); + mKeyCfg.getPkg2Key(mkeyidx, mKeyset.package1_key[mkeyidx]); + mKeyCfg.getNcaKeyAreaEncryptionKey(mkeyidx, 0, mKeyset.nca.key_area_key[0][mkeyidx]); + mKeyCfg.getNcaKeyAreaEncryptionKey(mkeyidx, 1, mKeyset.nca.key_area_key[1][mkeyidx]); + mKeyCfg.getNcaKeyAreaEncryptionKey(mkeyidx, 2, mKeyset.nca.key_area_key[2][mkeyidx]); + mKeyCfg.getETicketCommonKey(mkeyidx, mKeyset.ticket.titlekey_kek[mkeyidx]); } - - // store nca header key - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[0], kKeyStr), mKeyset.nca.header_key.key[0], 0x20); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[1], kKeyStr), mKeyset.nca.header_key.key[0], 0x20); - // store xci header key - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kKeyStr), mKeyset.xci.header_key.key, 0x10); - - // store rsa keys - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[1], kRsaKeySuffix[0]), mKeyset.nca.header_sign_key.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[1], kRsaKeySuffix[1]), mKeyset.nca.header_sign_key.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kRsaKeySuffix[0]), mKeyset.xci.header_sign_key.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kRsaKeySuffix[1]), mKeyset.xci.header_sign_key.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase, kRsaKeySuffix[0]), mKeyset.acid_sign_key.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase, kRsaKeySuffix[1]), mKeyset.acid_sign_key.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPackage2Base, kRsaKeySuffix[0]), mKeyset.package2_sign_key.priv_exponent, fnd::rsa::kRsa2048Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPackage2Base, kRsaKeySuffix[1]), mKeyset.package2_sign_key.modulus, fnd::rsa::kRsa2048Size); - - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase, kRsaKeySuffix[0]), mKeyset.pki.root_sign_key.priv_exponent, fnd::rsa::kRsa4096Size); - _SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase, kRsaKeySuffix[1]), mKeyset.pki.root_sign_key.modulus, fnd::rsa::kRsa4096Size); - - - // save keydata from input args if (args.nca_bodykey.isSet) { - if (args.nca_bodykey.var.length() == (sizeof(fnd::aes::sAes128Key)*2)) - { - decodeHexStringToBytes("--bodykey", args.nca_bodykey.var, mKeyset.nca.manual_body_key_aesctr.key, sizeof(fnd::aes::sAes128Key)); - } - else - { - decodeHexStringToBytes("--bodykey", args.nca_bodykey.var, mKeyset.nca.manual_body_key_aesxts.key[0], sizeof(fnd::aes::sAesXts128Key)); - } + fnd::aes::sAes128Key tmp_key; + fnd::Vec tmp_raw; + fnd::SimpleTextOutput::stringToArray(args.nca_bodykey.var, tmp_raw); + if (tmp_raw.size() != sizeof(fnd::aes::sAes128Key)) + throw fnd::Exception(kModuleName, "Key: \"--bodykey\" has incorrect length"); + memcpy(tmp_key.key, tmp_raw.data(), 16); + mKeyCfg.addNcaExternalContentKey(kDummyRightsIdForUserBodyKey, tmp_key); } if (args.nca_titlekey.isSet) { - if (args.nca_titlekey.var.length() == (sizeof(fnd::aes::sAes128Key)*2)) - { - decodeHexStringToBytes("--titlekey", args.nca_titlekey.var, mKeyset.nca.manual_title_key_aesctr.key, sizeof(fnd::aes::sAes128Key)); - } - else - { - decodeHexStringToBytes("--titlekey", args.nca_titlekey.var, mKeyset.nca.manual_title_key_aesxts.key[0], sizeof(fnd::aes::sAesXts128Key)); - } + fnd::aes::sAes128Key tmp_key; + fnd::Vec tmp_raw; + fnd::SimpleTextOutput::stringToArray(args.nca_bodykey.var, tmp_raw); + if (tmp_raw.size() != sizeof(fnd::aes::sAes128Key)) + throw fnd::Exception(kModuleName, "Key: \"--titlekey\" has incorrect length"); + memcpy(tmp_key.key, tmp_raw.data(), 16); + mKeyCfg.addNcaExternalContentKey(kDummyRightsIdForUserTitleKey, tmp_key); } // import certificate chain @@ -615,7 +517,19 @@ void UserSettings::populateKeyset(sCmdArgs& args) // extract title key if (tik.getBody().getTitleKeyEncType() == nn::es::ticket::AES128_CBC) { - memcpy(mKeyset.nca.manual_title_key_aesctr.key, tik.getBody().getEncTitleKey(), fnd::aes::kAes128KeySize); + fnd::aes::sAes128Key enc_title_key; + memcpy(enc_title_key.key, tik.getBody().getEncTitleKey(), 16); + mKeyCfg.addNcaExternalContentKey(kDummyRightsIdForUserTitleKey, enc_title_key); + fnd::aes::sAes128Key common_key, external_content_key; + if (mKeyCfg.getETicketCommonKey(nn::hac::NcaUtils::getMasterKeyRevisionFromKeyGeneration(tik.getBody().getCommonKeyId()), common_key) == true) + { + nn::hac::AesKeygen::generateKey(external_content_key.key, tik.getBody().getEncTitleKey(), common_key.key); + mKeyCfg.addNcaExternalContentKey(tik.getBody().getRightsId(), external_content_key); + } + else + { + std::cout << "[WARNING] Titlekey not imported from ticket because commonkey was not available" << std::endl; + } } else { @@ -623,67 +537,9 @@ void UserSettings::populateKeyset(sCmdArgs& args) } } -#undef _SAVE_KEYDATA -#undef _CONCAT_3_STRINGS -#undef _CONCAT_2_STRINGS - - // Derive keys - for (size_t i = 0; i < kMasterKeyNum; i++) - { - if (master_key[i] != zeros_aes_key) - { - if (aes_kek_generation_source != zeros_aes_key && aes_key_generation_source != zeros_aes_key) - { - if (i == 0 && nca_header_kek_source != zeros_aes_key && nca_header_key_source != zeros_aes_xts_key) - { - if (mKeyset.nca.header_key == zeros_aes_xts_key) - { - fnd::aes::sAes128Key nca_header_kek; - nn::hac::AesKeygen::generateKey(nca_header_kek.key, aes_kek_generation_source.key, nca_header_kek_source.key, aes_key_generation_source.key, master_key[i].key); - nn::hac::AesKeygen::generateKey(mKeyset.nca.header_key.key[0], nca_header_key_source.key[0], nca_header_kek.key); - nn::hac::AesKeygen::generateKey(mKeyset.nca.header_key.key[1], nca_header_key_source.key[1], nca_header_kek.key); - //printf("nca header key[0] "); - //fnd::SimpleTextOutput::hexDump(mKeyset.nca.header_key.key[0], 0x10); - //printf("nca header key[1] "); - //fnd::SimpleTextOutput::hexDump(mKeyset.nca.header_key.key[1], 0x10); - } - } - - for (size_t j = 0; j < nn::hac::nca::kKeyAreaEncryptionKeyNum; j++) - { - if (key_area_key_source[j] != zeros_aes_key && mKeyset.nca.key_area_key[j][i] == zeros_aes_key) - { - nn::hac::AesKeygen::generateKey(mKeyset.nca.key_area_key[j][i].key, aes_kek_generation_source.key, key_area_key_source[j].key, aes_key_generation_source.key, master_key[i].key); - //printf("nca keak %d/%02d ", j, i); - //fnd::SimpleTextOutput::hexDump(mKeyset.nca.key_area_key[j][i].key, 0x10); - } - } - } - - if (ticket_titlekek_source != zeros_aes_key && mKeyset.ticket.titlekey_kek[i] == zeros_aes_key) - { - nn::hac::AesKeygen::generateKey(mKeyset.ticket.titlekey_kek[i].key, ticket_titlekek_source.key, master_key[i].key); - //printf("ticket titlekek %02d ", i); - //fnd::SimpleTextOutput::hexDump(mKeyset.ticket.titlekey_kek[i].key, 0x10); - } - if (package2_key_source != zeros_aes_key && mKeyset.package2_key[i] == zeros_aes_key) - { - nn::hac::AesKeygen::generateKey(mKeyset.package2_key[i].key, package2_key_source.key, master_key[i].key); - //printf("package2 key %02d ", i); - //fnd::SimpleTextOutput::hexDump(mKeyset.package2_key[i].key, 0x10); - } - } - /* - for (size_t j = 0; j < nn::hac::nca::kKeyAreaEncryptionKeyNum; j++) - { - if (mKeyset.nca.key_area_key[j][i] != zeros_aes_key) - { - printf("nca body keak %d/%02d ", j, i); - fnd::SimpleTextOutput::hexDump(mKeyset.nca.key_area_key[j][i].key, 0x10); - } - } - */ - } + // replicate keys into old keyset + mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserBodyKey, mKeyset.nca.manual_body_key_aesctr); + mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserTitleKey, mKeyset.nca.manual_title_key_aesctr); } void UserSettings::populateUserSettings(sCmdArgs& args) @@ -747,21 +603,6 @@ void UserSettings::populateUserSettings(sCmdArgs& args) throw fnd::Exception(kModuleName, "Unknown file type."); } - -void UserSettings::decodeHexStringToBytes(const std::string& name, const std::string& str, byte_t* out, size_t out_len) -{ - size_t size = str.size(); - if ((size % 2) || ((size / 2) != out_len)) - { - throw fnd::Exception(kModuleName, "Key: \"" + name + "\" has incorrect length"); - } - - for (size_t i = 0; i < out_len; i++) - { - out[i] = (charToByte(str[i * 2]) << 4) | charToByte(str[(i * 2) + 1]); - } -} - FileType UserSettings::getFileTypeFromString(const std::string& type_str) { std::string str = type_str; @@ -1019,3 +860,25 @@ nn::hac::npdm::InstructionType UserSettings::getInstructionTypeFromString(const return type; } + +void UserSettings::getHomePath(std::string& path) const +{ + // open other resource files in $HOME/.switch/prod.keys (or $HOME/.switch/dev.keys if -d/--dev is set). + path.clear(); + if (path.empty()) fnd::io::getEnvironVar(path, "HOME"); + if (path.empty()) fnd::io::getEnvironVar(path, "USERPROFILE"); + if (path.empty()) return; +} + +void UserSettings::getSwitchPath(std::string& path) const +{ + std::string home; + home.clear(); + getHomePath(home); + if (home.empty()) + return; + + path.clear(); + fnd::io::appendToPath(path, home); + fnd::io::appendToPath(path, kHomeSwitchDirStr); +} \ No newline at end of file diff --git a/programs/nstool/source/UserSettings.h b/programs/nstool/source/UserSettings.h index a3fd6ed..573e124 100644 --- a/programs/nstool/source/UserSettings.h +++ b/programs/nstool/source/UserSettings.h @@ -8,6 +8,7 @@ #include #include #include "nstool.h" +#include "KeyConfiguration.h" class UserSettings { @@ -19,6 +20,7 @@ public: // generic options const std::string getInputPath() const; + const KeyConfiguration& getKeyCfg() const; const sKeyset& getKeyset() const; FileType getFileType() const; bool isVerifyFile() const; @@ -44,8 +46,15 @@ public: const sOptional& getAssetNacpPath() const; const fnd::List>& getCertificateChain() const; + void dumpKeys() const; + private: const std::string kModuleName = "UserSettings"; + + const std::string kHomeSwitchDirStr = ".switch"; + const std::string kGeneralKeyfileName[2] = { "prod.keys", "dev.keys" }; + const std::string kTitleKeyfileName = "title.keys"; + struct sCmdArgs { @@ -82,6 +91,7 @@ private: std::string mInputPath; FileType mFileType; sKeyset mKeyset; + KeyConfiguration mKeyCfg; bool mVerifyFile; CliOutputMode mOutputMode; @@ -109,7 +119,6 @@ private: void populateCmdArgs(const std::vector& arg_list, sCmdArgs& cmd_args); void populateKeyset(sCmdArgs& args); void populateUserSettings(sCmdArgs& args); - void decodeHexStringToBytes(const std::string& name, const std::string& str, byte_t* out, size_t out_len); FileType getFileTypeFromString(const std::string& type_str); FileType determineFileTypeFromFile(const std::string& path); bool determineValidNcaFromSample(const fnd::Vec& sample) const; @@ -118,4 +127,6 @@ private: bool determineValidEsCertFromSample(const fnd::Vec& sample) const; bool determineValidEsTikFromSample(const fnd::Vec& sample) const; nn::hac::npdm::InstructionType getInstructionTypeFromString(const std::string& type_str); + void getHomePath(std::string& path) const; + void getSwitchPath(std::string& path) const; }; \ No newline at end of file diff --git a/programs/nstool/source/nstool.h b/programs/nstool/source/nstool.h index ba36f7a..f1e3cf6 100644 --- a/programs/nstool/source/nstool.h +++ b/programs/nstool/source/nstool.h @@ -1,5 +1,4 @@ #pragma once -#pragma once #include #include #include @@ -61,6 +60,9 @@ struct sOptional inline T& operator*() { return var; } }; +const byte_t kDummyRightsIdForUserTitleKey[nn::hac::nca::kRightsIdLen] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const byte_t kDummyRightsIdForUserBodyKey[nn::hac::nca::kRightsIdLen] = {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}; + struct sKeyset { fnd::rsa::sRsa2048Key acid_sign_key; @@ -96,15 +98,4 @@ struct sKeyset { fnd::rsa::sRsa4096Key root_sign_key; } pki; -}; - -inline byte_t charToByte(char chr) -{ - if (chr >= 'a' && chr <= 'f') - return (chr - 'a') + 0xa; - else if (chr >= 'A' && chr <= 'F') - return (chr - 'A') + 0xa; - else if (chr >= '0' && chr <= '9') - return chr - '0'; - return 0; -} +}; \ No newline at end of file