Skip to content

ocpp : Added TLSv1.3 support for OCPP #153

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: dev/ev/ocpp
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion include/zephyr/net/ocpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
#include <zephyr/kernel.h>
#include <zephyr/net/net_ip.h>

#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
#include <zephyr/net/tls_credentials.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -92,7 +96,6 @@ enum ocpp_meter_measurand {
* is valid
*/
union ocpp_io_value {

struct {
/** Input to user, requested connector_id or 0 - main meter */
int id_con;
Expand Down Expand Up @@ -139,12 +142,25 @@ struct ocpp_cp_info {
char *meter_type; /**< Main power meter type */
};

#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
/** @brief TLS credentials information of the central system (CS) */
struct ocpp_tls_credentials {
const sec_tag_t *sec_tag_list; /**< TLS Sec tag list */
char *tls_hostname; /**< TLS Hostname */
size_t sec_tag_list_size; /**< Size of TLS Sec tag list */
size_t tls_hostname_size; /**< Size of TLS Hostname */
};
#endif

/** @brief Parameters for ocpp_init information about central system (CS) */
struct ocpp_cs_info {
char *cs_ip; /**< Central system IP address */
char *ws_url; /**< Websocket url exclude ipaddr & port */
int port; /**< Central system port number */
sa_family_t sa_family; /** IP protocol family type 4/6 */
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
struct ocpp_tls_credentials creds; /**< Central system TLS Credentials */
#endif
};

/** @brief Parameters opaque session handle for ocpp_* API */
Expand Down
16 changes: 15 additions & 1 deletion samples/net/ocpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(hello_world)
project(ocpp)

target_sources(app PRIVATE src/main.c)
set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)

function(pem_to_mbedtls target input_file_fullpath)
get_filename_component(input_file ${input_file_fullpath} NAME)
file(READ ${input_file_fullpath} input_file_content)
string(REGEX REPLACE "\n" "\\\\n" input_file_content "${input_file_content}")
set(GENERATED_FILE ${gen_dir}/${input_file}.inc)
file(WRITE ${GENERATED_FILE} "\"${input_file_content}\"\n")
generate_unique_target_name_from_filename(${input_file} generated_target_name)
add_custom_target(${generated_target_name} DEPENDS ${GENERATED_FILE})
add_dependencies(${target} ${generated_target_name})
endfunction()

pem_to_mbedtls(app ${ZEPHYR_BASE}/samples/net/ocpp/src/credentials/ec.crt)
7 changes: 7 additions & 0 deletions samples/net/ocpp/overlay-ec.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CONFIG_PSA_WANT_ALG_ECDH=y
CONFIG_PSA_WANT_ALG_ECDSA=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE=y
CONFIG_PSA_WANT_ECC_SECP_R1_256=y
38 changes: 38 additions & 0 deletions samples/net/ocpp/overlay-tls13.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Enable Secure Sockets
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y

# Mbed TLS configuration
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=20000
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048
CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y
CONFIG_MBEDTLS_SERVER_NAME_INDICATION=y
# Build the PSA Crypto core so that the TLS stack uses the PSA crypto API.
CONFIG_MBEDTLS_PSA_CRYPTO_C=y
CONFIG_ENTROPY_GENERATOR=y

# Disable some Kconfigs that are implied by CONFIG_NET_SOCKETS_SOCKOPT_TLS.
CONFIG_MBEDTLS_TLS_VERSION_1_2=n
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=n
CONFIG_MBEDTLS_MD=n
CONFIG_MBEDTLS_RSA_C=n
CONFIG_MBEDTLS_CIPHER_AES_ENABLED=n
CONFIG_PSA_WANT_KEY_TYPE_AES=n
CONFIG_PSA_WANT_ALG_CBC_NO_PADDING=n

# Debug log options (optional)
# CONFIG_MBEDTLS_LOG_LEVEL_DBG=y
# CONFIG_MBEDTLS_DEBUG=y

# TLS1.3 Configuration
CONFIG_MBEDTLS_TLS_VERSION_1_3=y
CONFIG_PSA_WANT_ALG_HKDF_EXTRACT=y
CONFIG_PSA_WANT_ALG_HKDF_EXPAND=y
CONFIG_PSA_WANT_ALG_GCM=y
CONFIG_PSA_WANT_KEY_TYPE_AES=y
CONFIG_PSA_WANT_ALG_CBC_NO_PADDING=y
CONFIG_PSA_WANT_ALG_SHA_256=y
CONFIG_PSA_WANT_ALG_SHA_384=y
CONFIG_MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED=y
19 changes: 14 additions & 5 deletions samples/net/ocpp/prj.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# HTTP & Websocket
CONFIG_HTTP_CLIENT=y
CONFIG_WEBSOCKET_CLIENT=y

Expand All @@ -12,20 +11,25 @@ CONFIG_NET_SOCKETS_POLL_MAX=4
CONFIG_NET_L2_ETHERNET=y
CONFIG_ETH_DRIVER=y
CONFIG_LOG=y
CONFIG_NET_LOG=y

CONFIG_LOG_MODE_IMMEDIATE=y

# Networking debug (Optional)
CONFIG_NET_LOG=n
CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=n

# OCPP
CONFIG_OCPP=y

# Please set the server addresses when compiling the sample
CONFIG_NET_SAMPLE_SNTP_SERVER=""
CONFIG_NET_SAMPLE_OCPP_SERVER=""
CONFIG_NET_SAMPLE_OCPP_PORT=8180
CONFIG_NET_SAMPLE_OCPP_PORT=8443

CONFIG_MAIN_STACK_SIZE=4096
CONFIG_HEAP_MEM_POOL_SIZE=15000

CONFIG_JSONC=y
CONFIG_JSON_LIBRARY=y
CONFIG_PICOLIBC=y
CONFIG_NET_ARP=y
CONFIG_NET_UDP=y
Expand All @@ -44,5 +48,10 @@ CONFIG_SNTP=y

CONFIG_ZBUS=y
CONFIG_ZBUS_RUNTIME_OBSERVERS=y
CONFIG_POSIX_CLOCK=y

CONFIG_POSIX_API=y
CONFIG_POSIX_CLOCK_SELECTION=y

# Logging
CONFIG_LOG=y
CONFIG_PRINTK=y
11 changes: 11 additions & 0 deletions samples/net/ocpp/src/credentials/certificate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef __CERTIFICATE_H__
#define __CERTIFICATE_H__

#define CA_CERTIFICATE_TAG 1
#define TLS_PEER_HOSTNAME "localhost"

static const unsigned char ca_certificate[] = {
#include "ec.crt.inc"
};

#endif
5 changes: 5 additions & 0 deletions samples/net/ocpp/src/credentials/ec-priv.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgwecn6Plv8ONZs2cF
IIlr4B4xaoPYEMHm9mSG4esgQ2uhRANCAARVR4/COFJhHmmGdERod/1DhM5hBcq/
xQHuUtxC1a977tMFCzINWTy155+/E8uj35FUhsLeFMoyGtgvKHKIBpgt
-----END PRIVATE KEY-----
10 changes: 10 additions & 0 deletions samples/net/ocpp/src/credentials/ec.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBfDCCASOgAwIBAgIUW0crZnSm9CwlYmnYdDSohFSG5UwwCgYIKoZIzj0EAwIw
FDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDgyNzA5NDcxN1oXDTM0MDgyNTA5
NDcxN1owFDESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEVUePwjhSYR5phnREaHf9Q4TOYQXKv8UB7lLcQtWve+7TBQsyDVk8teef
vxPLo9+RVIbC3hTKMhrYLyhyiAaYLaNTMFEwHQYDVR0OBBYEFDi6b5XH5Z5d4cSe
S5OVBHaWjB8SMB8GA1UdIwQYMBaAFDi6b5XH5Z5d4cSeS5OVBHaWjB8SMA8GA1Ud
EwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDRwAwRAIgMEnVFWqIHRphQtWn5CbXomkH
H/mDhf4ux5k55dmRRH8CIFwL0gYBrp26n0AsRSpVN1RroAt7M1MpCgEycVr3QNMQ
-----END CERTIFICATE-----
30 changes: 27 additions & 3 deletions samples/net/ocpp/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
#include <zephyr/random/random.h>
#include <zephyr/zbus/zbus.h>

#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
#include "credentials/certificate.h"
#endif

LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);

