OCPP 2.1 Edition 2 Section M

Certificate Management - CSMS Developer Guide

Based on OCPP 2.1 Edition 2 Specification (Part 2), Section M (Certificate Management). This guide covers all certificate lifecycle operations (M01–M07), including ISO 15118 Plug & Charge certificate installation and update, certificate retrieval, deletion, CA certificate installation, and OCSP/CRL status checking from the CSMS perspective.

12 Sections
7 Use Cases
M01 – M07

1. Overview

Introduction

The Certificate Management functional block handles all certificate lifecycle operations between the CSMS and Charging Stations. It supports ISO 15118 Plug & Charge (PnC) with seamless X.509 certificate authentication, TLS certificate management for installing, updating, and deleting root CA certificates, and OCSP/CRL status checking for validating certificate revocation status on behalf of Charging Stations.

CSMS Roles

The CSMS plays two distinct roles depending on the message flow:

Role Description Flows
Responder Charging Station sends a request, CSMS responds M01, M02, M06, M07
Initiator CSMS sends a request to Charging Station M03, M04, M05

ISO 15118 Plug & Charge

Seamless authentication using X.509 certificates stored in the EV, eliminating the need for RFID cards or other external identification means.

TLS Certificate Management

Installing, updating, and deleting root CA certificates and Charging Station certificates to maintain secure communications.

OCSP/CRL Status Checking

Validating certificate revocation status on behalf of Charging Stations using OCSP responders and Certificate Revocation Lists.

Certificate Lifecycle

Complete management of certificate installation, retrieval, deletion, and status verification across the charging infrastructure.

2. Certificate Types & PKI Structure

Reference

The CSMS must understand and manage multiple certificate types that form the PKI trust hierarchy for secure EV charging.

Certificate Types

Type Description Used For
V2GChargingStationCertificate Certificate of the Charging Station (SECC/EVSE Leaf Certificate in ISO 15118). Used for TLS between EV and Charging Station. EV-CS TLS
V2GRootCertificate Root certificate of the ISO 15118 V2G Root CA. The V2G Charging Station Certificate MUST be derived from this root. PnC authentication
MORootCertificate Root certificate from an eMobility Service Provider. Supports PnC with contracts from providers not derived from V2G root. PnC authentication
CSMSRootCertificate Root certificate used by the Charging Station to validate the CSMS server certificate in TLS. CS-CSMS TLS
ManufacturerRootCertificate Root certificate from the Charging Station manufacturer. Used for signed firmware validation. Firmware mgmt
OEMRootCertificate Root certificate from the car manufacturer (OEM). PnC authentication
V2GIntermediateCertificate Intermediate certificates between V2GChargingStationCertificate and V2GRootCertificate. EV-CS TLS setup

PKI Hierarchy

Four PKIs are involved in ISO 15118:

1. CSO (Charging Station Operator)

Trust anchor: V2G Root CA

2. CPS (Certificate Provisioning Service)

Trust anchor: V2G Root CA

3. MO (Mobility Operator)

May operate own Root CA or derive from V2G Root CA

4. OEM (Car Manufacturer)

May operate own Root CA or derive from V2G Root CA

Certificate-to-Use-Case Mapping

Certificate Use Cases Remarks
ChargingStationCertificate A02, A03 Used for OCPP security; chain must also be available
CPS Certificate Chain M03, M04, M05 For Plug & Charge authentication
EVContractCertificate M01, M02 Shorter lifetime (for plug & charge)
MORootCertificate M03, M04, M05 For Plug & Charge authentication
OEMProvisioningCertificate M01, M02 Long lifetime, installed in EV by OEM
V2GChargingStationCertificate A02, A03 Chain must be available; retrievable by CS
V2GRootCertificate M03, M04, M05 Only necessary to install for PnC authentication
V2GIntermediateCertificate A02, A03, M03, M04 Between V2GChargingStationCertificate and V2GRootCertificate

3. Message Direction Summary

Reference
Message Direction CSMS Role Use Case
Get15118EVCertificateRequest CS → CSMS Respond with Get15118EVCertificateResponse M01, M02
GetInstalledCertificateIdsRequest CSMS → CS Send request, handle GetInstalledCertificateIdsResponse M03
DeleteCertificateRequest CSMS → CS Send request, handle DeleteCertificateResponse M04
InstallCertificateRequest CSMS → CS Send request, handle InstallCertificateResponse M05
GetCertificateStatusRequest CS → CSMS Respond with GetCertificateStatusResponse M06
GetCertificateChainStatusRequest CS → CSMS Respond with GetCertificateChainStatusResponse M07
SignCertificateRequest CS → CSMS Respond with SignCertificateResponse, then send CertificateSignedRequest A02, A03
CertificateSignedRequest CSMS → CS Send signed certificate, handle CertificateSignedResponse A02, A03

4. M01 — Certificate Installation EV

CS-Initiated
Use Case ID M01
Name Certificate Installation
Objective Install a new certificate from the CSMS in the EV
Direction CS → CSMS (CS initiates)
CSMS Role Responder — receives Get15118EVCertificateRequest, responds with Get15118EVCertificateResponse

Flow Diagram

