Skip to content
Draft
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
14 changes: 14 additions & 0 deletions .github/examples-manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,20 @@ examples:
# {client,server}-tls-uart (needs /dev/ttyUSB0), and the four *-perf
# benchmarks. All still build.

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

- id: dtls
path: dtls
profile: dtls
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ jobs:
# Before the run: run_example.py execs itself into a netns with only
# loopback, so an example needing a third-party tree has to get it now.
- name: Fetch third-party sources for ${{ matrix.id }}
env:
# for a third-party tree that builds the wolfSSL sources under test
WOLFSSL_REF: ${{ matrix.wolfssl_ref }}
run: |
python3 .github/scripts/run_example.py --only '${{ matrix.id }}' --fetch

Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ android/wolfssljni-ndk-sample/proguard-project.txt
/psk/server-psk
/psk/server-tcp

/mbedtls-compat/client-tls-mbedtls
/mbedtls-compat/check-server-tls12
/mbedtls-compat/check-server-tls13

/tls/client-async
/tls/client-tcp
/tls/client-tls
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,25 @@ and example keystores.
Please see the [java/README.md](java/README.md) for further usage and details.


<br />

#### mbedtls-compat (Mbed TLS Compatibility)

This directory contains a client written for the Mbed TLS 4.x API, built on
wolfSSL through the Mbed TLS compatibility layer in wolfPSA.

The client links wolfPSA, built with the compatibility layer, in place of the
Mbed TLS libraries:

```
cd wolfpsa
make MBEDTLS_COMPAT=1 WOLFSSL_PATH=../wolfssl
```

Please see the [mbedtls-compat/README.md](mbedtls-compat/README.md) for further
usage and details.


<br />

#### mynewt (Apache Mynewt Examples)
Expand Down
38 changes: 38 additions & 0 deletions mbedtls-compat/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Mbed TLS Compatibility Example Makefile
CC = gcc
WOLFSSL_INSTALL_DIR = /usr/local
# wolfPSA built with MBEDTLS_COMPAT=1
WOLFPSA_DIR = ../../wolfpsa
CFLAGS = -Wall -I$(WOLFSSL_INSTALL_DIR)/include
LIBS = -L$(WOLFSSL_INSTALL_DIR)/lib -lwolfssl -lm
# The client uses only wolfPSA, so <mbedtls/ssl.h> resolves to wolfPSA
PSA_CFLAGS = -Wall -I$(WOLFPSA_DIR)/wolfpsa -I$(WOLFPSA_DIR)/build/include
PSA_LIBS = $(WOLFPSA_DIR)/libwolfpsa.a -lm

TARGETS = client-tls-mbedtls
# ../tls/server-tls13 requires a client certificate, which this client does
# not send, so make check runs ../tls/server-tls built for each version
CHECK_SERVERS = check-server-tls12 check-server-tls13

all: $(TARGETS)

$(WOLFPSA_DIR)/libwolfpsa.a:
@echo "$@ not found, build wolfPSA with make MBEDTLS_COMPAT=1"
@false

%: %.c $(WOLFPSA_DIR)/libwolfpsa.a
$(CC) -o $@ $< $(PSA_CFLAGS) $(PSA_LIBS)

check-server-tls12: ../tls/server-tls.c
$(CC) -o $@ $< $(CFLAGS) $(LIBS)

check-server-tls13: ../tls/server-tls.c
$(CC) -o $@ $< -DUSE_TLSV13 $(CFLAGS) $(LIBS)

check: $(TARGETS) $(CHECK_SERVERS)
./check.sh

clean:
rm -f $(TARGETS) $(CHECK_SERVERS)

.PHONY: all check clean
87 changes: 87 additions & 0 deletions mbedtls-compat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Mbed TLS Compatibility Example

