Skip to content

Commit 1fc1481

Browse files
committed
Add MbedTLS example
1 parent a8a1b75 commit 1fc1481

8 files changed

Lines changed: 383 additions & 0 deletions

File tree

‎.github/examples-manifest.yml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,20 @@ examples:
987987
# {client,server}-tls-uart (needs /dev/ttyUSB0), and the four *-perf
988988
# benchmarks. All still build.
989989

990+
- id: mbedtls-compat
991+
path: mbedtls-compat
992+
# default is only for the servers. The client links wolfPSA, built below.
993+
profile: default
994+
# wolfPSA master until a release has MBEDTLS_COMPAT, then pin that tag
995+
fetch:
996+
- [sh, -c, "test -d ../../wolfssl || git clone -q --depth 1 --branch \"${WOLFSSL_REF:-master}\" https://github.com/wolfSSL/wolfssl ../../wolfssl"]
997+
- [sh, -c, "test -d ../../wolfpsa || git clone -q --depth 1 --branch master https://github.com/wolfSSL/wolfpsa ../../wolfpsa"]
998+
- [sh, -c, "cd ../../wolfpsa && make -j\"$(nproc)\" MBEDTLS_COMPAT=1 WOLFSSL_PATH=../wolfssl"]
999+
# make check builds ../tls/server-tls.c for TLS 1.2 and 1.3 and runs the
1000+
# client against it, one server per case. tls/server-tls13 is not used: it
1001+
# requires a client certificate, which this client does not send.
1002+
mode: check
1003+
9901004
- id: dtls
9911005
path: dtls
9921006
profile: dtls

‎.github/workflows/examples.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ jobs:
155155
# Before the run: run_example.py execs itself into a netns with only
156156
# loopback, so an example needing a third-party tree has to get it now.
157157
- name: Fetch third-party sources for ${{ matrix.id }}
158+
env:
159+
# for a third-party tree that builds the wolfSSL sources under test
160+
WOLFSSL_REF: ${{ matrix.wolfssl_ref }}
158161
run: |
159162
python3 .github/scripts/run_example.py --only '${{ matrix.id }}' --fetch
160163

‎.gitignore‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ android/wolfssljni-ndk-sample/proguard-project.txt
8282
/psk/server-psk
8383
/psk/server-tcp
8484

85+
/mbedtls-compat/client-tls-mbedtls
86+
/mbedtls-compat/check-server-tls12
87+
/mbedtls-compat/check-server-tls13
88+
8589
/tls/client-async
8690
/tls/client-tcp
8791
/tls/client-tls

‎README.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,25 @@ and example keystores.
179179
Please see the [java/README.md](java/README.md) for further usage and details.
180180

181181

182+
<br />
183+
184+
#### mbedtls-compat (Mbed TLS Compatibility)
185+
186+
This directory contains a client written for the Mbed TLS 4.x API, built on
187+
wolfSSL through the Mbed TLS compatibility layer in wolfPSA.
188+
189+
The client links wolfPSA, built with the compatibility layer, in place of the
190+
Mbed TLS libraries:
191+
192+
```
193+
cd wolfpsa
194+
make MBEDTLS_COMPAT=1 WOLFSSL_PATH=../wolfssl
195+
```
196+
197+
Please see the [mbedtls-compat/README.md](mbedtls-compat/README.md) for further
198+
usage and details.
199+
200+
182201
<br />
183202

184203
#### mynewt (Apache Mynewt Examples)