Sequence Diagram (CSMS perspective)
EV                    Charging Station                  CSMS
 |                          |                             |
 |  CertificateInstallReq() |                             |
 |------------------------->|                             |
 |                          |  Get15118EVCertificateReq    |
 |                          |  (iso15118SchemaVersion,     |
 |                          |   action=Install, exiReq)    |
 |                          |---------------------------->|
 |                          |                             | Forward to Contract
 |                          |                             | Certificate Pool(s)
 |                          |                             |
 |                          |  Get15118EVCertificateRes    |
 |                          |  (status, exiResponse)       |
 |                          |<----------------------------|
 |  CertificateInstallRes() |                             |
 |<-------------------------|                             |

Incoming Request: Get15118EVCertificateRequest

The Charging Station forwards this when an EV initiates certificate installation during an ISO 15118 session.

Get15118EVCertificateRequest Schema
{
  "iso15118SchemaVersion": "string (max 50)",
    // REQUIRED - Schema version for the 15118 session between EV and CS.
    // Needed for parsing the EXI stream.

  "action": "Install | Update",
    // REQUIRED - For M01, this will be "Install".

  "exiRequest": "string (max 11000)",
    // REQUIRED - Raw CertificateInstallationReq from EV, Base64 encoded.
    // Min supported length: 11000.
    // Configurable via OCPPCommCtrlr.FieldLength

  "maximumContractCertificateChains": "integer (>= 0)",
    // (2.1) ABSENT during ISO 15118-2 session.
    // REQUIRED during ISO 15118-20 session.
    // Maximum number of contracts the EV wants to install.

  "prioritizedEMAIDs": ["string (max 255)", ...],
    // (2.1) ABSENT during ISO 15118-2. OPTIONAL during ISO 15118-20.
    // EMAIDs for which contract certificates must be requested first.
    // Min: 1, Max: 8 items
}

CSMS Response: Get15118EVCertificateResponse

Get15118EVCertificateResponse Schema
{
  "status": "Accepted | Failed",
    // REQUIRED - Whether the message was processed properly.

  "statusInfo": {                    // OPTIONAL
    "reasonCode": "string (max 20)",
    "additionalInfo": "string (max 1024)"
  },

  "exiResponse": "string (max 17000)",
    // REQUIRED - Raw CertificateInstallationRes for the EV, Base64 encoded.
    // Min supported length: 17000.
    // Configurable via OCPPCommCtrlr.FieldLength

  "remainingContracts": "integer (>= 0)"
    // (2.1) Number of contracts that can be retrieved with additional
    // requests. Used for ISO 15118-20 multi-contract flow.
}

CSMS Implementation Logic

CSMS Handler Pseudocode
HANDLE Get15118EVCertificateRequest(request):
    ASSERT request.action == "Install"

    // 1. Parse the EXI request
    //    Use request.iso15118SchemaVersion to determine the correct parser

    // 2. Forward to Contract Certificate Pool / secondary actor
    //    The CSMS is responsible for forwarding the CertificateInstallationRequest
    //    to the appropriate backend (e.g., contract certificate pool per VDE-AR-E 2802-100-1)

    // 3. Determine ISO 15118 version from presence of maximumContractCertificateChains
    IF request.maximumContractCertificateChains IS PRESENT:
        // ISO 15118-20 session
        isISO15118_20 = true
    ELSE:
        // ISO 15118-2 session
        isISO15118_20 = false

    // 4. For ISO 15118-20: Handle multi-contract flow
    IF isISO15118_20:
        // Fetch contracts from all Contract Certificate Pools
        // Respect prioritizedEMAIDs ordering if present
        // Return first CertificateInstallationRes + total remainingContracts
        response.remainingContracts = totalAvailableContracts - 1

        // The CS will send additional Get15118EVCertificateRequest messages
        // as long as remainingContracts > 0 (see req M01.FR.06)
        // Each subsequent response MUST decrease remainingContracts by 1 (req M01.FR.07)

    // 5. Build response
    response.status = "Accepted"  // or "Failed" if processing failed
    response.exiResponse = base64EncodedCertificateInstallationRes

    RETURN response

Requirements (CSMS-relevant)

ID Requirement
M01.FR.04 When maximumContractCertificateChains is present AND CSMS has received all CertificateInstallationRes from the certificate pool(s): CSMS SHALL return the first CertificateInstallationRes and total number of available contracts in remainingContracts.
M01.FR.07 When ISO 15118-20 AND CS sends another Get15118EVCertificateRequest (because remainingContracts > 0): CSMS SHALL return the next CertificateInstallationRes and decrease remainingContracts by 1.

Error Handling

  • If the CSMS cannot respond in time, the Charging Station SHALL indicate failure to the EV.
  • The ISO 15118-2 message timeout for CertificateInstallationReq is 5 seconds.

5. M02 — Certificate Update EV

CS-Initiated
Use Case ID M02
Name Certificate Update
Objective Update an existing certificate in the EV via the CSMS
Direction CS → CSMS (CS initiates)
CSMS Role Responder — receives Get15118EVCertificateRequest with action = Update, responds with Get15118EVCertificateResponse

Flow Diagram

Sequence Diagram (CSMS perspective)
EV                    Charging Station                  CSMS
 |                          |                             |
 |  CertificateUpdateReq()  |                             |  [ISO 15118-2]
 |     -- OR --             |                             |
 |  CertificateInstallReq() |                             |  [ISO 15118-20]
 |------------------------->|                             |
 |                          |  Get15118EVCertificateReq    |
 |                          |  (iso15118SchemaVersion,     |
 |                          |   action=Update, exiReq)     |
 |                          |---------------------------->|
 |                          |                             | Forward to Contract
 |                          |                             | Certificate Pool
 |                          |  Get15118EVCertificateRes    |
 |                          |  (status, exiResponse)       |
 |                          |<----------------------------|
 |  CertificateUpdateRes()  |                             |
 |<-------------------------|                             |

