Skip to content

Commit 81ba853

Browse files
florinmandachejuherr
authored andcommitted
feat: implement OCPP 1.6 Security
1 parent 639449c commit 81ba853

File tree

67 files changed

+4410
-18
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+4410
-18
lines changed

OCPP16_SECURITY_STATUS.md

Lines changed: 528 additions & 0 deletions
Large diffs are not rendered by default.

OCPP_SECURITY_PROFILES.md

Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
# OCPP 1.6 Security Profiles Configuration Guide
2+
3+
This document describes how to configure SteVe to support the three OCPP 1.6 security profiles defined in the OCPP 1.6 Security Whitepaper Edition 3.
4+
5+
---
6+
7+
## Security Profile Overview
8+
9+
### Profile 0: Unsecured Transport with Basic Authentication
10+
- **Transport**: HTTP or WebSocket (ws://)
11+
- **Authentication**: HTTP Basic Authentication
12+
- **Encryption**: None
13+
- **Use Case**: Development, testing, closed networks
14+
15+
### Profile 1: Unsecured Transport with Basic Authentication
16+
- **Transport**: HTTP or WebSocket (ws://)
17+
- **Authentication**: HTTP Basic Authentication + Charge Point Password
18+
- **Encryption**: None
19+
- **Use Case**: Private networks with additional authentication layer
20+
21+
### Profile 2: TLS with Basic Authentication
22+
- **Transport**: HTTPS or Secure WebSocket (wss://)
23+
- **Authentication**: HTTP Basic Authentication + TLS Server Certificate
24+
- **Encryption**: TLS 1.2 or higher
25+
- **Use Case**: Production environments with server authentication
26+
27+
### Profile 3: TLS with Client-Side Certificates
28+
- **Transport**: HTTPS or Secure WebSocket (wss://)
29+
- **Authentication**: Mutual TLS (mTLS) with client certificates
30+
- **Encryption**: TLS 1.2 or higher
31+
- **Use Case**: High-security production environments
32+
33+
---
34+
35+
## Configuration Properties
36+
37+
Add these properties to `application-prod.properties` or `application-test.properties`:
38+
39+
```properties
40+
# OCPP Security Profile (0, 1, 2, or 3)
41+
ocpp.security.profile=2
42+
43+
# TLS Configuration (required for Profile 2 and 3)
44+
ocpp.security.tls.enabled=true
45+
46+
# Server Keystore (contains server certificate and private key)
47+
ocpp.security.tls.keystore.path=/path/to/server-keystore.jks
48+
ocpp.security.tls.keystore.password=your-keystore-password
49+
ocpp.security.tls.keystore.type=JKS
50+
51+
# Truststore (contains trusted CA certificates)
52+
ocpp.security.tls.truststore.path=/path/to/truststore.jks
53+
ocpp.security.tls.truststore.password=your-truststore-password
54+
ocpp.security.tls.truststore.type=JKS
55+
56+
# Client Certificate Authentication (required for Profile 3)
57+
ocpp.security.tls.client.auth=false
58+
59+
# TLS Protocol Versions (comma-separated)
60+
ocpp.security.tls.protocols=TLSv1.2,TLSv1.3
61+
62+
# TLS Cipher Suites (optional, leave empty for defaults)
63+
ocpp.security.tls.ciphers=
64+
```
65+
66+
---
67+
68+
## Profile 0 Configuration (Unsecured)
69+
70+
**⚠️ NOT RECOMMENDED FOR PRODUCTION**
71+
72+
```properties
73+
ocpp.security.profile=0
74+
ocpp.security.tls.enabled=false
75+
76+
# Use HTTP Basic Auth credentials
77+
auth.user=admin
78+
auth.password=your-password
79+
```
80+
81+
**WebSocket URL**: `ws://your-server:8080/steve/websocket/CentralSystemService/{chargePointId}`
82+
83+
---
84+
85+
## Profile 1 Configuration (Basic Auth Only)
86+
87+
**⚠️ NOT RECOMMENDED FOR PRODUCTION**
88+
89+
```properties
90+
ocpp.security.profile=1
91+
ocpp.security.tls.enabled=false
92+
93+
# Configure charge point authorization keys in database
94+
# Each charge point should have an authorization_key set
95+
```
96+
97+
**WebSocket URL**: `ws://your-server:8080/steve/websocket/CentralSystemService/{chargePointId}`
98+
99+
**Database**: Set `authorization_key` column in `charge_box` table for each charge point.
100+
101+
---
102+
103+
## Profile 2 Configuration (TLS + Basic Auth)
104+
105+
**✅ RECOMMENDED FOR PRODUCTION**
106+
107+
### Step 1: Generate Server Certificate
108+
109+
```bash
110+
# Create server keystore with self-signed certificate (for testing)
111+
keytool -genkeypair -alias steve-server \
112+
-keyalg RSA -keysize 2048 -validity 365 \
113+
-keystore server-keystore.jks \
114+
-storepass changeit \
115+
-dname "CN=steve.example.com, OU=SteVe, O=Example, L=City, ST=State, C=US"
116+
117+
# OR: Import existing certificate and private key
118+
# (Use openssl to convert PEM to PKCS12, then import to JKS)
119+
```
120+
121+
### Step 2: Configure Properties
122+
123+
```properties
124+
ocpp.security.profile=2
125+
ocpp.security.tls.enabled=true
126+
127+
# Server certificate
128+
ocpp.security.tls.keystore.path=/opt/steve/certs/server-keystore.jks
129+
ocpp.security.tls.keystore.password=changeit
130+
ocpp.security.tls.keystore.type=JKS
131+
132+
# Enable HTTPS on Jetty
133+
https.enabled=true
134+
https.port=8443
135+
keystore.path=/opt/steve/certs/server-keystore.jks
136+
keystore.password=changeit
137+
138+
# Client authentication NOT required for Profile 2
139+
ocpp.security.tls.client.auth=false
140+
```
141+
142+
### Step 3: Configure Charge Points
143+
144+
**WebSocket URL**: `wss://steve.example.com:8443/steve/websocket/CentralSystemService/{chargePointId}`
145+
146+
**Certificate**: Charge points must trust the server certificate. Install the CA certificate or server certificate on charge points.
147+
148+
---
149+
150+
## Profile 3 Configuration (Mutual TLS)
151+
152+
**✅ RECOMMENDED FOR HIGH-SECURITY ENVIRONMENTS**
153+
154+
### Step 1: Generate CA Certificate
155+
156+
```bash
157+
# Create CA private key and certificate
158+
openssl genrsa -out ca-key.pem 4096
159+
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem \
160+
-subj "/CN=SteVe CA/O=Example/C=US"
161+
```
162+
163+
### Step 2: Generate Server Certificate (Signed by CA)
164+
165+
```bash
166+
# Generate server private key and CSR
167+
openssl genrsa -out server-key.pem 2048
168+
openssl req -new -key server-key.pem -out server.csr \
169+
-subj "/CN=steve.example.com/O=Example/C=US"
170+
171+
# Sign server certificate with CA
172+
openssl x509 -req -in server.csr -CA ca-cert.pem -CAkey ca-key.pem \
173+
-CAcreateserial -out server-cert.pem -days 365
174+
175+
# Convert to PKCS12
176+
openssl pkcs12 -export -in server-cert.pem -inkey server-key.pem \
177+
-out server.p12 -name steve-server -passout pass:changeit
178+
179+
# Import to JKS keystore
180+
keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 \
181+
-destkeystore server-keystore.jks -deststoretype JKS \
182+
-srcstorepass changeit -deststorepass changeit
183+
```
184+
185+
### Step 3: Create Truststore with CA Certificate
186+
187+
```bash
188+
# Import CA certificate to truststore
189+
keytool -import -trustcacerts -alias ca-cert \
190+
-file ca-cert.pem -keystore truststore.jks \
191+
-storepass changeit -noprompt
192+
```
193+
194+
### Step 4: Generate Client Certificates (for each Charge Point)
195+
196+
```bash
197+
# Generate client private key and CSR
198+
openssl genrsa -out client-cp001-key.pem 2048
199+
openssl req -new -key client-cp001-key.pem -out client-cp001.csr \
200+
-subj "/CN=CP001/O=Example/C=US"
201+
202+
# Sign client certificate with CA
203+
openssl x509 -req -in client-cp001.csr -CA ca-cert.pem -CAkey ca-key.pem \
204+
-CAcreateserial -out client-cp001-cert.pem -days 365
205+
206+
# Convert to PKCS12 for charge point
207+
openssl pkcs12 -export -in client-cp001-cert.pem -inkey client-cp001-key.pem \
208+
-out client-cp001.p12 -name cp001 -passout pass:changeit
209+
```
210+
211+
### Step 5: Configure Properties
212+
213+
```properties
214+
ocpp.security.profile=3
215+
ocpp.security.tls.enabled=true
216+
217+
# Server certificate
218+
ocpp.security.tls.keystore.path=/opt/steve/certs/server-keystore.jks
219+
ocpp.security.tls.keystore.password=changeit
220+
ocpp.security.tls.keystore.type=JKS
221+
222+
# Truststore with CA certificate (to verify client certificates)
223+
ocpp.security.tls.truststore.path=/opt/steve/certs/truststore.jks
224+
ocpp.security.tls.truststore.password=changeit
225+
ocpp.security.tls.truststore.type=JKS
226+
227+
# Require client certificates
228+
ocpp.security.tls.client.auth=true
229+
230+
# TLS protocols
231+
ocpp.security.tls.protocols=TLSv1.2,TLSv1.3
232+
233+
# Enable HTTPS
234+
https.enabled=true
235+
https.port=8443
236+
keystore.path=/opt/steve/certs/server-keystore.jks
237+
keystore.password=changeit
238+
```
239+
240+
### Step 6: Install Client Certificates on Charge Points
241+
242+
1. Transfer `client-cp001.p12` to charge point CP001
243+
2. Configure charge point to use client certificate for mTLS
244+
3. Configure charge point with CA certificate to verify server
245+
4. Set WebSocket URL: `wss://steve.example.com:8443/steve/websocket/CentralSystemService/CP001`
246+
247+
---
248+
249+
## Security Best Practices
250+
251+
### Certificate Management
252+
253+
1. **Use a proper CA**: For production, use certificates from a trusted CA (Let's Encrypt, DigiCert, etc.)
254+
2. **Certificate rotation**: Renew certificates before expiry
255+
3. **Revocation**: Implement CRL or OCSP for certificate revocation
256+
4. **Key length**: Use at least 2048-bit RSA keys or 256-bit ECC keys
257+
5. **Storage**: Protect private keys with strong passwords and secure storage
258+
259+
### TLS Configuration
260+
261+
1. **Protocol versions**: Use TLS 1.2 or higher, disable SSLv3 and TLS 1.0/1.1
262+
2. **Cipher suites**: Use strong ciphers (AES-GCM, ChaCha20-Poly1305)
263+
3. **Perfect Forward Secrecy**: Prefer ECDHE or DHE cipher suites
264+
4. **HSTS**: Enable HTTP Strict Transport Security
265+
266+
### Recommended Cipher Suites
267+
268+
```properties
269+
ocpp.security.tls.ciphers=\
270+
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\
271+
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\
272+
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,\
273+
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,\
274+
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
275+
```
276+
277+
---
278+
279+
## Database Configuration
280+
281+
The `charge_box` table includes security-related columns:
282+
283+
```sql
284+
-- Security profile for this charge point (0-3)
285+
ALTER TABLE charge_box ADD COLUMN security_profile INT DEFAULT 0;
286+
287+
-- Authorization key for Profile 1+ (optional)
288+
ALTER TABLE charge_box ADD COLUMN authorization_key VARCHAR(100);
289+
290+
-- CPO name (for certificate validation)
291+
ALTER TABLE charge_box ADD COLUMN cpo_name VARCHAR(255);
292+
293+
-- Certificate store max length
294+
ALTER TABLE charge_box ADD COLUMN certificate_store_max_length INT;
295+
296+
-- Additional root certificate check
297+
ALTER TABLE charge_box ADD COLUMN additional_root_certificate_check BOOLEAN DEFAULT FALSE;
298+
```
299+
300+
---
301+
302+
## Troubleshooting
303+
304+
### Connection Fails with "SSL Handshake Error"
305+
306+
- **Check**: Certificate validity (not expired)
307+
- **Check**: Hostname matches CN in server certificate
308+
- **Check**: Charge point trusts the server certificate or CA
309+
310+
### Client Certificate Not Accepted
311+
312+
- **Check**: Client certificate signed by trusted CA in truststore
313+
- **Check**: Client certificate not expired
314+
- **Check**: `ocpp.security.tls.client.auth=true` is set
315+
316+
### TLS Version Mismatch
317+
318+
- **Check**: Both server and charge point support same TLS version
319+
- **Check**: `ocpp.security.tls.protocols` includes supported versions
320+
321+
### Certificate Validation Fails
322+
323+
- **Check**: CN in certificate matches charge point ID or hostname
324+
- **Check**: Certificate chain is complete
325+
- **Check**: CA certificate imported to truststore
326+
327+
---
328+
329+
## Testing TLS Configuration
330+
331+
### Test Server Certificate with OpenSSL
332+
333+
```bash
334+
# Test TLS connection
335+
openssl s_client -connect steve.example.com:8443 -showcerts
336+
337+
# Test with client certificate
338+
openssl s_client -connect steve.example.com:8443 \
339+
-cert client-cp001-cert.pem -key client-cp001-key.pem
340+
```
341+
342+
### Test WebSocket Connection
343+
344+
```bash
345+
# Install wscat: npm install -g wscat
346+
347+
# Test Profile 2 (wss://)
348+
wscat -c "wss://steve.example.com:8443/steve/websocket/CentralSystemService/CP001"
349+
350+
# Test Profile 3 (wss:// with client cert)
351+
wscat -c "wss://steve.example.com:8443/steve/websocket/CentralSystemService/CP001" \
352+
--cert client-cp001.p12 --passphrase changeit
353+
```
354+
355+
---
356+
357+
## References
358+
359+
- [OCPP 1.6 Security Whitepaper Edition 3](https://openchargealliance.org/protocols/open-charge-point-protocol/)
360+
- [Java Keytool Documentation](https://docs.oracle.com/en/java/javase/17/docs/specs/man/keytool.html)
361+
- [OpenSSL Documentation](https://www.openssl.org/docs/)
362+
- [Spring Boot SSL Configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.server)
363+
364+
---
365+
366+
## Support
367+
368+
For questions or issues:
369+
- GitHub: https://github.com/steve-community/steve/issues
370+
- OCPP Forum: https://openchargealliance.org/
371+
372+
---
373+
374+
**Last Updated**: 2025-09-27
375+
**SteVe Version**: 3.x with OCPP 1.6 Security Extensions

0 commit comments

Comments
 (0)