samples: net: sockets: coap_server: Add CoAP secure support
Update the CoAP server sample to demonstrate using DTLS for secure sockets. Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
This commit is contained in:
parent
b596b13e7c
commit
51a4e4c858
14 changed files with 285 additions and 27 deletions
|
@ -4,6 +4,19 @@ cmake_minimum_required(VERSION 3.20.0)
|
|||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(coap_server)
|
||||
|
||||
if(CONFIG_NET_SOCKETS_ENABLE_DTLS AND
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED AND
|
||||
(CONFIG_NET_SAMPLE_PSK_HEADER_FILE STREQUAL "dummy_psk.h"))
|
||||
add_custom_target(development_psk
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "--- WARNING: Using dummy PSK! Only suitable for ---"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "--- development. Set NET_SAMPLE_PSK_HEADER_FILE to use ---"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "--- own pre-shared key. ---"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------"
|
||||
)
|
||||
add_dependencies(app development_psk)
|
||||
endif()
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
||||
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip)
|
||||
|
@ -18,3 +31,19 @@ zephyr_iterable_section(
|
|||
SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
|
||||
|
||||
include(${ZEPHYR_BASE}/samples/net/common/common.cmake)
|
||||
|
||||
set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)
|
||||
|
||||
foreach(inc_file
|
||||
ca.der
|
||||
server.der
|
||||
server_privkey.der
|
||||
coaps-server-cert.der
|
||||
coaps-server-key.der
|
||||
)
|
||||
generate_inc_file_for_target(
|
||||
app
|
||||
src/certs/${inc_file}
|
||||
${gen_dir}/${inc_file}.inc
|
||||
)
|
||||
endforeach()
|
||||
|
|
36
samples/net/sockets/coap_server/Kconfig
Normal file
36
samples/net/sockets/coap_server/Kconfig
Normal file
|
@ -0,0 +1,36 @@
|
|||
# Copyright (c) 2023, Emna Rekik
|
||||
# Copyright (c) 2025, Basalte bv
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Config options for CoAP server sample application
|
||||
|
||||
mainmenu "CoAP server sample application"
|
||||
|
||||
config NET_SAMPLE_COAPS_SERVICE
|
||||
bool "Enable CoAP secure service"
|
||||
depends on NET_SOCKETS_ENABLE_DTLS || TLS_CREDENTIALS
|
||||
|
||||
config NET_SAMPLE_COAP_SERVER_SERVICE_PORT
|
||||
int "Port number for CoAP service"
|
||||
default 5684 if NET_SAMPLE_COAPS_SERVICE
|
||||
default 5683
|
||||
|
||||
if NET_SAMPLE_COAPS_SERVICE
|
||||
|
||||
config NET_SAMPLE_PSK_HEADER_FILE
|
||||
string "Header file containing PSK"
|
||||
default "dummy_psk.h"
|
||||
depends on MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
help
|
||||
Name of a header file containing a pre-shared key.
|
||||
|
||||
config NET_SAMPLE_CERTS_WITH_SC
|
||||
bool "Signed Certificates"
|
||||
depends on NET_SOCKETS_SOCKOPT_TLS
|
||||
help
|
||||
Enable this flag, if you are interested to run this
|
||||
application with certificates.
|
||||
|
||||
endif
|
||||
|
||||
source "Kconfig.zephyr"
|
|
@ -17,8 +17,9 @@ service's name. A linker file is required, see ``sections-ram.ld`` for an exampl
|
|||
This demo assumes that the platform of choice has networking support,
|
||||
some adjustments to the configuration may be needed.
|
||||
|
||||
The sample will listen for requests in the CoAP UDP port (5683) in the
|
||||
site-local IPv6 multicast address reserved for CoAP nodes.
|
||||
The sample will listen for requests on the default CoAP UDP port
|
||||
(5683 or 5684 for secure CoAP) in the site-local IPv6 multicast address reserved
|
||||
for CoAP nodes.
|
||||
|
||||
The sample exports the following resources:
|
||||
|
||||
|
@ -37,6 +38,16 @@ against coap-server.
|
|||
|
||||
Building And Running
|
||||
********************
|
||||
Build the CoAP server sample application like this:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/net/sockets/coap_server
|
||||
:board: <board to use>
|
||||
:goals: build
|
||||
:compact:
|
||||
|
||||
Use :zephyr_file:`overlay-dtls.conf <samples/net/sockets/coap_server/overlay-dtls.conf>`
|
||||
to build the sample with CoAP secure resources instead.
|
||||
|
||||
This project has no output in case of success, the correct
|
||||
functionality can be verified by using some external tool such as tcpdump
|
||||
|
|
18
samples/net/sockets/coap_server/overlay-dtls.conf
Normal file
18
samples/net/sockets/coap_server/overlay-dtls.conf
Normal file
|
@ -0,0 +1,18 @@
|
|||
CONFIG_NET_SAMPLE_COAPS_SERVICE=y
|
||||
|
||||
# Secure Socket
|
||||
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
|
||||
CONFIG_NET_SOCKETS_ENABLE_DTLS=y
|
||||
CONFIG_NET_SOCKETS_TLS_MAX_CLIENT_SESSION_COUNT=6
|
||||
CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6
|
||||
CONFIG_NET_SOCKETS_DTLS_TIMEOUT=30000
|
||||
|
||||
# TLS configuration
|
||||
CONFIG_MBEDTLS_DEBUG=y
|
||||
CONFIG_MBEDTLS=y
|
||||
CONFIG_MBEDTLS_BUILTIN=y
|
||||
CONFIG_MBEDTLS_ENABLE_HEAP=y
|
||||
CONFIG_MBEDTLS_HEAP_SIZE=60000
|
||||
CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID=y
|
||||
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048
|
||||
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y
|
|
@ -6,7 +6,7 @@ CONFIG_NET_UDP=y
|
|||
# Socket
|
||||
CONFIG_NET_SOCKETS=y
|
||||
CONFIG_POSIX_API=y
|
||||
CONFIG_ZVFS_POLL_MAX=4
|
||||
CONFIG_ZVFS_POLL_MAX=10
|
||||
|
||||
# CoAP
|
||||
CONFIG_COAP=y
|
||||
|
@ -48,3 +48,6 @@ CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5
|
|||
CONFIG_NET_IPV4=n
|
||||
CONFIG_NET_CONFIG_NEED_IPV4=n
|
||||
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
|
||||
|
||||
# Enable v4-mapped-on-v6
|
||||
CONFIG_NET_IPV4_MAPPING_TO_IPV6=y
|
||||
|
|
|
@ -12,6 +12,16 @@ tests:
|
|||
platform_allow:
|
||||
- native_sim
|
||||
- qemu_x86
|
||||
sample.net.sockets.coaps_server:
|
||||
harness: net
|
||||
extra_args: EXTRA_CONF_FILE="overlay-dtls.conf"
|
||||
tags:
|
||||
- net
|
||||
- socket
|
||||
- tls
|
||||
platform_allow:
|
||||
- native_sim
|
||||
- qemu_x86
|
||||
sample.net.sockets.coap_server.wifi.nrf70dk:
|
||||
extra_args:
|
||||
- SNIPPET=wifi-ipv4
|
||||
|
|
43
samples/net/sockets/coap_server/src/certificate.h
Normal file
43
samples/net/sockets/coap_server/src/certificate.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __CERTIFICATE_H__
|
||||
#define __CERTIFICATE_H__
|
||||
|
||||
#define SERVER_CERTIFICATE_TAG 1
|
||||
#define PSK_TAG 2
|
||||
|
||||
#if !defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC)
|
||||
static const unsigned char server_certificate[] = {
|
||||
#include "coaps-server-cert.der.inc"
|
||||
};
|
||||
|
||||
/* This is the private key in pkcs#8 format. */
|
||||
static const unsigned char private_key[] = {
|
||||
#include "coaps-server-key.der.inc"
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static const unsigned char ca_certificate[] = {
|
||||
#include "ca.der.inc"
|
||||
};
|
||||
|
||||
static const unsigned char server_certificate[] = {
|
||||
#include "server.der.inc"
|
||||
};
|
||||
|
||||
/* This is the private key in pkcs#8 format. */
|
||||
static const unsigned char private_key[] = {
|
||||
#include "server_privkey.der.inc"
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
||||
#include CONFIG_NET_SAMPLE_PSK_HEADER_FILE
|
||||
#endif
|
||||
|
||||
#endif /* __CERTIFICATE_H__ */
|
BIN
samples/net/sockets/coap_server/src/certs/ca.der
Normal file
BIN
samples/net/sockets/coap_server/src/certs/ca.der
Normal file
Binary file not shown.
BIN
samples/net/sockets/coap_server/src/certs/coaps-server-cert.der
Normal file
BIN
samples/net/sockets/coap_server/src/certs/coaps-server-cert.der
Normal file
Binary file not shown.
BIN
samples/net/sockets/coap_server/src/certs/coaps-server-key.der
Normal file
BIN
samples/net/sockets/coap_server/src/certs/coaps-server-key.der
Normal file
Binary file not shown.
BIN
samples/net/sockets/coap_server/src/certs/server.der
Normal file
BIN
samples/net/sockets/coap_server/src/certs/server.der
Normal file
Binary file not shown.
BIN
samples/net/sockets/coap_server/src/certs/server_privkey.der
Normal file
BIN
samples/net/sockets/coap_server/src/certs/server_privkey.der
Normal file
Binary file not shown.
14
samples/net/sockets/coap_server/src/dummy_psk.h
Normal file
14
samples/net/sockets/coap_server/src/dummy_psk.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __DUMMY_PSK_H__
|
||||
#define __DUMMY_PSK_H__
|
||||
|
||||
static const unsigned char psk[] = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
|
||||
static const char psk_id[] = "PSK_identity";
|
||||
|
||||
#endif /* __DUMMY_PSK_H__ */
|
|
@ -8,18 +8,98 @@
|
|||
LOG_MODULE_REGISTER(net_coap_service_sample, LOG_LEVEL_DBG);
|
||||
|
||||
#include <zephyr/net/coap_service.h>
|
||||
#include <zephyr/net/mld.h>
|
||||
|
||||
#include "net_sample_common.h"
|
||||
|
||||
#ifdef CONFIG_NET_IPV6
|
||||
#include <zephyr/net/mld.h>
|
||||
|
||||
#include "net_private.h"
|
||||
#include "ipv6.h"
|
||||
#endif
|
||||
|
||||
#include "net_sample_common.h"
|
||||
static uint16_t coap_port = CONFIG_NET_SAMPLE_COAP_SERVER_SERVICE_PORT;
|
||||
|
||||
static const uint16_t coap_port = 5683;
|
||||
#ifndef CONFIG_NET_SAMPLE_COAPS_SERVICE
|
||||
|
||||
#ifdef CONFIG_NET_IPV6
|
||||
COAP_SERVICE_DEFINE(coap_server, NULL, &coap_port, COAP_SERVICE_AUTOSTART);
|
||||
|
||||
#else /* CONFIG_NET_SAMPLE_COAPS_SERVICE */
|
||||
|
||||
#include "certificate.h"
|
||||
|
||||
static const sec_tag_t sec_tag_list_verify_none[] = {
|
||||
SERVER_CERTIFICATE_TAG,
|
||||
#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
||||
PSK_TAG,
|
||||
#endif
|
||||
};
|
||||
|
||||
COAPS_SERVICE_DEFINE(coap_server, NULL, &coap_port, 0,
|
||||
sec_tag_list_verify_none, sizeof(sec_tag_list_verify_none));
|
||||
|
||||
#endif /* CONFIG_NET_SAMPLE_COAPS_SERVICE */
|
||||
|
||||
static int setup_dtls(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_SAMPLE_COAPS_SERVICE)
|
||||
#if defined(CONFIG_NET_SOCKETS_ENABLE_DTLS)
|
||||
int err;
|
||||
|
||||
#if defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC)
|
||||
err = tls_credential_add(SERVER_CERTIFICATE_TAG,
|
||||
TLS_CREDENTIAL_CA_CERTIFICATE,
|
||||
ca_certificate,
|
||||
sizeof(ca_certificate));
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to register CA certificate: %d", err);
|
||||
return err;
|
||||
}
|
||||
#endif /* defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) */
|
||||
|
||||
err = tls_credential_add(SERVER_CERTIFICATE_TAG,
|
||||
TLS_CREDENTIAL_SERVER_CERTIFICATE,
|
||||
server_certificate,
|
||||
sizeof(server_certificate));
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to register public certificate: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tls_credential_add(SERVER_CERTIFICATE_TAG,
|
||||
TLS_CREDENTIAL_PRIVATE_KEY,
|
||||
private_key, sizeof(private_key));
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to register private key: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
|
||||
err = tls_credential_add(PSK_TAG,
|
||||
TLS_CREDENTIAL_PSK,
|
||||
psk,
|
||||
sizeof(psk));
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to register PSK: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = tls_credential_add(PSK_TAG,
|
||||
TLS_CREDENTIAL_PSK_ID,
|
||||
psk_id,
|
||||
sizeof(psk_id) - 1);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to register PSK ID: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) */
|
||||
#endif /* defined(CONFIG_NET_SOCKETS_ENABLE_DTLS) */
|
||||
#endif /* defined(CONFIG_NET_SAMPLE_COAPS_SERVICE) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_NET_SAMPLE_COAPS_SERVICE) && defined(CONFIG_NET_IPV6)
|
||||
|
||||
#define ALL_NODES_LOCAL_COAP_MCAST \
|
||||
{ { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfd } } }
|
||||
|
@ -27,13 +107,13 @@ static const uint16_t coap_port = 5683;
|
|||
#define MY_IP6ADDR \
|
||||
{ { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
|
||||
static int join_coap_multicast_group(void)
|
||||
static int join_coap_multicast_group(uint16_t port)
|
||||
{
|
||||
static struct in6_addr my_addr = MY_IP6ADDR;
|
||||
static struct sockaddr_in6 mcast_addr = {
|
||||
struct sockaddr_in6 mcast_addr = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = ALL_NODES_LOCAL_COAP_MCAST,
|
||||
.sin6_port = htons(coap_port) };
|
||||
.sin6_port = htons(port) };
|
||||
struct net_if_addr *ifaddr;
|
||||
struct net_if *iface;
|
||||
int ret;
|
||||
|
@ -71,22 +151,36 @@ static int join_coap_multicast_group(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
wait_for_network();
|
||||
|
||||
return join_coap_multicast_group();
|
||||
}
|
||||
|
||||
#else /* CONFIG_NET_IPV6 */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
wait_for_network();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
COAP_SERVICE_DEFINE(coap_server, NULL, &coap_port, COAP_SERVICE_AUTOSTART);
|
||||
int main(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
wait_for_network();
|
||||
|
||||
ret = setup_dtls();
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to setup DTLS (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_NET_SAMPLE_COAPS_SERVICE) && defined(CONFIG_NET_IPV6)
|
||||
ret = join_coap_multicast_group(coap_port);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to join CoAP all-nodes multicast (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_SAMPLE_COAPS_SERVICE
|
||||
/* CoAP secure server has to be started manually after DTLS setup */
|
||||
ret = coap_service_start(&coap_server);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to start CoAP secure server (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue