Skip to content

Commit

Permalink
[tcat] Implement extraction of active dataset and commissioner cert.
Browse files Browse the repository at this point in the history
Commit adds implementation of:
	- 0x40 Tcat tlv extraction of active dataset,
	- 0x25 Tcat tlv extraction of commissioner certificate.

Includes also refactoring of `BleCommand` adds new method `process_response`.
This simplifies:
- `GetPskdHash`
- `GetRandomNumberChallenge`
  • Loading branch information
Przemyslaw Bida committed Dec 4, 2024
1 parent 2868c9c commit 2a5a9a3
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 165 deletions.
20 changes: 20 additions & 0 deletions include/openthread/ble_secure.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,26 @@ void otBleSecureSetPsk(otInstance *aInstance,
*/
otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength);

/**
* Returns the peer x509 certificate base64 encoded.
*
* @note Requires the build-time feature `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to
* be enabled.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[out] aPeerCert A pointer to the DER encoded certificate
* buffer.
* @param[in,out] aCertLength On input, the size the max size of @p
* aPeerCert. On output, the length of the DER 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 otBleSecureGetPeerCertificateRaw(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.
Expand Down
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (465)
#define OPENTHREAD_API_VERSION (466)

/**
* @addtogroup api-instance
Expand Down
27 changes: 14 additions & 13 deletions include/openthread/platform/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,20 @@ extern "C" {
*/
enum
{
OT_SETTINGS_KEY_ACTIVE_DATASET = 0x0001, ///< Active Operational Dataset.
OT_SETTINGS_KEY_PENDING_DATASET = 0x0002, ///< Pending Operational Dataset.
OT_SETTINGS_KEY_NETWORK_INFO = 0x0003, ///< Thread network information.
OT_SETTINGS_KEY_PARENT_INFO = 0x0004, ///< Parent information.
OT_SETTINGS_KEY_CHILD_INFO = 0x0005, ///< Child information.
OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY = 0x0007, ///< SLAAC key to generate semantically opaque IID.
OT_SETTINGS_KEY_DAD_INFO = 0x0008, ///< Duplicate Address Detection (DAD) information.
OT_SETTINGS_KEY_SRP_ECDSA_KEY = 0x000b, ///< SRP client ECDSA public/private key pair.
OT_SETTINGS_KEY_SRP_CLIENT_INFO = 0x000c, ///< The SRP client info (selected SRP server address).
OT_SETTINGS_KEY_SRP_SERVER_INFO = 0x000d, ///< The SRP server info (UDP port).
OT_SETTINGS_KEY_BR_ULA_PREFIX = 0x000f, ///< BR ULA prefix.
OT_SETTINGS_KEY_BR_ON_LINK_PREFIXES = 0x0010, ///< BR local on-link prefixes.
OT_SETTINGS_KEY_BORDER_AGENT_ID = 0x0011, ///< Unique Border Agent/Router ID.
OT_SETTINGS_KEY_ACTIVE_DATASET = 0x0001, ///< Active Operational Dataset.
OT_SETTINGS_KEY_PENDING_DATASET = 0x0002, ///< Pending Operational Dataset.
OT_SETTINGS_KEY_NETWORK_INFO = 0x0003, ///< Thread network information.
OT_SETTINGS_KEY_PARENT_INFO = 0x0004, ///< Parent information.
OT_SETTINGS_KEY_CHILD_INFO = 0x0005, ///< Child information.
OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY = 0x0007, ///< SLAAC key to generate semantically opaque IID.
OT_SETTINGS_KEY_DAD_INFO = 0x0008, ///< Duplicate Address Detection (DAD) information.
OT_SETTINGS_KEY_SRP_ECDSA_KEY = 0x000b, ///< SRP client ECDSA public/private key pair.
OT_SETTINGS_KEY_SRP_CLIENT_INFO = 0x000c, ///< The SRP client info (selected SRP server address).
OT_SETTINGS_KEY_SRP_SERVER_INFO = 0x000d, ///< The SRP server info (UDP port).
OT_SETTINGS_KEY_BR_ULA_PREFIX = 0x000f, ///< BR ULA prefix.
OT_SETTINGS_KEY_BR_ON_LINK_PREFIXES = 0x0010, ///< BR local on-link prefixes.
OT_SETTINGS_KEY_BORDER_AGENT_ID = 0x0011, ///< Unique Border Agent/Router ID.
OT_SETTINGS_KEY_TCAT_COMMISSIONER_CERTIFICATE = 0x0012, ///< Unique TCAT Commissioner certificate.

// Deprecated and reserved key values:
//
Expand Down
5 changes: 5 additions & 0 deletions src/core/api/ble_secure_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)

