Ported PkiValidator to libtoolchain.

This commit is contained in:
jakcron 2021-09-30 19:40:45 +08:00
parent 5c970a2986
commit 6a3bd0e562
2 changed files with 81 additions and 57 deletions

View file

@ -1,10 +1,11 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <nn/pki/SignUtils.h>
#include "PkiValidator.h" #include "PkiValidator.h"
nstool::PkiValidator::PkiValidator() #include <tc/crypto.h>
#include <nn/hac/define/types.h>
#include <nn/pki/SignUtils.h>
nstool::PkiValidator::PkiValidator() :
mModuleName("nstool::PkiValidator")
{ {
clearCertificates(); clearCertificates();
} }
@ -48,7 +49,7 @@ void nstool::PkiValidator::addCertificate(const nn::pki::SignedData<nn::pki::Cer
if (doesCertExist(cert_ident) == true) if (doesCertExist(cert_ident) == true)
{ {
throw tc::Exception(kModuleName, "Certificate already exists"); throw tc::Exception(mModuleName, "Certificate already exists");
} }
cert_sign_algo = nn::pki::sign::getSignatureAlgo(cert.getSignature().getSignType()); cert_sign_algo = nn::pki::sign::getSignatureAlgo(cert.getSignature().getSignType());
@ -58,15 +59,16 @@ void nstool::PkiValidator::addCertificate(const nn::pki::SignedData<nn::pki::Cer
switch (cert_hash_algo) switch (cert_hash_algo)
{ {
case (nn::pki::sign::HASH_ALGO_SHA1): case (nn::pki::sign::HASH_ALGO_SHA1):
cert_hash.alloc(fnd::sha::kSha1HashLen);
fnd::sha::Sha1(cert.getBody().getBytes().data(), cert.getBody().getBytes().size(), cert_hash.data()); cert_hash = tc::ByteData(tc::crypto::Sha1Generator::kHashSize);
tc::crypto::GenerateSha1Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size());
break; break;
case (nn::pki::sign::HASH_ALGO_SHA256): case (nn::pki::sign::HASH_ALGO_SHA256):
cert_hash.alloc(fnd::sha::kSha256HashLen); cert_hash = tc::ByteData(tc::crypto::Sha256Generator::kHashSize);
fnd::sha::Sha256(cert.getBody().getBytes().data(), cert.getBody().getBytes().size(), cert_hash.data()); tc::crypto::GenerateSha256Hash(cert_hash.data(), cert.getBody().getBytes().data(), cert.getBody().getBytes().size());
break; break;
default: default:
throw tc::Exception(kModuleName, "Unrecognised hash type"); throw tc::Exception(mModuleName, "Unrecognised hash type");
} }
validateSignature(cert.getBody().getIssuer(), cert.getSignature().getSignType(), cert.getSignature().getSignature(), cert_hash); validateSignature(cert.getBody().getIssuer(), cert.getSignature().getSignType(), cert.getSignature().getSignature(), cert_hash);
@ -75,9 +77,7 @@ void nstool::PkiValidator::addCertificate(const nn::pki::SignedData<nn::pki::Cer
} }
catch (const tc::Exception& e) catch (const tc::Exception& e)
{ {
std::stringstream ss; throw tc::Exception(mModuleName, fmt::format("Failed to add certificate {:s} ({:s})", cert_ident, e.error());
ss << "Failed to add certificate " << cert_ident << " (" << e.error() << ")";
throw tc::Exception(kModuleName, ss.str());
} }
} }
@ -93,31 +93,33 @@ void nstool::PkiValidator::validateSignature(const std::string& issuer, nn::pki:
// validate signature // validate signature
int sig_validate_res = -1; bool sig_valid = false;
// special case if signed by Root // get public key
if (issuer.find('-', 0) == std::string::npos) // tc::crypto::EccKey ecc_key;
{ tc::crypto::RsaKey rsa_key;
fnd::rsa::sRsa4096Key rsa4096_pub;
fnd::rsa::sRsa2048Key rsa2048_pub;
fnd::ecdsa::sEcdsa240Key ecdsa_pub;
if (mKeyCfg.getPkiRootSignKey(issuer, rsa4096_pub) == true && sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096) // special case if signed by Root (legacy nstool only defers to keybag for "Root", it did not store certificates)
if (issuer == "Root")
{ {
sig_validate_res = fnd::rsa::pkcs::rsaVerify(rsa4096_pub, getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data()); auto itr = mKeyCfg.broadon_signer.find(issuer);
}
else if (mKeyCfg.getPkiRootSignKey(issuer, rsa2048_pub) == true && sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048) if (itr == mKeyCfg.broadon_signer.end())
{ {
sig_validate_res = fnd::rsa::pkcs::rsaVerify(rsa2048_pub, getCryptoHashAlgoFromEsSignHashAlgo(hash_algo), hash.data(), signature.data()); throw tc::Exception(mModuleName, fmt::print("Public key for issuer \"{:s}\" does not exist.", issuer);
} }
else if (mKeyCfg.getPkiRootSignKey(issuer, ecdsa_pub) == true && sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
if (sign_algo != itr->second.key_type)
{ {
throw tc::Exception(kModuleName, "ECDSA signatures are not supported"); throw tc::Exception(mModuleName, fmt::print("Public key for issuer \"{:s}\" cannot verify this signature.", issuer);
} }
else
if (sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
{ {
throw tc::Exception(kModuleName, "Public key for issuer \"" + issuer + "\" does not exist."); throw tc::Exception(mModuleName, "ECDSA signatures are not supported");
} }
rsa_key = itr->second.rsa_key;
} }
else else
{ {
@ -127,25 +129,65 @@ 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) if (issuer_pubk_type == nn::pki::cert::RSA4096 && 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()); rsa_key = issuer_cert.getRsa4098PublicKey();
} }
else if (issuer_pubk_type == nn::pki::cert::RSA2048 && sign_algo == nn::pki::sign::SIGN_ALGO_RSA2048) else if (issuer_pubk_type == nn::pki::cert::RSA2048 && 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()); rsa_key = issuer_cert.getRsa2048PublicKey();
} }
else if (issuer_pubk_type == nn::pki::cert::ECDSA240 && sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240) else if (issuer_pubk_type == nn::pki::cert::ECDSA240 && sign_algo == nn::pki::sign::SIGN_ALGO_ECDSA240)
{ {
throw tc::Exception(kModuleName, "ECDSA signatures are not supported"); // ecc_key = issuer_cert.getEcdsa240PublicKey();
throw tc::Exception(mModuleName, "ECDSA signatures are not supported");
} }
else else
{ {
throw tc::Exception(kModuleName, "Mismatch between issuer public key and signature type"); throw tc::Exception(mModuleName, "Mismatch between issuer public key and signature type");
} }
} }
if (sig_validate_res != 0) // verify signature
switch (signature_id) {
case (SIGN_ID_RSA4096_SHA1):
sig_validate_res = 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);
break;
case (SIGN_ID_ECDSA240_SHA1):
sig_validate_res = false;
break;
case (SIGN_ID_RSA4096_SHA256):
sig_validate_res = 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);
break;
case (SIGN_ID_ECDSA240_SHA256):
sig_validate_res = false;
break;
}
if (sign_algo == nn::pki::sign::SIGN_ALGO_RSA4096)
{ {
throw tc::Exception(kModuleName, "Incorrect signature"); 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)
{
throw tc::Exception(mModuleName, "Incorrect signature");
} }
@ -159,7 +201,7 @@ void nstool::PkiValidator::makeCertIdent(const nn::pki::SignedData<nn::pki::Cert
void nstool::PkiValidator::makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const void nstool::PkiValidator::makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const
{ {
ident = issuer + nn::pki::sign::kIdentDelimiter + subject; ident = issuer + nn::pki::sign::kIdentDelimiter + subject;
ident = ident.substr(0, _MIN(ident.length(),64)); ident = ident.substr(0, std::min<size_t>(ident.length(),64));
} }
bool nstool::PkiValidator::doesCertExist(const std::string& ident) const bool nstool::PkiValidator::doesCertExist(const std::string& ident) const
@ -191,22 +233,5 @@ const nn::pki::SignedData<nn::pki::CertificateBody>& nstool::PkiValidator::getCe
} }
} }
throw tc::Exception(kModuleName, "Issuer certificate does not exist"); throw tc::Exception(mModuleName, "Issuer certificate does not exist");
}
fnd::sha::HashType nstool::PkiValidator::getCryptoHashAlgoFromEsSignHashAlgo(nn::pki::sign::HashAlgo hash_algo) const
{
fnd::sha::HashType hash_type = fnd::sha::HASH_SHA1;
switch (hash_algo)
{
case (nn::pki::sign::HASH_ALGO_SHA1):
hash_type = fnd::sha::HASH_SHA1;
break;
case (nn::pki::sign::HASH_ALGO_SHA256):
hash_type = fnd::sha::HASH_SHA256;
break;
};
return hash_type;
} }

View file

@ -20,7 +20,7 @@ public:
void validateSignature(const std::string& issuer, nn::pki::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const; void validateSignature(const std::string& issuer, nn::pki::sign::SignatureId signature_id, const tc::ByteData& signature, const tc::ByteData& hash) const;
private: private:
const std::string kModuleName = "NNPkiValidator"; std::string mModuleName;
KeyBag mKeyCfg; KeyBag mKeyCfg;
std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCertificateBank; std::vector<nn::pki::SignedData<nn::pki::CertificateBody>> mCertificateBank;
@ -29,7 +29,6 @@ private:
void makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const; void makeCertIdent(const std::string& issuer, const std::string& subject, std::string& ident) const;
bool doesCertExist(const std::string& ident) const; bool doesCertExist(const std::string& ident) const;
const nn::pki::SignedData<nn::pki::CertificateBody>& getCert(const std::string& ident) const; const nn::pki::SignedData<nn::pki::CertificateBody>& getCert(const std::string& ident) const;
fnd::sha::HashType getCryptoHashAlgoFromEsSignHashAlgo(nn::pki::sign::HashAlgo hash_algo) const;
}; };
} }