mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-17 12:32:14 +02:00
feat(tls_cxx): Publish mbedtls component
Adds examples and tests. Also supports DTLS now.
This commit is contained in:
@ -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)
|
4
components/mbedtls_cxx/examples/test_certs/README.md
Normal file
4
components/mbedtls_cxx/examples/test_certs/README.md
Normal file
@ -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.
|
19
components/mbedtls_cxx/examples/test_certs/ca.crt
Normal file
19
components/mbedtls_cxx/examples/test_certs/ca.crt
Normal file
@ -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-----
|
17
components/mbedtls_cxx/examples/test_certs/client.crt
Normal file
17
components/mbedtls_cxx/examples/test_certs/client.crt
Normal file
@ -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-----
|
27
components/mbedtls_cxx/examples/test_certs/client.key
Normal file
27
components/mbedtls_cxx/examples/test_certs/client.key
Normal file
@ -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-----
|
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/mbedtls_cxx:
|
||||
version: "*"
|
||||
override_path: "../.."
|
17
components/mbedtls_cxx/examples/test_certs/srv.crt
Normal file
17
components/mbedtls_cxx/examples/test_certs/srv.crt
Normal file
@ -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-----
|
27
components/mbedtls_cxx/examples/test_certs/srv.key
Normal file
27
components/mbedtls_cxx/examples/test_certs/srv.key
Normal file
@ -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-----
|
51
components/mbedtls_cxx/examples/test_certs/test_certs.hpp
Normal file
51
components/mbedtls_cxx/examples/test_certs/test_certs.hpp
Normal file
@ -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";
|
||||
}
|
||||
|
||||
}
|
11
components/mbedtls_cxx/examples/tls_client/CMakeLists.txt
Normal file
11
components/mbedtls_cxx/examples/tls_client/CMakeLists.txt
Normal file
@ -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)
|
4
components/mbedtls_cxx/examples/tls_client/README.md
Normal file
4
components/mbedtls_cxx/examples/tls_client/README.md
Normal file
@ -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.
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "tls_client.cpp"
|
||||
INCLUDE_DIRS ".")
|
@ -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
|
152
components/mbedtls_cxx/examples/tls_client/main/tls_client.cpp
Normal file
152
components/mbedtls_cxx/examples/tls_client/main/tls_client.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#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
|
@ -0,0 +1 @@
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
@ -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)
|
@ -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.
|
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "udp_mutual.cpp"
|
||||
INCLUDE_DIRS ".")
|
@ -0,0 +1,8 @@
|
||||
dependencies:
|
||||
idf: ">=5.0"
|
||||
espressif/mbedtls_cxx:
|
||||
version: "*"
|
||||
override_path: "../../.."
|
||||
test_certs:
|
||||
version: "*"
|
||||
path: "../../test_certs"
|
@ -0,0 +1,229 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <thread>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#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
|
@ -0,0 +1,2 @@
|
||||
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
|
||||
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192
|
Reference in New Issue
Block a user