mirror of
https://github.com/espressif/openthread.git
synced 2026-08-26 12:11:17 +00:00
[cli-tcp] add TLS mode to TCP CLI tool and TLS callbacks to TCP API (#8257)
This commit adds support for TLS in the TCP CLI tool, along with a test of TLS functionality. The main purpose of this is to provide an example of how to use mbedTLS with TCPlp to run TLS. I felt it is important to have an example because I expect that many applications that use TCP, particularly those in which a Thread device exchanges data with a device outside the Thread mesh, will need to run TLS over TCP for security reasons. A secondary benefit is to add TCP functionality to the TCP CLI tool. Additionally, by having the example code be part of a "real" application (the CLI tool), there is less risk of the code going stale as OpenThread evolves. I added an "expects" test for the TLS functionality in the CLI tool. I also ran the code on two Nordic NRF52840-DK boards to make sure it works. The performance impact of TLS appears to be small. When using TCP without TLS, I am able to achieve ~80 kb/s goodput between two NRF52840-DK boards. With TLS in the same setup, I am able to achieve ~70-75 kb/s goodput.
This commit is contained in:
@@ -49,6 +49,7 @@ OPENTHREAD_PUBLIC_CFLAGS := \
|
|||||||
-DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1 \
|
-DOPENTHREAD_CONFIG_MAC_FILTER_ENABLE=1 \
|
||||||
-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1 \
|
-DOPENTHREAD_CONFIG_NCP_HDLC_ENABLE=1 \
|
||||||
-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1 \
|
-DOPENTHREAD_CONFIG_PING_SENDER_ENABLE=1 \
|
||||||
|
-DOPENTHREAD_CONFIG_TLS_ENABLE=1 \
|
||||||
-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1 \
|
-DOPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE=1 \
|
||||||
-DOPENTHREAD_FTD=1 \
|
-DOPENTHREAD_FTD=1 \
|
||||||
-DOPENTHREAD_PLATFORM_POSIX=1 \
|
-DOPENTHREAD_PLATFORM_POSIX=1 \
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ extern "C" {
|
|||||||
* @note This number versions both OpenThread platform and user APIs.
|
* @note This number versions both OpenThread platform and user APIs.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define OPENTHREAD_API_VERSION (277)
|
#define OPENTHREAD_API_VERSION (278)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @addtogroup api-instance
|
* @addtogroup api-instance
|
||||||
|
|||||||
@@ -147,8 +147,8 @@ enum
|
|||||||
* @p aLength if the send buffer reaches capacity.
|
* @p aLength if the send buffer reaches capacity.
|
||||||
* @param[in] aFlags Flags specifying options for this operation (see enumeration above).
|
* @param[in] aFlags Flags specifying options for this operation (see enumeration above).
|
||||||
*
|
*
|
||||||
* @returns OT_ERROR_NONE Successfully copied data into the send buffer and sent it on the TCP endpoint.
|
* @retval OT_ERROR_NONE Successfully copied data into the send buffer and sent it on the TCP endpoint.
|
||||||
* @returns OT_ERROR_FAILED Failed to send out data on the TCP endpoint.
|
* @retval OT_ERROR_FAILED Failed to send out data on the TCP endpoint.
|
||||||
*/
|
*/
|
||||||
otError otTcpCircularSendBufferWrite(otTcpEndpoint *aEndpoint,
|
otError otTcpCircularSendBufferWrite(otTcpEndpoint *aEndpoint,
|
||||||
otTcpCircularSendBuffer *aSendBuffer,
|
otTcpCircularSendBuffer *aSendBuffer,
|
||||||
@@ -184,7 +184,7 @@ void otTcpCircularSendBufferHandleForwardProgress(otTcpCircularSendBuffer *aSend
|
|||||||
*
|
*
|
||||||
* @param[in] aSendBuffer A pointer to the TCP circular send buffer whose amount of free space to return.
|
* @param[in] aSendBuffer A pointer to the TCP circular send buffer whose amount of free space to return.
|
||||||
*
|
*
|
||||||
* @return The amount of free space in the send buffer.
|
* @returns The amount of free space in the send buffer.
|
||||||
*/
|
*/
|
||||||
size_t otTcpCircularSendBufferGetFreeSpace(const otTcpCircularSendBuffer *aSendBuffer);
|
size_t otTcpCircularSendBufferGetFreeSpace(const otTcpCircularSendBuffer *aSendBuffer);
|
||||||
|
|
||||||
@@ -215,6 +215,37 @@ void otTcpCircularSendBufferForceDiscardAll(otTcpCircularSendBuffer *aSendBuffer
|
|||||||
*/
|
*/
|
||||||
otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer);
|
otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context structure to use with mbedtls_ssl_set_bio.
|
||||||
|
*/
|
||||||
|
typedef struct otTcpEndpointAndCircularSendBuffer
|
||||||
|
{
|
||||||
|
otTcpEndpoint *mEndpoint;
|
||||||
|
otTcpCircularSendBuffer *mSendBuffer;
|
||||||
|
} otTcpEndpointAndCircularSendBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-blocking send callback to pass to mbedtls_ssl_set_bio.
|
||||||
|
*
|
||||||
|
* @param[in] aCtx A pointer to an otTcpEndpointAndCircularSendBuffer.
|
||||||
|
* @param[in] aBuf The data to add to the send buffer.
|
||||||
|
* @param[in] aLen The amount of data to add to the send buffer.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes sent, or an mbedtls error code.
|
||||||
|
*/
|
||||||
|
int otTcpMbedTlsSslSendCallback(void *aCtx, const unsigned char *aBuf, size_t aLen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-blocking receive callback to pass to mbedtls_ssl_set_bio.
|
||||||
|
*
|
||||||
|
* @param[in] aCtx A pointer to an otTcpEndpointAndCircularSendBuffer.
|
||||||
|
* @param[out] aBuf The buffer into which to receive data.
|
||||||
|
* @param[in] aLen The maxmimum amount of data that can be received.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes received, or an mbedtls error code.
|
||||||
|
*/
|
||||||
|
int otTcpMbedTlsSslRecvCallback(void *aCtx, unsigned char *aBuf, size_t aLen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -157,14 +157,19 @@ stoplistening
|
|||||||
Done
|
Done
|
||||||
```
|
```
|
||||||
|
|
||||||
### init [\<size\>]
|
### init [\<mode\>] [\<size\>]
|
||||||
|
|
||||||
Initializes the example TCP listener and the example TCP endpoint.
|
Initializes the example TCP listener and the example TCP endpoint.
|
||||||
|
|
||||||
|
- mode: this specifies the buffering strategy and whether to use TLS. The possible values are "linked", "circular" (default), and "tls".
|
||||||
- size: the size of the receive buffer to associate with the example TCP endpoint. If left unspecified, the maximum size is used.
|
- size: the size of the receive buffer to associate with the example TCP endpoint. If left unspecified, the maximum size is used.
|
||||||
|
|
||||||
|
If "tls" is used, then the TLS protocol will be used for the connection (on top of TCP). When communicating over TCP between two nodes, either both should use TLS or neither should (a non-TLS endpoint cannot communicate with a TLS endpoint). The first two options, "linked" and "circular", specify that TLS should not be used and specify a buffering strategy to use with TCP; two endpoints of a TCP connection may use different buffering strategies.
|
||||||
|
|
||||||
|
The behaviors of "linked" and "circular" buffering are identical, but the option is provided so that users of TCP can inspect the code to see an example of using the two buffering strategies.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
> tcp init
|
> tcp init tls
|
||||||
Done
|
Done
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+284
-21
@@ -46,6 +46,11 @@
|
|||||||
#include "common/encoding.hpp"
|
#include "common/encoding.hpp"
|
||||||
#include "common/timer.hpp"
|
#include "common/timer.hpp"
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
#include <mbedtls/debug.h>
|
||||||
|
#include <mbedtls/ecjpake.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ot {
|
namespace ot {
|
||||||
namespace Cli {
|
namespace Cli {
|
||||||
|
|
||||||
@@ -55,11 +60,30 @@ TcpExample::TcpExample(otInstance *aInstance, OutputImplementer &aOutputImplemen
|
|||||||
, mEndpointConnected(false)
|
, mEndpointConnected(false)
|
||||||
, mSendBusy(false)
|
, mSendBusy(false)
|
||||||
, mUseCircularSendBuffer(true)
|
, mUseCircularSendBuffer(true)
|
||||||
|
, mUseTls(false)
|
||||||
|
, mTlsHandshakeComplete(false)
|
||||||
, mBenchmarkBytesTotal(0)
|
, mBenchmarkBytesTotal(0)
|
||||||
, mBenchmarkBytesUnsent(0)
|
, mBenchmarkBytesUnsent(0)
|
||||||
{
|
{
|
||||||
|
mEndpointAndCircularSendBuffer.mEndpoint = &mEndpoint;
|
||||||
|
mEndpointAndCircularSendBuffer.mSendBuffer = &mSendBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
static int mbedtls_entropy_function(void *ctx, unsigned char *buffer, size_t length)
|
||||||
|
{
|
||||||
|
OT_UNUSED_VARIABLE(ctx);
|
||||||
|
otError error = ot::Random::Crypto::FillBuffer(static_cast<uint8_t *>(buffer), static_cast<uint16_t>(length));
|
||||||
|
return (error == OT_ERROR_NONE) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcpExample::MbedTlsDebugOutput(void *ctx, int level, const char *file, int line, const char *str)
|
||||||
|
{
|
||||||
|
TcpExample &tcpExample = *static_cast<TcpExample *>(ctx);
|
||||||
|
tcpExample.OutputLine("%s:%d:%d: %s", file, line, level, str);
|
||||||
|
}
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
template <> otError TcpExample::Process<Cmd("init")>(Arg aArgs[])
|
template <> otError TcpExample::Process<Cmd("init")>(Arg aArgs[])
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error = OT_ERROR_NONE;
|
||||||
@@ -70,18 +94,84 @@ template <> otError TcpExample::Process<Cmd("init")>(Arg aArgs[])
|
|||||||
if (aArgs[0].IsEmpty())
|
if (aArgs[0].IsEmpty())
|
||||||
{
|
{
|
||||||
mUseCircularSendBuffer = true;
|
mUseCircularSendBuffer = true;
|
||||||
|
mUseTls = false;
|
||||||
receiveBufferSize = sizeof(mReceiveBufferBytes);
|
receiveBufferSize = sizeof(mReceiveBufferBytes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (aArgs[0] == "circular")
|
if (aArgs[0] == "linked")
|
||||||
{
|
|
||||||
mUseCircularSendBuffer = true;
|
|
||||||
}
|
|
||||||
else if (aArgs[0] == "linked")
|
|
||||||
{
|
{
|
||||||
mUseCircularSendBuffer = false;
|
mUseCircularSendBuffer = false;
|
||||||
|
mUseTls = false;
|
||||||
}
|
}
|
||||||
|
else if (aArgs[0] == "circular")
|
||||||
|
{
|
||||||
|
mUseCircularSendBuffer = true;
|
||||||
|
mUseTls = false;
|
||||||
|
}
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
else if (aArgs[0] == "tls")
|
||||||
|
{
|
||||||
|
mUseCircularSendBuffer = true;
|
||||||
|
mUseTls = true;
|
||||||
|
|
||||||
|
// mbedtls_debug_set_threshold(0);
|
||||||
|
|
||||||
|
mbedtls_ctr_drbg_init(&mCtrDrbg);
|
||||||
|
mbedtls_x509_crt_init(&mSrvCert);
|
||||||
|
mbedtls_pk_init(&mPKey);
|
||||||
|
|
||||||
|
mbedtls_ssl_init(&mSslContext);
|
||||||
|
mbedtls_ssl_config_init(&mSslConfig);
|
||||||
|
mbedtls_ssl_conf_rng(&mSslConfig, mbedtls_ctr_drbg_random, &mCtrDrbg);
|
||||||
|
// mbedtls_ssl_conf_dbg(&mSslConfig, MbedTlsDebugOutput, this);
|
||||||
|
mbedtls_ssl_conf_authmode(&mSslConfig, MBEDTLS_SSL_VERIFY_NONE);
|
||||||
|
mbedtls_entropy_init(&mEntropy);
|
||||||
|
|
||||||
|
#if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
|
||||||
|
mbedtls_ssl_conf_min_tls_version(&mSslConfig, MBEDTLS_SSL_VERSION_TLS1_2);
|
||||||
|
mbedtls_ssl_conf_max_tls_version(&mSslConfig, MBEDTLS_SSL_VERSION_TLS1_2);
|
||||||
|
#else
|
||||||
|
mbedtls_ssl_conf_min_version(&mSslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
|
||||||
|
mbedtls_ssl_conf_max_version(&mSslConfig, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||||
|
#include "crypto/mbedtls.hpp"
|
||||||
|
int rv = mbedtls_pk_parse_key(&mPKey, reinterpret_cast<const unsigned char *>(sSrvKey), sSrvKeyLength,
|
||||||
|
nullptr, 0, Crypto::MbedTls::CryptoSecurePrng, nullptr);
|
||||||
|
#else
|
||||||
|
int rv = mbedtls_pk_parse_key(&mPKey, reinterpret_cast<const unsigned char *>(sSrvKey), sSrvKeyLength,
|
||||||
|
nullptr, 0);
|
||||||
|
#endif
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_pk_parse_key returned %d", rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = mbedtls_ctr_drbg_seed(&mCtrDrbg, mbedtls_entropy_function, nullptr, nullptr, 0);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_ctr_drbg_seed returned %d", rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = mbedtls_x509_crt_parse(&mSrvCert, reinterpret_cast<const unsigned char *>(sSrvPem), sSrvPemLength);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_x509_crt_parse (1) returned %d", rv);
|
||||||
|
}
|
||||||
|
rv = mbedtls_x509_crt_parse(&mSrvCert, reinterpret_cast<const unsigned char *>(sCasPem), sCasPemLength);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_x509_crt_parse (2) returned %d", rv);
|
||||||
|
}
|
||||||
|
rv = mbedtls_ssl_setup(&mSslContext, &mSslConfig);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_ssl_setup returned %d", rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||||
@@ -159,6 +249,19 @@ template <> otError TcpExample::Process<Cmd("deinit")>(Arg aArgs[])
|
|||||||
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||||
VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
|
VerifyOrExit(mInitialized, error = OT_ERROR_INVALID_STATE);
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls)
|
||||||
|
{
|
||||||
|
mbedtls_entropy_free(&mEntropy);
|
||||||
|
mbedtls_ssl_config_free(&mSslConfig);
|
||||||
|
mbedtls_ssl_free(&mSslContext);
|
||||||
|
|
||||||
|
mbedtls_pk_free(&mPKey);
|
||||||
|
mbedtls_x509_crt_free(&mSrvCert);
|
||||||
|
mbedtls_ctr_drbg_free(&mCtrDrbg);
|
||||||
|
}
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
endpointError = otTcpEndpointDeinitialize(&mEndpoint);
|
endpointError = otTcpEndpointDeinitialize(&mEndpoint);
|
||||||
mSendBusy = false;
|
mSendBusy = false;
|
||||||
|
|
||||||
@@ -212,6 +315,18 @@ template <> otError TcpExample::Process<Cmd("connect")>(Arg aArgs[])
|
|||||||
SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort));
|
SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort));
|
||||||
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls)
|
||||||
|
{
|
||||||
|
int rv = mbedtls_ssl_config_defaults(&mSslConfig, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_ssl_config_defaults returned %d", rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
SuccessOrExit(error = otTcpConnect(&mEndpoint, &sockaddr, OT_TCP_CONNECT_NO_FAST_OPEN));
|
SuccessOrExit(error = otTcpConnect(&mEndpoint, &sockaddr, OT_TCP_CONNECT_NO_FAST_OPEN));
|
||||||
mEndpointConnected = true;
|
mEndpointConnected = true;
|
||||||
|
|
||||||
@@ -230,9 +345,24 @@ template <> otError TcpExample::Process<Cmd("send")>(Arg aArgs[])
|
|||||||
|
|
||||||
if (mUseCircularSendBuffer)
|
if (mUseCircularSendBuffer)
|
||||||
{
|
{
|
||||||
size_t written;
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
SuccessOrExit(error = otTcpCircularSendBufferWrite(&mEndpoint, &mSendBuffer, aArgs[0].GetCString(),
|
if (mUseTls)
|
||||||
aArgs[0].GetLength(), &written, 0));
|
{
|
||||||
|
int rv = mbedtls_ssl_write(&mSslContext, reinterpret_cast<unsigned char *>(aArgs[0].GetCString()),
|
||||||
|
aArgs[0].GetLength());
|
||||||
|
if (rv < 0 && rv != MBEDTLS_ERR_SSL_WANT_WRITE && rv != MBEDTLS_ERR_SSL_WANT_READ)
|
||||||
|
{
|
||||||
|
ExitNow(error = kErrorFailed);
|
||||||
|
}
|
||||||
|
error = kErrorNone;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
{
|
||||||
|
size_t written;
|
||||||
|
SuccessOrExit(error = otTcpCircularSendBufferWrite(&mEndpoint, &mSendBuffer, aArgs[0].GetCString(),
|
||||||
|
aArgs[0].GetLength(), &written, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -442,6 +572,27 @@ void TcpExample::HandleTcpEstablished(otTcpEndpoint *aEndpoint)
|
|||||||
{
|
{
|
||||||
OT_UNUSED_VARIABLE(aEndpoint);
|
OT_UNUSED_VARIABLE(aEndpoint);
|
||||||
OutputLine("TCP: Connection established");
|
OutputLine("TCP: Connection established");
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
rv = mbedtls_ssl_set_hostname(&mSslContext, "localhost");
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_ssl_set_hostname returned %d", rv);
|
||||||
|
}
|
||||||
|
rv = mbedtls_ssl_set_hs_ecjpake_password(
|
||||||
|
&mSslContext, reinterpret_cast<const unsigned char *>(sEcjpakePassword), sEcjpakePasswordLength);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_ssl_set_hs_ecjpake_password returned %d", rv);
|
||||||
|
}
|
||||||
|
mbedtls_ssl_set_bio(&mSslContext, &mEndpointAndCircularSendBuffer, otTcpMbedTlsSslSendCallback,
|
||||||
|
otTcpMbedTlsSslRecvCallback, nullptr);
|
||||||
|
mTlsHandshakeComplete = false;
|
||||||
|
ContinueTLSHandshake();
|
||||||
|
}
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
void TcpExample::HandleTcpSendDone(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData)
|
void TcpExample::HandleTcpSendDone(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData)
|
||||||
@@ -488,6 +639,13 @@ void TcpExample::HandleTcpForwardProgress(otTcpEndpoint *aEndpoint, size_t aInSe
|
|||||||
|
|
||||||
otTcpCircularSendBufferHandleForwardProgress(&mSendBuffer, aInSendBuffer);
|
otTcpCircularSendBufferHandleForwardProgress(&mSendBuffer, aInSendBuffer);
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls)
|
||||||
|
{
|
||||||
|
ContinueTLSHandshake();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Handle case where we're in a benchmark. */
|
/* Handle case where we're in a benchmark. */
|
||||||
if (mBenchmarkBytesTotal != 0)
|
if (mBenchmarkBytesTotal != 0)
|
||||||
{
|
{
|
||||||
@@ -512,20 +670,53 @@ void TcpExample::HandleTcpReceiveAvailable(otTcpEndpoint *aEndpoint,
|
|||||||
OT_UNUSED_VARIABLE(aBytesRemaining);
|
OT_UNUSED_VARIABLE(aBytesRemaining);
|
||||||
OT_ASSERT(aEndpoint == &mEndpoint);
|
OT_ASSERT(aEndpoint == &mEndpoint);
|
||||||
|
|
||||||
if (aBytesAvailable > 0)
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls && ContinueTLSHandshake())
|
||||||
{
|
{
|
||||||
const otLinkedBuffer *data;
|
return;
|
||||||
size_t totalReceived = 0;
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
IgnoreError(otTcpReceiveByReference(aEndpoint, &data));
|
if ((mTlsHandshakeComplete || !mUseTls) && aBytesAvailable > 0)
|
||||||
for (; data != nullptr; data = data->mNext)
|
{
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls)
|
||||||
{
|
{
|
||||||
OutputLine("TCP: Received %u bytes: %.*s", static_cast<unsigned>(data->mLength),
|
uint8_t buffer[500];
|
||||||
static_cast<unsigned>(data->mLength), reinterpret_cast<const char *>(data->mData));
|
for (;;)
|
||||||
totalReceived += data->mLength;
|
{
|
||||||
|
int rv = mbedtls_ssl_read(&mSslContext, buffer, sizeof(buffer));
|
||||||
|
if (rv < 0)
|
||||||
|
{
|
||||||
|
if (rv == MBEDTLS_ERR_SSL_WANT_READ)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
OutputLine("TLS receive failure: %d", rv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutputLine("TLS: Received %u bytes: %.*s", static_cast<unsigned>(rv), rv,
|
||||||
|
reinterpret_cast<const char *>(buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OutputLine("(TCP: Received %u bytes)", static_cast<unsigned>(aBytesAvailable));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
{
|
||||||
|
const otLinkedBuffer *data;
|
||||||
|
size_t totalReceived = 0;
|
||||||
|
IgnoreError(otTcpReceiveByReference(aEndpoint, &data));
|
||||||
|
for (; data != nullptr; data = data->mNext)
|
||||||
|
{
|
||||||
|
OutputLine("TCP: Received %u bytes: %.*s", static_cast<unsigned>(data->mLength),
|
||||||
|
static_cast<unsigned>(data->mLength), reinterpret_cast<const char *>(data->mData));
|
||||||
|
totalReceived += data->mLength;
|
||||||
|
}
|
||||||
|
OT_ASSERT(aBytesAvailable == totalReceived);
|
||||||
|
IgnoreReturnValue(otTcpCommitReceive(aEndpoint, totalReceived, 0));
|
||||||
}
|
}
|
||||||
OT_ASSERT(aBytesAvailable == totalReceived);
|
|
||||||
IgnoreReturnValue(otTcpCommitReceive(aEndpoint, totalReceived, 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aEndOfStream)
|
if (aEndOfStream)
|
||||||
@@ -554,6 +745,13 @@ void TcpExample::HandleTcpDisconnected(otTcpEndpoint *aEndpoint, otTcpDisconnect
|
|||||||
|
|
||||||
OutputLine("TCP: %s", Stringify(aReason, kReasonStrings));
|
OutputLine("TCP: %s", Stringify(aReason, kReasonStrings));
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls)
|
||||||
|
{
|
||||||
|
mbedtls_ssl_session_reset(&mSslContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// We set this to false even for the TIME-WAIT state, so that we can reuse
|
// We set this to false even for the TIME-WAIT state, so that we can reuse
|
||||||
// the active socket if an incoming connection comes in instead of waiting
|
// the active socket if an incoming connection comes in instead of waiting
|
||||||
// for the 2MSL timeout.
|
// for the 2MSL timeout.
|
||||||
@@ -599,6 +797,26 @@ void TcpExample::HandleTcpAcceptDone(otTcpListener *aListener, otTcpEndpoint *aE
|
|||||||
mEndpointConnected = true;
|
mEndpointConnected = true;
|
||||||
OutputFormat("Accepted connection from ");
|
OutputFormat("Accepted connection from ");
|
||||||
OutputSockAddrLine(*aPeer);
|
OutputSockAddrLine(*aPeer);
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
if (mUseTls)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = mbedtls_ssl_config_defaults(&mSslConfig, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||||
|
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_ssl_config_defaults returned %d", rv);
|
||||||
|
}
|
||||||
|
mbedtls_ssl_conf_ca_chain(&mSslConfig, mSrvCert.next, nullptr);
|
||||||
|
rv = mbedtls_ssl_conf_own_cert(&mSslConfig, &mSrvCert, &mPKey);
|
||||||
|
if (rv != 0)
|
||||||
|
{
|
||||||
|
OutputLine("mbedtls_ssl_conf_own_cert returned %d", rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
otError TcpExample::ContinueBenchmarkCircularSend(void)
|
otError TcpExample::ContinueBenchmarkCircularSend(void)
|
||||||
@@ -612,10 +830,30 @@ otError TcpExample::ContinueBenchmarkCircularSend(void)
|
|||||||
uint32_t flag = (toSendThisIteration < freeSpace && toSendThisIteration < mBenchmarkBytesUnsent)
|
uint32_t flag = (toSendThisIteration < freeSpace && toSendThisIteration < mBenchmarkBytesUnsent)
|
||||||
? OT_TCP_CIRCULAR_SEND_BUFFER_WRITE_MORE_TO_COME
|
? OT_TCP_CIRCULAR_SEND_BUFFER_WRITE_MORE_TO_COME
|
||||||
: 0;
|
: 0;
|
||||||
size_t written;
|
size_t written = 0;
|
||||||
|
|
||||||
SuccessOrExit(error = otTcpCircularSendBufferWrite(&mEndpoint, &mSendBuffer, sBenchmarkData,
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
toSendThisIteration, &written, flag));
|
if (mUseTls)
|
||||||
|
{
|
||||||
|
int rv = mbedtls_ssl_write(&mSslContext, reinterpret_cast<const unsigned char *>(sBenchmarkData),
|
||||||
|
toSendThisIteration);
|
||||||
|
if (rv > 0)
|
||||||
|
{
|
||||||
|
written = static_cast<size_t>(rv);
|
||||||
|
OT_ASSERT(written <= mBenchmarkBytesUnsent);
|
||||||
|
}
|
||||||
|
else if (rv != MBEDTLS_ERR_SSL_WANT_WRITE && rv != MBEDTLS_ERR_SSL_WANT_READ)
|
||||||
|
{
|
||||||
|
ExitNow(error = kErrorFailed);
|
||||||
|
}
|
||||||
|
error = kErrorNone;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
{
|
||||||
|
SuccessOrExit(error = otTcpCircularSendBufferWrite(&mEndpoint, &mSendBuffer, sBenchmarkData,
|
||||||
|
toSendThisIteration, &written, flag));
|
||||||
|
}
|
||||||
mBenchmarkBytesUnsent -= written;
|
mBenchmarkBytesUnsent -= written;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -642,6 +880,31 @@ void TcpExample::CompleteBenchmark(void)
|
|||||||
mBenchmarkBytesTotal = 0;
|
mBenchmarkBytesTotal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
bool TcpExample::ContinueTLSHandshake(void)
|
||||||
|
{
|
||||||
|
bool wasNotAlreadyDone = false;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
if (!mTlsHandshakeComplete)
|
||||||
|
{
|
||||||
|
rv = mbedtls_ssl_handshake(&mSslContext);
|
||||||
|
if (rv == 0)
|
||||||
|
{
|
||||||
|
OutputLine("TLS Handshake Complete");
|
||||||
|
mTlsHandshakeComplete = true;
|
||||||
|
}
|
||||||
|
else if (rv != MBEDTLS_ERR_SSL_WANT_READ && rv != MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||||
|
{
|
||||||
|
OutputLine("TLS Handshake Failed: %d", rv);
|
||||||
|
}
|
||||||
|
wasNotAlreadyDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wasNotAlreadyDone;
|
||||||
|
}
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
} // namespace Cli
|
} // namespace Cli
|
||||||
} // namespace ot
|
} // namespace ot
|
||||||
|
|
||||||
|
|||||||
+84
-2
@@ -39,6 +39,15 @@
|
|||||||
#include <openthread/tcp.h>
|
#include <openthread/tcp.h>
|
||||||
#include <openthread/tcp_ext.h>
|
#include <openthread/tcp_ext.h>
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
|
#include <mbedtls/ctr_drbg.h>
|
||||||
|
#include <mbedtls/entropy.h>
|
||||||
|
#include <mbedtls/ssl.h>
|
||||||
|
#include <mbedtls/x509_crt.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "cli/cli_config.h"
|
#include "cli/cli_config.h"
|
||||||
#include "cli/cli_output.hpp"
|
#include "cli/cli_output.hpp"
|
||||||
#include "common/time.hpp"
|
#include "common/time.hpp"
|
||||||
@@ -80,6 +89,10 @@ private:
|
|||||||
otError ContinueBenchmarkCircularSend(void);
|
otError ContinueBenchmarkCircularSend(void);
|
||||||
void CompleteBenchmark(void);
|
void CompleteBenchmark(void);
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
bool ContinueTLSHandshake(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
static void HandleTcpEstablishedCallback(otTcpEndpoint *aEndpoint);
|
static void HandleTcpEstablishedCallback(otTcpEndpoint *aEndpoint);
|
||||||
static void HandleTcpSendDoneCallback(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData);
|
static void HandleTcpSendDoneCallback(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData);
|
||||||
static void HandleTcpForwardProgressCallback(otTcpEndpoint *aEndpoint, size_t aInSendBuffer, size_t aBacklog);
|
static void HandleTcpForwardProgressCallback(otTcpEndpoint *aEndpoint, size_t aInSendBuffer, size_t aBacklog);
|
||||||
@@ -108,6 +121,10 @@ private:
|
|||||||
otTcpEndpoint **aAcceptInto);
|
otTcpEndpoint **aAcceptInto);
|
||||||
void HandleTcpAcceptDone(otTcpListener *aListener, otTcpEndpoint *aEndpoint, const otSockAddr *aPeer);
|
void HandleTcpAcceptDone(otTcpListener *aListener, otTcpEndpoint *aEndpoint, const otSockAddr *aPeer);
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
static void MbedTlsDebugOutput(void *ctx, int level, const char *file, int line, const char *str);
|
||||||
|
#endif
|
||||||
|
|
||||||
otTcpEndpoint mEndpoint;
|
otTcpEndpoint mEndpoint;
|
||||||
otTcpListener mListener;
|
otTcpListener mListener;
|
||||||
|
|
||||||
@@ -115,6 +132,8 @@ private:
|
|||||||
bool mEndpointConnected;
|
bool mEndpointConnected;
|
||||||
bool mSendBusy;
|
bool mSendBusy;
|
||||||
bool mUseCircularSendBuffer;
|
bool mUseCircularSendBuffer;
|
||||||
|
bool mUseTls;
|
||||||
|
bool mTlsHandshakeComplete;
|
||||||
|
|
||||||
otTcpCircularSendBuffer mSendBuffer;
|
otTcpCircularSendBuffer mSendBuffer;
|
||||||
otLinkedBuffer mSendLink;
|
otLinkedBuffer mSendLink;
|
||||||
@@ -127,8 +146,71 @@ private:
|
|||||||
uint32_t mBenchmarkBytesUnsent;
|
uint32_t mBenchmarkBytesUnsent;
|
||||||
TimeMilli mBenchmarkStart;
|
TimeMilli mBenchmarkStart;
|
||||||
|
|
||||||
static constexpr const char *sBenchmarkData = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
otTcpEndpointAndCircularSendBuffer mEndpointAndCircularSendBuffer;
|
||||||
static constexpr const size_t sBenchmarkDataLength = 52;
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
mbedtls_ssl_context mSslContext;
|
||||||
|
mbedtls_ssl_config mSslConfig;
|
||||||
|
mbedtls_ctr_drbg_context mCtrDrbg;
|
||||||
|
mbedtls_x509_crt mSrvCert;
|
||||||
|
mbedtls_pk_context mPKey;
|
||||||
|
mbedtls_entropy_context mEntropy;
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
|
static constexpr const char *sBenchmarkData =
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
|
||||||
|
static constexpr const size_t sBenchmarkDataLength = 1040;
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
static constexpr const char *sCasPem = "-----BEGIN CERTIFICATE-----\r\n"
|
||||||
|
"MIIBtDCCATqgAwIBAgIBTTAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJOTDERMA8G\r\n"
|
||||||
|
"A1UEChMIUG9sYXJTU0wxKTAnBgNVBAMTIFBvbGFyU1NMIFRlc3QgSW50ZXJtZWRp\r\n"
|
||||||
|
"YXRlIEVDIENBMB4XDTE1MDkwMTE0MDg0M1oXDTI1MDgyOTE0MDg0M1owSjELMAkG\r\n"
|
||||||
|
"A1UEBhMCVUsxETAPBgNVBAoTCG1iZWQgVExTMSgwJgYDVQQDEx9tYmVkIFRMUyBU\r\n"
|
||||||
|
"ZXN0IGludGVybWVkaWF0ZSBDQSAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\r\n"
|
||||||
|
"732fWHLNPMPsP1U1ibXvb55erlEVMlpXBGsj+KYwVqU1XCmW9Z9hhP7X/5js/DX9\r\n"
|
||||||
|
"2J/utoHyjUtVpQOzdTrbsaMQMA4wDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNo\r\n"
|
||||||
|
"ADBlAjAJRxbGRas3NBmk9MnGWXg7PT1xnRELHRWWIvfLdVQt06l1/xFg3ZuPdQdt\r\n"
|
||||||
|
"Qh7CK80CMQD7wa1o1a8qyDKBfLN636uKmKGga0E+vYXBeFCy9oARBangGCB0B2vt\r\n"
|
||||||
|
"pz590JvGWfM=\r\n"
|
||||||
|
"-----END CERTIFICATE-----\r\n";
|
||||||
|
static constexpr const size_t sCasPemLength = 665; // includes NUL byte
|
||||||
|
|
||||||
|
static constexpr const char *sSrvPem = "-----BEGIN CERTIFICATE-----\r\n"
|
||||||
|
"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n"
|
||||||
|
"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n"
|
||||||
|
"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"
|
||||||
|
"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n"
|
||||||
|
"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n"
|
||||||
|
"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n"
|
||||||
|
"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n"
|
||||||
|
"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n"
|
||||||
|
"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n"
|
||||||
|
"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n"
|
||||||
|
"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n"
|
||||||
|
"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n"
|
||||||
|
"-----END CERTIFICATE-----\r\n";
|
||||||
|
static constexpr const size_t sSrvPemLength = 813; // includes NUL byte
|
||||||
|
|
||||||
|
static constexpr const char *sSrvKey = "-----BEGIN EC PRIVATE KEY-----\r\n"
|
||||||
|
"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n"
|
||||||
|
"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n"
|
||||||
|
"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n"
|
||||||
|
"-----END EC PRIVATE KEY-----\r\n";
|
||||||
|
static constexpr const size_t sSrvKeyLength = 233; // includes NUL byte
|
||||||
|
|
||||||
|
static constexpr const char *sEcjpakePassword = "TLS-over-TCPlp";
|
||||||
|
static constexpr const size_t sEcjpakePasswordLength = 14;
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Cli
|
} // namespace Cli
|
||||||
|
|||||||
@@ -41,6 +41,12 @@
|
|||||||
#include "common/locator_getters.hpp"
|
#include "common/locator_getters.hpp"
|
||||||
#include "net/tcp6_ext.hpp"
|
#include "net/tcp6_ext.hpp"
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
|
#include <mbedtls/ssl.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace ot;
|
using namespace ot;
|
||||||
|
|
||||||
void otTcpCircularSendBufferInitialize(otTcpCircularSendBuffer *aSendBuffer, void *aDataBuffer, size_t aCapacity)
|
void otTcpCircularSendBufferInitialize(otTcpCircularSendBuffer *aSendBuffer, void *aDataBuffer, size_t aCapacity)
|
||||||
@@ -79,4 +85,52 @@ otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer
|
|||||||
return AsCoreType(aSendBuffer).Deinitialize();
|
return AsCoreType(aSendBuffer).Deinitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
|
int otTcpMbedTlsSslSendCallback(void *aCtx, const unsigned char *aBuf, size_t aLen)
|
||||||
|
{
|
||||||
|
otTcpEndpointAndCircularSendBuffer *pair = static_cast<otTcpEndpointAndCircularSendBuffer *>(aCtx);
|
||||||
|
otTcpEndpoint *endpoint = pair->mEndpoint;
|
||||||
|
otTcpCircularSendBuffer *sendBuffer = pair->mSendBuffer;
|
||||||
|
size_t bytes_written;
|
||||||
|
int result;
|
||||||
|
otError error;
|
||||||
|
|
||||||
|
error = otTcpCircularSendBufferWrite(endpoint, sendBuffer, aBuf, aLen, &bytes_written, 0);
|
||||||
|
VerifyOrExit(error == OT_ERROR_NONE, result = MBEDTLS_ERR_SSL_INTERNAL_ERROR);
|
||||||
|
VerifyOrExit(aLen == 0 || bytes_written != 0, result = MBEDTLS_ERR_SSL_WANT_WRITE);
|
||||||
|
result = static_cast<int>(bytes_written);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int otTcpMbedTlsSslRecvCallback(void *aCtx, unsigned char *aBuf, size_t aLen)
|
||||||
|
{
|
||||||
|
otTcpEndpointAndCircularSendBuffer *pair = static_cast<otTcpEndpointAndCircularSendBuffer *>(aCtx);
|
||||||
|
otTcpEndpoint *endpoint = pair->mEndpoint;
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
const otLinkedBuffer *buffer;
|
||||||
|
int result;
|
||||||
|
otError error;
|
||||||
|
|
||||||
|
error = otTcpReceiveByReference(endpoint, &buffer);
|
||||||
|
VerifyOrExit(error == OT_ERROR_NONE, result = MBEDTLS_ERR_SSL_INTERNAL_ERROR);
|
||||||
|
while (bytes_read != aLen && buffer != nullptr)
|
||||||
|
{
|
||||||
|
size_t to_copy = OT_MIN(aLen - bytes_read, buffer->mLength);
|
||||||
|
memcpy(&aBuf[bytes_read], buffer->mData, to_copy);
|
||||||
|
bytes_read += to_copy;
|
||||||
|
buffer = buffer->mNext;
|
||||||
|
}
|
||||||
|
VerifyOrExit(aLen == 0 || bytes_read != 0, result = MBEDTLS_ERR_SSL_WANT_READ);
|
||||||
|
IgnoreReturnValue(otTcpCommitReceive(endpoint, bytes_read, 0));
|
||||||
|
result = static_cast<int>(bytes_read);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
|
||||||
#endif // OPENTHREAD_CONFIG_TCP_ENABLE
|
#endif // OPENTHREAD_CONFIG_TCP_ENABLE
|
||||||
|
|||||||
@@ -172,6 +172,16 @@
|
|||||||
#define OPENTHREAD_CONFIG_TCP_ENABLE 1
|
#define OPENTHREAD_CONFIG_TCP_ENABLE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
|
*
|
||||||
|
* Define as 1 to enable support for TLS over TCP.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if OPENTHREAD_CONFIG_TCP_ENABLE && !defined(OPENTHREAD_CONFIG_TLS_ENABLE)
|
||||||
|
#define OPENTHREAD_CONFIG_TLS_ENABLE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS
|
* @def OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ public:
|
|||||||
size_t GetFreeSize(void) const { return mMemory.mFreeSize; }
|
size_t GetFreeSize(void) const { return mMemory.mFreeSize; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
#if OPENTHREAD_CONFIG_TLS_ENABLE || OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||||
static constexpr uint16_t kMemorySize = OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE;
|
static constexpr uint16_t kMemorySize = OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE;
|
||||||
#else
|
#else
|
||||||
static constexpr uint16_t kMemorySize = OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS;
|
static constexpr uint16_t kMemorySize = OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS;
|
||||||
|
|||||||
@@ -0,0 +1,165 @@
|
|||||||
|
#!/usr/bin/expect -f
|
||||||
|
#
|
||||||
|
# Copyright (c) 2022, The OpenThread Authors.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in the
|
||||||
|
# documentation and/or other materials provided with the distribution.
|
||||||
|
# 3. Neither the name of the copyright holder nor the
|
||||||
|
# names of its contributors may be used to endorse or promote products
|
||||||
|
# derived from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
|
||||||
|
source "tests/scripts/expect/_common.exp"
|
||||||
|
source "tests/scripts/expect/_multinode.exp"
|
||||||
|
|
||||||
|
setup_two_nodes
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
send "tcp init tls\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
send "tcp init tls\n"
|
||||||
|
expect_line "Done"
|
||||||
|
set addr_2 [get_ipaddr mleid]
|
||||||
|
send "tcp listen :: 30000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
send "tcp stoplistening\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
send "tcp connect $addr_2 30000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
expect "TCP: Connection refused"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
send "tcp listen :: 30000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
set addr_1 [get_ipaddr mleid]
|
||||||
|
send "tcp bind $addr_1 25000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
send "tcp connect $addr_2 30000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
expect "TCP: Connection established"
|
||||||
|
expect "TLS Handshake Complete"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
expect "Accepted connection from \\\[$addr_1\\\]:25000"
|
||||||
|
expect "TCP: Connection established"
|
||||||
|
expect "TLS Handshake Complete"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
send "tcp send hello\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
expect "TLS: Received 5 bytes: hello"
|
||||||
|
expect "(TCP: Received 26 bytes)"
|
||||||
|
send "tcp send world\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
expect "TLS: Received 5 bytes: world"
|
||||||
|
expect "(TCP: Received 26 bytes)"
|
||||||
|
send "tcp sendend\n"
|
||||||
|
expect_line "Done"
|
||||||
|
send "tcp send more\n"
|
||||||
|
expect_line "Error 1: Failed"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
expect "TCP: Reached end of stream"
|
||||||
|
send "tcp send goodbye\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
expect "TLS: Received 7 bytes: goodbye"
|
||||||
|
expect "(TCP: Received 28 bytes)"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
send "tcp sendend\n"
|
||||||
|
expect_line "Done"
|
||||||
|
expect "TCP: Disconnected"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
expect "TCP: Reached end of stream"
|
||||||
|
expect "TCP: Entered TIME-WAIT state"
|
||||||
|
set timeout 130
|
||||||
|
expect "TCP: Disconnected"
|
||||||
|
|
||||||
|
# Test second connection with roles reversed (to be sure we're managing TLS state correctly)
|
||||||
|
|
||||||
|
send "tcp listen :: 30000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
send "tcp bind $addr_2 25000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
send "tcp connect $addr_1 30000\n"
|
||||||
|
expect_line "Done"
|
||||||
|
expect "TCP: Connection established"
|
||||||
|
expect "TLS Handshake Complete"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
expect "Accepted connection from \\\[$addr_2\\\]:25000"
|
||||||
|
expect "TCP: Connection established"
|
||||||
|
expect "TLS Handshake Complete"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
send "tcp send hello\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
expect "TLS: Received 5 bytes: hello"
|
||||||
|
expect "(TCP: Received 26 bytes)"
|
||||||
|
send "tcp send world\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
expect "TLS: Received 5 bytes: world"
|
||||||
|
expect "(TCP: Received 26 bytes)"
|
||||||
|
send "tcp sendend\n"
|
||||||
|
expect_line "Done"
|
||||||
|
send "tcp send more\n"
|
||||||
|
expect_line "Error 1: Failed"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
expect "TCP: Reached end of stream"
|
||||||
|
send "tcp send goodbye\n"
|
||||||
|
expect_line "Done"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
expect "TLS: Received 7 bytes: goodbye"
|
||||||
|
expect "(TCP: Received 28 bytes)"
|
||||||
|
|
||||||
|
switch_node 1
|
||||||
|
send "tcp sendend\n"
|
||||||
|
expect_line "Done"
|
||||||
|
expect "TCP: Disconnected"
|
||||||
|
|
||||||
|
switch_node 2
|
||||||
|
expect "TCP: Reached end of stream"
|
||||||
|
expect "TCP: Entered TIME-WAIT state"
|
||||||
|
set timeout 130
|
||||||
|
expect "TCP: Disconnected"
|
||||||
|
|
||||||
|
dispose_all
|
||||||
Vendored
+3
@@ -86,6 +86,9 @@
|
|||||||
|
|
||||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||||
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_TLS_ENABLE
|
||||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user