Shared Message Schemas

The message schemas are identical to M01. The only difference is the action field:

  • M01 (Install): action = "Install"
  • M02 (Update): action = "Update"

For ISO 15118-2: The Charging Station sends action = Update upon receiving a CertificateUpdateReq from the EV. For ISO 15118-20: ISO 15118-20 does not differentiate between Install and Update; the Charging Station acts according to M01 (req M02.FR.02).

CSMS Implementation Logic

CSMS Handler Pseudocode
HANDLE Get15118EVCertificateRequest(request):
    IF request.action == "Update":
        // Forward to the secondary actor (contract certificate pool)
        // which will process the CertificateUpdateRequest
        // The CSMS is responsible for forwarding it to the appropriate backend

        response.status = "Accepted"
        response.exiResponse = base64EncodedCertificateUpdateRes
        RETURN response

    IF request.action == "Install":
        // Handle as M01 (see above)

Requirements (CSMS-relevant)

ID Precondition Requirement
M02.FR.01 CS receives ISO 15118 CertificateUpdateReq AND EV uses ISO 15118-2 CS SHALL forward using Get15118EVCertificateRequest with action = Update. CSMS is responsible for forwarding to secondary actor.
M02.FR.02 CS receives ISO 15118 CertificateUpdateReq AND EV uses ISO 15118-20 CS SHALL act according to M01 (ISO 15118-20 does not differentiate Install/Update).

Error Handling

  • If CSMS cannot respond in time, the Charging Station SHALL indicate failure to the EV.
  • The ISO 15118-2 message timeout for CertificateUpdateReq is 5 seconds.

6. M03 — Retrieve Installed Certificates

CSMS-Initiated
Use Case ID M03
Name Retrieve list of available certificates from a Charging Station
Objective Enable the CSMS to retrieve a list of installed certificates from a Charging Station
Direction CSMS → CS (CSMS initiates)
CSMS Role Initiator — sends GetInstalledCertificateIdsRequest, handles GetInstalledCertificateIdsResponse

Flow Diagram

Sequence Diagram (CSMS perspective)
CSMS                              Charging Station
  |                                      |
  |  GetInstalledCertificateIdsRequest    |
  |  (certificateType)                   |
  |------------------------------------->|
  |                                      | Compute hashes and
  |                                      | list matching certs
  |  GetInstalledCertificateIdsResponse   |
  |  (status, certificateHashDataChain)  |
  |<-------------------------------------|

Outgoing Request: GetInstalledCertificateIdsRequest

GetInstalledCertificateIdsRequest Schema
{
  "certificateType": [
    "V2GRootCertificate" | "MORootCertificate" | "CSMSRootCertificate" |
    "V2GCertificateChain" | "ManufacturerRootCertificate" | "OEMRootCertificate"
  ]
    // OPTIONAL - Types of certificates requested.
    // When OMITTED, ALL certificate types are requested.
    // Min: 1 item
}

Note: There are no required fields. Omitting certificateType requests all certificates.

Incoming Response: GetInstalledCertificateIdsResponse

GetInstalledCertificateIdsResponse Schema
{
  "status": "Accepted | NotFound",
    // REQUIRED - Accepted = matching certificates found.
    // NotFound = no matching certificates.

  "statusInfo": {                    // OPTIONAL
    "reasonCode": "string (max 20)",
    "additionalInfo": "string (max 1024)"
  },

  "certificateHashDataChain": [      // OPTIONAL (present when status = Accepted)
    {
      "certificateType": "V2GRootCertificate | MORootCertificate | ...",
        // REQUIRED

      "certificateHashData": {       // REQUIRED - CertificateHashDataType
        "hashAlgorithm": "SHA256 | SHA384 | SHA512",
        "issuerNameHash": "string (max 128)",
        "issuerKeyHash": "string (max 128)",
        "serialNumber": "string (max 40)"
      },

      "childCertificateHashData": [  // OPTIONAL - Max 4 items
        {                            // Sub-CAs under a root
          "hashAlgorithm": "SHA256 | SHA384 | SHA512",
          "issuerNameHash": "string (max 128)",
          "issuerKeyHash": "string (max 128)",
          "serialNumber": "string (max 40)"
        }
      ]
    }
  ]
}

CSMS Implementation Logic

CSMS Implementation Pseudocode
FUNCTION retrieveInstalledCertificates(chargingStationId, certificateTypes):
    // 1. Build the request
    request = new GetInstalledCertificateIdsRequest()
    IF certificateTypes IS NOT EMPTY:
        request.certificateType = certificateTypes
    // If certificateTypes is empty/null, omit the field to get ALL types

    // 2. Send to Charging Station
    response = sendToChargingStation(chargingStationId, request)

    // 3. Handle response
    IF response.status == "Accepted":
        FOR EACH chain IN response.certificateHashDataChain:
            // Store certificate hash data for later use
            // (e.g., for DeleteCertificateRequest)
            storeCertificateInfo(
                chargingStationId,
                chain.certificateType,
                chain.certificateHashData,
                chain.childCertificateHashData  // may be null
            )
    ELSE IF response.status == "NotFound":
        // No matching certificates found on the Charging Station
        log("No certificates of requested type found on station " + chargingStationId)

    RETURN response

Requirements (CSMS-relevant)

