Skip to content

Commit

Permalink
added implementation for enum to string conversions
Browse files Browse the repository at this point in the history
Signed-off-by: pietfried <[email protected]>
  • Loading branch information
Pietfried committed Sep 29, 2023
1 parent 089843f commit 87c29b6
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 40 deletions.
26 changes: 19 additions & 7 deletions include/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,16 @@ struct CertificateHashData {
std::string serial_number; ///< The string representation of the hexadecimal value of the serial number without the
///< prefix "0x" and without leading zeroes.

bool operator==(const CertificateHashData &Other) {
return hash_algorithm == Other.hash_algorithm
&& issuer_name_hash == Other.issuer_name_hash
&& issuer_key_hash == Other.issuer_key_hash
&& serial_number == Other.serial_number;
bool operator==(const CertificateHashData& Other) {
return hash_algorithm == Other.hash_algorithm && issuer_name_hash == Other.issuer_name_hash &&
issuer_key_hash == Other.issuer_key_hash && serial_number == Other.serial_number;
}
};
struct CertificateHashDataChain {
CertificateType certificate_type; ///< Indicates the type of the certificate for which the hash data is provided
CertificateHashData certificate_hash_data; ///< Contains the hash data of the certificate
std::vector<CertificateHashData> child_certificate_hash_data; ///< Contains the hash data of the child's certificates
CertificateHashData certificate_hash_data; ///< Contains the hash data of the certificate
std::vector<CertificateHashData>
child_certificate_hash_data; ///< Contains the hash data of the child's certificates
};
struct GetInstalledCertificatesResult {
GetInstalledCertificatesStatus status; ///< Indicates the status of the request
Expand All @@ -121,6 +120,19 @@ struct GetKeyPairResult {
std::optional<KeyPair> pair;
};

namespace conversions {
std::string encoding_format_to_string(EncodingFormat e);
std::string ca_certificate_type_to_string(CaCertificateType e);
std::string leaf_certificate_type_to_string(LeafCertificateType e);
std::string certificate_type_to_string(CertificateType e);
std::string hash_algorithm_to_string(HashAlgorithm e);
std::string install_certificate_result_to_string(InstallCertificateResult e);
std::string delete_certificate_result_to_string(DeleteCertificateResult e);
std::string get_installed_certificates_status_to_string(GetInstalledCertificatesStatus e);
std::string get_key_pair_status_to_string(GetKeyPairStatus e);

} // namespace conversions

} // namespace evse_security

#endif // TYPES_HPP
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ target_sources(evse_security
PRIVATE
evse_security.cpp
x509_wrapper.cpp
types.cpp
)

target_include_directories(evse_security
Expand Down
68 changes: 35 additions & 33 deletions lib/evse_security.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,15 +181,14 @@ static CertificateType get_certificate_type(const CaCertificateType ca_certifica

static std::string get_random_file_name(const std::string& extension) {
char path[] = "XXXXXX";
mktemp(path);
mkstemp(path);

return std::string(path) + extension;
}


std::vector<X509Wrapper> get_leaf_certificates(const std::filesystem::path &cert_dir) {
std::vector<X509Wrapper> get_leaf_certificates(const std::filesystem::path& cert_dir) {
std::vector<X509Wrapper> certificates;

for (const auto& entry : std::filesystem::recursive_directory_iterator(cert_dir)) {
if (std::filesystem::is_regular_file(entry)) {
const auto cert_path = entry.path();
Expand All @@ -212,10 +211,10 @@ std::vector<X509Wrapper> get_leaf_certificates(const std::filesystem::path &cert
std::vector<X509Wrapper> get_leaf_certificates(std::vector<std::filesystem::path> paths) {
std::vector<X509Wrapper> certificates;

for(const auto &path : paths) {
for (const auto& path : paths) {
auto certifs = get_leaf_certificates(path);

if(certifs.size() > 0) {
if (certifs.size() > 0) {
certificates.reserve(certificates.size() + certifs.size());
std::move(std::begin(certifs), std::end(certifs), std::back_inserter(certificates));
}
Expand All @@ -224,17 +223,19 @@ std::vector<X509Wrapper> get_leaf_certificates(std::vector<std::filesystem::path
return certificates;
}

std::vector<X509Wrapper> get_ca_certificates(const std::map<CaCertificateType, std::filesystem::path> &ca_bundle_path_map) {
std::vector<X509Wrapper>
get_ca_certificates(const std::map<CaCertificateType, std::filesystem::path>& ca_bundle_path_map) {
// x509 wrapper specific
std::vector<X509Wrapper> ca_certificates;
for (auto const& [certificate_type, ca_bundle_path] : ca_bundle_path_map) {
try {
X509Wrapper ca_bundle(ca_bundle_path, EncodingFormat::PEM);
const auto certificates_of_bundle = ca_bundle.split();

if(certificates_of_bundle.size() > 0) {
if (certificates_of_bundle.size() > 0) {
ca_certificates.reserve(ca_certificates.size() + certificates_of_bundle.size());
std::move(std::begin(certificates_of_bundle), std::end(certificates_of_bundle), std::back_inserter(ca_certificates));
std::move(std::begin(certificates_of_bundle), std::end(certificates_of_bundle),
std::back_inserter(ca_certificates));
}
} catch (const CertificateLoadException& e) {
EVLOG_info << "Could not load ca bundle from file: " << ca_bundle_path;
Expand All @@ -245,17 +246,18 @@ std::vector<X509Wrapper> get_ca_certificates(const std::map<CaCertificateType, s

EvseSecurity::EvseSecurity(const FilePaths& file_paths, const std::optional<std::string>& private_key_password) :
private_key_password(private_key_password) {

std::vector<std::filesystem::path> dirs = { file_paths.directories.csms_leaf_cert_directory,
file_paths.directories.csms_leaf_key_directory,
file_paths.directories.secc_leaf_cert_directory,
file_paths.directories.secc_leaf_key_directory, };

for(const auto &path : dirs) {
std::vector<std::filesystem::path> dirs = {
file_paths.directories.csms_leaf_cert_directory,
file_paths.directories.csms_leaf_key_directory,
file_paths.directories.secc_leaf_cert_directory,
file_paths.directories.secc_leaf_key_directory,
};

for (const auto& path : dirs) {
if (!std::filesystem::exists(path)) {
throw std::runtime_error("Could not find configured leaf directory at: " + path.string());
}
else if(!std::filesystem::is_directory(path)) {
} else if (!std::filesystem::is_directory(path)) {
throw std::runtime_error(path.string() + " is not a directory.");
}
}
Expand All @@ -265,16 +267,16 @@ EvseSecurity::EvseSecurity(const FilePaths& file_paths, const std::optional<std:
this->ca_bundle_path_map[CaCertificateType::MO] = file_paths.mo_ca_bundle;
this->ca_bundle_path_map[CaCertificateType::V2G] = file_paths.v2g_ca_bundle;

for(const auto& pair : this->ca_bundle_path_map) {
if(!std::filesystem::exists(pair.second)) {
throw std::runtime_error("Could not find configured " + std::to_string((int)pair.first) + " bundle file at: " +
file_paths.csms_ca_bundle.string());
}
else if(std::filesystem::is_directory(pair.second)) {
throw std::runtime_error("Provided bundle " + std::to_string((int)pair.first) + " is directory: " +
file_paths.csms_ca_bundle.string());
for (const auto& pair : this->ca_bundle_path_map) {
if (!std::filesystem::exists(pair.second)) {
throw std::runtime_error("Could not find configured " +
conversions::ca_certificate_type_to_string(pair.first) +
" bundle file at: " + pair.second.string());
} else if (std::filesystem::is_directory(pair.second)) {
throw std::runtime_error("Provided bundle " + conversions::ca_certificate_type_to_string(pair.first) +
" is directory: " + pair.second.string());
}
}
}

this->directories = file_paths.directories;
}
Expand Down Expand Up @@ -321,7 +323,8 @@ DeleteCertificateResult EvseSecurity::delete_certificate(const CertificateHashDa
}
}

const auto leaf_certificates = get_leaf_certificates({directories.secc_leaf_cert_directory, directories.csms_leaf_cert_directory});
const auto leaf_certificates =
get_leaf_certificates({directories.secc_leaf_cert_directory, directories.csms_leaf_cert_directory});
for (const auto& leaf_certificate : leaf_certificates) {
if (leaf_certificate.get_issuer_name_hash() == certificate_hash_data.issuer_name_hash and
leaf_certificate.get_issuer_key_hash() == certificate_hash_data.issuer_key_hash and
Expand Down Expand Up @@ -372,7 +375,7 @@ InstallCertificateResult EvseSecurity::update_leaf_certificate(const std::string
return result;
}

const auto &leaf_certificate = _certificate_chain[0];
const auto& leaf_certificate = _certificate_chain[0];

// check if a private key belongs to the provided certificate
try {
Expand Down Expand Up @@ -401,8 +404,7 @@ InstallCertificateResult EvseSecurity::update_leaf_certificate(const std::string
return InstallCertificateResult::Accepted;
}

GetInstalledCertificatesResult
EvseSecurity::get_installed_certificate(CertificateType certificate_type) {
GetInstalledCertificatesResult EvseSecurity::get_installed_certificate(CertificateType certificate_type) {
return get_installed_certificates({certificate_type});
}

Expand Down Expand Up @@ -667,8 +669,8 @@ int EvseSecurity::get_leaf_expiry_days_count(LeafCertificateType certificate_typ
}

InstallCertificateResult EvseSecurity::verify_certificate(const std::string& certificate_chain,
LeafCertificateType certificate_type) {
try {
LeafCertificateType certificate_type) {
try {
X509Wrapper certificate(certificate_chain, EncodingFormat::PEM);
std::vector<X509Wrapper> _certificate_chain = certificate.split();
if (_certificate_chain.empty()) {
Expand Down
147 changes: 147 additions & 0 deletions lib/types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

#include <types.hpp>

namespace evse_security {

namespace conversions {

std::string encoding_format_to_string(EncodingFormat e) {
switch (e) {
case EncodingFormat::DER:
return "DER";
case EncodingFormat::PEM:
return "PEM";
default:
throw std::out_of_range("Could not convert EncodingFormat to string");
}
};

std::string ca_certificate_type_to_string(CaCertificateType e) {
switch (e) {
case CaCertificateType::V2G:
return "V2G";
case CaCertificateType::MO:
return "MO";
case CaCertificateType::CSMS:
return "CSMS";
case CaCertificateType::MF:
return "MF";
default:
throw std::out_of_range("Could not convert CaCertificateType to string");
}
};

std::string leaf_certificate_type_to_string(LeafCertificateType e) {
switch (e) {
case LeafCertificateType::CSMS:
return "CSMS";
case LeafCertificateType::V2G:
return "V2G";
case LeafCertificateType::MF:
return "MF";
default:
throw std::out_of_range("Could not convert LeafCertificateType to string");
}
};

std::string certificate_type_to_string(CertificateType e) {
switch (e) {
case CertificateType::V2GRootCertificate:
return "V2GRootCertificate";
case CertificateType::MORootCertificate:
return "MORootCertificate";
case CertificateType::CSMSRootCertificate:
return "CSMSRootCertificate";
case CertificateType::V2GCertificateChain:
return "V2GCertificateChain";
case CertificateType::MFRootCertificate:
return "MFRootCertificate";
default:
throw std::out_of_range("Could not convert CertificateType to string");
}
};

std::string hash_algorithm_to_string(HashAlgorithm e) {
switch (e) {
case HashAlgorithm::SHA256:
return "SHA256";
case HashAlgorithm::SHA384:
return "SHA384";
case HashAlgorithm::SHA512:
return "SHA512";
default:
throw std::out_of_range("Could not convert HashAlgorithm to string");
}
};

std::string install_certificate_result_to_string(InstallCertificateResult e) {
switch (e) {
case InstallCertificateResult::InvalidSignature:
return "InvalidSignature";
case InstallCertificateResult::InvalidCertificateChain:
return "InvalidCertificateChain";
case InstallCertificateResult::InvalidFormat:
return "InvalidFormat";
case InstallCertificateResult::InvalidCommonName:
return "InvalidCommonName";
case InstallCertificateResult::NoRootCertificateInstalled:
return "NoRootCertificateInstalled";
case InstallCertificateResult::Expired:
return "Expired";
case InstallCertificateResult::CertificateStoreMaxLengthExceeded:
return "CertificateStoreMaxLengthExceeded";
case InstallCertificateResult::WriteError:
return "WriteError";
case InstallCertificateResult::Accepted:
return "Accepted";
default:
throw std::out_of_range("Could not convert InstallCertificateResult to string");
}
};

std::string delete_certificate_result_to_string(DeleteCertificateResult e) {
switch (e) {
case DeleteCertificateResult::Accepted:
return "Accepted";
case DeleteCertificateResult::Failed:
return "Failed";
case DeleteCertificateResult::NotFound:
return "NotFound";
default:
throw std::out_of_range("Could not convert DeleteCertificateResult to string");
}
};

std::string get_installed_certificates_status_to_string(GetInstalledCertificatesStatus e) {
switch (e) {
case GetInstalledCertificatesStatus::Accepted:
return "Accepted";
case GetInstalledCertificatesStatus::NotFound:
return "NotFound";
default:
throw std::out_of_range("Could not convert GetInstalledCertificatesStatus to string");
}
};

std::string get_key_pair_status_to_string(GetKeyPairStatus e) {
switch (e) {
case GetKeyPairStatus::Accepted:
return "Accepted";
case GetKeyPairStatus::Rejected:
return "Rejected";
case GetKeyPairStatus::NotFound:
return "NotFound";
case GetKeyPairStatus::NotFoundValid:
return "NotFoundValid";
case GetKeyPairStatus::PrivateKeyNotFound:
return "PrivateKeyNotFound";
default:
throw std::out_of_range("Could not convert GetKeyPairStatus to string");
}
};

}

} // namespace evse_security

0 comments on commit 87c29b6

Please sign in to comment.