`client-tls-mbedtls.c` is an application written for the Mbed TLS 4.x API,
built on wolfSSL through the Mbed TLS compatibility layer in
[wolfPSA](https://github.com/wolfSSL/wolfpsa). Its `tls_get()` function is the
client from the "Porting a TLS Client" chapter of the Mbed TLS to wolfSSL
migration guide, unchanged.

wolfPSA provides the PSA Crypto API on wolfCrypt, as TF-PSA-Crypto does for
Mbed TLS. Built with `MBEDTLS_COMPAT=1`, it also provides the Mbed TLS TLS,
X.509 and network API on wolfSSL, so the client links `libwolfpsa.a` in place
of `libmbedtls`, `libmbedx509` and `libtfpsacrypto`. The calls mapped so far
and the known differences from Mbed TLS are in wolfPSA's README, section
"Mbed TLS compatibility".

## Building

Build wolfPSA with the compatibility layer, next to `wolfssl-examples`. It
compiles wolfCrypt and the wolfSSL TLS sources from `WOLFSSL_PATH` into
`libwolfpsa.a` with its own settings, so the client needs no wolfSSL install:

```
cd wolfpsa
make MBEDTLS_COMPAT=1 WOLFSSL_PATH=../wolfssl
```

Then build the example (set `WOLFPSA_DIR` if wolfPSA is elsewhere):

```
make
```

The Makefile puts wolfPSA's headers on the include path, so `<mbedtls/ssl.h>`
resolves to wolfPSA even if Mbed TLS is installed too.

## Running

The servers are wolfSSL programs, built from `../tls/server-tls.c` against an
installed wolfSSL, as for the other examples:

```
cd wolfssl
./configure
make
sudo make install
sudo ldconfig
```

Start a TLS 1.3 server, then run the client:

```
make check-server-tls13
./check-server-tls13 &
./client-tls-mbedtls 127.0.0.1
```

```
tls_get() returned 0
```

The client checks the server certificate against `../certs/ca-cert.pem` and
the name `example.com`. Options:

* `-A <file>` CA certificate file, PEM or DER
* `-S <name>` server name to send and check
* `-N` use a non-blocking socket

## Testing

`make check` builds `../tls/server-tls.c` as `check-server-tls12` and
`check-server-tls13` and runs the client against them for TLS 1.2 and 1.3,
blocking and non-blocking, and for each failure it should report: wrong server
name, wrong CA, missing CA file and a CA file that is not a certificate.
`../tls/server-tls13` is not used because it requires a client certificate,
which this client does not send.

A wrong server name or CA fails with `MBEDTLS_ERR_X509_CERT_VERIFY_FAILED`
(`-9984`), and a CA file that is not a certificate with
`MBEDTLS_ERR_X509_INVALID_FORMAT` (`-8576`). The compatibility layer returns
only Mbed TLS codes: a wolfSSL error with no Mbed TLS match returns a general
code for the call, such as `MBEDTLS_ERR_SSL_INTERNAL_ERROR`.

`check.sh` runs the client and servers from `BIN_DIR`, by default the current
directory.

An IP address passed to `-S` fails with `MBEDTLS_ERR_SSL_BAD_INPUT_DATA`
(`-135`), because the compatibility layer does not map IP address checks yet.
57 changes: 57 additions & 0 deletions mbedtls-compat/check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/sh

# Run client-tls-mbedtls against the check servers. Each case gets a new
# server because they exit after a failed handshake. WRAP prefixes the client.
# BIN_DIR is where they are built, by default the current directory.

BIN_DIR=${BIN_DIR:-.}
FAILS=0

# Retry while the server is not listening yet. A probe connection would end
# the server, since it exits when a handshake fails.
run_client() {
i=0
while :; do
out=$($WRAP "$BIN_DIR/client-tls-mbedtls" $opts 127.0.0.1 2>&1)
rc=$?
[ "$out" != "ERROR: failed to connect" ] && return
i=$((i + 1))
[ $i -ge 50 ] && return
sleep 0.1
done
}

# name|server|client options|expected tls_get() return
while IFS='|' read -r name server opts expect; do
[ -z "$name" ] && continue
"$BIN_DIR/$server" >/dev/null 2>&1 &
srv=$!
run_client
want=1
[ "$expect" -eq 0 ] && want=0
if [ "$out" = "tls_get() returned $expect" ] && [ $rc -eq $want ]; then
echo "PASS: $name"
else
echo "FAIL: $name: $out"
FAILS=$((FAILS + 1))
fi
kill $srv 2>/dev/null
wait $srv 2>/dev/null
done <<EOF
TLS 1.3|check-server-tls13||0
TLS 1.2|check-server-tls12||0
TLS 1.3 non-blocking|check-server-tls13|-N|0
TLS 1.2 non-blocking|check-server-tls12|-N|0
DER CA file|check-server-tls13|-A ../certs/ca-cert.der|0
wrong host, VERIFY_FAILED|check-server-tls13|-S wrong.example.org|-9984
wrong CA, VERIFY_FAILED|check-server-tls13|-A ../certs/ca-ecc-cert.pem|-9984
no CA file, X509_FILE_IO_ERROR|check-server-tls13|-A ../certs/missing.pem|-10496
not a certificate, X509_INVALID_FORMAT|check-server-tls13|-A README.md|-8576
IP address host, SSL_BAD_INPUT_DATA|check-server-tls13|-S 127.0.0.1|-135
EOF

if [ $FAILS -ne 0 ]; then
echo "$FAILS failed"
exit 1
fi
echo "PASS: mbedtls-compat checks"
Loading
Loading