ID Requirement
M03.FR.02 If no certificates matching certificateType are found, CS responds with status = NotFound.
M03.FR.03 If matching certificates found, CS responds with status = Accepted.
M03.FR.04 CS SHALL include hash data for each matching installed certificate.
M03.FR.05 When certificateType = V2GCertificateChain, CS SHALL include hash data for all certificates in the chain. Sub-CAs SHALL be placed as childCertificateHashData under the V2G Charging Station certificate.

Important Notes

  • For installing the V2G Charging Station Certificate, use A02/A03 (not M03). The V2G certificate chain SHOULD NOT include the V2GRootCertificate; install roots using M05.
  • Use the returned hash data to identify certificates for deletion (M04).

7. M04 — Delete Certificate

CSMS-Initiated
Use Case ID M04
Name Delete a specific certificate from a Charging Station
Objective Enable the CSMS to request the Charging Station to delete an installed certificate
Direction CSMS → CS (CSMS initiates)
CSMS Role Initiator — sends DeleteCertificateRequest, handles DeleteCertificateResponse

Flow Diagram

Sequence Diagram (CSMS perspective)
CSMS                              Charging Station
  |                                      |
  |  DeleteCertificateRequest             |
  |  (certificateHashData)               |
  |------------------------------------->|
  |                                      | Attempt to find
  |                                      | and delete cert
  |  DeleteCertificateResponse            |
  |  (status)                            |
  |<-------------------------------------|

Outgoing Request: DeleteCertificateRequest

DeleteCertificateRequest Schema
{
  "certificateHashData": {           // REQUIRED - CertificateHashDataType
    "hashAlgorithm": "SHA256 | SHA384 | SHA512",
      // REQUIRED - CSMS MUST use the SAME hashAlgorithm that the CS uses
      // to report the certificate in GetInstalledCertificateIdsResponse
      // (req M04.FR.07)

    "issuerNameHash": "string (max 128)",
      // REQUIRED - Hash of the issuer's distinguished name (DN),
      // calculated over the DER encoding of the issuer's name field.

    "issuerKeyHash": "string (max 128)",
      // REQUIRED - Hash of the DER encoded public key (value only,
      // excluding tag and length) of the subject public key field
      // in the issuer's certificate.

    "serialNumber": "string (max 40)"
      // REQUIRED - Hex string of the serial number,
      // without '0x' prefix and without leading zeroes.
  }
}

Incoming Response: DeleteCertificateResponse

DeleteCertificateResponse Schema
{
  "status": "Accepted | Failed | NotFound",
    // REQUIRED - Result of the delete operation.

  "statusInfo": {                    // OPTIONAL
    "reasonCode": "string (max 20)",
    "additionalInfo": "string (max 1024)"
  }
}

CSMS Implementation Logic

CSMS Implementation Pseudocode
FUNCTION deleteCertificate(chargingStationId, certificateHashData):
    // IMPORTANT: Before deleting, the CSMS SHOULD verify:

    // 1. DO NOT delete the Charging Station Certificate via this message.
    //    Deletion of the Charging Station Certificate is NOT allowed via
    //    DeleteCertificateRequest (req M04.FR.06). The CS will respond with Failed.

    // 2. Be VERY careful deleting the last/all CSMSRootCertificates.
    //    If all CSMSRootCertificates are deleted, the CS will NOT be able to
    //    connect to any CSMS (cannot validate server certificate).
    //    ADVISED: Confirm this is truly intended before proceeding.

    // 3. Use the SAME hashAlgorithm the CS reported in
    //    GetInstalledCertificateIdsResponse (req M04.FR.07)

    request = new DeleteCertificateRequest()
    request.certificateHashData = certificateHashData

    response = sendToChargingStation(chargingStationId, request)

    SWITCH response.status:
        CASE "Accepted":
            // Certificate was successfully deleted
            // Note: If deleted cert was a sub-CA or root, the CS MAY also
            //   delete all child certificates (req M04.FR.08)
            removeCertificateFromLocalStore(chargingStationId, certificateHashData)

        CASE "Failed":
            // Deletion failed. Possible reasons:
            //   - Certificate is the Charging Station Certificate (not deletable)
            //   - CS rejected deletion (last one of its type)
            //   - Internal CS error
            log("Delete failed: " + response.statusInfo?.reasonCode)

        CASE "NotFound":
            // Certificate not found on the Charging Station
            log("Certificate not found on station " + chargingStationId)

    RETURN response

Requirements (CSMS-relevant)

ID Precondition Requirement
M04.FR.02 Certificate found CS responds status = Accepted.
M04.FR.03 Deletion fails or CS rejects CS responds status = Failed. A CS MAY reject to prevent deleting the last one of its type.
M04.FR.04 Certificate not found CS responds status = NotFound.
M04.FR.06 certificateHashData refers to the Charging Station Certificate CS SHALL respond status = Failed. CSMS must NOT attempt to delete the CS certificate this way.
M04.FR.07 When deleting a certificate CSMS SHALL use the same hashAlgorithm as the CS uses to report the certificate in GetInstalledCertificateIdsResponse.
M04.FR.08 Deleted cert is a sub-CA or root CS MAY also delete all child certificates.

Warnings

  • Deleting all ManufacturerRootCertificates prevents "Signed Firmware" from being installed.
  • Deleting all CSMSRootCertificates will sever the CS's ability to connect to any CSMS.
  • Always run M03 first to retrieve current certificates and their hash data before attempting deletion.

8. M05 — Install CA Certificate

