diff --git a/config/v201/component_config/standardized/InternalCtrlr.json b/config/v201/component_config/standardized/InternalCtrlr.json index 28ce3b60f..d743ad569 100644 --- a/config/v201/component_config/standardized/InternalCtrlr.json +++ b/config/v201/component_config/standardized/InternalCtrlr.json @@ -770,6 +770,38 @@ "minimum": 1, "default": "60", "type": "integer" + }, + "AllowCSMSRootCertInstallWithUnsecureConnection": { + "variable_name": "AllowCSMSRootCertInstallWithUnsecureConnection", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "The flag that indicates if installation of CSMSRootCertificate is allowed when security profile is 1.", + "default": true, + "type": "boolean" + }, + "AllowMFRootCertInstallWithUnsecureConnection": { + "variable_name": "AllowMFRootCertInstallWithUnsecureConnection", + "characteristics": { + "supportsMonitoring": true, + "dataType": "boolean" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly" + } + ], + "description": "The flag that indicates if installation of ManufacturerRootCertificate is allowed when security profile is 1.", + "default": true, + "type": "boolean" } }, "required": [ diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index 2bd12cf01..63435d69b 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -782,6 +782,11 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa /// If \param persist is set to true, the change will be persisted across a reboot void execute_change_availability_request(ChangeAvailabilityRequest request, bool persist); + /// \brief Helper function to determine if a certificate installation should be allowed + /// \param cert_type is the certificate type to be checked + /// \return true if it should be allowed + bool should_allow_certificate_install(InstallCertificateUseEnum cert_type) const; + protected: std::shared_ptr smart_charging_handler; diff --git a/include/ocpp/v201/ctrlr_component_variables.hpp b/include/ocpp/v201/ctrlr_component_variables.hpp index 93af79ac1..6f3dad8bb 100644 --- a/include/ocpp/v201/ctrlr_component_variables.hpp +++ b/include/ocpp/v201/ctrlr_component_variables.hpp @@ -201,6 +201,8 @@ extern const ComponentVariable& MaxCertificateChainSize; extern const ComponentVariable& UpdateCertificateSymlinks; extern const RequiredComponentVariable& OrganizationName; extern const RequiredComponentVariable& SecurityProfile; +extern const ComponentVariable& AllowCSMSRootCertInstallWithUnsecureConnection; +extern const ComponentVariable& AllowMFRootCertInstallWithUnsecureConnection; extern const ComponentVariable& ACPhaseSwitchingSupported; extern const ComponentVariable& SmartChargingCtrlrAvailable; extern const ComponentVariable& SmartChargingCtrlrEnabled; diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 8fc4f5387..d460eab74 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -3588,24 +3588,50 @@ void ChargePoint::handle_get_installed_certificate_ids_req(Callsend(call_result); } +bool ChargePoint::should_allow_certificate_install(InstallCertificateUseEnum cert_type) const { + const int security_profile = this->device_model->get_value(ControllerComponentVariables::SecurityProfile); + + if (security_profile > 1) { + return true; + } + switch (cert_type) { + case InstallCertificateUseEnum::CSMSRootCertificate: + return this->device_model + ->get_optional_value(ControllerComponentVariables::AllowCSMSRootCertInstallWithUnsecureConnection) + .value_or(true); + + case InstallCertificateUseEnum::ManufacturerRootCertificate: + return this->device_model + ->get_optional_value(ControllerComponentVariables::AllowMFRootCertInstallWithUnsecureConnection) + .value_or(true); + default: + return true; + } +} + void ChargePoint::handle_install_certificate_req(Call call) { EVLOG_debug << "Received InstallCertificateRequest: " << call.msg << "\nwith messageId: " << call.uniqueId; const auto msg = call.msg; InstallCertificateResponse response; - const auto result = this->evse_security->install_ca_certificate( - msg.certificate.get(), ocpp::evse_security_conversions::from_ocpp_v201(msg.certificateType)); - response.status = ocpp::evse_security_conversions::to_ocpp_v201(result); - - if (response.status == InstallCertificateStatusEnum::Accepted) { - const auto& security_event = ocpp::security_events::RECONFIGURATIONOFSECURITYPARAMETERS; - std::string tech_info = - "Installed certificate: " + conversions::install_certificate_use_enum_to_string(msg.certificateType); - this->security_event_notification_req(CiString<50>(security_event), CiString<255>(tech_info), true, - utils::is_critical(security_event)); + if (!should_allow_certificate_install(msg.certificateType)) { + response.status = InstallCertificateStatusEnum::Rejected; + response.statusInfo = StatusInfo(); + response.statusInfo->reasonCode = "UnsecureConnection"; + response.statusInfo->additionalInfo = "CertificateInstallationNotAllowedWithUnsecureConnection"; + } else { + const auto result = this->evse_security->install_ca_certificate( + msg.certificate.get(), ocpp::evse_security_conversions::from_ocpp_v201(msg.certificateType)); + response.status = ocpp::evse_security_conversions::to_ocpp_v201(result); + if (response.status == InstallCertificateStatusEnum::Accepted) { + const auto& security_event = ocpp::security_events::RECONFIGURATIONOFSECURITYPARAMETERS; + std::string tech_info = + "Installed certificate: " + conversions::install_certificate_use_enum_to_string(msg.certificateType); + this->security_event_notification_req(CiString<50>(security_event), CiString<255>(tech_info), true, + utils::is_critical(security_event)); + } } - ocpp::CallResult call_result(response, call.uniqueId); this->send(call_result); } diff --git a/lib/ocpp/v201/ctrlr_component_variables.cpp b/lib/ocpp/v201/ctrlr_component_variables.cpp index 2b564b18f..474abb1dc 100644 --- a/lib/ocpp/v201/ctrlr_component_variables.cpp +++ b/lib/ocpp/v201/ctrlr_component_variables.cpp @@ -359,6 +359,20 @@ const ComponentVariable& ResumeTransactionsOnBoot = { "ResumeTransactionsOnBoot", }), }; +const ComponentVariable& AllowCSMSRootCertInstallWithUnsecureConnection = { + ControllerComponents::InternalCtrlr, + std::nullopt, + std::optional({ + "AllowCSMSRootCertInstallWithUnsecureConnection", + }), +}; +const ComponentVariable& AllowMFRootCertInstallWithUnsecureConnection = { + ControllerComponents::InternalCtrlr, + std::nullopt, + std::optional({ + "AllowMFRootCertInstallWithUnsecureConnection", + }), +}; const ComponentVariable& AlignedDataCtrlrEnabled = { ControllerComponents::AlignedDataCtrlr, std::nullopt,