Security Flows - CSMS Developer Guide
Based on OCPP 2.1 Edition 2 Specification (Part 2), Section A (Security). This guide covers all security flows (A01–A05), certificate management, and data types from the CSMS (Charging Station Management System) perspective using OCPP-J (JSON over WebSocket).
1. Overview
IntroductionSection A specifies the security mechanisms for OCPP 2.1 communication between the Charging Station (CS) and the CSMS. This covers credential management, certificate lifecycle, security event logging, security profile upgrades, and certificate management operations.
A01 — Credential Management
The CSMS updates the HTTP Basic Authentication password on a Charging Station. (Deprecated — use B09 NetworkConnectionProfile instead)
A02 — Certificate Lifecycle (CSMS-initiated)
The CSMS triggers the Charging Station to renew its client-side TLS certificate or V2G certificate.
A03 — Certificate Lifecycle (CS-initiated)
The Charging Station autonomously initiates a certificate renewal (within one month of expiry) and the CSMS processes the CSR.
A04 — Security Event Logging
The Charging Station reports security-relevant events to the CSMS in real-time.
A05 — Security Profile Upgrade
The CSMS upgrades a Charging Station from a lower security profile to a higher one using NetworkConfigurationPriority.
OCPP Message Direction Convention
| Direction | Meaning |
|---|---|
CS → CSMS | Charging Station sends a CALL (request) to the CSMS |
CSMS → CS | CSMS sends a CALL (request) to the Charging Station |
- A01, A02, A05 are CSMS-initiated — the CSMS starts the flow by sending a request to the Charging Station.
- A03 is CS-initiated — the Charging Station sends a
SignCertificateRequestto the CSMS (possibly triggered by CSMS via A02, or autonomously when its certificate is about to expire). - A04 is CS-initiated — the Charging Station sends a
SecurityEventNotificationRequestto the CSMS.
Messages Used in Security Flows
| Message | Direction | Used In |
|---|---|---|
SetVariablesRequest / SetVariablesResponse | CSMS → CS | A01, A05 |
TriggerMessageRequest / TriggerMessageResponse | CSMS → CS | A02 |
SignCertificateRequest / SignCertificateResponse | CS → CSMS | A02, A03 |
CertificateSignedRequest / CertificateSignedResponse | CSMS → CS | A02, A03 |
SecurityEventNotificationRequest / SecurityEventNotificationResponse | CS → CSMS | A04 |
ResetRequest / ResetResponse | CSMS → CS | A05 |
InstallCertificateRequest / InstallCertificateResponse | CSMS → CS | Cert Mgmt |
GetInstalledCertificateIdsRequest / GetInstalledCertificateIdsResponse | CSMS → CS | Cert Mgmt |
DeleteCertificateRequest / DeleteCertificateResponse | CSMS → CS | Cert Mgmt |
2. Connection-Level Security (Security Profiles)
ConfigurationOCPP 2.1 defines three security profiles. The CSMS MUST use exactly one security profile at a time per port/endpoint. The CSMS MAY operate different profiles on different ports/addresses.
| Profile | No. | CS Authentication | CSMS Authentication | Transport Security |
|---|---|---|---|---|
| Unsecured Transport with Basic Auth | 1 | HTTP Basic Auth (username/password) | None | None |
| TLS with Basic Authentication | 2 | HTTP Basic Auth (username/password) | TLS server certificate | TLS |
| TLS with Client Side Certificates | 3 | TLS client certificate | TLS server certificate | TLS |
Profile 1 — Unsecured Transport with Basic Authentication
[A00.FR.207] The CSMS SHALL validate that Charging Station identity AND Basic Authentication
password match the username and password in the Authorization header.
- Username = Charging Station identity (from OCPP-J connection URL).
- Password = value of
BasicAuthPasswordconfiguration variable (UTF-8 encoded string). - Password length: minimum 16 characters, maximum defined by
maxLimit(at least 40, at most 64). - [A00.FR.002] If the CS attempts to connect with a different profile than the CSMS is using, terminate the connection.
Warning: Only use on trusted networks (e.g., VPN). No transport-level encryption.
GET /ws HTTP/1.1
Remote-Addr: 127.0.0.1
UPGRADE: websocket
CONNECTION: Upgrade
HOST: 127.0.0.1:9999
SEC-WEBSOCKET-KEY: Pb4obWo2214EfaPQuazMjA==
SEC-WEBSOCKET-VERSION: 13
AUTHORIZATION: Basic <Base64 encoded(<ChargePointId>:<AuthorizationKey>)>Implementation steps:
- Parse the
Authorizationheader from the WebSocket upgrade request. - Decode the Base64 value to extract
<username>:<password>. - Look up the Charging Station by
username(= Charging Station identity). - Compare the
passwordagainst the stored password hash. - If mismatch: return HTTP 401 and do NOT upgrade to WebSocket.
- If match: return HTTP 101 and complete the WebSocket upgrade.
Profile 2 — TLS with Basic Authentication
All of Profile 1 responsibilities, plus:
- [A00.FR.306] Act as TLS server. [A00.FR.307] Authenticate itself using the CSMS certificate as the server-side certificate.
- [A00.FR.312] Secure the communication channel using TLS.
- [A00.FR.313] Only use TLS v1.2 or above. [A00.FR.315] Terminate connection on older TLS/SSL.
- [A00.FR.320] Do NOT use cipher suites with cryptographic primitives marked as unsuitable for legacy use.
- [A00.FR.321] Do NOT use TLS compression.
- [A00.FR.322] Terminate if CS only supports unsuitable cipher suites.
- [A00.FR.324] Validate Basic Auth credentials (same as Profile 1).
- The CSMS needs 2 different certificates (one RSA, one ECDSA) to support both cipher suite families.
Required cipher suites [A00.FR.318]:
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384TLS_RSA_WITH_AES_128_GCM_SHA256TLS_RSA_WITH_AES_256_GCM_SHA384Profile 3 — TLS with Client Side Certificates
All TLS requirements from Profile 2, plus:
- [A00.FR.403] Verify the certification path of the CS's certificate according to RFC 5280 Section 6 path validation rules.
- [A00.FR.404] Verify certificate ownership:
O(organizationName) RDN must contain the CSO name. - [A00.FR.405] Verify certificate identity:
CN(commonName) RDN must contain the unique serial number of the CS (not a URL or IP). - [A00.FR.407] If the CS does not have a valid certificate or the path is invalid (and NOT A00.FR.429), terminate the connection.
- [A00.FR.408] It is RECOMMENDED to log a security event
InvalidChargingStationCertificate. - [A00.FR.421] Support the same four cipher suites as Profile 2.
- [A00.FR.427] A unique Charging Station certificate SHALL be used for each Charging Station.
Exception [A00.FR.429]: The CSMS MAY accept a CS with an expired certificate
in a Pending BootNotification state,
then immediately execute use case A02 to renew the certificate.
Certificate Properties (CSMS must validate/generate)
| Req ID | Requirement |
|---|---|
A00.FR.501 | Private keys must provide security equivalent to >= 112-bit symmetric key |
A00.FR.502 | RSA/DSA keys: >= 2048 bits |
A00.FR.503 | ECC keys: >= 224 bits |
A00.FR.505 | Signing: RSA-PSS or ECDSA |
A00.FR.506 | Hash: SHA256 |
A00.FR.507 | Format: X.509, PEM encoded |
A00.FR.508 | Must include serial number |
A00.FR.510 | CSMS cert subject CN = FQDN of the CSMS endpoint |
A00.FR.511 | CS cert subject CN = unique serial number of the CS (not a URL or IP) |
Certificate Revocation (CSMS responsibilities)
| Req ID | Requirement |
|---|---|
A00.FR.701 | Use fast expiration (< 24 hours) for the CSMS certificate |
A00.FR.702 | Use online certificate verification (OCSP) to verify CS certificates |
A00.FR.705 | Verify certificate validity with the certificate authority server |
A00.FR.707 | Before providing a firmware signing certificate to a CS, validate both the certificate and the signed firmware |
3. A01 — Update Charging Station Password for HTTP Basic Authentication
CSMS-InitiatedDeprecated in OCPP 2.1: Use case B09 (Setting a new NetworkConnectionProfile) is the preferred approach. Retained for backwards compatibility.
The CSMS updates the BasicAuthPassword on a Charging
Station by sending a SetVariablesRequest.
After the CS accepts the new password, it disconnects and reconnects using the new credentials.
Applicable to: Security Profile 1 (Basic Security) or Profile 2 (TLS with Basic Auth).
Flow Sequence
CSMS Charging Station
| |
| SetVariablesRequest(BasicAuthPassword) |
| [ComponentName=SecurityCtrlr, |
| VariableName=BasicAuthPassword, |
| attributeValue=<new_password>] -----> |
| |
| SetVariablesResponse |
| [attributeStatus=Accepted] <------ |
| |
| [CS disconnects] |
| |
| [CS reconnects with new password] <------ |
| |Step 1: Send SetVariablesRequest
The CSMS sends a SetVariablesRequest with: component.name = "SecurityCtrlr", variable.name = "BasicAuthPassword",
and the new password string as attributeValue.
Password requirements [A01.FR.01, A01.FR.06, A01.FR.07]: Generate randomly with sufficient entropy. Use different passwords for different Charging Stations. Minimum 16 characters, maximum 64 characters. UTF-8 encoded string (NOT octet string or base64).
Step 2: Handle SetVariablesResponse
| Response attributeStatus | CSMS Action |
|---|---|
Accepted | [A01.FR.03] Password change successful. CSMS SHALL update stored credentials and stop accepting old password. |
Rejected / UnknownComponent / UnknownVariable / NotSupportedAttributeType | [A01.FR.04] Password NOT changed. CSMS SHALL keep accepting old credentials. MAY restrict CS functionality. |
RebootRequired | Variable accepted but requires a reboot. Keep old credentials until CS reconnects with new password. |
Step 3: Await Reconnection
After Accepted, the CS will
disconnect and reconnect using the new password. The CSMS must be ready to accept the new credentials
on the next connection attempt.
{
"setVariableData": [
{
"component": {
"name": "SecurityCtrlr"
},
"variable": {
"name": "BasicAuthPassword"
},
"attributeValue": "<new-password-string>"
}
]
}{
"setVariableResult": [
{
"attributeStatus": "Accepted",
"component": {
"name": "SecurityCtrlr"
},
"variable": {
"name": "BasicAuthPassword"
}
}
]
}CSMS Implementation Requirements
| Req ID | Requirement |
|---|---|
A01.FR.01 | Store as BasicAuthPassword configuration variable. |
A01.FR.03 | On Accepted response, the CSMS SHALL assume the password change was successful and no longer accept the old credentials. |
A01.FR.04 | On non-Accepted response, the CSMS SHALL assume the password has NOT changed and keep accepting old credentials. |
A01.FR.05 | On failure, the CSMS MAY restrict functionality (e.g., BootNotification Pending state) to retry updating credentials. |
A01.FR.06 | Different passwords SHOULD be used for different Charging Stations. |
A01.FR.07 | Passwords SHOULD be generated randomly with sufficient entropy. |
A01.FR.08 | The CSMS SHOULD only store salted password hashes, never plain text. |
A01.FR.09 | The CSMS SHOULD NOT put passwords in clear-text in log files or debug information. |
Error Scenarios
| Scenario | CSMS Behavior |
|---|---|
| CS responds with Rejected | Keep old password. Optionally put CS into Pending state to retry later. |
| CS responds with UnknownComponent or UnknownVariable | CS does not support SecurityCtrlr.BasicAuthPassword. This CS may not support password changes via OCPP. |
| No response (timeout) | Assume password NOT changed. Keep old credentials. Retry later. |
| CS disconnects but never reconnects with new password | Keep both old and new password valid for a grace period, then escalate. |
4. A02 — Update Charging Station Certificate by Request of CSMS
CSMS-InitiatedThe CSMS initiates a certificate renewal for the Charging Station's client-side TLS certificate (ChargingStationCertificate or V2G certificate). This is a multi-step flow involving the CSMS, the CS, and an external Certificate Authority (CA) server.
SignChargingStationCertificate
Renew the OCPP connection certificate (CS ↔ CSMS)
SignV2GCertificate
Renew the ISO 15118-2 V2G certificate (CS ↔ EV)
SignV2G20Certificate
Renew the ISO 15118-20 V2G certificate
SignCombinedCertificate
Renew a combined certificate
Applicable to: All profiles (primarily Profile 3). Also used when upgrading from Profile 2 to Profile 3.
Sequence — SignChargingStationCertificate
CSMS Charging Station Certificate Authority
| | |
| TriggerMessageRequest | |
| [requestedMessage= | |
| SignChargingStation | |
| Certificate] -----> | |
| | |
| TriggerMessageResponse | |
| [status=Accepted] <------ | |
| | |
| [CS generates new key pair] |
| | |
| SignCertificateRequest | |
| [csr=<PEM-encoded CSR>, | |
| certificateType= | |
| ChargingStationCertificate, | |
| hashRootCertificate=..., | |
| requestId=12345] | |
| <------ | |
| | |
| SignCertificateResponse | |
| [status=Accepted] -----> | |
| | |
| [Forward CSR to CA] ----------------------------------> |
| | |
| [CA signs certificate] <---------------------------------- |
| | |
| CertificateSignedRequest | |
| [certificateChain=<PEM>, | |
| certificateType= | |
| ChargingStationCertificate, | |
| requestId=12345] | |
| -----> | |
| | |
| [CS verifies certificate] |
| | |
| CertificateSignedResponse | |
| [status=Accepted] <------ | |
| | |
| [opt: CS switches to new certificate & reconnects] |
| | |Sequence — SignV2GCertificate
Prerequisite: For SignV2GCertificate, the variable ISO15118Ctrlr.SeccId must be set.
The CSMS first queries GetReportRequest for component ISO15118Ctrlr variable SeccId to discover unique SECC IDs.
CSMS Charging Station Certificate Authority
| | |
| [1. GetReportRequest for | |
| ISO15118Ctrlr.SeccId] -----> | |
| | |
| [NotifyReportResponse with | |
| unique SeccId values] <------ | |
| | |
| [2. For each unique SeccId:] | |
| | |
| TriggerMessageRequest | |
| [requestedMessage= | |
| SignV2GCertificate, | |
| evse={id:evseId}] -----> | |
| | |
| TriggerMessageResponse | |
| [status=Accepted] <------ | |
| | |
| SignCertificateRequest | |
| [csr=<PEM CSR>, | |
| certificateType= | |
| V2GCertificate] | |
| <------ | |
| | |
| [Same as above: sign & deliver] | |
| ... | |CSMS Actions — Step by Step
Step 1: Send TriggerMessageRequest (CSMS → CS)
{
"requestedMessage": "SignChargingStationCertificate"
// OR "SignV2GCertificate" / "SignV2G20Certificate" / "SignCombinedCertificate"
// For V2G certs, include optional "evse" for per-EVSE targeting:
// "evse": { "id": 1 }
}| requestedMessage Value | Description |
|---|---|
SignChargingStationCertificate | Request CS to generate CSR for its OCPP client certificate |
SignV2GCertificate | Request CS to generate CSR for ISO 15118-2 V2G certificate |
SignV2G20Certificate | Request CS to generate CSR for ISO 15118-20 V2G certificate |
SignCombinedCertificate | Request CS to generate CSR for a combined certificate |
Step 2: Handle TriggerMessageResponse (CS → CSMS)
| Response status | CSMS Action |
|---|---|
Accepted | CS will send a SignCertificateRequest. Wait for it. |
Rejected | CS rejected the trigger. Investigate / retry later. |
NotImplemented | CS does not support this trigger message type. |
Step 3: Handle SignCertificateRequest (CS → CSMS)
The CS sends a CSR (Certificate Signing Request) in PEM format.
| Field | Type | Required | Description |
|---|---|---|---|
csr | string (max 5500) | Required | PEM-encoded PKCS#10 CSR (RFC 2986) |
certificateType | enum | Optional | ChargingStationCertificate, V2GCertificate, or V2G20Certificate. Omitted = both 15118 and OCPP connection. |
hashRootCertificate | object | Optional | Hash of the Root CA to identify the Certificate Authority to use. |
requestId | integer | Optional | (2.1) RequestId to correlate with the CertificateSignedRequest. |
{
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC...base64-encoded-CSR...\n-----END CERTIFICATE REQUEST-----",
"certificateType": "ChargingStationCertificate",
"hashRootCertificate": {
"hashAlgorithm": "SHA256",
"issuerNameHash": "...",
"issuerKeyHash": "...",
"serialNumber": "..."
},
"requestId": 12345
}[A02.FR.11] If the CSMS can process the request, respond Accepted. [A02.FR.12] If not, respond Rejected.
Step 4: Send SignCertificateResponse (CSMS → CS)
{
"status": "Accepted" // or "Rejected"
}Step 5: Forward CSR to Certificate Authority
This is an out-of-band operation (not an OCPP message). The CSMS:
- [A02.FR.04] SHOULD NOT sign the certificate itself. Forward the CSR to a dedicated CA server.
- Wait for the CA to sign the certificate and return it.
- [A02.FR.14] When the SignCertificateRequest included a
certificateType, set the same type in the CertificateSignedRequest. - [A02.FR.25] When the SignCertificateRequest included a
requestId, the CSMS SHALL include the same requestId in the CertificateSignedRequest.
Step 6: Send CertificateSignedRequest (CSMS → CS)
{
"certificateChain": "-----BEGIN CERTIFICATE-----\n<leaf-certificate>\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n<sub-CA-certificate>\n-----END CERTIFICATE-----",
"certificateType": "ChargingStationCertificate",
"requestId": 12345
}Order: leaf certificate first, followed by intermediate sub-CA certs. Max size configurable via MaxCertificateChainSize.
[A02.FR.06 Note]: When providing a newly signed certificate with a start period equal to the current time, account for a slight time discrepancy between the CS and CSMS. The CS may reject the certificate if its validity period is slightly in the future from the device's perspective.
Step 7: Handle CertificateSignedResponse (CS → CSMS)
| Response status | CSMS Action |
|---|---|
Accepted | Certificate installed successfully. CS will reconnect with the new certificate. Expect WebSocket reconnection. |
Rejected | Certificate was rejected. CS discards it. Investigate cause (expired, invalid chain, wrong CN, chain too large). Consider re-running A02. |
CSMS Implementation Requirements
| Req ID | Requirement |
|---|---|
A02.FR.04 | The CSMS SHOULD NOT sign the certificate itself. Forward the CSR to a dedicated CA server. |
A02.FR.11 | If the CSMS is able to process the request, respond with status = Accepted. |
A02.FR.12 | If the CSMS is NOT able to process the request, respond with status = Rejected. |
A02.FR.14 | When the SignCertificateRequest included a certificateType, set the same certificateType in the CertificateSignedRequest. |
A02.FR.25 | When the SignCertificateRequest included a requestId, the CSMS SHALL include the same requestId in the CertificateSignedRequest. |
Error Handling
The CSMS accepts the CSR from the Charging Station before forwarding it to the CA. If the CA cannot be reached, or rejects the CSR, the Charging Station will never be informed directly.
| Scenario | CSMS Behavior |
|---|---|
| TriggerMessageResponse = Rejected or NotImplemented | CS cannot generate a CSR for this message type. Log and alert operator. |
| SignCertificateRequest never received (timeout) | CS failed to generate key pair or CSR. Retry TriggerMessageRequest. |
| CA is unreachable | Cannot sign certificate. Notify operator. CS continues with current certificate. Re-run A02 when resolved. |
| CA rejects the CSR | CSR sent by the CS is incorrect according to the CA. Notify operator to investigate. |
| CertificateSignedResponse = Rejected | CS rejected the signed certificate. Investigate and re-run A02. |
Retry Behavior (CSMS must be aware of)
The Charging Station will retry sending SignCertificateRequest with exponential back-off:
| Req ID | Behavior |
|---|---|
A02.FR.17 | If the CSMS accepted a SignCertificateRequest but hasn't sent a CertificateSignedRequest within CertSigningWaitMinimum seconds, the CS will re-send the SignCertificateRequest. |
A02.FR.18 | The CS doubles the back-off time each retry. |
A02.FR.19 | The CS stops retrying after CertSigningRepeatTimes attempts, until triggered again by the CSMS via TriggerMessageRequest. |
5. A03 — Update Charging Station Certificate Initiated by the Charging Station
CS-InitiatedThe Charging Station detects its certificate is nearing expiry (within one month) and proactively initiates renewal. The CSMS receives the CSR, forwards it to the CA, and delivers the signed certificate back. The message flow from Step 3 onward is identical to A02.
Applicable to: All profiles (primarily Profile 3). Prerequisite: Configuration variable OrganizationName MUST be set.
For SignV2GCertificate, ISO15118Ctrlr.SeccId must be set.
Flow Sequence
Charging Station CSMS Certificate Authority
| | |
| [cert expires in < 1 month] | |
| [generate new key pair] | |
| | |
| SignCertificateRequest(csr) | |
|----------------------------->| |
| | |
| SignCertificateResponse | |
| (Accepted) | |
|<-----------------------------| |
| | |
| | forward CSR |
| |------------------------->|
| | |
| | [sign cert] |
| | |
| | return Signed Cert |
| |<-------------------------|
| | |
| CertificateSignedRequest | |
| (certificateChain) | |
|<-----------------------------| |
| | |
| [verify cert] | |
| | |
| CertificateSignedResponse | |
| (Accepted/Rejected) | |
|----------------------------->| |
| | |Step 1: Handle SignCertificateRequest (CS → CSMS)
The CS sends a CSR without any prior trigger from the CSMS.
| certificateType | Meaning |
|---|---|
ChargingStationCertificate | CS-to-CSMS client certificate |
V2GCertificate | ISO 15118-2 V2G certificate |
V2G20Certificate | ISO 15118-20 V2G certificate |
(omitted) | Certificate for both 15118 and CSMS connection |
{
"csr": "<PEM-encoded PKCS#10 CSR>",
"certificateType": "ChargingStationCertificate",
"hashRootCertificate": {
"hashAlgorithm": "SHA256",
"issuerNameHash": "...",
"issuerKeyHash": "...",
"serialNumber": "..."
},
"requestId": 12345
}[A03.FR.11] If the CSMS can process the request: respond Accepted. [A03.FR.12] If the CSMS cannot: respond Rejected.
Step 2: Send SignCertificateResponse (CSMS → CS)
{
"status": "Accepted" // or "Rejected"
}Steps 3–5: Same as A02
Forward CSR to CA, receive signed certificate, send CertificateSignedRequest to CS,
and handle CertificateSignedResponse — same as A02 Steps 5–7.
- [A03.FR.04] CSMS SHOULD NOT sign the certificate itself; forward to a dedicated CA.
- [A03.FR.14] Set the
certificateTypein CertificateSignedRequest matching the SignCertificateRequest. - [A03.FR.21] If the SignCertificateRequest had a
requestId, include it in the CertificateSignedRequest.
Discarded Certificate [A03.FR.25]: If the CS discards a new client certificate (e.g., it couldn't reconnect with it),
it SHOULD send a SecurityEventNotification with type DiscardedRenewedClientCertificate.
The CSMS should monitor for this event and may need to re-trigger a certificate renewal.
CSMS Implementation Requirements
| Req ID | Requirement |
|---|---|
A03.FR.04 | The CSMS SHOULD NOT sign the certificate itself; forward to a dedicated CA. |
A03.FR.11 | If the CSMS can process the request: respond Accepted. |
A03.FR.12 | If the CSMS cannot process the request: respond Rejected. |
A03.FR.14 | Set the certificateType in CertificateSignedRequest matching the SignCertificateRequest. |
A03.FR.21 | If the SignCertificateRequest had a requestId, include it in the CertificateSignedRequest. |
A03.FR.25 | Monitor for DiscardedRenewedClientCertificate security event. May need to re-trigger certificate renewal. |
A02 vs A03 Comparison
| Aspect | A02 | A03 |
|---|---|---|
| Who initiates | CSMS (via TriggerMessageRequest) | Charging Station (autonomously) |
| First message | CSMS → CS: TriggerMessageRequest | CS → CSMS: SignCertificateRequest |
| Trigger condition | Proactive renewal by operator | CS detects its certificate is expiring (< 1 month) |
| Remaining flow | Identical from SignCertificateRequest onward | Same |
6. A04 — Security Event Notification
CS-InitiatedThe Charging Station reports critical security events to the CSMS in real-time. The CSMS receives, logs, and optionally acts upon these events.
Applicable to: All security profiles.
Flow Sequence
Charging Station CSMS
| |
| [critical security event occurs] |
| |
| SecurityEventNotificationRequest() |
|------------------------------------->|
| |
| [log & alert] |
| |
| SecurityEventNotificationResponse() |
|<-------------------------------------|
| |Step 1: Receive SecurityEventNotificationRequest (CS → CSMS)
| Field | Type | Required | Description |
|---|---|---|---|
type | string (max 50) | Required | Security event type identifier (from Appendix 1 of Part 2). |
timestamp | dateTime (RFC 3339) | Required | Date and time at which the event occurred. |
techInfo | string (max 255) | Optional | Additional technical information about the occurred security event. |
Step 2: Process the Security Event
The CSMS SHALL [A04.FR.03]:
- Log the event with the event type, timestamp, and any technical information.
- Classify severity based on the event type (see known security event types below).
- Trigger alerts for critical events that require operator intervention.
- Take automated action where appropriate (e.g., for InvalidChargingStationCertificate, consider re-running A02).
Step 3: Send SecurityEventNotificationResponse (CSMS → CS)
[A04.FR.03] The CSMS SHALL confirm receipt. The response body is empty:
{
"type": "FirmwareUpdated",
"timestamp": "2025-06-15T14:30:00.000Z",
"techInfo": "Firmware updated to version 2.3.1"
}// Empty object. No required fields.
{}Known Security Event Types
| Event Type | Critical | Description | Recommended CSMS Action |
|---|---|---|---|
FirmwareUpdated | Critical | Firmware has been updated | Log, verify firmware version |
FailedToAuthenticateAtCsms | Critical | CS failed to authenticate to CSMS | Investigate connection / certificate issues |
CentralSystemFailedToAuthenticate | Critical | CSMS failed to authenticate to CS | Check CSMS certificate validity |
SettingSystemTime | Critical | System time was changed | Verify time accuracy, could indicate attack |
StartupOfTheDevice | Critical | CS has booted | Track availability |
ResetOrReboot | Critical | CS was reset | Track stability |
SecurityLogWasCleared | Critical | Security log cleared | Potential evidence tampering |
ReconfigurationOfSecurityParameters | Critical | Security config changed | Verify authorized change |
MemoryExhaustion | Critical | Memory exhausted | Monitor health |
InvalidMessages | Critical | Invalid OCPP messages received | Possible attack |
AttemptedReplayAttacks | Critical | Replay attack detected | Security investigation |
TamperDetectionActivated | Critical | Physical tamper detected | Dispatch field service |
InvalidFirmwareSignature | Critical | Firmware signature check failed | Possible malicious firmware |
InvalidFirmwareSigningCertificate | Critical | Firmware signing cert invalid | Investigate certificate chain |
InvalidCsmsCertificate | Critical | CSMS cert rejected by CS | Check CSMS certificate |
InvalidChargingStationCertificate | Critical | CS cert is invalid | Trigger A02 |
InvalidTLSVersion | Critical | TLS version mismatch | Update TLS configuration |
InvalidTLSCipherSuite | Critical | Cipher suite rejected | Update cipher suite configuration |
DiscardedRenewedClientCertificate | Non-critical | CS discarded new cert after A02/A03 | Re-trigger certificate update |
Important Behavior Notes
| Req ID | Note |
|---|---|
A04.FR.02 | Security event notifications are queued with guaranteed delivery. If the CS is disconnected, it will send them when reconnected. The CSMS may receive events from the past. |
A04.FR.03 | The CSMS SHALL confirm receipt by sending SecurityEventNotificationResponse. |
A04.FR.04 | The CS stores all security events (including non-critical) in a local security log. |
7. A05 — Upgrade Charging Station Security Profile
CSMS-InitiatedThe CSMS upgrades the security profile of the OCPP connection (e.g., from Profile 1 to Profile 2, or Profile 2 to Profile 3). Typically used when migrating from OCPP 1.6 or upgrading field-deployed stations.
Note: Downgrading to Profile 1 is always rejected (even if AllowSecurityProfileDowngrade is true).
Downgrade from Profile 3 to Profile 2 is only allowed if AllowSecurityProfileDowngrade is true.
Prerequisites
- A
NetworkConnectionProfilewith the target security profile has been configured. - For upgrading to Profile 2 or 3: A valid CSMSRootCertificate is installed on the CS.
- For upgrading to Profile 3: A valid ChargingStationCertificate is installed on the CS.
- The prerequisites for the new security profile are met.
Flow Sequence
Operator CSMS Charging Station
| | |
| Change Config | |
|--------------->| |
| | |
| | SetVariablesRequest |
| | (NetworkConfigurationPriority) |
| |--------------------------------->|
| | |
| | SetVariablesResponse |
| | (status: RebootRequired/Accepted)|
| |<---------------------------------|
| | |
| | ResetRequest(OnIdle) |
| |--------------------------------->|
| | |
| | ResetResponse(Accepted) |
| |<---------------------------------|
| | |
| | [Reboot] |
| | |
| | [Connect using new profile] |
| | |
| | BootNotificationRequest(...) |
| |<---------------------------------|
| | |
| | BootNotificationResponse(...) |
| |--------------------------------->|
| | |CSMS Actions — Step by Step
Step 1: Set the NetworkConfigurationPriority (CSMS → CS)
The CSMS sends a SetVariablesRequest to reorder the NetworkConfigurationPriority so the new security profile becomes primary.
The attributeValue is a comma-separated list of configuration slot numbers,
where the first slot has the highest priority.
{
"setVariableData": [
{
"component": {
"name": "OCPPCommCtrlr"
},
"variable": {
"name": "NetworkConfigurationPriority"
},
"attributeValue": "2,1"
}
]
}Step 2: Handle SetVariablesResponse (CS → CSMS)
| attributeStatus | CSMS Action |
|---|---|
Accepted | Proceed to Step 3 (send ResetRequest). |
RebootRequired | Proceed to Step 3 (send ResetRequest). |
Rejected | Profile change denied. Check prerequisites (certificates installed?). |
Validation rules the CS enforces: [A05.FR.02] If upgrading to Profile 2/3 and no valid CSMSRootCertificate is installed: CS responds Rejected. [A05.FR.03] If upgrading to Profile 3 and no valid ChargingStationCertificate is installed: CS responds Rejected. [A05.FR.04] If all prerequisites are met: CS responds Accepted.
Step 3: Send ResetRequest (CSMS → CS)
Use OnIdle to avoid interrupting active charging sessions.
{
"type": "OnIdle"
}| Response status | CSMS Action |
|---|---|
Accepted | CS will reboot. Prepare to accept reconnection on the new security profile endpoint/port. |
Rejected | CS cannot reset now. Retry later. |
Scheduled | CS will reset when idle. Wait. |
Step 4: Accept Reconnection on New Profile
After reboot:
- [A05.FR.05] The CS will connect using the first entry in
NetworkConfigurationPriority(the new, higher security profile). - [A05.FR.06] The CS will update its
SecurityProfileconfig variable and remove all NetworkConnectionProfiles with a lower security profile. - [A05.FR.07] The CSMS SHALL NOT allow the CS to connect with a lower security profile anymore.
The CSMS receives a BootNotificationRequest from the CS on the new profile endpoint. Handle it normally.
Security Profile Downgrade Rules
| Current Profile | Target Profile | AllowSecurityProfileDowngrade | Result |
|---|---|---|---|
| 3 | 2 | true | Allowed [A05.FR.08] |
| 3 | 1 | true | Rejected [A05.FR.09] |
| 3 | 1 | false | Rejected [A05.FR.10] |
| 2 | 1 | Any | Rejected [A05.FR.09] |
| Any | Lower | false / not implemented | Rejected [A05.FR.10] |
8. Certificate Management Reference
ReferenceOCPP 2.1 provides messages for managing root certificates on Charging Stations. The CSMS can install, query, and delete certificates.
Certificate Types in OCPP
| Certificate | Private Key At | Purpose |
|---|---|---|
| CSMS Certificate | CSMS | Authenticate the CSMS to Charging Stations (TLS server cert) |
| Charging Station Certificate | Charging Station | Authenticate the CS to the CSMS (TLS client cert, Profile 3) |
| Firmware Signing Certificate | Manufacturer | Verify firmware image integrity and source |
| SECC Certificate | Charging Station | TLS connection between CS and EV (ISO 15118) |
Certificate Hierarchies
OCPP supports two separate certificate hierarchies:
1. Charging Station Operator (CSO) Hierarchy
Contains the CSMS and Charging Station certificates. The CSO MAY act as its own CA.
2. Manufacturer Hierarchy
Contains the Firmware Signing certificate. A trusted third party SHOULD be the CA.
InstallCertificateRequest (CSMS → CS)
Used to install root CA certificates on the Charging Station.
{
"certificateType": "CSMSRootCertificate",
"certificate": "-----BEGIN CERTIFICATE-----\n<PEM-encoded-root-cert>\n-----END CERTIFICATE-----"
}{
"status": "Accepted"
}| certificateType Values | Description |
|---|---|
V2GRootCertificate | V2G root CA certificate |
MORootCertificate | Mobility Operator root CA certificate |
ManufacturerRootCertificate | Manufacturer root CA certificate |
CSMSRootCertificate | CSMS root CA certificate |
OEMRootCertificate | OEM root CA certificate |
| Response status | Meaning |
|---|---|
Accepted | Certificate installed successfully |
Rejected | CS rejected the certificate (invalid, not trusted) |
Failed | Installation failed (storage error, etc.) |
GetInstalledCertificateIdsRequest (CSMS → CS)
Used to query which certificates are installed on a Charging Station.
{
"certificateType": [
"CSMSRootCertificate",
"V2GRootCertificate"
]
}
// Omit certificateType to get all types{
"status": "Accepted",
"certificateHashDataChain": [
{
"certificateType": "CSMSRootCertificate",
"certificateHashData": {
"hashAlgorithm": "SHA256",
"issuerNameHash": "...",
"issuerKeyHash": "...",
"serialNumber": "..."
},
"childCertificateHashData": []
}
]
}| Queryable certificateType Values | Description |
|---|---|
V2GRootCertificate | V2G root CA certificate |
MORootCertificate | Mobility Operator root CA certificate |
CSMSRootCertificate | CSMS root CA certificate |
V2GCertificateChain | Full V2G certificate chain |
ManufacturerRootCertificate | Manufacturer root CA certificate |
OEMRootCertificate | OEM root CA certificate |
| Response status | Meaning |
|---|---|
Accepted | Certificates found, data returned in certificateHashDataChain |
NotFound | No certificates of the requested type found |
DeleteCertificateRequest (CSMS → CS)
Used to remove a certificate from the Charging Station. The certificate is identified by its hash data.
{
"certificateHashData": {
"hashAlgorithm": "SHA256",
"issuerNameHash": "...",
"issuerKeyHash": "...",
"serialNumber": "..."
}
}{
"status": "Accepted"
}| Response status | Meaning |
|---|---|
Accepted | Certificate deleted successfully |
Failed | Deletion failed |
NotFound | Certificate not found |
9. Shared Data Types Reference
ReferenceCommon data types used across multiple security-related OCPP 2.1 messages.
CertificateHashDataType
Used across multiple messages to identify certificates by hash.
{
"hashAlgorithm": "SHA256 | SHA384 | SHA512",
"issuerNameHash": "string (max 128)",
"issuerKeyHash": "string (max 128)",
"serialNumber": "string (max 40)"
}
// All four fields are required| Field | Type | Description |
|---|---|---|
hashAlgorithm | enum: SHA256, SHA384, SHA512 | Hash algorithm used |
issuerNameHash | string (max 128) | Hash of the issuer's distinguished name (DN), calculated over the DER encoding of the issuer's name field |
issuerKeyHash | string (max 128) | Hash of the DER encoded public key (value excluding tag and length) of the subject public key field in the issuer's certificate |
serialNumber | string (max 40) | Hex representation of the serial number without '0x' prefix and without leading zeroes |
StatusInfoType
Used in many response messages to provide additional status details.
{
"reasonCode": "string (max 20)", // Required. Predefined code, case-insensitive.
"additionalInfo": "string (max 1024)" // Optional. Additional text with detailed information.
}CustomDataType
Present in all OCPP 2.1 messages. Allows vendor-specific extensions.
{
"vendorId": "string (max 255)" // Required. Vendor identifier for the custom data.
}Enumerations Quick Reference
CertificateSigningUseEnumType
| Value | Description |
|---|---|
ChargingStationCertificate | CS-to-CSMS connection certificate |
V2GCertificate | ISO 15118-2 certificate |
V2G20Certificate | ISO 15118-20 certificate |
InstallCertificateUseEnumType
| Value | Description |
|---|---|
V2GRootCertificate | V2G root CA certificate |
MORootCertificate | Mobility Operator root CA certificate |
ManufacturerRootCertificate | Manufacturer root CA certificate |
CSMSRootCertificate | CSMS root CA certificate |
OEMRootCertificate | OEM root CA certificate |
GetCertificateIdUseEnumType
| Value | Description |
|---|---|
V2GRootCertificate | V2G root CA certificate |
MORootCertificate | Mobility Operator root CA certificate |
CSMSRootCertificate | CSMS root CA certificate |
V2GCertificateChain | Full V2G certificate chain |
ManufacturerRootCertificate | Manufacturer root CA certificate |
OEMRootCertificate | OEM root CA certificate |
MessageTriggerEnumType (security-relevant values)
| Value | Description |
|---|---|
SignChargingStationCertificate | Trigger CS to generate CSR for its OCPP certificate |
SignV2GCertificate | Trigger CS to generate CSR for V2G (ISO 15118-2) certificate |
SignV2G20Certificate | Trigger CS to generate CSR for V2G (ISO 15118-20) certificate |
SignCombinedCertificate | Trigger CS to generate CSR for a combined certificate |
HashAlgorithmEnumType
| Value | Description |
|---|---|
SHA256 | SHA-256 hash algorithm |
SHA384 | SHA-384 hash algorithm |
SHA512 | SHA-512 hash algorithm |
10. Message Schema Reference
Protocol10.1 SetVariablesRequest (CSMS → CS)
Used in A01 to update BasicAuthPassword and in A05 to update NetworkConfigurationPriority.
{
"setVariableData": [
{
"attributeType": "Actual | Target | MinSet | MaxSet",
"attributeValue": "string (max 2500)",
"component": {
"name": "string (max 50)",
"instance": "string (max 50, optional)",
"evse": {
"id": "integer (min 0)",
"connectorId": "integer (min 0, optional)"
}
},
"variable": {
"name": "string (max 50)",
"instance": "string (max 50, optional)"
}
}
]
}
// Required: setVariableData (array, minItems 1)
// Per item: attributeValue, component.name, variable.name{
"setVariableResult": [
{
"attributeType": "Actual | Target | MinSet | MaxSet",
"attributeStatus": "Accepted | Rejected | UnknownComponent
| UnknownVariable
| NotSupportedAttributeType
| RebootRequired",
"attributeStatusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024, optional)"
},
"component": { "name": "string (max 50)" },
"variable": { "name": "string (max 50)" }
}
]
}
// Required: setVariableResult (array, minItems 1)
// Per item: attributeStatus, component.name, variable.name10.2 TriggerMessageRequest (CSMS → CS)
Used in A02 to request the CS to generate a CSR.
{
"requestedMessage":
"BootNotification | LogStatusNotification
| FirmwareStatusNotification | Heartbeat
| MeterValues | SignChargingStationCertificate
| SignV2GCertificate | SignV2G20Certificate
| SignCombinedCertificate | StatusNotification
| TransactionEvent
| PublishFirmwareStatusNotification",
"evse": {
"id": "integer",
"connectorId": "integer (optional)"
}
}
// Required: requestedMessage
// evse: optional, used for per-EVSE V2G certificate triggers{
"status": "Accepted | Rejected | NotImplemented",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024, optional)"
}
}
// Required: status10.3 SignCertificateRequest (CS → CSMS)
Sent by the CS in A02 (after TriggerMessage) and A03 (autonomously). Contains the Certificate Signing Request (CSR) for the CSMS to forward to the CA.
{
"csr": "string (max 5500, PEM-encoded CSR)",
"certificateType":
"ChargingStationCertificate | V2GCertificate
| V2G20Certificate",
"hashRootCertificate": {
"hashAlgorithm": "SHA256 | SHA384 | SHA512",
"issuerNameHash": "string (max 128)",
"issuerKeyHash": "string (max 128)",
"serialNumber": "string (max 40)"
},
"requestId": "integer"
}
// Required: csr
// certificateType: optional — when omitted, cert is for
// both 15118 and OCPP connection
// hashRootCertificate: optional — identifies the CA
// requestId: optional (2.1) — for correlation{
"status": "Accepted | Rejected",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024, optional)"
}
}
// Required: status10.4 CertificateSignedRequest (CSMS → CS)
Sent by the CSMS in both A02 and A03 after the CA signs the certificate. Delivers the signed certificate chain to the Charging Station.
{
"certificateChain":
"string (max 10000, PEM-encoded chain)",
"certificateType":
"ChargingStationCertificate | V2GCertificate
| V2G20Certificate",
"requestId": "integer"
}
// Required: certificateChain
// certificateType: should match SignCertificateRequest
// requestId: (2.1) must match SignCertificateRequest{
"status": "Accepted | Rejected",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024, optional)"
}
}
// Required: status10.5 SecurityEventNotificationRequest (CS → CSMS)
Sent by the CS in A04 to report a security-relevant event.
{
"type": "string (max 50)",
"timestamp": "dateTime (RFC 3339)",
"techInfo": "string (max 255, optional)"
}
// Required: type, timestamp{}
// Empty object. No fields required.10.6 InstallCertificateRequest (CSMS → CS)
Used to install root CA certificates on a Charging Station.
{
"certificateType":
"V2GRootCertificate | MORootCertificate
| CSMSRootCertificate
| ManufacturerRootCertificate
| OEMRootCertificate",
"certificate":
"string (max 10000, PEM-encoded X.509 certificate)"
}
// Required: certificateType, certificate{
"status": "Accepted | Rejected | Failed",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024, optional)"
}
}
// Required: status10.7 GetInstalledCertificateIdsRequest (CSMS → CS)
Used to query which certificates are installed on a Charging Station.
{
"certificateType": [
"V2GRootCertificate | MORootCertificate
| CSMSRootCertificate | V2GCertificateChain
| ManufacturerRootCertificate
| OEMRootCertificate"
]
}
// certificateType: optional array (minItems 1)
// Omit to get all types{
"status": "Accepted | NotFound",
"certificateHashDataChain": [
{
"certificateType": "...",
"certificateHashData": {
"hashAlgorithm": "SHA256 | SHA384 | SHA512",
"issuerNameHash": "string (max 128)",
"issuerKeyHash": "string (max 128)",
"serialNumber": "string (max 40)"
},
"childCertificateHashData": [ ... ]
}
]
}
// Required: status10.8 DeleteCertificateRequest (CSMS → CS)
Used to remove a certificate from the Charging Station.
{
"certificateHashData": {
"hashAlgorithm": "SHA256 | SHA384 | SHA512",
"issuerNameHash": "string (max 128)",
"issuerKeyHash": "string (max 128)",
"serialNumber": "string (max 40)"
}
}
// Required: certificateHashData{
"status": "Accepted | Failed | NotFound",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024, optional)"
}
}
// Required: status10.9 ResetRequest (CSMS → CS)
Used in A05 to reset the Charging Station after a security profile upgrade.
{
"type": "Immediate | OnIdle | ImmediateAndResume",
"evseId": "integer (min 0, optional)"
}
// Required: type
// evseId: optional — reset a specific EVSE
// instead of the entire station{
"status": "Accepted | Rejected | Scheduled",
"statusInfo": {
"reasonCode": "string (max 20)",
"additionalInfo": "string (max 1024, optional)"
}
}
// Required: status