CSMS-Initiated
Use Case ID M05
Name Install CA certificate in a Charging Station
Objective Install a new CSMS root, MO root, Manufacturer root, or V2G root certificate on the Charging Station
Direction CSMS → CS (CSMS initiates)
CSMS Role Initiator — sends InstallCertificateRequest, handles InstallCertificateResponse

Flow Diagram

Sequence Diagram (CSMS perspective)
CSMS                              Charging Station
  |                                      |
  |  InstallCertificateRequest            |
  |  (certificateType, certificate)      |
  |------------------------------------->|
  |                                      | Attempt to install
  |                                      | certificate in trust store
  |  InstallCertificateResponse           |
  |  (status)                            |
  |<-------------------------------------|

Outgoing Request: InstallCertificateRequest

InstallCertificateRequest Schema
{
  "certificateType": "V2GRootCertificate | MORootCertificate |
    ManufacturerRootCertificate | CSMSRootCertificate | OEMRootCertificate",
    // REQUIRED - Type of certificate being installed.

  "certificate": "string (max 10000)"
    // REQUIRED - PEM encoded X.509 certificate.
}

Incoming Response: InstallCertificateResponse

InstallCertificateResponse Schema
{
  "status": "Accepted | Rejected | Failed",
    // REQUIRED - Result of the installation.

  "statusInfo": {                    // OPTIONAL
    "reasonCode": "string (max 20)",
    "additionalInfo": "string (max 1024)"
  }
}

CSMS Implementation Logic

CSMS Implementation Pseudocode
FUNCTION installCACertificate(chargingStationId, certificateType, pemCertificate):
    request = new InstallCertificateRequest()
    request.certificateType = certificateType
    request.certificate = pemCertificate

    response = sendToChargingStation(chargingStationId, request)

    SWITCH response.status:
        CASE "Accepted":
            // Certificate successfully installed in the CS trust store
            // If it was already present, CS replaces it (req M05.FR.17)
            storeCertificateRecord(chargingStationId, certificateType, pemCertificate)

        CASE "Rejected":
            // Installation rejected. Possible reasons:
            //   - CertificateEntries.maxLimit would be exceeded (req M05.FR.06)
            //   - Certificate is invalid (req M05.FR.07)
            //   - For CSMSRootCertificate with AdditionalRootCertificateCheck=true:
            //     new cert is NOT signed by the old CSMS Root (req M05.FR.11)
            log("Install rejected: " + response.statusInfo?.reasonCode)

        CASE "Failed":
            // Installation failed due to internal CS error
            log("Install failed: " + response.statusInfo?.reasonCode)

    RETURN response

CSMS Root Certificate Rotation (Special Logic)

When AdditionalRootCertificateCheck is true on the Charging Station, special rules apply for CSMSRootCertificate installation:

CSMS Root Rotation Pseudocode
FUNCTION rotateCSMSRootCertificate(chargingStationId, newCertPEM):
    // req M05.FR.09: Only one CSMSRootCertificate can be installed at a time
    //   (plus a temporary fallback)

    // req M05.FR.10: The new CSMS Root certificate SHALL replace the old one
    //   AND the new Root Certificate MUST be signed by the old Root Certificate

    // req M05.FR.11: If NOT signed by old root -> CS responds Rejected

    // req M05.FR.12: If signed by old root -> CS installs new cert AND
    //   temporarily keeps old cert as fallback, responds Accepted

    // req M05.FR.13: After CS successfully reconnects using the new cert ->
    //   CS removes the old (fallback) certificate

    // req M05.FR.14: If CS cannot verify CSMS server cert with new root ->
    //   CS tries the old (fallback) root certificate

    response = installCACertificate(chargingStationId, "CSMSRootCertificate", newCertPEM)

    IF response.status == "Accepted":
        // The CS now has both old and new CSMS root certs temporarily
        // On next successful TLS connection with new cert, old is removed
        // CSMS should ensure its server certificate is signed by the new root

Requirements (CSMS-relevant)

ID Precondition Requirement
M05.FR.02 Installation successful CS responds status = Accepted.
M05.FR.03 Installation failed CS responds status = Failed.
M05.FR.06 CertificateEntries.maxLimit exceeded CS responds status = Rejected.
M05.FR.07 Certificate is invalid CS responds status = Rejected.
M05.FR.09 AdditionalRootCertificateCheck = true Only one CSMSRootCertificate (plus temp fallback) allowed at a time.
M05.FR.10 AdditionalRootCertificateCheck = true, installing CSMSRootCertificate New cert SHALL replace old; new cert MUST be signed by old root.
M05.FR.11 New cert NOT signed by old root CS SHALL NOT install; responds status = Rejected.
M05.FR.12 New cert IS signed by old root CS installs new, keeps old as fallback; responds status = Accepted.
M05.FR.17 Certificate already present in trust store CS SHALL replace and respond status = Accepted.

Important Notes

  • This message is for ROOT/CA certificates only. Do NOT use it for Charging Station leaf certificates. For that, use CertificateSignedRequest (use cases A02/A03).
  • Multiple certificates of the same type are allowed.
  • The V2G certificate chain SHOULD NOT include the V2GRootCertificate when installed via A02/A03; install roots using this use case (M05).

9. M06 — Get V2G Charging Station Certificate Status

CS-Initiated
Use Case ID M06
Name Get V2G Charging Station Certificate status
Objective Enable a Charging Station to cache the OCSP certificate status needed for the TLS handshake between EV and Charging Station
Direction CS → CSMS (CS initiates)
CSMS Role Responder — receives GetCertificateStatusRequest, responds with GetCertificateStatusResponse

