Skip to content

Commit

Permalink
tests: net: socket_tls: test different TLS configurations with sockets
Browse files Browse the repository at this point in the history
This commit adds a test to showcase how to configure TLS 1.2 and 1.3
socket connections against an OpenSSL server. Only a limited number
of combinations are available for now:

- TLS 1.2
	- RSA certificate and key exchange.
	- ECDSA certificate and ECDHE key exchange.

- TLS 1.3 only supports ephemeral (ECDHE) key exchange with/without
  session tickets.

Since the goal is to test TLS connection and not low level ethernet
functionalities or similar, the only supported platform is "native_sim"
where Linux sockets are used to connect to the OpenSSL server locally.

The idea is that the Zephyr application acts a client and tries to connect
to the OpenSSL server running on the same PC. For sake of simplificity a
bash script is provided to start the OpenSSL server properly.
For completeness a bash script is also provided to re-generate
certificates and keys.

Signed-off-by: Valerio Setti <[email protected]>
  • Loading branch information
valeriosetti authored and nashif committed Sep 12, 2024
1 parent 6be57aa commit 91fa8a2
Show file tree
Hide file tree
Showing 15 changed files with 578 additions and 0 deletions.
27 changes: 27 additions & 0 deletions tests/net/socket/tls_configurations/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

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

target_sources(app PRIVATE src/main.c)

set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)

# Helper function to convert the content of a PEM file (generated by OpenSSL)
# to a C string that can be parsed by Mbed TLS. The format is unchanged, it's
# still PEM, but new lines are replaced by "\n", so that both C compiler and
# Mbed TLS parser are happy.
function(pem_to_mbedtls target input_file)
file(READ credentials/${input_file} 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 ec.crt)
pem_to_mbedtls(app rsa.crt)
8 changes: 8 additions & 0 deletions tests/net/socket/tls_configurations/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

config SERVER_PORT
int "Server port to connect to"
default 4242

