Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

857 certificates handling over an unsecure connection in ocpp201 should not be allowed #863

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions config/v201/component_config/standardized/InternalCtrlr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
5 changes: 5 additions & 0 deletions include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SmartChargingHandlerInterface> smart_charging_handler;

Expand Down
2 changes: 2 additions & 0 deletions include/ocpp/v201/ctrlr_component_variables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
48 changes: 37 additions & 11 deletions lib/ocpp/v201/charge_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3588,24 +3588,50 @@ void ChargePoint::handle_get_installed_certificate_ids_req(Call<GetInstalledCert
this->send<GetInstalledCertificateIdsResponse>(call_result);
}

bool ChargePoint::should_allow_certificate_install(InstallCertificateUseEnum cert_type) const {
const int security_profile = this->device_model->get_value<int>(ControllerComponentVariables::SecurityProfile);

if (security_profile > 1) {
return true;
}
switch (cert_type) {
case InstallCertificateUseEnum::CSMSRootCertificate:
return this->device_model
->get_optional_value<bool>(ControllerComponentVariables::AllowCSMSRootCertInstallWithUnsecureConnection)
.value_or(true);

case InstallCertificateUseEnum::ManufacturerRootCertificate:
return this->device_model
->get_optional_value<bool>(ControllerComponentVariables::AllowMFRootCertInstallWithUnsecureConnection)
.value_or(true);
default:
return true;
}
}

void ChargePoint::handle_install_certificate_req(Call<InstallCertificateRequest> 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<InstallCertificateResponse> call_result(response, call.uniqueId);
this->send<InstallCertificateResponse>(call_result);
}
Expand Down
14 changes: 14 additions & 0 deletions lib/ocpp/v201/ctrlr_component_variables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,20 @@ const ComponentVariable& ResumeTransactionsOnBoot = {
"ResumeTransactionsOnBoot",
}),
};
const ComponentVariable& AllowCSMSRootCertInstallWithUnsecureConnection = {
ControllerComponents::InternalCtrlr,
std::nullopt,
std::optional<Variable>({
"AllowCSMSRootCertInstallWithUnsecureConnection",
}),
};
const ComponentVariable& AllowMFRootCertInstallWithUnsecureConnection = {
ControllerComponents::InternalCtrlr,
std::nullopt,
std::optional<Variable>({
"AllowMFRootCertInstallWithUnsecureConnection",
}),
};
const ComponentVariable& AlignedDataCtrlrEnabled = {
ControllerComponents::AlignedDataCtrlr,
std::nullopt,
Expand Down