‎mbedtls-compat/Makefile‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Mbed TLS Compatibility Example Makefile
2+
CC = gcc
3+
WOLFSSL_INSTALL_DIR = /usr/local
4+
# wolfPSA built with MBEDTLS_COMPAT=1
5+
WOLFPSA_DIR = ../../wolfpsa
6+
CFLAGS = -Wall -I$(WOLFSSL_INSTALL_DIR)/include
7+
LIBS = -L$(WOLFSSL_INSTALL_DIR)/lib -lwolfssl -lm
8+
# The client uses only wolfPSA, so <mbedtls/ssl.h> resolves to wolfPSA
9+
PSA_CFLAGS = -Wall -I$(WOLFPSA_DIR)/wolfpsa -I$(WOLFPSA_DIR)/build/include
10+
PSA_LIBS = $(WOLFPSA_DIR)/libwolfpsa.a -lm
11+
12+
TARGETS = client-tls-mbedtls
13+
# ../tls/server-tls13 requires a client certificate, which this client does
14+
# not send, so make check runs ../tls/server-tls built for each version
15+
CHECK_SERVERS = check-server-tls12 check-server-tls13
16+
17+
all: $(TARGETS)
18+
19+
$(WOLFPSA_DIR)/libwolfpsa.a:
20+
@echo "$@ not found, build wolfPSA with make MBEDTLS_COMPAT=1"
21+
@false
22+
23+
%: %.c $(WOLFPSA_DIR)/libwolfpsa.a
24+
$(CC) -o $@ $< $(PSA_CFLAGS) $(PSA_LIBS)
25+
26+
check-server-tls12: ../tls/server-tls.c
27+
$(CC) -o $@ $< $(CFLAGS) $(LIBS)
28+
29+
check-server-tls13: ../tls/server-tls.c
30+
$(CC) -o $@ $< -DUSE_TLSV13 $(CFLAGS) $(LIBS)
31+
32+
check: $(TARGETS) $(CHECK_SERVERS)
33+
./check.sh
34+
35+
clean:
36+
rm -f $(TARGETS) $(CHECK_SERVERS)
37+
38+
.PHONY: all check clean

