OCPP Security Profiles and TLS

IoTEV ChargingOCPPSecurity
Share on LinkedIn

A penetration test finds 40 chargers communicating over unencrypted WebSocket with basic auth credentials transmitted in plaintext. Security Profile 1—HTTP with username/password—is the factory default for many chargers because it simplifies manufacturing setup. In production, it exposes charging infrastructure to credential theft, session hijacking, and remote command injection. OCPP defines three security profiles; Profile 3 with mutual TLS is the target for every deployment.

Security profiles compared

Profile Transport Server auth Client auth Status
1 WS (plaintext) None HTTP Basic Deprecated
2 WSS (TLS) Server certificate HTTP Basic or cert Acceptable
3 WSS (TLS) Server certificate Client certificate Recommended

Profile 3 setup

CSMS server configuration:

server {
    listen 443 ssl;
    server_name ocpp.example.com;

    ssl_certificate     /etc/ssl/csms-server.crt;
    ssl_certificate_key /etc/ssl/csms-server.key;
    ssl_client_certificate /etc/ssl/charging-ca.crt;
    ssl_verify_client on;

    location /ocpp/ {
        proxy_pass http://ocpp-backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Client-CN $ssl_client_s_dn;
    }
}

Charger configuration:

SecurityProfile = 3
CpoName = ocpp.example.com
Identity = CS-001-ABC123

The charger connects via wss://ocpp.example.com/ocpp/CS-001-ABC123 presenting its client certificate.

Certificate provisioning flow

OCPP defines certificate management messages:

1. CSMS → InstallCertificate (root CA cert to charger trust store)
2. Charger generates key pair
3. Charger → SignCertificate (CSR to CSMS)
4. CSMS signs CSR with charging CA
5. CSMS → CertificateSigned (signed cert chain to charger)
6. Charger installs certificate, reconnects with Profile 3
// SignCertificate request (charger → CSMS)
{
  "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC...==\n-----END CERTIFICATE REQUEST-----"
}

// CertificateSigned (CSMS → charger)
{
  "certificateChain": "-----BEGIN CERTIFICATE-----\nMIID...==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIC...==\n-----END CERTIFICATE-----"
}

Automate this in your charger onboarding pipeline. Manual certificate installation does not scale past 20 devices.

Certificate rotation

async def rotate_charger_cert(charger_id: str, days_before_expiry: int = 30):
    cert = await db.get_certificate(charger_id)
    if cert.days_until_expiry > days_before_expiry:
        return

    # Trigger re-enrollment
    await csms.send_trigger_message(charger_id, "SignCertificate")
    # Charger generates new CSR, CSMS signs, old cert remains valid during overlap

Alert at 30 days and 7 days before expiry. Chargers that cannot connect due to expired certificates require physical intervention.

WebSocket over TLS (WSS)

OCPP uses WebSocket as its transport. Profile 2+ requires WSS:

Profile 1: ws://csms.example.com/ocpp/CS-001    ← plaintext
Profile 2: wss://csms.example.com/ocpp/CS-001   ← TLS encrypted
Profile 3: wss://csms.example.com/ocpp/CS-001   ← TLS + client cert

Verify the charger's WebSocket library supports WSS with client certificate presentation. Some embedded WebSocket stacks only support server-side TLS.

Network segmentation

Internet
  │
  ├── Firewall (allow 443/WSS inbound only)
  │
  ├── CSMS (DMZ)
  │     └── WSS termination
  │
  ├── Application network
  │     └── CSMS backend, billing, auth
  │
  └── Charger network (VPN or private APN)
        └── Chargers connect outbound to CSMS

Chargers initiate outbound connections—no inbound ports on charger networks. Use VPN or private cellular APN for charger-to-CSMS connectivity.

Security audit checklist

Compliance context

The German calibration law (Eichrecht) and the EU AFIR regulation increasingly require encrypted communication for public charging infrastructure. Security Profile 3 positions your network for regulatory compliance.

OCPP Security Profile comparison

Profile Transport Authentication Use case
Profile 1 HTTP/WS (unencrypted) None Lab/dev only — never production
Profile 2 HTTPS/WSS (TLS) HTTP Basic Auth Legacy deployments
Profile 3 HTTPS/WSS (TLS) Mutual TLS (client cert) Production standard

Profile 3 mutual TLS: charger presents client certificate, CSMS verifies against trusted CA. Charger identity cryptographically proven — not just password-based.

# Verify charger connects with client cert (Profile 3)
openssl s_client -connect csms.example.com:443 \
  -cert charger_client.pem -key charger_key.pem \
  -CAfile csms_ca.pem
# Should complete handshake; CSMS logs charger identity from cert CN

Certificate provisioning at scale

Manufacturing and field deployment workflow:

Factory:
  1. Generate unique key pair per charger (HSM or secure element)
  2. Submit CSR to CSMS CA
  3. Install signed certificate before shipping
  4. Record serial number → certificate mapping in inventory

Field replacement:
  1. New charger arrives with factory cert OR
  2. CSMS issues cert via OCPP CertificateSigned message (OCPP 2.0.1)
  3. Old cert revoked in CSMS inventory

Never reuse certificates across chargers — each charger needs unique identity for audit and revocation.

TLS configuration for OCPP WebSocket

# nginx WSS termination for OCPP
server {
    listen 443 ssl;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_client_certificate /etc/nginx/ca/charger_ca.pem;
    ssl_verify_client optional;  # Profile 2: optional; Profile 3: on

    location /ocpp/ {
        proxy_pass http://csms_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Charger-CN $ssl_client_s_dn;
    }
}

Verify with packet capture that no OCPP traffic flows over unencrypted WS in production.

Failure modes

Production checklist

Resources

Frequently asked questions

What are the three OCPP security profiles?

Profile 1: unencrypted HTTP with basic auth (deprecated, never use in production). Profile 2: TLS with server-side certificate (WSS) and basic auth or client certificates. Profile 3: TLS with mutual authentication—both CSMS and charger present certificates. Profile 3 is the production standard.

Why do chargers ship with Security Profile 1?

Manufacturing convenience—no certificate provisioning during factory setup. Before deploying to production, upgrade to Profile 2 or 3, install certificates, and disable plaintext connections. Many regulators now require encrypted OCPP.

How do I provision certificates to 500 chargers?

Use the OCPP Certificate Management functions: CSMS sends InstallCertificate, charger generates a key pair and sends SignCertificate request, CSMS signs and returns the certificate chain. Automate via your device provisioning pipeline.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →