aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/x509/cert_status.cpp7
-rw-r--r--src/lib/x509/cert_status.h2
-rw-r--r--src/lib/x509/x509_obj.cpp110
-rw-r--r--src/lib/x509/x509_obj.h18
-rw-r--r--src/lib/x509/x509cert.cpp13
-rw-r--r--src/lib/x509/x509path.cpp8
6 files changed, 99 insertions, 59 deletions
diff --git a/src/lib/x509/cert_status.cpp b/src/lib/x509/cert_status.cpp
index 76a102aef..9561cae57 100644
--- a/src/lib/x509/cert_status.cpp
+++ b/src/lib/x509/cert_status.cpp
@@ -91,7 +91,12 @@ const char* to_string(Certificate_Status_Code code)
return "Signature error";
case Certificate_Status_Code::CERT_PUBKEY_INVALID:
return "Certificate public key invalid";
- // intentionally no default so we are warned
+ case Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN:
+ return "Certificate signed with unknown/unavailable algorithm";
+ case Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS:
+ return "Certificate signature has invalid parameters";
+
+ // intentionally no default so we are warned if new enum values are added
}
return nullptr;
diff --git a/src/lib/x509/cert_status.h b/src/lib/x509/cert_status.h
index fb246e71a..0dd9f7b84 100644
--- a/src/lib/x509/cert_status.h
+++ b/src/lib/x509/cert_status.h
@@ -72,6 +72,8 @@ enum class Certificate_Status_Code {
CRL_BAD_SIGNATURE = 5001,
SIGNATURE_ERROR = 5002,
CERT_PUBKEY_INVALID = 5003,
+ SIGNATURE_ALGO_UNKNOWN = 5004,
+ SIGNATURE_ALGO_BAD_PARAMS = 5005
};
/**
diff --git a/src/lib/x509/x509_obj.cpp b/src/lib/x509/x509_obj.cpp
index 309bdb1f9..01a92a001 100644
--- a/src/lib/x509/x509_obj.cpp
+++ b/src/lib/x509/x509_obj.cpp
@@ -183,71 +183,85 @@ bool X509_Object::check_signature(const Public_Key* pub_key) const
return check_signature(*key);
}
-/*
-* Check the signature on an object
-*/
bool X509_Object::check_signature(const Public_Key& pub_key) const
{
- try {
- std::vector<std::string> sig_info =
- split_on(OIDS::lookup(m_sig_algo.get_oid()), '/');
+ const Certificate_Status_Code code = verify_signature(pub_key);
+ return (code == Certificate_Status_Code::VERIFIED);
+ }
- if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
- return false;
+Certificate_Status_Code X509_Object::verify_signature(const Public_Key& pub_key) const
+ {
+ const std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(m_sig_algo.get_oid()), '/');
- std::string padding = sig_info[1];
- Signature_Format format =
- (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+ if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name())
+ return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
- if(padding == "EMSA4")
- {
- // "MUST contain RSASSA-PSS-params"
- if(signature_algorithm().get_parameters().empty())
- {
- return false;
- }
+ std::string padding = sig_info[1];
+ const Signature_Format format =
+ (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
- Pss_params pss_parameter = decode_pss_params(signature_algorithm().get_parameters());
+ if(padding == "EMSA4")
+ {
+ // "MUST contain RSASSA-PSS-params"
+ if(signature_algorithm().parameters.empty())
+ {
+ return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
+ }
- // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
- std::string hash_algo = OIDS::lookup(pss_parameter.hash_algo.get_oid());
- if(hash_algo != "SHA-160" && hash_algo != "SHA-224" && hash_algo != "SHA-256" && hash_algo != "SHA-384"
- && hash_algo != "SHA-512")
- {
- return false;
- }
+ Pss_params pss_parameter = decode_pss_params(signature_algorithm().parameters);
- std::string mgf_algo = OIDS::lookup(pss_parameter.mask_gen_algo.get_oid());
- if(mgf_algo != "MGF1")
- {
- return false;
- }
+ // hash_algo must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
+ const std::string hash_algo = OIDS::lookup(pss_parameter.hash_algo.oid);
+ if(hash_algo != "SHA-160" &&
+ hash_algo != "SHA-224" &&
+ hash_algo != "SHA-256" &&
+ hash_algo != "SHA-384" &&
+ hash_algo != "SHA-512")
+ {
+ return Certificate_Status_Code::UNTRUSTED_HASH;
+ }
- // For MGF1, it is strongly RECOMMENDED that the underlying hash function be the same as the one identified by hashAlgorithm
- // Must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
- if(pss_parameter.mask_gen_hash.get_oid() != pss_parameter.hash_algo.get_oid())
- {
- return false;
- }
+ const std::string mgf_algo = OIDS::lookup(pss_parameter.mask_gen_algo.oid);
+ if(mgf_algo != "MGF1")
+ {
+ return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
+ }
- if(pss_parameter.trailer_field != 1)
- {
- return false;
- }
+ // For MGF1, it is strongly RECOMMENDED that the underlying hash function be the same as the one identified by hashAlgorithm
+ // Must be SHA1, SHA2-224, SHA2-256, SHA2-384 or SHA2-512
+ if(pss_parameter.mask_gen_hash.oid != pss_parameter.hash_algo.oid)
+ {
+ return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
+ }
- padding += "(" + hash_algo;
- padding += "," + mgf_algo;
- padding += "," + std::to_string(pss_parameter.salt_len) +
- ")"; // salt_len is actually not used for verification. Length is inferred from the signature
+ if(pss_parameter.trailer_field != 1)
+ {
+ return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
}
+ // salt_len is actually not used for verification. Length is inferred from the signature
+ padding += "(" + hash_algo + "," + mgf_algo + "," + std::to_string(pss_parameter.salt_len) + ")";
+ }
+
+ try
+ {
PK_Verifier verifier(pub_key, padding, format);
+ const bool valid = verifier.verify_message(tbs_data(), signature());
- return verifier.verify_message(tbs_data(), signature());
+ if(valid)
+ return Certificate_Status_Code::VERIFIED;
+ else
+ return Certificate_Status_Code::SIGNATURE_ERROR;
+ }
+ catch(Algorithm_Not_Found&)
+ {
+ return Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN;
}
- catch(std::exception&)
+ catch(...)
{
- return false;
+ // This shouldn't happen, fallback to generic signature error
+ return Certificate_Status_Code::SIGNATURE_ERROR;
}
}
diff --git a/src/lib/x509/x509_obj.h b/src/lib/x509/x509_obj.h
index c9ff0f761..72ba0f534 100644
--- a/src/lib/x509/x509_obj.h
+++ b/src/lib/x509/x509_obj.h
@@ -10,6 +10,7 @@
#include <botan/asn1_obj.h>
#include <botan/alg_id.h>
+#include <botan/cert_status.h>
#include <vector>
namespace Botan {
@@ -59,9 +60,17 @@ class BOTAN_PUBLIC_API(2,0) X509_Object : public ASN1_Object
* @return signed X509 object
*/
static std::vector<uint8_t> make_signed(class PK_Signer* signer,
- RandomNumberGenerator& rng,
- const AlgorithmIdentifier& alg_id,
- const secure_vector<uint8_t>& tbs);
+ RandomNumberGenerator& rng,
+ const AlgorithmIdentifier& alg_id,
+ const secure_vector<uint8_t>& tbs);
+
+ /**
+ * Check the signature on this data
+ * @param key the public key purportedly used to sign this data
+ * @return status of the signature - OK if verified or otherwise an indicator of
+ * the problem preventing verification.
+ */
+ Certificate_Status_Code verify_signature(const Public_Key& key) const;
/**
* Check the signature on this data
@@ -73,7 +82,8 @@ class BOTAN_PUBLIC_API(2,0) X509_Object : public ASN1_Object
/**
* Check the signature on this data
* @param key the public key purportedly used to sign this data
- * the pointer will be deleted after use
+ * the object will be deleted after use (this should have
+ * been a std::unique_ptr<Public_Key>)
* @return true if the signature is valid, otherwise false
*/
bool check_signature(const Public_Key* key) const;
diff --git a/src/lib/x509/x509cert.cpp b/src/lib/x509/x509cert.cpp
index da691452b..b1229679c 100644
--- a/src/lib/x509/x509cert.cpp
+++ b/src/lib/x509/x509cert.cpp
@@ -257,13 +257,22 @@ std::unique_ptr<X509_Certificate_Data> parse_x509_cert_body(const X509_Object& o
// Check for self-signed vs self-issued certificates
if(data->m_subject_dn == data->m_issuer_dn)
{
+ data->m_self_signed = false;
+
try
{
std::unique_ptr<Public_Key> pub_key(
X509::load_key(ASN1::put_in_sequence(data->m_subject_public_key_bits)));
- data->m_self_signed = obj.check_signature(*pub_key);
+
+ Certificate_Status_Code sig_status = obj.verify_signature(*pub_key);
+
+ if(sig_status == Certificate_Status_Code::OK ||
+ sig_status == Certificate_Status_Code::SIGNATURE_ALGO_UNKNOWN)
+ {
+ data->m_self_signed = true;
+ }
}
- catch(Decoding_Error&)
+ catch(...)
{
// ignore errors here to allow parsing to continue
}
diff --git a/src/lib/x509/x509path.cpp b/src/lib/x509/x509path.cpp
index 237ac33a5..c2a22e7f4 100644
--- a/src/lib/x509/x509path.cpp
+++ b/src/lib/x509/x509path.cpp
@@ -100,10 +100,10 @@ PKIX::check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& ce
}
else
{
- if(subject->check_signature(*issuer_key) == false)
- {
- status.insert(Certificate_Status_Code::SIGNATURE_ERROR);
- }
+ const Certificate_Status_Code sig_status = subject->verify_signature(*issuer_key);
+
+ if(sig_status != Certificate_Status_Code::VERIFIED)
+ status.insert(sig_status);
if(issuer_key->estimated_strength() < min_signature_algo_strength)
status.insert(Certificate_Status_Code::SIGNATURE_METHOD_TOO_WEAK);