‎mbedtls-compat/README.md‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Mbed TLS Compatibility Example
2+
3+
`client-tls-mbedtls.c` is an application written for the Mbed TLS 4.x API,
4+
built on wolfSSL through the Mbed TLS compatibility layer in
5+
[wolfPSA](https://github.com/wolfSSL/wolfpsa). Its `tls_get()` function is the
6+
client from the "Porting a TLS Client" chapter of the Mbed TLS to wolfSSL
7+
migration guide, unchanged.
8+
9+
wolfPSA provides the PSA Crypto API on wolfCrypt, as TF-PSA-Crypto does for
10+
Mbed TLS. Built with `MBEDTLS_COMPAT=1`, it also provides the Mbed TLS TLS,
11+
X.509 and network API on wolfSSL, so the client links `libwolfpsa.a` in place
12+
of `libmbedtls`, `libmbedx509` and `libtfpsacrypto`. The calls mapped so far
13+
and the known differences from Mbed TLS are in wolfPSA's README, section
14+
"Mbed TLS compatibility".
15+
16+
## Building
17+
18+
Build wolfPSA with the compatibility layer, next to `wolfssl-examples`. It
19+
compiles wolfCrypt and the wolfSSL TLS sources from `WOLFSSL_PATH` into
20+
`libwolfpsa.a` with its own settings, so the client needs no wolfSSL install:
21+
22+
```
23+
cd wolfpsa
24+
make MBEDTLS_COMPAT=1 WOLFSSL_PATH=../wolfssl
25+
```
26+
27+
Then build the example (set `WOLFPSA_DIR` if wolfPSA is elsewhere):
28+
29+
```
30+
make
31+
```
32+
33+
The Makefile puts wolfPSA's headers on the include path, so `<mbedtls/ssl.h>`
34+
resolves to wolfPSA even if Mbed TLS is installed too.
35+
36+
## Running
37+
38+
The servers are wolfSSL programs, built from `../tls/server-tls.c` against an
39+
installed wolfSSL, as for the other examples:
40+
41+
```
42+
cd wolfssl
43+
./configure
44+
make
45+
sudo make install
46+
sudo ldconfig
47+
```
48+
49+
Start a TLS 1.3 server, then run the client:
50+
51+
```
52+
make check-server-tls13
53+
./check-server-tls13 &
54+
./client-tls-mbedtls 127.0.0.1
55+
```
56+
57+
```
58+
tls_get() returned 0
59+
```
60+
61+
The client checks the server certificate against `../certs/ca-cert.pem` and
62+
the name `example.com`. Options:
63+
64+
* `-A <file>` CA certificate file, PEM or DER
65+
* `-S <name>` server name to send and check
66+
* `-N` use a non-blocking socket
67+
68+
## Testing
69+
70+
`make check` builds `../tls/server-tls.c` as `check-server-tls12` and
71+
`check-server-tls13` and runs the client against them for TLS 1.2 and 1.3,
72+
blocking and non-blocking, and for each failure it should report: wrong server
73+
name, wrong CA, missing CA file and a CA file that is not a certificate.
74+
`../tls/server-tls13` is not used because it requires a client certificate,
75+
which this client does not send.
76+
77+
A wrong server name or CA fails with `MBEDTLS_ERR_X509_CERT_VERIFY_FAILED`
78+
(`-9984`), and a CA file that is not a certificate with
79+
`MBEDTLS_ERR_X509_INVALID_FORMAT` (`-8576`). The compatibility layer returns
80+
only Mbed TLS codes: a wolfSSL error with no Mbed TLS match returns a general
81+
code for the call, such as `MBEDTLS_ERR_SSL_INTERNAL_ERROR`.
82+
83+
`check.sh` runs the client and servers from `BIN_DIR`, by default the current
84+
directory.
85+
86+
An IP address passed to `-S` fails with `MBEDTLS_ERR_SSL_BAD_INPUT_DATA`
87+
(`-135`), because the compatibility layer does not map IP address checks yet.

‎mbedtls-compat/check.sh‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/sh
2+
3+
# Run client-tls-mbedtls against the check servers. Each case gets a new
4+
# server because they exit after a failed handshake. WRAP prefixes the client.
5+
# BIN_DIR is where they are built, by default the current directory.
6+
7+
BIN_DIR=${BIN_DIR:-.}
8+
FAILS=0
9+
10+
# Retry while the server is not listening yet. A probe connection would end
11+
# the server, since it exits when a handshake fails.
12+
run_client() {
13+
i=0
14+
while :; do
15+
out=$($WRAP "$BIN_DIR/client-tls-mbedtls" $opts 127.0.0.1 2>&1)
16+
rc=$?
17+
[ "$out" != "ERROR: failed to connect" ] && return
18+
i=$((i + 1))
19+
[ $i -ge 50 ] && return
20+
sleep 0.1
21+
done
22+
}
23+
24+
# name|server|client options|expected tls_get() return
25+
while IFS='|' read -r name server opts expect; do
26+
[ -z "$name" ] && continue
27+
"$BIN_DIR/$server" >/dev/null 2>&1 &
28+
srv=$!
29+
run_client
30+
want=1
31+
[ "$expect" -eq 0 ] && want=0
32+
if [ "$out" = "tls_get() returned $expect" ] && [ $rc -eq $want ]; then
33+
echo "PASS: $name"
34+
else
35+
echo "FAIL: $name: $out"
36+
FAILS=$((FAILS + 1))
37+
fi
38+
kill $srv 2>/dev/null
39+
wait $srv 2>/dev/null
40+
done <<EOF
41+
TLS 1.3|check-server-tls13||0
42+
TLS 1.2|check-server-tls12||0
43+
TLS 1.3 non-blocking|check-server-tls13|-N|0
44+
TLS 1.2 non-blocking|check-server-tls12|-N|0
45+
DER CA file|check-server-tls13|-A ../certs/ca-cert.der|0
46+
wrong host, VERIFY_FAILED|check-server-tls13|-S wrong.example.org|-9984
47+
wrong CA, VERIFY_FAILED|check-server-tls13|-A ../certs/ca-ecc-cert.pem|-9984
48+
no CA file, X509_FILE_IO_ERROR|check-server-tls13|-A ../certs/missing.pem|-10496
49+
not a certificate, X509_INVALID_FORMAT|check-server-tls13|-A README.md|-8576
50+
IP address host, SSL_BAD_INPUT_DATA|check-server-tls13|-S 127.0.0.1|-135
51+
EOF
52+
53+
if [ $FAILS -ne 0 ]; then
54+
echo "$FAILS failed"
55+
exit 1
56+
fi
57+
echo "PASS: mbedtls-compat checks"

0 commit comments

Comments
 (0)