diff --git a/programs/nstool/source/EsTikProcess.cpp b/programs/nstool/source/EsTikProcess.cpp index 5a3801a..5bae731 100644 --- a/programs/nstool/source/EsTikProcess.cpp +++ b/programs/nstool/source/EsTikProcess.cpp @@ -41,9 +41,9 @@ void EsTikProcess::setInputFile(fnd::IFile* file, bool ownIFile) mOwnIFile = ownIFile; } -void EsTikProcess::setKeyset(const sKeyset* keyset) +void EsTikProcess::setKeyCfg(const KeyConfiguration& keycfg) { - mKeyset = keyset; + mKeyCfg = keycfg; } void EsTikProcess::setCertificateChain(const fnd::List>& certs) @@ -95,7 +95,7 @@ void EsTikProcess::verifyTicket() try { - pki_validator.setRootKey(mKeyset->pki.root_sign_key); + pki_validator.setKeyCfg(mKeyCfg); pki_validator.addCertificates(mCerts); pki_validator.validateSignature(mTik.getBody().getIssuer(), mTik.getSignature().getSignType(), mTik.getSignature().getSignature(), tik_hash); } diff --git a/programs/nstool/source/EsTikProcess.h b/programs/nstool/source/EsTikProcess.h index 82d82d0..ae77ec3 100644 --- a/programs/nstool/source/EsTikProcess.h +++ b/programs/nstool/source/EsTikProcess.h @@ -6,6 +6,7 @@ #include #include #include +#include "KeyConfiguration.h" #include "nstool.h" class EsTikProcess @@ -17,7 +18,7 @@ public: void process(); void setInputFile(fnd::IFile* file, bool ownIFile); - void setKeyset(const sKeyset* keyset); + void setKeyCfg(const KeyConfiguration& keycfg); void setCertificateChain(const fnd::List>& certs); void setCliOutputMode(CliOutputMode mode); void setVerifyMode(bool verify); @@ -27,7 +28,7 @@ private: fnd::IFile* mFile; bool mOwnIFile; - const sKeyset* mKeyset; + KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/KeyConfiguration.cpp b/programs/nstool/source/KeyConfiguration.cpp index 0a4f7b1..91c1122 100644 --- a/programs/nstool/source/KeyConfiguration.cpp +++ b/programs/nstool/source/KeyConfiguration.cpp @@ -10,6 +10,39 @@ KeyConfiguration::KeyConfiguration() clearNcaExternalKeys(); } +KeyConfiguration::KeyConfiguration(const KeyConfiguration& other) +{ + *this = other; +} + +void KeyConfiguration::operator=(const KeyConfiguration& other) +{ + mAcidSignKey = other.mAcidSignKey; + mPkg2SignKey = other.mPkg2SignKey; + mNcaHeader0SignKey = other.mNcaHeader0SignKey; + mXciHeaderSignKey = other.mXciHeaderSignKey; + + mNcaHeaderKey = other.mNcaHeaderKey; + mXciHeaderKey = other.mXciHeaderKey; + + for (size_t i = 0; i < kMasterKeyNum; i++) + { + mPkg2Key[i] = other.mPkg2Key[i]; + mPkg1Key[i] = other.mPkg1Key[i]; + mNcaKeyAreaEncryptionKey[0][i] = other.mNcaKeyAreaEncryptionKey[0][i]; + mNcaKeyAreaEncryptionKey[1][i] = other.mNcaKeyAreaEncryptionKey[1][i]; + mNcaKeyAreaEncryptionKey[2][i] = other.mNcaKeyAreaEncryptionKey[2][i]; + mNcaKeyAreaEncryptionKeyHw[0][i] = other.mNcaKeyAreaEncryptionKeyHw[0][i]; + mNcaKeyAreaEncryptionKeyHw[1][i] = other.mNcaKeyAreaEncryptionKeyHw[1][i]; + mNcaKeyAreaEncryptionKeyHw[2][i] = other.mNcaKeyAreaEncryptionKeyHw[2][i]; + mETicketCommonKey[i] = other.mETicketCommonKey[i]; + } + + mPkiRootKeyList = other.mPkiRootKeyList; + + mNcaExternalContentKeyList = other.mNcaExternalContentKeyList; +} + void KeyConfiguration::importHactoolGenericKeyfile(const std::string& path) { clearGeneralKeyConfiguration(); diff --git a/programs/nstool/source/KeyConfiguration.h b/programs/nstool/source/KeyConfiguration.h index f5197cb..41a59e9 100644 --- a/programs/nstool/source/KeyConfiguration.h +++ b/programs/nstool/source/KeyConfiguration.h @@ -13,6 +13,9 @@ class KeyConfiguration { public: KeyConfiguration(); + KeyConfiguration(const KeyConfiguration& other); + + void operator=(const KeyConfiguration& other); void importHactoolGenericKeyfile(const std::string& path); //void importHactoolTitleKeyfile(const std::string& path); diff --git a/programs/nstool/source/NcaProcess.cpp b/programs/nstool/source/NcaProcess.cpp index 90de628..3878764 100644 --- a/programs/nstool/source/NcaProcess.cpp +++ b/programs/nstool/source/NcaProcess.cpp @@ -15,7 +15,6 @@ NcaProcess::NcaProcess() : mFile(nullptr), mOwnIFile(false), - mKeyset(nullptr), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), mListFs(false) @@ -72,9 +71,9 @@ void NcaProcess::setInputFile(fnd::IFile* file, bool ownIFile) mOwnIFile = ownIFile; } -void NcaProcess::setKeyset(const sKeyset* keyset) +void NcaProcess::setKeyCfg(const KeyConfiguration& keycfg) { - mKeyset = keyset; + mKeyCfg = keycfg; } void NcaProcess::setCliOutputMode(CliOutputMode type) @@ -127,7 +126,9 @@ void NcaProcess::importHeader() mFile->read((byte_t*)&mHdrBlock, 0, sizeof(nn::hac::sNcaHeaderBlock)); // decrypt header block - nn::hac::NcaUtils::decryptNcaHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, mKeyset->nca.header_key); + fnd::aes::sAesXts128Key header_key; + mKeyCfg.getNcaHeaderKey(header_key); + nn::hac::NcaUtils::decryptNcaHeader((byte_t*)&mHdrBlock, (byte_t*)&mHdrBlock, header_key); // generate header hash fnd::sha::Sha256((byte_t*)&mHdrBlock.header, sizeof(nn::hac::sNcaHeader), mHdrHash.bytes); @@ -149,23 +150,31 @@ void NcaProcess::generateNcaBodyEncryptionKeys() byte_t keak_index = mHdr.getKaekIndex(); // process key area - sKeys::sKeyAreaKey keak; + sKeys::sKeyAreaKey kak; + fnd::aes::sAes128Key key_area_enc_key; for (size_t i = 0; i < nn::hac::nca::kAesKeyNum; i++) { if (mHdr.getEncAesKeys()[i] != zero_aesctr_key) { - keak.index = (byte_t)i; - keak.enc = mHdr.getEncAesKeys()[i]; - if (i < 4 && mKeyset->nca.key_area_key[keak_index][masterkey_rev] != zero_aesctr_key) + kak.index = (byte_t)i; + kak.enc = mHdr.getEncAesKeys()[i]; + // key[0-3] + if (i < 4 && mKeyCfg.getNcaKeyAreaEncryptionKey(masterkey_rev, keak_index, key_area_enc_key) == true) { - keak.decrypted = true; - nn::hac::AesKeygen::generateKey(keak.dec.key, keak.enc.key, mKeyset->nca.key_area_key[keak_index][masterkey_rev].key); + kak.decrypted = true; + nn::hac::AesKeygen::generateKey(kak.dec.key, kak.enc.key, key_area_enc_key.key); + } + // key[4] + else if (i == 4 && mKeyCfg.getNcaKeyAreaEncryptionKeyHw(masterkey_rev, keak_index, key_area_enc_key) == true) + { + kak.decrypted = true; + nn::hac::AesKeygen::generateKey(kak.dec.key, kak.enc.key, key_area_enc_key.key); } else { - keak.decrypted = false; + kak.decrypted = false; } - mBodyKeys.keak_list.addElement(keak); + mBodyKeys.keak_list.addElement(kak); } } @@ -176,21 +185,19 @@ void NcaProcess::generateNcaBodyEncryptionKeys() // if this has a rights id, the key needs to be sourced from a ticket if (mHdr.hasRightsId() == true) { - // if the titlekey_kek is available - if (mKeyset->ticket.titlekey_kek[masterkey_rev] != zero_aesctr_key) + fnd::aes::sAes128Key tmp_key; + if (mKeyCfg.getNcaExternalContentKey(mHdr.getRightsId(), tmp_key) == true) { - // the title key is provided (sourced from ticket) - if (mKeyset->nca.manual_title_key_aesctr != zero_aesctr_key) + mBodyKeys.aes_ctr = tmp_key; + } + else if (mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserTitleKey, tmp_key) == true) + { + fnd::aes::sAes128Key common_key; + if (mKeyCfg.getETicketCommonKey(masterkey_rev, common_key) == true) { - nn::hac::AesKeygen::generateKey(mBodyKeys.aes_ctr.var.key, mKeyset->nca.manual_title_key_aesctr.key, mKeyset->ticket.titlekey_kek[masterkey_rev].key); - mBodyKeys.aes_ctr.isSet = true; - } - if (mKeyset->nca.manual_title_key_aesxts != zero_aesxts_key) - { - nn::hac::AesKeygen::generateKey(mBodyKeys.aes_xts.var.key[0], mKeyset->nca.manual_title_key_aesxts.key[0], mKeyset->ticket.titlekey_kek[masterkey_rev].key); - nn::hac::AesKeygen::generateKey(mBodyKeys.aes_xts.var.key[1], mKeyset->nca.manual_title_key_aesxts.key[1], mKeyset->ticket.titlekey_kek[masterkey_rev].key); - mBodyKeys.aes_xts.isSet = true; + nn::hac::AesKeygen::generateKey(tmp_key.key, tmp_key.key, common_key.key); } + mBodyKeys.aes_ctr = tmp_key; } } // otherwise decrypt key area @@ -225,15 +232,13 @@ void NcaProcess::generateNcaBodyEncryptionKeys() } // if the keys weren't generated, check if the keys were supplied by the user - if (mBodyKeys.aes_ctr.isSet == false && mKeyset->nca.manual_body_key_aesctr != zero_aesctr_key) + if (mBodyKeys.aes_ctr.isSet == false) { - mBodyKeys.aes_ctr = mKeyset->nca.manual_body_key_aesctr; - } - if (mBodyKeys.aes_xts.isSet == false && mKeyset->nca.manual_body_key_aesxts != zero_aesxts_key) - { - mBodyKeys.aes_xts = mKeyset->nca.manual_body_key_aesxts; + if (mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserBodyKey, mBodyKeys.aes_ctr.var) == true) + mBodyKeys.aes_ctr.isSet = true; } + if (_HAS_BIT(mCliOutputMode, OUTPUT_KEY_DATA)) { if (mBodyKeys.aes_ctr.isSet) @@ -365,7 +370,9 @@ void NcaProcess::generatePartitionConfiguration() void NcaProcess::validateNcaSignatures() { // validate signature[0] - if (fnd::rsa::pss::rsaVerify(mKeyset->nca.header_sign_key, fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_main) != 0) + fnd::rsa::sRsa2048Key sign0_key; + mKeyCfg.getNcaHeader0SignKey(sign0_key); + if (fnd::rsa::pss::rsaVerify(sign0_key, fnd::sha::HASH_SHA256, mHdrHash.bytes, mHdrBlock.signature_main) != 0) { std::cout << "[WARNING] NCA Header Main Signature: FAIL" << std::endl; } diff --git a/programs/nstool/source/NcaProcess.h b/programs/nstool/source/NcaProcess.h index a9b0806..3a34e98 100644 --- a/programs/nstool/source/NcaProcess.h +++ b/programs/nstool/source/NcaProcess.h @@ -4,6 +4,7 @@ #include #include #include "HashTreeMeta.h" +#include "KeyConfiguration.h" #include "nstool.h" @@ -18,7 +19,7 @@ public: // generic void setInputFile(fnd::IFile* file, bool ownIFile); - void setKeyset(const sKeyset* keyset); + void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -36,7 +37,7 @@ private: // user options fnd::IFile* mFile; bool mOwnIFile; - const sKeyset* mKeyset; + KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/NpdmProcess.cpp b/programs/nstool/source/NpdmProcess.cpp index b9f5fe6..71b9f14 100644 --- a/programs/nstool/source/NpdmProcess.cpp +++ b/programs/nstool/source/NpdmProcess.cpp @@ -5,7 +5,6 @@ NpdmProcess::NpdmProcess() : mFile(nullptr), mOwnIFile(false), - mKeyset(nullptr), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false) { @@ -57,9 +56,9 @@ void NpdmProcess::setInputFile(fnd::IFile* file, bool ownIFile) mOwnIFile = ownIFile; } -void NpdmProcess::setKeyset(const sKeyset* keyset) +void NpdmProcess::setKeyCfg(const KeyConfiguration& keycfg) { - mKeyset = keyset; + mKeyCfg = keycfg; } void NpdmProcess::setCliOutputMode(CliOutputMode type) @@ -95,7 +94,11 @@ void NpdmProcess::importNpdm() void NpdmProcess::validateAcidSignature(const nn::hac::AccessControlInfoDescBinary& acid) { try { - acid.validateSignature(mKeyset->acid_sign_key); + fnd::rsa::sRsa2048Key acid_sign_key; + if (mKeyCfg.getAcidSignKey(acid_sign_key) != true) + throw fnd::Exception(); + + acid.validateSignature(acid_sign_key); } catch (...) { std::cout << "[WARNING] ACID Signature: FAIL" << std::endl; diff --git a/programs/nstool/source/NpdmProcess.h b/programs/nstool/source/NpdmProcess.h index d476493..68c3523 100644 --- a/programs/nstool/source/NpdmProcess.h +++ b/programs/nstool/source/NpdmProcess.h @@ -3,6 +3,7 @@ #include #include #include +#include "KeyConfiguration.h" #include "nstool.h" @@ -15,7 +16,7 @@ public: void process(); void setInputFile(fnd::IFile* file, bool ownIFile); - void setKeyset(const sKeyset* keyset); + void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -26,7 +27,7 @@ private: fnd::IFile* mFile; bool mOwnIFile; - const sKeyset* mKeyset; + KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/PkiCertProcess.cpp b/programs/nstool/source/PkiCertProcess.cpp index bc71e09..f9912a3 100644 --- a/programs/nstool/source/PkiCertProcess.cpp +++ b/programs/nstool/source/PkiCertProcess.cpp @@ -39,9 +39,9 @@ void PkiCertProcess::setInputFile(fnd::IFile* file, bool ownIFile) mOwnIFile = ownIFile; } -void PkiCertProcess::setKeyset(const sKeyset* keyset) +void PkiCertProcess::setKeyCfg(const KeyConfiguration& keycfg) { - mKeyset = keyset; + mKeyCfg = keycfg; } void PkiCertProcess::setCliOutputMode(CliOutputMode mode) @@ -80,7 +80,7 @@ void PkiCertProcess::validateCerts() try { - pki.setRootKey(mKeyset->pki.root_sign_key); + pki.setKeyCfg(mKeyCfg); pki.addCertificates(mCert); } catch (const fnd::Exception& e) diff --git a/programs/nstool/source/PkiCertProcess.h b/programs/nstool/source/PkiCertProcess.h index e7dd144..964a70d 100644 --- a/programs/nstool/source/PkiCertProcess.h +++ b/programs/nstool/source/PkiCertProcess.h @@ -6,6 +6,7 @@ #include #include #include +#include "KeyConfiguration.h" #include "nstool.h" class PkiCertProcess @@ -17,7 +18,7 @@ public: void process(); void setInputFile(fnd::IFile* file, bool ownIFile); - void setKeyset(const sKeyset* keyset); + void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -27,7 +28,7 @@ private: fnd::IFile* mFile; bool mOwnIFile; - const sKeyset* mKeyset; + KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/PkiValidator.cpp b/programs/nstool/source/PkiValidator.cpp index 70c1589..37bb9b5 100644 --- a/programs/nstool/source/PkiValidator.cpp +++ b/programs/nstool/source/PkiValidator.cpp @@ -9,7 +9,7 @@ PkiValidator::PkiValidator() clearCertificates(); } -void PkiValidator::setRootKey(const fnd::rsa::sRsa4096Key& root_key) +void PkiValidator::setKeyCfg(const KeyConfiguration& keycfg) { // save a copy of the certificate bank fnd::List> old_certs = mCertificateBank; @@ -18,7 +18,7 @@ void PkiValidator::setRootKey(const fnd::rsa::sRsa4096Key& root_key) mCertificateBank.clear(); // overwrite the root key - mRootKey = root_key; + mKeyCfg = keycfg; // if there were certificates before, reimport them (so they are checked against the new root key) if (old_certs.size() > 0) @@ -96,13 +96,28 @@ void PkiValidator::validateSignature(const std::string& issuer, nn::pki::sign::S int sig_validate_res = -1; // special case if signed by Root - if (issuer == nn::pki::sign::kRootIssuerStr) + if (issuer.find('-', 0) == std::string::npos) { - if (sign_algo != nn::pki::sign::SIGN_ALGO_RSA4096) + fnd::rsa::sRsa4096Key rsa4096_pub; + fnd::rsa::sRsa2048Key rsa2048_pub; + fnd::ecdsa::sEcdsa240Key ecdsa_pub; + + if (mKeyCfg.getPkiRootSignKey(issuer, rsa4096_pub) == true && sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096) { - throw fnd::Exception(kModuleName, "Issued by Root, but does not have a RSA4096 signature"); + sig_validate_res = fnd::rsa::pkcs::rsaVerify(rsa4096_pub, getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data()); + } + else if (mKeyCfg.getPkiRootSignKey(issuer, rsa2048_pub) == true && sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048) + { + sig_validate_res = fnd::rsa::pkcs::rsaVerify(rsa2048_pub, getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data()); + } + else if (mKeyCfg.getPkiRootSignKey(issuer, ecdsa_pub) == true && sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240) + { + throw fnd::Exception(kModuleName, "ECDSA signatures are not supported"); + } + else + { + throw fnd::Exception(kModuleName, "Public key for issuer \"" + issuer + "\" does not exist."); } - sig_validate_res = fnd::rsa::pkcs::rsaVerify(mRootKey, getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data()); } else { diff --git a/programs/nstool/source/PkiValidator.h b/programs/nstool/source/PkiValidator.h index 6ef0bd2..7b7a0ab 100644 --- a/programs/nstool/source/PkiValidator.h +++ b/programs/nstool/source/PkiValidator.h @@ -6,13 +6,14 @@ #include #include #include +#include "KeyConfiguration.h" class PkiValidator { public: PkiValidator(); - void setRootKey(const fnd::rsa::sRsa4096Key& root_key); + void setKeyCfg(const KeyConfiguration& keycfg); void addCertificates(const fnd::List>& certs); void addCertificate(const nn::pki::SignedData& cert); void clearCertificates(); @@ -22,8 +23,7 @@ public: private: const std::string kModuleName = "NNPkiValidator"; - - fnd::rsa::sRsa4096Key mRootKey; + KeyConfiguration mKeyCfg; fnd::List> mCertificateBank; void makeCertIdent(const nn::pki::SignedData& cert, std::string& ident) const; diff --git a/programs/nstool/source/UserSettings.cpp b/programs/nstool/source/UserSettings.cpp index a587ede..ce1e929 100644 --- a/programs/nstool/source/UserSettings.cpp +++ b/programs/nstool/source/UserSettings.cpp @@ -96,9 +96,9 @@ const std::string UserSettings::getInputPath() const return mInputPath; } -const sKeyset& UserSettings::getKeyset() const +const KeyConfiguration& UserSettings::getKeyCfg() const { - return mKeyset; + return mKeyCfg; } FileType UserSettings::getFileType() const @@ -386,8 +386,6 @@ void UserSettings::populateCmdArgs(const std::vector& arg_list, sCm void UserSettings::populateKeyset(sCmdArgs& args) { - memset((void*)&mKeyset, 0, sizeof(sKeyset)); - if (args.keyset_path.isSet) { mKeyCfg.importHactoolGenericKeyfile(*args.keyset_path); @@ -413,22 +411,7 @@ void UserSettings::populateKeyset(sCmdArgs& args) } - 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++) - { - 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]); - } + if (args.nca_bodykey.isSet) { @@ -503,7 +486,7 @@ void UserSettings::populateKeyset(sCmdArgs& args) try { - pki_validator.setRootKey(mKeyset.pki.root_sign_key); + pki_validator.setKeyCfg(mKeyCfg); pki_validator.addCertificates(mCertChain); pki_validator.validateSignature(tik.getBody().getIssuer(), tik.getSignature().getSignType(), tik.getSignature().getSignature(), tik_hash); } @@ -519,7 +502,6 @@ void UserSettings::populateKeyset(sCmdArgs& args) { 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) { @@ -536,10 +518,6 @@ void UserSettings::populateKeyset(sCmdArgs& args) std::cout << "[WARNING] Titlekey not imported from ticket because it is personalised" << std::endl; } } - - // 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) @@ -721,7 +699,9 @@ bool UserSettings::determineValidNcaFromSample(const fnd::Vec& sample) c if (sample.size() < nn::hac::nca::kHeaderSize) return false; - nn::hac::NcaUtils::decryptNcaHeader(sample.data(), nca_raw, mKeyset.nca.header_key); + fnd::aes::sAesXts128Key header_key; + mKeyCfg.getNcaHeaderKey(header_key); + nn::hac::NcaUtils::decryptNcaHeader(sample.data(), nca_raw, header_key); if (nca_header->st_magic.get() != nn::hac::nca::kNca2StructMagic && nca_header->st_magic.get() != nn::hac::nca::kNca3StructMagic) return false; diff --git a/programs/nstool/source/UserSettings.h b/programs/nstool/source/UserSettings.h index 573e124..84450ba 100644 --- a/programs/nstool/source/UserSettings.h +++ b/programs/nstool/source/UserSettings.h @@ -21,7 +21,6 @@ public: // generic options const std::string getInputPath() const; const KeyConfiguration& getKeyCfg() const; - const sKeyset& getKeyset() const; FileType getFileType() const; bool isVerifyFile() const; CliOutputMode getCliOutputMode() const; @@ -90,7 +89,6 @@ private: std::string mInputPath; FileType mFileType; - sKeyset mKeyset; KeyConfiguration mKeyCfg; bool mVerifyFile; CliOutputMode mOutputMode; diff --git a/programs/nstool/source/XciProcess.cpp b/programs/nstool/source/XciProcess.cpp index b535204..48bde39 100644 --- a/programs/nstool/source/XciProcess.cpp +++ b/programs/nstool/source/XciProcess.cpp @@ -8,7 +8,6 @@ XciProcess::XciProcess() : mFile(nullptr), mOwnIFile(false), - mKeyset(nullptr), mCliOutputMode(_BIT(OUTPUT_BASIC)), mVerify(false), mListFs(false), @@ -50,9 +49,9 @@ void XciProcess::setInputFile(fnd::IFile* file, bool ownIFile) mOwnIFile = ownIFile; } -void XciProcess::setKeyset(const sKeyset* keyset) +void XciProcess::setKeyCfg(const KeyConfiguration& keycfg) { - mKeyset = keyset; + mKeyCfg = keycfg; } void XciProcess::setCliOutputMode(CliOutputMode type) @@ -89,7 +88,10 @@ void XciProcess::importHeader() // allocate memory for and decrypt sXciHeader scratch.alloc(sizeof(nn::hac::sXciHeader)); - nn::hac::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.data(), mKeyset->xci.header_key.key); + + fnd::aes::sAes128Key header_key; + mKeyCfg.getXciHeaderKey(header_key); + nn::hac::XciUtils::decryptXciHeader((const byte_t*)&mHdrPage.header, scratch.data(), header_key.key); // deserialise header mHdr.fromBytes(scratch.data(), scratch.size()); @@ -198,9 +200,11 @@ bool XciProcess::validateRegionOfFile(size_t offset, size_t len, const byte_t* t void XciProcess::validateXciSignature() { + fnd::rsa::sRsa2048Key header_sign_key; fnd::sha::sSha256Hash calc_hash; fnd::sha::Sha256((byte_t*)&mHdrPage.header, sizeof(nn::hac::sXciHeader), calc_hash.bytes); - if (fnd::rsa::pkcs::rsaVerify(mKeyset->xci.header_sign_key, fnd::sha::HASH_SHA256, calc_hash.bytes, mHdrPage.signature) != 0) + mKeyCfg.getXciHeaderSignKey(header_sign_key); + if (fnd::rsa::pkcs::rsaVerify(header_sign_key, fnd::sha::HASH_SHA256, calc_hash.bytes, mHdrPage.signature) != 0) { std::cout << "[WARNING] XCI Header Signature: FAIL" << std::endl; } diff --git a/programs/nstool/source/XciProcess.h b/programs/nstool/source/XciProcess.h index c3da185..0978b18 100644 --- a/programs/nstool/source/XciProcess.h +++ b/programs/nstool/source/XciProcess.h @@ -4,11 +4,10 @@ #include #include #include - -#include "nstool.h" - +#include "KeyConfiguration.h" #include "PfsProcess.h" +#include "nstool.h" class XciProcess { @@ -20,7 +19,7 @@ public: // generic void setInputFile(fnd::IFile* file, bool ownIFile); - void setKeyset(const sKeyset* keyset); + void setKeyCfg(const KeyConfiguration& keycfg); void setCliOutputMode(CliOutputMode type); void setVerifyMode(bool verify); @@ -34,7 +33,7 @@ private: fnd::IFile* mFile; bool mOwnIFile; - const sKeyset* mKeyset; + KeyConfiguration mKeyCfg; CliOutputMode mCliOutputMode; bool mVerify; diff --git a/programs/nstool/source/main.cpp b/programs/nstool/source/main.cpp index 6a30e29..9659241 100644 --- a/programs/nstool/source/main.cpp +++ b/programs/nstool/source/main.cpp @@ -41,7 +41,7 @@ int main(int argc, char** argv) xci.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); - xci.setKeyset(&user_set.getKeyset()); + xci.setKeyCfg(user_set.getKeyCfg()); xci.setCliOutputMode(user_set.getCliOutputMode()); xci.setVerifyMode(user_set.isVerifyFile()); @@ -90,7 +90,7 @@ int main(int argc, char** argv) NcaProcess nca; nca.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); - nca.setKeyset(&user_set.getKeyset()); + nca.setKeyCfg(user_set.getKeyCfg()); nca.setCliOutputMode(user_set.getCliOutputMode()); nca.setVerifyMode(user_set.isVerifyFile()); @@ -112,7 +112,7 @@ int main(int argc, char** argv) NpdmProcess npdm; npdm.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); - npdm.setKeyset(&user_set.getKeyset()); + npdm.setKeyCfg(user_set.getKeyCfg()); npdm.setCliOutputMode(user_set.getCliOutputMode()); npdm.setVerifyMode(user_set.isVerifyFile()); @@ -180,7 +180,7 @@ int main(int argc, char** argv) PkiCertProcess cert; cert.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); - cert.setKeyset(&user_set.getKeyset()); + cert.setKeyCfg(user_set.getKeyCfg()); cert.setCliOutputMode(user_set.getCliOutputMode()); cert.setVerifyMode(user_set.isVerifyFile()); @@ -191,7 +191,7 @@ int main(int argc, char** argv) EsTikProcess tik; tik.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE); - tik.setKeyset(&user_set.getKeyset()); + tik.setKeyCfg(user_set.getKeyCfg()); tik.setCertificateChain(user_set.getCertificateChain()); tik.setCliOutputMode(user_set.getCliOutputMode()); tik.setVerifyMode(user_set.isVerifyFile()); diff --git a/programs/nstool/source/nstool.h b/programs/nstool/source/nstool.h index f1e3cf6..6bdf571 100644 --- a/programs/nstool/source/nstool.h +++ b/programs/nstool/source/nstool.h @@ -61,41 +61,4 @@ struct sOptional }; 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; - fnd::aes::sAes128Key package1_key[kMasterKeyNum]; - fnd::rsa::sRsa2048Key package2_sign_key; - fnd::aes::sAes128Key package2_key[kMasterKeyNum]; - - struct sNcaData - { - fnd::rsa::sRsa2048Key header_sign_key; - fnd::aes::sAesXts128Key header_key; - fnd::aes::sAes128Key key_area_key[kNcaKeakNum][kMasterKeyNum]; - - fnd::aes::sAes128Key manual_title_key_aesctr; - fnd::aes::sAesXts128Key manual_title_key_aesxts; - fnd::aes::sAes128Key manual_body_key_aesctr; - fnd::aes::sAesXts128Key manual_body_key_aesxts; - } nca; - - struct sXciData - { - fnd::rsa::sRsa2048Key header_sign_key; - fnd::aes::sAes128Key header_key; - } xci; - - struct sTicketData - { - fnd::rsa::sRsa2048Key sign_key; - fnd::aes::sAes128Key titlekey_kek[kMasterKeyNum]; - } ticket; - - struct sPkiData - { - fnd::rsa::sRsa4096Key root_sign_key; - } pki; -}; \ No newline at end of file +const byte_t kDummyRightsIdForUserBodyKey[nn::hac::nca::kRightsIdLen] = {0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe}; \ No newline at end of file