Skip to content

Commit

Permalink
Added functions for ocsp request with v2g and mo
Browse files Browse the repository at this point in the history
Signed-off-by: AssemblyJohn <[email protected]>
  • Loading branch information
AssemblyJohn committed Mar 20, 2024
1 parent c2b49ce commit 651ad96
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 39 deletions.
2 changes: 1 addition & 1 deletion include/evse_security/evse_security.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ class EvseSecurity {
/// @param certificate_chain PEM formatted certificate or certificate chain
/// @param certificate_type type of the leaf certificate
/// @return contains OCSP request data
OCSPRequestDataList get_ocsp_request_data(const std::string& certificate_chain);
OCSPRequestDataList get_mo_ocsp_request_data(const std::string& certificate_chain);

/// @brief Updates the OCSP cache for the given \p certificate_hash_data with the given \p ocsp_response
/// @param certificate_hash_data identifies the certificate for which the \p ocsp_response is specified
Expand Down
98 changes: 60 additions & 38 deletions lib/evse_security/evse_security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,8 @@ static std::set<fs::path> get_certificate_path_of_key(const fs::path& key, const
throw NoCertificateValidException(error);
}

X509CertificateBundle get_leaf_certificates(const fs::path& cert_dir) {
return X509CertificateBundle(cert_dir, EncodingFormat::PEM);
}
// Declared here to avoid requirement of X509Wrapper include in header
static OCSPRequestDataList get_ocsp_request_data_internal(fs::path& root_path, std::vector<X509Wrapper>& leaf_chain);

std::mutex EvseSecurity::security_mutex;

Expand Down Expand Up @@ -624,63 +623,86 @@ int EvseSecurity::get_count_of_installed_certificates(const std::vector<Certific
OCSPRequestDataList EvseSecurity::get_v2g_ocsp_request_data() {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

OCSPRequestDataList response;
std::vector<OCSPRequestData> ocsp_request_data_list;

try {
const auto secc_key_pair = this->get_key_pair_internal(LeafCertificateType::V2G, EncodingFormat::PEM);

if (secc_key_pair.status != GetKeyPairStatus::Accepted or !secc_key_pair.pair.has_value()) {
return response;
EVLOG_error << "Could not get key pair, for v2g ocsp request!";
return OCSPRequestDataList();
}

X509CertificateBundle leaf_bundle(secc_key_pair.pair.value().certificate, EncodingFormat::PEM);
std::vector<X509Wrapper> chain =
std::move(X509CertificateBundle(secc_key_pair.pair.value().certificate, EncodingFormat::PEM).split());
return get_ocsp_request_data_internal(this->ca_bundle_path_map.at(CaCertificateType::V2G), chain);
} catch (const CertificateLoadException& e) {
EVLOG_error << "Could not get v2g ocsp cache, certificate load failure: " << e.what();
}

// Build hierarchy for the bundle
auto& hierarchy = leaf_bundle.get_certficate_hierarchy();
return OCSPRequestDataList();
}

// Iterate cache, get hashes
hierarchy.for_each([&](const X509Node& node) {
std::string responder_url = node.certificate.get_responder_url();
auto certificate_hash_data = node.hash;
if (!responder_url.empty() and certificate_hash_data.is_valid()) {
OCSPRequestData ocsp_request_data = {certificate_hash_data, responder_url};
ocsp_request_data_list.push_back(ocsp_request_data);
}
OCSPRequestDataList EvseSecurity::get_mo_ocsp_request_data(const std::string& certificate_chain) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

return true;
});
try {
std::vector<X509Wrapper> chain =
std::move(X509CertificateBundle(certificate_chain, EncodingFormat::PEM).split());

response.ocsp_request_data_list = ocsp_request_data_list;
// Find the MO root
return get_ocsp_request_data_internal(this->ca_bundle_path_map.at(CaCertificateType::MO), chain);
} catch (const CertificateLoadException& e) {
EVLOG_error << "Could not get ocsp cache, certificate load failure: " << e.what();
EVLOG_error << "Could not get mo ocsp cache, certificate load failure: " << e.what();
}

return response;
return OCSPRequestDataList();
}

OCSPRequestDataList EvseSecurity::get_ocsp_request_data(const std::string& certificate_chain) {
std::lock_guard<std::mutex> guard(EvseSecurity::security_mutex);

OCSPRequestDataList get_ocsp_request_data_internal(fs::path& root_path, std::vector<X509Wrapper>& leaf_chain) {
OCSPRequestDataList response;
std::vector<OCSPRequestData> ocsp_request_data_list;

try {
X509CertificateBundle leaf_bundle(certificate_chain, EncodingFormat::PEM);
X509CertificateHierarchy& hierarchy = leaf_bundle.get_certficate_hierarchy();

hierarchy.for_each([&](const X509Node& node) {
std::string responder_url = node.certificate.get_responder_url();
auto certificate_hash_data = node.hash;
if (!responder_url.empty() and certificate_hash_data.is_valid()) {
OCSPRequestData ocsp_request_data = {certificate_hash_data, responder_url};
ocsp_request_data_list.push_back(ocsp_request_data);
std::vector<X509Wrapper> full_hierarchy = X509CertificateBundle(root_path, EncodingFormat::PEM).split();
std::move(std::begin(leaf_chain), std::end(leaf_chain), std::back_inserter(full_hierarchy));

// Build the full hierarchy
auto hierarchy = X509CertificateHierarchy::build_hierarchy(full_hierarchy);

// Search for the first valid root, and collect all the chain
for (auto& root : hierarchy.get_hierarchy()) {
if (root.certificate.is_selfsigned() && root.certificate.is_valid()) {
// Collect the chain
std::vector<X509Wrapper> descendants = hierarchy.collect_descendants(root.certificate);
bool has_proper_descendants = (descendants.size() > 0);

for (auto& certificate : descendants) {
std::string responder_url = certificate.get_responder_url();

if (!responder_url.empty()) {
try {
auto certificate_hash_data = hierarchy.get_certificate_hash(certificate);
OCSPRequestData ocsp_request_data = {certificate_hash_data, responder_url};
ocsp_request_data_list.push_back(ocsp_request_data);
} catch (const NoCertificateFound& e) {
EVLOG_error << "Could not find hash for certificate: " << certificate.get_common_name()
<< " with error: " << e.what();
}
}
}

// If we have collected the descendants we can break
// else we can continue iterating for a proper root
if (has_proper_descendants) {
break;
}
}
}

return true;
});
response.ocsp_request_data_list = ocsp_request_data_list;
} catch (const CertificateLoadException& e) {
EVLOG_error << "Could not get ocsp cache, certificate load failure: " << e.what();
} catch (const NoCertificateFound& e) {
EVLOG_error << "Could not find proper root: " << e.what();
}

return response;
Expand Down Expand Up @@ -843,7 +865,7 @@ GetKeyPairResult EvseSecurity::get_key_pair_internal(LeafCertificateType certifi

// choose appropriate cert (valid_from / valid_to)
try {
auto leaf_certificates = std::move(get_leaf_certificates(cert_dir));
auto leaf_certificates = X509CertificateBundle(cert_dir, EncodingFormat::PEM);

if (leaf_certificates.empty()) {
EVLOG_warning << "Could not find any key pair";
Expand Down

0 comments on commit 651ad96

Please sign in to comment.