#define NO_OF_CONN 2
Expand Down Expand Up @@ -207,6 +211,7 @@ static void ocpp_cp_entry(void *p1, void *p2, void *p3)
/* Avoid quick retry since authorization request is possible only
* after Bootnotification process (handled in lib) completed.
*/

k_sleep(K_SECONDS(5));
ret = ocpp_authorize(sh,
idtag,
Expand All @@ -220,6 +225,7 @@ static void ocpp_cp_entry(void *p1, void *p2, void *p3)
ret, idcon, status);
break;
}

}

if (status != OCPP_AUTH_ACCEPTED) {
Expand Down Expand Up @@ -331,9 +337,9 @@ int main(void)

struct ocpp_cp_info cpi = { "basic", "zephyr", .num_of_con = NO_OF_CONN };
struct ocpp_cs_info csi = { NULL,
"/steve/websocket/CentralSystemService/zephyr",
CONFIG_NET_SAMPLE_OCPP_PORT,
AF_INET };
"/steve/websocket/CentralSystemService/basic",
CONFIG_NET_SAMPLE_OCPP_PORT,
AF_INET};

printk("OCPP sample %s\n", CONFIG_BOARD);

Expand All @@ -353,6 +359,24 @@ int main(void)

ocpp_get_time_from_sntp();

