[nstool] Migrated from sKeyset to KeyConfiguration

This commit is contained in:
jakcron 2018-08-21 20:03:19 +08:00
parent 67a13b9d34
commit 1fd8f59025
18 changed files with 149 additions and 140 deletions

View file

@ -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<nn::pki::SignedData<nn::pki::CertificateBody>>& 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);
}

View file

@ -6,6 +6,7 @@
#include <nn/pki/SignedData.h>
#include <nn/pki/CertificateBody.h>
#include <nn/es/TicketBody_V2.h>
#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<nn::pki::SignedData<nn::pki::CertificateBody>>& 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;

View file

@ -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();

View file

@ -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);

View file

@ -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)
{
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;
mBodyKeys.aes_ctr = tmp_key;
}
if (mKeyset->nca.manual_title_key_aesxts != zero_aesxts_key)
else if (mKeyCfg.getNcaExternalContentKey(kDummyRightsIdForUserTitleKey, tmp_key) == true)
{
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;
fnd::aes::sAes128Key common_key;
if (mKeyCfg.getETicketCommonKey(masterkey_rev, common_key) == 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;
}

View file

@ -4,6 +4,7 @@
#include <fnd/SimpleFile.h>
#include <nn/hac/NcaHeader.h>
#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;

View file

@ -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;

View file

@ -3,6 +3,7 @@
#include <fnd/types.h>
#include <fnd/IFile.h>
#include <nn/hac/NpdmBinary.h>
#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;

View file

@ -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)

View file

@ -6,6 +6,7 @@
#include <fnd/Vec.h>
#include <nn/pki/SignedData.h>
#include <nn/pki/CertificateBody.h>
#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;

View file

@ -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<nn::pki::SignedData<nn::pki::CertificateBody>> 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
{

View file

@ -6,13 +6,14 @@
#include <nn/pki/SignedData.h>
#include <nn/pki/CertificateBody.h>
#include <string>
#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<nn::pki::SignedData<nn::pki::CertificateBody>>& certs);
void addCertificate(const nn::pki::SignedData<nn::pki::CertificateBody>& cert);
void clearCertificates();
@ -22,8 +23,7 @@ public:
private:
const std::string kModuleName = "NNPkiValidator";
fnd::rsa::sRsa4096Key mRootKey;
KeyConfiguration mKeyCfg;
fnd::List<nn::pki::SignedData<nn::pki::CertificateBody>> mCertificateBank;
void makeCertIdent(const nn::pki::SignedData<nn::pki::CertificateBody>& cert, std::string& ident) const;

View file

@ -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<std::string>& 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<byte_t>& 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;

View file

@ -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;

View file

@ -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;
}

View file

@ -4,11 +4,10 @@
#include <fnd/IFile.h>
#include <fnd/List.h>
#include <nn/hac/XciHeader.h>
#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;

View file

@ -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());

View file

@ -62,40 +62,3 @@ 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;
};