Move some files around to test each process as it's ported.

This commit is contained in:
jakcron 2021-10-01 17:39:34 +08:00
parent 258173915c
commit 09e6b8a857
30 changed files with 258 additions and 248 deletions

View file

@ -35,7 +35,7 @@ void nstool::AssetProcess::setVerifyMode(bool verify)
void nstool::AssetProcess::setListFs(bool list)
{
mRomfs.setListFs(list);
//mRomfs.setListFs(list);
}
void nstool::AssetProcess::setIconExtractPath(const tc::io::Path& path)
@ -50,7 +50,7 @@ void nstool::AssetProcess::setNacpExtractPath(const tc::io::Path& path)
void nstool::AssetProcess::setRomfsExtractPath(const tc::io::Path& path)
{
mRomfs.setExtractPath(path);
//mRomfs.setExtractPath(path);
}
@ -95,11 +95,11 @@ void nstool::AssetProcess::processSections()
writeSubStreamToFile(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size, mNacpExtractPath.get());
}
mNacp.setInputFile(std::make_shared<tc::io::SubStream>(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size));
mNacp.setCliOutputMode(mCliOutputMode);
mNacp.setVerifyMode(mVerify);
//mNacp.setInputFile(std::make_shared<tc::io::SubStream>(mFile, mHdr.getNacpInfo().offset, mHdr.getNacpInfo().size));
//mNacp.setCliOutputMode(mCliOutputMode);
//mNacp.setVerifyMode(mVerify);
mNacp.process();
//mNacp.process();
}
if (mHdr.getRomfsInfo().size > 0)
@ -107,11 +107,11 @@ void nstool::AssetProcess::processSections()
if ((mHdr.getRomfsInfo().size + mHdr.getRomfsInfo().offset) > file_size)
throw tc::Exception(mModuleName, "ASET geometry for romfs beyond file size");
mRomfs.setInputFile(std::make_shared<tc::io::SubStream>(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size));
mRomfs.setCliOutputMode(mCliOutputMode);
mRomfs.setVerifyMode(mVerify);
//mRomfs.setInputFile(std::make_shared<tc::io::SubStream>(mFile, mHdr.getRomfsInfo().offset, mHdr.getRomfsInfo().size));
//mRomfs.setCliOutputMode(mCliOutputMode);
//mRomfs.setVerifyMode(mVerify);
mRomfs.process();
//mRomfs.process();
}
}

View file

@ -36,8 +36,8 @@ private:
tc::Optional<tc::io::Path> mNacpExtractPath;
nn::hac::AssetHeader mHdr;
NacpProcess mNacp;
RomfsProcess mRomfs;
//NacpProcess mNacp;
//RomfsProcess mRomfs;
void importHeader();
void processSections();

View file