#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
sec_tag_t tags[] = {CA_CERTIFICATE_TAG};

ret = tls_credential_add(CA_CERTIFICATE_TAG,
TLS_CREDENTIAL_CA_CERTIFICATE,
ca_certificate,
sizeof(ca_certificate));
if (ret < 0) {
LOG_ERR("Failed to register CA certificate: %d", ret);
return ret;
}

csi.creds.sec_tag_list = tags;
csi.creds.tls_hostname = TLS_PEER_HOSTNAME;
csi.creds.sec_tag_list_size = sizeof(tags);
csi.creds.tls_hostname_size = strlen(TLS_PEER_HOSTNAME);
#endif

ret = ocpp_init(&cpi,
&csi,
user_notify_cb,
Expand Down
63 changes: 48 additions & 15 deletions subsys/net/lib/ocpp/ocpp.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ void ocpp_get_utc_now(char utc[CISTR25])
gmtime_r(&tv.tv_sec, &htime);

snprintk(utc, CISTR25, "%04d-%02d-%02dT%02d:%02d:%02dZ",
htime.tm_year + 1900,
htime.tm_mon + 1,
htime.tm_mday,
htime.tm_hour,
htime.tm_min,
htime.tm_sec);
htime.tm_year + 1900,
htime.tm_mon + 1,
htime.tm_mday,
htime.tm_hour,
htime.tm_min,
htime.tm_sec);
}

bool ocpp_session_is_valid(struct ocpp_session *sh)
Expand Down Expand Up @@ -173,7 +173,6 @@ static int ocpp_connect_to_cs(struct ocpp_info *ctx)
}
ui->wssock = ret;
}

LOG_DBG("WS connect success %d", ui->wssock);
return 0;
}
Expand Down Expand Up @@ -309,7 +308,7 @@ static int ocpp_process_server_msg(struct ocpp_info *ctx)