source "Kconfig.zephyr"
5 changes: 5 additions & 0 deletions tests/net/socket/tls_configurations/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 tests/net/socket/tls_configurations/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-----
28 changes: 28 additions & 0 deletions tests/net/socket/tls_configurations/credentials/rsa-priv.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRaXhTWuxKafRh
fsewYRSRjpeOQJPqY1u38eTFFgcb4oAZOguoubEpJHui3olEWdcyfREx+GsDUo1n
5G6az6m65tCSAKEoFumREhDngt3crdw91hnrnBPjnpCNzeGQ1EqBFbW9mwjp1xQY
pBG0pCwdGIxlzW9ufVrtTbmLp1xcz3U7/RJBwDTX1o+u1oV5mJ9+oYtMQ1b8mOcr
f8Wdg01CWk0ag/C2os07XmRNOCUdO1kh1BHQuPV5K+tgdgHOZdYBBHv8LCgT+FO9
8r3lhuzVsWTyJLGYYTFnT5b8EtpilnsTDZykmTqzTF3tFejY4OgWS8kmUgEG6QLn
+Q+ewaKxAgMBAAECggEAdA3fgVKCYTsXFHEOedFTdNdxZoSjdOJbkjWccx0iE3IT
S+e/TmKarBJr8nch259ug6yMOwVRSSYW99zA70rm5Y3FSSTQK0eHab55X9RG4GX6
CMr+0nRNEXhu5CeVOo5sO92sOsgQyIdJu94xccsKJ5XTORgBCVqvaZQJoDvAFC5j
ErZpwYYl0P9Dx/jRSrqC0llOBASj0EMfPVSoImxuiGIKrT+flD2GR0IBJ6BjD+k8
wgWNdqv8pq4MGs/lodqA8DPnealcCVaCwobIzUWHjjW06m++iFL9d3LDr9rHMDG8
rp6pE9D2fn8wb43wiTe++n6zFNLnzVfNQS/P33jCAQKBgQD/Gj9+ypciFMuWedDl
9qgmttjzUcEyyAViD4FWSsef98MLgcxDdz9o/BxS4xJUbxPj/lAaakEFVIStoFo5
Meu5cHGYA35Wm5193g9i7YQI/wLyS/SnHV3O8GixqIwI5Mci/MXbvKb5TwQBRS3+
3MXqBewL7OTXmkqXmpF9BSE3PQKBgQDSJhJocS8cheIAmWp94SLmTrCuxy1HeDFL
0PiIMlWbxvpdO0RUd1hg1IOk21z/7llwxh8JPtFYcQogJA4/WfBHy4Vqh483SYj8
8aOrkxbRNE3j3+VSCTZReX6ACRsReHJTktEsI07iU3Bnmpwg2x3d6D4JUqVZA4PX
nbimkP6whQKBgQCCLT/HkNQstRXq9MCwCP1nvBjbmZWQN1ff4W+rvD9AF2u1nIfC
ycBW74f4mB1Lbt9kkesIf74sXSPTgidoVlwm5gVhgC7hPUnR6BZL8k5VVOSJBk+T
U74CEtYqCotjInOoG/tPlWZThInTqBy/mKN6N4lr0Hg6uWZlFKA3fv2jNQKBgGvw
fjgDGs2tvt3L7zTk9MYS2RGM4Kb7B2cH2QArymkPFP3aOUihXFWwEkYVHnmedXZF
bR+Ukna46RiFLIRBr/dQhCCprFgbfy9c9lJkZK3kDbXkBKfUb3/9xYoCI1Mf6Kkg
mivvns8FSJEOiu8dXQPkDClBuAg2k/ul2XhEtWz5AoGBAN8LRCutUDkBT7kr072O
m0fGQFzKq3jN8otsSfdBb40pqZqBCNAn/ojBAc2wcqLMUMHU9cHvEntsXZCbDmmO
5Mx3UF3mUCYAqcl6YCP9qiL6etBqD0q8TGngAT2MoMweh3xaHpSOcT4qISunW5ZG
6LTYdd5z+ab+sHB0pUTrsFER
-----END PRIVATE KEY-----
19 changes: 19 additions & 0 deletions tests/net/socket/tls_configurations/credentials/rsa.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCTCCAfGgAwIBAgIUQxMu5/uGKh0/cmqChP7kIeSFm5wwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDgyNzA5NDcxN1oXDTM0MDgy
NTA5NDcxN1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA0Wl4U1rsSmn0YX7HsGEUkY6XjkCT6mNbt/HkxRYHG+KA
GToLqLmxKSR7ot6JRFnXMn0RMfhrA1KNZ+Rums+puubQkgChKBbpkRIQ54Ld3K3c
PdYZ65wT456Qjc3hkNRKgRW1vZsI6dcUGKQRtKQsHRiMZc1vbn1a7U25i6dcXM91
O/0SQcA019aPrtaFeZiffqGLTENW/JjnK3/FnYNNQlpNGoPwtqLNO15kTTglHTtZ
IdQR0Lj1eSvrYHYBzmXWAQR7/CwoE/hTvfK95Ybs1bFk8iSxmGExZ0+W/BLaYpZ7
Ew2cpJk6s0xd7RXo2ODoFkvJJlIBBukC5/kPnsGisQIDAQABo1MwUTAdBgNVHQ4E
FgQU76/m3HsYiudPteCzusB4UmGFb5UwHwYDVR0jBBgwFoAU76/m3HsYiudPteCz
usB4UmGFb5UwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAXhaB
lnyVhD5NSAEx4K6jCB3qTkk4QX90C2m2WVPP+8CXVcvbGWeSWpRUS4Xh1Cv3Ic1g
Zb+QZL5d+KWwC+u2Ih44bVuO0xNqhya+SBDzF8h/hmeR4dWerwrWUE5NCHzByxDM
tcyKRzINIOta9fSuiacD+k/3I4ns9UcXWLRwAD2g/M03dYir5GjJySW7q9pRxKdy
SvkhZOXdPsDjJveJJztMurox8rsXANsWsMrjJ3EEkhxCZRjdjq0CrCtryHHIJSTf
Cu9MFtWpV1xvJQeIoCKBed076T1XPYUG5q1TO96GZgv+1o6+Mbd8j4myyt2KkuP4
6tvuNznVD1ykZK3OdQ==
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions tests/net/socket/tls_configurations/overlay-ec.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CONFIG_PSA_WANT_ALG_ECDH=y
CONFIG_PSA_WANT_ALG_ECDSA=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE=y
CONFIG_PSA_WANT_ECC_SECP_R1_256=y
4 changes: 4 additions & 0 deletions tests/net/socket/tls_configurations/overlay-rsa.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CONFIG_PSA_WANT_ALG_RSA_OAEP=y
CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_CRYPT=y
CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_SIGN=y
CONFIG_PSA_WANT_ALG_RSA_PSS=y
8 changes: 8 additions & 0 deletions tests/net/socket/tls_configurations/overlay-tls12.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CONFIG_MBEDTLS_TLS_VERSION_1_2=y
CONFIG_PSA_WANT_ALG_TLS12_PRF=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_PSA_WANT_KEY_TYPE_HMAC=y
CONFIG_PSA_WANT_ALG_HMAC=y
8 changes: 8 additions & 0 deletions tests/net/socket/tls_configurations/overlay-tls13.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
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
52 changes: 52 additions & 0 deletions tests/net/socket/tls_configurations/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Kernel options
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_POSIX_API=y
CONFIG_HEAP_MEM_POOL_SIZE=2048

