[nstool] Root issuer validation, via key provided in key file.

This commit is contained in:
jakcron 2018-07-30 04:21:19 +08:00
parent 0aebf43f4b
commit a569ecc29d
4 changed files with 47 additions and 30 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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;