mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[tcat] initial commit of bluetooth-based commissioning (#9210)
This commit introduces first implementation of Bluetooth based comissioning for thread devices. Co-authored-by: Arnulf Rupp <a.rupp@inventronicsglobal.com> Co-authored-by: Piotr Jasinski <piotr.jasinski@nordicsemi.no>
This commit is contained in:
@@ -172,6 +172,7 @@ ot_option(OT_ASSERT OPENTHREAD_CONFIG_ASSERT_ENABLE "assert function OT_ASSERT()
|
||||
ot_option(OT_BACKBONE_ROUTER OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE "backbone router functionality")
|
||||
ot_option(OT_BACKBONE_ROUTER_DUA_NDPROXYING OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE "BBR DUA ND Proxy")
|
||||
ot_option(OT_BACKBONE_ROUTER_MULTICAST_ROUTING OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE "BBR MR")
|
||||
ot_option(OT_BLE_TCAT OPENTHREAD_CONFIG_BLE_TCAT_ENABLE "Ble based thread commissioning")
|
||||
ot_option(OT_BORDER_AGENT OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE "border agent")
|
||||
ot_option(OT_BORDER_AGENT_ID OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE "create and save border agent ID")
|
||||
ot_option(OT_BORDER_ROUTER OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE "border router")
|
||||
|
||||
@@ -81,6 +81,9 @@ if (openthread_enable_core_config_args) {
|
||||
# Enable backbone router functionality
|
||||
openthread_config_backbone_router_enable = false
|
||||
|
||||
# Enable BLE based commissioning functionality
|
||||
openthread_config_ble_tcat_enable = false
|
||||
|
||||
# Enable border agent support
|
||||
openthread_config_border_agent_enable = false
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ set(OT_PLATFORM_DEFINES ${OT_PLATFORM_DEFINES} PARENT_SCOPE)
|
||||
|
||||
add_library(openthread-simulation
|
||||
alarm.c
|
||||
ble.c
|
||||
crypto.c
|
||||
diag.c
|
||||
dns.c
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
#include <openthread/platform/ble.h>
|
||||
|
||||
otError otPlatBleEnable(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleDisable(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aInterval);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapAdvStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapDisconnect(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGattMtuGet(otInstance *aInstance, uint16_t *aMtu)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aMtu);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, const otBleRadioPacket *aPacket)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aHandle);
|
||||
OT_UNUSED_VARIABLE(aPacket);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -41,6 +41,7 @@ source_set("openthread") {
|
||||
public = [
|
||||
"backbone_router.h",
|
||||
"backbone_router_ftd.h",
|
||||
"ble_secure.h",
|
||||
"border_agent.h",
|
||||
"border_router.h",
|
||||
"border_routing.h",
|
||||
@@ -84,6 +85,7 @@ source_set("openthread") {
|
||||
"ping_sender.h",
|
||||
"platform/alarm-micro.h",
|
||||
"platform/alarm-milli.h",
|
||||
"platform/ble.h",
|
||||
"platform/border_routing.h",
|
||||
"platform/crypto.h",
|
||||
"platform/debug_uart.h",
|
||||
@@ -115,6 +117,7 @@ source_set("openthread") {
|
||||
"srp_client_buffers.h",
|
||||
"srp_server.h",
|
||||
"tasklet.h",
|
||||
"tcat.h",
|
||||
"tcp.h",
|
||||
"tcp_ext.h",
|
||||
"thread.h",
|
||||
|
||||
@@ -0,0 +1,434 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines the top-level functions for the OpenThread BLE Secure implementation.
|
||||
*
|
||||
* @note
|
||||
* The functions in this module require the build-time feature `OPENTHREAD_CONFIG_BLE_TCAT_ENABLE=1`.
|
||||
*
|
||||
* @note
|
||||
* To enable cipher suite DTLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
* must be enabled in mbedtls-config.h
|
||||
* To enable cipher suite DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
|
||||
* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED must be enabled in mbedtls-config.h.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_BLE_SECURE_H_
|
||||
#define OPENTHREAD_BLE_SECURE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <openthread/message.h>
|
||||
#include <openthread/tcat.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-ble-secure
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that control BLE Secure (TLS over BLE) communication.
|
||||
*
|
||||
* The functions in this module are available when BLE Secure API feature
|
||||
* (`OPENTHREAD_CONFIG_BLE_TCAT_ENABLE`) is enabled.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pointer to call when ble secure connection state changes.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aConnected TRUE, if a secure connection was established, FALSE otherwise.
|
||||
* @param[in] aBleConnectionOpen TRUE if a BLE connection was established to carry a TLS data stream, FALSE
|
||||
* otherwise.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
typedef void (*otHandleBleSecureConnect)(otInstance *aInstance,
|
||||
bool aConnected,
|
||||
bool aBleConnectionOpen,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Pointer to call when data was received over a BLE Secure TLS connection.
|
||||
*
|
||||
*/
|
||||
typedef otHandleTcatApplicationDataReceive otHandleBleSecureReceive;
|
||||
|
||||
/**
|
||||
* Starts the BLE Secure service.
|
||||
* When TLV mode is active, the function @p aReceiveHandler will be called once a complete TLV was received and the
|
||||
* message offset points to the TLV value.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aConnectHandler A pointer to a function that will be called when the connection
|
||||
* state changes.
|
||||
* @param[in] aReceiveHandler A pointer to a function that will be called once data has been received
|
||||
* over the TLS connection.
|
||||
* @param[in] aTlvMode A boolean value indicating if line mode shall be activated.
|
||||
* @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the BLE Secure server.
|
||||
* @retval OT_ERROR_ALREADY The service was stated already.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureStart(otInstance *aInstance,
|
||||
otHandleBleSecureConnect aConnectHandler,
|
||||
otHandleBleSecureReceive aReceiveHandler,
|
||||
bool aTlvMode,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Enables the TCAT protocol over BLE Secure.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method call, may be
|
||||
* NULL).
|
||||
* @param[in] aHandler A pointer to a function that is called when the join operation completes.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the BLE Secure Joiner role.
|
||||
* @retval OT_ERROR_INVALID_ARGS @p aElevationPsk or @p aVendorInfo is invalid.
|
||||
* @retval OT_ERROR_INVALID_STATE The BLE function has not been started or line mode is not selected.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureTcatStart(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo, otHandleTcatJoin aHandler);
|
||||
|
||||
/**
|
||||
* Stops the BLE Secure server.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
*/
|
||||
void otBleSecureStop(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Sets the Pre-Shared Key (PSK) and cipher suite
|
||||
* TLS_PSK_WITH_AES_128_CCM_8.
|
||||
*
|
||||
* @note Requires the build-time feature `MBEDTLS_KEY_EXCHANGE_PSK_ENABLED` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPsk A pointer to the PSK.
|
||||
* @param[in] aPskLength The PSK length.
|
||||
* @param[in] aPskIdentity The Identity Name for the PSK.
|
||||
* @param[in] aPskIdLength The PSK Identity Length.
|
||||
*
|
||||
*/
|
||||
void otBleSecureSetPsk(otInstance *aInstance,
|
||||
const uint8_t *aPsk,
|
||||
uint16_t aPskLength,
|
||||
const uint8_t *aPskIdentity,
|
||||
uint16_t aPskIdLength);
|
||||
|
||||
/**
|
||||
* Returns the peer x509 certificate base64 encoded.
|
||||
*
|
||||
* @note Requires the build-time features `MBEDTLS_BASE64_C` and
|
||||
* `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[out] aPeerCert A pointer to the base64 encoded certificate buffer.
|
||||
* @param[in,out] aCertLength On input, the size the max size of @p aPeerCert.
|
||||
* On output, the length of the base64 encoded peer certificate.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully get the peer certificate.
|
||||
* @retval OT_ERROR_INVALID_ARGS @p aInstance or @p aCertLength is invalid.
|
||||
* @retval OT_ERROR_INVALID_STATE Not connected yet.
|
||||
* @retval OT_ERROR_NO_BUFS Can't allocate memory for certificate.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength);
|
||||
|
||||
/**
|
||||
* Returns an attribute value identified by its OID from the subject
|
||||
* of the peer x509 certificate. The peer OID is provided in binary format.
|
||||
* The attribute length is set if the attribute was successfully read or zero
|
||||
* if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard
|
||||
* if the attribute was successfully read.
|
||||
*
|
||||
* @note Requires the build-time feature
|
||||
* `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aOid A pointer to the OID to be found.
|
||||
* @param[in] aOidLength The length of the OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
* @param[out] aAsn1Type A pointer to the ASN.1 type of the attribute written to the buffer.
|
||||
*
|
||||
* @retval OT_ERROR_INVALID_STATE Not connected yet.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid attribute length.
|
||||
* @retval OT_ERROR_NONE Successfully read attribute.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient memory for storing the attribute value.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance,
|
||||
const char *aOid,
|
||||
size_t aOidLength,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength,
|
||||
int *aAsn1Type);
|
||||
|
||||
/**
|
||||
* Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
|
||||
* the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor.
|
||||
* The attribute length is set if the attribute was successfully read or zero if unsuccessful.
|
||||
* Requires a connection to be active.
|
||||
*
|
||||
* @note Requires the build-time feature
|
||||
* `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully read attribute.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid attribute length.
|
||||
* @retval OT_NOT_FOUND The requested attribute was not found.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient memory for storing the attribute value.
|
||||
* @retval OT_ERROR_INVALID_STATE Not connected yet.
|
||||
* @retval OT_ERROR_NOT_IMPLEMENTED The value of aThreadOidDescriptor is >127.
|
||||
* @retval OT_ERROR_PARSE The certificate extensions could not be parsed.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureGetThreadAttributeFromPeerCertificate(otInstance *aInstance,
|
||||
int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength);
|
||||
|
||||
/**
|
||||
* Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
|
||||
* the own x509 certificate, where the last digit x is set to aThreadOidDescriptor.
|
||||
* The attribute length is set if the attribute was successfully read or zero if unsuccessful.
|
||||
* Requires a connection to be active.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully read attribute.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid attribute length.
|
||||
* @retval OT_NOT_FOUND The requested attribute was not found.
|
||||
* @retval OT_ERROR_NO_BUFS Insufficient memory for storing the attribute value.
|
||||
* @retval OT_ERROR_INVALID_STATE Not connected yet.
|
||||
* @retval OT_ERROR_NOT_IMPLEMENTED The value of aThreadOidDescriptor is >127.
|
||||
* @retval OT_ERROR_PARSE The certificate extensions could not be parsed.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureGetThreadAttributeFromOwnCertificate(otInstance *aInstance,
|
||||
int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength);
|
||||
|
||||
/**
|
||||
* Sets the authentication mode for the BLE secure connection.
|
||||
*
|
||||
* Disable or enable the verification of peer certificate.
|
||||
* Must be called before start.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aVerifyPeerCertificate true, to verify the peer certificate.
|
||||
*
|
||||
*/
|
||||
void otBleSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate);
|
||||
|
||||
/**
|
||||
* Sets the local device's X509 certificate with corresponding private key for
|
||||
* TLS session with TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8.
|
||||
*
|
||||
* @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aX509Cert A pointer to the PEM formatted X509 certificate.
|
||||
* @param[in] aX509Length The length of certificate.
|
||||
* @param[in] aPrivateKey A pointer to the PEM formatted private key.
|
||||
* @param[in] aPrivateKeyLength The length of the private key.
|
||||
*
|
||||
*/
|
||||
void otBleSecureSetCertificate(otInstance *aInstance,
|
||||
const uint8_t *aX509Cert,
|
||||
uint32_t aX509Length,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint32_t aPrivateKeyLength);
|
||||
|
||||
/**
|
||||
* Sets the trusted top level CAs. It is needed for validating the
|
||||
* certificate of the peer.
|
||||
*
|
||||
* TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
|
||||
*
|
||||
* @note Requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aX509CaCertificateChain A pointer to the PEM formatted X509 CA chain.
|
||||
* @param[in] aX509CaCertChainLength The length of chain.
|
||||
*
|
||||
*/
|
||||
void otBleSecureSetCaCertificateChain(otInstance *aInstance,
|
||||
const uint8_t *aX509CaCertificateChain,
|
||||
uint32_t aX509CaCertChainLength);
|
||||
|
||||
/**
|
||||
* Initializes TLS session with a peer using an already open BLE connection.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started TLS connection.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureConnect(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Stops the BLE and TLS connection.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
*/
|
||||
void otBleSecureDisconnect(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TLS session is active (connected or conneting).
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval TRUE If TLS session is active.
|
||||
* @retval FALSE If TLS session is not active.
|
||||
*
|
||||
*/
|
||||
bool otBleSecureIsConnectionActive(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TLS session is connected.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval TRUE The TLS session is connected.
|
||||
* @retval FALSE The TLS session is not connected.
|
||||
*
|
||||
*/
|
||||
bool otBleSecureIsConnected(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TCAT agent is enabled.
|
||||
*
|
||||
* @retval TRUE The TCAT agent is enabled.
|
||||
* @retval FALSE The TCAT agent is not enabled.
|
||||
*
|
||||
*/
|
||||
bool otBleSecureIsTcatEnabled(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Indicates whether or not a TCAT command class is authorized.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCommandClass A command class to check.
|
||||
*
|
||||
* @retval TRUE The command class is authorized.
|
||||
* @retval FALSE The command class is not authorized.
|
||||
*
|
||||
*/
|
||||
bool otBleSecureIsCommandClassAuthorized(otInstance *aInstance, otTcatCommandClass aCommandClass);
|
||||
|
||||
/**
|
||||
* Sends a secure BLE message.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aMessage A pointer to the message to send.
|
||||
*
|
||||
* If the return value is OT_ERROR_NONE, OpenThread takes ownership of @p aMessage, and the caller should no longer
|
||||
* reference @p aMessage. If the return value is not OT_ERROR_NONE, the caller retains ownership of @p aMessage,
|
||||
* including freeing @p aMessage if the message buffer is no longer needed.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent message.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate buffer memory.
|
||||
* @retval OT_ERROR_INVALID_STATE TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureSendMessage(otInstance *aInstance, otMessage *aMessage);
|
||||
|
||||
/**
|
||||
* Sends a secure BLE data packet.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aBuf A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
|
||||
* @param[in] aLength A number indicating the length of the data buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent data.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate buffer memory.
|
||||
* @retval OT_ERROR_INVALID_STATE TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureSend(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Sends a secure BLE data packet containing a TCAT Send Application Data TLV.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aBuf A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
|
||||
* @param[in] aLength A number indicating the length of the data buffer.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully sent data.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate buffer memory.
|
||||
* @retval OT_ERROR_INVALID_STATE TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureSendApplicationTlv(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Flushes the send buffer.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully flushed output buffer.
|
||||
* @retval OT_ERROR_NO_BUFS Failed to allocate buffer memory.
|
||||
* @retval OT_ERROR_INVALID_STATE TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
otError otBleSecureFlush(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* OPENTHREAD_BLE_SECURE_H_ */
|
||||
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (380)
|
||||
#define OPENTHREAD_API_VERSION (381)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines a OpenThread BLE GATT peripheral interface driver.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_PLATFORM_BLE_H_
|
||||
#define OPENTHREAD_PLATFORM_BLE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread/error.h>
|
||||
#include <openthread/instance.h>
|
||||
|
||||
/**
|
||||
* @addtogroup plat-ble
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction for BLE Host communication.
|
||||
* The platform needs to implement Bluetooth LE 4.2 or higher.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time slot duration on PHY layer in microseconds (0.625ms).
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_BLE_TIMESLOT_UNIT 625
|
||||
|
||||
/**
|
||||
* Minimum allowed interval for advertising packet in OT_BLE_ADV_INTERVAL_UNIT units (20ms).
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_BLE_ADV_INTERVAL_MIN 0x0020
|
||||
|
||||
/**
|
||||
* Maximum allowed interval for advertising packet in OT_BLE_ADV_INTERVAL_UNIT units (10.24s).
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_BLE_ADV_INTERVAL_MAX 0x4000
|
||||
|
||||
/**
|
||||
* Default interval for advertising packet (ms).
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_BLE_ADV_INTERVAL_DEFAULT 100
|
||||
|
||||
/**
|
||||
* Unit used to calculate interval duration (0.625ms).
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_BLE_ADV_INTERVAL_UNIT OT_BLE_TIMESLOT_UNIT
|
||||
|
||||
/**
|
||||
* Maximum allowed ATT MTU size (must be >= 23).
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_BLE_ATT_MTU_MAX 67
|
||||
|
||||
/**
|
||||
* Default power value for BLE.
|
||||
*/
|
||||
|
||||
#define OT_BLE_DEFAULT_POWER 0
|
||||
|
||||
/**
|
||||
* Represents a BLE packet.
|
||||
*
|
||||
*/
|
||||
typedef struct otBleRadioPacket
|
||||
{
|
||||
uint8_t *mValue; ///< The value of an attribute
|
||||
uint16_t mLength; ///< Length of the @p mValue.
|
||||
int8_t mPower; ///< Transmit/receive power in dBm.
|
||||
} otBleRadioPacket;
|
||||
|
||||
/*******************************************************************************
|
||||
* @section Bluetooth Low Energy management.
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Enable the Bluetooth Low Energy radio.
|
||||
*
|
||||
* @note BLE Device should use the highest ATT_MTU supported that does not
|
||||
* exceed OT_BLE_ATT_MTU_MAX octets.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully enabled.
|
||||
* @retval OT_ERROR_FAILED The BLE radio could not be enabled.
|
||||
*/
|
||||
otError otPlatBleEnable(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Disable the Bluetooth Low Energy radio.
|
||||
*
|
||||
* When disabled, the BLE stack will flush event queues and not generate new
|
||||
* events. The BLE peripheral is turned off or put into a low power sleep
|
||||
* state. Any dynamic memory used by the stack should be released,
|
||||
* but static memory may remain reserved.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully transitioned to disabled.
|
||||
* @retval OT_ERROR_FAILED The BLE radio could not be disabled.
|
||||
*
|
||||
*/
|
||||
otError otPlatBleDisable(otInstance *aInstance);
|
||||
|
||||
/****************************************************************************
|
||||
* @section Bluetooth Low Energy GAP.
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* Starts BLE Advertising procedure.
|
||||
*
|
||||
* The BLE device shall use undirected advertising with no filter applied.
|
||||
* A single BLE Advertising packet must be sent on all advertising
|
||||
* channels (37, 38 and 39).
|
||||
*
|
||||
* @note This function shall be used only for BLE Peripheral role.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aInterval The interval between subsequent advertising packets
|
||||
* in OT_BLE_ADV_INTERVAL_UNIT units.
|
||||
* Shall be within OT_BLE_ADV_INTERVAL_MIN and
|
||||
* OT_BLE_ADV_INTERVAL_MAX range or OT_BLE_ADV_INTERVAL_DEFAULT
|
||||
* for a default value set at compile time.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Advertising procedure has been started.
|
||||
* @retval OT_ERROR_INVALID_STATE BLE Device is in invalid state.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid interval value has been supplied.
|
||||
*
|
||||
*/
|
||||
otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval);
|
||||
|
||||
/**
|
||||
* Stops BLE Advertising procedure.
|
||||
*
|
||||
* @note This function shall be used only for BLE Peripheral role.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Advertising procedure has been stopped.
|
||||
* @retval OT_ERROR_INVALID_STATE BLE Device is in invalid state.
|
||||
*
|
||||
*/
|
||||
otError otPlatBleGapAdvStop(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* The BLE driver calls this method to notify OpenThread that a BLE Central Device has
|
||||
* been connected.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aConnectionId The identifier of the open connection.
|
||||
*
|
||||
*/
|
||||
extern void otPlatBleGapOnConnected(otInstance *aInstance, uint16_t aConnectionId);
|
||||
|
||||
/**
|
||||
* The BLE driver calls this method to notify OpenThread that the BLE Central Device
|
||||
* has been disconnected.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aConnectionId The identifier of the closed connection.
|
||||
*
|
||||
*/
|
||||
extern void otPlatBleGapOnDisconnected(otInstance *aInstance, uint16_t aConnectionId);
|
||||
|
||||
/**
|
||||
* Disconnects BLE connection.
|
||||
*
|
||||
* The BLE device shall use the Remote User Terminated Connection (0x13) reason
|
||||
* code when disconnecting from the peer BLE device..
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Disconnection procedure has been started.
|
||||
* @retval OT_ERROR_INVALID_STATE BLE Device is in invalid state.
|
||||
*
|
||||
*/
|
||||
otError otPlatBleGapDisconnect(otInstance *aInstance);
|
||||
|
||||
/*******************************************************************************
|
||||
* @section Bluetooth Low Energy GATT Common.
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* Reads currently use value of ATT_MTU.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[out] aMtu A pointer to output the current ATT_MTU value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE ATT_MTU value has been placed in @p aMtu.
|
||||
* @retval OT_ERROR_FAILED BLE Device cannot determine its ATT_MTU.
|
||||
*
|
||||
*/
|
||||
otError otPlatBleGattMtuGet(otInstance *aInstance, uint16_t *aMtu);
|
||||
|
||||
/**
|
||||
* The BLE driver calls this method to notify OpenThread that ATT_MTU has been updated.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aMtu The updated ATT_MTU value.
|
||||
*
|
||||
*/
|
||||
extern void otPlatBleGattOnMtuUpdate(otInstance *aInstance, uint16_t aMtu);
|
||||
|
||||
/*******************************************************************************
|
||||
* @section Bluetooth Low Energy GATT Server.
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Sends ATT Handle Value Indication.
|
||||
*
|
||||
* @note This function shall be used only for GATT Server.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aHandle The handle of the attribute to be indicated.
|
||||
* @param[in] aPacket A pointer to the packet contains value to be indicated.
|
||||
*
|
||||
* @retval OT_ERROR_NONE ATT Handle Value Indication has been sent.
|
||||
* @retval OT_ERROR_INVALID_STATE BLE Device is in invalid state.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid handle value, data or data length has been supplied.
|
||||
* @retval OT_ERROR_NO_BUFS No available internal buffer found.
|
||||
*
|
||||
*/
|
||||
otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, const otBleRadioPacket *aPacket);
|
||||
|
||||
/**
|
||||
* The BLE driver calls this method to notify OpenThread that an ATT Write Request
|
||||
* packet has been received.
|
||||
*
|
||||
* @note This function shall be used only for GATT Server.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aHandle The handle of the attribute to be written.
|
||||
* @param[in] aPacket A pointer to the packet contains value to be written to the attribute.
|
||||
*
|
||||
*/
|
||||
extern void otPlatBleGattServerOnWriteRequest(otInstance *aInstance, uint16_t aHandle, const otBleRadioPacket *aPacket);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_PLATFORM_BLE_H_
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines the top-level functions for the OpenThread TCAT.
|
||||
*
|
||||
* @note
|
||||
* The functions in this module require the build-time feature `OPENTHREAD_CONFIG_BLE_TCAT_ENABLE=1`.
|
||||
*
|
||||
* @note
|
||||
* To enable cipher suite DTLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
* must be enabled in mbedtls-config.h
|
||||
* To enable cipher suite DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
|
||||
* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED must be enabled in mbedtls-config.h.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_TCAT_H_
|
||||
#define OPENTHREAD_TCAT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <openthread/message.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-ble-secure
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions that implement TCAT communication.
|
||||
*
|
||||
* The functions in this module are available when TCAT feature
|
||||
* (`OPENTHREAD_CONFIG_BLE_TCAT_ENABLE`) is enabled.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
#define OT_TCAT_MAX_SERVICE_NAME_LENGTH \
|
||||
15 ///< Maximum string length of a UDP or TCP service name (does not include null char).
|
||||
|
||||
/**
|
||||
* Represents TCAT status code.
|
||||
*
|
||||
*/
|
||||
typedef enum otTcatStatusCode
|
||||
{
|
||||
OT_TCAT_STATUS_SUCCESS = 0, ///< Command or request was successfully processed
|
||||
OT_TCAT_STATUS_UNSUPPORTED = 1, ///< Requested command or received TLV is not supported
|
||||
OT_TCAT_STATUS_PARSE_ERROR = 2, ///< Request / command could not be parsed correctly
|
||||
OT_TCAT_STATUS_VALUE_ERROR = 3, ///< The value of the transmitted TLV has an error
|
||||
OT_TCAT_STATUS_GENERAL_ERROR = 4, ///< An error not matching any other category occurred
|
||||
OT_TCAT_STATUS_BUSY = 5, ///< Command cannot be executed because the resource is busy
|
||||
OT_TCAT_STATUS_UNDEFINED = 6, ///< The requested value, data or service is not defined (currently) or not present
|
||||
OT_TCAT_STATUS_HASH_ERROR = 7, ///< The hash value presented by the commissioner was incorrect
|
||||
OT_TCAT_STATUS_UNAUTHORIZED = 16, ///< Sender does not have sufficient authorization for the given command
|
||||
|
||||
} otTcatStatusCode;
|
||||
|
||||
/**
|
||||
* Represents TCAT application protocol.
|
||||
*
|
||||
*/
|
||||
typedef enum otTcatApplicationProtocol
|
||||
{
|
||||
OT_TCAT_APPLICATION_PROTOCOL_NONE = 0, ///< Message which has been sent without activating the TCAT agent
|
||||
OT_TCAT_APPLICATION_PROTOCOL_STATUS = 1, ///< Message directed to a UDP service
|
||||
OT_TCAT_APPLICATION_PROTOCOL_TCP = 2, ///< Message directed to a TCP service
|
||||
|
||||
} otTcatApplicationProtocol;
|
||||
|
||||
/**
|
||||
* Represents a TCAT command class.
|
||||
*
|
||||
*/
|
||||
typedef enum otTcatCommandClass
|
||||
{
|
||||
OT_TCAT_COMMAND_CLASS_GENERAL = 0, ///< TCAT commands related to general operations
|
||||
OT_TCAT_COMMAND_CLASS_COMMISSIONING = 1, ///< TCAT commands related to commissioning
|
||||
OT_TCAT_COMMAND_CLASS_EXTRACTION = 2, ///< TCAT commands related to key extraction
|
||||
OT_TCAT_COMMAND_CLASS_DECOMMISSIONING = 3, ///< TCAT commands related to de-commissioning
|
||||
OT_TCAT_COMMAND_CLASS_APPLICATION = 4, ///< TCAT commands related to application layer
|
||||
|
||||
} otTcatCommandClass;
|
||||
|
||||
/**
|
||||
* This structure represents a TCAT vendor information.
|
||||
*
|
||||
* The content of this structure MUST persist and remain unchanged while a TCAT session is running.
|
||||
*
|
||||
*/
|
||||
typedef struct otTcatVendorInfo
|
||||
{
|
||||
const char *mProvisioningUrl; ///< Provisioning URL path string
|
||||
const char *mVendorName; ///< Vendor name string
|
||||
const char *mVendorModel; ///< Vendor model string
|
||||
const char *mVendorSwVersion; ///< Vendor software version string
|
||||
const char *mVendorData; ///< Vendor specific data string
|
||||
const char *mPskdString; ///< Vendor managed pre-shared key for device
|
||||
const char *mInstallCode; ///< Vendor managed install code string
|
||||
const char *mDeviceId; ///< Vendor managed device ID string (if NULL: device ID is set to EUI-64 in binary format)
|
||||
|
||||
} otTcatVendorInfo;
|
||||
|
||||
/**
|
||||
* Pointer to call when application data was received over a TCAT TLS connection.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aMessage A pointer to the message.
|
||||
* @param[in] aOffset The offset where the application data begins.
|
||||
* @param[in] aTcatApplicationProtocol The protocol type of the message received.
|
||||
* @param[in] aServiceName The name of the service the message is direced to.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
typedef void (*otHandleTcatApplicationDataReceive)(otInstance *aInstance,
|
||||
const otMessage *aMessage,
|
||||
int32_t aOffset,
|
||||
otTcatApplicationProtocol aTcatApplicationProtocol,
|
||||
const char *aServiceName,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Pointer to call to notify the completion of a join operation.
|
||||
*
|
||||
* @param[in] aError OT_ERROR_NONE if the join process succeeded.
|
||||
* OT_ERROR_SECURITY if the join process failed due to security credentials.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
typedef void (*otHandleTcatJoin)(otError aError, void *aContext);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* OPENTHREAD_TCAT_H_ */
|
||||
@@ -201,6 +201,9 @@ build_all_features()
|
||||
# Build with RAM settings
|
||||
reset_source
|
||||
"$(dirname "$0")"/cmake-build simulation -DOT_SETTINGS_RAM=ON
|
||||
|
||||
reset_source
|
||||
"$(dirname "$0")"/cmake-build simulation -DOT_BLE_TCAT=ON
|
||||
}
|
||||
|
||||
build_nest_common()
|
||||
|
||||
@@ -48,6 +48,7 @@ set(COMMON_SOURCES
|
||||
cli_output.cpp
|
||||
cli_srp_client.cpp
|
||||
cli_srp_server.cpp
|
||||
cli_tcat.cpp
|
||||
cli_tcp.cpp
|
||||
cli_udp.cpp
|
||||
)
|
||||
|
||||
@@ -117,6 +117,7 @@ Done
|
||||
- [sntp](#sntp-query-sntp-server-ip-sntp-server-port)
|
||||
- [state](#state)
|
||||
- [srp](README_SRP.md)
|
||||
- [tcat](README_TCAT.md)
|
||||
- [tcp](README_TCP.md)
|
||||
- [thread](#thread-start)
|
||||
- [timeinqueue](#timeinqueue)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# OpenThread CLI - TCAT Example
|
||||
|
||||
## Command List
|
||||
|
||||
- help [#help]
|
||||
- start [#start]
|
||||
- stop [#stop]
|
||||
|
||||
### help
|
||||
|
||||
print help
|
||||
|
||||
```bash
|
||||
tcat help
|
||||
help
|
||||
start
|
||||
stop
|
||||
Done
|
||||
```
|
||||
|
||||
### start
|
||||
|
||||
Start tcat server and ble advertisement.
|
||||
|
||||
```bash
|
||||
tcat start
|
||||
Done
|
||||
```
|
||||
|
||||
### stop
|
||||
|
||||
Stop tcat server and ble advertisement.
|
||||
|
||||
```bash
|
||||
tcat stop
|
||||
Done
|
||||
```
|
||||
@@ -148,6 +148,9 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
|
||||
, mLinkMetrics(aInstance, *this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
, mTcat(aInstance, *this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
|
||||
, mLocateInProgress(false)
|
||||
#endif
|
||||
@@ -7240,6 +7243,10 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
template <> otError Interpreter::Process<Cmd("tcat")>(Arg aArgs[]) { return mTcat.Process(aArgs); }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
|
||||
template <> otError Interpreter::Process<Cmd("tcp")>(Arg aArgs[]) { return mTcp.Process(aArgs); }
|
||||
#endif
|
||||
@@ -8509,6 +8516,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
|
||||
CmdEntry("srp"),
|
||||
#endif
|
||||
CmdEntry("state"),
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
CmdEntry("tcat"),
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_TCP_ENABLE && OPENTHREAD_CONFIG_CLI_TCP_ENABLE
|
||||
CmdEntry("tcp"),
|
||||
#endif
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include "cli/cli_output.hpp"
|
||||
#include "cli/cli_srp_client.hpp"
|
||||
#include "cli/cli_srp_server.hpp"
|
||||
#include "cli/cli_tcat.hpp"
|
||||
#include "cli/cli_tcp.hpp"
|
||||
#include "cli/cli_udp.hpp"
|
||||
#if OPENTHREAD_CONFIG_COAP_API_ENABLE
|
||||
@@ -594,6 +595,9 @@ private:
|
||||
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
|
||||
LinkMetrics mLinkMetrics;
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
Tcat mTcat;
|
||||
#endif
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
|
||||
@@ -58,6 +58,16 @@
|
||||
#define OPENTHREAD_CONFIG_CLI_MAX_LINE_LENGTH 384
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
*
|
||||
* Indicates whether TCAT should be enabled in the CLI tool.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
#define OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_CLI_TCP_ENABLE
|
||||
*
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "cli/cli_output.hpp"
|
||||
|
||||
#include "cli/cli_tcat.hpp"
|
||||
|
||||
#include <openthread/ble_secure.h>
|
||||
|
||||
#include <mbedtls/oid.h>
|
||||
#include <openthread/tcat.h>
|
||||
#include <openthread/platform/ble.h>
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
|
||||
#define OT_CLI_TCAT_X509_CERT \
|
||||
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||
"MIIBmDCCAT+gAwIBAgIEAQIDBDAKBggqhkjOPQQDAjBvMQswCQYDVQQGEwJYWDEQ\r\n" \
|
||||
"MA4GA1UECBMHTXlTdGF0ZTEPMA0GA1UEBxMGTXlDaXR5MQ8wDQYDVQQLEwZNeVVu\r\n" \
|
||||
"aXQxETAPBgNVBAoTCE15VmVuZG9yMRkwFwYDVQQDExB3d3cubXl2ZW5kb3IuY29t\r\n" \
|
||||
"MB4XDTIzMTAxNjEwMzk1NFoXDTI0MTAxNjEwMzk1NFowIjEgMB4GA1UEAxMXbXl2\r\n" \
|
||||
"ZW5kb3IuY29tL3RjYXQvbXlkZXYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB\r\n" \
|
||||
"aWwFDNj1bpQIdN+Kp2cHWw55U/+fa+OmZnoy1B4BOT+822jdwPBuyXWAQoBdYdQJ\r\n" \
|
||||
"ff4RgmhczyV4PhArPIuAoxYwFDASBgkrBgEEAYLfKgMEBQABAQEBMAoGCCqGSM49\r\n" \
|
||||
"BAMCA0cAMEQCIBEHxiEDij26y6V77Q311Gj4CZAuZuPGXZpnzL2BLk7bAiAlFk6G\r\n" \
|
||||
"mYGzkcrYyssFI9HlPgrisWoMmgummaTtCuvrEw==\r\n" \
|
||||
"-----END CERTIFICATE-----\r\n"
|
||||
|
||||
#define OT_CLI_TCAT_PRIV_KEY \
|
||||
"-----BEGIN EC PRIVATE KEY-----\r\n" \
|
||||
"MHcCAQEEIDeJ6lVQKiOIBxKwTZp6TkU5QVHt9pvXOR9CGpPBI3DhoAoGCCqGSM49\r\n" \
|
||||
"AwEHoUQDQgAEAWlsBQzY9W6UCHTfiqdnB1sOeVP/n2vjpmZ6MtQeATk/vNto3cDw\r\n" \
|
||||
"bsl1gEKAXWHUCX3+EYJoXM8leD4QKzyLgA==\r\n" \
|
||||
"-----END EC PRIVATE KEY-----\r\n"
|
||||
|
||||
#define OT_CLI_TCAT_TRUSTED_ROOT_CERTIFICATE \
|
||||
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||
"MIICCDCCAa2gAwIBAgIJAIKxygBXoH+5MAoGCCqGSM49BAMCMG8xCzAJBgNVBAYT\r\n" \
|
||||
"AlhYMRAwDgYDVQQIEwdNeVN0YXRlMQ8wDQYDVQQHEwZNeUNpdHkxDzANBgNVBAsT\r\n" \
|
||||
"Bk15VW5pdDERMA8GA1UEChMITXlWZW5kb3IxGTAXBgNVBAMTEHd3dy5teXZlbmRv\r\n" \
|
||||
"ci5jb20wHhcNMjMxMDE2MTAzMzE1WhcNMjYxMDE2MTAzMzE1WjBvMQswCQYDVQQG\r\n" \
|
||||
"EwJYWDEQMA4GA1UECBMHTXlTdGF0ZTEPMA0GA1UEBxMGTXlDaXR5MQ8wDQYDVQQL\r\n" \
|
||||
"EwZNeVVuaXQxETAPBgNVBAoTCE15VmVuZG9yMRkwFwYDVQQDExB3d3cubXl2ZW5k\r\n" \
|
||||
"b3IuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWdyzPAXGKeZY94OhHAWX\r\n" \
|
||||
"HzJfQIjGSyaOzlgL9OEFw2SoUDncLKPGwfPAUSfuMyEkzszNDM0HHkBsDLqu4n25\r\n" \
|
||||
"/6MyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU4EynoSw9eDKZEVPkums2\r\n" \
|
||||
"IWLAJCowCgYIKoZIzj0EAwIDSQAwRgIhAMYGGL9xShyE6P9wEU+MAYF6W3CzdrwV\r\n" \
|
||||
"kuerX1encIH2AiEA5rq490NUobM1Au43roxJq1T6Z43LscPVbGZfULD1Jq0=\r\n" \
|
||||
"-----END CERTIFICATE-----\r\n"
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Cli {
|
||||
|
||||
otTcatVendorInfo sVendorInfo;
|
||||
const char kPskdVendor[] = "J01NM3";
|
||||
const char kUrl[] = "dummy_url";
|
||||
|
||||
static void HandleBleSecureReceive(otInstance *aInstance,
|
||||
const otMessage *aMessage,
|
||||
int32_t aOffset,
|
||||
otTcatApplicationProtocol aTcatApplicationProtocol,
|
||||
const char *aServiceName,
|
||||
void *aContext)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aContext);
|
||||
OT_UNUSED_VARIABLE(aTcatApplicationProtocol);
|
||||
OT_UNUSED_VARIABLE(aServiceName);
|
||||
static constexpr int kTextMaxLen = 100;
|
||||
static constexpr uint8_t kBufPrefixLen = 5;
|
||||
uint16_t nLen;
|
||||
uint8_t buf[kTextMaxLen];
|
||||
|
||||
nLen = otMessageRead(aMessage, (uint16_t)aOffset, buf + kBufPrefixLen, sizeof(buf) - kBufPrefixLen - 1);
|
||||
|
||||
memcpy(buf, "RECV:", kBufPrefixLen);
|
||||
|
||||
buf[nLen + kBufPrefixLen] = 0;
|
||||
|
||||
IgnoreReturnValue(otBleSecureSendApplicationTlv(aInstance, buf, (uint16_t)strlen((char *)buf)));
|
||||
IgnoreReturnValue(otBleSecureFlush(aInstance));
|
||||
}
|
||||
|
||||
template <> otError Tcat::Process<Cmd("start")>(Arg aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aArgs);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
sVendorInfo.mPskdString = kPskdVendor;
|
||||
sVendorInfo.mProvisioningUrl = kUrl;
|
||||
|
||||
otBleSecureSetCertificate(GetInstancePtr(), reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_X509_CERT),
|
||||
sizeof(OT_CLI_TCAT_X509_CERT), reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_PRIV_KEY),
|
||||
sizeof(OT_CLI_TCAT_PRIV_KEY));
|
||||
|
||||
otBleSecureSetCaCertificateChain(GetInstancePtr(),
|
||||
reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_TRUSTED_ROOT_CERTIFICATE),
|
||||
sizeof(OT_CLI_TCAT_TRUSTED_ROOT_CERTIFICATE));
|
||||
|
||||
otBleSecureSetSslAuthMode(GetInstancePtr(), true);
|
||||
|
||||
SuccessOrExit(error = otBleSecureStart(GetInstancePtr(), nullptr, HandleBleSecureReceive, true, nullptr));
|
||||
SuccessOrExit(error = otBleSecureTcatStart(GetInstancePtr(), &sVendorInfo, nullptr));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
template <> otError Tcat::Process<Cmd("stop")>(Arg aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aArgs);
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otBleSecureStop(GetInstancePtr());
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Tcat::Process(Arg aArgs[])
|
||||
{
|
||||
#define CmdEntry(aCommandString) \
|
||||
{ \
|
||||
aCommandString, &Tcat::Process<Cmd(aCommandString)> \
|
||||
}
|
||||
|
||||
static constexpr Command kCommands[] = {CmdEntry("start"), CmdEntry("stop")};
|
||||
|
||||
static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
const Command *command;
|
||||
|
||||
if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
|
||||
{
|
||||
OutputCommandTable(kCommands);
|
||||
ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
|
||||
VerifyOrExit(command != nullptr);
|
||||
|
||||
error = (this->*command->mHandler)(aArgs + 1);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace ot
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
#ifndef CLI_TCAT_HPP_
|
||||
#define CLI_TCAT_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "cli/cli_output.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Cli {
|
||||
|
||||
/**
|
||||
* Implements the Tcat CLI interpreter.
|
||||
*
|
||||
*/
|
||||
class Tcat : private Output
|
||||
{
|
||||
public:
|
||||
typedef Utils::CmdLineParser::Arg Arg;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param[in] aInstance The OpenThread Instance.
|
||||
* @param[in] aOutputImplementer An `OutputImplementer`.
|
||||
*
|
||||
*/
|
||||
Tcat(otInstance *aInstance, OutputImplementer &aOutputImplementer)
|
||||
: Output(aInstance, aOutputImplementer)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a CLI sub-command.
|
||||
*
|
||||
* @param[in] aArgs An array of command line arguments.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully executed the CLI command.
|
||||
* @retval OT_ERROR_PENDING The CLI command was successfully started but final result is pending.
|
||||
* @retval OT_ERROR_INVALID_COMMAND Invalid or unknown CLI command.
|
||||
* @retval OT_ERROR_INVALID_ARGS Invalid arguments.
|
||||
* @retval ... Error during execution of the CLI command.
|
||||
*
|
||||
*/
|
||||
otError Process(Arg aArgs[]);
|
||||
|
||||
private:
|
||||
using Command = CommandEntry<Tcat>;
|
||||
|
||||
template <CommandId kCommandId> otError Process(Arg aArgs[]);
|
||||
};
|
||||
|
||||
} // namespace Cli
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
|
||||
|
||||
#endif // CLI_TCAT_HPP_
|
||||
+12
-3
@@ -74,6 +74,10 @@ if (openthread_enable_core_config_args) {
|
||||
defines += [ "OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE=1" ]
|
||||
}
|
||||
|
||||
if (openthread_config_ble_tcat_enable) {
|
||||
defines += [ "OPENTHREAD_CONFIG_BLE_TCAT_ENABLE=1" ]
|
||||
}
|
||||
|
||||
if (openthread_config_border_agent_enable) {
|
||||
defines += [ "OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE=1" ]
|
||||
}
|
||||
@@ -301,6 +305,7 @@ config("core_config") {
|
||||
openthread_core_files = [
|
||||
"api/backbone_router_api.cpp",
|
||||
"api/backbone_router_ftd_api.cpp",
|
||||
"api/ble_secure_api.cpp",
|
||||
"api/border_agent_api.cpp",
|
||||
"api/border_router_api.cpp",
|
||||
"api/border_routing_api.cpp",
|
||||
@@ -510,8 +515,6 @@ openthread_core_files = [
|
||||
"meshcop/dataset_manager_ftd.cpp",
|
||||
"meshcop/dataset_updater.cpp",
|
||||
"meshcop/dataset_updater.hpp",
|
||||
"meshcop/dtls.cpp",
|
||||
"meshcop/dtls.hpp",
|
||||
"meshcop/energy_scan_client.cpp",
|
||||
"meshcop/energy_scan_client.hpp",
|
||||
"meshcop/extended_panid.cpp",
|
||||
@@ -530,6 +533,10 @@ openthread_core_files = [
|
||||
"meshcop/network_name.hpp",
|
||||
"meshcop/panid_query_client.cpp",
|
||||
"meshcop/panid_query_client.hpp",
|
||||
"meshcop/secure_transport.cpp",
|
||||
"meshcop/secure_transport.hpp",
|
||||
"meshcop/tcat_agent.cpp",
|
||||
"meshcop/tcat_agent.hpp",
|
||||
"meshcop/timestamp.cpp",
|
||||
"meshcop/timestamp.hpp",
|
||||
"net/checksum.cpp",
|
||||
@@ -585,6 +592,8 @@ openthread_core_files = [
|
||||
"net/tcp6_ext.hpp",
|
||||
"net/udp6.cpp",
|
||||
"net/udp6.hpp",
|
||||
"radio/ble_secure.cpp",
|
||||
"radio/ble_secure.hpp",
|
||||
"radio/max_power_table.hpp",
|
||||
"radio/radio.cpp",
|
||||
"radio/radio.hpp",
|
||||
@@ -789,7 +798,6 @@ source_set("libopenthread_core_config") {
|
||||
"config/dns_client.h",
|
||||
"config/dns_dso.h",
|
||||
"config/dnssd_server.h",
|
||||
"config/dtls.h",
|
||||
"config/history_tracker.h",
|
||||
"config/ip6.h",
|
||||
"config/joiner.h",
|
||||
@@ -811,6 +819,7 @@ source_set("libopenthread_core_config") {
|
||||
"config/platform.h",
|
||||
"config/power_calibration.h",
|
||||
"config/radio_link.h",
|
||||
"config/secure_transport.h",
|
||||
"config/sntp_client.h",
|
||||
"config/srp_client.h",
|
||||
"config/srp_server.h",
|
||||
|
||||
@@ -33,6 +33,7 @@ set(COMMON_INCLUDES
|
||||
set(COMMON_SOURCES
|
||||
api/backbone_router_api.cpp
|
||||
api/backbone_router_ftd_api.cpp
|
||||
api/ble_secure_api.cpp
|
||||
api/border_agent_api.cpp
|
||||
api/border_router_api.cpp
|
||||
api/border_routing_api.cpp
|
||||
@@ -148,7 +149,6 @@ set(COMMON_SOURCES
|
||||
meshcop/dataset_manager.cpp
|
||||
meshcop/dataset_manager_ftd.cpp
|
||||
meshcop/dataset_updater.cpp
|
||||
meshcop/dtls.cpp
|
||||
meshcop/energy_scan_client.cpp
|
||||
meshcop/extended_panid.cpp
|
||||
meshcop/joiner.cpp
|
||||
@@ -158,6 +158,8 @@ set(COMMON_SOURCES
|
||||
meshcop/meshcop_tlvs.cpp
|
||||
meshcop/network_name.cpp
|
||||
meshcop/panid_query_client.cpp
|
||||
meshcop/secure_transport.cpp
|
||||
meshcop/tcat_agent.cpp
|
||||
meshcop/timestamp.cpp
|
||||
net/checksum.cpp
|
||||
net/dhcp6_client.cpp
|
||||
@@ -185,6 +187,7 @@ set(COMMON_SOURCES
|
||||
net/tcp6.cpp
|
||||
net/tcp6_ext.cpp
|
||||
net/udp6.cpp
|
||||
radio/ble_secure.cpp
|
||||
radio/radio.cpp
|
||||
radio/radio_callbacks.cpp
|
||||
radio/radio_platform.cpp
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the OpenThread BLE Secure API.
|
||||
*/
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#include <openthread/ble_secure.h>
|
||||
#include <openthread/platform/ble.h>
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/locator_getters.hpp"
|
||||
#include "meshcop/tcat_agent.hpp"
|
||||
#include "radio/ble_secure.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
otError otBleSecureStart(otInstance *aInstance,
|
||||
otHandleBleSecureConnect aConnectHandler,
|
||||
otHandleBleSecureReceive aReceiveHandler,
|
||||
bool aTlvMode,
|
||||
void *aContext)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().Start(aConnectHandler, aReceiveHandler, aTlvMode, aContext);
|
||||
}
|
||||
|
||||
otError otBleSecureTcatStart(otInstance *aInstance, const otTcatVendorInfo *aVendorInfo, otHandleTcatJoin aHandler)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().TcatStart(AsCoreType(aVendorInfo), aHandler);
|
||||
}
|
||||
|
||||
void otBleSecureStop(otInstance *aInstance) { AsCoreType(aInstance).Get<Ble::BleSecure>().Stop(); }
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
void otBleSecureSetPsk(otInstance *aInstance,
|
||||
const uint8_t *aPsk,
|
||||
uint16_t aPskLength,
|
||||
const uint8_t *aPskIdentity,
|
||||
uint16_t aPskIdLength)
|
||||
{
|
||||
AssertPointerIsNotNull(aPsk);
|
||||
AssertPointerIsNotNull(aPskIdentity);
|
||||
OT_ASSERT(aPskLength != 0 && aPskIdLength != 0);
|
||||
|
||||
AsCoreType(aInstance).Get<Ble::BleSecure>().SetPreSharedKey(aPsk, aPskLength, aPskIdentity, aPskIdLength);
|
||||
}
|
||||
#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().GetPeerCertificateBase64(aPeerCert, aCertLength);
|
||||
}
|
||||
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance,
|
||||
const char *aOid,
|
||||
size_t aOidLength,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength,
|
||||
int *aAsn1Type)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().GetPeerSubjectAttributeByOid(aOid, aOidLength, aAttributeBuffer,
|
||||
aAttributeLength, aAsn1Type);
|
||||
}
|
||||
|
||||
otError otBleSecureGetThreadAttributeFromPeerCertificate(otInstance *aInstance,
|
||||
int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().GetThreadAttributeFromPeerCertificate(
|
||||
aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
|
||||
}
|
||||
#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
otError otBleSecureGetThreadAttributeFromOwnCertificate(otInstance *aInstance,
|
||||
int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().GetThreadAttributeFromOwnCertificate(
|
||||
aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
|
||||
}
|
||||
|
||||
void otBleSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate)
|
||||
{
|
||||
AsCoreType(aInstance).Get<Ble::BleSecure>().SetSslAuthMode(aVerifyPeerCertificate);
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
void otBleSecureSetCertificate(otInstance *aInstance,
|
||||
const uint8_t *aX509Cert,
|
||||
uint32_t aX509Length,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint32_t aPrivateKeyLength)
|
||||
{
|
||||
OT_ASSERT(aX509Cert != nullptr && aX509Length != 0 && aPrivateKey != nullptr && aPrivateKeyLength != 0);
|
||||
|
||||
AsCoreType(aInstance).Get<Ble::BleSecure>().SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength);
|
||||
}
|
||||
|
||||
void otBleSecureSetCaCertificateChain(otInstance *aInstance,
|
||||
const uint8_t *aX509CaCertificateChain,
|
||||
uint32_t aX509CaCertChainLength)
|
||||
{
|
||||
OT_ASSERT(aX509CaCertificateChain != nullptr && aX509CaCertChainLength != 0);
|
||||
|
||||
AsCoreType(aInstance).Get<Ble::BleSecure>().SetCaCertificateChain(aX509CaCertificateChain, aX509CaCertChainLength);
|
||||
}
|
||||
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
|
||||
otError otBleSecureConnect(otInstance *aInstance) { return AsCoreType(aInstance).Get<Ble::BleSecure>().Connect(); }
|
||||
|
||||
void otBleSecureDisconnect(otInstance *aInstance) { AsCoreType(aInstance).Get<Ble::BleSecure>().Disconnect(); }
|
||||
|
||||
bool otBleSecureIsConnectionActive(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().IsConnectionActive();
|
||||
}
|
||||
|
||||
bool otBleSecureIsConnected(otInstance *aInstance) { return AsCoreType(aInstance).Get<Ble::BleSecure>().IsConnected(); }
|
||||
|
||||
bool otBleSecureIsTcatEnabled(otInstance *aInstance)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().IsTcatEnabled();
|
||||
}
|
||||
|
||||
bool otBleSecureIsCommandClassAuthorized(otInstance *aInstance, otTcatCommandClass aCommandClass)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().IsCommandClassAuthorized(
|
||||
static_cast<Ble::BleSecure::CommandClass>(aCommandClass));
|
||||
}
|
||||
|
||||
otError otBleSecureSendMessage(otInstance *aInstance, otMessage *aMessage)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().SendMessage(AsCoreType(aMessage));
|
||||
}
|
||||
|
||||
otError otBleSecureSend(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().Send(aBuf, aLength);
|
||||
}
|
||||
|
||||
otError otBleSecureSendApplicationTlv(otInstance *aInstance, uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Ble::BleSecure>().SendApplicationTlv(aBuf, aLength);
|
||||
}
|
||||
|
||||
otError otBleSecureFlush(otInstance *aInstance) { return AsCoreType(aInstance).Get<Ble::BleSecure>().Flush(); }
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
@@ -28,13 +28,14 @@
|
||||
|
||||
#include "coap_secure.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
#include "common/locator_getters.hpp"
|
||||
#include "common/log.hpp"
|
||||
#include "common/new.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
#include "meshcop/dtls.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
|
||||
#include "thread/thread_netif.hpp"
|
||||
|
||||
/**
|
||||
@@ -67,7 +68,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error CoapSecure::Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext)
|
||||
Error CoapSecure::Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -98,7 +99,7 @@ Error CoapSecure::Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aCal
|
||||
void CoapSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd)
|
||||
{
|
||||
static_assert(static_cast<uint16_t>(MeshCoP::JoinerPskd::kMaxLength) <=
|
||||
static_cast<uint16_t>(MeshCoP::Dtls::kPskMaxLength),
|
||||
static_cast<uint16_t>(MeshCoP::SecureTransport::kPskMaxLength),
|
||||
"The maximum length of DTLS PSK is smaller than joiner PSKd");
|
||||
|
||||
SuccessOrAssert(mDtls.SetPsk(reinterpret_cast<const uint8_t *>(aPskd.GetAsCString()), aPskd.GetLength()));
|
||||
@@ -224,4 +225,4 @@ exit:
|
||||
} // namespace Coap
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
#include "common/callback.hpp"
|
||||
#include "meshcop/dtls.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
|
||||
#include <openthread/coap_secure.h>
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
* @retval kErrorAlready Already started.
|
||||
*
|
||||
*/
|
||||
Error Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext);
|
||||
Error Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* Sets connected callback of this secure CoAP agent.
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
* @returns A reference to the DTLS object.
|
||||
*
|
||||
*/
|
||||
MeshCoP::Dtls &GetDtls(void) { return mDtls; }
|
||||
MeshCoP::SecureTransport &GetDtls(void) { return mDtls; }
|
||||
|
||||
/**
|
||||
* Gets the UDP port of this agent.
|
||||
@@ -409,7 +409,7 @@ private:
|
||||
static void HandleTransmit(Tasklet &aTasklet);
|
||||
void HandleTransmit(void);
|
||||
|
||||
MeshCoP::Dtls mDtls;
|
||||
MeshCoP::SecureTransport mDtls;
|
||||
Callback<ConnectedCallback> mConnectedCallback;
|
||||
ot::MessageQueue mTransmitQueue;
|
||||
TaskletContext mTransmitTask;
|
||||
@@ -418,6 +418,6 @@ private:
|
||||
} // namespace Coap
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
#endif // COAP_SECURE_HPP_
|
||||
|
||||
@@ -286,7 +286,8 @@ public:
|
||||
kTypeSupervision = 2, ///< A child supervision frame.
|
||||
kTypeMacEmptyData = 3, ///< An empty MAC data frame.
|
||||
kTypeIp4 = 4, ///< A full uncompressed IPv4 packet, for NAT64.
|
||||
kTypeOther = 5, ///< Other (data) message.
|
||||
kTypeBle = 5, ///< A BLE payload message.
|
||||
kTypeOther = 6, ///< Other (data) message.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -178,8 +178,8 @@
|
||||
* Define as 1 to enable support for TLS over TCP.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_TLS_ENABLE
|
||||
#define OPENTHREAD_CONFIG_TLS_ENABLE OPENTHREAD_CONFIG_TCP_ENABLE
|
||||
#if (OPENTHREAD_CONFIG_TCP_ENABLE || OPENTHREAD_CONFIG_BLE_TCAT_ENABLE) && !defined(OPENTHREAD_CONFIG_TLS_ENABLE)
|
||||
#define OPENTHREAD_CONFIG_TLS_ENABLE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef OPENTHREAD_ENABLE_DTLS
|
||||
#error "OPENTHREAD_ENABLE_DTLS was replaced by OPENTHREAD_CONFIG_DTLS_ENABLE."
|
||||
#error "OPENTHREAD_ENABLE_DTLS was replaced by OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE."
|
||||
#endif
|
||||
|
||||
#ifdef OPENTHREAD_ENABLE_JAM_DETECTION
|
||||
|
||||
@@ -28,12 +28,12 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes compile-time configurations for DTLS.
|
||||
* This file includes compile-time configurations for TLS/DTLS.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_DTLS_H_
|
||||
#define CONFIG_DTLS_H_
|
||||
#ifndef CONFIG_SECURE_TRANSPORT_H_
|
||||
#define CONFIG_SECURE_TRANSPORT_H_
|
||||
|
||||
#include "config/border_agent.h"
|
||||
#include "config/coap.h"
|
||||
@@ -51,15 +51,19 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
* @def OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
*
|
||||
* Define to 1 to enable DTLS.
|
||||
* Define to 1 to enable DTLS/TLS.
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#define OPENTHREAD_CONFIG_DTLS_ENABLE \
|
||||
#ifndef OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
#define OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE \
|
||||
(OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE || \
|
||||
OPENTHREAD_CONFIG_COMMISSIONER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE)
|
||||
OPENTHREAD_CONFIG_COMMISSIONER_ENABLE || OPENTHREAD_CONFIG_JOINER_ENABLE || OPENTHREAD_CONFIG_BLE_TCAT_ENABLE)
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_DTLS_H_
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#error "OPENTHREAD_CONFIG_DTLS_ENABLE is deprecated please use OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE instead"
|
||||
#endif
|
||||
|
||||
#endif // CONFIG_SECURE_TRANSPORT_H_
|
||||
@@ -156,7 +156,7 @@ Instance::Instance(void)
|
||||
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
|
||||
, mCommissioner(*this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
, mTmfSecureAgent(*this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_JOINER_ENABLE
|
||||
@@ -211,6 +211,9 @@ Instance::Instance(void)
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
, mApplicationCoapSecure(*this, /* aLayerTwoSecurity */ true)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
, mApplicationBleSecure(*this)
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
, mPingSender(*this)
|
||||
#endif
|
||||
@@ -456,7 +459,7 @@ void Instance::GetBufferInfo(BufferInfo &aInfo)
|
||||
Get<Tmf::Agent>().GetRequestMessages().GetInfo(aInfo.mCoapQueue);
|
||||
Get<Tmf::Agent>().GetCachedResponses().GetInfo(aInfo.mCoapQueue);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
Get<Tmf::SecureAgent>().GetRequestMessages().GetInfo(aInfo.mCoapSecureQueue);
|
||||
Get<Tmf::SecureAgent>().GetCachedResponses().GetInfo(aInfo.mCoapSecureQueue);
|
||||
#endif
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
#include "net/sntp_client.hpp"
|
||||
#include "net/srp_client.hpp"
|
||||
#include "net/srp_server.hpp"
|
||||
#include "radio/ble_secure.hpp"
|
||||
#include "thread/address_resolver.hpp"
|
||||
#include "thread/announce_begin_server.hpp"
|
||||
#include "thread/announce_sender.hpp"
|
||||
@@ -547,7 +548,7 @@ private:
|
||||
MeshCoP::Commissioner mCommissioner;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
Tmf::SecureAgent mTmfSecureAgent;
|
||||
#endif
|
||||
|
||||
@@ -618,6 +619,10 @@ private:
|
||||
Coap::CoapSecure mApplicationCoapSecure;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
Ble::BleSecure mApplicationBleSecure;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
|
||||
Utils::PingSender mPingSender;
|
||||
#endif
|
||||
@@ -830,7 +835,7 @@ template <> inline Ip6::Mpl &Instance::Get(void) { return mIp6.mMpl; }
|
||||
|
||||
template <> inline Tmf::Agent &Instance::Get(void) { return mTmfAgent; }
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
template <> inline Tmf::SecureAgent &Instance::Get(void) { return mTmfSecureAgent; }
|
||||
#endif
|
||||
|
||||
@@ -1017,6 +1022,10 @@ template <> inline Nat64::Translator &Instance::Get(void) { return mNat64Transla
|
||||
template <> inline Srp::Server &Instance::Get(void) { return mSrpServer; }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
template <> inline Ble::BleSecure &Instance::Get(void) { return mApplicationBleSecure; }
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
|
||||
|
||||
@@ -50,9 +50,9 @@
|
||||
#include "common/timer.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/announce_begin_client.hpp"
|
||||
#include "meshcop/dtls.hpp"
|
||||
#include "meshcop/energy_scan_client.hpp"
|
||||
#include "meshcop/panid_query_client.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
#include "thread/key_manager.hpp"
|
||||
|
||||
@@ -49,9 +49,9 @@
|
||||
#include "common/message.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/dtls.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "meshcop/meshcop_tlvs.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
#include "thread/discover_scanner.hpp"
|
||||
#include "thread/tmf.hpp"
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
* This file implements the necessary hooks for mbedTLS.
|
||||
*/
|
||||
|
||||
#include "dtls.hpp"
|
||||
#include "secure_transport.hpp"
|
||||
|
||||
#include <mbedtls/debug.h>
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
@@ -52,42 +52,43 @@
|
||||
#include "instance/instance.hpp"
|
||||
#include "thread/thread_netif.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
|
||||
RegisterLogModule("Dtls");
|
||||
RegisterLogModule("SecTransport");
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
|
||||
const uint16_t Dtls::sGroups[] = {MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, MBEDTLS_SSL_IANA_TLS_GROUP_NONE};
|
||||
const uint16_t SecureTransport::sGroups[] = {MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, MBEDTLS_SSL_IANA_TLS_GROUP_NONE};
|
||||
#else
|
||||
const mbedtls_ecp_group_id Dtls::sCurves[] = {MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_NONE};
|
||||
const mbedtls_ecp_group_id SecureTransport::sCurves[] = {MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_NONE};
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03020000)
|
||||
const uint16_t Dtls::sSignatures[] = {MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, MBEDTLS_TLS1_3_SIG_NONE};
|
||||
const uint16_t SecureTransport::sSignatures[] = {MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, MBEDTLS_TLS1_3_SIG_NONE};
|
||||
#else
|
||||
const int Dtls::sHashes[] = {MBEDTLS_MD_SHA256, MBEDTLS_MD_NONE};
|
||||
const int SecureTransport::sHashes[] = {MBEDTLS_MD_SHA256, MBEDTLS_MD_NONE};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity)
|
||||
SecureTransport::SecureTransport(Instance &aInstance, bool aLayerTwoSecurity, bool aDatagramTransport)
|
||||
: InstanceLocator(aInstance)
|
||||
, mState(kStateClosed)
|
||||
, mPskLength(0)
|
||||
, mVerifyPeerCertificate(true)
|
||||
, mTimer(aInstance, Dtls::HandleTimer, this)
|
||||
, mTimer(aInstance, SecureTransport::HandleTimer, this)
|
||||
, mTimerIntermediate(0)
|
||||
, mTimerSet(false)
|
||||
, mLayerTwoSecurity(aLayerTwoSecurity)
|
||||
, mDatagramTransport(aDatagramTransport)
|
||||
, mReceiveMessage(nullptr)
|
||||
, mSocket(aInstance)
|
||||
, mMessageSubType(Message::kSubTypeNone)
|
||||
, mMessageDefaultSubType(Message::kSubTypeNone)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
mPreSharedKey = nullptr;
|
||||
mPreSharedKeyIdentity = nullptr;
|
||||
@@ -118,12 +119,15 @@ Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity)
|
||||
#endif
|
||||
}
|
||||
|
||||
void Dtls::FreeMbedtls(void)
|
||||
void SecureTransport::FreeMbedtls(void)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
mbedtls_ssl_cookie_free(&mCookieCtx);
|
||||
if (mDatagramTransport)
|
||||
{
|
||||
mbedtls_ssl_cookie_free(&mCookieCtx);
|
||||
}
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
mbedtls_x509_crt_free(&mCaChain);
|
||||
mbedtls_x509_crt_free(&mOwnCert);
|
||||
@@ -134,13 +138,13 @@ void Dtls::FreeMbedtls(void)
|
||||
mbedtls_ssl_free(&mSsl);
|
||||
}
|
||||
|
||||
Error Dtls::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
|
||||
Error SecureTransport::Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext)
|
||||
{
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(mState == kStateClosed, error = kErrorAlready);
|
||||
|
||||
SuccessOrExit(error = mSocket.Open(&Dtls::HandleUdpReceive, this));
|
||||
SuccessOrExit(error = mSocket.Open(&SecureTransport::HandleUdpReceive, this));
|
||||
|
||||
mConnectedCallback.Set(aConnectedHandler, aContext);
|
||||
mReceiveCallback.Set(aReceiveHandler, aContext);
|
||||
@@ -150,7 +154,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Dtls::Connect(const Ip6::SockAddr &aSockAddr)
|
||||
Error SecureTransport::Connect(const Ip6::SockAddr &aSockAddr)
|
||||
{
|
||||
Error error;
|
||||
|
||||
@@ -165,24 +169,30 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Dtls::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
void SecureTransport::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
static_cast<Dtls *>(aContext)->HandleUdpReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo));
|
||||
static_cast<SecureTransport *>(aContext)->HandleUdpReceive(AsCoreType(aMessage), AsCoreType(aMessageInfo));
|
||||
}
|
||||
|
||||
void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
void SecureTransport::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
switch (mState)
|
||||
{
|
||||
case Dtls::kStateClosed:
|
||||
case SecureTransport::kStateClosed:
|
||||
ExitNow();
|
||||
|
||||
case Dtls::kStateOpen:
|
||||
case SecureTransport::kStateOpen:
|
||||
IgnoreError(mSocket.Connect(Ip6::SockAddr(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort())));
|
||||
|
||||
mMessageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr());
|
||||
mMessageInfo.SetPeerPort(aMessageInfo.GetPeerPort());
|
||||
mMessageInfo.SetIsHostInterface(aMessageInfo.IsHostInterface());
|
||||
|
||||
mMessageInfo.SetSockAddr(aMessageInfo.GetSockAddr());
|
||||
if (Get<ThreadNetif>().HasUnicastAddress(aMessageInfo.GetSockAddr()))
|
||||
{
|
||||
mMessageInfo.SetSockAddr(aMessageInfo.GetSockAddr());
|
||||
}
|
||||
|
||||
mMessageInfo.SetSockPort(aMessageInfo.GetSockPort());
|
||||
|
||||
SuccessOrExit(Setup(false));
|
||||
@@ -196,7 +206,7 @@ void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageI
|
||||
}
|
||||
|
||||
#ifdef MBEDTLS_SSL_SRV_C
|
||||
if (mState == Dtls::kStateConnecting)
|
||||
if (mState == SecureTransport::kStateConnecting)
|
||||
{
|
||||
IgnoreError(SetClientId(mMessageInfo.GetPeerAddr().mFields.m8, sizeof(mMessageInfo.GetPeerAddr().mFields)));
|
||||
}
|
||||
@@ -208,9 +218,9 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t Dtls::GetUdpPort(void) const { return mSocket.GetSockName().GetPort(); }
|
||||
uint16_t SecureTransport::GetUdpPort(void) const { return mSocket.GetSockName().GetPort(); }
|
||||
|
||||
Error Dtls::Bind(uint16_t aPort)
|
||||
Error SecureTransport::Bind(uint16_t aPort)
|
||||
{
|
||||
Error error;
|
||||
|
||||
@@ -223,7 +233,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Dtls::Bind(TransportCallback aCallback, void *aContext)
|
||||
Error SecureTransport::Bind(TransportCallback aCallback, void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -237,7 +247,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Dtls::Setup(bool aClient)
|
||||
Error SecureTransport::Setup(bool aClient)
|
||||
{
|
||||
int rval;
|
||||
|
||||
@@ -248,7 +258,7 @@ Error Dtls::Setup(bool aClient)
|
||||
|
||||
mbedtls_ssl_init(&mSsl);
|
||||
mbedtls_ssl_config_init(&mConf);
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
mbedtls_x509_crt_init(&mCaChain);
|
||||
mbedtls_x509_crt_init(&mOwnCert);
|
||||
@@ -256,15 +266,20 @@ Error Dtls::Setup(bool aClient)
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
mbedtls_ssl_cookie_init(&mCookieCtx);
|
||||
if (mDatagramTransport)
|
||||
{
|
||||
mbedtls_ssl_cookie_init(&mCookieCtx);
|
||||
}
|
||||
#endif
|
||||
|
||||
rval = mbedtls_ssl_config_defaults(&mConf, aClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
||||
MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
rval = mbedtls_ssl_config_defaults(
|
||||
&mConf, aClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
|
||||
mDatagramTransport ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
if (mVerifyPeerCertificate && mCipherSuites[0] == MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8)
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
if (mVerifyPeerCertificate && (mCipherSuites[0] == MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ||
|
||||
mCipherSuites[0] == MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256))
|
||||
{
|
||||
mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
}
|
||||
@@ -313,7 +328,7 @@ Error Dtls::Setup(bool aClient)
|
||||
mbedtls_ssl_conf_dbg(&mConf, HandleMbedtlsDebug, this);
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
|
||||
if (!aClient)
|
||||
if (!aClient && mDatagramTransport)
|
||||
{
|
||||
rval = mbedtls_ssl_cookie_setup(&mCookieCtx, Crypto::MbedTls::CryptoSecurePrng, nullptr);
|
||||
VerifyOrExit(rval == 0);
|
||||
@@ -325,17 +340,21 @@ Error Dtls::Setup(bool aClient)
|
||||
rval = mbedtls_ssl_setup(&mSsl, &mConf);
|
||||
VerifyOrExit(rval == 0);
|
||||
|
||||
mbedtls_ssl_set_bio(&mSsl, this, &Dtls::HandleMbedtlsTransmit, HandleMbedtlsReceive, nullptr);
|
||||
mbedtls_ssl_set_timer_cb(&mSsl, this, &Dtls::HandleMbedtlsSetTimer, HandleMbedtlsGetTimer);
|
||||
mbedtls_ssl_set_bio(&mSsl, this, &SecureTransport::HandleMbedtlsTransmit, HandleMbedtlsReceive, nullptr);
|
||||
|
||||
if (mDatagramTransport)
|
||||
{
|
||||
mbedtls_ssl_set_timer_cb(&mSsl, this, &SecureTransport::HandleMbedtlsSetTimer, HandleMbedtlsGetTimer);
|
||||
}
|
||||
|
||||
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
|
||||
{
|
||||
rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength);
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
else
|
||||
{
|
||||
rval = SetApplicationCoapSecureKeys();
|
||||
rval = SetApplicationSecureKeys();
|
||||
}
|
||||
#endif
|
||||
VerifyOrExit(rval == 0);
|
||||
@@ -348,10 +367,10 @@ Error Dtls::Setup(bool aClient)
|
||||
{
|
||||
LogInfo("DTLS started");
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
else
|
||||
{
|
||||
LogInfo("Application Coap Secure DTLS started");
|
||||
LogInfo("Application Secure (D)TLS started");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -369,14 +388,16 @@ exit:
|
||||
return Crypto::MbedTls::MapError(rval);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
int Dtls::SetApplicationCoapSecureKeys(void)
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
int SecureTransport::SetApplicationSecureKeys(void)
|
||||
{
|
||||
int rval = 0;
|
||||
|
||||
switch (mCipherSuites[0])
|
||||
{
|
||||
case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
|
||||
case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
if (mCaChainSrc != nullptr)
|
||||
{
|
||||
@@ -426,9 +447,9 @@ exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
|
||||
void Dtls::Close(void)
|
||||
void SecureTransport::Close(void)
|
||||
{
|
||||
Disconnect();
|
||||
|
||||
@@ -440,7 +461,7 @@ void Dtls::Close(void)
|
||||
mTimer.Stop();
|
||||
}
|
||||
|
||||
void Dtls::Disconnect(void)
|
||||
void SecureTransport::Disconnect(void)
|
||||
{
|
||||
VerifyOrExit(mState == kStateConnecting || mState == kStateConnected);
|
||||
|
||||
@@ -457,7 +478,7 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error Dtls::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
|
||||
Error SecureTransport::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -472,13 +493,13 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
|
||||
void Dtls::SetCertificate(const uint8_t *aX509Certificate,
|
||||
uint32_t aX509CertLength,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint32_t aPrivateKeyLength)
|
||||
void SecureTransport::SetCertificate(const uint8_t *aX509Certificate,
|
||||
uint32_t aX509CertLength,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint32_t aPrivateKeyLength)
|
||||
{
|
||||
OT_ASSERT(aX509CertLength > 0);
|
||||
OT_ASSERT(aX509Certificate != nullptr);
|
||||
@@ -491,11 +512,19 @@ void Dtls::SetCertificate(const uint8_t *aX509Certificate,
|
||||
mPrivateKeySrc = aPrivateKey;
|
||||
mPrivateKeyLength = aPrivateKeyLength;
|
||||
|
||||
mCipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
|
||||
if (mDatagramTransport)
|
||||
{
|
||||
mCipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
|
||||
}
|
||||
|
||||
mCipherSuites[1] = 0;
|
||||
}
|
||||
|
||||
void Dtls::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength)
|
||||
void SecureTransport::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength)
|
||||
{
|
||||
OT_ASSERT(aX509CaCertChainLength > 0);
|
||||
OT_ASSERT(aX509CaCertificateChain != nullptr);
|
||||
@@ -507,7 +536,10 @@ void Dtls::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_
|
||||
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
void Dtls::SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength)
|
||||
void SecureTransport::SetPreSharedKey(const uint8_t *aPsk,
|
||||
uint16_t aPskLength,
|
||||
const uint8_t *aPskIdentity,
|
||||
uint16_t aPskIdLength)
|
||||
{
|
||||
OT_ASSERT(aPsk != nullptr);
|
||||
OT_ASSERT(aPskIdentity != nullptr);
|
||||
@@ -525,7 +557,7 @@ void Dtls::SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
Error Dtls::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
|
||||
Error SecureTransport::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -550,17 +582,153 @@ exit:
|
||||
}
|
||||
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
Error SecureTransport::GetPeerSubjectAttributeByOid(const char *aOid,
|
||||
size_t aOidLength,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength,
|
||||
int *aAsn1Type)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
const mbedtls_asn1_named_data *data;
|
||||
size_t length;
|
||||
size_t attributeBufferSize;
|
||||
mbedtls_x509_crt *peerCert = const_cast<mbedtls_x509_crt *>(mbedtls_ssl_get_peer_cert(&mSsl));
|
||||
|
||||
VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs);
|
||||
attributeBufferSize = *aAttributeLength;
|
||||
*aAttributeLength = 0;
|
||||
|
||||
VerifyOrExit(aAttributeBuffer != nullptr, error = kErrorNoBufs);
|
||||
VerifyOrExit(peerCert != nullptr, error = kErrorInvalidState);
|
||||
data = mbedtls_asn1_find_named_data(&peerCert->subject, aOid, aOidLength);
|
||||
VerifyOrExit(data != nullptr, error = kErrorNotFound);
|
||||
length = data->val.len;
|
||||
VerifyOrExit(length <= attributeBufferSize, error = kErrorNoBufs);
|
||||
|
||||
if (aAttributeLength != nullptr)
|
||||
{
|
||||
*aAttributeLength = length;
|
||||
}
|
||||
|
||||
if (aAsn1Type != nullptr)
|
||||
{
|
||||
*aAsn1Type = data->val.tag;
|
||||
}
|
||||
|
||||
memcpy(aAttributeBuffer, data->val.p, length);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error SecureTransport::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSsl);
|
||||
|
||||
return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
|
||||
}
|
||||
|
||||
#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
Error SecureTransport::GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
const mbedtls_x509_crt *cert = &mOwnCert;
|
||||
|
||||
return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
|
||||
}
|
||||
|
||||
Error SecureTransport::GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
|
||||
int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
Error error = kErrorNotFound;
|
||||
char oid[9] = {0x2B, 0x06, 0x01, 0x04, 0x01, static_cast<char>(0x82), static_cast<char>(0xDF),
|
||||
0x2A, 0x00}; // 1.3.6.1.4.1.44970.0
|
||||
mbedtls_x509_buf v3_ext;
|
||||
unsigned char *p, *end, *endExtData;
|
||||
size_t len;
|
||||
size_t attributeBufferSize;
|
||||
mbedtls_x509_buf extnOid;
|
||||
int ret, isCritical;
|
||||
|
||||
VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs);
|
||||
attributeBufferSize = *aAttributeLength;
|
||||
*aAttributeLength = 0;
|
||||
|
||||
VerifyOrExit(aCert != nullptr, error = kErrorInvalidState);
|
||||
v3_ext = aCert->v3_ext;
|
||||
p = v3_ext.p;
|
||||
VerifyOrExit(p != nullptr, error = kErrorInvalidState);
|
||||
end = p + v3_ext.len;
|
||||
VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0,
|
||||
error = kErrorParse);
|
||||
VerifyOrExit(end == p + len, error = kErrorParse);
|
||||
|
||||
VerifyOrExit(aThreadOidDescriptor < 128, error = kErrorNotImplemented);
|
||||
oid[sizeof(oid) - 1] = static_cast<char>(aThreadOidDescriptor);
|
||||
|
||||
while (p < end)
|
||||
{
|
||||
isCritical = 0;
|
||||
VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0,
|
||||
error = kErrorParse);
|
||||
endExtData = p + len;
|
||||
|
||||
// Get extension ID
|
||||
VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &extnOid.len, MBEDTLS_ASN1_OID) == 0, error = kErrorParse);
|
||||
extnOid.tag = MBEDTLS_ASN1_OID;
|
||||
extnOid.p = p;
|
||||
p += extnOid.len;
|
||||
|
||||
// Get optional critical
|
||||
ret = mbedtls_asn1_get_bool(&p, endExtData, &isCritical);
|
||||
VerifyOrExit(ret == 0 || ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = kErrorParse);
|
||||
|
||||
// Data should be octet string type
|
||||
VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &len, MBEDTLS_ASN1_OCTET_STRING) == 0, error = kErrorParse);
|
||||
VerifyOrExit(endExtData == p + len, error = kErrorParse);
|
||||
|
||||
if (isCritical || extnOid.len != sizeof(oid))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memcmp(extnOid.p, oid, sizeof(oid)) == 0)
|
||||
{
|
||||
*aAttributeLength = len;
|
||||
|
||||
if (aAttributeBuffer != nullptr)
|
||||
{
|
||||
VerifyOrExit(len <= attributeBufferSize, error = kErrorNoBufs);
|
||||
memcpy(aAttributeBuffer, p, len);
|
||||
}
|
||||
|
||||
error = kErrorNone;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
|
||||
#ifdef MBEDTLS_SSL_SRV_C
|
||||
Error Dtls::SetClientId(const uint8_t *aClientId, uint8_t aLength)
|
||||
Error SecureTransport::SetClientId(const uint8_t *aClientId, uint8_t aLength)
|
||||
{
|
||||
int rval = mbedtls_ssl_set_client_transport_id(&mSsl, aClientId, aLength);
|
||||
return Crypto::MbedTls::MapError(rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
Error Dtls::Send(Message &aMessage, uint16_t aLength)
|
||||
Error SecureTransport::Send(Message &aMessage, uint16_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint8_t buffer[kApplicationDataMaxLength];
|
||||
@@ -583,7 +751,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Dtls::Receive(Message &aMessage)
|
||||
void SecureTransport::Receive(Message &aMessage)
|
||||
{
|
||||
mReceiveMessage = &aMessage;
|
||||
|
||||
@@ -592,28 +760,28 @@ void Dtls::Receive(Message &aMessage)
|
||||
mReceiveMessage = nullptr;
|
||||
}
|
||||
|
||||
int Dtls::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength)
|
||||
int SecureTransport::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
return static_cast<Dtls *>(aContext)->HandleMbedtlsTransmit(aBuf, aLength);
|
||||
return static_cast<SecureTransport *>(aContext)->HandleMbedtlsTransmit(aBuf, aLength);
|
||||
}
|
||||
|
||||
int Dtls::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
|
||||
int SecureTransport::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
Error error;
|
||||
int rval = 0;
|
||||
|
||||
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
|
||||
{
|
||||
LogDebg("HandleMbedtlsTransmit");
|
||||
LogDebg("HandleMbedtlsTransmit DTLS");
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
else
|
||||
{
|
||||
LogDebg("ApplicationCoapSecure HandleMbedtlsTransmit");
|
||||
LogDebg("HandleMbedtlsTransmit TLS");
|
||||
}
|
||||
#endif
|
||||
|
||||
error = HandleDtlsSend(aBuf, static_cast<uint16_t>(aLength), mMessageSubType);
|
||||
error = HandleSecureTransportSend(aBuf, static_cast<uint16_t>(aLength), mMessageSubType);
|
||||
|
||||
// Restore default sub type.
|
||||
mMessageSubType = mMessageDefaultSubType;
|
||||
@@ -637,23 +805,23 @@ int Dtls::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength)
|
||||
return rval;
|
||||
}
|
||||
|
||||
int Dtls::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength)
|
||||
int SecureTransport::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
return static_cast<Dtls *>(aContext)->HandleMbedtlsReceive(aBuf, aLength);
|
||||
return static_cast<SecureTransport *>(aContext)->HandleMbedtlsReceive(aBuf, aLength);
|
||||
}
|
||||
|
||||
int Dtls::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength)
|
||||
int SecureTransport::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
|
||||
{
|
||||
LogDebg("HandleMbedtlsReceive");
|
||||
LogDebg("HandleMbedtlsReceive DTLS");
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
else
|
||||
{
|
||||
LogDebg("ApplicationCoapSecure HandleMbedtlsReceive");
|
||||
LogDebg("HandleMbedtlsReceive TLS");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -672,9 +840,12 @@ exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
int Dtls::HandleMbedtlsGetTimer(void *aContext) { return static_cast<Dtls *>(aContext)->HandleMbedtlsGetTimer(); }
|
||||
int SecureTransport::HandleMbedtlsGetTimer(void *aContext)
|
||||
{
|
||||
return static_cast<SecureTransport *>(aContext)->HandleMbedtlsGetTimer();
|
||||
}
|
||||
|
||||
int Dtls::HandleMbedtlsGetTimer(void)
|
||||
int SecureTransport::HandleMbedtlsGetTimer(void)
|
||||
{
|
||||
int rval;
|
||||
|
||||
@@ -682,10 +853,10 @@ int Dtls::HandleMbedtlsGetTimer(void)
|
||||
{
|
||||
LogDebg("HandleMbedtlsGetTimer");
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
else
|
||||
{
|
||||
LogDebg("ApplicationCoapSecure HandleMbedtlsGetTimer");
|
||||
LogDebg("HandleMbedtlsGetTimer");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -709,21 +880,21 @@ int Dtls::HandleMbedtlsGetTimer(void)
|
||||
return rval;
|
||||
}
|
||||
|
||||
void Dtls::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish)
|
||||
void SecureTransport::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish)
|
||||
{
|
||||
static_cast<Dtls *>(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish);
|
||||
static_cast<SecureTransport *>(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish);
|
||||
}
|
||||
|
||||
void Dtls::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish)
|
||||
void SecureTransport::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish)
|
||||
{
|
||||
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
|
||||
{
|
||||
LogDebg("SetTimer");
|
||||
LogDebg("SetTimer DTLS");
|
||||
}
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
else
|
||||
{
|
||||
LogDebg("ApplicationCoapSecure SetTimer");
|
||||
LogDebg("SetTimer TLS");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -742,42 +913,42 @@ void Dtls::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish)
|
||||
|
||||
#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
|
||||
void Dtls::HandleMbedtlsExportKeys(void *aContext,
|
||||
mbedtls_ssl_key_export_type aType,
|
||||
const unsigned char *aMasterSecret,
|
||||
size_t aMasterSecretLen,
|
||||
const unsigned char aClientRandom[32],
|
||||
const unsigned char aServerRandom[32],
|
||||
mbedtls_tls_prf_types aTlsPrfType)
|
||||
void SecureTransport::HandleMbedtlsExportKeys(void *aContext,
|
||||
mbedtls_ssl_key_export_type aType,
|
||||
const unsigned char *aMasterSecret,
|
||||
size_t aMasterSecretLen,
|
||||
const unsigned char aClientRandom[32],
|
||||
const unsigned char aServerRandom[32],
|
||||
mbedtls_tls_prf_types aTlsPrfType)
|
||||
{
|
||||
static_cast<Dtls *>(aContext)->HandleMbedtlsExportKeys(aType, aMasterSecret, aMasterSecretLen, aClientRandom,
|
||||
aServerRandom, aTlsPrfType);
|
||||
static_cast<SecureTransport *>(aContext)->HandleMbedtlsExportKeys(aType, aMasterSecret, aMasterSecretLen,
|
||||
aClientRandom, aServerRandom, aTlsPrfType);
|
||||
}
|
||||
|
||||
void Dtls::HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType,
|
||||
const unsigned char *aMasterSecret,
|
||||
size_t aMasterSecretLen,
|
||||
const unsigned char aClientRandom[32],
|
||||
const unsigned char aServerRandom[32],
|
||||
mbedtls_tls_prf_types aTlsPrfType)
|
||||
void SecureTransport::HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType,
|
||||
const unsigned char *aMasterSecret,
|
||||
size_t aMasterSecretLen,
|
||||
const unsigned char aClientRandom[32],
|
||||
const unsigned char aServerRandom[32],
|
||||
mbedtls_tls_prf_types aTlsPrfType)
|
||||
{
|
||||
Crypto::Sha256::Hash kek;
|
||||
Crypto::Sha256 sha256;
|
||||
unsigned char keyBlock[kDtlsKeyBlockSize];
|
||||
unsigned char randBytes[2 * kDtlsRandomBufferSize];
|
||||
unsigned char keyBlock[kSecureTransportKeyBlockSize];
|
||||
unsigned char randBytes[2 * kSecureTransportRandomBufferSize];
|
||||
|
||||
VerifyOrExit(mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8);
|
||||
VerifyOrExit(aType == MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET);
|
||||
|
||||
memcpy(randBytes, aServerRandom, kDtlsRandomBufferSize);
|
||||
memcpy(randBytes + kDtlsRandomBufferSize, aClientRandom, kDtlsRandomBufferSize);
|
||||
memcpy(randBytes, aServerRandom, kSecureTransportRandomBufferSize);
|
||||
memcpy(randBytes + kSecureTransportRandomBufferSize, aClientRandom, kSecureTransportRandomBufferSize);
|
||||
|
||||
// Retrieve the Key block from Master secret
|
||||
mbedtls_ssl_tls_prf(aTlsPrfType, aMasterSecret, aMasterSecretLen, "key expansion", randBytes, sizeof(randBytes),
|
||||
keyBlock, sizeof(keyBlock));
|
||||
|
||||
sha256.Start();
|
||||
sha256.Update(keyBlock, kDtlsKeyBlockSize);
|
||||
sha256.Update(keyBlock, kSecureTransportKeyBlockSize);
|
||||
sha256.Finish(kek);
|
||||
|
||||
LogDebg("Generated KEK");
|
||||
@@ -789,22 +960,22 @@ exit:
|
||||
|
||||
#else
|
||||
|
||||
int Dtls::HandleMbedtlsExportKeys(void *aContext,
|
||||
const unsigned char *aMasterSecret,
|
||||
const unsigned char *aKeyBlock,
|
||||
size_t aMacLength,
|
||||
size_t aKeyLength,
|
||||
size_t aIvLength)
|
||||
int SecureTransport::HandleMbedtlsExportKeys(void *aContext,
|
||||
const unsigned char *aMasterSecret,
|
||||
const unsigned char *aKeyBlock,
|
||||
size_t aMacLength,
|
||||
size_t aKeyLength,
|
||||
size_t aIvLength)
|
||||
{
|
||||
return static_cast<Dtls *>(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength, aKeyLength,
|
||||
aIvLength);
|
||||
return static_cast<SecureTransport *>(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength,
|
||||
aKeyLength, aIvLength);
|
||||
}
|
||||
|
||||
int Dtls::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
|
||||
const unsigned char *aKeyBlock,
|
||||
size_t aMacLength,
|
||||
size_t aKeyLength,
|
||||
size_t aIvLength)
|
||||
int SecureTransport::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret,
|
||||
const unsigned char *aKeyBlock,
|
||||
size_t aMacLength,
|
||||
size_t aKeyLength,
|
||||
size_t aIvLength)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMasterSecret);
|
||||
|
||||
@@ -826,12 +997,12 @@ exit:
|
||||
|
||||
#endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000)
|
||||
|
||||
void Dtls::HandleTimer(Timer &aTimer)
|
||||
void SecureTransport::HandleTimer(Timer &aTimer)
|
||||
{
|
||||
static_cast<Dtls *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleTimer();
|
||||
static_cast<SecureTransport *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleTimer();
|
||||
}
|
||||
|
||||
void Dtls::HandleTimer(void)
|
||||
void SecureTransport::HandleTimer(void)
|
||||
{
|
||||
switch (mState)
|
||||
{
|
||||
@@ -852,7 +1023,7 @@ void Dtls::HandleTimer(void)
|
||||
}
|
||||
}
|
||||
|
||||
void Dtls::Process(void)
|
||||
void SecureTransport::Process(void)
|
||||
{
|
||||
uint8_t buf[OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN];
|
||||
bool shouldDisconnect = false;
|
||||
@@ -938,12 +1109,12 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
void Dtls::HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr)
|
||||
void SecureTransport::HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr)
|
||||
{
|
||||
static_cast<Dtls *>(aContext)->HandleMbedtlsDebug(aLevel, aFile, aLine, aStr);
|
||||
static_cast<SecureTransport *>(aContext)->HandleMbedtlsDebug(aLevel, aFile, aLine, aStr);
|
||||
}
|
||||
|
||||
void Dtls::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr)
|
||||
void SecureTransport::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aStr);
|
||||
OT_UNUSED_VARIABLE(aFile);
|
||||
@@ -970,7 +1141,9 @@ void Dtls::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const ch
|
||||
}
|
||||
}
|
||||
|
||||
Error Dtls::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType)
|
||||
Error SecureTransport::HandleSecureTransportSend(const uint8_t *aBuf,
|
||||
uint16_t aLength,
|
||||
Message::SubType aMessageSubType)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
ot::Message *message = nullptr;
|
||||
@@ -1004,4 +1177,4 @@ exit:
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
@@ -31,17 +31,33 @@
|
||||
* This file includes definitions for using mbedTLS.
|
||||
*/
|
||||
|
||||
#ifndef DTLS_HPP_
|
||||
#define DTLS_HPP_
|
||||
#ifndef SECURE_TRANSPORT_HPP_
|
||||
#define SECURE_TRANSPORT_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#ifdef OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#error `OPENTHREAD_CONFIG_TLS_API_ENABLE` must not be defined directly, it is determined from `COAP_SECURE_API_ENABLE` and `BLE_TCAT_ENABLE`
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE || OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
#define OPENTHREAD_CONFIG_TLS_API_ENABLE 1
|
||||
#else
|
||||
#define OPENTHREAD_CONFIG_TLS_API_ENABLE 0
|
||||
#endif
|
||||
|
||||
#include <mbedtls/net_sockets.h>
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/ssl_cookie.h>
|
||||
#include <mbedtls/version.h>
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
#ifndef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#error OPENTHREAD_CONFIG_BLE_TCAT_ENABLE requires MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
#include <mbedtls/base64.h>
|
||||
#endif
|
||||
@@ -67,19 +83,20 @@ namespace ot {
|
||||
|
||||
namespace MeshCoP {
|
||||
|
||||
class Dtls : public InstanceLocator
|
||||
class SecureTransport : public InstanceLocator
|
||||
{
|
||||
public:
|
||||
static constexpr uint8_t kPskMaxLength = 32; ///< Maximum PSK length.
|
||||
|
||||
/**
|
||||
* Initializes the DTLS object.
|
||||
* Initializes the SecureTransport object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the OpenThread instance.
|
||||
* @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not.
|
||||
* @param[in] aDatagramTransport Specifies if dtls of tls connection should be used.
|
||||
*
|
||||
*/
|
||||
explicit Dtls(Instance &aInstance, bool aLayerTwoSecurity);
|
||||
explicit SecureTransport(Instance &aInstance, bool aLayerTwoSecurity, bool aDatagramTransport = true);
|
||||
|
||||
/**
|
||||
* Pointer is called when a connection is established or torn down.
|
||||
@@ -91,7 +108,7 @@ public:
|
||||
typedef void (*ConnectedHandler)(void *aContext, bool aConnected);
|
||||
|
||||
/**
|
||||
* Pointer is called when data is received from the DTLS session.
|
||||
* Pointer is called when data is received from the session.
|
||||
*
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
* @param[in] aBuf A pointer to the received data buffer.
|
||||
@@ -111,14 +128,14 @@ public:
|
||||
typedef Error (*TransportCallback)(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* Opens the DTLS socket.
|
||||
* Opens the socket.
|
||||
*
|
||||
* @param[in] aReceiveHandler A pointer to a function that is called to receive DTLS payload.
|
||||
* @param[in] aReceiveHandler A pointer to a function that is called to receive payload.
|
||||
* @param[in] aConnectedHandler A pointer to a function that is called when connected or disconnected.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
* @retval kErrorNone Successfully opened the socket.
|
||||
* @retval kErrorAlready The DTLS is already open.
|
||||
* @retval kErrorAlready The connection is already open.
|
||||
*
|
||||
*/
|
||||
Error Open(ReceiveHandler aReceiveHandler, ConnectedHandler aConnectedHandler, void *aContext);
|
||||
@@ -128,8 +145,8 @@ public:
|
||||
*
|
||||
* @param[in] aPort The port to bind.
|
||||
*
|
||||
* @retval kErrorNone Successfully bound the DTLS socket.
|
||||
* @retval kErrorInvalidState The DTLS socket is not open.
|
||||
* @retval kErrorNone Successfully bound the socket.
|
||||
* @retval kErrorInvalidState The socket is not open.
|
||||
* @retval kErrorAlready Already bound.
|
||||
*
|
||||
*/
|
||||
@@ -144,20 +161,20 @@ public:
|
||||
uint16_t GetUdpPort(void) const;
|
||||
|
||||
/**
|
||||
* Binds this DTLS with a transport callback.
|
||||
* Binds with a transport callback.
|
||||
*
|
||||
* @param[in] aCallback A pointer to a function for sending messages.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
* @retval kErrorNone Successfully bound the DTLS socket.
|
||||
* @retval kErrorInvalidState The DTLS socket is not open.
|
||||
* @retval kErrorNone Successfully bound the socket.
|
||||
* @retval kErrorInvalidState The socket is not open.
|
||||
* @retval kErrorAlready Already bound.
|
||||
*
|
||||
*/
|
||||
Error Bind(TransportCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* Establishes a DTLS session.
|
||||
* Establishes a secure session.
|
||||
*
|
||||
* For CoAP Secure API do first:
|
||||
* Set X509 Pk and Cert for use DTLS mode ECDHE ECDSA with AES 128 CCM 8 or
|
||||
@@ -165,38 +182,38 @@ public:
|
||||
*
|
||||
* @param[in] aSockAddr A reference to the remote sockaddr.
|
||||
*
|
||||
* @retval kErrorNone Successfully started DTLS handshake.
|
||||
* @retval kErrorInvalidState The DTLS socket is not open.
|
||||
* @retval kErrorNone Successfully started handshake.
|
||||
* @retval kErrorInvalidState The socket is not open.
|
||||
*
|
||||
*/
|
||||
Error Connect(const Ip6::SockAddr &aSockAddr);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the DTLS session is active.
|
||||
* Indicates whether or not the session is active.
|
||||
*
|
||||
* @retval TRUE If DTLS session is active.
|
||||
* @retval FALSE If DTLS session is not active.
|
||||
* @retval TRUE If session is active.
|
||||
* @retval FALSE If session is not active.
|
||||
*
|
||||
*/
|
||||
bool IsConnectionActive(void) const { return mState >= kStateConnecting; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the DTLS session is connected.
|
||||
* Indicates whether or not the session is connected.
|
||||
*
|
||||
* @retval TRUE The DTLS session is connected.
|
||||
* @retval FALSE The DTLS session is not connected.
|
||||
* @retval TRUE The session is connected.
|
||||
* @retval FALSE The session is not connected.
|
||||
*
|
||||
*/
|
||||
bool IsConnected(void) const { return mState == kStateConnected; }
|
||||
|
||||
/**
|
||||
* Disconnects the DTLS session.
|
||||
* Disconnects the session.
|
||||
*
|
||||
*/
|
||||
void Disconnect(void);
|
||||
|
||||
/**
|
||||
* Closes the DTLS socket.
|
||||
* Closes the socket.
|
||||
*
|
||||
*/
|
||||
void Close(void);
|
||||
@@ -212,10 +229,10 @@ public:
|
||||
*/
|
||||
Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
/**
|
||||
* Sets the Pre-Shared Key (PSK) for DTLS sessions-
|
||||
* Sets the Pre-Shared Key (PSK) for sessions-
|
||||
* identified by a PSK.
|
||||
*
|
||||
* DTLS mode "PSK with AES 128 CCM 8" for Application CoAPS.
|
||||
@@ -280,8 +297,84 @@ public:
|
||||
Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize);
|
||||
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/**
|
||||
* Set the authentication mode for a dtls connection.
|
||||
* Returns an attribute value identified by its OID from the subject
|
||||
* of the peer x509 certificate. The peer OID is provided in binary format.
|
||||
* The attribute length is set if the attribute was successfully read or zero
|
||||
* if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard
|
||||
* if the attribute was successfully read.
|
||||
*
|
||||
* @param[in] aOid A pointer to the OID to be found.
|
||||
* @param[in] aOidLength The length of the OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
* @param[out] aAsn1Type A pointer to the ASN.1 type of the attribute written to the buffer.
|
||||
*
|
||||
* @retval kErrorInvalidState Not connected yet.
|
||||
* @retval kErrorInvalidArgs Invalid attribute length.
|
||||
* @retval kErrorNone Successfully read attribute.
|
||||
* @retval kErrorNoBufs Insufficient memory for storing the attribute value.
|
||||
*
|
||||
*/
|
||||
Error GetPeerSubjectAttributeByOid(const char *aOid,
|
||||
size_t aOidLength,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength,
|
||||
int *aAsn1Type);
|
||||
|
||||
/**
|
||||
* Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
|
||||
* the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor.
|
||||
* The attribute length is set if the attribute was successfully read or zero if unsuccessful.
|
||||
* Requires a connection to be active.
|
||||
*
|
||||
* @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully read attribute.
|
||||
* @retval kErrorInvalidArgs Invalid attribute length.
|
||||
* @retval kErrorNotFound The requested attribute was not found.
|
||||
* @retval kErrorNoBufs Insufficient memory for storing the attribute value.
|
||||
* @retval kErrorInvalidState Not connected yet.
|
||||
* @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127.
|
||||
* @retval kErrorParse The certificate extensions could not be parsed.
|
||||
*
|
||||
*/
|
||||
Error GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength);
|
||||
#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
/**
|
||||
* Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
|
||||
* the own x509 certificate, where the last digit x is set to aThreadOidDescriptor.
|
||||
* The attribute length is set if the attribute was successfully read or zero if unsuccessful.
|
||||
* Requires a connection to be active.
|
||||
*
|
||||
* @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully read attribute.
|
||||
* @retval kErrorInvalidArgs Invalid attribute length.
|
||||
* @retval kErrorNotFound The requested attribute was not found.
|
||||
* @retval kErrorNoBufs Insufficient memory for storing the attribute value.
|
||||
* @retval kErrorInvalidState Not connected yet.
|
||||
* @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127.
|
||||
* @retval kErrorParse The certificate extensions could not be parsed.
|
||||
*
|
||||
*/
|
||||
Error GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength);
|
||||
|
||||
/**
|
||||
* Set the authentication mode for a connection.
|
||||
*
|
||||
* Disable or enable the verification of peer certificate.
|
||||
* Must called before start.
|
||||
@@ -290,7 +383,7 @@ public:
|
||||
*
|
||||
*/
|
||||
void SetSslAuthMode(bool aVerifyPeerCertificate) { mVerifyPeerCertificate = aVerifyPeerCertificate; }
|
||||
#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
|
||||
#ifdef MBEDTLS_SSL_SRV_C
|
||||
/**
|
||||
@@ -306,19 +399,19 @@ public:
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sends data within the DTLS session.
|
||||
* Sends data within the session.
|
||||
*
|
||||
* @param[in] aMessage A message to send via DTLS.
|
||||
* @param[in] aMessage A message to send via connection.
|
||||
* @param[in] aLength Number of bytes in the data buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully sent the data via the DTLS session.
|
||||
* @retval kErrorNone Successfully sent the data via the session.
|
||||
* @retval kErrorNoBufs A message is too long.
|
||||
*
|
||||
*/
|
||||
Error Send(Message &aMessage, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Provides a received DTLS message to the DTLS object.
|
||||
* Provides a received message to the SecureTransport object.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message.
|
||||
*
|
||||
@@ -335,9 +428,9 @@ public:
|
||||
void SetDefaultMessageSubType(Message::SubType aMessageSubType) { mMessageDefaultSubType = aMessageSubType; }
|
||||
|
||||
/**
|
||||
* Returns the DTLS session's peer address.
|
||||
* Returns the session's peer address.
|
||||
*
|
||||
* @return DTLS session's message info.
|
||||
* @return session's message info.
|
||||
*
|
||||
*/
|
||||
const Ip6::MessageInfo &GetMessageInfo(void) const { return mMessageInfo; }
|
||||
@@ -349,34 +442,39 @@ private:
|
||||
{
|
||||
kStateClosed, // UDP socket is closed.
|
||||
kStateOpen, // UDP socket is open.
|
||||
kStateInitializing, // The DTLS service is initializing.
|
||||
kStateConnecting, // The DTLS service is establishing a connection.
|
||||
kStateConnected, // The DTLS service has a connection established.
|
||||
kStateCloseNotify, // The DTLS service is closing a connection.
|
||||
kStateInitializing, // The service is initializing.
|
||||
kStateConnecting, // The service is establishing a connection.
|
||||
kStateConnected, // The service has a connection established.
|
||||
kStateCloseNotify, // The service is closing a connection.
|
||||
};
|
||||
|
||||
static constexpr uint32_t kGuardTimeNewConnectionMilli = 2000;
|
||||
|
||||
#if !OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if !OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
static constexpr uint16_t kApplicationDataMaxLength = 1152;
|
||||
#else
|
||||
static constexpr uint16_t kApplicationDataMaxLength = OPENTHREAD_CONFIG_DTLS_APPLICATION_DATA_MAX_LENGTH;
|
||||
#endif
|
||||
|
||||
static constexpr size_t kDtlsKeyBlockSize = 40;
|
||||
static constexpr size_t kDtlsRandomBufferSize = 32;
|
||||
static constexpr size_t kSecureTransportKeyBlockSize = 40;
|
||||
static constexpr size_t kSecureTransportRandomBufferSize = 32;
|
||||
|
||||
void FreeMbedtls(void);
|
||||
Error Setup(bool aClient);
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
/**
|
||||
* Set keys and/or certificates for dtls session dependent of used cipher suite.
|
||||
*
|
||||
* @retval mbedtls error, 0 if successfully.
|
||||
*
|
||||
*/
|
||||
int SetApplicationCoapSecureKeys(void);
|
||||
int SetApplicationSecureKeys(void);
|
||||
|
||||
Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
|
||||
int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength);
|
||||
#endif
|
||||
|
||||
static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr);
|
||||
@@ -434,8 +532,8 @@ private:
|
||||
|
||||
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
void HandleDtlsReceive(const uint8_t *aBuf, uint16_t aLength);
|
||||
Error HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType);
|
||||
void HandleSecureTransportReceive(const uint8_t *aBuf, uint16_t aLength);
|
||||
Error HandleSecureTransportSend(const uint8_t *aBuf, uint16_t aLength, Message::SubType aMessageSubType);
|
||||
|
||||
void Process(void);
|
||||
|
||||
@@ -459,7 +557,7 @@ private:
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
const uint8_t *mCaChainSrc;
|
||||
uint32_t mCaChainLength;
|
||||
@@ -494,16 +592,19 @@ private:
|
||||
bool mTimerSet : 1;
|
||||
|
||||
bool mLayerTwoSecurity : 1;
|
||||
bool mDatagramTransport : 1;
|
||||
|
||||
Message *mReceiveMessage;
|
||||
|
||||
Callback<ConnectedHandler> mConnectedCallback;
|
||||
Callback<ReceiveHandler> mReceiveCallback;
|
||||
void *mContext;
|
||||
|
||||
Ip6::MessageInfo mMessageInfo;
|
||||
Ip6::Udp::Socket mSocket;
|
||||
|
||||
Callback<TransportCallback> mTransportCallback;
|
||||
void *mTransportContext;
|
||||
|
||||
Message::SubType mMessageSubType;
|
||||
Message::SubType mMessageDefaultSubType;
|
||||
@@ -512,4 +613,4 @@ private:
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
#endif // DTLS_HPP_
|
||||
#endif // SECURE_TRANSPORT_HPP_
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the TCAT Agent service.
|
||||
*/
|
||||
|
||||
#include "tcat_agent.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common/array.hpp"
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/locator_getters.hpp"
|
||||
#include "common/string.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
#include "radio/radio.hpp"
|
||||
#include "thread/thread_netif.hpp"
|
||||
#include "thread/uri_paths.hpp"
|
||||
#include "utils/otns.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
|
||||
RegisterLogModule("TcatAgent");
|
||||
|
||||
bool TcatAgent::VendorInfo::IsValid(void) const
|
||||
{
|
||||
return mProvisioningUrl == nullptr || IsValidUtf8String(mProvisioningUrl) || mPskdString != nullptr;
|
||||
}
|
||||
|
||||
TcatAgent::TcatAgent(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mVendorInfo(nullptr)
|
||||
, mCurrentApplicationProtocol(kApplicationProtocolNone)
|
||||
, mState(kStateDisabled)
|
||||
, mAlreadyCommissioned(false)
|
||||
, mCommissionerHasNetworkName(false)
|
||||
, mCommissionerHasDomainName(false)
|
||||
, mCommissionerHasExtendedPanId(false)
|
||||
{
|
||||
mJoinerPskd.Clear();
|
||||
mCurrentServiceName[0] = 0;
|
||||
}
|
||||
|
||||
Error TcatAgent::Start(const TcatAgent::VendorInfo &aVendorInfo,
|
||||
AppDataReceiveCallback aAppDataReceiveCallback,
|
||||
JoinCallback aHandler,
|
||||
void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
LogInfo("Starting");
|
||||
|
||||
VerifyOrExit(aVendorInfo.IsValid(), error = kErrorInvalidArgs);
|
||||
SuccessOrExit(error = mJoinerPskd.SetFrom(aVendorInfo.mPskdString));
|
||||
|
||||
mAppDataReceiveCallback.Set(aAppDataReceiveCallback, aContext);
|
||||
mJoinCallback.Set(aHandler, aContext);
|
||||
|
||||
mVendorInfo = &aVendorInfo;
|
||||
mCurrentApplicationProtocol = kApplicationProtocolNone;
|
||||
mState = kStateEnabled;
|
||||
mAlreadyCommissioned = false;
|
||||
|
||||
exit:
|
||||
LogError("start TCAT agent", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
void TcatAgent::Stop(void)
|
||||
{
|
||||
mCurrentApplicationProtocol = kApplicationProtocolNone;
|
||||
mState = kStateDisabled;
|
||||
mAlreadyCommissioned = false;
|
||||
mAppDataReceiveCallback.Clear();
|
||||
mJoinCallback.Clear();
|
||||
LogInfo("TCAT agent stopped");
|
||||
}
|
||||
|
||||
Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
|
||||
{
|
||||
size_t len;
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
|
||||
len = sizeof(mCommissionerAuthorizationField);
|
||||
SuccessOrExit(
|
||||
error = aTlsContext.GetThreadAttributeFromPeerCertificate(
|
||||
kCertificateAuthorizationField, reinterpret_cast<uint8_t *>(&mCommissionerAuthorizationField), &len));
|
||||
VerifyOrExit(len == sizeof(mCommissionerAuthorizationField), error = kErrorParse);
|
||||
VerifyOrExit((mCommissionerAuthorizationField.mHeader & kCommissionerFlag) == 1, error = kErrorParse);
|
||||
|
||||
len = sizeof(mDeviceAuthorizationField);
|
||||
SuccessOrExit(error = aTlsContext.GetThreadAttributeFromOwnCertificate(
|
||||
kCertificateAuthorizationField, reinterpret_cast<uint8_t *>(&mDeviceAuthorizationField), &len));
|
||||
VerifyOrExit(len == sizeof(mDeviceAuthorizationField), error = kErrorParse);
|
||||
VerifyOrExit((mDeviceAuthorizationField.mHeader & kCommissionerFlag) == 0, error = kErrorParse);
|
||||
|
||||
mCommissionerHasDomainName = false;
|
||||
mCommissionerHasNetworkName = false;
|
||||
mCommissionerHasExtendedPanId = false;
|
||||
|
||||
len = sizeof(mCommissionerDomainName) - 1;
|
||||
if (aTlsContext.GetThreadAttributeFromPeerCertificate(
|
||||
kCertificateDomainName, reinterpret_cast<uint8_t *>(&mCommissionerDomainName), &len) == kErrorNone)
|
||||
{
|
||||
mCommissionerDomainName.m8[len] = '\0';
|
||||
mCommissionerHasDomainName = true;
|
||||
}
|
||||
|
||||
len = sizeof(mCommissionerNetworkName) - 1;
|
||||
if (aTlsContext.GetThreadAttributeFromPeerCertificate(
|
||||
kCertificateNetworkName, reinterpret_cast<uint8_t *>(&mCommissionerNetworkName), &len) == kErrorNone)
|
||||
{
|
||||
mCommissionerNetworkName.m8[len] = '\0';
|
||||
mCommissionerHasNetworkName = true;
|
||||
}
|
||||
|
||||
len = sizeof(mCommissionerExtendedPanId);
|
||||
if (aTlsContext.GetThreadAttributeFromPeerCertificate(
|
||||
kCertificateExtendedPanId, reinterpret_cast<uint8_t *>(&mCommissionerExtendedPanId), &len) == kErrorNone)
|
||||
{
|
||||
if (len == sizeof(mCommissionerExtendedPanId))
|
||||
{
|
||||
mCommissionerHasExtendedPanId = true;
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentApplicationProtocol = kApplicationProtocolNone;
|
||||
mCurrentServiceName[0] = 0;
|
||||
mState = kStateConnected;
|
||||
mAlreadyCommissioned = Get<ActiveDatasetManager>().IsCommissioned();
|
||||
LogInfo("TCAT agent connected");
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void TcatAgent::Disconnected(void)
|
||||
{
|
||||
mCurrentApplicationProtocol = kApplicationProtocolNone;
|
||||
mAlreadyCommissioned = false;
|
||||
|
||||
if (mState != kStateDisabled)
|
||||
{
|
||||
mState = kStateEnabled;
|
||||
}
|
||||
|
||||
LogInfo("TCAT agent disconnected");
|
||||
}
|
||||
|
||||
bool TcatAgent::CheckCommandClassAuthorizationFlags(CommandClassFlags aCommissionerCommandClassFlags,
|
||||
CommandClassFlags aDeviceCommandClassFlags,
|
||||
Dataset *aDataset) const
|
||||
{
|
||||
bool authorized = false;
|
||||
bool additionalDeviceRequirementMet = false;
|
||||
bool domainNamesMatch = false;
|
||||
bool networkNamesMatch = false;
|
||||
bool extendedPanIdsMatch = false;
|
||||
|
||||
VerifyOrExit(IsConnected());
|
||||
VerifyOrExit(aCommissionerCommandClassFlags & kAccessFlag);
|
||||
|
||||
if (aDeviceCommandClassFlags & kAccessFlag)
|
||||
{
|
||||
additionalDeviceRequirementMet = true;
|
||||
}
|
||||
|
||||
if (aDeviceCommandClassFlags & kPskdFlag)
|
||||
{
|
||||
additionalDeviceRequirementMet = true;
|
||||
}
|
||||
|
||||
if (aDeviceCommandClassFlags & kPskcFlag)
|
||||
{
|
||||
additionalDeviceRequirementMet = true;
|
||||
}
|
||||
|
||||
if (mCommissionerHasNetworkName || mCommissionerHasExtendedPanId)
|
||||
{
|
||||
Dataset::Info datasetInfo;
|
||||
Error datasetError = kErrorNone;
|
||||
|
||||
if (aDataset == nullptr)
|
||||
{
|
||||
datasetError = Get<ActiveDatasetManager>().Read(datasetInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
aDataset->ConvertTo(datasetInfo);
|
||||
}
|
||||
|
||||
if (datasetError == kErrorNone)
|
||||
{
|
||||
if (datasetInfo.IsNetworkNamePresent() && mCommissionerHasNetworkName &&
|
||||
(datasetInfo.GetNetworkName() == mCommissionerNetworkName))
|
||||
{
|
||||
networkNamesMatch = true;
|
||||
}
|
||||
|
||||
if (datasetInfo.IsExtendedPanIdPresent() && mCommissionerHasExtendedPanId &&
|
||||
(datasetInfo.GetExtendedPanId() == mCommissionerExtendedPanId))
|
||||
{
|
||||
extendedPanIdsMatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!networkNamesMatch)
|
||||
{
|
||||
VerifyOrExit((aCommissionerCommandClassFlags & kNetworkNameFlag) == 0);
|
||||
}
|
||||
else if (aDeviceCommandClassFlags & kNetworkNameFlag)
|
||||
{
|
||||
additionalDeviceRequirementMet = true;
|
||||
}
|
||||
|
||||
if (!extendedPanIdsMatch)
|
||||
{
|
||||
VerifyOrExit((aCommissionerCommandClassFlags & kExtendedPanIdFlag) == 0);
|
||||
}
|
||||
else if (aDeviceCommandClassFlags & kExtendedPanIdFlag)
|
||||
{
|
||||
additionalDeviceRequirementMet = true;
|
||||
}
|
||||
|
||||
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
VerifyOrExit((aCommissionerCommandClassFlags & kThreadDomainFlag) == 0);
|
||||
#endif
|
||||
|
||||
if (!domainNamesMatch)
|
||||
{
|
||||
VerifyOrExit((aCommissionerCommandClassFlags & kThreadDomainFlag) == 0);
|
||||
}
|
||||
else if (aDeviceCommandClassFlags & kThreadDomainFlag)
|
||||
{
|
||||
additionalDeviceRequirementMet = true;
|
||||
}
|
||||
|
||||
if (additionalDeviceRequirementMet)
|
||||
{
|
||||
authorized = true;
|
||||
}
|
||||
|
||||
exit:
|
||||
return authorized;
|
||||
}
|
||||
|
||||
bool TcatAgent::IsCommandClassAuthorized(CommandClass aCommandClass) const
|
||||
{
|
||||
bool authorized = false;
|
||||
|
||||
switch (aCommandClass)
|
||||
{
|
||||
case kGeneral:
|
||||
authorized = true;
|
||||
break;
|
||||
|
||||
case kCommissioning:
|
||||
authorized = CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mCommissioningFlags,
|
||||
mDeviceAuthorizationField.mCommissioningFlags, nullptr);
|
||||
break;
|
||||
|
||||
case kExtraction:
|
||||
authorized = CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mExtractionFlags,
|
||||
mDeviceAuthorizationField.mExtractionFlags, nullptr);
|
||||
break;
|
||||
|
||||
case kTlvDecommissioning:
|
||||
authorized = CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mDecommissioningFlags,
|
||||
mDeviceAuthorizationField.mDecommissioningFlags, nullptr);
|
||||
break;
|
||||
|
||||
case kApplication:
|
||||
authorized = CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags,
|
||||
mDeviceAuthorizationField.mApplicationFlags, nullptr);
|
||||
break;
|
||||
|
||||
case kInvalid:
|
||||
authorized = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return authorized;
|
||||
}
|
||||
|
||||
TcatAgent::CommandClass TcatAgent::GetCommandClass(uint8_t aTlvType) const
|
||||
{
|
||||
static constexpr int kGeneralTlvs = 0x1F;
|
||||
static constexpr int kCommissioningTlvs = 0x3F;
|
||||
static constexpr int kExtractionTlvs = 0x5F;
|
||||
static constexpr int kTlvDecommissioningTlvs = 0x7F;
|
||||
static constexpr int kApplicationTlvs = 0x9F;
|
||||
|
||||
if (aTlvType <= kGeneralTlvs)
|
||||
{
|
||||
return kGeneral;
|
||||
}
|
||||
else if (aTlvType <= kCommissioningTlvs)
|
||||
{
|
||||
return kCommissioning;
|
||||
}
|
||||
else if (aTlvType <= kExtractionTlvs)
|
||||
{
|
||||
return kExtraction;
|
||||
}
|
||||
else if (aTlvType <= kTlvDecommissioningTlvs)
|
||||
{
|
||||
return kTlvDecommissioning;
|
||||
}
|
||||
else if (aTlvType <= kApplicationTlvs)
|
||||
{
|
||||
return kApplication;
|
||||
}
|
||||
else
|
||||
{
|
||||
return kInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
bool TcatAgent::CanProcessTlv(uint8_t aTlvType) const
|
||||
{
|
||||
CommandClass tlvCommandClass = GetCommandClass(aTlvType);
|
||||
return IsCommandClassAuthorized(tlvCommandClass);
|
||||
}
|
||||
|
||||
Error TcatAgent::HandleSingleTlv(const Message &aIncommingMessage, Message &aOutgoingMessage)
|
||||
{
|
||||
Error error = kErrorParse;
|
||||
ot::Tlv tlv;
|
||||
uint16_t offset = aIncommingMessage.GetOffset();
|
||||
uint16_t length;
|
||||
bool response = false;
|
||||
|
||||
VerifyOrExit(IsConnected(), error = kErrorInvalidState);
|
||||
SuccessOrExit(error = aIncommingMessage.Read(offset, tlv));
|
||||
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
ot::ExtendedTlv extTlv;
|
||||
SuccessOrExit(error = aIncommingMessage.Read(offset, extTlv));
|
||||
length = extTlv.GetLength();
|
||||
offset += sizeof(ot::ExtendedTlv);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = tlv.GetLength();
|
||||
offset += sizeof(ot::Tlv);
|
||||
}
|
||||
|
||||
if (!CanProcessTlv(tlv.GetType()))
|
||||
{
|
||||
error = kErrorRejected;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (tlv.GetType())
|
||||
{
|
||||
case kTlvDisconnect:
|
||||
error = kErrorAbort;
|
||||
break;
|
||||
|
||||
case kTlvSetActiveOperationalDataset:
|
||||
error = HandleSetActiveOperationalDataset(aIncommingMessage, offset, length);
|
||||
break;
|
||||
|
||||
case kTlvStartThreadInterface:
|
||||
error = HandleStartThreadInterface();
|
||||
break;
|
||||
|
||||
case kTlvStopThreadInterface:
|
||||
error = otThreadSetEnabled(&GetInstance(), false);
|
||||
break;
|
||||
|
||||
case kTlvSendApplicationData:
|
||||
LogInfo("Application data len:%d, offset:%d", length, offset);
|
||||
mAppDataReceiveCallback.InvokeIfSet(&GetInstance(), &aIncommingMessage, offset,
|
||||
MapEnum(mCurrentApplicationProtocol), mCurrentServiceName);
|
||||
response = true;
|
||||
error = kErrorNone;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = kErrorInvalidCommand;
|
||||
}
|
||||
}
|
||||
|
||||
if (!response)
|
||||
{
|
||||
StatusCode statusCode;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case kErrorNone:
|
||||
statusCode = kStatusSuccess;
|
||||
break;
|
||||
|
||||
case kErrorInvalidState:
|
||||
statusCode = kStatusUndefined;
|
||||
break;
|
||||
|
||||
case kErrorParse:
|
||||
statusCode = kStatusParseError;
|
||||
break;
|
||||
|
||||
case kErrorInvalidCommand:
|
||||
statusCode = kStatusUnsupported;
|
||||
break;
|
||||
|
||||
case kErrorRejected:
|
||||
statusCode = kStatusUnauthorized;
|
||||
break;
|
||||
|
||||
case kErrorNotImplemented:
|
||||
statusCode = kStatusUnsupported;
|
||||
break;
|
||||
|
||||
default:
|
||||
statusCode = kStatusGeneralError;
|
||||
break;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = ot::Tlv::Append<ResponseWithStatusTlv>(aOutgoingMessage, statusCode));
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncommingMessage, uint16_t aOffset, uint16_t aLength)
|
||||
{
|
||||
Dataset dataset;
|
||||
otOperationalDatasetTlvs datasetTlvs;
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = dataset.ReadFromMessage(aIncommingMessage, aOffset, aLength));
|
||||
|
||||
if (!CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags,
|
||||
mDeviceAuthorizationField.mApplicationFlags, &dataset))
|
||||
{
|
||||
error = kErrorRejected;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
dataset.ConvertTo(datasetTlvs);
|
||||
error = Get<ActiveDatasetManager>().Save(datasetTlvs);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error TcatAgent::HandleStartThreadInterface(void)
|
||||
{
|
||||
Error error;
|
||||
Dataset::Info datasetInfo;
|
||||
|
||||
VerifyOrExit(Get<ActiveDatasetManager>().Read(datasetInfo) == kErrorNone, error = kErrorInvalidState);
|
||||
VerifyOrExit(datasetInfo.IsNetworkKeyPresent(), error = kErrorInvalidState);
|
||||
|
||||
#if OPENTHREAD_CONFIG_LINK_RAW_ENABLE
|
||||
VerifyOrExit(!Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
|
||||
#endif
|
||||
|
||||
Get<ThreadNetif>().Up();
|
||||
error = Get<Mle::MleRouter>().Start();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
|
||||
void TcatAgent::LogError(const char *aActionText, Error aError)
|
||||
{
|
||||
if (aError != kErrorNone)
|
||||
{
|
||||
LogWarn("Failed to %s: %s", aActionText, ErrorToString(aError));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Implements the TCAT Agent service.
|
||||
*/
|
||||
|
||||
#ifndef TCAT_AGENT_HPP_
|
||||
#define TCAT_AGENT_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#include <openthread/tcat.h>
|
||||
#include <openthread/platform/ble.h>
|
||||
|
||||
#include "common/as_core_type.hpp"
|
||||
#include "common/callback.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "common/log.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "common/non_copyable.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
#include "meshcop/dataset.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "meshcop/meshcop_tlvs.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Ble {
|
||||
class BleSecure;
|
||||
}
|
||||
|
||||
namespace MeshCoP {
|
||||
|
||||
class TcatAgent : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Pointer to call when application data was received over the TLS connection.
|
||||
*
|
||||
* Please see otHandleTcatApplicationDataReceive for details.
|
||||
*
|
||||
*/
|
||||
typedef otHandleTcatApplicationDataReceive AppDataReceiveCallback;
|
||||
|
||||
/**
|
||||
* Pointer to call to notify the completion of a join operation.
|
||||
*
|
||||
* Please see otHandleTcatJoin for details.
|
||||
*
|
||||
*/
|
||||
typedef otHandleTcatJoin JoinCallback;
|
||||
|
||||
/**
|
||||
* Represents a TCAT command class.
|
||||
*
|
||||
*/
|
||||
enum CommandClass
|
||||
{
|
||||
kGeneral = OT_TCAT_COMMAND_CLASS_GENERAL, ///< TCAT commands related to general operations
|
||||
kCommissioning = OT_TCAT_COMMAND_CLASS_COMMISSIONING, ///< TCAT commands related to commissioning
|
||||
kExtraction = OT_TCAT_COMMAND_CLASS_EXTRACTION, ///< TCAT commands related to key extraction
|
||||
kTlvDecommissioning = OT_TCAT_COMMAND_CLASS_DECOMMISSIONING, ///< TCAT commands related to de-commissioning
|
||||
kApplication = OT_TCAT_COMMAND_CLASS_APPLICATION, ///< TCAT commands related to application layer
|
||||
kInvalid ///< TCAT command belongs to reserved pool or is invalid
|
||||
};
|
||||
|
||||
/**
|
||||
* The certificate authorization field header type to indicate the type and version of the certificate.
|
||||
*
|
||||
*/
|
||||
enum CertificateAuthorizationFieldHeader : uint8_t
|
||||
{
|
||||
kCommissionerFlag = 1 << 0, ///< TCAT commissioner ('1') or device ('0')
|
||||
kHeaderVersion = 0xD0, ///< Header version (3 bits)
|
||||
};
|
||||
|
||||
/**
|
||||
* The command class flag type to indicate which requirements apply for a given command class.
|
||||
*
|
||||
*/
|
||||
enum CommandClassFlags : uint8_t
|
||||
{
|
||||
kAccessFlag = 1 << 0, ///< Access to the command class (device: without without additional requirements).
|
||||
kPskdFlag = 1 << 1, ///< Access requires proof-of-possession of the device's PSKd
|
||||
kNetworkNameFlag = 1 << 2, ///< Access requires matching network name
|
||||
kExtendedPanIdFlag = 1 << 3, ///< Access requires matching XPANID
|
||||
kThreadDomainFlag = 1 << 4, ///< Access requires matching XPANID
|
||||
kPskcFlag = 1 << 5, ///< Access requires proof-of-possession of the device's PSKc
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a data structure for storing TCAT Commissioner authorization information in the
|
||||
* certificate ASN.1 field 1.3.6.1.4.1.44970.3.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct CertificateAuthorizationField
|
||||
{
|
||||
CertificateAuthorizationFieldHeader mHeader; ///< Typ and version
|
||||
CommandClassFlags mCommissioningFlags; ///< Command class flags
|
||||
CommandClassFlags mExtractionFlags; ///< Command class flags
|
||||
CommandClassFlags mDecommissioningFlags; ///< Command class flags
|
||||
CommandClassFlags mApplicationFlags; ///< Command class flags
|
||||
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
typedef CertificateAuthorizationField CertificateAuthorizationField;
|
||||
|
||||
/**
|
||||
* Represents the TCAT vendor information.
|
||||
*
|
||||
*/
|
||||
class VendorInfo : public otTcatVendorInfo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Validates whether the TCAT vendor information is valid.
|
||||
*
|
||||
* @returns Whether the parameters are valid.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* TCAT TLV Types.
|
||||
*
|
||||
*/
|
||||
enum TlvType : uint8_t
|
||||
{
|
||||
// Command Class General
|
||||
kTlvResponseWithStatus = 1, ///< TCAT response with status value TLV
|
||||
kTlvResponseWithPayload = 2, ///< TCAT response with payload TLV
|
||||
kTlvResponseEvent = 3, ///< TCAT response event TLV (reserved)
|
||||
kTlvGetNetworkName = 8, ///< TCAT network name query TLV
|
||||
kTlvDisconnect = 9, ///< TCAT disconnect request TLV
|
||||
kTlvPing = 10, ///< TCAT ping request TLV
|
||||
kTlvGetDeviceId = 11, ///< TCAT device ID query TLV
|
||||
kTlvGetExtendedPanID = 12, ///< TCAT extended PAN ID query TLV
|
||||
kTlvPresentPskdHash = 16, ///< TCAT commissioner rights elevation request TLV using PSKd hash
|
||||
kTlvPresentPskcHash = 17, ///< TCAT commissioner rights elevation request TLV using PSKc hash
|
||||
kTlvPresentInstallCodeHash = 18, ///< TCAT commissioner rights elevation request TLV using install code
|
||||
kTlvRequestRandomNumChallenge = 19, ///< TCAT random number challenge query TLV
|
||||
kTlvRequestPskdHash = 20, ///< TCAT PSKd hash request TLV
|
||||
|
||||
// Command Class Commissioning
|
||||
kTlvSetActiveOperationalDataset = 32, ///< TCAT active operational dataset TLV
|
||||
kTlvSetActiveOperationalDatasetAlternative = 33, ///< TCAT active operational dataset alternative #1 TLV
|
||||
kTlvGetProvisioningTlvs = 36, ///< TCAT provisioning TLVs query TLV
|
||||
kTlvGetCommissionerCertificate = 37, ///< TCAT commissioner certificate query TLV
|
||||
kTlvGetDiagnosticTlvs = 38, ///< TCAT diagnostics TLVs query TLV
|
||||
kTlvStartThreadInterface = 39, ///< TCAT start thread interface request TLV
|
||||
kTlvStopThreadInterface = 40, ///< TCAT stop thread interface request TLV
|
||||
|
||||
// Command Class Extraction
|
||||
kTlvGetActiveOperationalDataset = 64, ///< TCAT active oerational dataset query TLV
|
||||
kTlvGetActiveOperationalDatasetAlternative = 65, ///< TCAT active oerational dataset alternative #1 query TLV
|
||||
|
||||
// Command Class Decommissioning
|
||||
kTlvDecommission = 96, ///< TCAT decommission request TLV
|
||||
|
||||
// Command Class Application
|
||||
kTlvSelectApplicationLayerUdp = 128, ///< TCAT select UDP protocol application layer request TLV
|
||||
kTlvSelectApplicationLayerTcp = 129, ///< TCAT select TCP protocol application layer request TLV
|
||||
kTlvSendApplicationData = 130, ///< TCAT send application data TLV
|
||||
kTlvSendVendorSpecificData = 159, ///< TCAT send vendor specific command or data TLV
|
||||
|
||||
// Command Class CCM
|
||||
kTlvSetLDevIdOperationalCert = 160, ///< TCAT LDevID operational certificate TLV
|
||||
kTlvSetLDevIdPrivateKey = 161, ///< TCAT LDevID operational certificate pricate key TLV
|
||||
kTlvSetDomainCaCert = 162, ///< TCAT domain CA certificate TLV
|
||||
};
|
||||
|
||||
/**
|
||||
* TCAT Response Types.
|
||||
*
|
||||
*/
|
||||
enum StatusCode : uint8_t
|
||||
{
|
||||
kStatusSuccess = OT_TCAT_STATUS_SUCCESS, ///< Command or request was successfully processed
|
||||
kStatusUnsupported = OT_TCAT_STATUS_UNSUPPORTED, ///< Requested command or received TLV is not supported
|
||||
kStatusParseError = OT_TCAT_STATUS_PARSE_ERROR, ///< Request / command could not be parsed correctly
|
||||
kStatusValueError = OT_TCAT_STATUS_VALUE_ERROR, ///< The value of the transmitted TLV has an error
|
||||
kStatusGeneralError = OT_TCAT_STATUS_GENERAL_ERROR, ///< An error not matching any other category occurred
|
||||
kStatusBusy = OT_TCAT_STATUS_BUSY, ///< Command cannot be executed because the resource is busy
|
||||
kStatusUndefined = OT_TCAT_STATUS_UNDEFINED, ///< The requested value, data or service is not defined
|
||||
///< (currently) or not present
|
||||
kStatusHashError = OT_TCAT_STATUS_HASH_ERROR, ///< The hash value presented by the commissioner was incorrect
|
||||
kStatusUnauthorized =
|
||||
OT_TCAT_STATUS_UNAUTHORIZED, ///< Sender does not have sufficient authorization for the given command
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents TCAT application protocol.
|
||||
*
|
||||
*/
|
||||
enum TcatApplicationProtocol : uint8_t
|
||||
{
|
||||
kApplicationProtocolNone =
|
||||
OT_TCAT_APPLICATION_PROTOCOL_NONE, ///< Message which has been sent without activating the TCAT agent
|
||||
kApplicationProtocolUdp = OT_TCAT_APPLICATION_PROTOCOL_STATUS, ///< Message directed to a UDP service
|
||||
kApplicationProtocolTcp = OT_TCAT_APPLICATION_PROTOCOL_TCP, ///< Message directed to a TCP service
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a TCAT certificate V3 extension attribute (OID 1.3.6.1.4.1.44970.x).
|
||||
*
|
||||
*/
|
||||
enum TcatCertificateAttribute
|
||||
{
|
||||
kCertificateDomainName = 1,
|
||||
kCertificateAuthorizationField = 3,
|
||||
kCertificateNetworkName = 4,
|
||||
kCertificateExtendedPanId = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents TCAT status.
|
||||
*
|
||||
*/
|
||||
enum State : uint8_t
|
||||
{
|
||||
kStateDisabled,
|
||||
kStateEnabled,
|
||||
kStateConnected,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the Joiner object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the OpenThread instance.
|
||||
*
|
||||
*/
|
||||
explicit TcatAgent(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* Enables the TCAT protocol.
|
||||
*
|
||||
* @param[in] aVendorInfo A pointer to the Vendor Information (must remain valid after the method
|
||||
* call, may be NULL).
|
||||
* @param[in] aAppDataReceiveCallback A pointer to a function that is called when the user data is received.
|
||||
* @param[in] aHandler A pointer to a function that is called when the join operation completes.
|
||||
* @param[in] aContext A context pointer.
|
||||
*
|
||||
* @retval kErrorNone Successfully started the TCAT agent.
|
||||
* @retval kErrorInvalidArgs The aVendorInfo is invalid.
|
||||
*
|
||||
*/
|
||||
Error Start(const VendorInfo &aVendorInfo,
|
||||
AppDataReceiveCallback aAppDataReceiveCallback,
|
||||
JoinCallback aHandler,
|
||||
void *aContext);
|
||||
|
||||
/**
|
||||
* Stops the TCAT protocol.
|
||||
*
|
||||
*/
|
||||
void Stop(void);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TCAT agent is enabled.
|
||||
*
|
||||
* @retval TRUE The TCAT agent is enabled.
|
||||
* @retval FALSE The TCAT agent is not enabled.
|
||||
*
|
||||
*/
|
||||
bool IsEnabled(void) const { return mState != kStateDisabled; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TCAT agent is connected.
|
||||
*
|
||||
* @retval TRUE The TCAT agent is connected.
|
||||
* @retval FALSE The TCAT agent is not connected.
|
||||
*
|
||||
*/
|
||||
bool IsConnected(void) const { return mState == kStateConnected; }
|
||||
|
||||
/**
|
||||
* Indicates whether or not a command class is authorized.
|
||||
*
|
||||
* @param[in] aCommandClass Command class to subject for authorization check.
|
||||
*
|
||||
* @retval TRUE The command class is authorized.
|
||||
* @retval FALSE The command class is not authorized.
|
||||
*
|
||||
*/
|
||||
bool IsCommandClassAuthorized(CommandClass aCommandClass) const;
|
||||
|
||||
private:
|
||||
Error Connected(MeshCoP::SecureTransport &aTlsContext);
|
||||
void Disconnected(void);
|
||||
|
||||
Error HandleSingleTlv(const Message &aIncommingMessage, Message &aOutgoingMessage);
|
||||
Error HandleSetActiveOperationalDataset(const Message &aIncommingMessage, uint16_t aOffset, uint16_t aLength);
|
||||
Error HandleStartThreadInterface(void);
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_WARN)
|
||||
void LogError(const char *aActionText, Error aError);
|
||||
#else
|
||||
void LogError(const char *, Error) {}
|
||||
#endif
|
||||
|
||||
bool CheckCommandClassAuthorizationFlags(CommandClassFlags aCommissionerCommandClassFlags,
|
||||
CommandClassFlags aDeviceCommandClassFlags,
|
||||
Dataset *aDataset) const;
|
||||
bool CanProcessTlv(uint8_t aTlvType) const;
|
||||
CommandClass GetCommandClass(uint8_t aTlvType) const;
|
||||
|
||||
static constexpr uint16_t kJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
|
||||
|
||||
JoinerPskd mJoinerPskd;
|
||||
const VendorInfo *mVendorInfo;
|
||||
Callback<JoinCallback> mJoinCallback;
|
||||
Callback<AppDataReceiveCallback> mAppDataReceiveCallback;
|
||||
CertificateAuthorizationField mCommissionerAuthorizationField;
|
||||
CertificateAuthorizationField mDeviceAuthorizationField;
|
||||
TcatApplicationProtocol mCurrentApplicationProtocol;
|
||||
NetworkName mCommissionerNetworkName;
|
||||
NetworkName mCommissionerDomainName;
|
||||
ExtendedPanId mCommissionerExtendedPanId;
|
||||
char mCurrentServiceName[OT_TCAT_MAX_SERVICE_NAME_LENGTH + 1];
|
||||
State mState;
|
||||
bool mAlreadyCommissioned : 1;
|
||||
bool mCommissionerHasNetworkName : 1;
|
||||
bool mCommissionerHasDomainName : 1;
|
||||
bool mCommissionerHasExtendedPanId : 1;
|
||||
|
||||
friend class Ble::BleSecure;
|
||||
};
|
||||
|
||||
} // namespace MeshCoP
|
||||
|
||||
DefineCoreType(otTcatVendorInfo, MeshCoP::TcatAgent::VendorInfo);
|
||||
|
||||
DefineMapEnum(otTcatApplicationProtocol, MeshCoP::TcatAgent::TcatApplicationProtocol);
|
||||
|
||||
typedef UintTlvInfo<MeshCoP::TcatAgent::kTlvResponseWithStatus, uint8_t> ResponseWithStatusTlv;
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#endif // TCAT_AGENT_HPP_
|
||||
@@ -88,7 +88,6 @@
|
||||
#include "config/dns_client.h"
|
||||
#include "config/dns_dso.h"
|
||||
#include "config/dnssd_server.h"
|
||||
#include "config/dtls.h"
|
||||
#include "config/history_tracker.h"
|
||||
#include "config/ip6.h"
|
||||
#include "config/joiner.h"
|
||||
@@ -109,6 +108,7 @@
|
||||
#include "config/platform.h"
|
||||
#include "config/power_calibration.h"
|
||||
#include "config/radio_link.h"
|
||||
#include "config/secure_transport.h"
|
||||
#include "config/sntp_client.h"
|
||||
#include "config/srp_client.h"
|
||||
#include "config/srp_server.h"
|
||||
|
||||
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
#include "ble_secure.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#include <openthread/platform/ble.h>
|
||||
#include "common/locator_getters.hpp"
|
||||
#include "common/log.hpp"
|
||||
#include "common/tlvs.hpp"
|
||||
#include "instance/instance.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
|
||||
using namespace ot;
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the secure Ble agent.
|
||||
*/
|
||||
|
||||
namespace ot {
|
||||
namespace Ble {
|
||||
|
||||
RegisterLogModule("BleSecure");
|
||||
|
||||
BleSecure::BleSecure(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mTls(aInstance, false, false)
|
||||
, mTcatAgent(aInstance)
|
||||
, mTlvMode(false)
|
||||
, mReceivedMessage(nullptr)
|
||||
, mSendMessage(nullptr)
|
||||
, mTransmitTask(aInstance)
|
||||
, mBleState(kStopped)
|
||||
, mMtuSize(kInitialMtuSize)
|
||||
{
|
||||
}
|
||||
|
||||
Error BleSecure::Start(ConnectCallback aConnectHandler, ReceiveCallback aReceiveHandler, bool aTlvMode, void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(mBleState == kStopped, error = kErrorAlready);
|
||||
|
||||
mConnectCallback.Set(aConnectHandler, aContext);
|
||||
mReceiveCallback.Set(aReceiveHandler, aContext);
|
||||
mTlvMode = aTlvMode;
|
||||
mMtuSize = kInitialMtuSize;
|
||||
|
||||
SuccessOrExit(error = otPlatBleEnable(&GetInstance()));
|
||||
SuccessOrExit(error = otPlatBleGapAdvStart(&GetInstance(), OT_BLE_ADV_INTERVAL_DEFAULT));
|
||||
SuccessOrExit(error = mTls.Open(&BleSecure::HandleTlsReceive, &BleSecure::HandleTlsConnected, this));
|
||||
SuccessOrExit(error = mTls.Bind(HandleTransport, this));
|
||||
|
||||
exit:
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
mBleState = kAdvertising;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
Error BleSecure::TcatStart(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo,
|
||||
MeshCoP::TcatAgent::JoinCallback aJoinHandler)
|
||||
{
|
||||
return mTcatAgent.Start(aVendorInfo, mReceiveCallback.GetHandler(), aJoinHandler, mReceiveCallback.GetContext());
|
||||
}
|
||||
|
||||
void BleSecure::Stop(void)
|
||||
{
|
||||
VerifyOrExit(mBleState != kStopped);
|
||||
SuccessOrExit(otPlatBleGapAdvStop(&GetInstance()));
|
||||
SuccessOrExit(otPlatBleDisable(&GetInstance()));
|
||||
mBleState = kStopped;
|
||||
mMtuSize = kInitialMtuSize;
|
||||
|
||||
if (mTcatAgent.IsEnabled())
|
||||
{
|
||||
mTcatAgent.Stop();
|
||||
}
|
||||
|
||||
mTls.Close();
|
||||
|
||||
mTransmitQueue.DequeueAndFreeAll();
|
||||
|
||||
mConnectCallback.Clear();
|
||||
mReceiveCallback.Clear();
|
||||
|
||||
FreeMessage(mReceivedMessage);
|
||||
mReceivedMessage = nullptr;
|
||||
FreeMessage(mSendMessage);
|
||||
mSendMessage = nullptr;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error BleSecure::Connect(void)
|
||||
{
|
||||
Ip6::SockAddr sockaddr;
|
||||
|
||||
return mTls.Connect(sockaddr);
|
||||
}
|
||||
|
||||
void BleSecure::Disconnect(void)
|
||||
{
|
||||
if (mTls.IsConnected())
|
||||
{
|
||||
mTls.Disconnect();
|
||||
}
|
||||
|
||||
if (mBleState == kConnected)
|
||||
{
|
||||
IgnoreReturnValue(otPlatBleGapDisconnect(&GetInstance()));
|
||||
}
|
||||
}
|
||||
|
||||
void BleSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd)
|
||||
{
|
||||
static_assert(static_cast<uint16_t>(MeshCoP::JoinerPskd::kMaxLength) <=
|
||||
static_cast<uint16_t>(MeshCoP::SecureTransport::kPskMaxLength),
|
||||
"The maximum length of TLS PSK is smaller than joiner PSKd");
|
||||
|
||||
SuccessOrAssert(mTls.SetPsk(reinterpret_cast<const uint8_t *>(aPskd.GetAsCString()), aPskd.GetLength()));
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
Error BleSecure::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength)
|
||||
{
|
||||
Error error;
|
||||
|
||||
VerifyOrExit(aCertLength != nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
error = mTls.GetPeerCertificateBase64(aPeerCert, aCertLength, *aCertLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
Error BleSecure::SendMessage(ot::Message &aMessage)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsConnected(), error = kErrorInvalidState);
|
||||
if (mSendMessage == nullptr)
|
||||
{
|
||||
mSendMessage = Get<MessagePool>().Allocate(Message::kTypeBle);
|
||||
VerifyOrExit(mSendMessage != nullptr, error = kErrorNoBufs);
|
||||
}
|
||||
SuccessOrExit(error = mSendMessage->AppendBytesFromMessage(aMessage, 0, aMessage.GetLength()));
|
||||
SuccessOrExit(error = Flush());
|
||||
|
||||
exit:
|
||||
aMessage.Free();
|
||||
return error;
|
||||
}
|
||||
|
||||
Error BleSecure::Send(uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsConnected(), error = kErrorInvalidState);
|
||||
if (mSendMessage == nullptr)
|
||||
{
|
||||
mSendMessage = Get<MessagePool>().Allocate(Message::kTypeBle);
|
||||
VerifyOrExit(mSendMessage != nullptr, error = kErrorNoBufs);
|
||||
}
|
||||
SuccessOrExit(error = mSendMessage->AppendBytes(aBuf, aLength));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error BleSecure::SendApplicationTlv(uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
if (aLength > Tlv::kBaseTlvMaxLength)
|
||||
{
|
||||
ot::ExtendedTlv tlv;
|
||||
|
||||
tlv.SetType(ot::MeshCoP::TcatAgent::kTlvSendApplicationData);
|
||||
tlv.SetLength(aLength);
|
||||
SuccessOrExit(error = Send(reinterpret_cast<uint8_t *>(&tlv), sizeof(tlv)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ot::Tlv tlv;
|
||||
|
||||
tlv.SetType(ot::MeshCoP::TcatAgent::kTlvSendApplicationData);
|
||||
tlv.SetLength((uint8_t)aLength);
|
||||
SuccessOrExit(error = Send(reinterpret_cast<uint8_t *>(&tlv), sizeof(tlv)));
|
||||
}
|
||||
|
||||
error = Send(aBuf, aLength);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error BleSecure::Flush(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(IsConnected(), error = kErrorInvalidState);
|
||||
VerifyOrExit(mSendMessage->GetLength() != 0, error = kErrorNone);
|
||||
|
||||
mTransmitQueue.Enqueue(*mSendMessage);
|
||||
mTransmitTask.Post();
|
||||
|
||||
mSendMessage = nullptr;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error BleSecure::HandleBleReceive(uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
ot::Message *message = nullptr;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Error error = kErrorNone;
|
||||
|
||||
if ((message = Get<MessagePool>().Allocate(Message::kTypeBle, 0)) == nullptr)
|
||||
{
|
||||
error = kErrorNoBufs;
|
||||
ExitNow();
|
||||
}
|
||||
SuccessOrExit(error = message->AppendBytes(aBuf, aLength));
|
||||
|
||||
// Cannot call Receive(..) directly because Setup(..) and mState are private
|
||||
mTls.HandleUdpReceive(*message, messageInfo);
|
||||
|
||||
exit:
|
||||
FreeMessage(message);
|
||||
return error;
|
||||
}
|
||||
|
||||
void BleSecure::HandleBleConnected(uint16_t aConnectionId)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aConnectionId);
|
||||
|
||||
mBleState = kConnected;
|
||||
|
||||
IgnoreReturnValue(otPlatBleGattMtuGet(&GetInstance(), &mMtuSize));
|
||||
|
||||
mConnectCallback.InvokeIfSet(&GetInstance(), IsConnected(), true);
|
||||
}
|
||||
|
||||
void BleSecure::HandleBleDisconnected(uint16_t aConnectionId)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aConnectionId);
|
||||
|
||||
mBleState = kAdvertising;
|
||||
mMtuSize = kInitialMtuSize;
|
||||
|
||||
if (IsConnected())
|
||||
{
|
||||
Disconnect(); // Stop TLS connection
|
||||
}
|
||||
|
||||
mConnectCallback.InvokeIfSet(&GetInstance(), false, false);
|
||||
}
|
||||
|
||||
Error BleSecure::HandleBleMtuUpdate(uint16_t aMtu)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
if (aMtu <= OT_BLE_ATT_MTU_MAX)
|
||||
{
|
||||
mMtuSize = aMtu;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMtuSize = OT_BLE_ATT_MTU_MAX;
|
||||
error = kErrorInvalidArgs;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void BleSecure::HandleTlsConnected(void *aContext, bool aConnected)
|
||||
{
|
||||
return static_cast<BleSecure *>(aContext)->HandleTlsConnected(aConnected);
|
||||
}
|
||||
|
||||
void BleSecure::HandleTlsConnected(bool aConnected)
|
||||
{
|
||||
if (aConnected)
|
||||
{
|
||||
if (mReceivedMessage == nullptr)
|
||||
{
|
||||
mReceivedMessage = Get<MessagePool>().Allocate(Message::kTypeBle);
|
||||
}
|
||||
|
||||
if (mTcatAgent.IsEnabled())
|
||||
{
|
||||
IgnoreReturnValue(mTcatAgent.Connected(mTls));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeMessage(mReceivedMessage);
|
||||
mReceivedMessage = nullptr;
|
||||
|
||||
if (mTcatAgent.IsEnabled())
|
||||
{
|
||||
mTcatAgent.Disconnected();
|
||||
}
|
||||
}
|
||||
|
||||
mConnectCallback.InvokeIfSet(&GetInstance(), aConnected, true);
|
||||
}
|
||||
|
||||
void BleSecure::HandleTlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
return static_cast<BleSecure *>(aContext)->HandleTlsReceive(aBuf, aLength);
|
||||
}
|
||||
|
||||
void BleSecure::HandleTlsReceive(uint8_t *aBuf, uint16_t aLength)
|
||||
{
|
||||
VerifyOrExit(mReceivedMessage != nullptr);
|
||||
|
||||
if (!mTlvMode)
|
||||
{
|
||||
SuccessOrExit(mReceivedMessage->AppendBytes(aBuf, aLength));
|
||||
mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, 0, OT_TCAT_APPLICATION_PROTOCOL_NONE, "");
|
||||
IgnoreReturnValue(mReceivedMessage->SetLength(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
ot::Tlv tlv;
|
||||
uint32_t requiredBytes = sizeof(Tlv);
|
||||
uint32_t offset;
|
||||
|
||||
while (aLength > 0)
|
||||
{
|
||||
if (mReceivedMessage->GetLength() < requiredBytes)
|
||||
{
|
||||
uint32_t missingBytes = requiredBytes - mReceivedMessage->GetLength();
|
||||
|
||||
if (missingBytes > aLength)
|
||||
{
|
||||
SuccessOrExit(mReceivedMessage->AppendBytes(aBuf, aLength));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(mReceivedMessage->AppendBytes(aBuf, (uint16_t)missingBytes));
|
||||
aLength -= missingBytes;
|
||||
aBuf += missingBytes;
|
||||
}
|
||||
}
|
||||
|
||||
IgnoreReturnValue(mReceivedMessage->Read(0, tlv));
|
||||
|
||||
if (tlv.IsExtended())
|
||||
{
|
||||
ot::ExtendedTlv extTlv;
|
||||
requiredBytes = sizeof(extTlv);
|
||||
|
||||
if (mReceivedMessage->GetLength() < requiredBytes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IgnoreReturnValue(mReceivedMessage->Read(0, extTlv));
|
||||
requiredBytes = extTlv.GetSize();
|
||||
offset = sizeof(extTlv);
|
||||
}
|
||||
else
|
||||
{
|
||||
requiredBytes = tlv.GetSize();
|
||||
offset = sizeof(tlv);
|
||||
}
|
||||
|
||||
if (mReceivedMessage->GetLength() < requiredBytes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// TLV fully loaded
|
||||
|
||||
if (mTcatAgent.IsEnabled())
|
||||
{
|
||||
ot::Message *message;
|
||||
Error error = kErrorNone;
|
||||
|
||||
message = Get<MessagePool>().Allocate(Message::kTypeBle);
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
|
||||
error = mTcatAgent.HandleSingleTlv(*mReceivedMessage, *message);
|
||||
if (message->GetLength() != 0)
|
||||
{
|
||||
IgnoreReturnValue(SendMessage(*message));
|
||||
}
|
||||
|
||||
if (error == kErrorAbort)
|
||||
{
|
||||
Disconnect();
|
||||
Stop();
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mReceivedMessage->SetOffset((uint16_t)offset);
|
||||
mReceiveCallback.InvokeIfSet(&GetInstance(), mReceivedMessage, (int32_t)offset,
|
||||
OT_TCAT_APPLICATION_PROTOCOL_NONE, "");
|
||||
}
|
||||
|
||||
SuccessOrExit(mReceivedMessage->SetLength(0)); // also sets the offset to 0
|
||||
requiredBytes = sizeof(Tlv);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void BleSecure::HandleTransmit(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
ot::Message *message = mTransmitQueue.GetHead();
|
||||
|
||||
VerifyOrExit(message != nullptr);
|
||||
mTransmitQueue.Dequeue(*message);
|
||||
|
||||
if (mTransmitQueue.GetHead() != nullptr)
|
||||
{
|
||||
mTransmitTask.Post();
|
||||
}
|
||||
|
||||
SuccessOrExit(error = mTls.Send(*message, message->GetLength()));
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
{
|
||||
LogNote("Transmit: %s", ErrorToString(error));
|
||||
message->Free();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebg("Transmit: %s", ErrorToString(error));
|
||||
}
|
||||
}
|
||||
|
||||
Error BleSecure::HandleTransport(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
return static_cast<BleSecure *>(aContext)->HandleTransport(aMessage);
|
||||
}
|
||||
|
||||
Error BleSecure::HandleTransport(ot::Message &aMessage)
|
||||
{
|
||||
otBleRadioPacket packet;
|
||||
uint16_t len = aMessage.GetLength();
|
||||
uint16_t offset = 0;
|
||||
Error error = kErrorNone;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
if (len <= mMtuSize - kGattOverhead)
|
||||
{
|
||||
packet.mLength = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.mLength = mMtuSize - kGattOverhead;
|
||||
}
|
||||
|
||||
if (packet.mLength > kPacketBufferSize)
|
||||
{
|
||||
packet.mLength = kPacketBufferSize;
|
||||
}
|
||||
|
||||
IgnoreReturnValue(aMessage.Read(offset, mPacketBuffer, packet.mLength));
|
||||
packet.mValue = mPacketBuffer;
|
||||
packet.mPower = OT_BLE_DEFAULT_POWER;
|
||||
|
||||
SuccessOrExit(error = otPlatBleGattServerIndicate(&GetInstance(), kTxBleHandle, &packet));
|
||||
|
||||
len -= packet.mLength;
|
||||
offset += packet.mLength;
|
||||
}
|
||||
|
||||
aMessage.Free();
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace Ble
|
||||
} // namespace ot
|
||||
|
||||
void otPlatBleGattServerOnWriteRequest(otInstance *aInstance, uint16_t aHandle, const otBleRadioPacket *aPacket)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aHandle); // Only a single handle is expected for RX
|
||||
|
||||
VerifyOrExit(aPacket != nullptr);
|
||||
IgnoreReturnValue(AsCoreType(aInstance).Get<Ble::BleSecure>().HandleBleReceive(aPacket->mValue, aPacket->mLength));
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void otPlatBleGapOnConnected(otInstance *aInstance, uint16_t aConnectionId)
|
||||
{
|
||||
AsCoreType(aInstance).Get<Ble::BleSecure>().HandleBleConnected(aConnectionId);
|
||||
}
|
||||
|
||||
void otPlatBleGapOnDisconnected(otInstance *aInstance, uint16_t aConnectionId)
|
||||
{
|
||||
AsCoreType(aInstance).Get<Ble::BleSecure>().HandleBleDisconnected(aConnectionId);
|
||||
}
|
||||
|
||||
void otPlatBleGattOnMtuUpdate(otInstance *aInstance, uint16_t aMtu)
|
||||
{
|
||||
IgnoreReturnValue(AsCoreType(aInstance).Get<Ble::BleSecure>().HandleBleMtuUpdate(aMtu));
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
@@ -0,0 +1,489 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
#ifndef BLE_SECURE_HPP_
|
||||
#define BLE_SECURE_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#include <openthread/ble_secure.h>
|
||||
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "meshcop/secure_transport.hpp"
|
||||
#include "meshcop/tcat_agent.hpp"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Includes definitions for the secure BLE agent.
|
||||
*/
|
||||
|
||||
namespace ot {
|
||||
|
||||
namespace Ble {
|
||||
|
||||
class BleSecure : public InstanceLocator, private NonCopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Pointer to call when the secure BLE connection state changes.
|
||||
*
|
||||
* Please see otHandleBleSecureConnect for details.
|
||||
*
|
||||
*/
|
||||
typedef otHandleBleSecureConnect ConnectCallback;
|
||||
|
||||
/**
|
||||
* Pointer to call when data was received over the TLS connection.
|
||||
* If line mode is activated the function is called only after EOL has been received.
|
||||
*
|
||||
* Please see otHandleBleSecureReceive for details.
|
||||
*
|
||||
*/
|
||||
typedef otHandleBleSecureReceive ReceiveCallback;
|
||||
|
||||
/**
|
||||
* Represents a TCAT command class.
|
||||
*
|
||||
*/
|
||||
typedef MeshCoP::TcatAgent::CommandClass CommandClass;
|
||||
|
||||
/**
|
||||
* Constructor initializes the object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the OpenThread instance.
|
||||
*
|
||||
*/
|
||||
explicit BleSecure(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* Starts the secure BLE agent.
|
||||
*
|
||||
* @param[in] aConnectHandler A pointer to a function that will be called when the connection
|
||||
* state changes.
|
||||
* @param[in] aReceiveHandler A pointer to a function that will be called once data has been received
|
||||
* over the TLS connection.
|
||||
* @param[in] aTlvMode A boolean value indicating if line mode shall be activated.
|
||||
* @param[in] aContext A pointer to arbitrary context information. May be NULL if not used.
|
||||
*
|
||||
* @retval kErrorNone Successfully started the BLE agent.
|
||||
* @retval kErrorAlready Already started.
|
||||
*
|
||||
*/
|
||||
Error Start(ConnectCallback aConnectHandler, ReceiveCallback aReceiveHandler, bool aTlvMode, void *aContext);
|
||||
|
||||
/**
|
||||
* Enables the TCAT protocol over BLE Secure.
|
||||
*
|
||||
* @param[in] aVendorInfo A reference to the Vendor Information (must remain valid after the method call)
|
||||
* @param[in] aHandler Callback to a function that is called when the join operation completes.
|
||||
*
|
||||
* @retval kErrorNone Successfully started the BLE Secure Joiner role.
|
||||
* @retval kErrorInvalidArgs The aVendorInfo is invalid.
|
||||
* @retval kErrorInvaidState The BLE function has not been started or line mode is not selected.
|
||||
*
|
||||
*/
|
||||
Error TcatStart(const MeshCoP::TcatAgent::VendorInfo &aVendorInfo, MeshCoP::TcatAgent::JoinCallback aHandler);
|
||||
|
||||
/**
|
||||
* Stops the secure BLE agent.
|
||||
*
|
||||
*/
|
||||
void Stop(void);
|
||||
|
||||
/**
|
||||
* Initializes TLS session with a peer using an already open BLE connection.
|
||||
*
|
||||
* @retval kErrorNone Successfully started TLS connection.
|
||||
*
|
||||
*/
|
||||
Error Connect(void);
|
||||
|
||||
/**
|
||||
* Stops the BLE and TLS connection.
|
||||
*
|
||||
*/
|
||||
void Disconnect(void);
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TLS session is active (connected or conneting).
|
||||
*
|
||||
* @retval TRUE If TLS session is active.
|
||||
* @retval FALSE If TLS session is not active.
|
||||
*
|
||||
*/
|
||||
bool IsConnectionActive(void) const { return mTls.IsConnectionActive(); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TLS session is connected.
|
||||
*
|
||||
* @retval TRUE The TLS session is connected.
|
||||
* @retval FALSE The TLS session is not connected.
|
||||
*
|
||||
*/
|
||||
bool IsConnected(void) const { return mTls.IsConnected(); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not the TCAT agent is enabled.
|
||||
*
|
||||
* @retval TRUE The TCAT agent is enabled.
|
||||
* @retval FALSE The TCAT agent is not enabled.
|
||||
*
|
||||
*/
|
||||
bool IsTcatEnabled(void) const { return mTcatAgent.IsEnabled(); }
|
||||
|
||||
/**
|
||||
* Indicates whether or not a TCAT command class is authorized.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCommandClass A command class to check.
|
||||
*
|
||||
* @retval TRUE The command class is authorized.
|
||||
* @retval FALSE The command class is not authorized.
|
||||
*
|
||||
*/
|
||||
bool IsCommandClassAuthorized(CommandClass aCommandClass) const
|
||||
{
|
||||
return mTcatAgent.IsCommandClassAuthorized(aCommandClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the PSK.
|
||||
*
|
||||
* @param[in] aPsk A pointer to the PSK.
|
||||
* @param[in] aPskLength The PSK length.
|
||||
*
|
||||
* @retval kErrorNone Successfully set the PSK.
|
||||
* @retval kErrorInvalidArgs The PSK is invalid.
|
||||
*
|
||||
*/
|
||||
Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength) { return mTls.SetPsk(aPsk, aPskLength); }
|
||||
|
||||
/**
|
||||
* Sets the PSK.
|
||||
*
|
||||
* @param[in] aPskd A Joiner PSKd.
|
||||
*
|
||||
*/
|
||||
void SetPsk(const MeshCoP::JoinerPskd &aPskd);
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
/**
|
||||
* Sets the Pre-Shared Key (PSK) for TLS sessions identified by a PSK.
|
||||
*
|
||||
* TLS mode "TLS with AES 128 CCM 8" for secure BLE.
|
||||
*
|
||||
* @param[in] aPsk A pointer to the PSK.
|
||||
* @param[in] aPskLength The PSK char length.
|
||||
* @param[in] aPskIdentity The Identity Name for the PSK.
|
||||
* @param[in] aPskIdLength The PSK Identity Length.
|
||||
*
|
||||
*/
|
||||
void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength)
|
||||
{
|
||||
mTls.SetPreSharedKey(aPsk, aPskLength, aPskIdentity, aPskIdLength);
|
||||
}
|
||||
#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
/**
|
||||
* Sets a X509 certificate with corresponding private key for TLS session.
|
||||
*
|
||||
* TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
|
||||
*
|
||||
* @param[in] aX509Cert A pointer to the PEM formatted X509 PEM certificate.
|
||||
* @param[in] aX509Length The length of certificate.
|
||||
* @param[in] aPrivateKey A pointer to the PEM formatted private key.
|
||||
* @param[in] aPrivateKeyLength The length of the private key.
|
||||
*
|
||||
*/
|
||||
void SetCertificate(const uint8_t *aX509Cert,
|
||||
uint32_t aX509Length,
|
||||
const uint8_t *aPrivateKey,
|
||||
uint32_t aPrivateKeyLength)
|
||||
{
|
||||
mTls.SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the trusted top level CAs. It is needed for validate the certificate of the peer.
|
||||
*
|
||||
* TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
|
||||
*
|
||||
* @param[in] aX509CaCertificateChain A pointer to the PEM formatted X509 CA chain.
|
||||
* @param[in] aX509CaCertChainLength The length of chain.
|
||||
*
|
||||
*/
|
||||
void SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength)
|
||||
{
|
||||
mTls.SetCaCertificateChain(aX509CaCertificateChain, aX509CaCertChainLength);
|
||||
}
|
||||
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
|
||||
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/**
|
||||
* Returns the peer x509 certificate base64 encoded.
|
||||
*
|
||||
* TLS mode "ECDHE ECDSA with AES 128 CCM 8" for secure BLE.
|
||||
*
|
||||
* @param[out] aPeerCert A pointer to the base64 encoded certificate buffer.
|
||||
* @param[out] aCertLength On input, the size the max size of @p aPeerCert.
|
||||
* On output, the length of the base64 encoded peer certificate.
|
||||
*
|
||||
* @retval kErrorNone Successfully get the peer certificate.
|
||||
* @retval kErrorInvalidArgs @p aInstance or @p aCertLength is invalid.
|
||||
* @retval kErrorInvalidState Not connected yet.
|
||||
* @retval kErrorNoBufs Can't allocate memory for certificate.
|
||||
*
|
||||
*/
|
||||
Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength);
|
||||
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/**
|
||||
* Returns an attribute value identified by its OID from the subject
|
||||
* of the peer x509 certificate. The peer OID is provided in binary format.
|
||||
* The attribute length is set if the attribute was successfully read or zero
|
||||
* if unsuccessful. The ASN.1 type as is set as defineded in the ITU-T X.690 standard
|
||||
* if the attribute was successfully read.
|
||||
*
|
||||
* @param[in] aOid A pointer to the OID to be found.
|
||||
* @param[in] aOidLength The length of the OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
* @param[out] aAsn1Type A pointer to the ASN.1 type of the attribute written to the buffer.
|
||||
*
|
||||
* @retval kErrorInvalidState Not connected yet.
|
||||
* @retval kErrorNone Successfully read attribute.
|
||||
* @retval kErrorNoBufs Insufficient memory for storing the attribute value.
|
||||
*
|
||||
*/
|
||||
Error GetPeerSubjectAttributeByOid(const char *aOid,
|
||||
size_t aOidLength,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength,
|
||||
int *aAsn1Type)
|
||||
{
|
||||
return mTls.GetPeerSubjectAttributeByOid(aOid, aOidLength, aAttributeBuffer, aAttributeLength, aAsn1Type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
|
||||
* the peer x509 certificate, where the last digit x is set to aThreadOidDescriptor.
|
||||
* The attribute length is set if the attribute was successfully read or zero if unsuccessful.
|
||||
* Requires a connection to be active.
|
||||
*
|
||||
* @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully read attribute.
|
||||
* @retval kErrorNotFound The requested attribute was not found.
|
||||
* @retval kErrorNoBufs Insufficient memory for storing the attribute value.
|
||||
* @retval kErrorInvalidState Not connected yet.
|
||||
* @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127.
|
||||
* @retval kErrorParse The certificate extensions could not be parsed.
|
||||
*
|
||||
*/
|
||||
Error GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
return mTls.GetThreadAttributeFromPeerCertificate(aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
|
||||
}
|
||||
#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
|
||||
/**
|
||||
* Returns an attribute value for the OID 1.3.6.1.4.1.44970.x from the v3 extensions of
|
||||
* the own x509 certificate, where the last digit x is set to aThreadOidDescriptor.
|
||||
* The attribute length is set if the attribute was successfully read or zero if unsuccessful.
|
||||
* Requires a connection to be active.
|
||||
*
|
||||
* @param[in] aThreadOidDescriptor The last digit of the Thread attribute OID.
|
||||
* @param[out] aAttributeBuffer A pointer to the attribute buffer.
|
||||
* @param[in,out] aAttributeLength On input, the size the max size of @p aAttributeBuffer.
|
||||
* On output, the length of the attribute written to the buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully read attribute.
|
||||
* @retval kErrorNotFound The requested attribute was not found.
|
||||
* @retval kErrorNoBufs Insufficient memory for storing the attribute value.
|
||||
* @retval kErrorInvalidState Not connected yet.
|
||||
* @retval kErrorNotImplemented The value of aThreadOidDescriptor is >127.
|
||||
* @retval kErrorParse The certificate extensions could not be parsed.
|
||||
*
|
||||
*/
|
||||
Error GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor,
|
||||
uint8_t *aAttributeBuffer,
|
||||
size_t *aAttributeLength)
|
||||
{
|
||||
return mTls.GetThreadAttributeFromOwnCertificate(aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the authentication mode for the BLE secure connection. It disables or enables the verification
|
||||
* of peer certificate.
|
||||
*
|
||||
* @param[in] aVerifyPeerCertificate true, if the peer certificate should be verified
|
||||
*
|
||||
*/
|
||||
void SetSslAuthMode(bool aVerifyPeerCertificate) { mTls.SetSslAuthMode(aVerifyPeerCertificate); }
|
||||
|
||||
/**
|
||||
* Sends a secure BLE message.
|
||||
*
|
||||
* @param[in] aMessage A pointer to the message to send.
|
||||
*
|
||||
* If the return value is kErrorNone, OpenThread takes ownership of @p aMessage, and the caller should no longer
|
||||
* reference @p aMessage. If the return value is not kErrorNone, the caller retains ownership of @p aMessage,
|
||||
* including freeing @p aMessage if the message buffer is no longer needed.
|
||||
*
|
||||
* @retval kErrorNone Successfully sent message.
|
||||
* @retval kErrorNoBufs Failed to allocate buffer memory.
|
||||
* @retval kErrorInvalidState TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
Error SendMessage(Message &aMessage);
|
||||
|
||||
/**
|
||||
* Sends a secure BLE data packet.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
|
||||
* @param[in] aLength A number indicating the length of the data buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully sent data.
|
||||
* @retval kErrorNoBufs Failed to allocate buffer memory.
|
||||
* @retval kErrorInvalidState TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
Error Send(uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Sends a secure BLE data packet containing a TCAT Send Application Data TLV.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the data to send as the Value of the TCAT Send Application Data TLV.
|
||||
* @param[in] aLength A number indicating the length of the data buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully sent data.
|
||||
* @retval kErrorNoBufs Failed to allocate buffer memory.
|
||||
* @retval kErrorInvalidState TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
Error SendApplicationTlv(uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Sends all remaining bytes in the send buffer.
|
||||
*
|
||||
* @retval kErrorNone Successfully enqueued data into the output interface.
|
||||
* @retval kErrorNoBufs Failed to allocate buffer memory.
|
||||
* @retval kErrorInvalidState TLS connection was not initialized.
|
||||
*
|
||||
*/
|
||||
Error Flush(void);
|
||||
|
||||
/**
|
||||
* Used to pass data received over a BLE link to the secure BLE server.
|
||||
*
|
||||
* @param[in] aBuf A pointer to the data received.
|
||||
* @param[in] aLength A number indicating the length of the data buffer.
|
||||
*
|
||||
*/
|
||||
Error HandleBleReceive(uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* Used to notify the secure BLE server that a BLE Device has been connected.
|
||||
*
|
||||
* @param[in] aConnectionId The identifier of the open connection.
|
||||
*
|
||||
*/
|
||||
void HandleBleConnected(uint16_t aConnectionId);
|
||||
|
||||
/**
|
||||
* Used to notify the secure BLE server that the BLE Device has been disconnected.
|
||||
*
|
||||
* @param[in] aConnectionId The identifier of the open connection.
|
||||
*
|
||||
*/
|
||||
void HandleBleDisconnected(uint16_t aConnectionId);
|
||||
|
||||
/**
|
||||
* Used to notify the secure BLE server that the BLE Device has updated ATT_MTU size.
|
||||
*
|
||||
* @param[in] aMtu The updated ATT_MTU value.
|
||||
*
|
||||
*/
|
||||
Error HandleBleMtuUpdate(uint16_t aMtu);
|
||||
|
||||
private:
|
||||
enum BleState : uint8_t
|
||||
{
|
||||
kStopped = 0, // Ble secure not started.
|
||||
kAdvertising = 1, // Ble secure not advertising.
|
||||
kConnected = 2, // Ble secure not connected.
|
||||
};
|
||||
|
||||
static constexpr uint8_t kInitialMtuSize = 23; // ATT_MTU
|
||||
static constexpr uint8_t kGattOverhead = 3; // BLE GATT payload fits MTU size - 3 bytes
|
||||
static constexpr uint8_t kPacketBufferSize = OT_BLE_ATT_MTU_MAX - kGattOverhead;
|
||||
static constexpr uint16_t kTxBleHandle = 0; // Characteristics Handle for TX (not used)
|
||||
|
||||
static void HandleTlsConnected(void *aContext, bool aConnected);
|
||||
void HandleTlsConnected(bool aConnected);
|
||||
|
||||
static void HandleTlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
|
||||
void HandleTlsReceive(uint8_t *aBuf, uint16_t aLength);
|
||||
|
||||
void HandleTransmit(void);
|
||||
|
||||
static Error HandleTransport(void *aContext, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
Error HandleTransport(ot::Message &aMessage);
|
||||
|
||||
using TxTask = TaskletIn<BleSecure, &BleSecure::HandleTransmit>;
|
||||
|
||||
MeshCoP::SecureTransport mTls;
|
||||
MeshCoP::TcatAgent mTcatAgent;
|
||||
Callback<ConnectCallback> mConnectCallback;
|
||||
Callback<ReceiveCallback> mReceiveCallback;
|
||||
bool mTlvMode;
|
||||
ot::Message *mReceivedMessage;
|
||||
ot::Message *mSendMessage;
|
||||
ot::MessageQueue mTransmitQueue;
|
||||
TxTask mTransmitTask;
|
||||
uint8_t mPacketBuffer[kPacketBufferSize];
|
||||
BleState mBleState;
|
||||
uint16_t mMtuSize;
|
||||
};
|
||||
|
||||
} // namespace Ble
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
#endif // BLE_SECURE_HPP_
|
||||
@@ -97,7 +97,7 @@ void ThreadNetif::Down(void)
|
||||
#if OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
|
||||
Get<Dns::ServiceDiscovery::Server>().Stop();
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
Get<Tmf::SecureAgent>().Stop();
|
||||
#endif
|
||||
IgnoreError(Get<Tmf::Agent>().Stop());
|
||||
|
||||
@@ -271,7 +271,7 @@ Message::Priority Agent::DscpToPriority(uint8_t aDscp)
|
||||
return priority;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
SecureAgent::SecureAgent(Instance &aInstance)
|
||||
: Coap::CoapSecure(aInstance)
|
||||
@@ -329,7 +329,7 @@ bool SecureAgent::HandleResource(const char *aUriPath, Message &aMessage, const
|
||||
return didHandle;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
} // namespace Tmf
|
||||
} // namespace ot
|
||||
|
||||
@@ -214,7 +214,7 @@ private:
|
||||
static Error Filter(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
|
||||
};
|
||||
|
||||
#if OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
|
||||
/**
|
||||
* Implements functionality of the secure TMF agent.
|
||||
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
size_t GetFreeSize(void) const { return mMemory.mFreeSize; }
|
||||
|
||||
private:
|
||||
#if OPENTHREAD_CONFIG_TLS_ENABLE || OPENTHREAD_CONFIG_DTLS_ENABLE
|
||||
#if OPENTHREAD_CONFIG_TLS_ENABLE || OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
|
||||
static constexpr uint16_t kMemorySize = OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE;
|
||||
#else
|
||||
static constexpr uint16_t kMemorySize = OPENTHREAD_CONFIG_HEAP_INTERNAL_SIZE_NO_DTLS;
|
||||
|
||||
@@ -125,6 +125,7 @@ endif()
|
||||
add_library(openthread-posix
|
||||
alarm.cpp
|
||||
backtrace.cpp
|
||||
ble.cpp
|
||||
configuration.cpp
|
||||
config_file.cpp
|
||||
daemon.cpp
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
#include <openthread/platform/ble.h>
|
||||
|
||||
otError otPlatBleEnable(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleDisable(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aInterval);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapAdvStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapDisconnect(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGattMtuGet(otInstance *aInstance, uint16_t *aMtu)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aMtu);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, const otBleRadioPacket *aPacket)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aHandle);
|
||||
OT_UNUSED_VARIABLE(aPacket);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -35,6 +35,9 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
#include <openthread/platform/ble.h>
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -681,5 +684,52 @@ OT_TOOL_WEAK otPlatMcuPowerState otPlatGetMcuPowerState(otInstance *aInstance) {
|
||||
|
||||
OT_TOOL_WEAK otError otPlatSetMcuPowerState(otInstance *aInstance, otPlatMcuPowerState aState) { return OT_ERROR_NONE; }
|
||||
#endif // OPENTHREAD_CONFIG_NCP_ENABLE_MCU_POWER_STATE_CONTROL
|
||||
#ifdef OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
otError otPlatBleEnable(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleDisable(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aInterval);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapAdvStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGapDisconnect(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGattMtuGet(otInstance *aInstance, uint16_t *aMtu)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aMtu);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
otError otPlatBleGattServerIndicate(otInstance *aInstance, uint16_t aHandle, const otBleRadioPacket *aPacket)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aHandle);
|
||||
OT_UNUSED_VARIABLE(aPacket);
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
|
||||
} // extern "C"
|
||||
|
||||
Vendored
+4
@@ -92,6 +92,10 @@
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
|
||||
#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
|
||||
#endif
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
|
||||
Reference in New Issue
Block a user