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 authored and canisLupus1313 committed Jan 10, 2025
1 parent 5ddcb44 commit 8306a37
Show file tree
Hide file tree
Showing 16 changed files with 415 additions and 165 deletions.
21 changes: 21 additions & 0 deletions include/openthread/ble_secure.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,27 @@ void otBleSecureSetPsk(otInstance *aInstance,
*/
otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength);

/**
* Returns the DER encoded peer x509 certificate.
*
* @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 otBleSecureGetPeerCertificateDer(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 (470)
#define OPENTHREAD_API_VERSION (471)

/**
* @addtogroup api-instance
Expand Down
2 changes: 2 additions & 0 deletions include/openthread/platform/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ enum
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, ///< Certificate of the TCAT Commissioner which latest updated the active dataset.

// Deprecated and reserved key values:
//
Expand Down
16 changes: 16 additions & 0 deletions src/core/api/ble_secure_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/

#include "openthread-core-config.h"
#include <openthread/error.h>

#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE

Expand Down Expand Up @@ -87,7 +88,9 @@ otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char
{
Error error;

VerifyOrExit(aPeerCert != nullptr, error = kErrorInvalidArgs);
VerifyOrExit(aCertLength != nullptr, error = kErrorInvalidArgs);

error = AsCoreType(aInstance).Get<Ble::BleSecure>().GetPeerCertificateBase64(aPeerCert, aCertLength, *aCertLength);

exit:
Expand All @@ -96,6 +99,19 @@ otError otBleSecureGetPeerCertificateBase64(otInstance *aInstance, unsigned char
#endif

#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
otError otBleSecureGetPeerCertificateDer(otInstance *aInstance, unsigned char *aPeerCert, size_t *aCertLength)
{
Error error;

VerifyOrExit(aPeerCert != nullptr, error = kErrorInvalidArgs);
VerifyOrExit(aCertLength != nullptr, error = kErrorInvalidArgs);

error = AsCoreType(aInstance).Get<Ble::BleSecure>().GetPeerCertificateDer(aPeerCert, aCertLength, *aCertLength);

exit:
return error;
}

otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance,
const char *aOid,
size_t aOidLength,
Expand Down
53 changes: 34 additions & 19 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,9 +195,10 @@ const char *SettingsBase::KeyToString(Key aKey)
ValidateNextEnum(kKeyBrUlaPrefix);
ValidateNextEnum(kKeyBrOnLinkPrefixes);
ValidateNextEnum(kKeyBorderAgentId);
ValidateNextEnum(kKeyTcatCommissionerCertificate);
};

static_assert(kLastKey == kKeyBorderAgentId, "kLastKey is not valid");
static_assert(kLastKey == kKeyTcatCommissionerCertificate, "kLastKey is not valid");

OT_ASSERT(aKey <= kLastKey);

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
58 changes: 44 additions & 14 deletions src/core/common/settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,22 +106,24 @@ 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`.
static constexpr Key kLastKey =
kKeyTcatCommissionerCertificate; ///< The last (numerically) enumerator value in `Key`.

static_assert(static_cast<uint16_t>(kLastKey) < static_cast<uint16_t>(OT_SETTINGS_KEY_VENDOR_RESERVED_MIN),
"Core settings keys overlap with vendor reserved keys");
Expand Down Expand Up @@ -802,6 +804,34 @@ 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 DER-encoded X509 end-entity certificate to store.
* @param[in] aCertLen Certificate length.
*
*/
void SaveTcatCommissionerCertificate(uint8_t *aCert, uint16_t aCertLen);

/**
* Reads the Tcat Commissioner certificate.
*
* @param[out] aCert Buffer to store the DER-encoded X509 end-entity certificate of the TCAT
* Commissioner
* @param[in,out] aCertLen On input, the max size of @p aCert. On output, the length of the DER encoded peer
* certificate.
*
* @retval kErrorNone Successfully read the Dataset.
* @retval kErrorNotFound No corresponding value in the setting store.
* @retval kErrorNoBufs 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
31 changes: 31 additions & 0 deletions src/core/meshcop/secure_transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,37 @@ Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerC
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)

#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
Error SecureTransport::Extension::GetPeerCertificateDer(uint8_t *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
{
Error error = kErrorNone;
SecureSession *session = mSecureTransport.mSessions.GetHead();

VerifyOrExit(session->IsConnected(), error = kErrorInvalidState);

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

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

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

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

exit:
return error;
}

Error SecureTransport::Extension::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 @@ -435,6 +435,19 @@ class SecureTransport : private NonCopyable
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)

#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/**
* Returns the DER encoded peer x509 certificate.
*
* @param[out] aPeerCert A pointer to the DER encoded certificate buffer.
* @param[out] aCertLength The length of the DER 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 GetPeerCertificateDer(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
Loading

0 comments on commit 8306a37

Please sign in to comment.