From 0140455ff73e8144e6996b1bfe71b71a3b134e4c Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 8 Feb 2024 20:11:30 +0100 Subject: [PATCH 1/2] feat(tls_cxx): Publish mbedtls component Adds examples and tests. Also supports DTLS now. --- .github/workflows/publish-docs-component.yml | 1 + .github/workflows/tls_cxx__build.yml | 30 ++ .pre-commit-config.yaml | 4 +- README.md | 4 + .../extra_tcp_transports/CMakeLists.txt | 6 +- .../extra_tcp_transports/tls_transport.cpp | 2 + .../modem_tcp_client/main/idf_component.yml | 3 + .../esp_modem/test/target_ota/CMakeLists.txt | 2 +- .../components/manual_ota/CMakeLists.txt | 2 +- .../manual_ota/transport_batch_tls.cpp | 2 + components/mbedtls_cxx/.cz.yaml | 8 + components/mbedtls_cxx/CMakeLists.txt | 3 + components/mbedtls_cxx/README.md | 3 + .../examples/test_certs/CMakeLists.txt | 8 + .../mbedtls_cxx/examples/test_certs/README.md | 4 + .../mbedtls_cxx/examples/test_certs/ca.crt | 19 ++ .../examples/test_certs/client.crt | 17 ++ .../examples/test_certs/client.key | 27 ++ .../examples/test_certs/idf_component.yml | 4 + .../mbedtls_cxx/examples/test_certs/srv.crt | 17 ++ .../mbedtls_cxx/examples/test_certs/srv.key | 27 ++ .../examples/test_certs/test_certs.hpp | 51 ++++ .../examples/tls_client/CMakeLists.txt | 11 + .../mbedtls_cxx/examples/tls_client/README.md | 4 + .../examples/tls_client/main/CMakeLists.txt | 2 + .../tls_client/main/idf_component.yml | 7 + .../examples/tls_client/main/tls_client.cpp | 152 ++++++++++ .../examples/tls_client/sdkconfig.defaults | 1 + .../examples/udp_mutual_auth/CMakeLists.txt | 11 + .../examples/udp_mutual_auth/README.md | 4 + .../udp_mutual_auth/main/CMakeLists.txt | 2 + .../udp_mutual_auth/main/idf_component.yml | 8 + .../udp_mutual_auth/main/udp_mutual.cpp | 229 ++++++++++++++ .../udp_mutual_auth/sdkconfig.defaults | 2 + components/mbedtls_cxx/idf_component.yml | 7 + .../include/mbedtls_wrap.hpp | 83 +++++- .../mbedtls_wrap.cpp | 92 +++++- .../tests/uart_mutual_auth/CMakeLists.txt | 8 + .../tests/uart_mutual_auth/README.md | 17 ++ .../uart_mutual_auth/main/CMakeLists.txt | 2 + .../uart_mutual_auth/main/Kconfig.projbuild | 19 ++ .../uart_mutual_auth/main/idf_component.yml | 8 + .../uart_mutual_auth/main/uart_mutual.cpp | 282 ++++++++++++++++++ .../tests/uart_mutual_auth/sdkconfig.ci.dtls | 3 + .../tests/uart_mutual_auth/sdkconfig.ci.tls | 3 + .../tests/uart_mutual_auth/sdkconfig.defaults | 3 + 46 files changed, 1181 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/tls_cxx__build.yml create mode 100644 components/mbedtls_cxx/.cz.yaml create mode 100644 components/mbedtls_cxx/CMakeLists.txt create mode 100644 components/mbedtls_cxx/README.md create mode 100644 components/mbedtls_cxx/examples/test_certs/CMakeLists.txt create mode 100644 components/mbedtls_cxx/examples/test_certs/README.md create mode 100644 components/mbedtls_cxx/examples/test_certs/ca.crt create mode 100644 components/mbedtls_cxx/examples/test_certs/client.crt create mode 100644 components/mbedtls_cxx/examples/test_certs/client.key create mode 100644 components/mbedtls_cxx/examples/test_certs/idf_component.yml create mode 100644 components/mbedtls_cxx/examples/test_certs/srv.crt create mode 100644 components/mbedtls_cxx/examples/test_certs/srv.key create mode 100644 components/mbedtls_cxx/examples/test_certs/test_certs.hpp create mode 100644 components/mbedtls_cxx/examples/tls_client/CMakeLists.txt create mode 100644 components/mbedtls_cxx/examples/tls_client/README.md create mode 100644 components/mbedtls_cxx/examples/tls_client/main/CMakeLists.txt create mode 100644 components/mbedtls_cxx/examples/tls_client/main/idf_component.yml create mode 100644 components/mbedtls_cxx/examples/tls_client/main/tls_client.cpp create mode 100644 components/mbedtls_cxx/examples/tls_client/sdkconfig.defaults create mode 100644 components/mbedtls_cxx/examples/udp_mutual_auth/CMakeLists.txt create mode 100644 components/mbedtls_cxx/examples/udp_mutual_auth/README.md create mode 100644 components/mbedtls_cxx/examples/udp_mutual_auth/main/CMakeLists.txt create mode 100644 components/mbedtls_cxx/examples/udp_mutual_auth/main/idf_component.yml create mode 100644 components/mbedtls_cxx/examples/udp_mutual_auth/main/udp_mutual.cpp create mode 100644 components/mbedtls_cxx/examples/udp_mutual_auth/sdkconfig.defaults create mode 100644 components/mbedtls_cxx/idf_component.yml rename components/{esp_modem/examples/modem_tcp_client/components/extra_tcp_transports => mbedtls_cxx}/include/mbedtls_wrap.hpp (52%) rename components/{esp_modem/examples/modem_tcp_client/components/extra_tcp_transports => mbedtls_cxx}/mbedtls_wrap.cpp (59%) create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/CMakeLists.txt create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/README.md create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/main/CMakeLists.txt create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/main/Kconfig.projbuild create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/main/idf_component.yml create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/main/uart_mutual.cpp create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.dtls create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.tls create mode 100644 components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.defaults diff --git a/.github/workflows/publish-docs-component.yml b/.github/workflows/publish-docs-component.yml index 71bef14fc3..1cdb90d276 100644 --- a/.github/workflows/publish-docs-component.yml +++ b/.github/workflows/publish-docs-component.yml @@ -99,5 +99,6 @@ jobs: components/console_cmd_ifconfig; components/console_cmd_wifi; components/esp_wifi_remote; + components/mbedtls_cxx; namespace: "espressif" api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/.github/workflows/tls_cxx__build.yml b/.github/workflows/tls_cxx__build.yml new file mode 100644 index 0000000000..5a053c13fc --- /dev/null +++ b/.github/workflows/tls_cxx__build.yml @@ -0,0 +1,30 @@ +name: "mbedtls-cxx: build-tests" + +on: + push: + branches: + - master + pull_request: + types: [opened, synchronize, reopened, labeled] + +jobs: + build_tls_cxx: + if: contains(github.event.pull_request.labels.*.name, 'tls_cxx') || github.event_name == 'push' + name: Build + strategy: + matrix: + idf_ver: ["latest", "release-v5.2", "release-v5.1"] + test: [ { app: client, path: "examples/tls_client" }, { app: udp, path: "examples/udp_mutual_auth" }, { app: test, path: "tests/uart_mutual_auth" } ] + runs-on: ubuntu-20.04 + container: espressif/idf:${{ matrix.idf_ver }} + steps: + - name: Checkout esp-protocols + uses: actions/checkout@v3 + with: + submodules: recursive + - name: Build ${{ matrix.test.app }} with IDF-${{ matrix.idf_ver }} + shell: bash + run: | + ${IDF_PATH}/install.sh --enable-pytest + . ${IDF_PATH}/export.sh + python ./ci/build_apps.py ./components/mbedtls_cxx/${{ matrix.test.path }} -vv --preserve-all diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9a2a622ec1..a12312a52d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,8 +61,8 @@ repos: - repo: local hooks: - id: commit message scopes - name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, wifi_remote" - entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote)\)\:)' + name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, console, common, eppp, wifi_remote, tls_cxx" + entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|console|websocket|asio|mqtt_cxx|examples|eppp|wifi_remote|tls_cxx)\)\:)' language: pygrep args: [--multiline] stages: [commit-msg] diff --git a/README.md b/README.md index b2822989e6..920ca34905 100644 --- a/README.md +++ b/README.md @@ -57,3 +57,7 @@ Please refer to instructions in [ESP-IDF](https://github.com/espressif/esp-idf) ### esp_wifi_remote * Brief introduction [README](components/esp_wifi_remote/README.md) + +### mbedtls_cxx + +* Brief introduction [README](components/mbedtls_cxx/README.md) diff --git a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/CMakeLists.txt b/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/CMakeLists.txt index 40ee59b5ff..748f82c200 100644 --- a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/CMakeLists.txt +++ b/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/CMakeLists.txt @@ -1,4 +1,4 @@ -idf_component_register(SRCS mbedtls_wrap.cpp - tls_transport.cpp +idf_component_register(SRCS tls_transport.cpp INCLUDE_DIRS include - REQUIRES tcp_transport) + REQUIRES tcp_transport + PRIV_REQUIRES mbedtls_cxx) diff --git a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/tls_transport.cpp b/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/tls_transport.cpp index fba3d96fa1..25540aaa63 100644 --- a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/tls_transport.cpp +++ b/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/tls_transport.cpp @@ -11,6 +11,8 @@ static const char *TAG = "tls_transport"; +using namespace idf::mbedtls_cxx; + class TlsTransport: public Tls { public: explicit TlsTransport(esp_transport_handle_t parent) : Tls(), transport_(parent) {} diff --git a/components/esp_modem/examples/modem_tcp_client/main/idf_component.yml b/components/esp_modem/examples/modem_tcp_client/main/idf_component.yml index 3289c9b167..0d9805d7fe 100644 --- a/components/esp_modem/examples/modem_tcp_client/main/idf_component.yml +++ b/components/esp_modem/examples/modem_tcp_client/main/idf_component.yml @@ -2,3 +2,6 @@ dependencies: espressif/esp_modem: version: "^1.0.1" override_path: "../../../" + espressif/mbedtls_cxx: + version: "*" + override_path: "../../../../mbedtls_cxx" diff --git a/components/esp_modem/test/target_ota/CMakeLists.txt b/components/esp_modem/test/target_ota/CMakeLists.txt index ca5c2eaaac..78ee6f0b43 100644 --- a/components/esp_modem/test/target_ota/CMakeLists.txt +++ b/components/esp_modem/test/target_ota/CMakeLists.txt @@ -2,7 +2,7 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.8) -set(EXTRA_COMPONENT_DIRS "../.." "../../examples/modem_tcp_client/components") +set(EXTRA_COMPONENT_DIRS "../.." "../../../mbedtls_cxx") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(ota_test) diff --git a/components/esp_modem/test/target_ota/components/manual_ota/CMakeLists.txt b/components/esp_modem/test/target_ota/components/manual_ota/CMakeLists.txt index 5eb262e108..126eb4c23e 100644 --- a/components/esp_modem/test/target_ota/components/manual_ota/CMakeLists.txt +++ b/components/esp_modem/test/target_ota/components/manual_ota/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRCS manual_ota.cpp transport_batch_tls.cpp INCLUDE_DIRS "." - PRIV_REQUIRES extra_tcp_transports esp_http_client app_update) + PRIV_REQUIRES mbedtls_cxx esp_http_client app_update) diff --git a/components/esp_modem/test/target_ota/components/manual_ota/transport_batch_tls.cpp b/components/esp_modem/test/target_ota/components/manual_ota/transport_batch_tls.cpp index 8f9f31b91e..160172b27f 100644 --- a/components/esp_modem/test/target_ota/components/manual_ota/transport_batch_tls.cpp +++ b/components/esp_modem/test/target_ota/components/manual_ota/transport_batch_tls.cpp @@ -10,6 +10,8 @@ #define TAG "batch-tls" +using namespace idf::mbedtls_cxx; + class TlsTransport: public Tls { public: explicit TlsTransport(esp_transport_handle_t parent): diff --git a/components/mbedtls_cxx/.cz.yaml b/components/mbedtls_cxx/.cz.yaml new file mode 100644 index 0000000000..19a1e30dd4 --- /dev/null +++ b/components/mbedtls_cxx/.cz.yaml @@ -0,0 +1,8 @@ +--- +commitizen: + bump_message: 'bump(tls_cxx): $current_version -> $new_version' + pre_bump_hooks: python ../../ci/changelog.py mbedtls_cxx + tag_format: tls_cxx-v$version + version: 0.0.0 + version_files: + - idf_component.yml diff --git a/components/mbedtls_cxx/CMakeLists.txt b/components/mbedtls_cxx/CMakeLists.txt new file mode 100644 index 0000000000..8e2b0b42d3 --- /dev/null +++ b/components/mbedtls_cxx/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS mbedtls_wrap.cpp + INCLUDE_DIRS include + REQUIRES tcp_transport) diff --git a/components/mbedtls_cxx/README.md b/components/mbedtls_cxx/README.md new file mode 100644 index 0000000000..7dee4d9a77 --- /dev/null +++ b/components/mbedtls_cxx/README.md @@ -0,0 +1,3 @@ +# mbedtls_cxx + +This is a simplified C++ wrapper of mbedTLS for performing TLS and DTLS handshake a communication. This component allows for overriding low level IO functions (`send()` and `recv()`) and thus supporting TLS over various physical channels. diff --git a/components/mbedtls_cxx/examples/test_certs/CMakeLists.txt b/components/mbedtls_cxx/examples/test_certs/CMakeLists.txt new file mode 100644 index 0000000000..5f59a08249 --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register( + EMBED_TXTFILES srv.crt + EMBED_TXTFILES srv.key + EMBED_TXTFILES ca.crt + EMBED_TXTFILES client.crt + EMBED_TXTFILES client.key + INCLUDE_DIRS "." + REQUIRES mbedtls_cxx) diff --git a/components/mbedtls_cxx/examples/test_certs/README.md b/components/mbedtls_cxx/examples/test_certs/README.md new file mode 100644 index 0000000000..510190764b --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/README.md @@ -0,0 +1,4 @@ +# Test Certificates and Keys + +This is a utility component, that uses test certificates for server and client side in examples and tests. +These are self-signed certificates and generated only for test and demonstration purposes. diff --git a/components/mbedtls_cxx/examples/test_certs/ca.crt b/components/mbedtls_cxx/examples/test_certs/ca.crt new file mode 100644 index 0000000000..0475433ee3 --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/ca.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDIzCCAgugAwIBAgIULOncUeRLKxgrihIh1kHGGlPV7ecwDQYJKoZIhvcNAQEL +BQAwITELMAkGA1UEBhMCQ1oxEjAQBgNVBAMMCUVzcHJlc3NpZjAeFw0yNDA0MDMw +OTE0MjNaFw0zNDA0MDEwOTE0MjNaMCExCzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlF +c3ByZXNzaWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbayaZAuzQ +WrwRj3oiFP9AZK0ECaDvVlJec4M6yokded1pqNY+bNmA7VsHSQkf3d1rO1G5GwEX +oMPli15m7rJodq9iYp1J2LhLhpKDNapm19reyH9A4rAfjSyk/WyvT+3Y5sNHVFdE +2t1EetOyzy90CfOHT9JfWG9PiV6b1W65CqgjJVCHMWioppVAGQCoN+mDBf1VhD4a +m6onei+ijHdALJDfp74mSIOJGulm/IR7504s+yy7068PQ05V/wHkmd9O1Iww5fnJ +dRh2KvTFZVOB5u9y54MTJb0sGZj+JfxIbcFiIWAykLFVWBk5PO6yj8fNMmk/Ogb2 +K4wo7AZnJ3qBAgMBAAGjUzBRMB0GA1UdDgQWBBT3j77hJHm/hI34fEn3tocHqB4I +NzAfBgNVHSMEGDAWgBT3j77hJHm/hI34fEn3tocHqB4INzAPBgNVHRMBAf8EBTAD +AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBstXfBIRvqZp4OBQ2kCJig/CErcfdB4qQO +S2LzQmpIOUQ4d/zvZOQD2WIw/x2Rd1/hto/+f57pOZNHsi8vfX2Z7kPOlD9ZG1wT +znl1v8wOMP01AFJuVtmJQV0C4lVupb2/Mmu42xqP9pr/uL5pJ2rFb8ujl2xakhSv +YVdMONtZL0mh9+hdnUb7Fj7KI3qWxzc7+uXGjCzh6LkOmcMBOB6+0V6xW2NVpUUP +tuXytK0t2oyWpDvwFIrl0J6qBNRlH1ON1iz33HOo73IjprMNx3hIo5y/N8+TTxY6 +KEegbP67hSnJJhQ7tezoOu4OE0xmJp0XmGPMNewYARqL2UvHnZyf +-----END CERTIFICATE----- diff --git a/components/mbedtls_cxx/examples/test_certs/client.crt b/components/mbedtls_cxx/examples/test_certs/client.crt new file mode 100644 index 0000000000..37ddce4b62 --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/client.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICwjCCAaoCFAWE4aJdYWbMJAaBTMxVpoXMrhzvMA0GCSqGSIb3DQEBCwUAMCEx +CzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwHhcNMjQwNDAzMDkxNjE4 +WhcNMzQwNDAxMDkxNjE4WjAaMRgwFgYDVQQDDA9lc3ByZXNzaWYubG9jYWwwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDcjdBQ3sHbfuWRo2LlqZF37Dfu +ymz5/fq+szcOLUUWCccxku9qNNEdZAcZHMsINurezpHXa6ZNKGqmbmqZPVrEKzMU +IolpnQmcerRt/yKqxCZ/kgsJE3IZyqi1T+xDwaBEhgdB6+wxyrL0/uBlLCbEdZAA +7MPcauIKz8ykfIwo7Ht/vcHNxGaFFu+DcNoJI/Pw6hERlC9DHuUftK0/Lap1K2o+ +6kFQKqhVrvNQmaiqnz3Dr9psPO90AvbRqeODmfpi7rtU4MKOprQhUrMS9s9d5yVd +JILp74pt6nzu3EnFiixRD5XD9PtK5NvP1sgDAgbWgTttwM9X7N6mzEe/gVUZAgMB +AAEwDQYJKoZIhvcNAQELBQADggEBAJVsbAamDRuZ1J2ogHLo/UmjmcmIATmqO7Eb +aoid7+FYme/2NFzofOFtJNaCumdhwxSyf7ER6m2DUO6bDseblqNCTyRDNNXzTHEF +QiYh2PThKSDdH0fbEf4IpcbOCnpSEpIg9C/ywEhq/wzYiOlxPhNWxBKHLhEkM7aW +BerAhInCRRXymfus2HUf6aTWZ0wigMoUVKwOu16Zh04D2d6qb314cEMgKvANPiTT +dgEae7Ot+rP1s2Zp75zUbWuz4uWd4wJDOHWR25mkD3ZELfbrpmEymbOTQ26zOpIU +iPNfYZ1t9KwEjkKN+jBTXKu7QhB/u+g5yBHjRL++LEli4YGGGiA= +-----END CERTIFICATE----- diff --git a/components/mbedtls_cxx/examples/test_certs/client.key b/components/mbedtls_cxx/examples/test_certs/client.key new file mode 100644 index 0000000000..2aeaad60d3 --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA3I3QUN7B237lkaNi5amRd+w37sps+f36vrM3Di1FFgnHMZLv +ajTRHWQHGRzLCDbq3s6R12umTShqpm5qmT1axCszFCKJaZ0JnHq0bf8iqsQmf5IL +CRNyGcqotU/sQ8GgRIYHQevsMcqy9P7gZSwmxHWQAOzD3GriCs/MpHyMKOx7f73B +zcRmhRbvg3DaCSPz8OoREZQvQx7lH7StPy2qdStqPupBUCqoVa7zUJmoqp89w6/a +bDzvdAL20anjg5n6Yu67VODCjqa0IVKzEvbPXeclXSSC6e+Kbep87txJxYosUQ+V +w/T7SuTbz9bIAwIG1oE7bcDPV+zepsxHv4FVGQIDAQABAoIBAQDPzzc224yg+iHo +ZaArcOhFrGbPMiAYNLxrroTzcKglqbTr+txmn7lhDfy6Jq0O4l/O66fy59Vb4fcL +NgJuvKanK2UHVbtPrc1+iQc0lS7e4866aKrJNG9P6emoXNPqy6fsqLRx4o88IxcX +TIe2DDHC7lpu5KdvKa4uLblOSqPtcZTHXPD9olVe8ZYF5CttMUTc4SkF4HSkY2jb +0j+6kASN4eQ2CqEt+IW4IxI5NiEzrlzZSOdyqIOeyGUZz+QcfILOProWZHYzH3jO +HQe4PJSXO57f2dojY1GqRcjnr3guQMpw1s7wmDYO1QekiBYwRERNzjEY7VhgDq8T +0rwJPHP5AoGBAPO13QpJVSj1NfQ/H0AgZlsJIIlIwIC2YwuwjA7b36A3JOFolkHj +tq4eNntThNRQbTL9OficbxJSHXQcOsQeo7dvwEhJjuVwEajL4/6cjc9b4oyGJxLl +TKTshUPmeKPfGWUjRZKGbVWbT3m4BXqGiv4laCZ0LDHiCt4DvEzQ1Bo3AoGBAOet +BClbcbUJhxkAme5HHI9A5VcqyOi2CrRh+HjKd/2IJlDA+Vmbl2iEB+9cMRGRubaz +brk1yAzgtW29GX8kngr8yxDtIM8M7lPR2NhXx7XbmCKwKosZ7l6hHNdnD12TFyLC +juuJlUA37sWXw8r33623mLFQlNVjnL0onUa1XSMvAoGACw47+cR73YDKMstOQp11 +pzmRxUiMmworEhOvNtlYmq8FuEgDUPfgiKOMOyn9w5fmbEK6h4GpND6PYX4KWG0/ +ZgnmwiC8H8Jmuq6NKDa35Ck57MAFM8E9Kdok7YCeBmkPgNwJwuzgNtr1zwK/FODX +m1HdGKl6e8TSU2H9/8oVZR8CgYEAoHSWI0awNCCLLufZtMwPna/mpz58s6ARPel0 +u8QO4st/LgLZMBSxArQfAsqpOW/iXgVcNG5pRXIEdiK4G/TyeM2onup9BKoCDo+S +ThRNv0h9z9iPPpQRIf0YCp/YZojPR0XU0pERi86xUqzP8C1I//neiUA0NK6vCdut +QiGuhgUCgYEAp89EFcM1WvtPRJE+md8N8BUef5MJ+JJ0nb+BW1kkLY50Q1MVmsVX +dUowYupWLBgEfMn8fy8Q+xD9EeiISTF9MtT1X4iQSI/pzKW5LLd0OJYnqPMWzygg +ASzSNWdYBIGNkqsQGmGCtF9+i6V4acfTTbMD9LiB7u5/enQa8N0Qg+s= +-----END RSA PRIVATE KEY----- diff --git a/components/mbedtls_cxx/examples/test_certs/idf_component.yml b/components/mbedtls_cxx/examples/test_certs/idf_component.yml new file mode 100644 index 0000000000..8b11c97cb5 --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/idf_component.yml @@ -0,0 +1,4 @@ +dependencies: + espressif/mbedtls_cxx: + version: "*" + override_path: "../.." diff --git a/components/mbedtls_cxx/examples/test_certs/srv.crt b/components/mbedtls_cxx/examples/test_certs/srv.crt new file mode 100644 index 0000000000..83777ec910 --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/srv.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICwjCCAaoCFAWE4aJdYWbMJAaBTMxVpoXMrhzuMA0GCSqGSIb3DQEBCwUAMCEx +CzAJBgNVBAYTAkNaMRIwEAYDVQQDDAlFc3ByZXNzaWYwHhcNMjQwNDAzMDkxNTI3 +WhcNMzQwNDAxMDkxNTI3WjAaMRgwFgYDVQQDDA9lc3ByZXNzaWYubG9jYWwwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDChMP2z+M0MSy4dNO64tuJoI37 +lWBBFEmaRj7AkEQQ2opD36qJvgv17AU/S997vQvpmL3GLC0uIKNFvdUp0p7Zw4m0 +UuPDU8NZTCUqjGJVV2advYzsCCRz3dlosX8z5JpN9GmxLsPjoy+jJskVU/ZCiUnv +Tipk86VZq9K2gHVGaghVk0qbo8QEorjPLk0w8KfYpSNjMV8XL3wMIWeUQ7ZzlRIg +fhFVv7QO7hCGq/h1lGeyMjszmajCmALp8DyzFggL0I6HKpqBGh7WD99Tndhl3qkL +3VFiNuNALKn+ZDW7xYseCLf2w3zxMYzNwsdgFCcOlYJ4cznx/OFFKPTybXc3AgMB +AAEwDQYJKoZIhvcNAQELBQADggEBAFD31VncaNRvs4T8fc9g8GtiHS4/f0fDzwQY +CFufm+I/J1V0NFQZtfhJEnjXu3c8CAlZx8texiJplZwMXhEsd2Qs2JkQ0i9/vlAs +ClhqR9+lPmCDISK2cQZL5gUwGE8JpGev3ty8LNxVEgTTxlSSM7IdVtVJVRpWSxCj +4zSIiozt0w4XwU240W+pDGEptnSh0CtXl8fPTQa3Zr3eepk4Io0z14+lDecYExhi +acgqAaEKLety0+EfApsR0IK/QWGnDECQMCZiduLOJhPhssE3Ybxr0bRcUOuS1ltY +63h/eVuaOxgcp+YMkIDaSuW/LBcl1p84ZQ3B+hrUTN5TztggCtU= +-----END CERTIFICATE----- diff --git a/components/mbedtls_cxx/examples/test_certs/srv.key b/components/mbedtls_cxx/examples/test_certs/srv.key new file mode 100644 index 0000000000..4a08079e51 --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/srv.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAwoTD9s/jNDEsuHTTuuLbiaCN+5VgQRRJmkY+wJBEENqKQ9+q +ib4L9ewFP0vfe70L6Zi9xiwtLiCjRb3VKdKe2cOJtFLjw1PDWUwlKoxiVVdmnb2M +7Agkc93ZaLF/M+SaTfRpsS7D46MvoybJFVP2QolJ704qZPOlWavStoB1RmoIVZNK +m6PEBKK4zy5NMPCn2KUjYzFfFy98DCFnlEO2c5USIH4RVb+0Du4Qhqv4dZRnsjI7 +M5mowpgC6fA8sxYIC9COhyqagRoe1g/fU53YZd6pC91RYjbjQCyp/mQ1u8WLHgi3 +9sN88TGMzcLHYBQnDpWCeHM58fzhRSj08m13NwIDAQABAoIBAQCNJAqRDrzcRQYe +/V4YT71eOmprbzK9ZfwV/fxQex14YSpMH4G9mnFRSqVwDRymy0BWiibBIZLS0onF +8/008IekmNZVSoPLWf73z2F0YxKCu/1QXZZgOXRBwmqbJZeXzrsL71m1X6pxhRnu +txjW6epY0wcbpcrrH0MOMredBs6RfOBi55wpuXNPjEP1YchBNXem0OR/ai5I3hGG +5ifStVvMv/+2N1vwTTelz28YvXcKqQXpMFhbVxfkIPw5JVnNvcDAWuC5oOj+jWeX +p5lhBzFqtnRuNjiC81qSbv/R5zDLMtceewwRew9/yu4su0VUsn8frSqTqsUPtpqf +Wa7BQgjBAoGBAOgSLCF/BZmeiJwNlVw1Mk/uHrDgGqDzZzGbKUX1CTtIoWOqT/JA +yr4NFpMQq8imS/XAvZJ8HyvBlT+YScmews+4TTRr/4QoAo00q99c24g2k3y4gZ/r +ddD5LFwkyr/JUwGQbSyx4Vf9CnVhHbnibm8jnI033hq9f9oOBr5tSOlXAoGBANaT +WPQIzansIu7f9inVNGzVsZEzmSoKU9P/81HsVblfhySXA3elqIK4WKJzJlyyRWk/ +bE5tSVdk04mMWpNBgWmz6rVvFRZMDRjlJVoumqJ6F5wKK/yGTshwWTixiR+gX3/q +PtJVWGcv8y8tlfZmuxjeJyQzz6GA/T/yU2717tUhAoGBAK5u2lTjEOaCztPdMeL4 +6TRDGzZ/fAR2b55NrhwzLhktYoFzRlwkbz+ivtETuss6k+XIVbWBLjzJaNFAOlYd +yvgu43j/pDNFj4VrjbR6K1ibDQi19liptwi4AavQy8SUIpwOXsE1gteMDwxjTuCl +XbST49wRnhQjU7Im0NLZefBJAoGBALQcvOci2JeQegYvAi89IqNUgJdUS3Wpc5IZ +X0Hd8lsG36aMCEIPULJhUS0TIRlgHrlonl36iDyOiq4DnSfMLXfvqM0g7/9mWPwT +pFXdlrlZaKX3N9LhXhILlCjthR+B+4egtZjSQMFk02k/h4hr1RLbrtlJkDiN0IYz +v2r9jrthAoGANtSFvvDTpUi79RaXkUYID8OqXIdqujViaDeWGI+wVgE88b8JF8ac +XcMcHz1J6meebPsjmkcNLLrD3jWo7NyiKT1j2xeYg6c0JEEMGNG/pmmu7b0a/P+i +jcofvRHBh/yYZwodabhoSHHtWOI2d+w1L2ECx/iezQM0uMfaXCsZ6ak= +-----END RSA PRIVATE KEY----- diff --git a/components/mbedtls_cxx/examples/test_certs/test_certs.hpp b/components/mbedtls_cxx/examples/test_certs/test_certs.hpp new file mode 100644 index 0000000000..5645a8bdbd --- /dev/null +++ b/components/mbedtls_cxx/examples/test_certs/test_certs.hpp @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include "mbedtls_wrap.hpp" + +namespace test_certs { +using pem_format = const unsigned char; +extern pem_format cacert_start[] asm("_binary_ca_crt_start"); +extern pem_format cacert_end[] asm("_binary_ca_crt_end"); +extern pem_format clientcert_start[] asm("_binary_client_crt_start"); +extern pem_format clientcert_end[] asm("_binary_client_crt_end"); +extern pem_format clientkey_start[] asm("_binary_client_key_start"); +extern pem_format clientkey_end[] asm("_binary_client_key_end"); +extern pem_format servercert_start[] asm("_binary_srv_crt_start"); +extern pem_format servercert_end[] asm("_binary_srv_crt_end"); +extern pem_format serverkey_start[] asm("_binary_srv_key_start"); +extern pem_format serverkey_end[] asm("_binary_srv_key_end"); + +enum class type { + cacert, + servercert, + serverkey, + clientcert, + clientkey +}; + +#define IF_BUF_TYPE(buf_type) \ + if (t == type::buf_type) { \ + return idf::mbedtls_cxx::const_buf{buf_type ## _start, buf_type ## _end - buf_type ## _start}; \ + } + +static inline idf::mbedtls_cxx::const_buf get_buf(type t) +{ + IF_BUF_TYPE(cacert); + IF_BUF_TYPE(servercert); + IF_BUF_TYPE(serverkey); + IF_BUF_TYPE(clientcert); + IF_BUF_TYPE(clientkey); + return idf::mbedtls_cxx::const_buf{}; +} + +static inline const char *get_server_cn() +{ + return "espressif.local"; +} + +} diff --git a/components/mbedtls_cxx/examples/tls_client/CMakeLists.txt b/components/mbedtls_cxx/examples/tls_client/CMakeLists.txt new file mode 100644 index 0000000000..ac83b5d1b2 --- /dev/null +++ b/components/mbedtls_cxx/examples/tls_client/CMakeLists.txt @@ -0,0 +1,11 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +if("${IDF_TARGET}" STREQUAL "linux") + list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") +endif() +project(tls_client) diff --git a/components/mbedtls_cxx/examples/tls_client/README.md b/components/mbedtls_cxx/examples/tls_client/README.md new file mode 100644 index 0000000000..f42b5bae24 --- /dev/null +++ b/components/mbedtls_cxx/examples/tls_client/README.md @@ -0,0 +1,4 @@ +# TCP client example + +This is a simple example uses `mbedtls_cxx` to connect to a remote echo server. +The example needs a connection to internet (or a network where the TLS echo-server is available), it could be run on linux target as well as on ESP32. diff --git a/components/mbedtls_cxx/examples/tls_client/main/CMakeLists.txt b/components/mbedtls_cxx/examples/tls_client/main/CMakeLists.txt new file mode 100644 index 0000000000..f89b6a82d6 --- /dev/null +++ b/components/mbedtls_cxx/examples/tls_client/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "tls_client.cpp" + INCLUDE_DIRS ".") diff --git a/components/mbedtls_cxx/examples/tls_client/main/idf_component.yml b/components/mbedtls_cxx/examples/tls_client/main/idf_component.yml new file mode 100644 index 0000000000..8bd6aa2845 --- /dev/null +++ b/components/mbedtls_cxx/examples/tls_client/main/idf_component.yml @@ -0,0 +1,7 @@ +dependencies: + idf: ">=5.0" + espressif/mbedtls_cxx: + version: "*" + override_path: "../../.." + protocol_examples_common: + path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/components/mbedtls_cxx/examples/tls_client/main/tls_client.cpp b/components/mbedtls_cxx/examples/tls_client/main/tls_client.cpp new file mode 100644 index 0000000000..84083047de --- /dev/null +++ b/components/mbedtls_cxx/examples/tls_client/main/tls_client.cpp @@ -0,0 +1,152 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include "esp_log.h" +#include "mbedtls_wrap.hpp" + +using namespace idf::mbedtls_cxx; + +namespace { +constexpr auto *TAG = "simple_tls_client"; +} + +class TlsSocketClient: public Tls { +public: + TlsSocketClient() = default; + ~TlsSocketClient() override + { + if (sock >= 0) { + ::close(sock); + } + } + int send(const unsigned char *buf, size_t len) override + { + return ::send(sock, buf, len, 0); + } + int recv(unsigned char *buf, size_t len) override + { + return ::recv(sock, buf, len, 0); + } + bool connect(const char *host, int port) + { + addr_info addr(host, AF_INET, SOCK_STREAM); + if (!addr) { + ESP_LOGE(TAG, "Failed to resolve host"); + return false; + } + sock = addr.get_sock(); + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create socket"); + return false; + } + + if (::connect(sock, addr.get_addr(port), sizeof(struct sockaddr)) < 0) { + ESP_LOGE(TAG, "Failed to connect %d", errno); + return false; + } + + if (!init(is_server{false}, do_verify{false})) { + return false; + } + return handshake() == 0; + } + +private: + int sock{-1}; + /** + * RAII wrapper of the address_info + */ + struct addr_info { + struct addrinfo *ai { + nullptr + }; + ~addr_info() + { + freeaddrinfo(ai); + } + explicit addr_info(const char *host, int family, int type) + { + struct addrinfo hints {}; + hints.ai_family = family; + hints.ai_socktype = type; + if (getaddrinfo(host, nullptr, &hints, &ai) < 0) { + freeaddrinfo(ai); + ai = nullptr; + } + } + explicit operator bool() const + { + return ai != nullptr; + } + struct sockaddr *get_addr(uint16_t port) const { + auto *p = (struct sockaddr_in *)ai->ai_addr; + p->sin_port = htons(port); + return (struct sockaddr *)p; + } + int get_sock() const + { + return socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + } + }; +}; + +namespace { + +void tls_client() +{ + const unsigned char message[] = "Hello\n"; + unsigned char reply[128]; + TlsSocketClient client; + if (!client.connect("tcpbin.com", 4243)) { + ESP_LOGE(TAG, "Failed to connect! %d", errno); + return; + } + if (client.write(message, sizeof(message)) < 0) { + ESP_LOGE(TAG, "Failed to write!"); + return; + } + int len = client.read(reply, sizeof(reply)); + if (len < 0) { + ESP_LOGE(TAG, "Failed to read!"); + return; + } + ESP_LOGI(TAG, "Successfully received: %.*s", len, reply); +} + +} // namespace + +#if CONFIG_IDF_TARGET_LINUX +/** + * Linux target: We're already connected, just run the client + */ +int main() +{ + tls_client(); + return 0; +} +#else +/** + * ESP32 chipsets: Need to initialize system components + * and connect to network + */ + +#include "nvs_flash.h" +#include "esp_event.h" +#include "protocol_examples_common.h" +#include "esp_netif.h" + +extern "C" void app_main() +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(example_connect()); + + tls_client(); +} +#endif diff --git a/components/mbedtls_cxx/examples/tls_client/sdkconfig.defaults b/components/mbedtls_cxx/examples/tls_client/sdkconfig.defaults new file mode 100644 index 0000000000..ce53d73ece --- /dev/null +++ b/components/mbedtls_cxx/examples/tls_client/sdkconfig.defaults @@ -0,0 +1 @@ +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 diff --git a/components/mbedtls_cxx/examples/udp_mutual_auth/CMakeLists.txt b/components/mbedtls_cxx/examples/udp_mutual_auth/CMakeLists.txt new file mode 100644 index 0000000000..ab10f2872d --- /dev/null +++ b/components/mbedtls_cxx/examples/udp_mutual_auth/CMakeLists.txt @@ -0,0 +1,11 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +if("${IDF_TARGET}" STREQUAL "linux") + list(APPEND EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/mocks/freertos/") +endif() +project(udp_mutual) diff --git a/components/mbedtls_cxx/examples/udp_mutual_auth/README.md b/components/mbedtls_cxx/examples/udp_mutual_auth/README.md new file mode 100644 index 0000000000..4347e0c1cf --- /dev/null +++ b/components/mbedtls_cxx/examples/udp_mutual_auth/README.md @@ -0,0 +1,4 @@ +# UDP Mutual authentication example + +This example uses `mbedtls_cxx` to perform a DTLS handshake and exchange a message between server and client. +The example uses UDP sockets on `'localhost'` interface, so no actual connection is needed, it could be run on linux target as well as on ESP32. diff --git a/components/mbedtls_cxx/examples/udp_mutual_auth/main/CMakeLists.txt b/components/mbedtls_cxx/examples/udp_mutual_auth/main/CMakeLists.txt new file mode 100644 index 0000000000..4ff54fa168 --- /dev/null +++ b/components/mbedtls_cxx/examples/udp_mutual_auth/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "udp_mutual.cpp" + INCLUDE_DIRS ".") diff --git a/components/mbedtls_cxx/examples/udp_mutual_auth/main/idf_component.yml b/components/mbedtls_cxx/examples/udp_mutual_auth/main/idf_component.yml new file mode 100644 index 0000000000..6077bbd24b --- /dev/null +++ b/components/mbedtls_cxx/examples/udp_mutual_auth/main/idf_component.yml @@ -0,0 +1,8 @@ +dependencies: + idf: ">=5.0" + espressif/mbedtls_cxx: + version: "*" + override_path: "../../.." + test_certs: + version: "*" + path: "../../test_certs" diff --git a/components/mbedtls_cxx/examples/udp_mutual_auth/main/udp_mutual.cpp b/components/mbedtls_cxx/examples/udp_mutual_auth/main/udp_mutual.cpp new file mode 100644 index 0000000000..c71e6b0b4a --- /dev/null +++ b/components/mbedtls_cxx/examples/udp_mutual_auth/main/udp_mutual.cpp @@ -0,0 +1,229 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include "esp_log.h" +#include "mbedtls_wrap.hpp" +#include "test_certs.hpp" + +namespace { +constexpr auto *TAG = "udp_example"; +} + +using namespace idf::mbedtls_cxx; +using namespace test_certs; + +class SecureLink: public Tls { +public: + explicit SecureLink() : Tls(), addr("localhost", 3333, AF_INET, SOCK_DGRAM) {} + ~SecureLink() override + { + if (sock >= 0) { + ::close(sock); + } + } + int send(const unsigned char *buf, size_t len) override + { + return sendto(sock, buf, len, 0, addr, ai_size); + } + int recv(unsigned char *buf, size_t len) override + { + socklen_t socklen = sizeof(sockaddr); + return recvfrom(sock, buf, len, 0, addr, &socklen); + } + int recv_timeout(unsigned char *buf, size_t len, int timeout) override + { + struct timeval tv { + timeout / 1000, (timeout % 1000 ) * 1000 + }; + fd_set read_fds; + FD_ZERO( &read_fds ); + FD_SET( sock, &read_fds ); + + int ret = select(sock + 1, &read_fds, nullptr, nullptr, timeout == 0 ? nullptr : &tv); + if (ret == 0) { + return MBEDTLS_ERR_SSL_TIMEOUT; + } + if (ret < 0) { + if (errno == EINTR) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + return ret; + } + return recv(buf, len); + } + bool open(bool server_not_client) + { + if (!addr) { + ESP_LOGE(TAG, "Failed to resolve endpoint"); + return false; + } + sock = addr.get_sock(); + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create socket"); + return false; + } + TlsConfig config{}; + config.is_dtls = true; + config.timeout = 10000; + if (server_not_client) { + int err = bind(sock, addr, ai_size); + if (err < 0) { + ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno); + return false; + } + const unsigned char client_id[] = "localhost"; + config.client_id = std::make_pair(client_id, sizeof(client_id)); + } + if (!init(is_server{server_not_client}, do_verify{true}, &config)) { + return false; + } + + return handshake() == 0; + } + +private: + int sock{-1}; + /** + * RAII wrapper of the address_info + */ + struct addr_info { + struct addrinfo *ai = nullptr; + explicit addr_info(const char *host, int port, int family, int type) + { + struct addrinfo hints {}; + hints.ai_family = family; + hints.ai_socktype = type; + if (getaddrinfo(host, nullptr, &hints, &ai) < 0) { + freeaddrinfo(ai); + ai = nullptr; + } + auto *p = (struct sockaddr_in *)ai->ai_addr; + p->sin_port = htons(port); + } + ~addr_info() + { + freeaddrinfo(ai); + } + explicit operator bool() const + { + return ai != nullptr; + } + operator sockaddr *() const + { + auto *p = (struct sockaddr_in *)ai->ai_addr; + return (struct sockaddr *)p; + } + + int get_sock() const + { + return socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + } + } addr; + const int ai_size{sizeof(struct sockaddr_in)}; +}; + +namespace { + +void tls_client() +{ + const unsigned char message[] = "Hello\n"; + unsigned char reply[128]; + SecureLink client; + client.set_hostname(get_server_cn()); + if (!client.set_own_cert(get_buf(type::clientcert), get_buf(type::clientkey))) { + ESP_LOGE(TAG, "Failed to set own cert"); + return; + } + if (!client.set_ca_cert(get_buf(type::cacert))) { + ESP_LOGE(TAG, "Failed to set peer's cert"); + return; + } + if (!client.open(false)) { + ESP_LOGE(TAG, "Failed to CONNECT! %d", errno); + return; + } + ESP_LOGI(TAG, "client opened..."); + if (client.write(message, sizeof(message)) < 0) { + ESP_LOGE(TAG, "Failed to write!"); + return; + } + int len = client.read(reply, sizeof(reply)); + if (len < 0) { + ESP_LOGE(TAG, "Failed to read!"); + return; + } + ESP_LOGI(TAG, "Successfully received: %.*s", len, reply); +} + +void tls_server() +{ + unsigned char message[128]; + SecureLink server; + if (!server.set_own_cert(get_buf(type::servercert), get_buf(type::serverkey))) { + ESP_LOGE(TAG, "Failed to set own cert"); + return; + } + if (!server.set_ca_cert(get_buf(type::cacert))) { + ESP_LOGE(TAG, "Failed to set peer's cert"); + return; + } + ESP_LOGI(TAG, "opening..."); + if (!server.open(true)) { + ESP_LOGE(TAG, "Failed to OPEN! %d", errno); + return; + } + int len = server.read(message, sizeof(message)); + if (len < 0) { + ESP_LOGE(TAG, "Failed to read!"); + return; + } + ESP_LOGI(TAG, "Received from client: %.*s", len, message); + if (server.write(message, len) < 0) { + ESP_LOGE(TAG, "Failed to write!"); + return; + } + ESP_LOGI(TAG, "Written back"); +} + +void udp_auth() +{ + std::thread t2(tls_server); + std::thread t1(tls_client); + t1.join(); + t2.join(); +} + +} // namespace + +#if CONFIG_IDF_TARGET_LINUX +/** + * Linux target: We're already connected, just run the client + */ +int main() +{ + udp_auth(); + return 0; +} +#else +/** + * ESP32 chipsets: Need to initialize system components + * and connect to network + */ + +#include "esp_event.h" +#include "esp_netif.h" + +extern "C" void app_main() +{ + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + udp_auth(); +} +#endif diff --git a/components/mbedtls_cxx/examples/udp_mutual_auth/sdkconfig.defaults b/components/mbedtls_cxx/examples/udp_mutual_auth/sdkconfig.defaults new file mode 100644 index 0000000000..f4780e8394 --- /dev/null +++ b/components/mbedtls_cxx/examples/udp_mutual_auth/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192 diff --git a/components/mbedtls_cxx/idf_component.yml b/components/mbedtls_cxx/idf_component.yml new file mode 100644 index 0000000000..1c352e7432 --- /dev/null +++ b/components/mbedtls_cxx/idf_component.yml @@ -0,0 +1,7 @@ +version: 0.0.0 +url: https://github.com/espressif/esp-protocols/tree/master/components/mbedtls_cxx +description: C++ wrapper of mbedtls to perform (D)TLS connection +license: Apache-2.0 +dependencies: + idf: + version: '>=5.0' diff --git a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/include/mbedtls_wrap.hpp b/components/mbedtls_cxx/include/mbedtls_wrap.hpp similarity index 52% rename from components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/include/mbedtls_wrap.hpp rename to components/mbedtls_cxx/include/mbedtls_wrap.hpp index 5dc1df71ab..50ed1ccf88 100644 --- a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/include/mbedtls_wrap.hpp +++ b/components/mbedtls_cxx/include/mbedtls_wrap.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,34 +7,78 @@ #include #include -#include +#include +#include #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/error.h" -using const_buf = std::span; +namespace idf::mbedtls_cxx { +using const_buf = std::pair; +using buf = std::pair; + +struct TlsConfig { + bool is_dtls; + uint32_t timeout; + const_buf client_id; +}; + +/** + * @brief Application wrapper of (D)TLS for authentication and creating encrypted communication channels + */ class Tls { public: - enum class is_server : bool {}; - enum class do_verify : bool {}; + /** + * High level configs for this class are per below: (server/client, with/out verification, TLS/DTLS) + */ + enum class is_server : bool { + }; + enum class do_verify : bool { + }; + enum class is_dtls : bool { + }; Tls(); + virtual ~Tls(); - bool init(is_server server, do_verify verify); + + bool init(is_server server, do_verify verify, TlsConfig *config = nullptr); + + bool init_dtls_cookies(); + + bool set_client_id(); + bool deinit(); + int handshake(); + int write(const unsigned char *buf, size_t len); + int read(unsigned char *buf, size_t len); + [[nodiscard]] bool set_own_cert(const_buf crt, const_buf key); + [[nodiscard]] bool set_ca_cert(const_buf crt); + bool set_hostname(const char *name); + virtual int send(const unsigned char *buf, size_t len) = 0; + virtual int recv(unsigned char *buf, size_t len) = 0; + + virtual int recv_timeout(unsigned char *buf, size_t len, int timeout) + { + return recv(buf, len); + } + size_t get_available_bytes(); protected: + /** + * mbedTLS internal structures (available after inheritance) + */ mbedtls_ssl_context ssl_{}; mbedtls_x509_crt public_cert_{}; mbedtls_pk_context pk_key_{}; @@ -42,35 +86,56 @@ class Tls { mbedtls_ssl_config conf_{}; mbedtls_ctr_drbg_context ctr_drbg_{}; mbedtls_entropy_context entropy_{}; + mbedtls_timing_delay_context timer_{}; + mbedtls_ssl_cookie_ctx cookie_{}; + const_buf client_id_{}; + virtual void delay() {} + bool is_server_{false}; + bool is_dtls_{false}; + bool set_session(); + bool get_session(); + void reset_session(); + bool is_session_loaded(); private: static void print_error(const char *function, int error_code); + static int bio_write(void *ctx, const unsigned char *buf, size_t len); + static int bio_read(void *ctx, unsigned char *buf, size_t len); - int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen); + + static int bio_read_tout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout); + + int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen); + struct unique_session { unique_session() { ::mbedtls_ssl_session_init(&s); } + ~unique_session() { ::mbedtls_ssl_session_free(&s); } + mbedtls_ssl_session *ptr() { return &s; } + mbedtls_ssl_session s; }; + std::unique_ptr session_; }; +} diff --git a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/mbedtls_wrap.cpp b/components/mbedtls_cxx/mbedtls_wrap.cpp similarity index 59% rename from components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/mbedtls_wrap.cpp rename to components/mbedtls_cxx/mbedtls_wrap.cpp index eda6045fec..c486191592 100644 --- a/components/esp_modem/examples/modem_tcp_client/components/extra_tcp_transports/mbedtls_wrap.cpp +++ b/components/mbedtls_cxx/mbedtls_wrap.cpp @@ -1,23 +1,34 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include #include "mbedtls/ctr_drbg.h" #include "mbedtls/ssl.h" #include "mbedtls_wrap.hpp" -bool Tls::init(is_server server, do_verify verify) +using namespace idf::mbedtls_cxx; + +bool Tls::init(is_server server, do_verify verify, TlsConfig *config) { const char pers[] = "mbedtls_wrapper"; + is_server_ = server == is_server{true}; + is_dtls_ = config ? config->is_dtls : false; + uint32_t timeout = config ? config->timeout : 0; mbedtls_entropy_init(&entropy_); mbedtls_ctr_drbg_seed(&ctr_drbg_, mbedtls_entropy_func, &entropy_, (const unsigned char *)pers, sizeof(pers)); - int ret = mbedtls_ssl_config_defaults(&conf_, server == is_server{true} ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); + int endpoint = server == is_server{true} ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT; + int transport = is_dtls_ ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM; + int ret = mbedtls_ssl_config_defaults(&conf_, endpoint, transport, MBEDTLS_SSL_PRESET_DEFAULT); if (ret) { print_error("mbedtls_ssl_config_defaults", ret); return false; } mbedtls_ssl_conf_rng(&conf_, mbedtls_ctr_drbg_random, &ctr_drbg_); + if (timeout) { + mbedtls_ssl_conf_read_timeout(&conf_, timeout); + } mbedtls_ssl_conf_authmode(&conf_, verify == do_verify{true} ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE); ret = mbedtls_ssl_conf_own_cert(&conf_, &public_cert_, &pk_key_); if (ret) { @@ -27,11 +38,34 @@ bool Tls::init(is_server server, do_verify verify) if (verify == do_verify{true}) { mbedtls_ssl_conf_ca_chain(&conf_, &ca_cert_, nullptr); } + +#if CONFIG_MBEDTLS_SSL_PROTO_DTLS + if (is_server_ && is_dtls_) { + if (!init_dtls_cookies()) { + return false; + } + } +#endif // MBEDTLS_SSL_PROTO_DTLS + ret = mbedtls_ssl_setup(&ssl_, &conf_); if (ret) { print_error("mbedtls_ssl_setup", ret); return false; } + + if (timeout) { + mbedtls_ssl_set_timer_cb(&ssl_, &timer_, mbedtls_timing_set_delay, mbedtls_timing_get_delay); + } + +#if CONFIG_MBEDTLS_SSL_PROTO_DTLS + if (is_server_ && is_dtls_ && config && config->client_id != const_buf {}) { + client_id_ = config->client_id; + if (!set_client_id()) { + return false; + } + } +#endif // MBEDTLS_SSL_PROTO_DTLS + return true; } @@ -57,10 +91,19 @@ void Tls::print_error(const char *function, int error_code) int Tls::handshake() { int ret = 0; - mbedtls_ssl_set_bio(&ssl_, this, bio_write, bio_read, nullptr); + mbedtls_ssl_set_bio(&ssl_, this, bio_write, bio_read, is_dtls_ ? bio_read_tout : nullptr); while ( ( ret = mbedtls_ssl_handshake( &ssl_ ) ) != 0 ) { if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { +#if CONFIG_MBEDTLS_SSL_PROTO_DTLS + if (is_server_ && is_dtls_ && ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { + // hello verification requested -> restart the session with this client_id + if (!set_client_id()) { + return -1; + } + continue; + } +#endif // MBEDTLS_SSL_PROTO_DTLS print_error( "mbedtls_ssl_handshake returned", ret ); return -1; } @@ -81,6 +124,12 @@ int Tls::bio_read(void *ctx, unsigned char *buf, size_t len) return s->recv(buf, len); } +int Tls::bio_read_tout(void *ctx, unsigned char *buf, size_t len, uint32_t timeout) +{ + auto s = static_cast(ctx); + return s->recv_timeout(buf, len, timeout); +} + int Tls::write(const unsigned char *buf, size_t len) { return mbedtls_ssl_write( &ssl_, buf, len ); @@ -93,12 +142,12 @@ int Tls::read(unsigned char *buf, size_t len) bool Tls::set_own_cert(const_buf crt, const_buf key) { - int ret = mbedtls_x509_crt_parse(&public_cert_, crt.data(), crt.size()); + int ret = mbedtls_x509_crt_parse(&public_cert_, crt.first, crt.second); if (ret < 0) { print_error("mbedtls_x509_crt_parse", ret); return false; } - ret = mbedtls_pk_parse_key(&pk_key_, key.data(), key.size(), nullptr, 0); + ret = mbedtls_pk_parse_key(&pk_key_, key.first, key.second, nullptr, 0); if (ret < 0) { print_error("mbedtls_pk_parse_keyfile", ret); return false; @@ -108,7 +157,7 @@ bool Tls::set_own_cert(const_buf crt, const_buf key) bool Tls::set_ca_cert(const_buf crt) { - int ret = mbedtls_x509_crt_parse(&ca_cert_, crt.data(), crt.size()); + int ret = mbedtls_x509_crt_parse(&ca_cert_, crt.first, crt.second); if (ret < 0) { print_error("mbedtls_x509_crt_parse", ret); return false; @@ -188,3 +237,32 @@ bool Tls::is_session_loaded() { return session_ != nullptr; } + +#if CONFIG_MBEDTLS_SSL_PROTO_DTLS +bool Tls::init_dtls_cookies() +{ + int ret = mbedtls_ssl_cookie_setup(&cookie_, mbedtls_ctr_drbg_random, &ctr_drbg_); + if (ret != 0) { + print_error("mbedtls_ssl_cookie_setup() failed", ret); + return false; + } + mbedtls_ssl_conf_dtls_cookies(&conf_, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &cookie_); + + return true; +} + +bool Tls::set_client_id() +{ + int ret; + if (client_id_ == const_buf{}) { + printf("client_id is not set"); + return false; + } + mbedtls_ssl_session_reset(&ssl_); + if ((ret = mbedtls_ssl_set_client_transport_id(&ssl_, client_id_.first, client_id_.second)) != 0) { + print_error("mbedtls_ssl_set_client_transport_id()", ret); + return false; + } + return true; +} +#endif diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/CMakeLists.txt b/components/mbedtls_cxx/tests/uart_mutual_auth/CMakeLists.txt new file mode 100644 index 0000000000..2069c9fde5 --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/CMakeLists.txt @@ -0,0 +1,8 @@ +# For more information about build system see +# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(uart_mutual) diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/README.md b/components/mbedtls_cxx/tests/uart_mutual_auth/README.md new file mode 100644 index 0000000000..eeac985bd4 --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/README.md @@ -0,0 +1,17 @@ +# UART mutual authentication test + +This test creates a (D)TLS server and a client on one device and checks if they can perform a TLS handshake and exchange a message. +The test uses UART as the physical layer of communication channel and, since it runs on a single ESP32, it expects two UART ports interconnected as per below: + +``` + +------------------------+ + | ESP32 | + | | + | UART-1 UART-2 | + +---25---26------4---5---+ + | | | | + | +-------+ | + +----------------+ +``` + +The test runs in two configurations: TLS and DTLS. diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/main/CMakeLists.txt b/components/mbedtls_cxx/tests/uart_mutual_auth/main/CMakeLists.txt new file mode 100644 index 0000000000..99edf49baa --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "uart_mutual.cpp" + INCLUDE_DIRS ".") diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/main/Kconfig.projbuild b/components/mbedtls_cxx/tests/uart_mutual_auth/main/Kconfig.projbuild new file mode 100644 index 0000000000..91d2c47f32 --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/main/Kconfig.projbuild @@ -0,0 +1,19 @@ +menu "Test Configuration" + + choice TEST_CONNECTION_METHOD + prompt "Choose connection method" + default TEST_TLS + help + Select type of connection. Either TLS or DTLS + + config TEST_TLS + bool "TLS" + help + Use TLS method. + config TEST_DTLS + bool "DTLS" + help + Use DTLS method. + endchoice # TEST_CONNECTION_METHOD + +endmenu diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/main/idf_component.yml b/components/mbedtls_cxx/tests/uart_mutual_auth/main/idf_component.yml new file mode 100644 index 0000000000..a21bc68739 --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/main/idf_component.yml @@ -0,0 +1,8 @@ +dependencies: + idf: ">=5.0" + espressif/mbedtls_cxx: + version: "*" + override_path: "../../.." + test_certs: + version: "*" + path: "../../../examples/test_certs" diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/main/uart_mutual.cpp b/components/mbedtls_cxx/tests/uart_mutual_auth/main/uart_mutual.cpp new file mode 100644 index 0000000000..767ff48545 --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/main/uart_mutual.cpp @@ -0,0 +1,282 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include "esp_log.h" +#include "mbedtls_wrap.hpp" +#include "driver/uart.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "test_certs.hpp" + +namespace { +constexpr auto *TAG = "uart_mutual_tls"; + +/** + * Using DTLS the below is set to true. + * In that case, we need to receive the entire datagram, not a fragment + * This defines a very simple datagram protocol over UART: + * | HEADER (2bytes) | PAYLOAD ... | + * | dgram_len | dgram_payload | + * + * If `use_dgrams` is set to false, we perform TLS on UART stream. + * The UART driver is already a stream-like API (using ringbufer), so we simple read and write to UART + */ +#if CONFIG_TEST_TLS +const bool use_dgrams = false; +#elif CONFIG_TEST_DTLS +const bool use_dgrams = true; +#endif +} + +using namespace idf::mbedtls_cxx; +using namespace test_certs; + +class SecureLink: public Tls { +public: + explicit SecureLink(uart_port_t port, int tx, int rx) : Tls(), uart(port, tx, rx) {} + ~SecureLink() = default; + int send(const unsigned char *buf, size_t len) override + { + if (use_dgrams) { + // sends a separate dgram header + uint16_t header = len; + uart_write_bytes(uart.port_, &header, 2); + } + return uart_write_bytes(uart.port_, buf, len); + } + + int recv(unsigned char *buf, size_t len) override + { + // stream read + return uart.recv(buf, len, 0); + } + + int recv_timeout(unsigned char *buf, size_t len, int timeout) override + { + // dgram read + return uart.recv_dgram(buf, len, timeout); + } + + bool listen() // open as server + { + return open(true); + } + + bool connect() // open as client + { + return open(false); + } + +private: + bool open(bool server_not_client) + { + if (uart.init() != ESP_OK) { + return false; + } + while (!uart.debounce(server_not_client)) { + printf("debouncing...\n"); + usleep(10000); + } + TlsConfig config{}; + config.is_dtls = use_dgrams; + config.timeout = 10000; + if (server_not_client) { + const unsigned char client_id[] = "Client1"; + config.client_id = std::make_pair(client_id, sizeof(client_id)); + } + if (!init(is_server{server_not_client}, do_verify{true}, &config)) { + return false; + } + + return handshake() == 0; + } + + /** + * RAII wrapper of UART + */ + struct uart_info { + uart_port_t port_; + QueueHandle_t queue_{}; + int tx_, rx_; + + // used for datagrams + bool header_{true}; + int in_payload_{0}; + int payload_len_{0}; + uint8_t payload_[1600] {}; + + explicit uart_info(uart_port_t port, int tx, int rx): port_(port), tx_(tx), rx_(rx) + { + } + esp_err_t init() + { + uart_config_t uart_config = {}; + uart_config.baud_rate = 115200; + uart_config.data_bits = UART_DATA_8_BITS; + uart_config.parity = UART_PARITY_DISABLE; + uart_config.stop_bits = UART_STOP_BITS_1; + uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; + uart_config.source_clk = UART_SCLK_DEFAULT; + ESP_RETURN_ON_ERROR(uart_driver_install(port_, 1024, 0, 1, &queue_, 0), TAG, "Failed to install UART"); + ESP_RETURN_ON_ERROR(uart_param_config(port_, &uart_config), TAG, "Failed to set params"); + ESP_RETURN_ON_ERROR(uart_set_pin(port_, tx_, rx_, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE), TAG, "Failed to set UART pins"); + ESP_RETURN_ON_ERROR(uart_set_rx_timeout(port_, 10), TAG, "Failed to set UART Rx timeout"); + return ESP_OK; + } + ~uart_info() + { + uart_driver_delete(port_); + } + bool debounce(bool server) + { + uint8_t data = 0; + if (server) { + while (uart_read_bytes(port_, &data, 1, 0) != 0) { + if (data == 0x55) { + uart_write_bytes(port_, &data, 1); + return true; + } + } + return false; + } + data = 0x55; + uart_write_bytes(port_, &data, 1); + data = 0; + uart_read_bytes(port_, &data, 1, pdMS_TO_TICKS(1000)); + if (data != 0x55) { + uart_flush_input(port_); + return false; + } + return true; + } + + int recv(unsigned char *buf, size_t size, int timeout) // this is for stream transport + { + int len = uart_read_bytes(port_, buf, size, pdMS_TO_TICKS(timeout)); + if (len == 0) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + return len; + } + + int recv_dgram(unsigned char *buf, size_t size, int timeout) // this is for datagrams + { + uart_event_t event = {}; + size_t length; + uart_get_buffered_data_len(port_, &length); + if (length == 0) { + xQueueReceive(queue_, &event, pdMS_TO_TICKS(timeout)); + } + uart_get_buffered_data_len(port_, &length); + if (length == 0) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + if (header_) { + if (length >= 2) { + uart_read_bytes(port_, &payload_len_, 2, 0); + header_ = false; + length -= 2; + } + } + if (!header_ && length > 0) { + int to_read = payload_len_ - in_payload_; + int l = uart_read_bytes(port_, &payload_[in_payload_], to_read, 0); + in_payload_ += l; + if (payload_len_ == in_payload_) { + header_ = true; + memcpy(buf, payload_, payload_len_); + in_payload_ = 0; + return payload_len_; + } + } + return MBEDTLS_ERR_SSL_WANT_READ; + } + } uart; +}; + +namespace { +void tls_client() +{ + const unsigned char message[] = "Hello\n"; + unsigned char reply[128]; + SecureLink client(UART_NUM_2, 4, 5); + client.set_hostname(get_server_cn()); + if (!client.set_own_cert(get_buf(type::clientcert), get_buf(type::clientkey))) { + ESP_LOGE(TAG, "Failed to set own cert"); + return; + } + if (!client.set_ca_cert(get_buf(type::cacert))) { + ESP_LOGE(TAG, "Failed to set peer's cert"); + return; + } + if (!client.connect()) { + ESP_LOGE(TAG, "Failed to CONNECT! %d", errno); + return; + } + ESP_LOGI(TAG, "client opened..."); + if (client.write(message, sizeof(message)) < 0) { + ESP_LOGE(TAG, "Failed to write!"); + return; + } + + int len; + while ((len = client.read(reply, sizeof(reply))) == MBEDTLS_ERR_SSL_WANT_READ) { + vTaskDelay(pdMS_TO_TICKS(500)); + } + if (len < 0) { + ESP_LOGE(TAG, "Failed to read!"); + return; + } + ESP_LOGI(TAG, "Successfully received: %.*s", len, reply); +} + +void tls_server() +{ + unsigned char message[128]; + SecureLink server(UART_NUM_1, 25, 26); + if (!server.set_own_cert(get_buf(type::servercert), get_buf(type::serverkey))) { + ESP_LOGE(TAG, "Failed to set own cert"); + return; + } + if (!server.set_ca_cert(get_buf(type::cacert))) { + ESP_LOGE(TAG, "Failed to set peer's cert"); + return; + } + ESP_LOGI(TAG, "openning..."); + if (!server.listen()) { + ESP_LOGE(TAG, "Failed to OPEN! %d", errno); + return; + } + int len; + while ((len = server.read(message, sizeof(message))) == MBEDTLS_ERR_SSL_WANT_READ) { + vTaskDelay(pdMS_TO_TICKS(500)); + } + if (len < 0) { + ESP_LOGE(TAG, "Failed to read! %x", -len); + return; + } + ESP_LOGI(TAG, "Received from client: %.*s", len, message); + if (server.write(message, len) < 0) { + ESP_LOGE(TAG, "Failed to write!"); + return; + } + ESP_LOGI(TAG, "Written back"); + vTaskDelay(pdMS_TO_TICKS(500)); +} +} // namespace + +extern "C" void app_main() +{ + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + std::thread t2(tls_server); + std::thread t1(tls_client); + t1.join(); + t2.join(); +} diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.dtls b/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.dtls new file mode 100644 index 0000000000..5d61d8a487 --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.dtls @@ -0,0 +1,3 @@ +CONFIG_TEST_DTLS=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192 diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.tls b/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.tls new file mode 100644 index 0000000000..512cc006ff --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.ci.tls @@ -0,0 +1,3 @@ +CONFIG_TEST_TLS=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192 diff --git a/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.defaults b/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.defaults new file mode 100644 index 0000000000..76a2028264 --- /dev/null +++ b/components/mbedtls_cxx/tests/uart_mutual_auth/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192 From 13793a8236d4c1038e60ec5ee063af060a07fef5 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Thu, 11 Apr 2024 16:52:51 +0200 Subject: [PATCH 2/2] bump(tls_cxx): First version [0.1.0] 0.1.0 Features - Publish mbedtls component (0140455f) --- components/mbedtls_cxx/.cz.yaml | 2 +- components/mbedtls_cxx/CHANGELOG.md | 7 +++++++ components/mbedtls_cxx/idf_component.yml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 components/mbedtls_cxx/CHANGELOG.md diff --git a/components/mbedtls_cxx/.cz.yaml b/components/mbedtls_cxx/.cz.yaml index 19a1e30dd4..d4da46e78c 100644 --- a/components/mbedtls_cxx/.cz.yaml +++ b/components/mbedtls_cxx/.cz.yaml @@ -3,6 +3,6 @@ commitizen: bump_message: 'bump(tls_cxx): $current_version -> $new_version' pre_bump_hooks: python ../../ci/changelog.py mbedtls_cxx tag_format: tls_cxx-v$version - version: 0.0.0 + version: 0.1.0 version_files: - idf_component.yml diff --git a/components/mbedtls_cxx/CHANGELOG.md b/components/mbedtls_cxx/CHANGELOG.md new file mode 100644 index 0000000000..c1cffd1fc9 --- /dev/null +++ b/components/mbedtls_cxx/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +## [0.1.0](https://github.com/espressif/esp-protocols/commits/tls_cxx-v0.1.0) + +### Features + +- Publish mbedtls component ([0140455f](https://github.com/espressif/esp-protocols/commit/0140455f)) diff --git a/components/mbedtls_cxx/idf_component.yml b/components/mbedtls_cxx/idf_component.yml index 1c352e7432..8d753a8339 100644 --- a/components/mbedtls_cxx/idf_component.yml +++ b/components/mbedtls_cxx/idf_component.yml @@ -1,4 +1,4 @@ -version: 0.0.0 +version: 0.1.0 url: https://github.com/espressif/esp-protocols/tree/master/components/mbedtls_cxx description: C++ wrapper of mbedtls to perform (D)TLS connection license: Apache-2.0