@ -45,7 +45,6 @@ void nstool::CnmtProcess::importCnmt()
throw tc::Exception(mModuleName, "No file reader set.");
}
// check if file_size is greater than 20MB, don't import.
size_t cnmt_file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
if (cnmt_file_size > (0x100000 * 20))
@ -68,7 +67,7 @@ void nstool::CnmtProcess::displayCnmt()
fmt::print("[ContentMeta]\n");
fmt::print(" TitleId: 0x{:016x}\n", mCnmt.getTitleId());
fmt::print(" Version: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getVersionAsString(mCnmt.getTitleVersion()), mCnmt.getTitleVersion());
fmt::print(" Type: {:s} (v{:d})\n", nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()), (uint32_t)mCnmt.getContentMetaType());
fmt::print(" Type: {:s} ({:d})\n", nn::hac::ContentMetaUtil::getContentMetaTypeAsString(mCnmt.getContentMetaType()), (uint32_t)mCnmt.getContentMetaType());
fmt::print(" Attributes: 0x{:x}", *((byte_t*)&cnmt_hdr->attributes));
if (mCnmt.getAttribute().size())
{

View file

@ -1,14 +1,10 @@
#include <iostream>
#include <iomanip>
#include <fnd/SimpleTextOutput.h>
#include <fnd/OffsetAdjustedIFile.h>
#include <nn/pki/SignUtils.h>
#include "EsTikProcess.h"
#include "PkiValidator.h"
#include <nn/pki/SignUtils.h>
nstool::EsTikProcess::EsTikProcess() :
mModuleName("nstool::EsTikProcess"),
mFile(),
mCliOutputMode(true, false, false, false),
mVerify(false)
@ -53,16 +49,23 @@ void nstool::EsTikProcess::setVerifyMode(bool verify)
void nstool::EsTikProcess::importTicket()
{
tc::ByteData scratch;
if (*mFile == nullptr)
if (mFile == nullptr)
{
throw tc::Exception(kModuleName, "No file reader set.");
throw tc::Exception(mModuleName, "No file reader set.");
}
scratch.alloc((*mFile)->size());
(*mFile)->read(scratch.data(), 0, scratch.size());
// check if file_size is greater than 20MB, don't import.
size_t file_size = tc::io::IOUtil::castInt64ToSize(mFile->length());
if (file_size > (0x100000 * 20))
{
throw tc::Exception(mModuleName, "File too large.");
}
// read cnmt
tc::ByteData scratch = tc::ByteData(file_size);
mFile->seek(0, tc::io::SeekOrigin::Begin);
mFile->read(scratch.data(), scratch.size());
mTik.fromBytes(scratch.data(), scratch.size());
}
@ -74,12 +77,12 @@ void nstool::EsTikProcess::verifyTicket()
switch (nn::pki::sign::getHashAlgo(mTik.getSignature().getSignType()))
{
case (nn::pki::sign::HASH_ALGO_SHA1):
tik_hash.alloc(fnd::sha::kSha1HashLen);
fnd::sha::Sha1(mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size(), tik_hash.data());
tik_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize);
tc::crypto::GenerateSha1Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size());
break;
case (nn::pki::sign::HASH_ALGO_SHA256):
tik_hash.alloc(fnd::sha::kSha256HashLen);
fnd::sha::Sha256(mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size(), tik_hash.data());
tik_hash = tc::ByteData(tc::crypto::Sha256Generator::kHashSize);
tc::crypto::GenerateSha256Hash(tik_hash.data(), mTik.getBody().getBytes().data(), mTik.getBody().getBytes().size());
break;
}
@ -91,85 +94,73 @@ void nstool::EsTikProcess::verifyTicket()
}
catch (const tc::Exception& e)
{
std::cout << "[WARNING] Ticket signature could not be validated (" << e.error() << ")" << std::endl;
fmt::print("[WARNING] Ticket signature could not be validated ({:s})\n", e.error());
}
}
void nstool::EsTikProcess::displayTicket()
{
#define _SPLIT_VER(ver) (uint32_t)((ver>>10) & 0x3f) << "." << (uint32_t)((ver>>4) & 0x3f) << "." << (uint32_t)((ver>>0) & 0xf)
const nn::es::TicketBody_V2& body = mTik.getBody();
std::cout << "[ES Ticket]" << std::endl;
std::cout << " SignType: " << getSignTypeStr(mTik.getSignature().getSignType());
fmt::print("[ES Ticket]\n");
fmt::print(" SignType: {:s}", getSignTypeStr(mTik.getSignature().getSignType()));
if (mCliOutputMode.show_extended_info)
std::cout << " (0x" << std::hex << mTik.getSignature().getSignType() << ")";
std::cout << std::endl;
fmt::print(" (0x{:x})", mTik.getSignature().getSignType());
fmt::print("\n");
std::cout << " Issuer: " << body.getIssuer() << std::endl;
std::cout << " Title Key:" << std::endl;
std::cout << " EncMode: " << getTitleKeyPersonalisationStr(body.getTitleKeyEncType()) << std::endl;
std::cout << " KeyGeneration: " << std::dec << (uint32_t)body.getCommonKeyId() << std::endl;
fmt::print(" Issuer: {:s}\n", body.getIssuer());
fmt::print(" Title Key:\n");
fmt::print(" EncMode: {:s}\n", getTitleKeyPersonalisationStr(body.getTitleKeyEncType()));
fmt::print(" KeyGeneration: {:d}\n", (uint32_t)body.getCommonKeyId());
if (body.getTitleKeyEncType() == nn::es::ticket::RSA2048)
{
std::cout << " Data:" << std::endl;
for (size_t i = 0; i < 0x10; i++)
std::cout << " " << fnd::SimpleTextOutput::arrayToString(body.getEncTitleKey() + 0x10*i, 0x10, true, ":") << std::endl;
fmt::print(" Data:\n");
fmt::print(" {:s}", tc::cli::FormatUtil::formatBytesAsStringWithLineLimit(body.getEncTitleKey(), 0x100, true, ":", 0x10, 6, false));
}
else if (body.getTitleKeyEncType() == nn::es::ticket::AES128_CBC)
{
std::cout << " Data:" << std::endl;
std::cout << " " << fnd::SimpleTextOutput::arrayToString(body.getEncTitleKey(), 0x10, true, ":") << std::endl;
fmt::print(" Data:\n");
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getEncTitleKey(), 0x10, true, ":"));
}
else
{
std::cout << " Data: <cannot display>" << std::endl;
fmt::print(" Data: <cannot display>\n");
}
std::cout << " Version: v" << _SPLIT_VER(body.getTicketVersion());
if (mCliOutputMode.show_extended_info)
std::cout << " (" << (uint32_t)body.getTicketVersion() << ")";
std::cout << std::endl;
std::cout << " License Type: " << getLicenseTypeStr(body.getLicenseType()) << std::endl;
fmt::print(" Version: {:s} (v{:d})\n", getTitleVersionStr(body.getTicketVersion()), body.getTicketVersion());
fmt::print(" License Type: {:s}\n", getLicenseTypeStr(body.getLicenseType()));
if (body.getPropertyFlags().size() > 0)
{
std::cout << " Flags:" << std::endl;
nn::es::sTicketBody_v2* raw_body = (nn::es::sTicketBody_v2*)body.getBytes().data();
fmt::print(" PropertyMask: 0x{:04x}\n", ((tc::bn::le16<uint16_t>*)&raw_body->property_mask)->unwrap());
for (size_t i = 0; i < body.getPropertyFlags().size(); i++)
{
std::cout << " " << getPropertyFlagStr(body.getPropertyFlags()[i]) << std::endl;
fmt::print(" {:s}\n", getPropertyFlagStr(body.getPropertyFlags()[i]));
}
}
if (mCliOutputMode.show_extended_info)
{
std::cout << " Reserved Region:" << std::endl;
fnd::SimpleTextOutput::hexDump(body.getReservedRegion(), 8, 0x10, 4);
fmt::print(" Reserved Region:\n");
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getReservedRegion(), 8, true, ""));
}
if (body.getTicketId() != 0 || mCliOutputMode.show_extended_info)
std::cout << " TicketId: 0x" << std::hex << std::setw(16) << std::setfill('0') << body.getTicketId() << std::endl;
fmt::print(" TicketId: 0x{:016x}\n", body.getTicketId());
if (body.getDeviceId() != 0 || mCliOutputMode.show_extended_info)
std::cout << " DeviceId: 0x" << std::hex << std::setw(16) << std::setfill('0') << body.getDeviceId() << std::endl;
fmt::print(" DeviceId: 0x{:016x}\n", body.getDeviceId());
std::cout << " RightsId: " << std::endl << " ";
fnd::SimpleTextOutput::hexDump(body.getRightsId(), 16);
fmt::print(" RightsId: \n");
fmt::print(" {:s}\n", tc::cli::FormatUtil::formatBytesAsString(body.getRightsId(), 16, true, ""));
std::cout << " SectionTotalSize: 0x" << std::hex << body.getSectionTotalSize() << std::endl;
std::cout << " SectionHeaderOffset: 0x" << std::hex << body.getSectionHeaderOffset() << std::endl;
std::cout << " SectionNum: 0x" << std::hex << body.getSectionNum() << std::endl;
std::cout << " SectionEntrySize: 0x" << std::hex << body.getSectionEntrySize() << std::endl;
#undef _SPLIT_VER
fmt::print(" SectionTotalSize: 0x{:x}\n", body.getSectionTotalSize());
fmt::print(" SectionHeaderOffset: 0x{:x}\n", body.getSectionHeaderOffset());
fmt::print(" SectionNum: 0x{:x}\n", body.getSectionNum());
fmt::print(" SectionEntrySize: 0x{:x}\n", body.getSectionEntrySize());
}
const char* nstool::EsTikProcess::getSignTypeStr(uint32_t type) const
std::string nstool::EsTikProcess::getSignTypeStr(uint32_t type) const
{
const char* str = nullptr;
std::string str;
switch(type)
{
case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
@ -197,9 +188,9 @@ const char* nstool::EsTikProcess::getSignTypeStr(uint32_t type) const
return str;
}
const char* nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) const
std::string nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) const
{
const char* str = nullptr;
std::string str;
switch(flag)
{
case (nn::es::ticket::AES128_CBC):
@ -209,15 +200,15 @@ const char* nstool::EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) con
str = "Personalised (RSA2048)";
break;
default:
str = "Unknown";
str = fmt::format("Unknown ({:d})", flag);
break;
}
return str;
}
const char* nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const
std::string nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const
{
const char* str = nullptr;
std::string str;
switch(flag)
{
case (nn::es::ticket::LICENSE_PERMANENT):
@ -239,15 +230,15 @@ const char* nstool::EsTikProcess::getLicenseTypeStr(byte_t flag) const
str = "Service";
break;
default:
str = "Unknown";
str = fmt::format("Unknown ({:d})", flag);
break;
}
return str;
}
const char* nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const
std::string nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const
{
const char* str = nullptr;
std::string str;
switch(flag)
{
case (nn::es::ticket::FLAG_PRE_INSTALL):
@ -259,9 +250,23 @@ const char* nstool::EsTikProcess::getPropertyFlagStr(byte_t flag) const
case (nn::es::ticket::FLAG_ALLOW_ALL_CONTENT):
str = "AllContent";
break;
case (nn::es::ticket::FLAG_DEVICE_LINK_INDEPENDENT):
str = "DeviceLinkIndependent";
break;
case (nn::es::ticket::FLAG_VOLATILE):
str = "Volatile";
break;
case (nn::es::ticket::FLAG_ELICENSE_REQUIRED):
str = "ELicenseRequired";
break;
default:
str = "Unknown";
str = fmt::format("Unknown ({:d})", flag);
break;
}
return str;
}
std::string nstool::EsTikProcess::getTitleVersionStr(uint16_t version) const
{
return fmt::format("{:d}.{:d}.{:d}", ((version>>10) & 0x3f), ((version>>4) & 0x3f), ((version>>0) & 0xf));
}

