Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add extra 'IssuerNotFound' error #63

Merged
merged 1 commit into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/evse_security/evse_security.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class EvseSecurity {
CertificateValidationResult verify_certificate_internal(const std::string& certificate_chain,
LeafCertificateType certificate_type);
GetKeyPairResult get_key_pair_internal(LeafCertificateType certificate_type, EncodingFormat encoding);
bool is_ca_certificate_installed_internal(CaCertificateType certificate_type);

/// @brief Determines if the total filesize of certificates is > than the max_filesystem_usage bytes
bool is_filesystem_full();
Expand Down
3 changes: 3 additions & 0 deletions lib/evse_security/crypto/openssl/openssl_supplier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static CertificateValidationResult to_certificate_error(const int ec) {
case X509_V_ERR_CERT_SIGNATURE_FAILURE:
return CertificateValidationResult::InvalidSignature;
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
return CertificateValidationResult::IssuerNotFound;
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
return CertificateValidationResult::InvalidLeafSignature;
Expand Down Expand Up @@ -578,11 +579,13 @@ CertificateValidationResult OpenSSLSupplier::x509_verify_certificate_chain(X509H
const char* c_file_path = file_path.has_value() ? file_path.value().c_str() : nullptr;

if (1 != X509_STORE_load_locations(store_ptr.get(), c_file_path, c_dir_path)) {
EVLOG_warning << "X509 could not load store locations!";
return CertificateValidationResult::Unknown;
}

if (dir_path.has_value()) {
if (X509_STORE_add_lookup(store_ptr.get(), X509_LOOKUP_file()) == nullptr) {
EVLOG_warning << "X509 could not add store lookup!";
return CertificateValidationResult::Unknown;
}
}
Expand Down
62 changes: 39 additions & 23 deletions lib/evse_security/evse_security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ InstallCertificateResult EvseSecurity::install_ca_certificate(const std::string&
CaCertificateType certificate_type) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

EVLOG_debug << "Installing ca certificate: " << conversions::ca_certificate_type_to_string(certificate_type);
EVLOG_info << "Installing ca certificate: " << conversions::ca_certificate_type_to_string(certificate_type);

if (is_filesystem_full()) {
EVLOG_error << "Filesystem full, can't install new CA certificate!";
Expand Down Expand Up @@ -299,7 +299,7 @@ InstallCertificateResult EvseSecurity::install_ca_certificate(const std::string&
DeleteCertificateResult EvseSecurity::delete_certificate(const CertificateHashData& certificate_hash_data) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

EVLOG_debug << "Delete ca certificate: " << certificate_hash_data.serial_number;
EVLOG_info << "Delete CA certificate: " << certificate_hash_data.serial_number;

auto response = DeleteCertificateResult::NotFound;

Expand Down Expand Up @@ -396,6 +396,8 @@ InstallCertificateResult EvseSecurity::update_leaf_certificate(const std::string
return InstallCertificateResult::CertificateStoreMaxLengthExceeded;
}

EVLOG_info << "Updating leaf certificate: " << conversions::leaf_certificate_type_to_string(certificate_type);

fs::path cert_path;
fs::path key_path;

Expand Down Expand Up @@ -743,6 +745,10 @@ void EvseSecurity::update_ocsp_cache(const CertificateHashData& certificate_hash
bool EvseSecurity::is_ca_certificate_installed(CaCertificateType certificate_type) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

return is_ca_certificate_installed_internal(certificate_type);
}

bool EvseSecurity::is_ca_certificate_installed_internal(CaCertificateType certificate_type) {
try {
X509CertificateBundle bundle(this->ca_bundle_path_map.at(certificate_type), EncodingFormat::PEM);

Expand All @@ -751,8 +757,9 @@ bool EvseSecurity::is_ca_certificate_installed(CaCertificateType certificate_typ

// Get all roots and search for a valid self-signed
for (auto& root : hierarchy.get_hierarchy()) {
if (root.certificate.is_selfsigned() && root.certificate.is_valid())
if (root.certificate.is_selfsigned() && root.certificate.is_valid()) {
return true;
}
}
} catch (const CertificateLoadException& e) {
EVLOG_error << "Could not load ca certificate type:"
Expand Down Expand Up @@ -843,7 +850,7 @@ GetKeyPairResult EvseSecurity::get_key_pair(LeafCertificateType certificate_type
}

GetKeyPairResult EvseSecurity::get_key_pair_internal(LeafCertificateType certificate_type, EncodingFormat encoding) {
EVLOG_debug << "Requesting key/pair: " << conversions::leaf_certificate_type_to_string(certificate_type);
EVLOG_info << "Requesting key/pair: " << conversions::leaf_certificate_type_to_string(certificate_type);

GetKeyPairResult result;
result.pair = std::nullopt;
Expand Down Expand Up @@ -1060,7 +1067,7 @@ std::string EvseSecurity::get_verify_file(CaCertificateType certificate_type) {
int EvseSecurity::get_leaf_expiry_days_count(LeafCertificateType certificate_type) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

EVLOG_debug << "Requesting certificate expiry: " << conversions::leaf_certificate_type_to_string(certificate_type);
EVLOG_info << "Requesting certificate expiry: " << conversions::leaf_certificate_type_to_string(certificate_type);

// Internal since we already locked mutex
const auto key_pair = this->get_key_pair_internal(certificate_type, EncodingFormat::PEM);
Expand Down Expand Up @@ -1090,7 +1097,7 @@ bool EvseSecurity::verify_file_signature(const fs::path& path, const std::string
const std::string signature) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

EVLOG_debug << "Verifying file signature for " << path.string();
EVLOG_info << "Verifying file signature for " << path.string();

std::vector<std::byte> sha256_digest;

Expand Down Expand Up @@ -1133,6 +1140,27 @@ CertificateValidationResult EvseSecurity::verify_certificate(const std::string&

CertificateValidationResult EvseSecurity::verify_certificate_internal(const std::string& certificate_chain,
LeafCertificateType certificate_type) {
EVLOG_info << "Verifying leaf certificate: " << conversions::leaf_certificate_type_to_string(certificate_type);

CaCertificateType ca_certificate_type;

if (certificate_type == LeafCertificateType::CSMS) {
ca_certificate_type = CaCertificateType::CSMS;
} else if (certificate_type == LeafCertificateType::V2G) {
ca_certificate_type = CaCertificateType::V2G;
} else if (certificate_type == LeafCertificateType::MF)
ca_certificate_type = CaCertificateType::MF;
else if (certificate_type == LeafCertificateType::MO) {
ca_certificate_type = CaCertificateType::MO;
} else {
throw std::runtime_error("Could not convert LeafCertificateType to CaCertificateType during verification!");
}

// If we don't have a root certificate installed, return that we can't find an issuer
if (false == is_ca_certificate_installed_internal(ca_certificate_type)) {
return CertificateValidationResult::IssuerNotFound;
}

try {
X509CertificateBundle certificate(certificate_chain, EncodingFormat::PEM);
std::vector<X509Wrapper> _certificate_chain = certificate.split();
Expand All @@ -1142,7 +1170,6 @@ CertificateValidationResult EvseSecurity::verify_certificate_internal(const std:

const auto leaf_certificate = _certificate_chain.at(0);
std::vector<X509Handle*> parent_certificates;
fs::path store;

// Retrieve the hierarchy in order to check if the chain contains a root certificate
X509CertificateHierarchy& hierarchy = certificate.get_certficate_hierarchy();
Expand All @@ -1151,30 +1178,19 @@ CertificateValidationResult EvseSecurity::verify_certificate_internal(const std:
for (size_t i = 1; i < _certificate_chain.size(); i++) {
const auto& cert = _certificate_chain[i];
if (hierarchy.is_root(cert)) {
EVLOG_warning << "ignore root certificate: " << cert.get_common_name();
EVLOG_warning << "Ignore root certificate: " << cert.get_common_name();
} else {
parent_certificates.emplace_back(cert.get());
}
}

if (certificate_type == LeafCertificateType::CSMS) {
store = this->ca_bundle_path_map.at(CaCertificateType::CSMS);
} else if (certificate_type == LeafCertificateType::V2G) {
store = this->ca_bundle_path_map.at(CaCertificateType::V2G);
} else if (certificate_type == LeafCertificateType::MF)
store = this->ca_bundle_path_map.at(CaCertificateType::MF);
else if (certificate_type == LeafCertificateType::MO) {
store = this->ca_bundle_path_map.at(CaCertificateType::MO);
} else {
throw std::runtime_error("Could not convert LeafCertificateType to CaCertificateType during verification!");
}

fs::path root_store = this->ca_bundle_path_map.at(ca_certificate_type);
CertificateValidationResult validated{};

if (fs::is_directory(store)) {
if (fs::is_directory(root_store)) {
// In case of a directory load the certificates manually and add them
// to the parent certificates
X509CertificateBundle roots(store, EncodingFormat::PEM);
X509CertificateBundle roots(root_store, EncodingFormat::PEM);

// We use a root chain instead of relying on OpenSSL since that requires to have
// the name of the certificates in the format "hash.0", hash being the subject hash
Expand All @@ -1191,7 +1207,7 @@ CertificateValidationResult EvseSecurity::verify_certificate_internal(const std:
std::nullopt, std::nullopt);
} else {
validated = CryptoSupplier::x509_verify_certificate_chain(leaf_certificate.get(), parent_certificates, true,
std::nullopt, store);
std::nullopt, root_store);
}

return validated;
Expand Down
Loading