Skip to content

Commit

Permalink
Over-write existing OCSP data based on certificate hash
Browse files Browse the repository at this point in the history
Signed-off-by: AssemblyJohn <[email protected]>
  • Loading branch information
AssemblyJohn committed Apr 24, 2024
1 parent 8b69ebb commit 2b358e3
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 27 deletions.
5 changes: 0 additions & 5 deletions include/evse_security/certificate/x509_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@ enum class X509CertificateSource {
STRING
};

const fs::path PEM_EXTENSION = ".pem";
const fs::path DER_EXTENSION = ".der";
const fs::path KEY_EXTENSION = ".key";
const fs::path TPM_KEY_EXTENSION = ".tkey";

/// @brief Convenience wrapper around openssl X509 certificate
class X509Wrapper {
public:
Expand Down
6 changes: 6 additions & 0 deletions include/evse_security/evse_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ struct GetCertificateInfoResult {
std::optional<CertificateInfo> info;
};

const fs::path PEM_EXTENSION = ".pem";
const fs::path DER_EXTENSION = ".der";
const fs::path KEY_EXTENSION = ".key";
const fs::path TPM_KEY_EXTENSION = ".tkey";
const fs::path CERT_HASH_EXTENSION = ".hash";

namespace conversions {
std::string encoding_format_to_string(EncodingFormat e);
std::string ca_certificate_type_to_string(CaCertificateType e);
Expand Down
6 changes: 6 additions & 0 deletions include/evse_security/utils/evse_filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <evse_security/utils/evse_filesystem_types.hpp>

struct CertificateHashData;

namespace evse_security::filesystem_utils {

bool is_subdirectory(const fs::path& base, const fs::path& subdir);
Expand All @@ -25,4 +27,8 @@ bool process_file(const fs::path& file_path, size_t buffer_size,

std::string get_random_file_name(const std::string& extension);

/// @brief Attempts to read a certificate hash from a file. The extension is taken into account
/// @return True if we could read, false otherwise
bool read_hash_from_file(const fs::path& file_path, CertificateHashData& out_hash);

} // namespace evse_security::filesystem_utils
60 changes: 38 additions & 22 deletions lib/evse_security/evse_security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,7 @@ void EvseSecurity::update_ocsp_cache(const CertificateHashData& certificate_hash
X509CertificateBundle ca_bundle(ca_bundle_path, EncodingFormat::PEM);
auto& certificate_hierarchy = ca_bundle.get_certficate_hierarchy();

// TODO: If we already have the hash, over-write, else create a new one
try {
// Find the certificate
X509Wrapper cert = certificate_hierarchy.find_certificate(certificate_hash_data);
Expand All @@ -793,15 +794,37 @@ void EvseSecurity::update_ocsp_cache(const CertificateHashData& certificate_hash
if (cert.get_file().has_value()) {
const auto ocsp_path = cert.get_file().value().parent_path() / "ocsp";

if (!fs::exists(ocsp_path)) {
if (false == fs::exists(ocsp_path)) {
fs::create_directories(ocsp_path);
} else {
// Iterate existing hashes
for (const auto& hash_entry : fs::recursive_directory_iterator(ocsp_path)) {
if(hash_entry.is_regular_file()) {
CertificateHashData read_hash;

if (filesystem_utils::read_hash_from_file(hash_entry.path(), read_hash) &&
read_hash == certificate_hash_data) {
EVLOG_debug << "OCSP certificate hash already found, over-writing!";

// Over-write the hash file and return
fs::path ocsp_path = hash_entry.path();
ocsp_path.replace_extension(CERT_HASH_EXTENSION);

std::ofstream fs(ocsp_path.c_str());
fs << ocsp_response;
fs.close();

return;
}
}
}
}

// Randomize filename, since multiple certificates can be stored in same bundle
const auto name = filesystem_utils::get_random_file_name("_ocsp");

const auto ocsp_file_path = ocsp_path / name / ".der";
const auto hash_file_path = ocsp_path / name / ".hash";
const auto ocsp_file_path = ocsp_path / name / DER_EXTENSION;
const auto hash_file_path = ocsp_path / name / CERT_HASH_EXTENSION;

// Write out OCSP data
std::ofstream fs(ocsp_file_path.c_str());
Expand All @@ -814,6 +837,8 @@ void EvseSecurity::update_ocsp_cache(const CertificateHashData& certificate_hash
hs << certificate_hash_data.issuer_key_hash;
hs << certificate_hash_data.serial_number;
hs.close();

EVLOG_debug << "OCSP certificate hash not found, written at path: " << ocsp_file_path;
} else {
EVLOG_error << "Could not find OCSP cache patch directory!";
}
Expand Down Expand Up @@ -852,29 +877,20 @@ EvseSecurity::retrieve_ocsp_cache_internal(const CertificateHashData& certificat
// Search through the OCSP directory and see if we can find any related certificate hash data
for (const auto& ocsp_entry : fs::directory_iterator(ocsp_path)) {
if (ocsp_entry.is_regular_file()) {
if (ocsp_entry.path().extension() == ".hash") {
std::ifstream hs(ocsp_entry.path().c_str());

CertificateHashData read_hash;
CertificateHashData read_hash;

hs >> read_hash.issuer_name_hash;
hs >> read_hash.issuer_key_hash;
hs >> read_hash.serial_number;
if (filesystem_utils::read_hash_from_file(ocsp_entry.path(), read_hash) &&
(read_hash == certificate_hash_data)) {
fs::path replaced_ext = ocsp_entry.path();
replaced_ext.replace_extension(".der");

hs.close();
std::ifstream in_fs(replaced_ext.c_str());
std::string ocsp_response;

if (read_hash == certificate_hash_data) {
fs::path replaced_ext = ocsp_entry.path();
replaced_ext.replace_extension(".der");
in_fs >> ocsp_response;
in_fs.close();

std::ifstream in_fs(replaced_ext.c_str());
std::string ocsp_response;

in_fs >> ocsp_response;
in_fs.close();

return std::make_optional<std::string>(std::move(ocsp_response));
}
return std::make_optional<std::string>(std::move(ocsp_response));
}
}
}
Expand Down
17 changes: 17 additions & 0 deletions lib/evse_security/utils/evse_filesystem.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Pionix GmbH and Contributors to EVerest
#include <evse_security/utils/evse_filesystem.hpp>
#include <evse_security/evse_types.hpp>

#include <fstream>
#include <iostream>
Expand Down Expand Up @@ -118,4 +119,20 @@ std::string get_random_file_name(const std::string& extension) {
return buff.str();
}

bool read_hash_from_file(const fs::path& file_path, CertificateHashData& out_hash) {
if (file_path.extension() == CERT_HASH_EXTENSION) {
std::ifstream hs(file_path);

hs >> out_hash.issuer_name_hash;
hs >> out_hash.issuer_key_hash;
hs >> out_hash.serial_number;

hs.close();

return true;
}

return false;
}

} // namespace evse_security::filesystem_utils

0 comments on commit 2b358e3

Please sign in to comment.