View file

@ -22,7 +22,7 @@ public:
void setVerifyMode(bool verify);
private:
const std::string kModuleName = "EsTikProcess";
std::string mModuleName;
std::shared_ptr<tc::io::IStream> mFile;
KeyBag mKeyCfg;
@ -36,10 +36,11 @@ private:
void importTicket();
void verifyTicket();
void displayTicket();
const char* getSignTypeStr(uint32_t type) const;
const char* getTitleKeyPersonalisationStr(byte_t flag) const;
const char* getLicenseTypeStr(byte_t flag) const;
const char* getPropertyFlagStr(byte_t flag) const;
std::string getSignTypeStr(uint32_t type) const;
std::string getTitleKeyPersonalisationStr(byte_t flag) const;
std::string getLicenseTypeStr(byte_t flag) const;
std::string getPropertyFlagStr(byte_t flag) const;
std::string getTitleVersionStr(uint16_t version) const;
};
}

View file

@ -21,7 +21,7 @@ public:
void setVerifyMode(bool verify);
// xci specific
void setPartitionForExtract(const std::string& partition_name, const std::string& extract_path);
void setPartitionForExtract(const std::string& partition_name, const tc::io::Path& extract_path);
void setListFs(bool list_fs);
private:
@ -37,7 +37,7 @@ private:
struct sExtractInfo
{
std::string partition_name;
std::string extract_path;
tc::io::Path extract_path;
void operator=(const sExtractInfo& other)
{
@ -45,7 +45,7 @@ private:
extract_path = other.extract_path;
}
bool operator==(const std::string& name) const
bool operator==(const tc::io::Path& name) const
{
return name == partition_name;
}
@ -57,7 +57,7 @@ private:
bool mIsSdkXciEncrypted;
size_t mGcHeaderOffset;
bool mProccessExtendedHeader;
byte_t mHdrSignature[fnd::rsa::kRsa2048Size];
nn::hac::detail::rsa2048_signature_t mHdrSignature;
fnd::sha::sSha256Hash mHdrHash;
nn::hac::GameCardHeader mHdr;

View file

@ -17,7 +17,7 @@ public:
void setCliOutputMode(CliOutputMode type);
void setVerifyMode(bool verify);
void setKipExtractPath(const std::string& path);
void setKipExtractPath(const tc::io::Path& path);
private:
const std::string kModuleName = "IniProcess";
const std::string kKipExtention = ".kip";
@ -27,8 +27,7 @@ private:
CliOutputMode mCliOutputMode;
bool mVerify;
bool mDoExtractKip;
std::string mKipExtractPath;
tc::Optional<tc::io::Path> mKipExtractPath;
nn::hac::IniHeader mHdr;
std::vector<std::shared_ptr<tc::io::IStream>> mKipList;

View file

@ -5,6 +5,7 @@
#include <map>
#include <tc/Optional.h>
#include <tc/io.h>
#include <nn/pki/SignUtils.h>
#include <nn/hac/define/types.h>
#include <nn/hac/define/nca.h>

View file

@ -20,10 +20,10 @@ public:
void setVerifyMode(bool verify);
// nca specfic
void setPartition0ExtractPath(const std::string& path);
void setPartition1ExtractPath(const std::string& path);
void setPartition2ExtractPath(const std::string& path);
void setPartition3ExtractPath(const std::string& path);
void setPartition0ExtractPath(const tc::io::Path& path);
void setPartition1ExtractPath(const tc::io::Path& path);
void setPartition2ExtractPath(const tc::io::Path& path);
void setPartition3ExtractPath(const tc::io::Path& path);
void setListFs(bool list_fs);
private:
@ -36,11 +36,7 @@ private:
CliOutputMode mCliOutputMode;
bool mVerify;
struct sExtract
{
std::string path;
bool doExtract;
} mPartitionPath[nn::hac::nca::kPartitionNum];
std::array<tc::Optional<tc::io::Path>, nn::hac::nca::kPartitionNum> mPartitionPath;
bool mListFs;
@ -82,23 +78,25 @@ private:
};
std::vector<sKeyAreaKey> kak_list;
tc::Optional<KeyBag::aes128_key_t> aes_ctr;
tc::Optional<nn::hac::detail::aes128_key_t> aes_ctr;
} mContentKey;
struct sPartitionInfo
{
std::shared_ptr<tc::io::IStream> reader;
std::string fail_reason;
size_t offset;
size_t size;
int64_t offset;
int64_t size;
// meta data
nn::hac::nca::FormatType format_type;
nn::hac::nca::HashType hash_type;
nn::hac::nca::EncryptionType enc_type;
fnd::LayeredIntegrityMetadata layered_intergrity_metadata;
fnd::aes::sAesIvCtr aes_ctr;
} mPartitions[nn::hac::nca::kPartitionNum];
//fnd::LayeredIntegrityMetadata layered_intergrity_metadata;
nn::hac::detail::aes_iv_t aes_ctr;
}
std::array<sPartitionInfo, nn::hac::nca::kPartitionNum> mPartitions;
void importHeader();
void generateNcaBodyEncryptionKeys();

