mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 00:39:14 +00:00
Enable CiaProcess to fallback use certs to verify cert/tik/tmd.
This commit is contained in:
+55
-34
@@ -23,6 +23,7 @@ ctrtool::CiaProcess::CiaProcess() :
|
|||||||
mFooterExtractPath(),
|
mFooterExtractPath(),
|
||||||
mContentIndex(0),
|
mContentIndex(0),
|
||||||
mIssuerSigner(),
|
mIssuerSigner(),
|
||||||
|
mCertImportedIssuerSigner(),
|
||||||
mCertChain(),
|
mCertChain(),
|
||||||
mCertSigValid(),
|
mCertSigValid(),
|
||||||
mTicket(),
|
mTicket(),
|
||||||
@@ -255,37 +256,36 @@ void ctrtool::CiaProcess::importHeader()
|
|||||||
// process CIA
|
// process CIA
|
||||||
if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default)
|
if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default)
|
||||||
{
|
{
|
||||||
std::shared_ptr<tc::io::IStream> cert_stream;
|
|
||||||
if (mCertSizeInfo.size > 0)
|
if (mCertSizeInfo.size > 0)
|
||||||
{
|
{
|
||||||
cert_stream = std::shared_ptr<tc::io::SubStream>(new tc::io::SubStream(mInputStream, mCertSizeInfo.offset, mCertSizeInfo.size));
|
std::shared_ptr<tc::io::IStream> certchain_stream = std::shared_ptr<tc::io::SubStream>(new tc::io::SubStream(mInputStream, mCertSizeInfo.offset, mCertSizeInfo.size));
|
||||||
|
|
||||||
if (mCertSizeInfo.size < 0x1000000)
|
while (certchain_stream->position() < certchain_stream->length())
|
||||||
{
|
{
|
||||||
tc::ByteData cert_data = tc::ByteData(mCertSizeInfo.size);
|
std::shared_ptr<tc::io::IStream> cert_stream = std::make_shared<tc::io::SubStream>(tc::io::SubStream(certchain_stream, certchain_stream->position(), certchain_stream->length() - certchain_stream->position()));
|
||||||
|
mCertChain.push_back(ntd::n3ds::es::CertificateDeserialiser(cert_stream));
|
||||||
|
mCertSigValid.push_back(ValidState::Unchecked);
|
||||||
|
|
||||||
cert_stream->seek(0, tc::io::SeekOrigin::Begin);
|
// update position of input stream
|
||||||
cert_stream->read(cert_data.data(), cert_data.size());
|
//certchain_stream->seek(cert_stream->position(), tc::io::SeekOrigin::Current);
|
||||||
|
|
||||||
for (size_t certchain_pos = 0; certchain_pos < cert_data.size();)
|
// import issuer profile from certificate
|
||||||
|
if (mCertChain.back().public_key_type == brd::es::ESCertPubKeyType::RSA2048)
|
||||||
{
|
{
|
||||||
size_t certbin_size = ntd::n3ds::es::getCertificateSize(cert_data.data() + certchain_pos);
|
std::string issuer = fmt::format("{}-{}", mCertChain.back().signature.issuer, mCertChain.back().subject);
|
||||||
if (certbin_size == 0)
|
brd::es::ESSigType sig_type = brd::es::ESSigType::RSA2048_SHA256;
|
||||||
{
|
auto& public_key = mCertChain.back().rsa2048_public_key;
|
||||||
throw tc::InvalidOperationException(mModuleLabel, "Certificate chain had invalid data.");
|
|
||||||
}
|
|
||||||
|
|
||||||
mCertChain.push_back(ntd::n3ds::es::CertificateDeserialiser(std::make_shared<tc::io::SubStream>(tc::io::SubStream(cert_stream, certchain_pos, certbin_size))));
|
mCertImportedIssuerSigner.insert(std::pair<std::string, std::shared_ptr<ntd::n3ds::es::ISigner>>(issuer, std::make_shared<ntd::n3ds::es::RsaSigner>(ntd::n3ds::es::RsaSigner(sig_type, issuer, tc::crypto::RsaPublicKey(public_key.m.data(), public_key.m.size())))));
|
||||||
mCertSigValid.push_back(ValidState::Unchecked);
|
}
|
||||||
|
else if (mCertChain.back().public_key_type == brd::es::ESCertPubKeyType::RSA4096)
|
||||||
certchain_pos += certbin_size;
|
{
|
||||||
|
std::string issuer = fmt::format("{}-{}", mCertChain.back().signature.issuer + mCertChain.back().subject);
|
||||||
|
brd::es::ESSigType sig_type = brd::es::ESSigType::RSA4096_SHA256;
|
||||||
|
auto& public_key = mCertChain.back().rsa4096_public_key;
|
||||||
|
|
||||||
|
mCertImportedIssuerSigner.insert(std::pair<std::string, std::shared_ptr<ntd::n3ds::es::ISigner>>(issuer, std::make_shared<ntd::n3ds::es::RsaSigner>(ntd::n3ds::es::RsaSigner(sig_type, issuer, tc::crypto::RsaPublicKey(public_key.m.data(), public_key.m.size())))));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fmt::print("[LOG] Certificate chain too large, cannot verify Ticket or TitleMetaData.\n");
|
|
||||||
mCertSizeInfo.size = 0;
|
|
||||||
mCertSizeInfo.offset = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -406,11 +406,18 @@ void ctrtool::CiaProcess::verifyMetadata()
|
|||||||
// verify cert
|
// verify cert
|
||||||
for (size_t i = 0; i < mCertChain.size(); i++)
|
for (size_t i = 0; i < mCertChain.size(); i++)
|
||||||
{
|
{
|
||||||
auto issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer);
|
auto keybag_issuer_itr = mIssuerSigner.find(mCertChain[i].signature.issuer);
|
||||||
if (issuer_itr != mIssuerSigner.end() && issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type)
|
auto local_issuer_itr = mCertImportedIssuerSigner.find(mCertChain[i].signature.issuer);
|
||||||
|
|
||||||
|
// try first with the keybag imported issuer
|
||||||
|
if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type)
|
||||||
{
|
{
|
||||||
//fmt::print("CertHash[{:d}]: {}\n", i, getTruncatedBytesString(mCertChain[i].calculated_hash.data(), mCertChain[i].calculated_hash.size(), mVerbose));
|
mCertSigValid[i] = keybag_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
||||||
mCertSigValid[i] = issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
}
|
||||||
|
// fallback try with the issuer profiles imported from the local certificates
|
||||||
|
else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mCertChain[i].signature.sig_type)
|
||||||
|
{
|
||||||
|
mCertSigValid[i] = local_issuer_itr->second->verifyHash(mCertChain[i].calculated_hash.data(), mCertChain[i].signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -423,11 +430,18 @@ void ctrtool::CiaProcess::verifyMetadata()
|
|||||||
if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTikSizeInfo.size > 0)
|
if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTikSizeInfo.size > 0)
|
||||||
{
|
{
|
||||||
// verify ticket
|
// verify ticket
|
||||||
auto issuer_itr = mIssuerSigner.find(mTicket.signature.issuer);
|
auto keybag_issuer_itr = mIssuerSigner.find(mTicket.signature.issuer);
|
||||||
if (issuer_itr != mIssuerSigner.end() && issuer_itr->second->getSigType() == mTicket.signature.sig_type)
|
auto local_issuer_itr = mCertImportedIssuerSigner.find(mTicket.signature.issuer);
|
||||||
|
|
||||||
|
// try first with the keybag imported issuer
|
||||||
|
if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTicket.signature.sig_type)
|
||||||
{
|
{
|
||||||
//fmt::print("TikHash: {}\n", getTruncatedBytesString(mTicket.calculated_hash.data(), mTicket.calculated_hash.size(), mVerbose));
|
mTicketSigValid = keybag_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
||||||
mTicketSigValid = issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
}
|
||||||
|
// fallback try with the issuer profiles imported from the local certificates
|
||||||
|
else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTicket.signature.sig_type)
|
||||||
|
{
|
||||||
|
mTicketSigValid = local_issuer_itr->second->verifyHash(mTicket.calculated_hash.data(), mTicket.signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -439,11 +453,18 @@ void ctrtool::CiaProcess::verifyMetadata()
|
|||||||
if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTmdSizeInfo.size > 0)
|
if (mHeader.format_version.unwrap() == ntd::n3ds::CiaHeader::FormatVersion_Default && mTmdSizeInfo.size > 0)
|
||||||
{
|
{
|
||||||
// verify tmd
|
// verify tmd
|
||||||
auto issuer_itr = mIssuerSigner.find(mTitleMetaData.signature.issuer);
|
auto keybag_issuer_itr = mIssuerSigner.find(mTitleMetaData.signature.issuer);
|
||||||
if (issuer_itr != mIssuerSigner.end() && issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type)
|
auto local_issuer_itr = mCertImportedIssuerSigner.find(mTitleMetaData.signature.issuer);
|
||||||
|
|
||||||
|
// try first with the keybag imported issuer
|
||||||
|
if (keybag_issuer_itr != mIssuerSigner.end() && keybag_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type)
|
||||||
{
|
{
|
||||||
//fmt::print("TmdHash: {}\n", getTruncatedBytesString(mTitleMetaData.calculated_hash.data(), mTitleMetaData.calculated_hash.size(), mVerbose));
|
mTitleMetaDataSigValid = keybag_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
||||||
mTitleMetaDataSigValid = issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
}
|
||||||
|
// fallback try with the issuer profiles imported from the local certificates
|
||||||
|
else if (local_issuer_itr != mCertImportedIssuerSigner.end() && local_issuer_itr->second->getSigType() == mTitleMetaData.signature.sig_type)
|
||||||
|
{
|
||||||
|
mTitleMetaDataSigValid = local_issuer_itr->second->verifyHash(mTitleMetaData.calculated_hash.data(), mTitleMetaData.signature.sig.data()) ? ValidState::Good : ValidState::Fail;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ private:
|
|||||||
// process variables
|
// process variables
|
||||||
ntd::n3ds::CiaHeader mHeader;
|
ntd::n3ds::CiaHeader mHeader;
|
||||||
std::map<std::string, std::shared_ptr<ntd::n3ds::es::ISigner>> mIssuerSigner;
|
std::map<std::string, std::shared_ptr<ntd::n3ds::es::ISigner>> mIssuerSigner;
|
||||||
|
std::map<std::string, std::shared_ptr<ntd::n3ds::es::ISigner>> mCertImportedIssuerSigner;
|
||||||
std::vector<ntd::n3ds::es::Certificate> mCertChain;
|
std::vector<ntd::n3ds::es::Certificate> mCertChain;
|
||||||
std::vector<ValidState> mCertSigValid;
|
std::vector<ValidState> mCertSigValid;
|
||||||
ntd::n3ds::es::Ticket mTicket;
|
ntd::n3ds::es::Ticket mTicket;
|
||||||
|
|||||||
Reference in New Issue
Block a user