mirror of
https://github.com/jakcron/nstool
synced 2024-12-27 07:01:20 +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_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_header_key : AES128-XTS Key (0x20 bytes)
|
||||
nca_header_sign_key_modulus : RSA2048 Modulus (0x100 bytes)
|
||||
|
|
|
@ -93,12 +93,6 @@ void EsCertProcess::validateCert(const es::SignedData<es::CertificateBody>& cert
|
|||
|
||||
try
|
||||
{
|
||||
// special case if signed by Root
|
||||
if (cert.getBody().getIssuer() == es::sign::kRootIssuerStr)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Signed by Root");
|
||||
}
|
||||
|
||||
// get cert hash
|
||||
switch (cert_hash_algo)
|
||||
{
|
||||
|
@ -112,28 +106,40 @@ void EsCertProcess::validateCert(const es::SignedData<es::CertificateBody>& cert
|
|||
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
|
||||
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());
|
||||
}
|
||||
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");
|
||||
if (cert_sign_algo != es::sign::SIGN_ALGO_RSA4096)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Issued by Root, but does not have a RSA4096 signature");
|
||||
}
|
||||
sig_validate_res = crypto::rsa::pkcs::rsaVerify(mKeyset->pki_root_sign_key, getCryptoHashAlgoFromEsSignHashAlgo(cert_hash_algo), cert_hash, cert.getSignature().getSignature().data());
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -423,6 +423,7 @@ void UserSettings::populateKeyset(sCmdArgs& args)
|
|||
const std::string kKekGenSource = "aes_kek_generation";
|
||||
const std::string kKeyGenSource = "aes_key_generation";
|
||||
const std::string kAcidBase = "acid";
|
||||
const std::string kPkiRootBase = "pki_root";
|
||||
const std::string kTicketCommonKeyBase[2] = { "titlekek", "ticket_commonkey" };
|
||||
const std::string kNcaBodyBase[2] = {"key_area_key", "nca_body_keak"};
|
||||
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);
|
||||
|
||||
// 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[1]), mKeyset.nca.header_sign_key.modulus, 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, 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[1]), mKeyset.xci.header_sign_key.modulus, 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, 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[1]), mKeyset.acid_sign_key.modulus, 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, 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
|
||||
if (args.nca_bodykey.isSet)
|
||||
|
|
|
@ -65,6 +65,8 @@ struct sKeyset
|
|||
{
|
||||
crypto::rsa::sRsa2048Key acid_sign_key;
|
||||
|
||||
crypto::rsa::sRsa4096Key pki_root_sign_key;
|
||||
|
||||
crypto::aes::sAes128Key package1_key[kMasterKeyNum];
|
||||
crypto::rsa::sRsa2048Key package2_sign_key;
|
||||
crypto::aes::sAes128Key package2_key[kMasterKeyNum];
|
||||
|
@ -86,7 +88,7 @@ struct sKeyset
|
|||
crypto::rsa::sRsa2048Key header_sign_key;
|
||||
crypto::aes::sAes128Key header_key;
|
||||
} xci;
|
||||
|
||||
|
||||
struct sTicketData
|
||||
{
|
||||
crypto::rsa::sRsa2048Key sign_key;
|
||||
|
|
Loading…
Reference in a new issue