View file

@ -25,9 +25,9 @@ public:
// for homebrew NROs with Asset blobs appended
void setAssetListFs(bool list);
void setAssetIconExtractPath(const std::string& path);
void setAssetNacpExtractPath(const std::string& path);
void setAssetRomfsExtractPath(const std::string& path);
void setAssetIconExtractPath(const tc::io::Path& path);
void setAssetNacpExtractPath(const tc::io::Path& path);
void setAssetRomfsExtractPath(const tc::io::Path& path);
const RoMetadataProcess& getRoMetadataProcess() const;
private:

View file

@ -19,7 +19,7 @@ public:
// pfs specific
void setMountPointName(const std::string& mount_name);
void setExtractPath(const std::string& path);
void setExtractPath(const tc::io::Path& path);
void setListFs(bool list_fs);
const nn::hac::PartitionFsHeader& getPfsHeader() const;
@ -32,8 +32,7 @@ private:
CliOutputMode mCliOutputMode;
bool mVerify;
std::string mExtractPath;
bool mExtract;
tc::Optional<tc::io::Path> mExtractPath;
std::string mMountName;
bool mListFs;

View file

@ -77,7 +77,7 @@ void nstool::PkiValidator::addCertificate(const nn::pki::SignedData<nn::pki::Cer
}
catch (const tc::Exception& e)
{
throw tc::Exception(mModuleName, fmt::format("Failed to add certificate {:s} ({:s})", cert_ident, e.error());
throw tc::Exception(mModuleName, fmt::format("Failed to add certificate {:s} ({:s})", cert_ident, e.error()));
}
}
@ -89,8 +89,6 @@ void nstool::PkiValidator::clearCertificates()
void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const
{
nn::pki::sign::SignatureAlgo sign_algo = nn::pki::sign::getSignatureAlgo(signature_id);
nn::pki::sign::HashAlgo hash_algo = nn::pki::sign::getHashAlgo(signature_id);
// validate signature
bool sig_valid = false;
@ -106,12 +104,12 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
if (itr == mKeyCfg.broadon_signer.end())
{
throw tc::Exception(mModuleName, fmt::print("Public key for issuer \"{:s}\" does not exist.", issuer);
throw tc::Exception(mModuleName, fmt::format("Public key for issuer \"{:s}\" does not exist.", issuer));
}
if (sign_algo != itr->second.key_type)
{
throw tc::Exception(mModuleName, fmt::print("Public key for issuer \"{:s}\" cannot verify this signature.", issuer);
throw tc::Exception(mModuleName, fmt::format("Public key for issuer \"{:s}\" cannot verify this signature.", issuer));
}
if (sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
@ -129,7 +127,7 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
if (issuer_pubk_type == nn::pki::cert::RSA4096 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096)
{
rsa_key = issuer_cert.getRsa4098PublicKey();
rsa_key = issuer_cert.getRsa4096PublicKey();
}
else if (issuer_pubk_type == nn::pki::cert::RSA2048 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048)
{
@ -148,42 +146,25 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
// verify signature
switch (signature_id) {
case (SIGN_ID_RSA4096_SHA1):
sig_validate_res = tc::crypto::VerifyRsa4096Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
case (nn::pki::sign::SIGN_ID_RSA4096_SHA1):
sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
break;
case (SIGN_ID_RSA2048_SHA1):
sig_validate_res = tc::crypto::VerifyRsa2048Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
case (nn::pki::sign::SIGN_ID_RSA2048_SHA1):
sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha1(signature.data(), hash.data(), rsa_key);
break;
case (SIGN_ID_ECDSA240_SHA1):
sig_validate_res = false;
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA1):
sig_valid = false;
break;
case (SIGN_ID_RSA4096_SHA256):
sig_validate_res = tc::crypto::VerifyRsa4096Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
case (nn::pki::sign::SIGN_ID_RSA4096_SHA256):
sig_valid = tc::crypto::VerifyRsa4096Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
break;
case (SIGN_ID_RSA2048_SHA256):
sig_validate_res = tc::crypto::VerifyRsa2048Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
case (nn::pki::sign::SIGN_ID_RSA2048_SHA256):
sig_valid = tc::crypto::VerifyRsa2048Pkcs1Sha256(signature.data(), hash.data(), rsa_key);
break;
case (SIGN_ID_ECDSA240_SHA256):
sig_validate_res = false;
case (nn::pki::sign::SIGN_ID_ECDSA240_SHA256):
sig_valid = false;
break;
}
if (sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096)
{
sig_validate_res = fnd::rsa::pkcs::rsaVerify(issuer_cert.getRsa4098PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data());
}
else if (sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048)
{
sig_validate_res = fnd::rsa::pkcs::rsaVerify(issuer_cert.getRsa2048PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data());
}
else if (sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
{
throw tc::Exception(mModuleName, "ECDSA signatures are not supported");
}
else
{
throw tc::Exception(mModuleName, "Mismatch between issuer public key and signature type");
}
if (sig_valid == false)
{

View file

@ -45,8 +45,8 @@ public:
struct sFile
{
std::string name;
uint64_t offset;
uint64_t size;
int64_t offset;
int64_t size;
void operator=(const sFile& other)
{
@ -84,7 +84,7 @@ public:
// romfs specific
void setMountPointName(const std::string& mount_name);
void setExtractPath(const std::string& path);
void setExtractPath(const tc::io::Path& path);
void setListFs(bool list_fs);
const sDirectory& getRootDir() const;
@ -101,8 +101,7 @@ private:
bool mVerbose;
bool mVerify;
std::string mExtractPath;
bool mExtract;
tc::Optional<tc::io::Path> mExtractPath;
std::string mMountName;
bool mListFs;

View file

@ -349,6 +349,9 @@ private:
nstool::SettingsInitializer::SettingsInitializer(const std::vector<std::string>& args) :
Settings(),
mModuleLabel("nstool::SettingsInitializer"),
mShowLayout(false),
mShowKeydata(false),
mVerbose(false),
mTitleKey(),
mBodyKey(),
mTikPath(),
@ -359,6 +362,23 @@ nstool::SettingsInitializer::SettingsInitializer(const std::vector<std::string>&
if (infile.path.isNull())
throw tc::ArgumentException(mModuleLabel, "No input file was specified.");
// determine CLI output mode
opt.cli_output_mode.show_basic_info = true;
if (mVerbose)
{
opt.cli_output_mode.show_extended_info = true;
opt.cli_output_mode.show_layout = true;
opt.cli_output_mode.show_keydata = true;
}
if (mShowKeydata)
{
opt.cli_output_mode.show_keydata = true;
}
if (mShowLayout)
{
opt.cli_output_mode.show_layout = true;
}
// locate key file, if not specfied
if (mKeysetPath.isNull())
{
@ -431,9 +451,9 @@ void nstool::SettingsInitializer::parse_args(const std::vector<std::string>& arg
// none just yet
// get option flags
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.show_layout, {"--showlayout"})));
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.show_keydata, { "--showkeys" })));
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.verbose, {"-v", "--verbose"})));
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(mShowLayout, {"--showlayout"})));
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(mShowKeydata, { "--showkeys" })));
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(mVerbose, {"-v", "--verbose"})));
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.verify, {"-y", "--verify"})));
opts.registerOptionHandler(std::shared_ptr<FlagOptionHandler>(new FlagOptionHandler(opt.is_dev, {"-d", "--dev"})));