Flow Diagram

Sequence Diagram (CSMS perspective)
Charging Station                    CSMS
      |                               |
      |  GetCertificateStatusRequest   |
      |  (ocspRequestData)            |
      |------------------------------>|
      |                               | Retrieve OCSP certificate
      |                               | status from OCSP responder
      |  GetCertificateStatusResponse  |
      |  (status, ocspResult)         |
      |<------------------------------|
      |                               |
      | Cache retrieved information   |
      |<---                           |

Incoming Request: GetCertificateStatusRequest

GetCertificateStatusRequest Schema
{
  "ocspRequestData": {               // REQUIRED - OCSPRequestDataType
    "hashAlgorithm": "SHA256 | SHA384 | SHA512",
      // REQUIRED

    "issuerNameHash": "string (max 128)",
      // REQUIRED - Hash of the issuer's distinguished name (DN), DER encoded.

    "issuerKeyHash": "string (max 128)",
      // REQUIRED - Hash of the DER encoded public key of the issuer.

    "serialNumber": "string (max 40)",
      // REQUIRED - Hex serial number without '0x' prefix or leading zeroes.

    "responderURL": "string (max 2000)"
      // REQUIRED - OCSP responder URL (case insensitive).
      // REQUIRED in OCPP (optional in ISO 15118).
  }
}

CSMS Response: GetCertificateStatusResponse

GetCertificateStatusResponse Schema
{
  "status": "Accepted | Failed",
    // REQUIRED - Whether the CSMS was successful in retrieving the OCSP status.
    // Does NOT indicate the validity of the certificate itself.

  "statusInfo": {                    // OPTIONAL
    "reasonCode": "string (max 20)",
    "additionalInfo": "string (max 1024)"
  },

  "ocspResult": "string (max 18000)"
    // OCSPResponse class per IETF RFC 6960, DER encoded then Base64 encoded.
    // MAY only be omitted when status is not Accepted.
    // Min supported length: 18000.
    // Configurable via OCPPCommCtrlr.FieldLength
}

CSMS Implementation Logic

CSMS Handler Pseudocode
HANDLE GetCertificateStatusRequest(request):
    ocspData = request.ocspRequestData

    // 1. Build OCSP request per RFC 6960 using the provided hash data
    ocspRequest = buildOCSPRequest(
        hashAlgorithm: ocspData.hashAlgorithm,
        issuerNameHash: ocspData.issuerNameHash,
        issuerKeyHash: ocspData.issuerKeyHash,
        serialNumber: ocspData.serialNumber
    )

    // 2. Send OCSP request to the responder URL
    TRY:
        ocspResponse = httpPost(ocspData.responderURL, ocspRequest)

        // 3. Format response per requirements:
        //    - OCSPResponse per IETF RFC 6960 (req M06.FR.08)
        //    - Formatted according to ASN.1 [X.680] (req M06.FR.08)
        //    - DER encoded (req M06.FR.09)
        //    - Then Base64 encoded for transmission
        derEncoded = ocspResponse.toDER()
        base64Result = base64Encode(derEncoded)

        response.status = "Accepted"      // req M06.FR.02
        response.ocspResult = base64Result // req M06.FR.03

    CATCH error:
        // OCSP retrieval failed
        response.status = "Failed"         // req M06.FR.04
        response.statusInfo = {
            reasonCode: "OCSPFetchFailed",
            additionalInfo: error.message
        }
        // ocspResult MAY be omitted when status != Accepted

    RETURN response

Requirements (CSMS-relevant)

ID Requirement
M06.FR.01 CSMS SHALL respond with GetCertificateStatusResponse.
M06.FR.02 If OCSP retrieval successful: set status = Accepted.
M06.FR.03 Include OCSP response data in ocspResult field.
M06.FR.04 If OCSP retrieval failed: set status = Failed.
M06.FR.08 Format OCSP response data per IETF RFC 6960, formatted according to ASN.1 [X.680].
M06.FR.09 OCSPResponse data SHALL be DER encoded.

Important Notes

  • The status field indicates whether the CSMS retrieved the OCSP status successfully. It does NOT indicate the validity of the certificate itself.
  • OCPP allows only one certificate per GetCertificateStatusRequest. One request needs to be sent per SubCA certificate.
  • responderURL is required in OCPP (while optional in ISO 15118). A certificate without a responderURL cannot be checked via this use case.
  • The Charging Station SHOULD refresh cached OCSP data at least once a week (req M06.FR.10).
  • After a Charging Station Certificate update, the CS SHALL refresh OCSP data for the new certificate and intermediates (req M06.FR.07).

10. M07 — Get Vehicle Certificate Chain Revocation Status

CS-Initiated New in 2.1
Use Case ID M07
Name Get Vehicle Certificate Chain Revocation Status
Objective Let the Charging Station check validity of the vehicle certificate chain using OCSP and CRL
Direction CS → CSMS (CS initiates)
CSMS Role Responder — receives GetCertificateChainStatusRequest, responds with GetCertificateChainStatusResponse

New in OCPP 2.1. Required by ISO 15118-20 during the TLS handshake. Results are allowed to be cached at CSMS or Charging Station for at most one week.

Flow Diagram