if (is_rsp) {
buf = strtok_r(uid, "-", &tmp);
sh = (struct ocpp_session *) atoi(buf);
sh = (struct ocpp_session *)atoi(buf);

buf = strtok_r(NULL, "-", &tmp);
pdu = atoi(buf);
Expand Down Expand Up @@ -460,14 +459,13 @@ static void ocpp_wsreader(void *p1, void *p2, void *p3)

ctx->is_cs_offline = true;
tcpfd.fd = ui->tcpsock;

tcpfd.events = ZSOCK_POLLIN | ZSOCK_POLLERR
| ZSOCK_POLLHUP | ZSOCK_POLLNVAL;

while (1) {

if (ctx->is_cs_offline &&
!(retry_cnt++ % TCP_CONNECT_AFTER)) {

k_mutex_lock(&ctx->ilock, K_FOREVER);
ocpp_connect_to_cs(ctx);
k_mutex_unlock(&ctx->ilock);
Expand Down Expand Up @@ -507,19 +505,47 @@ static void ocpp_wsreader(void *p1, void *p2, void *p3)

int ocpp_upstream_init(struct ocpp_info *ctx, struct ocpp_cs_info *csi)
{
int ret;
struct ocpp_upstream_info *ui = &ctx->ui;

LOG_INF("upstream init");

ui->csi.ws_url = strdup(csi->ws_url);
ui->csi.cs_ip = strdup(csi->cs_ip);
ui->csi.port = csi->port;
ui->csi.sa_family = csi->sa_family;
ui->tcpsock = zsock_socket(csi->sa_family, SOCK_STREAM,
IPPROTO_TCP);

LOG_INF("upstream init");

#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
ui->csi.creds.sec_tag_list = csi->creds.sec_tag_list;
ui->csi.creds.sec_tag_list_size = csi->creds.sec_tag_list_size;
ui->csi.creds.tls_hostname = csi->creds.tls_hostname;

ui->tcpsock = zsock_socket(csi->sa_family, SOCK_STREAM, IPPROTO_TLS_1_3);
if (ui->tcpsock < 0) {
LOG_ERR("Failed to create TLS socket: %d", errno);
return -errno;
}

ret = zsock_setsockopt(ui->tcpsock, SOL_TLS, TLS_SEC_TAG_LIST, csi->creds.sec_tag_list,
csi->creds.sec_tag_list_size);
if (ret < 0) {
LOG_ERR("Failed to set TLS_SEC_TAG_LIST: %d", -errno);
goto fail;
}

ret = zsock_setsockopt(ui->tcpsock, SOL_TLS, TLS_HOSTNAME, csi->creds.tls_hostname,
csi->creds.tls_hostname_size);
if (ret < 0) {
LOG_ERR("Failed to set TLS_HOSTNAME: %d", -errno);
goto fail;
}
#else
ui->tcpsock = zsock_socket(csi->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (ui->tcpsock < 0) {
LOG_ERR("Failed to create TCP socket: %d", -errno);
return -errno;
}
#endif

k_mutex_init(&ui->ws_sndlock);
k_poll_signal_init(&ui->ws_rspsig);
Expand All @@ -530,9 +556,16 @@ int ocpp_upstream_init(struct ocpp_info *ctx, struct ocpp_cs_info *csi)
k_thread_create(&ui->tinfo, ocpp_wsreader_stack,
CONFIG_OCPP_WSREADER_THREAD_STACKSIZE,
ocpp_wsreader, ctx, NULL, NULL,
OCPP_UPSTREAM_PRIORITY, 0, K_MSEC(100));
OCPP_UPSTREAM_PRIORITY, 0, K_MSEC(100));

return 0;

fail:
if (ui->tcpsock >= 0) {
zsock_close(ui->tcpsock);
ui->tcpsock = -1;
}
return -errno;
}

static void timer_heartbeat_cb(struct k_timer *t)
Expand Down
Loading