View file

@ -138,6 +138,7 @@ private:
bool mShowLayout;
bool mShowKeydata;
bool mVerbose;
tc::Optional<tc::io::Path> mKeysetPath;
tc::Optional<KeyBag::aes128_key_t> mTitleKey;

View file

@ -2,22 +2,22 @@
#include <tc/os/UnicodeMain.h>
#include "Settings.h"
/*
#include "GameCardProcess.h"
#include "PfsProcess.h"
#include "RomfsProcess.h"
#include "NcaProcess.h"
#include "MetaProcess.h"
//#include "GameCardProcess.h"
//#include "PfsProcess.h"
//#include "RomfsProcess.h"
//#include "NcaProcess.h"
//#include "MetaProcess.h"
#include "CnmtProcess.h"
#include "NsoProcess.h"
#include "NroProcess.h"
#include "NacpProcess.h"
#include "IniProcess.h"
#include "KipProcess.h"
#include "PkiCertProcess.h"
//#include "NsoProcess.h"
//#include "NroProcess.h"
//#include "NacpProcess.h"
//#include "IniProcess.h"
//#include "KipProcess.h"
//#include "PkiCertProcess.h"
#include "EsTikProcess.h"
#include "AssetProcess.h"
*/
int umain(const std::vector<std::string>& args, const std::vector<std::string>& env)
{
@ -27,208 +27,214 @@ int umain(const std::vector<std::string>& args, const std::vector<std::string>&
std::shared_ptr<tc::io::IStream> infile_stream = std::make_shared<tc::io::FileStream>(tc::io::FileStream(set.infile.path.get(), tc::io::FileMode::Open, tc::io::FileAccess::Read));
/*
if (set.infile.filetype == nstool::Settings::FILE_TYPE_GAMECARD)
{
GameCardProcess obj;
nstool::GameCardProcess obj;
obj.setInputFile(infile_stream);
obj.setKeyCfg(set.opt.keybag);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
if (set.xci.update_extract_path.isSet())
obj.setPartitionForExtract(nn::hac::gc::kUpdatePartitionStr, set.xci.update_extract_path.get());
if (set.xci.logo_extract_path.isSet())
obj.setPartitionForExtract(nn::hac::gc::kLogoPartitionStr, set.xci.logo_extract_path.get());
if (user_set.getXciNormalPath().isSet())
obj.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, user_set.getXciNormalPath().get());
if (user_set.getXciSecurePath().isSet())
obj.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, user_set.getXciSecurePath().get());
obj.setListFs(user_set.isListFs());
if (set.xci.normal_extract_path.isSet())
obj.setPartitionForExtract(nn::hac::gc::kNormalPartitionStr, set.xci.normal_extract_path.get());
if (set.xci.secure_extract_path.isSet())
obj.setPartitionForExtract(nn::hac::gc::kSecurePartitionStr, set.xci.secure_extract_path.get());
obj.setListFs(set.fs.show_fs_tree);
obj.process();
}
*/
/*
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_PARTITIONFS || set.infile.filetype == nstool::Settings::FILE_TYPE_NSP)
{
PfsProcess obj;
nstool::PfsProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
if (user_set.getFsPath().isSet())
obj.setExtractPath(user_set.getFsPath().get());
obj.setListFs(user_set.isListFs());
if (set.fs.extract_path.isSet())
obj.setExtractPath(set.fs.extract_path.get());
obj.setListFs(set.fs.show_fs_tree);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_ROMFS)
{
RomfsProcess obj;
nstool::RomfsProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
if (user_set.getFsPath().isSet())
obj.setExtractPath(user_set.getFsPath().get());
obj.setListFs(user_set.isListFs());
if (set.fs.extract_path.isSet())
obj.setExtractPath(set.fs.extract_path.get());
obj.setListFs(set.fs.show_fs_tree);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NCA)
{
NcaProcess obj;
nstool::NcaProcess obj;
obj.setInputFile(infile_stream);
obj.setKeyCfg(set.opt.keybag);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
if (user_set.getNcaPart0Path().isSet())
obj.setPartition0ExtractPath(user_set.getNcaPart0Path().get());
if (user_set.getNcaPart1Path().isSet())
obj.setPartition1ExtractPath(user_set.getNcaPart1Path().get());
if (user_set.getNcaPart2Path().isSet())
obj.setPartition2ExtractPath(user_set.getNcaPart2Path().get());
if (user_set.getNcaPart3Path().isSet())
obj.setPartition3ExtractPath(user_set.getNcaPart3Path().get());
obj.setListFs(user_set.isListFs());
if (set.nca.part0_extract_path.isSet())
obj.setPartition0ExtractPath(set.nca.part0_extract_path.get());
if (set.nca.part1_extract_path.isSet())
obj.setPartition1ExtractPath(set.nca.part1_extract_path.get());
if (set.nca.part2_extract_path.isSet())
obj.setPartition2ExtractPath(set.nca.part2_extract_path.get());
if (set.nca.part3_extract_path.isSet())
obj.setPartition3ExtractPath(set.nca.part3_extract_path.get());
obj.setListFs(set.fs.show_fs_tree);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_META)
{
MetaProcess obj;
nstool::MetaProcess obj;
obj.setInputFile(infile_stream);
obj.setKeyCfg(set.opt.keybag);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_CNMT)
else*/ if (set.infile.filetype == nstool::Settings::FILE_TYPE_CNMT)
{
CnmtProcess obj;
nstool::CnmtProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.process();
}
/*
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NSO)
{
NsoProcess obj;
nstool::NsoProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.setIs64BitInstruction(user_set.getIs64BitInstruction());
obj.setListApi(user_set.isListApi());
obj.setListSymbols(user_set.isListSymbols());
obj.setIs64BitInstruction(set.code.is_64bit_instruction);
obj.setListApi(set.code.list_api);
obj.setListSymbols(set.code.list_symbols);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NRO)
{
NroProcess obj;
nstool::NroProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.setIs64BitInstruction(user_set.getIs64BitInstruction());
obj.setListApi(user_set.isListApi());
obj.setListSymbols(user_set.isListSymbols());
obj.setIs64BitInstruction(set.code.is_64bit_instruction);
obj.setListApi(set.code.list_api);
obj.setListSymbols(set.code.list_symbols);
if (user_set.getAssetIconPath().isSet())
obj.setAssetIconExtractPath(user_set.getAssetIconPath().get());
if (user_set.getAssetNacpPath().isSet())
obj.setAssetNacpExtractPath(user_set.getAssetNacpPath().get());
if (set.aset.icon_extract_path.isSet())
obj.setAssetIconExtractPath(set.aset.icon_extract_path.get());
if (set.aset.nacp_extract_path.isSet())
obj.setAssetNacpExtractPath(set.aset.nacp_extract_path.get());
if (user_set.getFsPath().isSet())
obj.setAssetRomfsExtractPath(user_set.getFsPath().get());
obj.setAssetListFs(user_set.isListFs());
if (set.fs.extract_path.isSet())
obj.setAssetRomfsExtractPath(set.fs.extract_path.get());
obj.setAssetListFs(set.fs.show_fs_tree);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_NACP)
{
NacpProcess obj;
nstool::NacpProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_INI)
{
IniProcess obj;
nstool::IniProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
if (user_set.getKipExtractPath().isSet())
obj.setKipExtractPath(user_set.getKipExtractPath().get());
if (set.kip.extract_path.isSet())
obj.setKipExtractPath(set.kip.extract_path.get());
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_KIP)
{
KipProcess obj;
nstool::KipProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_PKI_CERT)
{
PkiCertProcess obj;
nstool::PkiCertProcess obj;
obj.setInputFile(infile_stream);
obj.setKeyCfg(set.opt.keybag);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.process();
}
*/
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_ES_TIK)
{
EsTikProcess obj;
nstool::EsTikProcess obj;
obj.setInputFile(infile_stream);
obj.setKeyCfg(set.opt.keybag);
obj.setCertificateChain(user_set.getCertificateChain());
obj.setCliOutputMode(user_set.getCliOutputMode());
//obj.setCertificateChain(user_set.getCertificateChain());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
obj.process();
}
else if (set.infile.filetype == nstool::Settings::FILE_TYPE_HB_ASSET)
{
AssetProcess obj;
nstool::AssetProcess obj;
obj.setInputFile(infile_stream);
obj.setCliOutputMode(user_set.getCliOutputMode());
obj.setCliOutputMode(set.opt.cli_output_mode);
obj.setVerifyMode(set.opt.verify);
if (user_set.getAssetIconPath().isSet())
obj.setIconExtractPath(user_set.getAssetIconPath().get());
if (user_set.getAssetNacpPath().isSet())
obj.setNacpExtractPath(user_set.getAssetNacpPath().get());
if (set.aset.icon_extract_path.isSet())
obj.setIconExtractPath(set.aset.icon_extract_path.get());
if (set.aset.nacp_extract_path.isSet())
obj.setNacpExtractPath(set.aset.nacp_extract_path.get());
if (user_set.getFsPath().isSet())
obj.setRomfsExtractPath(user_set.getFsPath().get());
obj.setListFs(user_set.isListFs());
if (set.fs.extract_path.isSet())
obj.setRomfsExtractPath(set.fs.extract_path.get());
obj.setListFs(set.fs.show_fs_tree);
obj.process();
}

View file

@ -1,5 +1,6 @@
#pragma once
#include <tc/types.h>
#include <tc/Exception.h>
#include <tc/Optional.h>
#include <tc/io.h>
#include <tc/io/IOUtil.h>

View file

@ -68,13 +68,13 @@ void nstool::processResFile(const std::shared_ptr<tc::io::IStream>& file, std::m
void nstool::writeSubStreamToFile(const std::shared_ptr<tc::io::IStream>& in_stream, int64_t offset, int64_t length, const tc::io::Path& out_path, size_t cache_size)
{
writeStreamToStream(std::make_shared<tc::io::SubStream>(tc::io::SubStream(in_stream, offset, length)), std::make_shared<tc::io::FileStream>(tc::io::FileStream(out_path, tc::io::FileAccess::OpenOrCreate, tc::io::FileMode::Write)), cache_size);
writeStreamToStream(std::make_shared<tc::io::SubStream>(tc::io::SubStream(in_stream, offset, length)), std::make_shared<tc::io::FileStream>(tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)), cache_size);
}
void nstool::writeStreamToFile(const std::shared_ptr<tc::io::IStream>& in_stream, const tc::io::Path& out_path, size_t cache_size)
{
writeStreamToStream(in_stream, std::make_shared<tc::io::FileStream>(tc::io::FileStream(out_path, tc::io::FileAccess::OpenOrCreate, tc::io::FileMode::Write)), cache_size);
writeStreamToStream(in_stream, std::make_shared<tc::io::FileStream>(tc::io::FileStream(out_path, tc::io::FileMode::OpenOrCreate, tc::io::FileAccess::Write)), cache_size);
}
void nstool::writeStreamToStream(const std::shared_ptr<tc::io::IStream>& in_stream, const std::shared_ptr<tc::io::IStream>& out_stream, size_t cache_size)
@ -90,7 +90,7 @@ void nstool::writeStreamToStream(const std::shared_ptr<tc::io::IStream>& in_stre
cache_read_len = in_stream->read(cache.data(), cache.size());
if (cache_read_len == 0)
{
throw tc::io::IOException(mModuleLabel, "Failed to read from RomFs file.");
throw tc::io::IOException("nstool::writeStreamToStream()", "Failed to read from source streeam.");
}
out_stream->write(cache.data(), cache_read_len);