- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
291 lines
12 KiB
C++
291 lines
12 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// Copyright Pionix GmbH and Contributors to EVerest
|
|
|
|
#include "evse_securityImpl.hpp"
|
|
#include <everest/conversions/evse_security/conversions.hpp>
|
|
|
|
namespace module {
|
|
namespace main {
|
|
|
|
void evse_securityImpl::init() {
|
|
|
|
const auto certs_path = this->mod->info.paths.etc / "certs";
|
|
evse_security::FilePaths file_paths = {certs_path / this->mod->config.csms_ca_bundle,
|
|
certs_path / this->mod->config.mf_ca_bundle,
|
|
certs_path / this->mod->config.mo_ca_bundle,
|
|
certs_path / this->mod->config.v2g_ca_bundle,
|
|
certs_path / this->mod->config.csms_leaf_cert_directory,
|
|
certs_path / this->mod->config.csms_leaf_key_directory,
|
|
certs_path / this->mod->config.secc_leaf_cert_directory,
|
|
certs_path / this->mod->config.secc_leaf_key_directory};
|
|
|
|
std::optional<std::string> private_key_password = std::nullopt;
|
|
if (!this->mod->config.private_key_password.empty()) {
|
|
private_key_password = this->mod->config.private_key_password;
|
|
}
|
|
|
|
this->evse_security = std::make_unique<evse_security::EvseSecurity>(file_paths, private_key_password);
|
|
}
|
|
|
|
void evse_securityImpl::ready() {
|
|
}
|
|
|
|
types::evse_security::InstallCertificateResult
|
|
evse_securityImpl::handle_install_ca_certificate(std::string& certificate,
|
|
types::evse_security::CaCertificateType& certificate_type) {
|
|
try {
|
|
const auto response = conversions::to_everest(
|
|
this->evse_security->install_ca_certificate(certificate, conversions::from_everest(certificate_type)));
|
|
if (response == types::evse_security::InstallCertificateResult::Accepted) {
|
|
types::evse_security::CertificateStoreUpdate update;
|
|
update.operation = types::evse_security::CertificateStoreUpdateOperation::Installed;
|
|
update.ca_certificate_type = certificate_type;
|
|
this->publish_certificate_store_update(update);
|
|
}
|
|
return response;
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return types::evse_security::InstallCertificateResult::WriteError;
|
|
}
|
|
}
|
|
|
|
types::evse_security::DeleteCertificateResult
|
|
evse_securityImpl::handle_delete_certificate(types::evse_security::CertificateHashData& certificate_hash_data) {
|
|
try {
|
|
const auto response = this->evse_security->delete_certificate(conversions::from_everest(certificate_hash_data));
|
|
const auto result = conversions::to_everest(response.result);
|
|
|
|
if (result == types::evse_security::DeleteCertificateResult::Accepted) {
|
|
types::evse_security::CertificateStoreUpdate update;
|
|
|
|
update.operation = types::evse_security::CertificateStoreUpdateOperation::Deleted;
|
|
|
|
if (response.ca_certificate_type.has_value()) {
|
|
update.ca_certificate_type = conversions::to_everest(response.ca_certificate_type.value());
|
|
}
|
|
if (response.leaf_certificate_type.has_value()) {
|
|
update.leaf_certificate_type = conversions::to_everest(response.leaf_certificate_type.value());
|
|
}
|
|
|
|
this->publish_certificate_store_update(update);
|
|
}
|
|
|
|
return result;
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return types::evse_security::DeleteCertificateResult::Failed;
|
|
}
|
|
}
|
|
|
|
types::evse_security::InstallCertificateResult
|
|
evse_securityImpl::handle_update_leaf_certificate(std::string& certificate_chain,
|
|
types::evse_security::LeafCertificateType& certificate_type) {
|
|
try {
|
|
const auto response = conversions::to_everest(this->evse_security->update_leaf_certificate(
|
|
certificate_chain, conversions::from_everest(certificate_type)));
|
|
if (response == types::evse_security::InstallCertificateResult::Accepted) {
|
|
types::evse_security::CertificateStoreUpdate update;
|
|
update.operation = types::evse_security::CertificateStoreUpdateOperation::Installed;
|
|
update.leaf_certificate_type = certificate_type;
|
|
this->publish_certificate_store_update(update);
|
|
}
|
|
return response;
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return types::evse_security::InstallCertificateResult::WriteError;
|
|
}
|
|
}
|
|
|
|
types::evse_security::CertificateValidationResult evse_securityImpl::handle_verify_certificate(
|
|
std::string& certificate_chain, std::vector<types::evse_security::LeafCertificateType>& certificate_types) {
|
|
|
|
std::vector<evse_security::LeafCertificateType> _certificate_types;
|
|
|
|
for (const auto& certificate_type : certificate_types) {
|
|
try {
|
|
_certificate_types.push_back(conversions::from_everest(certificate_type));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
}
|
|
}
|
|
|
|
try {
|
|
return conversions::to_everest(this->evse_security->verify_certificate(certificate_chain, _certificate_types));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return types::evse_security::CertificateValidationResult::Unknown;
|
|
}
|
|
}
|
|
|
|
types::evse_security::GetInstalledCertificatesResult evse_securityImpl::handle_get_installed_certificates(
|
|
std::vector<types::evse_security::CertificateType>& certificate_types) {
|
|
std::vector<evse_security::CertificateType> _certificate_types;
|
|
|
|
for (const auto& certificate_type : certificate_types) {
|
|
try {
|
|
_certificate_types.push_back(conversions::from_everest(certificate_type));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
}
|
|
}
|
|
|
|
try {
|
|
return conversions::to_everest(this->evse_security->get_installed_certificates(_certificate_types));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return {types::evse_security::GetInstalledCertificatesStatus::NotFound, {}};
|
|
}
|
|
}
|
|
|
|
types::evse_security::OCSPRequestDataList evse_securityImpl::handle_get_v2g_ocsp_request_data() {
|
|
try {
|
|
return conversions::to_everest(this->evse_security->get_v2g_ocsp_request_data());
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return {};
|
|
}
|
|
}
|
|
|
|
types::evse_security::OCSPRequestDataList
|
|
evse_securityImpl::handle_get_mo_ocsp_request_data(std::string& certificate_chain) {
|
|
try {
|
|
return conversions::to_everest(this->evse_security->get_mo_ocsp_request_data(certificate_chain));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return {};
|
|
}
|
|
}
|
|
|
|
void evse_securityImpl::handle_update_ocsp_cache(types::evse_security::CertificateHashData& certificate_hash_data,
|
|
std::string& ocsp_response) {
|
|
try {
|
|
this->evse_security->update_ocsp_cache(conversions::from_everest(certificate_hash_data), ocsp_response);
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
}
|
|
}
|
|
|
|
bool evse_securityImpl::handle_is_ca_certificate_installed(types::evse_security::CaCertificateType& certificate_type) {
|
|
try {
|
|
return this->evse_security->is_ca_certificate_installed(conversions::from_everest(certificate_type));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
types::evse_security::GetCertificateSignRequestResult evse_securityImpl::handle_generate_certificate_signing_request(
|
|
types::evse_security::LeafCertificateType& certificate_type, std::string& country, std::string& organization,
|
|
std::string& common, bool& use_tpm) {
|
|
types::evse_security::GetCertificateSignRequestResult response;
|
|
|
|
try {
|
|
auto csr_response = this->evse_security->generate_certificate_signing_request(
|
|
conversions::from_everest(certificate_type), country, organization, common, use_tpm);
|
|
|
|
response.status = conversions::to_everest(csr_response.status);
|
|
|
|
if (csr_response.status == evse_security::GetCertificateSignRequestStatus::Accepted &&
|
|
csr_response.csr.has_value()) {
|
|
response.csr = csr_response.csr;
|
|
}
|
|
|
|
return response;
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
response.status = types::evse_security::GetCertificateSignRequestStatus::GenerationError;
|
|
return response;
|
|
}
|
|
}
|
|
|
|
types::evse_security::GetCertificateInfoResult
|
|
evse_securityImpl::handle_get_leaf_certificate_info(types::evse_security::LeafCertificateType& certificate_type,
|
|
types::evse_security::EncodingFormat& encoding,
|
|
bool& include_ocsp) {
|
|
types::evse_security::GetCertificateInfoResult response;
|
|
|
|
try {
|
|
const auto leaf_info = this->evse_security->get_leaf_certificate_info(
|
|
conversions::from_everest(certificate_type), conversions::from_everest(encoding), include_ocsp);
|
|
|
|
response.status = conversions::to_everest(leaf_info.status);
|
|
|
|
if (leaf_info.status == evse_security::GetCertificateInfoStatus::Accepted && leaf_info.info.has_value()) {
|
|
response.info = conversions::to_everest(leaf_info.info.value());
|
|
}
|
|
|
|
return response;
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
response.status = types::evse_security::GetCertificateInfoStatus::Rejected;
|
|
return response;
|
|
}
|
|
}
|
|
|
|
types::evse_security::GetCertificateFullInfoResult
|
|
evse_securityImpl::handle_get_all_valid_certificates_info(types::evse_security::LeafCertificateType& certificate_type,
|
|
types::evse_security::EncodingFormat& encoding,
|
|
bool& include_ocsp) {
|
|
types::evse_security::GetCertificateFullInfoResult response;
|
|
|
|
try {
|
|
const auto full_leaf_info = this->evse_security->get_all_valid_certificates_info(
|
|
conversions::from_everest(certificate_type), conversions::from_everest(encoding), include_ocsp);
|
|
|
|
response.status = conversions::to_everest(full_leaf_info.status);
|
|
|
|
if (full_leaf_info.status == evse_security::GetCertificateInfoStatus::Accepted) {
|
|
for (const auto& info : full_leaf_info.info) {
|
|
response.info.push_back(conversions::to_everest(info));
|
|
}
|
|
}
|
|
|
|
return response;
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
response.status = types::evse_security::GetCertificateInfoStatus::Rejected;
|
|
return response;
|
|
}
|
|
}
|
|
|
|
std::string evse_securityImpl::handle_get_verify_file(types::evse_security::CaCertificateType& certificate_type) {
|
|
try {
|
|
return this->evse_security->get_verify_file(conversions::from_everest(certificate_type));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return {};
|
|
}
|
|
}
|
|
|
|
std::string evse_securityImpl::handle_get_verify_location(types::evse_security::CaCertificateType& certificate_type) {
|
|
try {
|
|
return this->evse_security->get_verify_location(conversions::from_everest(certificate_type));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return {};
|
|
}
|
|
}
|
|
|
|
int evse_securityImpl::handle_get_leaf_expiry_days_count(types::evse_security::LeafCertificateType& certificate_type) {
|
|
try {
|
|
return this->evse_security->get_leaf_expiry_days_count(conversions::from_everest(certificate_type));
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool evse_securityImpl::handle_verify_file_signature(std::string& file_path, std::string& signing_certificate,
|
|
std::string& signature) {
|
|
try {
|
|
return evse_security::EvseSecurity::verify_file_signature(std::filesystem::path(file_path), signing_certificate,
|
|
signature);
|
|
} catch (const std::out_of_range& e) {
|
|
EVLOG_warning << e.what();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
} // namespace main
|
|
} // namespace module
|