mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-23 03:05:27 +00:00
[nxtool] Inital reading of ES tickets and certificates.
This commit is contained in:
parent
9ae737cdc8
commit
e7148c39ea
249
programs/nstool/source/EsCertProcess.cpp
Normal file
249
programs/nstool/source/EsCertProcess.cpp
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
#include <fnd/SimpleTextOutput.h>
|
||||||
|
#include "OffsetAdjustedIFile.h"
|
||||||
|
#include "EsCertProcess.h"
|
||||||
|
|
||||||
|
EsCertProcess::EsCertProcess() :
|
||||||
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||||
|
mVerify(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EsCertProcess::~EsCertProcess()
|
||||||
|
{
|
||||||
|
if (mOwnIFile)
|
||||||
|
{
|
||||||
|
delete mFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::process()
|
||||||
|
{
|
||||||
|
if (mFile == nullptr)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
importCerts();
|
||||||
|
if (mVerify)
|
||||||
|
validateCerts();
|
||||||
|
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||||
|
displayCerts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
|
{
|
||||||
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::setKeyset(const sKeyset* keyset)
|
||||||
|
{
|
||||||
|
mKeyset = keyset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::setCliOutputMode(CliOutputMode mode)
|
||||||
|
{
|
||||||
|
mCliOutputMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::setVerifyMode(bool verify)
|
||||||
|
{
|
||||||
|
mVerify = verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::importCerts()
|
||||||
|
{
|
||||||
|
fnd::Vec<byte_t> scratch;
|
||||||
|
|
||||||
|
scratch.alloc(mFile->size());
|
||||||
|
mFile->read(scratch.data(), 0, scratch.size());
|
||||||
|
|
||||||
|
es::SignedData<es::CertificateBody> cert;
|
||||||
|
for (size_t f_pos = 0; f_pos < scratch.size(); f_pos += cert.getBytes().size())
|
||||||
|
{
|
||||||
|
cert.fromBytes(scratch.data() + f_pos, scratch.size() - f_pos);
|
||||||
|
mCert.addElement(cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::validateCerts()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < mCert.size(); i++)
|
||||||
|
{
|
||||||
|
EsCertProcess::validateCert(mCert[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::validateCert(const es::SignedData<es::CertificateBody>& cert)
|
||||||
|
{
|
||||||
|
std::string cert_ident = "";
|
||||||
|
cert_ident += cert.getBody().getSubject();
|
||||||
|
cert_ident += cert.getBody().getSubject();
|
||||||
|
cert_ident += cert.getBody().getSubject();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (cert.getBody().getIssuer() == es::sign::kRootIssuerStr)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Signed by Root");
|
||||||
|
}
|
||||||
|
|
||||||
|
const es::CertificateBody& issuer = getIssuerCert(cert.getBody().getIssuer()).getBody();
|
||||||
|
|
||||||
|
if (issuer.getPublicKeyType() == es::cert::RSA4096 && (cert.getSignature().getSignType() == es::sign::SIGN_RSA4096_SHA1 || cert.getSignature().getSignType() == es::sign::SIGN_RSA4096_SHA256))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "RSA4096 signatures are not supported");
|
||||||
|
}
|
||||||
|
else if (issuer.getPublicKeyType() == es::cert::RSA2048 && (cert.getSignature().getSignType() == es::sign::SIGN_RSA2048_SHA1 || cert.getSignature().getSignType() == es::sign::SIGN_RSA2048_SHA256))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "RSA2048 signatures are not supported");
|
||||||
|
}
|
||||||
|
else if (issuer.getPublicKeyType() == es::cert::ECDSA240 && (cert.getSignature().getSignType() == es::sign::SIGN_ECDSA240_SHA1 || cert.getSignature().getSignType() == es::sign::SIGN_ECDSA240_SHA256))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "ECDSA signatures are not supported");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Mismatch between issuer public key and signature type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const fnd::Exception& e)
|
||||||
|
{
|
||||||
|
printf("[WARNING] Failed to validate %s (%s)\n", cert_ident.c_str(), e.error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::displayCerts()
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < mCert.size(); i++)
|
||||||
|
{
|
||||||
|
displayCert(mCert[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsCertProcess::displayCert(const es::SignedData<es::CertificateBody>& cert)
|
||||||
|
{
|
||||||
|
#define _SPLIT_VER(ver) ( (ver>>26) & 0x3f), ( (ver>>20) & 0x3f), ( (ver>>16) & 0xf), (ver & 0xffff)
|
||||||
|
#define _HEXDUMP_U(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02X", var[a__a__A]); } while(0)
|
||||||
|
#define _HEXDUMP_L(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02x", var[a__a__A]); } while(0)
|
||||||
|
|
||||||
|
printf("[ES Certificate]\n");
|
||||||
|
printf(" SignType: %s", getSignTypeStr(cert.getSignature().getSignType()));
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
printf(" (0x%" PRIx32 ") (%s)", cert.getSignature().getSignType(), getEndiannessStr(cert.getSignature().isLittleEndian()));
|
||||||
|
printf("\n");
|
||||||
|
printf(" Issuer: %s\n", cert.getBody().getIssuer().c_str());
|
||||||
|
printf(" Subject: %s\n", cert.getBody().getSubject().c_str());
|
||||||
|
printf(" PublicKeyType: %s", getPublicKeyType(cert.getBody().getPublicKeyType()));
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED))
|
||||||
|
printf(" (%d)", cert.getBody().getPublicKeyType());
|
||||||
|
printf("\n");
|
||||||
|
printf(" CertID: 0x%" PRIx32 " \n", cert.getBody().getCertId());
|
||||||
|
|
||||||
|
if (cert.getBody().getPublicKeyType() == es::cert::RSA4096)
|
||||||
|
{
|
||||||
|
printf(" PublicKey:\n");
|
||||||
|
printf(" Modulus:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(cert.getBody().getRsa4098PublicKey().modulus, _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED) ? crypto::rsa::kRsa4096Size : 0x10, 0x10, 6);
|
||||||
|
printf(" Public Exponent:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(cert.getBody().getRsa4098PublicKey().public_exponent, crypto::rsa::kRsaPublicExponentSize, 0x10, 6);
|
||||||
|
}
|
||||||
|
else if (cert.getBody().getPublicKeyType() == es::cert::RSA2048)
|
||||||
|
{
|
||||||
|
printf(" PublicKey:\n");
|
||||||
|
printf(" Public Exponent:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(cert.getBody().getRsa2048PublicKey().modulus, _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED) ? crypto::rsa::kRsa2048Size : 0x10, 0x10, 6);
|
||||||
|
printf(" Modulus:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(cert.getBody().getRsa2048PublicKey().public_exponent, crypto::rsa::kRsaPublicExponentSize, 0x10, 6);
|
||||||
|
}
|
||||||
|
else if (cert.getBody().getPublicKeyType() == es::cert::ECDSA240)
|
||||||
|
{
|
||||||
|
printf(" PublicKey:\n");
|
||||||
|
printf(" R:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(cert.getBody().getEcdsa240PublicKey().r, _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED) ? crypto::ecdsa::kEcdsa240Size : 0x10, 0x10, 6);
|
||||||
|
printf(" S:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(cert.getBody().getEcdsa240PublicKey().s, _HAS_BIT(mCliOutputMode, OUTPUT_EXTENDED) ? crypto::ecdsa::kEcdsa240Size : 0x10, 0x10, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#undef _HEXDUMP_L
|
||||||
|
#undef _HEXDUMP_U
|
||||||
|
#undef _SPLIT_VER
|
||||||
|
}
|
||||||
|
|
||||||
|
const es::SignedData<es::CertificateBody>& EsCertProcess::getIssuerCert(const std::string& issuer_name) const
|
||||||
|
{
|
||||||
|
std::string full_cert_name;
|
||||||
|
for (size_t i = 0; i < mCert.size(); i++)
|
||||||
|
{
|
||||||
|
full_cert_name = mCert[i].getBody().getIssuer() + es::sign::kIdentDelimiter + mCert[i].getBody().getSubject();
|
||||||
|
if (full_cert_name == issuer_name)
|
||||||
|
{
|
||||||
|
return mCert[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw fnd::Exception(kModuleName, "Issuer certificate does not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* EsCertProcess::getSignTypeStr(es::sign::SignType type) const
|
||||||
|
{
|
||||||
|
const char* str;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (es::sign::SIGN_RSA4096_SHA1):
|
||||||
|
str = "RSA4096-SHA1";
|
||||||
|
break;
|
||||||
|
case (es::sign::SIGN_RSA2048_SHA1):
|
||||||
|
str = "RSA2048-SHA1";
|
||||||
|
break;
|
||||||
|
case (es::sign::SIGN_ECDSA240_SHA1):
|
||||||
|
str = "ECDSA240-SHA1";
|
||||||
|
break;
|
||||||
|
case (es::sign::SIGN_RSA4096_SHA256):
|
||||||
|
str = "RSA4096-SHA256";
|
||||||
|
break;
|
||||||
|
case (es::sign::SIGN_RSA2048_SHA256):
|
||||||
|
str = "RSA2048-SHA256";
|
||||||
|
break;
|
||||||
|
case (es::sign::SIGN_ECDSA240_SHA256):
|
||||||
|
str = "ECDSA240-SHA256";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* EsCertProcess::getEndiannessStr(bool isLittleEndian) const
|
||||||
|
{
|
||||||
|
return isLittleEndian ? "LittleEndian" : "BigEndian";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* EsCertProcess::getPublicKeyType(es::cert::PublicKeyType type) const
|
||||||
|
{
|
||||||
|
const char* str;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (es::cert::RSA4096):
|
||||||
|
str = "RSA4096";
|
||||||
|
break;
|
||||||
|
case (es::cert::RSA2048):
|
||||||
|
str = "RSA2048";
|
||||||
|
break;
|
||||||
|
case (es::cert::ECDSA240):
|
||||||
|
str = "ECDSA240";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
46
programs/nstool/source/EsCertProcess.h
Normal file
46
programs/nstool/source/EsCertProcess.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/IFile.h>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <fnd/Vec.h>
|
||||||
|
#include <es/SignedData.h>
|
||||||
|
#include <es/CertificateBody.h>
|
||||||
|
#include "nstool.h"
|
||||||
|
|
||||||
|
class EsCertProcess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EsCertProcess();
|
||||||
|
~EsCertProcess();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
|
void setKeyset(const sKeyset* keyset);
|
||||||
|
void setCliOutputMode(CliOutputMode type);
|
||||||
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "EsCertProcess";
|
||||||
|
|
||||||
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
|
const sKeyset* mKeyset;
|
||||||
|
CliOutputMode mCliOutputMode;
|
||||||
|
bool mVerify;
|
||||||
|
|
||||||
|
fnd::List<es::SignedData<es::CertificateBody>> mCert;
|
||||||
|
|
||||||
|
void importCerts();
|
||||||
|
void validateCerts();
|
||||||
|
void validateCert(const es::SignedData<es::CertificateBody>& cert);
|
||||||
|
void displayCerts();
|
||||||
|
void displayCert(const es::SignedData<es::CertificateBody>& cert);
|
||||||
|
|
||||||
|
const es::SignedData<es::CertificateBody>& getIssuerCert(const std::string& issuer_name) const;
|
||||||
|
|
||||||
|
const char* getSignTypeStr(es::sign::SignType type) const;
|
||||||
|
const char* getEndiannessStr(bool isLittleEndian) const;
|
||||||
|
const char* getPublicKeyType(es::cert::PublicKeyType type) const;
|
||||||
|
};
|
187
programs/nstool/source/EsTikProcess.cpp
Normal file
187
programs/nstool/source/EsTikProcess.cpp
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
#include <fnd/SimpleTextOutput.h>
|
||||||
|
#include "OffsetAdjustedIFile.h"
|
||||||
|
#include "EsTikProcess.h"
|
||||||
|
|
||||||
|
EsTikProcess::EsTikProcess() :
|
||||||
|
mFile(nullptr),
|
||||||
|
mOwnIFile(false),
|
||||||
|
mCliOutputMode(_BIT(OUTPUT_BASIC)),
|
||||||
|
mVerify(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EsTikProcess::~EsTikProcess()
|
||||||
|
{
|
||||||
|
if (mOwnIFile)
|
||||||
|
{
|
||||||
|
delete mFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsTikProcess::process()
|
||||||
|
{
|
||||||
|
fnd::Vec<byte_t> scratch;
|
||||||
|
|
||||||
|
if (mFile == nullptr)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch.alloc(mFile->size());
|
||||||
|
mFile->read(scratch.data(), 0, scratch.size());
|
||||||
|
|
||||||
|
mTik.fromBytes(scratch.data(), scratch.size());
|
||||||
|
|
||||||
|
if (_HAS_BIT(mCliOutputMode, OUTPUT_BASIC))
|
||||||
|
displayTicket();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsTikProcess::setInputFile(fnd::IFile* file, bool ownIFile)
|
||||||
|
{
|
||||||
|
mFile = file;
|
||||||
|
mOwnIFile = ownIFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsTikProcess::setKeyset(const sKeyset* keyset)
|
||||||
|
{
|
||||||
|
mKeyset = keyset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsTikProcess::setCliOutputMode(CliOutputMode mode)
|
||||||
|
{
|
||||||
|
mCliOutputMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsTikProcess::setVerifyMode(bool verify)
|
||||||
|
{
|
||||||
|
mVerify = verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EsTikProcess::displayTicket()
|
||||||
|
{
|
||||||
|
#define _SPLIT_VER(ver) ( (ver>>10) & 0x3f), ( (ver>>4) & 0x3f), ( (ver>>0) & 0xf)
|
||||||
|
#define _HEXDUMP_U(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02X", var[a__a__A]); } while(0)
|
||||||
|
#define _HEXDUMP_L(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02x", var[a__a__A]); } while(0)
|
||||||
|
|
||||||
|
const es::TicketBody_V2& body = mTik.getBody();
|
||||||
|
|
||||||
|
printf("[ES Ticket]\n");
|
||||||
|
printf(" SignType: 0x%" PRIx32 " (%s)\n", mTik.getSignature().getSignType(), mTik.getSignature().isLittleEndian()? "LittleEndian" : "BigEndian");
|
||||||
|
printf(" Issuer: %s\n", body.getIssuer().c_str());
|
||||||
|
printf(" Title Key:\n");
|
||||||
|
printf(" EncMode: %s\n", getTitleKeyPersonalisationStr(body.getTitleKeyEncType()));
|
||||||
|
printf(" CommonKeyId: %02X\n", body.getCommonKeyId());
|
||||||
|
printf(" EncData:\n");
|
||||||
|
size_t size = body.getTitleKeyEncType() == es::ticket::RSA2048 ? crypto::rsa::kRsa2048Size : crypto::aes::kAes128KeySize;
|
||||||
|
fnd::SimpleTextOutput::hexDump(body.getEncTitleKey(), size, 0x10, 6);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (body.getTitleKeyEncType() == es::ticket::AES128_CBC && body.getCommonKeyId() == 0)
|
||||||
|
{
|
||||||
|
byte_t iv[crypto::aes::kAesBlockSize];
|
||||||
|
byte_t key[crypto::aes::kAes128KeySize];
|
||||||
|
memcpy(iv, body.getRightsId(), crypto::aes::kAesBlockSize);
|
||||||
|
crypto::aes::AesCbcDecrypt(body.getEncTitleKey(), crypto::aes::kAes128KeySize, eticket_common_key, iv, key);
|
||||||
|
size = crypto::aes::kAes128KeySize;
|
||||||
|
printf(" TitleKey:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(key, size, 0x10, 6);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
printf(" Version: v%d.%d.%d (%d)\n", _SPLIT_VER(body.getTicketVersion()), body.getTicketVersion());
|
||||||
|
printf(" License Type: %s\n", getLicenseTypeStr(body.getLicenseType()));
|
||||||
|
|
||||||
|
if (body.getPropertyFlags().size() > 0)
|
||||||
|
{
|
||||||
|
printf(" Flags:\n");
|
||||||
|
for (size_t i = 0; i < body.getPropertyFlags().size(); i++)
|
||||||
|
{
|
||||||
|
printf(" %s\n", getPropertyFlagStr(body.getPropertyFlags()[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" Reserved Region:\n");
|
||||||
|
fnd::SimpleTextOutput::hexDump(body.getReservedRegion(), 8, 0x10, 4);
|
||||||
|
printf(" TicketId: 0x%016" PRIx64 "\n", body.getTicketId());
|
||||||
|
printf(" DeviceId: 0x%016" PRIx64 "\n", body.getDeviceId());
|
||||||
|
printf(" RightsId: ");
|
||||||
|
fnd::SimpleTextOutput::hexDump(body.getRightsId(), 16);
|
||||||
|
|
||||||
|
printf(" SectionTotalSize: 0x%x\n", body.getSectionTotalSize());
|
||||||
|
printf(" SectionHeaderOffset: 0x%x\n", body.getSectionHeaderOffset());
|
||||||
|
printf(" SectionNum: 0x%x\n", body.getSectionNum());
|
||||||
|
printf(" SectionEntrySize: 0x%x\n", body.getSectionEntrySize());
|
||||||
|
|
||||||
|
|
||||||
|
#undef _HEXDUMP_L
|
||||||
|
#undef _HEXDUMP_U
|
||||||
|
#undef _SPLIT_VER
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* EsTikProcess::getTitleKeyPersonalisationStr(byte_t flag) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
switch(flag)
|
||||||
|
{
|
||||||
|
case (es::ticket::AES128_CBC):
|
||||||
|
str = "Generic (AESCBC)";
|
||||||
|
break;
|
||||||
|
case (es::ticket::RSA2048):
|
||||||
|
str = "Personalised (RSA2048)";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* EsTikProcess::getLicenseTypeStr(byte_t flag) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
switch(flag)
|
||||||
|
{
|
||||||
|
case (es::ticket::LICENSE_PERMANENT):
|
||||||
|
str = "Permanent";
|
||||||
|
break;
|
||||||
|
case (es::ticket::LICENSE_DEMO):
|
||||||
|
str = "Demo";
|
||||||
|
break;
|
||||||
|
case (es::ticket::LICENSE_TRIAL):
|
||||||
|
str = "Trial";
|
||||||
|
break;
|
||||||
|
case (es::ticket::LICENSE_RENTAL):
|
||||||
|
str = "Rental";
|
||||||
|
break;
|
||||||
|
case (es::ticket::LICENSE_SUBSCRIPTION):
|
||||||
|
str = "Subscription";
|
||||||
|
break;
|
||||||
|
case (es::ticket::LICENSE_SERVICE):
|
||||||
|
str = "Service";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* EsTikProcess::getPropertyFlagStr(byte_t flag) const
|
||||||
|
{
|
||||||
|
const char* str = nullptr;
|
||||||
|
switch(flag)
|
||||||
|
{
|
||||||
|
case (es::ticket::FLAG_PRE_INSTALL):
|
||||||
|
str = "PreInstall";
|
||||||
|
break;
|
||||||
|
case (es::ticket::FLAG_SHARED_TITLE):
|
||||||
|
str = "SharedTitle";
|
||||||
|
break;
|
||||||
|
case (es::ticket::FLAG_ALLOW_ALL_CONTENT):
|
||||||
|
str = "AllContent";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str = "Unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
38
programs/nstool/source/EsTikProcess.h
Normal file
38
programs/nstool/source/EsTikProcess.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/IFile.h>
|
||||||
|
#include <fnd/Vec.h>
|
||||||
|
#include <es/SignedData.h>
|
||||||
|
#include <es/TicketBody_V2.h>
|
||||||
|
#include "nstool.h"
|
||||||
|
|
||||||
|
class EsTikProcess
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EsTikProcess();
|
||||||
|
~EsTikProcess();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setInputFile(fnd::IFile* file, bool ownIFile);
|
||||||
|
void setKeyset(const sKeyset* keyset);
|
||||||
|
void setCliOutputMode(CliOutputMode mode);
|
||||||
|
void setVerifyMode(bool verify);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "EsTikProcess";
|
||||||
|
|
||||||
|
fnd::IFile* mFile;
|
||||||
|
bool mOwnIFile;
|
||||||
|
const sKeyset* mKeyset;
|
||||||
|
CliOutputMode mCliOutputMode;
|
||||||
|
bool mVerify;
|
||||||
|
|
||||||
|
es::SignedData<es::TicketBody_V2> mTik;
|
||||||
|
|
||||||
|
void displayTicket();
|
||||||
|
const char* getTitleKeyPersonalisationStr(byte_t flag) const;
|
||||||
|
const char* getLicenseTypeStr(byte_t flag) const;
|
||||||
|
const char* getPropertyFlagStr(byte_t flag) const;
|
||||||
|
};
|
|
@ -10,6 +10,8 @@
|
||||||
#include "NsoProcess.h"
|
#include "NsoProcess.h"
|
||||||
#include "NroProcess.h"
|
#include "NroProcess.h"
|
||||||
#include "NacpProcess.h"
|
#include "NacpProcess.h"
|
||||||
|
#include "EsCertProcess.h"
|
||||||
|
#include "EsTikProcess.h"
|
||||||
#include "AssetProcess.h"
|
#include "AssetProcess.h"
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
@ -158,6 +160,28 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
nacp.process();
|
nacp.process();
|
||||||
}
|
}
|
||||||
|
else if (user_set.getFileType() == FILE_ES_CERT)
|
||||||
|
{
|
||||||
|
EsCertProcess cert;
|
||||||
|
|
||||||
|
cert.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
|
cert.setKeyset(&user_set.getKeyset());
|
||||||
|
cert.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
|
cert.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
cert.process();
|
||||||
|
}
|
||||||
|
else if (user_set.getFileType() == FILE_ES_TIK)
|
||||||
|
{
|
||||||
|
EsTikProcess tik;
|
||||||
|
|
||||||
|
tik.setInputFile(new fnd::SimpleFile(user_set.getInputPath(), fnd::SimpleFile::Read), OWN_IFILE);
|
||||||
|
tik.setKeyset(&user_set.getKeyset());
|
||||||
|
tik.setCliOutputMode(user_set.getCliOutputMode());
|
||||||
|
tik.setVerifyMode(user_set.isVerifyFile());
|
||||||
|
|
||||||
|
tik.process();
|
||||||
|
}
|
||||||
else if (user_set.getFileType() == FILE_HB_ASSET)
|
else if (user_set.getFileType() == FILE_HB_ASSET)
|
||||||
{
|
{
|
||||||
AssetProcess obj;
|
AssetProcess obj;
|
||||||
|
|
Loading…
Reference in a new issue