mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
[nstool] Root issuer validation, via key provided in key file.
This commit is contained in:
parent
0aebf43f4b
commit
a569ecc29d
4 changed files with 47 additions and 30 deletions
4
KEYS.md
4
KEYS.md
|
@ -25,6 +25,10 @@ package2_sign_key_private : RSA2048 Private Exponent (0x100 bytes)
|
||||||
; Ticket Keys
|
; Ticket Keys
|
||||||
ticket_commonkey_## : AES128 Key (0x10 bytes)
|
ticket_commonkey_## : AES128 Key (0x10 bytes)
|
||||||
|
|
||||||
|
; PKI Root Signing Key
|
||||||
|
pki_root_sign_key_modulus : RSA4096 Modulus (0x200 bytes)
|
||||||
|
pki_root_sign_key_private : RSA4096 Private Exponent (0x200 bytes)
|
||||||
|
|
||||||
; NCA Keys
|
; NCA Keys
|
||||||
nca_header_key : AES128-XTS Key (0x20 bytes)
|
nca_header_key : AES128-XTS Key (0x20 bytes)
|
||||||
nca_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
nca_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
||||||
|
|
|
@ -93,12 +93,6 @@ void EsCertProcess::validateCert(const es::SignedData<es::CertificateBody>& cert
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// special case if signed by Root
|
|
||||||
if (cert.getBody().getIssuer() == es::sign::kRootIssuerStr)
|
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "Signed by Root");
|
|
||||||
}
|
|
||||||
|
|
||||||
// get cert hash
|
// get cert hash
|
||||||
switch (cert_hash_algo)
|
switch (cert_hash_algo)
|
||||||
{
|
{
|
||||||
|
@ -112,28 +106,40 @@ void EsCertProcess::validateCert(const es::SignedData<es::CertificateBody>& cert
|
||||||
throw fnd::Exception(kModuleName, "Unrecognised hash type");
|
throw fnd::Exception(kModuleName, "Unrecognised hash type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to find issuer cert
|
|
||||||
const es::CertificateBody& issuer = getIssuerCert(cert.getBody().getIssuer()).getBody();
|
|
||||||
es::cert::PublicKeyType issuer_pubk_type = issuer.getPublicKeyType();
|
|
||||||
|
|
||||||
// validate signature
|
// validate signature
|
||||||
int sig_validate_res = -1;
|
int sig_validate_res = -1;
|
||||||
|
|
||||||
if (issuer_pubk_type == es::cert::RSA4096 && cert_sign_algo == es::sign::SIGN_ALGO_RSA4096)
|
// special case if signed by Root
|
||||||
|
if (cert.getBody().getIssuer() == es::sign::kRootIssuerStr)
|
||||||
{
|
{
|
||||||
sig_validate_res = crypto::rsa::pkcs::rsaVerify(issuer.getRsa4098PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
if (cert_sign_algo != es::sign::SIGN_ALGO_RSA4096)
|
||||||
}
|
{
|
||||||
else if (issuer_pubk_type == es::cert::RSA2048 && cert_sign_algo == es::sign::SIGN_ALGO_RSA2048)
|
throw fnd::Exception(kModuleName, "Issued by Root, but does not have a RSA4096 signature");
|
||||||
{
|
}
|
||||||
sig_validate_res = crypto::rsa::pkcs::rsaVerify(issuer.getRsa2048PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
sig_validate_res = crypto::rsa::pkcs::rsaVerify(mKeyset->pki_root_sign_key, getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
||||||
}
|
|
||||||
else if (issuer_pubk_type == es::cert::ECDSA240 && cert_sign_algo == es::sign::SIGN_ALGO_ECDSA240)
|
|
||||||
{
|
|
||||||
throw fnd::Exception(kModuleName, "ECDSA signatures are not supported");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw fnd::Exception(kModuleName, "Mismatch between issuer public key and signature type");
|
// try to find issuer cert
|
||||||
|
const es::CertificateBody& issuer = getIssuerCert(cert.getBody().getIssuer()).getBody();
|
||||||
|
es::cert::PublicKeyType issuer_pubk_type = issuer.getPublicKeyType();
|
||||||
|
|
||||||
|
if (issuer_pubk_type == es::cert::RSA4096 && cert_sign_algo == es::sign::SIGN_ALGO_RSA4096)
|
||||||
|
{
|
||||||
|
sig_validate_res = crypto::rsa::pkcs::rsaVerify(issuer.getRsa4098PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
||||||
|
}
|
||||||
|
else if (issuer_pubk_type == es::cert::RSA2048 && cert_sign_algo == es::sign::SIGN_ALGO_RSA2048)
|
||||||
|
{
|
||||||
|
sig_validate_res = crypto::rsa::pkcs::rsaVerify(issuer.getRsa2048PublicKey(), getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
||||||
|
}
|
||||||
|
else if (issuer_pubk_type == es::cert::ECDSA240 && cert_sign_algo == es::sign::SIGN_ALGO_ECDSA240)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "ECDSA signatures are not supported");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Mismatch between issuer public key and signature type");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sig_validate_res != 0)
|
if (sig_validate_res != 0)
|
||||||
|
|
|
@ -423,6 +423,7 @@ void UserSettings::populateKeyset(sCmdArgs& args)
|
||||||
const std::string kKekGenSource = "aes_kek_generation";
|
const std::string kKekGenSource = "aes_kek_generation";
|
||||||
const std::string kKeyGenSource = "aes_key_generation";
|
const std::string kKeyGenSource = "aes_key_generation";
|
||||||
const std::string kAcidBase = "acid";
|
const std::string kAcidBase = "acid";
|
||||||
|
const std::string kPkiRootBase = "pki_root";
|
||||||
const std::string kTicketCommonKeyBase[2] = { "titlekek", "ticket_commonkey" };
|
const std::string kTicketCommonKeyBase[2] = { "titlekek", "ticket_commonkey" };
|
||||||
const std::string kNcaBodyBase[2] = {"key_area_key", "nca_body_keak"};
|
const std::string kNcaBodyBase[2] = {"key_area_key", "nca_body_keak"};
|
||||||
const std::string kNcaBodyKeakIndexName[3] = {"application", "ocean", "system"};
|
const std::string kNcaBodyKeakIndexName[3] = {"application", "ocean", "system"};
|
||||||
|
@ -492,17 +493,21 @@ void UserSettings::populateKeyset(sCmdArgs& args)
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kKeyStr), mKeyset.xci.header_key.key, 0x10);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kKeyStr), mKeyset.xci.header_key.key, 0x10);
|
||||||
|
|
||||||
// store rsa keys
|
// store rsa keys
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[1], kRsaKeySuffix[0]), mKeyset.nca.header_sign_key.priv_exponent, 0x100);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[1], kRsaKeySuffix[0]), mKeyset.nca.header_sign_key.priv_exponent, crypto::rsa::kRsa2048Size);
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[1], kRsaKeySuffix[1]), mKeyset.nca.header_sign_key.modulus, 0x100);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kNcaHeaderBase[1], kRsaKeySuffix[1]), mKeyset.nca.header_sign_key.modulus, crypto::rsa::kRsa2048Size);
|
||||||
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kRsaKeySuffix[0]), mKeyset.xci.header_sign_key.priv_exponent, 0x100);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kRsaKeySuffix[0]), mKeyset.xci.header_sign_key.priv_exponent, crypto::rsa::kRsa2048Size);
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kRsaKeySuffix[1]), mKeyset.xci.header_sign_key.modulus, 0x100);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kXciHeaderBase, kRsaKeySuffix[1]), mKeyset.xci.header_sign_key.modulus, crypto::rsa::kRsa2048Size);
|
||||||
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase, kRsaKeySuffix[0]), mKeyset.acid_sign_key.priv_exponent, 0x100);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase, kRsaKeySuffix[0]), mKeyset.acid_sign_key.priv_exponent, crypto::rsa::kRsa2048Size);
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase, kRsaKeySuffix[1]), mKeyset.acid_sign_key.modulus, 0x100);
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kAcidBase, kRsaKeySuffix[1]), mKeyset.acid_sign_key.modulus, crypto::rsa::kRsa2048Size);
|
||||||
|
|
||||||
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPackage2Base, kRsaKeySuffix[0]), mKeyset.package2_sign_key.priv_exponent, crypto::rsa::kRsa2048Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPackage2Base, kRsaKeySuffix[1]), mKeyset.package2_sign_key.modulus, crypto::rsa::kRsa2048Size);
|
||||||
|
|
||||||
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase, kRsaKeySuffix[0]), mKeyset.pki_root_sign_key.priv_exponent, crypto::rsa::kRsa4096Size);
|
||||||
|
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPkiRootBase, kRsaKeySuffix[1]), mKeyset.pki_root_sign_key.modulus, crypto::rsa::kRsa4096Size);
|
||||||
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPackage2Base, kRsaKeySuffix[0]), mKeyset.package2_sign_key.priv_exponent, 0x100);
|
|
||||||
_SAVE_KEYDATA(_CONCAT_2_STRINGS(kPackage2Base, kRsaKeySuffix[1]), mKeyset.package2_sign_key.modulus, 0x100);
|
|
||||||
|
|
||||||
// save keydata from input args
|
// save keydata from input args
|
||||||
if (args.nca_bodykey.isSet)
|
if (args.nca_bodykey.isSet)
|
||||||
|
|
|
@ -65,6 +65,8 @@ struct sKeyset
|
||||||
{
|
{
|
||||||
crypto::rsa::sRsa2048Key acid_sign_key;
|
crypto::rsa::sRsa2048Key acid_sign_key;
|
||||||
|
|
||||||
|
crypto::rsa::sRsa4096Key pki_root_sign_key;
|
||||||
|
|
||||||
crypto::aes::sAes128Key package1_key[kMasterKeyNum];
|
crypto::aes::sAes128Key package1_key[kMasterKeyNum];
|
||||||
crypto::rsa::sRsa2048Key package2_sign_key;
|
crypto::rsa::sRsa2048Key package2_sign_key;
|
||||||
crypto::aes::sAes128Key package2_key[kMasterKeyNum];
|
crypto::aes::sAes128Key package2_key[kMasterKeyNum];
|
||||||
|
@ -86,7 +88,7 @@ struct sKeyset
|
||||||
crypto::rsa::sRsa2048Key header_sign_key;
|
crypto::rsa::sRsa2048Key header_sign_key;
|
||||||
crypto::aes::sAes128Key header_key;
|
crypto::aes::sAes128Key header_key;
|
||||||
} xci;
|
} xci;
|
||||||
|
|
||||||
struct sTicketData
|
struct sTicketData
|
||||||
{
|
{
|
||||||
crypto::rsa::sRsa2048Key sign_key;
|
crypto::rsa::sRsa2048Key sign_key;
|
||||||
|
|
Loading…
Reference in a new issue