Skip to content

Commit d8c310d

Browse files
committed
Add DTLS example
The server listens for the client to connect and send it a string. It then sends the same text back to the client.
1 parent 84e8d48 commit d8c310d

17 files changed

+2054
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ App|Description
196196
[picow_http_client](pico_w/wifi/http_client) | Demonstrates how to make http and https requests
197197
[picow_http_client_verify](pico_w/wifi/http_client) | Demonstrates how to make a https request with server authentication
198198
[picow_mqtt_client](pico_w/wifi/mqtt) | Demonstrates how to implement a MQTT client application
199+
[picow_dtls](pico_w/wifi/dtls) | Demonstrates how to implement a simple DTLS client and server
199200

200201
#### FreeRTOS examples
201202

pico_w/wifi/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ else()
1919
add_subdirectory_exclude_platforms(udp_beacon)
2020
add_subdirectory_exclude_platforms(http_client)
2121
add_subdirectory_exclude_platforms(mqtt)
22+
add_subdirectory_exclude_platforms(dtls)
2223

2324
if (NOT PICO_MBEDTLS_PATH)
2425
message("Skipping tls examples as PICO_MBEDTLS_PATH is not defined")

pico_w/wifi/dtls/CMakeLists.txt

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Pick DTLS server from environment
2+
if (DEFINED ENV{DTLS_SERVER} AND (NOT DTLS_SERVER))
3+
set(DTLS_SERVER $ENV{DTLS_SERVER})
4+
message("Using DTLS_SERVER from environment ('${DTLS_SERVER}')")
5+
endif()
6+
if (NOT DTLS_SERVER)
7+
message("Skipping DTLS example as DTLS_SERVER is not defined")
8+
return()
9+
endif()
10+
set(DTLS_SERVER "${DTLS_SERVER}" CACHE INTERNAL "DTLS server for examples")
11+
if (NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/certs/${DTLS_SERVER}")
12+
message("Generate DTLS certs by running ${CMAKE_CURRENT_LIST_DIR}/certs/makecerts.sh")
13+
return()
14+
endif()
15+
16+
set(RANDOM_DATA_LEN 32)
17+
string(RANDOM LENGTH ${RANDOM_DATA_LEN} RANDOM_DATA)
18+
19+
pico_add_library(pico_dtls)
20+
target_include_directories(pico_dtls_headers INTERFACE
21+
${CMAKE_CURRENT_LIST_DIR}
22+
)
23+
target_sources(pico_dtls INTERFACE
24+
${CMAKE_CURRENT_LIST_DIR}/dtls_common.c
25+
)
26+
pico_mirrored_target_link_libraries(pico_dtls INTERFACE
27+
pico_lwip_mbedtls
28+
pico_mbedtls
29+
)
30+
target_compile_definitions(pico_dtls INTERFACE
31+
CUSTOM_MBEDTLS_ENTROPY_PTR=\"${RANDOM_DATA}\"
32+
CUSTOM_MBEDTLS_ENTROPY_LEN=${RANDOM_DATA_LEN}
33+
)
34+
35+
set(TARGET_NAME dtls_echo_server)
36+
37+
add_executable(${TARGET_NAME}
38+
dtls_echo_server.c
39+
)
40+
target_include_directories(${TARGET_NAME} PRIVATE
41+
${CMAKE_CURRENT_LIST_DIR}
42+
${CMAKE_CURRENT_LIST_DIR}/..
43+
)
44+
target_link_libraries(${TARGET_NAME} PRIVATE
45+
pico_cyw43_arch_lwip_threadsafe_background
46+
pico_lwip_nosys
47+
pico_stdlib
48+
pico_dtls
49+
)
50+
target_compile_definitions(${TARGET_NAME} PRIVATE
51+
DTLS_CERT_INC=\"certs/${DTLS_SERVER}/dtls_server.inc\"
52+
)
53+
target_compile_definitions(${TARGET_NAME} PRIVATE
54+
CYW43_HOST_NAME=\"pico_dtls_example\"
55+
WIFI_SSID=\"${WIFI_SSID}\"
56+
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
57+
)
58+
pico_add_extra_outputs(${TARGET_NAME})
59+
60+
set(TARGET_NAME dtls_echo_client)
61+
62+
add_executable(${TARGET_NAME}
63+
dtls_echo_client.c
64+
)
65+
target_include_directories(${TARGET_NAME} PRIVATE
66+
${CMAKE_CURRENT_LIST_DIR}
67+
${CMAKE_CURRENT_LIST_DIR}/..
68+
)
69+
target_link_libraries(${TARGET_NAME} PRIVATE
70+
pico_cyw43_arch_lwip_threadsafe_background
71+
pico_lwip_nosys
72+
pico_stdlib
73+
pico_dtls
74+
)
75+
target_compile_definitions(${TARGET_NAME} PRIVATE
76+
DTLS_SERVER=\"${DTLS_SERVER}\"
77+
DTLS_CERT_INC=\"certs/${DTLS_SERVER}/dtls_client.inc\"
78+
)
79+
target_compile_definitions(${TARGET_NAME} PRIVATE
80+
WIFI_SSID=\"${WIFI_SSID}\"
81+
WIFI_PASSWORD=\"${WIFI_PASSWORD}\"
82+
)
83+
pico_add_extra_outputs(${TARGET_NAME})

pico_w/wifi/dtls/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Setup
2+
3+
These examples demonstrate how to use dtls via mbedtls on a Pico W device.
4+
You need to define DTLS_SERVER and run the makecerts.sh script to generate the certificates and keys needed for the server and client.
5+
```
6+
export DTLS_SERVER=myserver
7+
cd dtls/certs
8+
./makecerts.sh
9+
```
10+
The examples should now build.
11+
12+
# Running the dtls examples
13+
14+
The client connects to a server and sends it a few lines of text which it expects to be sent back.
15+
16+
You can build and run the client and server examples on two Pico W devices. To make testing easier to test with just one Pico W device, you can run the server or client on a Linux host.
17+
The client.sh and server.sh scripts show how to run the client or server with openssl. The host folder contains source code for a version of the client and server using mbedtls.
18+
19+
## Using openssl
20+
21+
The host/server.sh and host/client/sh scripts demonstrate how to use DTLS with openssl, although you will have to echo text manually.
22+
For example, run dtls_echo_client on a Pico W device and the server.sh on a linux PC.
23+
```
24+
export DTLS_SERVER=myserver
25+
cd host
26+
./server.sh
27+
```
28+
The scripts use the keys in certs/myserver
29+
30+
Or run dtls_echo_server on a Pico W device and client.sh on a linux PC. The host name for the server on Pico W is set to `pico_dtls_example`"`. Make sure you build the code for the Pico W and run the client with the right DTLS_SERVER name (and matching keys in the client and server) or else the SSL handshake will fail.
31+
```
32+
export DTLS_SERVER=pico_dtls_example
33+
ping pico_dtls_example # make sure you can reach it!
34+
cd host
35+
./client.sh
36+
```
37+
The scripts use the keys in certs/pico_dtls_example. Type a sentence into the client.sh console and the server should send it back as a reply.
38+
39+
## Using mbedtls
40+
41+
The host folder contains C versions of the examples that can be compiled natively for the host. They are modified versions of mbedtls examples.
42+
You can build these on a rpi linux device to act as the server or client. The mbedtls library in PICO_SDK_PATH will be used to build the host code.
43+
44+
For example, run dtls_echo_client on a Pico W device and the dtls_host_echo_server on a linux PC.
45+
```
46+
export DTLS_SERVER=myserver
47+
cd host
48+
mkdir build
49+
cd build
50+
cmake ..
51+
make -j8
52+
./dtls_host_echo_server
53+
54+
```
55+
Or run dtls_echo_server on a Pico W device and dtls_host_echo_client on a linux PC.
56+
```
57+
export DTLS_SERVER=pico_dtls_example
58+
cd host
59+
mkdir build
60+
cd build
61+
cmake ..
62+
make -j8
63+
./dtls_host_echo_client
64+
```
65+
Remember to build the client and server for the host and Pico W with the correct value of DTLS_SERVER or else the handshake will fail.

pico_w/wifi/dtls/certs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*/
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/bash
2+
3+
if [ "${PWD##*/}" != "certs" ]; then
4+
echo Run this in the certs folder
5+
exit 1
6+
fi
7+
if [ -z "$DTLS_SERVER" ]; then
8+
echo Define DTLS_SERVER
9+
exit 1
10+
fi
11+
SERVER_NAME=$DTLS_SERVER
12+
13+
if [ -d "$SERVER_NAME" ]; then
14+
echo Run \"rm -fr $SERVER_NAME\" to regenerate these keys
15+
exit 1
16+
fi
17+
mkdir $SERVER_NAME
18+
echo Generating keys in $PWD/$SERVER_NAME
19+
20+
openssl genrsa -out $SERVER_NAME/ca.key 2048
21+
openssl req -new -x509 -days 99999 -key $SERVER_NAME/ca.key -out $SERVER_NAME/ca.crt -subj "/C=UK/ST=Cambridgeshire/L=Cambridge/O=Raspberry Pi Ltd/OU=Software/CN=rpiroot"
22+
23+
openssl genrsa -out $SERVER_NAME/server.key 2048
24+
openssl req -new -out $SERVER_NAME/server.csr -key $SERVER_NAME/server.key -subj "/C=UK/ST=Cambridgeshire/L=Cambridge/O=Raspberry Pi Ltd/OU=Software/CN=$SERVER_NAME"
25+
openssl x509 -req -in $SERVER_NAME/server.csr -CA $SERVER_NAME/ca.crt -CAkey $SERVER_NAME/ca.key -CAcreateserial -out $SERVER_NAME/server.crt -days 9999
26+
27+
openssl genrsa -out $SERVER_NAME/client.key 2048
28+
openssl req -new -out $SERVER_NAME/client.csr -key $SERVER_NAME/client.key -subj "/C=UK/ST=Cambridgeshire/L=Cambridge/O=Raspberry Pi Ltd/OU=Software/CN=$SERVER_NAME"
29+
openssl x509 -req -in $SERVER_NAME/client.csr -CA $SERVER_NAME/ca.crt -CAkey $SERVER_NAME/ca.key -CAcreateserial -out $SERVER_NAME/client.crt -days 999
30+
31+
echo -n \#define DTLS_ROOT_CERT \" > $SERVER_NAME/dtls_client.inc
32+
cat $SERVER_NAME/ca.crt | awk '{printf "%s\\n\\\n", $0}' >> $SERVER_NAME/dtls_client.inc
33+
echo "\"" >> $SERVER_NAME/dtls_client.inc
34+
echo >> $SERVER_NAME/dtls_client.inc
35+
36+
echo -n \#define DTLS_KEY \" >> $SERVER_NAME/dtls_client.inc
37+
cat $SERVER_NAME/client.key | awk '{printf "%s\\n\\\n", $0}' >> $SERVER_NAME/dtls_client.inc
38+
echo "\"" >> $SERVER_NAME/dtls_client.inc
39+
echo >> $SERVER_NAME/dtls_client.inc
40+
41+
echo -n \#define DTLS_CERT \" >> $SERVER_NAME/dtls_client.inc
42+
cat $SERVER_NAME/client.crt | awk '{printf "%s\\n\\\n", $0}' >> $SERVER_NAME/dtls_client.inc
43+
echo "\"" >> $SERVER_NAME/dtls_client.inc
44+
45+
echo -n \#define DTLS_ROOT_CERT \" > $SERVER_NAME/dtls_server.inc
46+
cat $SERVER_NAME/ca.crt | awk '{printf "%s\\n\\\n", $0}' >> $SERVER_NAME/dtls_server.inc
47+
echo "\"" >> $SERVER_NAME/dtls_server.inc
48+
echo >> $SERVER_NAME/dtls_server.inc
49+
50+
echo -n \#define DTLS_KEY \" >> $SERVER_NAME/dtls_server.inc
51+
cat $SERVER_NAME/server.key | awk '{printf "%s\\n\\\n", $0}' >> $SERVER_NAME/dtls_server.inc
52+
echo "\"" >> $SERVER_NAME/dtls_server.inc
53+
echo >> $SERVER_NAME/dtls_server.inc
54+
55+
echo -n \#define DTLS_CERT \" >> $SERVER_NAME/dtls_server.inc
56+
cat $SERVER_NAME/server.crt | awk '{printf "%s\\n\\\n", $0}' >> $SERVER_NAME/dtls_server.inc
57+
echo "\"" >> $SERVER_NAME/dtls_server.inc

0 commit comments

Comments
 (0)