Sequence Diagram (CSMS perspective)
Charging Station                              CSMS
      |                                         |
      |  GetCertificateChainStatusRequest        |
      |  (certificateStatusRequests: [           |
      |    { certHashData, source:OCSP, urls },  |
      |    { certHashData, source:CRL, urls }    |
      |  ])                                      |
      |---------------------------------------->|
      |                                         | For each certificate:
      |                                         |   1. Check cached status
      |                                         |   2. If not cached, issue
      |                                         |      OCSP request or download CRL
      |  GetCertificateChainStatusResponse       |
      |  (certificateStatus: [                   |
      |    { certHashData, source, status,       |
      |      nextUpdate },                       |
      |    ...                                   |
      |  ])                                      |
      |<-----------------------------------------|
      |                                         |
      | Cache status for up to 1 week           |

Incoming Request: GetCertificateChainStatusRequest

GetCertificateChainStatusRequest Schema
{
  "certificateStatusRequests": [     // REQUIRED - Min: 1, Max: 4
    {
      "certificateHashData": {       // REQUIRED - CertificateHashDataType
        "hashAlgorithm": "SHA256 | SHA384 | SHA512",
        "issuerNameHash": "string (max 128)",
        "issuerKeyHash": "string (max 128)",
        "serialNumber": "string (max 40)"
      },

      "source": "CRL | OCSP",
        // REQUIRED - Whether to check via OCSP or CRL.

      "urls": ["string (max 2000)", ...]
        // REQUIRED - URL(s) of the OCSP responder or CRL distribution point.
        // Min: 1, Max: 5
    }
  ]
}

CSMS Response: GetCertificateChainStatusResponse

GetCertificateChainStatusResponse Schema
{
  "certificateStatus": [             // REQUIRED - Min: 1, Max: 4
    {
      "certificateHashData": {       // REQUIRED - echo back
        "hashAlgorithm": "SHA256 | SHA384 | SHA512",
        "issuerNameHash": "string (max 128)",
        "issuerKeyHash": "string (max 128)",
        "serialNumber": "string (max 40)"
      },

      "source": "CRL | OCSP",
        // REQUIRED - Source used for this status check.

      "status": "Good | Revoked | Unknown | Failed",
        // REQUIRED - Revocation status of the certificate.

      "nextUpdate": "date-time (ISO 8601)"
        // REQUIRED - When the status information will next be updated.
    }
  ]
}

CSMS Implementation Logic

CSMS Handler Pseudocode
HANDLE GetCertificateChainStatusRequest(request):
    results = []

    FOR EACH entry IN request.certificateStatusRequests:
        certHash = entry.certificateHashData
        source = entry.source
        urls = entry.urls

        // 1. Check local cache first
        cached = checkCache(certHash, source)
        IF cached IS NOT NULL AND cached.nextUpdate > now():
            results.add(cached)
            CONTINUE

        // 2. Not cached or expired - perform live check
        IF source == "OCSP":
            // req M07.FR.01: Perform OCSP request to one of the URLs
            result = performOCSPCheck(certHash, urls)

            IF result.success:
                // req M07.FR.03: Use the OCSP status (Good/Revoked/Unknown)
                results.add({
                    certificateHashData: certHash,
                    source: "OCSP",
                    status: result.ocspStatus,
                    nextUpdate: result.nextUpdate
                })
            ELSE:
                // req M07.FR.02: OCSP request failed
                results.add({
                    certificateHashData: certHash,
                    source: "OCSP",
                    status: "Failed",
                    nextUpdate: now() + 1hour
                })

        ELSE IF source == "CRL":
            // req M07.FR.04: Retrieve CRL from one of the URLs
            crl = downloadCRL(urls)

            IF crl IS NULL:
                // req M07.FR.05: CRL download failed
                results.add({
                    certificateHashData: certHash,
                    source: "CRL",
                    status: "Failed",
                    nextUpdate: now() + 1hour
                })
            ELSE:
                IF crl.contains(certHash.serialNumber):
                    // req M07.FR.06: Certificate is revoked
                    results.add({
                        certificateHashData: certHash,
                        source: "CRL",
                        status: "Revoked",
                        nextUpdate: crl.nextUpdate
                    })
                ELSE:
                    // req M07.FR.07: Certificate not in CRL -> Good
                    results.add({
                        certificateHashData: certHash,
                        source: "CRL",
                        status: "Good",
                        nextUpdate: crl.nextUpdate
                    })

        // Cache the result
        cacheResult(certHash, source, results.last())

    // req M07.FR.08: Respond with all results
    response.certificateStatus = results
    RETURN response

Example Request/Response

Example Request (two certificates: one via OCSP, one via CRL)
{
  "certificateStatusRequests": [
    {
      "certificateHashData": {
        "hashAlgorithm": "SHA256",
        "issuerNameHash": "12345ABCDE",
        "issuerKeyHash": "ABCDE1234",
        "serialNumber": "AB123456789"
      },
      "source": "OCSP",
      "urls": ["https://ocsp.responder.org/revoked.ocsp"]
    },
    {
      "certificateHashData": {
        "hashAlgorithm": "SHA256",
        "issuerNameHash": "ABCDE12345",
        "issuerKeyHash": "1234ABCDE",
        "serialNumber": "987634294239"
      },
      "source": "CRL",
      "urls": [
        "https://crls.com/revoked.crl",
        "ftp://ftp.crls.com/revoked.crl"
      ]
    }
  ]
}
Example Response
{
  "certificateStatus": [
    {
      "certificateHashData": {
        "hashAlgorithm": "SHA256",
        "issuerNameHash": "12345ABCDE",
        "issuerKeyHash": "ABCDE1234",
        "serialNumber": "AB123456789"
      },
      "source": "OCSP",
      "status": "Good",
      "nextUpdate": "2025-02-01T12:00Z"
    },
    {
      "certificateHashData": {
        "hashAlgorithm": "SHA256",
        "issuerNameHash": "ABCDE12345",
        "issuerKeyHash": "1234ABCDE",
        "serialNumber": "987634294239"
      },
      "source": "CRL",
      "status": "Good",
      "nextUpdate": "2025-02-01T12:00Z"
    }
  ]
}

Requirements (CSMS-relevant)

ID Precondition Requirement
M07.FR.01 source = OCSP CSMS SHALL perform OCSP request to one of the urls for certificateHashData of each certificate.
M07.FR.02 OCSP request fails CSMS SHALL use status = Failed for this certificate.
M07.FR.03 OCSP request succeeds CSMS SHALL use the OCSP status (Good/Revoked/Unknown) for status.
M07.FR.04 source = CRL CSMS SHALL retrieve CRL from one of the urls for certificateHashData of each certificate.
M07.FR.05 CRL download fails CSMS SHALL use status = Failed for this certificate.
M07.FR.06 CRL downloaded AND serialNumber IS in the CRL CSMS SHALL use status = Revoked.
M07.FR.07 CRL downloaded AND serialNumber is NOT in the CRL CSMS SHALL use status = Good.
M07.FR.08 All certificates checked CSMS SHALL respond with GetCertificateChainStatusResponse containing all results with certificateHashData, source, status, and nextUpdate.

11. Shared Data Types Reference

Reference

StatusInfoType

Used in many responses to provide additional status details.

StatusInfoType Schema
{
  "reasonCode": "string (max 20)",
    // REQUIRED - Predefined code for the reason. Case-insensitive.

  "additionalInfo": "string (max 1024)"
    // OPTIONAL - Free-text additional information.
}

CertificateHashDataType

Used to uniquely identify a certificate by its issuer's hash data and serial number.

CertificateHashDataType Schema
{
  "hashAlgorithm": "SHA256 | SHA384 | SHA512",
    // REQUIRED

  "issuerNameHash": "string (max 128)",
    // REQUIRED - Hash of the issuer's distinguished name (DN),
    // calculated over the DER encoding of the issuer's name field
    // in the certificate being checked.

  "issuerKeyHash": "string (max 128)",
    // REQUIRED - Hash of the DER encoded public key: the value
    // (excluding tag and length) of the subject public key field
    // in the issuer's certificate.

  "serialNumber": "string (max 40)"
    // REQUIRED - Hex string representation of the serial number
    // without '0x' prefix and without leading zeroes.
}

CustomDataType

Optional extension point for vendor-specific data. Present in all messages.

CustomDataType Schema
{
  "vendorId": "string (max 255)"
    // REQUIRED
}

Enum Reference

Enum Values Used In
CertificateActionEnum Install, Update Get15118EVCertificateRequest
Iso15118EVCertificateStatusEnum Accepted, Failed Get15118EVCertificateResponse
GetCertificateIdUseEnum V2GRootCertificate, MORootCertificate, CSMSRootCertificate, V2GCertificateChain, ManufacturerRootCertificate, OEMRootCertificate GetInstalledCertificateIdsRequest/Response
GetInstalledCertificateStatusEnum Accepted, NotFound GetInstalledCertificateIdsResponse
DeleteCertificateStatusEnum Accepted, Failed, NotFound DeleteCertificateResponse
InstallCertificateUseEnum V2GRootCertificate, MORootCertificate, ManufacturerRootCertificate, CSMSRootCertificate, OEMRootCertificate InstallCertificateRequest
InstallCertificateStatusEnum Accepted, Rejected, Failed InstallCertificateResponse
GetCertificateStatusEnum Accepted, Failed GetCertificateStatusResponse
HashAlgorithmEnum SHA256, SHA384, SHA512 Multiple messages
CertificateSigningUseEnum ChargingStationCertificate, V2GCertificate, V2G20Certificate SignCertificateRequest, CertificateSignedRequest
GenericStatusEnum Accepted, Rejected SignCertificateResponse
CertificateSignedStatusEnum Accepted, Rejected CertificateSignedResponse
CertificateStatusSourceEnum CRL, OCSP GetCertificateChainStatusRequest/Response
CertificateStatusEnum Good, Revoked, Unknown, Failed GetCertificateChainStatusResponse

12. Configuration Variables

Reference
Variable Description Relevant To
OCPPCommCtrlr.FieldLength["Get15118EVCertificateRequest.exiRequest"] Max supported length for exiRequest if > 11000 M01, M02
OCPPCommCtrlr.FieldLength["Get15118EVCertificateResponse.exiResponse"] Max supported length for exiResponse if > 17000 M01, M02
OCPPCommCtrlr.FieldLength["GetCertificateStatusResponse.ocspResult"] Max supported length for ocspResult if > 18000 M06
MaxCertificateChainSize Limits the maximum size of the certificateChain field in CertificateSignedRequest A02, A03
CertificateEntries.maxLimit Maximum number of certificates that can be stored on the Charging Station M05
AdditionalRootCertificateCheck When true, enforces that new CSMS Root cert must be signed by old one M05

OCPP 2.1 Certificate Management Flows (M01–M07) - CSMS Developer Guide. Based on OCPP 2.1 Edition 2 Specification (Part 2), Section M.