From ca2fbbb8b6dd8256ac1b720a03f702627da70820 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Tue, 13 Feb 2024 11:49:35 +0100 Subject: [PATCH 01/12] Add authorization using contract certificates according to OCPP use case C07 requirements Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 55 ++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index abd54d660..0b3852767 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -563,6 +563,61 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: return response; } + // C07: Authorization using contract certifates + if (id_token.type == IdTokenEnum::eMAID) { + // Temporary variable that is set to true to avoid immediate response to allow the local auth list or auth cache to be tried + bool tryLocalAuthListOrCache = false; + + // First try to validate the contract certificate locally + if (certificate.has_value()) { + InstallCertificateResult localVerifyResult = this->evse_security->verify_certificate(certificate.value().get(), ocpp::CertificateSigningUseEnum::V2GCertificate); + EVLOG_info << "Local contract validation result: " << localVerifyResult; + + bool CentralContractValidationAllowed = this->device_model->get_optional_value(ControllerComponentVariables::CentralContractValidationAllowed).value_or(true); + bool ContractValidationOffline = this->device_model->get_optional_value(ControllerComponentVariables::ContractValidationOffline).value_or(true); + // C07.FR.01: When CS is online, it shall send an AuthorizeRequest + // C07.FR.02: The AuthorizeRequest shall at least contain the OCSP data + if (this->websocket->is_connected()) { + // C07.FR.06: Pass contract validation to CSMS when no contract root is found + if (CentralContractValidationAllowed and localVerifyResult == InstallCertificateResult::NoRootCertificateInstalled) { + EVLOG_info << "Online: No local contract root found. Pass contract validation to CSMS"; + response = this->authorize_req(id_token, certificate, ocsp_request_data); + } else { + EVLOG_info << "Online: Pass OCSP data to CSMS"; + response = this->authorize_req(id_token, std::nullopt, ocsp_request_data); + // TODO: local validation results are ignored, response is based only on OCSP data, is that acceptable? + } + } else { // Offline + // C07.FR.08: CS shall try to validate the contract locally + if (ContractValidationOffline) { + EVLOG_info << "Offline: contract " << localVerifyResult; + switch (localVerifyResult) { + // C07.FR.09: CS shall lookup the eMAID in Local Auth List or Auth Cache when local validation succeeded + case InstallCertificateResult::Accepted: + tryLocalAuthListOrCache = true; + break; + case InstallCertificateResult::Expired: + response.idTokenInfo.status = AuthorizationStatusEnum::Expired; + break; + default: + response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; + break; + } + } else { + // C07.FR.07: CS shall not allow charging + response.idTokenInfo.status = AuthorizationStatusEnum::NotAtThisTime; + } + } + } else { + EVLOG_warning << "Can not validate eMAID without certificate chain"; + response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; + } + // For eMAID, we will respond here, unless the local auth list or auth cache is tried + if (!tryLocalAuthListOrCache) { + return response; + } + } + if (this->device_model->get_optional_value(ControllerComponentVariables::LocalAuthListCtrlrEnabled) .value_or(false)) { const auto id_token_info = this->database_handler->get_local_authorization_list_entry(id_token); From 27afed259ef95a4fef4def7be7b5f37c8440f1f2 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Tue, 13 Feb 2024 15:21:58 +0100 Subject: [PATCH 02/12] Check also LocalAuthorizeOffline to comply with requirement C07.FR.09 Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 0b3852767..253b84f0f 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -563,7 +563,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: return response; } - // C07: Authorization using contract certifates + // C07: Authorization using contract certificates if (id_token.type == IdTokenEnum::eMAID) { // Temporary variable that is set to true to avoid immediate response to allow the local auth list or auth cache to be tried bool tryLocalAuthListOrCache = false; @@ -575,6 +575,8 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: bool CentralContractValidationAllowed = this->device_model->get_optional_value(ControllerComponentVariables::CentralContractValidationAllowed).value_or(true); bool ContractValidationOffline = this->device_model->get_optional_value(ControllerComponentVariables::ContractValidationOffline).value_or(true); + bool LocalAuthorizeOffline = this->device_model->get_optional_value(ControllerComponentVariables::LocalAuthorizeOffline).value_or(true); + // C07.FR.01: When CS is online, it shall send an AuthorizeRequest // C07.FR.02: The AuthorizeRequest shall at least contain the OCSP data if (this->websocket->is_connected()) { @@ -594,7 +596,14 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: switch (localVerifyResult) { // C07.FR.09: CS shall lookup the eMAID in Local Auth List or Auth Cache when local validation succeeded case InstallCertificateResult::Accepted: - tryLocalAuthListOrCache = true; + // In C07.FR.09 LocalAuthorizeOffline is mentioned, this seems to be a generic config item that applies + // to Local Auth List and Auth Cache, but since there are no requirements about it, lets check it here + if (LocalAuthorizeOffline) { + tryLocalAuthListOrCache = true; + } else { + // No requirement states what to do when ContractValidationOffline is true and LocalAuthorizeOffline is false + response.idTokenInfo.status = AuthorizationStatusEnum::NotAtThisTime; + } break; case InstallCertificateResult::Expired: response.idTokenInfo.status = AuthorizationStatusEnum::Expired; From 8834f2acc681f99ffbdf9f13af904349186890f1 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Mon, 26 Feb 2024 14:24:52 +0100 Subject: [PATCH 03/12] Use new interface of libevse-security verify_certificate Signed-off-by: Menno de Graaf --- include/ocpp/common/evse_security.hpp | 4 +- include/ocpp/common/evse_security_impl.hpp | 5 +- include/ocpp/common/types.hpp | 25 ++++++++++ lib/ocpp/common/evse_security_impl.cpp | 26 +++++++++- lib/ocpp/common/types.cpp | 55 ++++++++++++++++++++++ lib/ocpp/v16/charge_point_impl.cpp | 4 +- lib/ocpp/v201/charge_point.cpp | 17 +++++-- 7 files changed, 123 insertions(+), 13 deletions(-) diff --git a/include/ocpp/common/evse_security.hpp b/include/ocpp/common/evse_security.hpp index b7690b5ef..c093c4b3c 100644 --- a/include/ocpp/common/evse_security.hpp +++ b/include/ocpp/common/evse_security.hpp @@ -46,8 +46,8 @@ class EvseSecurity { /// \param certificate_chain PEM formatted certificate or certificate chain /// \param certificate_type type of the leaf certificate /// \return result of the operation - virtual InstallCertificateResult verify_certificate(const std::string& certificate_chain, - const CertificateSigningUseEnum& certificate_type) = 0; + virtual CertificateValidationResult verify_certificate(const std::string& certificate_chain, + const CaCertificateType& certificate_type) = 0; /// \brief Retrieves all certificates installed on the filesystem applying the \p certificate_types filter. This /// function respects the requirements of OCPP specified for the CSMS initiated message diff --git a/include/ocpp/common/evse_security_impl.hpp b/include/ocpp/common/evse_security_impl.hpp index ddc989486..275a095f7 100644 --- a/include/ocpp/common/evse_security_impl.hpp +++ b/include/ocpp/common/evse_security_impl.hpp @@ -39,8 +39,8 @@ class EvseSecurityImpl : public EvseSecurity { DeleteCertificateResult delete_certificate(const CertificateHashDataType& certificate_hash_data) override; InstallCertificateResult update_leaf_certificate(const std::string& certificate_chain, const CertificateSigningUseEnum& certificate_type) override; - InstallCertificateResult verify_certificate(const std::string& certificate_chain, - const CertificateSigningUseEnum& certificate_type) override; + CertificateValidationResult verify_certificate(const std::string& certificate_chain, + const CaCertificateType& certificate_type) override; std::vector get_installed_certificates(const std::vector& certificate_types) override; std::vector get_ocsp_request_data() override; @@ -62,6 +62,7 @@ CaCertificateType to_ocpp(evse_security::CaCertificateType other); CertificateSigningUseEnum to_ocpp(evse_security::LeafCertificateType other); CertificateType to_ocpp(evse_security::CertificateType other); HashAlgorithmEnumType to_ocpp(evse_security::HashAlgorithm other); +CertificateValidationResult to_ocpp(evse_security::CertificateValidationError other); InstallCertificateResult to_ocpp(evse_security::InstallCertificateResult other); DeleteCertificateResult to_ocpp(evse_security::DeleteCertificateResult other); diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index 137381b2d..eaea1d21c 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -335,6 +335,31 @@ CaCertificateType string_to_ca_certificate_type(const std::string& s); /// \returns an output stream with the CaCertificateType written to std::ostream& operator<<(std::ostream& os, const CaCertificateType& ca_certificate_type); +enum class CertificateValidationResult { + Accepted, + Expired, + InvalidSignature, + IssuerNotFound, + InvalidLeafSignature, + InvalidChain, + Unknown, +}; + +namespace conversions { +/// \brief Converts the given InstallCertificateResult \p e to human readable string +/// \returns a string representation of the InstallCertificateResult +std::string certificate_validation_result_to_string(CertificateValidationResult e); + +/// \brief Converts the given std::string \p s to InstallCertificateResult +/// \returns a InstallCertificateResult from a string representation +CertificateValidationResult string_to_certificate_validation_result(const std::string& s); +} // namespace conversions + +/// \brief Writes the string representation of the given InstallCertificateResult \p +/// install_certificate_result to the given output stream \p os \returns an output stream with the +/// InstallCertificateResult written to +std::ostream& operator<<(std::ostream& os, const CertificateValidationResult& certificate_validation_result); + enum class InstallCertificateResult { InvalidSignature, InvalidCertificateChain, diff --git a/lib/ocpp/common/evse_security_impl.cpp b/lib/ocpp/common/evse_security_impl.cpp index cfd7c6dd5..8d27db4df 100644 --- a/lib/ocpp/common/evse_security_impl.cpp +++ b/lib/ocpp/common/evse_security_impl.cpp @@ -40,8 +40,8 @@ InstallCertificateResult EvseSecurityImpl::update_leaf_certificate(const std::st this->evse_security->update_leaf_certificate(certificate_chain, conversions::from_ocpp(certificate_type))); } -InstallCertificateResult EvseSecurityImpl::verify_certificate(const std::string& certificate_chain, - const CertificateSigningUseEnum& certificate_type) { +CertificateValidationResult EvseSecurityImpl::verify_certificate(const std::string& certificate_chain, + const CaCertificateType& certificate_type) { return conversions::to_ocpp( this->evse_security->verify_certificate(certificate_chain, conversions::from_ocpp(certificate_type))); } @@ -174,6 +174,28 @@ HashAlgorithmEnumType to_ocpp(evse_security::HashAlgorithm other) { } } +CertificateValidationResult to_ocpp(evse_security::CertificateValidationError other) { + switch (other) { + case evse_security::CertificateValidationError::NoError: + return CertificateValidationResult::Accepted; + case evse_security::CertificateValidationError::Expired: + return CertificateValidationResult::Expired; + case evse_security::CertificateValidationError::InvalidSignature: + return CertificateValidationResult::InvalidSignature; + case evse_security::CertificateValidationError::IssuerNotFound: + return CertificateValidationResult::IssuerNotFound; + case evse_security::CertificateValidationError::InvalidLeafSignature: + return CertificateValidationResult::InvalidLeafSignature; + case evse_security::CertificateValidationError::InvalidChain: + return CertificateValidationResult::InvalidChain; + case evse_security::CertificateValidationError::Unknown: + return CertificateValidationResult::Unknown; + default: + throw std::runtime_error( + "Could not convert evse_security::CertificateValidationError to CertificateValidationResult"); + } +} + InstallCertificateResult to_ocpp(evse_security::InstallCertificateResult other) { switch (other) { case evse_security::InstallCertificateResult::InvalidSignature: diff --git a/lib/ocpp/common/types.cpp b/lib/ocpp/common/types.cpp index 82d0b79c9..cce8d2925 100644 --- a/lib/ocpp/common/types.cpp +++ b/lib/ocpp/common/types.cpp @@ -602,6 +602,61 @@ std::ostream& operator<<(std::ostream& os, const CaCertificateType& ca_certifica os << conversions::ca_certificate_type_to_string(ca_certificate_type); return os; } + +namespace conversions { +std::string certificate_validation_result_to_string(CertificateValidationResult e) { + switch (e) { + case CertificateValidationResult::Accepted: + return "Accepted"; + case CertificateValidationResult::Expired: + return "Expired"; + case CertificateValidationResult::InvalidSignature: + return "InvalidSignature"; + case CertificateValidationResult::IssuerNotFound: + return "IssuerNotFound"; + case CertificateValidationResult::InvalidLeafSignature: + return "InvalidLeafSignature"; + case CertificateValidationResult::InvalidChain: + return "InvalidChain"; + case CertificateValidationResult::Unknown: + return "Unknown"; + } + + throw std::out_of_range("No known string conversion for provided enum of type CertificateValidationResult"); +} + +CertificateValidationResult string_to_certificate_validation_result(const std::string& s) { + if (s == "Accepted") { + return CertificateValidationResult::Accepted; + } + if (s == "Expired") { + return CertificateValidationResult::Expired; + } + if (s == "InvalidSignature") { + return CertificateValidationResult::InvalidSignature; + } + if (s == "IssuerNotFound") { + return CertificateValidationResult::IssuerNotFound; + } + if (s == "InvalidLeafSignature") { + return CertificateValidationResult::InvalidLeafSignature; + } + if (s == "InvalidChain") { + return CertificateValidationResult::InvalidChain; + } + if (s == "Unknown") { + return CertificateValidationResult::Unknown; + } + throw std::out_of_range("Provided string " + s + + " could not be converted to enum of type CertificateValidationResult"); +} +} // namespace conversions + +std::ostream& operator<<(std::ostream& os, const CertificateValidationResult& certificate_validation_result) { + os << conversions::certificate_validation_result_to_string(certificate_validation_result); + return os; +} + namespace conversions { std::string install_certificate_result_to_string(InstallCertificateResult e) { switch (e) { diff --git a/lib/ocpp/v16/charge_point_impl.cpp b/lib/ocpp/v16/charge_point_impl.cpp index c5d0b2eac..fde34d412 100644 --- a/lib/ocpp/v16/charge_point_impl.cpp +++ b/lib/ocpp/v16/charge_point_impl.cpp @@ -2378,8 +2378,8 @@ void ChargePointImpl::handleSignedUpdateFirmware(ocpp::Callevse_security->verify_certificate(call.msg.firmware.signingCertificate.get(), - ocpp::CertificateSigningUseEnum::ManufacturerCertificate) != - ocpp::InstallCertificateResult::Accepted) { + ocpp::CaCertificateType::MF) != + ocpp::CertificateValidationResult::Accepted) { response.status = UpdateFirmwareStatusEnumType::InvalidCertificate; ocpp::CallResult call_result(response, call.uniqueId); this->send(call_result); diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 253b84f0f..ea352afff 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -570,7 +570,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: // First try to validate the contract certificate locally if (certificate.has_value()) { - InstallCertificateResult localVerifyResult = this->evse_security->verify_certificate(certificate.value().get(), ocpp::CertificateSigningUseEnum::V2GCertificate); + CertificateValidationResult localVerifyResult = this->evse_security->verify_certificate(certificate.value().get(), ocpp::CaCertificateType::V2G); EVLOG_info << "Local contract validation result: " << localVerifyResult; bool CentralContractValidationAllowed = this->device_model->get_optional_value(ControllerComponentVariables::CentralContractValidationAllowed).value_or(true); @@ -581,12 +581,17 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: // C07.FR.02: The AuthorizeRequest shall at least contain the OCSP data if (this->websocket->is_connected()) { // C07.FR.06: Pass contract validation to CSMS when no contract root is found - if (CentralContractValidationAllowed and localVerifyResult == InstallCertificateResult::NoRootCertificateInstalled) { + if (CentralContractValidationAllowed and localVerifyResult == CertificateValidationResult::IssuerNotFound) { EVLOG_info << "Online: No local contract root found. Pass contract validation to CSMS"; response = this->authorize_req(id_token, certificate, ocsp_request_data); } else { EVLOG_info << "Online: Pass OCSP data to CSMS"; - response = this->authorize_req(id_token, std::nullopt, ocsp_request_data); + if (!ocsp_request_data.has_value()) { + EVLOG_warning << "OCSP data is missing"; + response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; + } else { + response = this->authorize_req(id_token, std::nullopt, ocsp_request_data); + } // TODO: local validation results are ignored, response is based only on OCSP data, is that acceptable? } } else { // Offline @@ -595,7 +600,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: EVLOG_info << "Offline: contract " << localVerifyResult; switch (localVerifyResult) { // C07.FR.09: CS shall lookup the eMAID in Local Auth List or Auth Cache when local validation succeeded - case InstallCertificateResult::Accepted: + case CertificateValidationResult::Accepted: // In C07.FR.09 LocalAuthorizeOffline is mentioned, this seems to be a generic config item that applies // to Local Auth List and Auth Cache, but since there are no requirements about it, lets check it here if (LocalAuthorizeOffline) { @@ -603,10 +608,12 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: } else { // No requirement states what to do when ContractValidationOffline is true and LocalAuthorizeOffline is false response.idTokenInfo.status = AuthorizationStatusEnum::NotAtThisTime; + response.certificateStatus = AuthorizeCertificateStatusEnum::Accepted; } break; - case InstallCertificateResult::Expired: + case CertificateValidationResult::Expired: response.idTokenInfo.status = AuthorizationStatusEnum::Expired; + response.certificateStatus = AuthorizeCertificateStatusEnum::CertificateExpired; break; default: response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; From c0dce5ef6a5bed56e28aee87ae76b607f6026809 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Mon, 26 Feb 2024 16:22:40 +0100 Subject: [PATCH 04/12] Verify contract certificate against MO chain Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index ea352afff..9db9220ef 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -570,7 +570,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: // First try to validate the contract certificate locally if (certificate.has_value()) { - CertificateValidationResult localVerifyResult = this->evse_security->verify_certificate(certificate.value().get(), ocpp::CaCertificateType::V2G); + CertificateValidationResult localVerifyResult = this->evse_security->verify_certificate(certificate.value().get(), ocpp::CaCertificateType::MO); EVLOG_info << "Local contract validation result: " << localVerifyResult; bool CentralContractValidationAllowed = this->device_model->get_optional_value(ControllerComponentVariables::CentralContractValidationAllowed).value_or(true); From f7dac28bcaf94089c039eca1592979c3b3410070 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Wed, 28 Feb 2024 08:35:59 +0100 Subject: [PATCH 05/12] Add functionality for generating OCSP data for a contract certficiate chain Signed-off-by: Menno de Graaf --- include/ocpp/common/evse_security.hpp | 7 ++++ include/ocpp/common/evse_security_impl.hpp | 2 + include/ocpp/v201/charge_point.hpp | 5 +++ lib/ocpp/common/evse_security_impl.cpp | 13 +++++++ lib/ocpp/v201/charge_point.cpp | 44 +++++++++++++++++++--- 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/include/ocpp/common/evse_security.hpp b/include/ocpp/common/evse_security.hpp index c093c4b3c..0b9012f35 100644 --- a/include/ocpp/common/evse_security.hpp +++ b/include/ocpp/common/evse_security.hpp @@ -62,6 +62,13 @@ class EvseSecurity { /// \return contains OCSP request data virtual std::vector get_ocsp_request_data() = 0; + /// \brief Retrieves the OCSP request data of a certificate chain. + /// \param certificate_chain PEM formatted certificate or certificate chain + /// \param certificate_type type of the leaf certificate + /// \return contains OCSP request data + virtual std::vector get_ocsp_request_data(const std::string& certificate_chain, + const CaCertificateType& certificate_type) = 0; + /// \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 /// \param ocsp_response the actual OCSP data diff --git a/include/ocpp/common/evse_security_impl.hpp b/include/ocpp/common/evse_security_impl.hpp index 275a095f7..5e5fde68d 100644 --- a/include/ocpp/common/evse_security_impl.hpp +++ b/include/ocpp/common/evse_security_impl.hpp @@ -44,6 +44,8 @@ class EvseSecurityImpl : public EvseSecurity { std::vector get_installed_certificates(const std::vector& certificate_types) override; std::vector get_ocsp_request_data() override; + std::vector get_ocsp_request_data(const std::string& certificate_chain, + const CaCertificateType& certificate_type) override; void update_ocsp_cache(const CertificateHashDataType& certificate_hash_data, const std::string& ocsp_response) override; bool is_ca_certificate_installed(const CaCertificateType& certificate_type) override; diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index 94f0b4288..70c7b3741 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -654,6 +654,11 @@ class ChargePoint : ocpp::ChargingStationBase { /// \return True on success. False if evse id does not exist. bool on_charging_state_changed(const uint32_t evse_id, ChargingStateEnum charging_state); + /// \brief Generates OCSP request data from a (contract) certificate chain + /// \param certificate + /// \return vector with OCSP request data + std::vector generate_ocsp_data(const CiString<5500>& certificate); + /// \brief Validates provided \p id_token \p certificate and \p ocsp_request_data using CSMS, AuthCache or AuthList /// \param id_token /// \param certificate diff --git a/lib/ocpp/common/evse_security_impl.cpp b/lib/ocpp/common/evse_security_impl.cpp index 8d27db4df..a1276fa1d 100644 --- a/lib/ocpp/common/evse_security_impl.cpp +++ b/lib/ocpp/common/evse_security_impl.cpp @@ -74,6 +74,19 @@ std::vector EvseSecurityImpl::get_ocsp_request_data() { return result; } + +std::vector EvseSecurityImpl::get_ocsp_request_data(const std::string& certificate_chain, + const CaCertificateType& certificate_type) { + std::vector result; + + const auto ocsp_request_data = this->evse_security->get_ocsp_request_data(certificate_chain, conversions::from_ocpp(certificate_type)); + for (const auto& ocsp_request_entry : ocsp_request_data.ocsp_request_data_list) { + result.push_back(conversions::to_ocpp(ocsp_request_entry)); + } + + return result; +} + void EvseSecurityImpl::update_ocsp_cache(const CertificateHashDataType& certificate_hash_data, const std::string& ocsp_response) { this->evse_security->update_ocsp_cache(conversions::from_ocpp(certificate_hash_data), ocsp_response); diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 9db9220ef..ce6e4c716 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -544,6 +544,32 @@ bool ChargePoint::on_charging_state_changed(const uint32_t evse_id, ChargingStat return false; } +std::vector ChargePoint::generate_ocsp_data(const CiString<5500>& certificate) { + std::vector ocsp_request_data_list; + const auto ocsp_data_list = this->evse_security->get_ocsp_request_data(certificate.get(), ocpp::CaCertificateType::MO); + for (const auto& ocsp_data : ocsp_data_list) { + OCSPRequestData request; + switch (ocsp_data.hashAlgorithm) { + case HashAlgorithmEnumType::SHA256: + request.hashAlgorithm = ocpp::v201::HashAlgorithmEnum::SHA256; + break; + case HashAlgorithmEnumType::SHA384: + request.hashAlgorithm = ocpp::v201::HashAlgorithmEnum::SHA384; + break; + case HashAlgorithmEnumType::SHA512: + request.hashAlgorithm = ocpp::v201::HashAlgorithmEnum::SHA512; + break; + } + request.issuerKeyHash = ocsp_data.issuerKeyHash; + request.issuerNameHash = ocsp_data.issuerNameHash; + request.responderURL = ocsp_data.responderUrl; + request.serialNumber = ocsp_data.serialNumber; + ocsp_request_data_list.push_back(request); + } + return ocsp_request_data_list; +} + + AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std::optional>& certificate, const std::optional>& ocsp_request_data) { // TODO(piet): C01.FR.14 @@ -585,12 +611,20 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: EVLOG_info << "Online: No local contract root found. Pass contract validation to CSMS"; response = this->authorize_req(id_token, certificate, ocsp_request_data); } else { - EVLOG_info << "Online: Pass OCSP data to CSMS"; - if (!ocsp_request_data.has_value()) { - EVLOG_warning << "OCSP data is missing"; - response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; - } else { + // If OCSP data was provided as argument, use it + // Else, try to generate the OCSP data from the certificate chain and use that + if (ocsp_request_data.has_value()) { + EVLOG_info << "Online: Pass provided OCSP data to CSMS"; response = this->authorize_req(id_token, std::nullopt, ocsp_request_data); + } else { + std::vector generated_ocsp_request_data_list = generate_ocsp_data(certificate.value()); + if (generated_ocsp_request_data_list.size() > 0) { + EVLOG_info << "Online: Pass generated OCSP data to CSMS"; + response = this->authorize_req(id_token, std::nullopt, generated_ocsp_request_data_list); + } else { + EVLOG_warning << "Online: OCSP data could not be generated"; + response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; + } } // TODO: local validation results are ignored, response is based only on OCSP data, is that acceptable? } From 147aabd6969e5d883eb08f452cf01706265d39fe Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Mon, 4 Mar 2024 16:57:30 +0100 Subject: [PATCH 06/12] Pass OCSP data if it is provided and add CSMS response feedback Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 57 +++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index ce6e4c716..16bf10844 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -593,9 +593,15 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: if (id_token.type == IdTokenEnum::eMAID) { // Temporary variable that is set to true to avoid immediate response to allow the local auth list or auth cache to be tried bool tryLocalAuthListOrCache = false; - - // First try to validate the contract certificate locally - if (certificate.has_value()) { + bool forwardToCsms = false; + + // If OCSP data is provided as argument, use it + if (this->websocket->is_connected() and ocsp_request_data.has_value()) { + EVLOG_info << "Online: Pass provided OCSP data to CSMS"; + response = this->authorize_req(id_token, std::nullopt, ocsp_request_data); + forwardToCsms = true; + } else if (certificate.has_value()) { + // First try to validate the contract certificate locally CertificateValidationResult localVerifyResult = this->evse_security->verify_certificate(certificate.value().get(), ocpp::CaCertificateType::MO); EVLOG_info << "Local contract validation result: " << localVerifyResult; @@ -605,28 +611,30 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: // C07.FR.01: When CS is online, it shall send an AuthorizeRequest // C07.FR.02: The AuthorizeRequest shall at least contain the OCSP data + // TODO: local validation results are ignored if response is based only on OCSP data, is that acceptable? if (this->websocket->is_connected()) { - // C07.FR.06: Pass contract validation to CSMS when no contract root is found - if (CentralContractValidationAllowed and localVerifyResult == CertificateValidationResult::IssuerNotFound) { - EVLOG_info << "Online: No local contract root found. Pass contract validation to CSMS"; - response = this->authorize_req(id_token, certificate, ocsp_request_data); + // If no OCSP data was provided, check for a contract root + if (localVerifyResult == CertificateValidationResult::IssuerNotFound) { + // C07.FR.06: Pass contract validation to CSMS when no contract root is found + if (CentralContractValidationAllowed) { + EVLOG_info << "Online: No local contract root found. Pass contract validation to CSMS"; + response = this->authorize_req(id_token, certificate, std::nullopt); + forwardToCsms = true; + } else { + EVLOG_warning << "Online: Central Contract Validation not allowed"; + response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; + } } else { - // If OCSP data was provided as argument, use it - // Else, try to generate the OCSP data from the certificate chain and use that - if (ocsp_request_data.has_value()) { - EVLOG_info << "Online: Pass provided OCSP data to CSMS"; - response = this->authorize_req(id_token, std::nullopt, ocsp_request_data); + // Try to generate the OCSP data from the certificate chain and use that + std::vector generated_ocsp_request_data_list = generate_ocsp_data(certificate.value()); + if (generated_ocsp_request_data_list.size() > 0) { + EVLOG_info << "Online: Pass generated OCSP data to CSMS"; + response = this->authorize_req(id_token, std::nullopt, generated_ocsp_request_data_list); + forwardToCsms = true; } else { - std::vector generated_ocsp_request_data_list = generate_ocsp_data(certificate.value()); - if (generated_ocsp_request_data_list.size() > 0) { - EVLOG_info << "Online: Pass generated OCSP data to CSMS"; - response = this->authorize_req(id_token, std::nullopt, generated_ocsp_request_data_list); - } else { - EVLOG_warning << "Online: OCSP data could not be generated"; - response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; - } + EVLOG_warning << "Online: OCSP data could not be generated"; + response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; } - // TODO: local validation results are ignored, response is based only on OCSP data, is that acceptable? } } else { // Offline // C07.FR.08: CS shall try to validate the contract locally @@ -662,6 +670,13 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: EVLOG_warning << "Can not validate eMAID without certificate chain"; response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; } + if (forwardToCsms) { + // AuthorizeRequest sent to CSMS, let's show the results + EVLOG_info << "CSMS idToken status: " << response.idTokenInfo.status; + if (response.certificateStatus.has_value()) { + EVLOG_info << "CSMS certificate status: " << response.certificateStatus.value(); + } + } // For eMAID, we will respond here, unless the local auth list or auth cache is tried if (!tryLocalAuthListOrCache) { return response; From 26bbf7c954b5999448a93602f1731f6e0b2569f1 Mon Sep 17 00:00:00 2001 From: Marc Emmers Date: Wed, 6 Mar 2024 10:34:28 +0100 Subject: [PATCH 07/12] Send certificate type in sign certificate request Signed-off-by: Marc Emmers --- lib/ocpp/v201/charge_point.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 16bf10844..8c2329076 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -1714,7 +1714,7 @@ void ChargePoint::sign_certificate_req(const ocpp::CertificateSigningUseEnum& ce std::optional organization; if (certificate_signing_use == ocpp::CertificateSigningUseEnum::ChargingStationCertificate) { - req.certificateType = CertificateSigningUseEnum::ChargingStationCertificate; + req.certificateType = ocpp::v201::CertificateSigningUseEnum::ChargingStationCertificate; common = this->device_model->get_optional_value(ControllerComponentVariables::ChargeBoxSerialNumber); organization = @@ -1722,7 +1722,7 @@ void ChargePoint::sign_certificate_req(const ocpp::CertificateSigningUseEnum& ce country = this->device_model->get_optional_value(ControllerComponentVariables::ISO15118CtrlrCountryName); } else { - req.certificateType = CertificateSigningUseEnum::V2GCertificate; + req.certificateType = ocpp::v201::CertificateSigningUseEnum::V2GCertificate; common = this->device_model->get_optional_value(ControllerComponentVariables::ISO15118CtrlrSeccId); organization = this->device_model->get_optional_value( ControllerComponentVariables::ISO15118CtrlrOrganizationName); From 66f90cb5d3fb4d7e74f8acc7df4eb61628a9a639 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Wed, 13 Mar 2024 15:39:40 +0100 Subject: [PATCH 08/12] Fix formatting Signed-off-by: Menno de Graaf --- include/ocpp/common/evse_security.hpp | 4 +- include/ocpp/common/evse_security_impl.hpp | 4 +- lib/ocpp/common/evse_security_impl.cpp | 7 ++- lib/ocpp/v201/charge_point.cpp | 66 +++++++++++++--------- 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/include/ocpp/common/evse_security.hpp b/include/ocpp/common/evse_security.hpp index 0b9012f35..0af6acdaf 100644 --- a/include/ocpp/common/evse_security.hpp +++ b/include/ocpp/common/evse_security.hpp @@ -47,7 +47,7 @@ class EvseSecurity { /// \param certificate_type type of the leaf certificate /// \return result of the operation virtual CertificateValidationResult verify_certificate(const std::string& certificate_chain, - const CaCertificateType& certificate_type) = 0; + const CaCertificateType& certificate_type) = 0; /// \brief Retrieves all certificates installed on the filesystem applying the \p certificate_types filter. This /// function respects the requirements of OCPP specified for the CSMS initiated message @@ -67,7 +67,7 @@ class EvseSecurity { /// \param certificate_type type of the leaf certificate /// \return contains OCSP request data virtual std::vector get_ocsp_request_data(const std::string& certificate_chain, - const CaCertificateType& certificate_type) = 0; + const CaCertificateType& certificate_type) = 0; /// \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 diff --git a/include/ocpp/common/evse_security_impl.hpp b/include/ocpp/common/evse_security_impl.hpp index 5e5fde68d..4d2b00d54 100644 --- a/include/ocpp/common/evse_security_impl.hpp +++ b/include/ocpp/common/evse_security_impl.hpp @@ -40,12 +40,12 @@ class EvseSecurityImpl : public EvseSecurity { InstallCertificateResult update_leaf_certificate(const std::string& certificate_chain, const CertificateSigningUseEnum& certificate_type) override; CertificateValidationResult verify_certificate(const std::string& certificate_chain, - const CaCertificateType& certificate_type) override; + const CaCertificateType& certificate_type) override; std::vector get_installed_certificates(const std::vector& certificate_types) override; std::vector get_ocsp_request_data() override; std::vector get_ocsp_request_data(const std::string& certificate_chain, - const CaCertificateType& certificate_type) override; + const CaCertificateType& certificate_type) override; void update_ocsp_cache(const CertificateHashDataType& certificate_hash_data, const std::string& ocsp_response) override; bool is_ca_certificate_installed(const CaCertificateType& certificate_type) override; diff --git a/lib/ocpp/common/evse_security_impl.cpp b/lib/ocpp/common/evse_security_impl.cpp index a1276fa1d..19b1884af 100644 --- a/lib/ocpp/common/evse_security_impl.cpp +++ b/lib/ocpp/common/evse_security_impl.cpp @@ -41,7 +41,7 @@ InstallCertificateResult EvseSecurityImpl::update_leaf_certificate(const std::st } CertificateValidationResult EvseSecurityImpl::verify_certificate(const std::string& certificate_chain, - const CaCertificateType& certificate_type) { + const CaCertificateType& certificate_type) { return conversions::to_ocpp( this->evse_security->verify_certificate(certificate_chain, conversions::from_ocpp(certificate_type))); } @@ -76,10 +76,11 @@ std::vector EvseSecurityImpl::get_ocsp_request_data() { } std::vector EvseSecurityImpl::get_ocsp_request_data(const std::string& certificate_chain, - const CaCertificateType& certificate_type) { + const CaCertificateType& certificate_type) { std::vector result; - const auto ocsp_request_data = this->evse_security->get_ocsp_request_data(certificate_chain, conversions::from_ocpp(certificate_type)); + const auto ocsp_request_data = + this->evse_security->get_ocsp_request_data(certificate_chain, conversions::from_ocpp(certificate_type)); for (const auto& ocsp_request_entry : ocsp_request_data.ocsp_request_data_list) { result.push_back(conversions::to_ocpp(ocsp_request_entry)); } diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 8c2329076..15e2b642e 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -546,7 +546,8 @@ bool ChargePoint::on_charging_state_changed(const uint32_t evse_id, ChargingStat std::vector ChargePoint::generate_ocsp_data(const CiString<5500>& certificate) { std::vector ocsp_request_data_list; - const auto ocsp_data_list = this->evse_security->get_ocsp_request_data(certificate.get(), ocpp::CaCertificateType::MO); + const auto ocsp_data_list = + this->evse_security->get_ocsp_request_data(certificate.get(), ocpp::CaCertificateType::MO); for (const auto& ocsp_data : ocsp_data_list) { OCSPRequestData request; switch (ocsp_data.hashAlgorithm) { @@ -589,9 +590,10 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: return response; } - // C07: Authorization using contract certificates + // C07: Authorization using contract certificates if (id_token.type == IdTokenEnum::eMAID) { - // Temporary variable that is set to true to avoid immediate response to allow the local auth list or auth cache to be tried + // Temporary variable that is set to true to avoid immediate response to allow the local auth list + // or auth cache to be tried bool tryLocalAuthListOrCache = false; bool forwardToCsms = false; @@ -602,12 +604,20 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: forwardToCsms = true; } else if (certificate.has_value()) { // First try to validate the contract certificate locally - CertificateValidationResult localVerifyResult = this->evse_security->verify_certificate(certificate.value().get(), ocpp::CaCertificateType::MO); + CertificateValidationResult localVerifyResult = + this->evse_security->verify_certificate(certificate.value().get(), ocpp::CaCertificateType::MO); EVLOG_info << "Local contract validation result: " << localVerifyResult; - bool CentralContractValidationAllowed = this->device_model->get_optional_value(ControllerComponentVariables::CentralContractValidationAllowed).value_or(true); - bool ContractValidationOffline = this->device_model->get_optional_value(ControllerComponentVariables::ContractValidationOffline).value_or(true); - bool LocalAuthorizeOffline = this->device_model->get_optional_value(ControllerComponentVariables::LocalAuthorizeOffline).value_or(true); + bool CentralContractValidationAllowed = + this->device_model + ->get_optional_value(ControllerComponentVariables::CentralContractValidationAllowed) + .value_or(true); + bool ContractValidationOffline = + this->device_model->get_optional_value(ControllerComponentVariables::ContractValidationOffline) + .value_or(true); + bool LocalAuthorizeOffline = + this->device_model->get_optional_value(ControllerComponentVariables::LocalAuthorizeOffline) + .value_or(true); // C07.FR.01: When CS is online, it shall send an AuthorizeRequest // C07.FR.02: The AuthorizeRequest shall at least contain the OCSP data @@ -636,30 +646,30 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; } } - } else { // Offline + } else { // Offline // C07.FR.08: CS shall try to validate the contract locally if (ContractValidationOffline) { EVLOG_info << "Offline: contract " << localVerifyResult; switch (localVerifyResult) { - // C07.FR.09: CS shall lookup the eMAID in Local Auth List or Auth Cache when local validation succeeded - case CertificateValidationResult::Accepted: - // In C07.FR.09 LocalAuthorizeOffline is mentioned, this seems to be a generic config item that applies - // to Local Auth List and Auth Cache, but since there are no requirements about it, lets check it here - if (LocalAuthorizeOffline) { - tryLocalAuthListOrCache = true; - } else { - // No requirement states what to do when ContractValidationOffline is true and LocalAuthorizeOffline is false - response.idTokenInfo.status = AuthorizationStatusEnum::NotAtThisTime; - response.certificateStatus = AuthorizeCertificateStatusEnum::Accepted; - } - break; - case CertificateValidationResult::Expired: - response.idTokenInfo.status = AuthorizationStatusEnum::Expired; - response.certificateStatus = AuthorizeCertificateStatusEnum::CertificateExpired; - break; - default: - response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; - break; + // C07.FR.09: CS shall lookup the eMAID in Local Auth List or Auth Cache when local validation succeeded + case CertificateValidationResult::Accepted: + // In C07.FR.09 LocalAuthorizeOffline is mentioned, this seems to be a generic config item that applies + // to Local Auth List and Auth Cache, but since there are no requirements about it, lets check it here + if (LocalAuthorizeOffline) { + tryLocalAuthListOrCache = true; + } else { + // No requirement states what to do when ContractValidationOffline is true and LocalAuthorizeOffline is false + response.idTokenInfo.status = AuthorizationStatusEnum::NotAtThisTime; + response.certificateStatus = AuthorizeCertificateStatusEnum::Accepted; + } + break; + case CertificateValidationResult::Expired: + response.idTokenInfo.status = AuthorizationStatusEnum::Expired; + response.certificateStatus = AuthorizeCertificateStatusEnum::CertificateExpired; + break; + default: + response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; + break; } } else { // C07.FR.07: CS shall not allow charging @@ -679,7 +689,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: } // For eMAID, we will respond here, unless the local auth list or auth cache is tried if (!tryLocalAuthListOrCache) { - return response; + return response; } } From 872b70729dd17c9e10b9a1d3518a076a577f65c9 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Wed, 13 Mar 2024 15:45:00 +0100 Subject: [PATCH 09/12] Fix formatting Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 15e2b642e..d984aa185 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -636,7 +636,8 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: } } else { // Try to generate the OCSP data from the certificate chain and use that - std::vector generated_ocsp_request_data_list = generate_ocsp_data(certificate.value()); + std::vector generated_ocsp_request_data_list = + generate_ocsp_data(certificate.value()); if (generated_ocsp_request_data_list.size() > 0) { EVLOG_info << "Online: Pass generated OCSP data to CSMS"; response = this->authorize_req(id_token, std::nullopt, generated_ocsp_request_data_list); @@ -651,14 +652,17 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: if (ContractValidationOffline) { EVLOG_info << "Offline: contract " << localVerifyResult; switch (localVerifyResult) { - // C07.FR.09: CS shall lookup the eMAID in Local Auth List or Auth Cache when local validation succeeded + // C07.FR.09: CS shall lookup the eMAID in Local Auth List or Auth Cache when + // local validation succeeded case CertificateValidationResult::Accepted: - // In C07.FR.09 LocalAuthorizeOffline is mentioned, this seems to be a generic config item that applies - // to Local Auth List and Auth Cache, but since there are no requirements about it, lets check it here + // In C07.FR.09 LocalAuthorizeOffline is mentioned, this seems to be a generic config item + // that applies to Local Auth List and Auth Cache, but since there are no requirements about + // it, lets check it here if (LocalAuthorizeOffline) { tryLocalAuthListOrCache = true; } else { - // No requirement states what to do when ContractValidationOffline is true and LocalAuthorizeOffline is false + // No requirement states what to do when ContractValidationOffline is true + // and LocalAuthorizeOffline is false response.idTokenInfo.status = AuthorizationStatusEnum::NotAtThisTime; response.certificateStatus = AuthorizeCertificateStatusEnum::Accepted; } From f5ff753a34d93c22fcd845dafee3448b5c6fe92b Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Wed, 13 Mar 2024 15:47:15 +0100 Subject: [PATCH 10/12] Fix formatting Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index d984aa185..81c1f4d47 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -570,7 +570,6 @@ std::vector ChargePoint::generate_ocsp_data(const CiString<5500 return ocsp_request_data_list; } - AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std::optional>& certificate, const std::optional>& ocsp_request_data) { // TODO(piet): C01.FR.14 From 44ade1e0c4f9b4164b64d25180e7d863e9134fad Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Wed, 20 Mar 2024 08:31:28 +0100 Subject: [PATCH 11/12] Fix review comment Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 81c1f4d47..62e79a52e 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -594,13 +594,13 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: // Temporary variable that is set to true to avoid immediate response to allow the local auth list // or auth cache to be tried bool tryLocalAuthListOrCache = false; - bool forwardToCsms = false; + bool forwardedToCsms = false; // If OCSP data is provided as argument, use it if (this->websocket->is_connected() and ocsp_request_data.has_value()) { EVLOG_info << "Online: Pass provided OCSP data to CSMS"; response = this->authorize_req(id_token, std::nullopt, ocsp_request_data); - forwardToCsms = true; + forwardedToCsms = true; } else if (certificate.has_value()) { // First try to validate the contract certificate locally CertificateValidationResult localVerifyResult = @@ -628,7 +628,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: if (CentralContractValidationAllowed) { EVLOG_info << "Online: No local contract root found. Pass contract validation to CSMS"; response = this->authorize_req(id_token, certificate, std::nullopt); - forwardToCsms = true; + forwardedToCsms = true; } else { EVLOG_warning << "Online: Central Contract Validation not allowed"; response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; @@ -640,7 +640,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: if (generated_ocsp_request_data_list.size() > 0) { EVLOG_info << "Online: Pass generated OCSP data to CSMS"; response = this->authorize_req(id_token, std::nullopt, generated_ocsp_request_data_list); - forwardToCsms = true; + forwardedToCsms = true; } else { EVLOG_warning << "Online: OCSP data could not be generated"; response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; @@ -683,7 +683,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: EVLOG_warning << "Can not validate eMAID without certificate chain"; response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; } - if (forwardToCsms) { + if (forwardedToCsms) { // AuthorizeRequest sent to CSMS, let's show the results EVLOG_info << "CSMS idToken status: " << response.idTokenInfo.status; if (response.certificateStatus.has_value()) { From 79a010e5382aa63c524468c8fcb5caca98d0e156 Mon Sep 17 00:00:00 2001 From: Menno de Graaf Date: Wed, 20 Mar 2024 09:19:22 +0100 Subject: [PATCH 12/12] Fix review comment Signed-off-by: Menno de Graaf --- lib/ocpp/v201/charge_point.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 62e79a52e..553ac4a49 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -662,7 +662,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: } else { // No requirement states what to do when ContractValidationOffline is true // and LocalAuthorizeOffline is false - response.idTokenInfo.status = AuthorizationStatusEnum::NotAtThisTime; + response.idTokenInfo.status = AuthorizationStatusEnum::Unknown; response.certificateStatus = AuthorizeCertificateStatusEnum::Accepted; } break; @@ -671,7 +671,7 @@ AuthorizeResponse ChargePoint::validate_token(const IdToken id_token, const std: response.certificateStatus = AuthorizeCertificateStatusEnum::CertificateExpired; break; default: - response.idTokenInfo.status = AuthorizationStatusEnum::Invalid; + response.idTokenInfo.status = AuthorizationStatusEnum::Unknown; break; } } else {