# Generic networking options
CONFIG_NETWORKING=y

# Socket
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y

# Disable native ethernet driver (using native sockets instead)
CONFIG_ETH_NATIVE_POSIX=n

# Use native sockets
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_DRIVERS=y
CONFIG_NET_NATIVE_OFFLOADED_SOCKETS=y

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

# Disable some Kconfigs that are implied by CONFIG_NET_SOCKETS_SOCKOPT_TLS.
# These are not wrong in general, but specific to a certain case (TLS 1.2 + RSA
# key exchange/certificate + AES encryption). What we want here instead is to
# have a basic configuration in this "prj.conf" file and then add algorithm
# support in overlay files.
CONFIG_MBEDTLS_TLS_VERSION_1_2=n
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=n
CONFIG_MBEDTLS_CIPHER_AES_ENABLED=n
CONFIG_PSA_WANT_KEY_TYPE_AES=n
CONFIG_PSA_WANT_ALG_CBC_NO_PADDING=n

# Logging
CONFIG_LOG=y
CONFIG_PRINTK=y

# Debug log options (optional)
# CONFIG_NET_LOG=y
# CONFIG_MBEDTLS_LOG_LEVEL_DBG=y
# CONFIG_MBEDTLS_DEBUG=y
17 changes: 17 additions & 0 deletions tests/net/socket/tls_configurations/pytest/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0

import pytest

def pytest_addoption(parser):
parser.addoption('--server-type')
parser.addoption('--port')

@pytest.fixture()
def server_type(request):
return request.config.getoption('--server-type')

@pytest.fixture()
def port(request):
return request.config.getoption('--port')
80 changes: 80 additions & 0 deletions tests/net/socket/tls_configurations/pytest/test_app_vs_openssl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0

import logging
import os
import subprocess
from twister_harness import DeviceAdapter

logger = logging.getLogger(__name__)

def get_arguments_from_server_type(server_type, port):
this_path = os.path.dirname(os.path.abspath(__file__))
certs_path = os.path.join(this_path, "..", "credentials")

args = ["openssl", "s_server"]
if server_type == "1.2-rsa":
args.extend(["-cert", "{}/rsa.crt".format(certs_path),
"-key", "{}/rsa-priv.key".format(certs_path),
"-certform", "PEM",
"-tls1_2",
"-cipher", "AES128-SHA256,AES256-SHA256"])
elif server_type == "1.2-ec":
args.extend(["-cert", "{}/ec.crt".format(certs_path),
"-key", "{}/ec-priv.key".format(certs_path),
"-certform", "PEM",
"-tls1_2",
"-cipher", "ECDHE-ECDSA-AES128-SHA256"])
elif server_type == "1.3-ephemeral":
args.extend(["-cert", "{}/ec.crt".format(certs_path),
"-key", "{}/ec-priv.key".format(certs_path),
"-certform", "PEM",
"-tls1_3",
"-ciphersuites", "TLS_AES_128_GCM_SHA256",
"-num_tickets", "0"])
elif server_type == "1.3-ephemeral-tickets":
args.extend(["-cert", "{}/ec.crt".format(certs_path),
"-key", "{}/ec-priv.key".format(certs_path),
"-certform", "PEM",
"-tls1_3",
"-ciphersuites", "TLS_AES_128_GCM_SHA256"])
elif server_type == "1.3-psk-tickets":
args.extend(["-tls1_3",
"-ciphersuites", "TLS_AES_128_GCM_SHA256",
"-psk_identity", "PSK_identity", "-psk", "0102030405",
"-allow_no_dhe_kex", "-nocert"])
else:
raise Exception("Wrong server type")

args.extend(["-serverpref", "-state", "-debug", "-status_verbose", "-rev",
"-accept", "{}".format(port)])
return args

def start_server(server_type, port):
logger.info("Server type: " + server_type)
args = get_arguments_from_server_type(server_type, port)
logger.info("Launch command:")
print(" ".join(args))
openssl = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

try:
openssl.wait(1)
logger.error("Server startup failed. Here's the logs from OpenSSL:")
for line in openssl.stdout.readlines():
logger.error(line)
raise Exception("Server startup failed")
except subprocess.TimeoutExpired:
logger.info("Server is up")

return openssl

def test_app_vs_openssl(dut: DeviceAdapter, server_type, port):
server = start_server(server_type, port)

logger.info("Launch Zephyr application")
dut.launch()
dut.readlines_until("Test PASSED", timeout=3.0)

logger.info("Kill server")
server.kill()
Loading

0 comments on commit 91fa8a2

Please sign in to comment.