#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
otError otBleSecureGetPeerCertificateRaw(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength)
{
return AsCoreType(aInstance).Get<Ble::BleSecure>().GetPeerCertificateRaw(aPeerCert, aCertLength);
}

otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance,
const char *aOid,
size_t aOidLength,
Expand Down
51 changes: 33 additions & 18 deletions src/core/common/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

#include "settings.hpp"

#include "common/code_utils.hpp"
#include "common/error.hpp"
#include "instance/instance.hpp"

namespace ot {
Expand Down Expand Up @@ -151,24 +153,25 @@ const char *SettingsBase::ActionToString(Action aAction)
const char *SettingsBase::KeyToString(Key aKey)
{
static const char *const kKeyStrings[] = {
"", // (0) (Unused)
"ActiveDataset", // (1) kKeyActiveDataset
"PendingDataset", // (2) kKeyPendingDataset
"NetworkInfo", // (3) kKeyNetworkInfo
"ParentInfo", // (4) kKeyParentInfo
"ChildInfo", // (5) kKeyChildInfo
"", // (6) Removed (previously auto-start).
"SlaacIidSecretKey", // (7) kKeySlaacIidSecretKey
"DadInfo", // (8) kKeyDadInfo
"", // (9) Removed (previously OMR prefix).
"", // (10) Removed (previously on-link prefix).
"SrpEcdsaKey", // (11) kKeySrpEcdsaKey
"SrpClientInfo", // (12) kKeySrpClientInfo
"SrpServerInfo", // (13) kKeySrpServerInfo
"", // (14) Removed (previously NAT64 prefix)
"BrUlaPrefix", // (15) kKeyBrUlaPrefix
"BrOnLinkPrefixes", // (16) kKeyBrOnLinkPrefixes
"BorderAgentId" // (17) kKeyBorderAgentId
"", // (0) (Unused)
"ActiveDataset", // (1) kKeyActiveDataset
"PendingDataset", // (2) kKeyPendingDataset
"NetworkInfo", // (3) kKeyNetworkInfo
"ParentInfo", // (4) kKeyParentInfo
"ChildInfo", // (5) kKeyChildInfo
"", // (6) Removed (previously auto-start).
"SlaacIidSecretKey", // (7) kKeySlaacIidSecretKey
"DadInfo", // (8) kKeyDadInfo
"", // (9) Removed (previously OMR prefix).
"", // (10) Removed (previously on-link prefix).
"SrpEcdsaKey", // (11) kKeySrpEcdsaKey
"SrpClientInfo", // (12) kKeySrpClientInfo
"SrpServerInfo", // (13) kKeySrpServerInfo
"", // (14) Removed (previously NAT64 prefix)
"BrUlaPrefix", // (15) kKeyBrUlaPrefix
"BrOnLinkPrefixes", // (16) kKeyBrOnLinkPrefixes
"BorderAgentId", // (17) kKeyBorderAgentId
"TcatCommissionerCertificate" // (18) kKeyTcatCommissionerCertificate
};

struct EnumCheck
Expand All @@ -192,6 +195,7 @@ const char *SettingsBase::KeyToString(Key aKey)
ValidateNextEnum(kKeyBrUlaPrefix);
ValidateNextEnum(kKeyBrOnLinkPrefixes);
ValidateNextEnum(kKeyBorderAgentId);
ValidateNextEnum(kKeyTcatCommissionerCertificate);
};

static_assert(kLastKey == kKeyBorderAgentId, "kLastKey is not valid");
Expand Down Expand Up @@ -263,6 +267,17 @@ void Settings::DeleteOperationalDataset(MeshCoP::Dataset::Type aType)
OT_ASSERT(error != kErrorNotImplemented);
}

#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
void Settings::SaveTcatCommissionerCertificate(uint8_t *aCert, uint16_t aCertLen)
{
Error error = Get<SettingsDriver>().Set(kKeyTcatCommissionerCertificate, aCert, aCertLen);

Log(kActionSave, error, kKeyTcatCommissionerCertificate);

SuccessOrAssert(error);
}
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE

