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 9, 2024
1 parent 7b72e97 commit db43984
Show file tree
Hide file tree
Showing 17 changed files with 401 additions and 158 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 (465)
#define OPENTHREAD_API_VERSION (466)

/**
* @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
56 changes: 42 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,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
38 changes: 38 additions & 0 deletions src/core/meshcop/secure_transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,44 @@ 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(unsigned char *aPeerCert,
size_t *aCertLength,
size_t aCertBufferSize)
{
Error error = kErrorNone;

VerifyOrExit(mSecureTransport.IsStateConnected(), error = kErrorInvalidState);

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

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

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

*aCertLength = mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)
->MBEDTLS_PRIVATE(peer_cert)
->MBEDTLS_PRIVATE(raw)
.MBEDTLS_PRIVATE(len);
memcpy(aPeerCert,
mSecureTransport.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 @@ -222,6 +222,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 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 db43984

Please sign in to comment.