#if OPENTHREAD_FTD
Error Settings::AddChildInfo(const ChildInfo &aChildInfo)
{
Expand Down
53 changes: 40 additions & 13 deletions src/core/common/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,19 +106,20 @@ class SettingsBase : public InstanceLocator
*/
enum Key : uint16_t
{
kKeyActiveDataset = OT_SETTINGS_KEY_ACTIVE_DATASET,
kKeyPendingDataset = OT_SETTINGS_KEY_PENDING_DATASET,
kKeyNetworkInfo = OT_SETTINGS_KEY_NETWORK_INFO,
kKeyParentInfo = OT_SETTINGS_KEY_PARENT_INFO,
kKeyChildInfo = OT_SETTINGS_KEY_CHILD_INFO,
kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
kKeyDadInfo = OT_SETTINGS_KEY_DAD_INFO,
kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
kKeySrpClientInfo = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO,
kKeyBrUlaPrefix = OT_SETTINGS_KEY_BR_ULA_PREFIX,
kKeyBrOnLinkPrefixes = OT_SETTINGS_KEY_BR_ON_LINK_PREFIXES,
kKeyBorderAgentId = OT_SETTINGS_KEY_BORDER_AGENT_ID,
kKeyActiveDataset = OT_SETTINGS_KEY_ACTIVE_DATASET,
kKeyPendingDataset = OT_SETTINGS_KEY_PENDING_DATASET,
kKeyNetworkInfo = OT_SETTINGS_KEY_NETWORK_INFO,
kKeyParentInfo = OT_SETTINGS_KEY_PARENT_INFO,
kKeyChildInfo = OT_SETTINGS_KEY_CHILD_INFO,
kKeySlaacIidSecretKey = OT_SETTINGS_KEY_SLAAC_IID_SECRET_KEY,
kKeyDadInfo = OT_SETTINGS_KEY_DAD_INFO,
kKeySrpEcdsaKey = OT_SETTINGS_KEY_SRP_ECDSA_KEY,
kKeySrpClientInfo = OT_SETTINGS_KEY_SRP_CLIENT_INFO,
kKeySrpServerInfo = OT_SETTINGS_KEY_SRP_SERVER_INFO,
kKeyBrUlaPrefix = OT_SETTINGS_KEY_BR_ULA_PREFIX,
kKeyBrOnLinkPrefixes = OT_SETTINGS_KEY_BR_ON_LINK_PREFIXES,
kKeyBorderAgentId = OT_SETTINGS_KEY_BORDER_AGENT_ID,
kKeyTcatCommissionerCertificate = OT_SETTINGS_KEY_TCAT_COMMISSIONER_CERTIFICATE,
};

static constexpr Key kLastKey = kKeyBorderAgentId; ///< The last (numerically) enumerator value in `Key`.
Expand Down Expand Up @@ -802,6 +803,32 @@ class Settings : public SettingsBase, private NonCopyable
*/
void DeleteOperationalDataset(MeshCoP::Dataset::Type aType);

#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
/**
* Stores the Tcat Commissioner certificate.
*
* @param[in] aCert The Dataset type (active or pending) to read.
* @param[in] aCertLen Certificate length.
*
*/
void SaveTcatCommissionerCertificate(uint8_t *aCert, uint16_t aCertLen);

/**
* Reads the Tcat Commissioner certificate.
*
* @param[in] aCert The Dataset type (active or pending) to read.
* @param[out] aCertLen Certificate length.
*
* @retval kErrorNone Successfully read the Dataset.
* @retval kErrorNotFound No corresponding value in the setting store.
* @retval kErrorNoBuffs Buffer has not enough space to store the data.
*/
Error GetTcatCommissionerCertificate(uint8_t *aCert, uint16_t &aCertLen)
{
return Get<SettingsDriver>().Get(kKeyTcatCommissionerCertificate, aCert, &aCertLen);
}
#endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE

/**
* Reads a specified settings entry.
*
Expand Down
28 changes: 28 additions & 0 deletions src/core/meshcop/secure_transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,34 @@ Error SecureTransport::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)

#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
Error SecureTransport::GetPeerCertificateRaw(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
{
Error error = kErrorNone;

VerifyOrExit(IsStateConnected(), error = kErrorInvalidState);

#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
VerifyOrExit(mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len < aCertBufferSize,
error = kErrorNoBufs);

*aCertLength = mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len;
memcpy(aPeerCert, mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p, *aCertLength);

#else
VerifyOrExit(mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len) <
aCertBufferSize,
error = kErrorNoBufs);

*aCertLength = mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len);
memcpy(aPeerCert,
mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
*aCertLength);
#endif

exit:
return error;
}

Error SecureTransport::GetPeerSubjectAttributeByOid(const char *aOid,
size_t aOidLength,
uint8_t *aAttributeBuffer,
Expand Down
13 changes: 13 additions & 0 deletions src/core/meshcop/secure_transport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,19 @@ class SecureTransport : public InstanceLocator
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)

#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/**
* Returns the peer x509 certificate DER encoded.
*
* @param[out] aPeerCert A pointer to the base64 encoded certificate buffer.
* @param[out] aCertLength The length of the base64 encoded peer certificate.
* @param[in] aCertBufferSize The buffer size of aPeerCert.
*
* @retval kErrorInvalidState Not connected yet.
* @retval kErrorNone Successfully get the peer certificate.
* @retval kErrorNoBufs Can't allocate memory for certificate.
*/
Error GetPeerCertificateRaw(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize);

/**
* Returns an attribute value identified by its OID from the subject
* of the peer x509 certificate. The peer OID is provided in binary format.
Expand Down
62 changes: 59 additions & 3 deletions src/core/meshcop/tcat_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/

#include "tcat_agent.hpp"
#include <openthread/platform/settings.h>
#include "common/code_utils.hpp"

#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
Expand Down Expand Up @@ -404,6 +405,10 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncomingMessage, Message &aOutg
error = HandleSetActiveOperationalDataset(aIncomingMessage, offset, length);
break;

case kTlvGetActiveOperationalDataset:
error = HandleGetActiveOperationalDataset(aOutgoingMessage, response);
break;

case kTlvStartThreadInterface:
error = HandleStartThreadInterface();
break;
Expand Down Expand Up @@ -454,6 +459,9 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncomingMessage, Message &aOutg
case kTlvRequestPskdHash:
error = HandleRequestPskdHash(aIncomingMessage, aOutgoingMessage, offset, length, response);
break;
case kTlvGetCommissionerCertificate:
error = HandleGetCommissionerCertificate(aOutgoingMessage, response);
break;
default:
error = kErrorInvalidCommand;
}
Expand Down Expand Up @@ -506,9 +514,11 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncomingMessage, Message &aOutg

Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncomingMessage, uint16_t aOffset, uint16_t aLength)
{
Dataset dataset;
OffsetRange offsetRange;
Error error;
Dataset dataset;
OffsetRange offsetRange;
Error error;
unsigned char buf[1024];
size_t bufLen = sizeof(buf);

offsetRange.Init(aOffset, aLength);
SuccessOrExit(error = dataset.SetFrom(aIncomingMessage, offsetRange));
Expand All @@ -523,6 +533,52 @@ Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncomingMessa

Get<ActiveDatasetManager>().SaveLocal(dataset);

SuccessOrExit(error = otBleSecureGetPeerCertificateRaw(&GetInstance(), buf, &bufLen));
Get<Settings>().SaveTcatCommissionerCertificate(buf, (uint16_t)bufLen);
exit:
return error;
}

Error TcatAgent::HandleGetActiveOperationalDataset(Message &aOutgoingMessage, bool &aResponse)
{
Error error = kErrorNone;
Dataset dataset;
Dataset::Tlvs datasetTlvs;

if (!CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags,
mDeviceAuthorizationField.mApplicationFlags, &dataset))
{
error = kErrorRejected;
ExitNow();
}

SuccessOrExit(error = Get<ActiveDatasetManager>().Read(datasetTlvs));
SuccessOrExit(
error = Tlv::AppendTlv(aOutgoingMessage, kTlvResponseWithPayload, datasetTlvs.mTlvs, datasetTlvs.mLength));
aResponse = true;

exit:
return error;
}

Error TcatAgent::HandleGetCommissionerCertificate(Message &aOutgoingMessage, bool &aResponse)
{
Error error = kErrorNone;
Dataset dataset;
unsigned char buf[1024];
uint16_t bufLen = sizeof(buf);

if (!CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags,
mDeviceAuthorizationField.mApplicationFlags, &dataset))
{
error = kErrorRejected;
ExitNow();
}

VerifyOrExit(kErrorNone == Get<Settings>().GetTcatCommissionerCertificate(buf, bufLen), error = kErrorInvalidState);
SuccessOrExit(error = Tlv::AppendTlv(aOutgoingMessage, kTlvResponseWithPayload, buf, bufLen));
aResponse = true;

exit:
return error;
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/meshcop/tcat_agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ class TcatAgent : public InstanceLocator, private NonCopyable

Error HandleSingleTlv(const Message &aIncomingMessage, Message &aOutgoingMessage);
Error HandleSetActiveOperationalDataset(const Message &aIncomingMessage, uint16_t aOffset, uint16_t aLength);
Error HandleGetActiveOperationalDataset(Message &aOutgoingMessage, bool &aResponse);
Error HandleDecomission(void);
Error HandlePing(const Message &aIncomingMessage,
Message &aOutgoingMessage,
Expand All @@ -359,6 +360,7 @@ class TcatAgent : public InstanceLocator, private NonCopyable
uint16_t aLength,
bool &aResponse);
Error HandleStartThreadInterface(void);
Error HandleGetCommissionerCertificate(Message &aOutgoingMessage, bool &aResponse);

Error VerifyHash(const Message &aIncomingMessage,
uint16_t aOffset,
Expand Down
Loading

0 comments on commit 2a5a9a3

Please sign in to comment.