[secure-transport] introduce Extension class (#10978)

This commit updates `SecureTransport`. It introduces the `Extension`
class within `SecureTransport`, providing support for additional
cipher suites and related methods to configure the ciphers
(e.g., `SetPreSharedKey()`, `SetCertificate()`).

This class decouples this functionality from the common
`SecureTransport` object, allowing it to be added to any class.
Classes like `ApplicationCoapSecure` or `BleSecure` can inherit from
`Extension` to provide these methods. An `Extension` is then
associated with a `SecureTransport` (or any of its subclasses). This
approach ensures that only instances requiring extended cipher suite
support incur the associated memory cost and avoid repeated code.

This commit also introduces `Dtls`, `DtlsExtended`, and `Tls` as
subclasses of `SecureTransport` for easier use by other modules.
This commit is contained in:
Abtin Keshavarzian
2024-12-04 10:19:58 -08:00
committed by Jonathan Hui
parent f0d6007cc3
commit 53c02c6141
17 changed files with 441 additions and 565 deletions
+8 -2
View File
@@ -85,9 +85,15 @@ void otBleSecureSetPsk(otInstance *aInstance,
#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);
Error error;
VerifyOrExit(aCertLength != nullptr, error = kErrorInvalidArgs);
error = AsCoreType(aInstance).Get<Ble::BleSecure>().GetPeerCertificateBase64(aPeerCert, aCertLength, *aCertLength);
exit:
return error;
}
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
#endif
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
otError otBleSecureGetPeerSubjectAttributeByOid(otInstance *aInstance,
+6 -6
View File
@@ -42,9 +42,9 @@ namespace Coap {
RegisterLogModule("CoapSecure");
CoapSecureBase::CoapSecureBase(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity)
CoapSecureBase::CoapSecureBase(Instance &aInstance, MeshCoP::Dtls &aDtls)
: CoapBase(aInstance, Send)
, mDtls(aInstance, aLayerTwoSecurity)
, mDtls(aDtls)
, mTransmitTask(aInstance, HandleTransmit, this)
{
}
@@ -62,7 +62,7 @@ exit:
return error;
}
Error CoapSecureBase::Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext)
Error CoapSecureBase::Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext)
{
Error error;
@@ -106,7 +106,7 @@ Error CoapSecureBase::Connect(const Ip6::SockAddr &aSockAddr, ConnectEventCallba
void CoapSecureBase::SetPsk(const MeshCoP::JoinerPskd &aPskd)
{
static_assert(static_cast<uint16_t>(MeshCoP::JoinerPskd::kMaxLength) <=
static_cast<uint16_t>(MeshCoP::SecureTransport::kPskMaxLength),
static_cast<uint16_t>(MeshCoP::Dtls::kPskMaxLength),
"The maximum length of DTLS PSK is smaller than joiner PSKd");
SuccessOrAssert(mDtls.SetPsk(reinterpret_cast<const uint8_t *>(aPskd.GetAsCString()), aPskd.GetLength()));
@@ -172,12 +172,12 @@ Error CoapSecureBase::Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessa
return kErrorNone;
}
void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext)
void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent, void *aContext)
{
return static_cast<CoapSecureBase *>(aContext)->HandleDtlsConnectEvent(aEvent);
}
void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent)
void CoapSecureBase::HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent)
{
mConnectEventCallback.InvokeIfSet(aEvent);
}
+12 -84
View File
@@ -96,7 +96,7 @@ public:
* @retval kErrorNone Successfully started the CoAP agent.
* @retval kErrorAlready Already started.
*/
Error Start(MeshCoP::SecureTransport::TransportCallback aCallback, void *aContext);
Error Start(MeshCoP::Dtls::TransportCallback aCallback, void *aContext);
/**
* Sets connected callback of this secure CoAP agent.
@@ -159,7 +159,7 @@ public:
*
* @returns A reference to the DTLS object.
*/
MeshCoP::SecureTransport &GetDtls(void) { return mDtls; }
MeshCoP::Dtls &GetDtls(void) { return mDtls; }
/**
* Gets the UDP port of this agent.
@@ -293,7 +293,7 @@ public:
const Ip6::MessageInfo &GetMessageInfo(void) const { return mDtls.GetMessageInfo(); }
protected:
CoapSecureBase(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity);
CoapSecureBase(Instance &aInstance, MeshCoP::Dtls &aDtls);
Error Open(uint16_t aMaxAttempts, AutoStopCallback aCallback, void *aContext);
@@ -304,8 +304,8 @@ protected:
Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext);
void HandleDtlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent);
static void HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent, void *aContext);
void HandleDtlsConnectEvent(MeshCoP::Dtls::ConnectEvent aEvent);
static void HandleDtlsAutoClose(void *aContext);
void HandleDtlsAutoClose(void);
@@ -316,7 +316,7 @@ protected:
static void HandleTransmit(Tasklet &aTasklet);
void HandleTransmit(void);
MeshCoP::SecureTransport mDtls;
MeshCoP::Dtls &mDtls;
Callback<ConnectEventCallback> mConnectEventCallback;
Callback<AutoStopCallback> mAutoStopCallback;
ot::MessageQueue mTransmitQueue;
@@ -328,7 +328,7 @@ protected:
/**
* Represents an Application CoAPS.
*/
class ApplicationCoapSecure : public CoapSecureBase
class ApplicationCoapSecure : public CoapSecureBase, public MeshCoP::Dtls::Extension
{
public:
/**
@@ -338,86 +338,14 @@ public:
* @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not.
*/
ApplicationCoapSecure(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity)
: CoapSecureBase(aInstance, aLayerTwoSecurity)
: CoapSecureBase(aInstance, mDtls)
, MeshCoP::Dtls::Extension(mDtls)
, mDtls(aInstance, aLayerTwoSecurity, *this)
{
}
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
/**
* Sets the Pre-Shared Key (PSK) for DTLS sessions identified by a PSK.
*
* DTLS mode "TLS with AES 128 CCM 8" for Application CoAPS.
*
* @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)
{
mDtls.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 DTLS session.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @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)
{
mDtls.SetCertificate(aX509Cert, aX509Length, aPrivateKey, aPrivateKeyLength);
}
/**
* Sets the trusted top level CAs. It is needed for validate the certificate of the peer.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @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)
{
mDtls.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.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @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 kErrorNone Successfully get the peer certificate.
* @retval kErrorNoBufs Can't allocate memory for certificate.
*/
Error GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
{
return mDtls.GetPeerCertificateBase64(aPeerCert, aCertLength, aCertBufferSize);
}
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/**
* Sets the authentication mode for the CoAP 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) { mDtls.SetSslAuthMode(aVerifyPeerCertificate); }
private:
MeshCoP::DtlsExtended mDtls;
};
#endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
+6 -6
View File
@@ -639,14 +639,14 @@ exit:
FreeMessageOnError(response, error);
}
void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent, void *aContext)
void BorderAgent::HandleConnected(Dtls::ConnectEvent aEvent, void *aContext)
{
static_cast<BorderAgent *>(aContext)->HandleConnected(aEvent);
}
void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent)
void BorderAgent::HandleConnected(Dtls::ConnectEvent aEvent)
{
if (aEvent == SecureTransport::kConnected)
if (aEvent == Dtls::kConnected)
{
LogInfo("SecureSession connected");
mState = kStateConnected;
@@ -674,11 +674,11 @@ void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent)
{
RestartAfterRemovingEphemeralKey();
if (aEvent == SecureTransport::kDisconnectedError)
if (aEvent == Dtls::kDisconnectedError)
{
mCounters.mEpskcSecureSessionFailures++;
}
else if (aEvent == SecureTransport::kDisconnectedPeerClosed)
else if (aEvent == Dtls::kDisconnectedPeerClosed)
{
mCounters.mEpskcDeactivationDisconnects++;
}
@@ -689,7 +689,7 @@ void BorderAgent::HandleConnected(SecureTransport::ConnectEvent aEvent)
mState = kStateStarted;
mUdpProxyPort = 0;
if (aEvent == SecureTransport::kDisconnectedError)
if (aEvent == Dtls::kDisconnectedError)
{
mCounters.mPskcSecureSessionFailures++;
}
+3 -4
View File
@@ -251,8 +251,7 @@ public:
uint16_t GetUdpProxyPort(void) const { return mUdpProxyPort; }
private:
static_assert(kMaxEphemeralKeyLength <= SecureTransport::kPskMaxLength,
"Max ephemeral key length is larger than max PSK len");
static_assert(kMaxEphemeralKeyLength <= Dtls::kPskMaxLength, "Max ephemeral key length is larger than max PSK len");
static constexpr uint16_t kUdpPort = OPENTHREAD_CONFIG_BORDER_AGENT_UDP_PORT;
static constexpr uint32_t kKeepAliveTimeout = 50 * 1000; // Timeout to reject a commissioner (in msec)
@@ -288,8 +287,8 @@ private:
void SendErrorMessage(const ForwardContext &aForwardContext, Error aError);
void SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, Error aError);
static void HandleConnected(SecureTransport::ConnectEvent aEvent, void *aContext);
void HandleConnected(SecureTransport::ConnectEvent aEvent);
static void HandleConnected(Dtls::ConnectEvent aEvent, void *aContext);
void HandleConnected(Dtls::ConnectEvent aEvent);
template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+3 -3
View File
@@ -112,14 +112,14 @@ exit:
return;
}
void Commissioner::HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent, void *aContext)
void Commissioner::HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent, void *aContext)
{
static_cast<Commissioner *>(aContext)->HandleSecureAgentConnectEvent(aEvent);
}
void Commissioner::HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent)
void Commissioner::HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent)
{
bool isConnected = (aEvent == SecureTransport::kConnected);
bool isConnected = (aEvent == Dtls::kConnected);
if (!isConnected)
{
mJoinerSessionTimer.Stop();
+2 -2
View File
@@ -414,8 +414,8 @@ private:
Error aResult);
void HandleLeaderKeepAliveResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult);
static void HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent, void *aContext);
void HandleSecureAgentConnectEvent(SecureTransport::ConnectEvent aEvent);
static void HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent, void *aContext);
void HandleSecureAgentConnectEvent(Dtls::ConnectEvent aEvent);
template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
+3 -3
View File
@@ -367,16 +367,16 @@ exit:
return error;
}
void Joiner::HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent, void *aContext)
void Joiner::HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent, void *aContext)
{
static_cast<Joiner *>(aContext)->HandleSecureCoapClientConnect(aEvent);
}
void Joiner::HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent)
void Joiner::HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent)
{
VerifyOrExit(mState == kStateConnect);
if (aEvent == SecureTransport::kConnected)
if (aEvent == Dtls::kConnected)
{
SetState(kStateConnected);
SendJoinerFinalize();
+2 -2
View File
@@ -189,8 +189,8 @@ private:
static void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult, void *aContext);
void HandleDiscoverResult(Mle::DiscoverScanner::ScanResult *aResult);
static void HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent, void *aContext);
void HandleSecureCoapClientConnect(SecureTransport::ConnectEvent aEvent);
static void HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent, void *aContext);
void HandleSecureCoapClientConnect(Dtls::ConnectEvent aEvent);
static void HandleJoinerFinalizeResponse(void *aContext,
otMessage *aMessage,
+71 -52
View File
@@ -89,6 +89,9 @@ SecureTransport::SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwo
, mSocket(aInstance, *this)
, mTimer(aInstance, SecureTransport::HandleTimer, this)
, mTimerIntermediate(0)
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
, mExtension(nullptr)
#endif
{
ClearAllBytes(mPsk);
ClearAllBytes(mSsl);
@@ -108,7 +111,10 @@ void SecureTransport::FreeMbedtls(void)
}
#endif
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
mEcdheEcdsaInfo.Free();
if (mExtension != nullptr)
{
mExtension->mEcdheEcdsaInfo.Free();
}
#endif
mbedtls_ssl_config_free(&mConf);
mbedtls_ssl_free(&mSsl);
@@ -277,9 +283,14 @@ Error SecureTransport::Setup(bool aClient)
mbedtls_ssl_init(&mSsl);
mbedtls_ssl_config_init(&mConf);
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
mEcdheEcdsaInfo.Init();
if (mExtension != nullptr)
{
mExtension->mEcdheEcdsaInfo.Init();
}
#endif
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
if (mDatagramTransport)
{
@@ -367,9 +378,9 @@ Error SecureTransport::Setup(bool aClient)
rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength);
}
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
else
else if (mExtension != nullptr)
{
rval = SetApplicationSecureKeys();
rval = mExtension->SetApplicationSecureKeys();
}
#endif
VerifyOrExit(rval == 0);
@@ -400,23 +411,23 @@ exit:
}
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
int SecureTransport::SetApplicationSecureKeys(void)
int SecureTransport::Extension::SetApplicationSecureKeys(void)
{
int rval = 0;
switch (mCipherSuite)
switch (mSecureTransport.mCipherSuite)
{
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
case kEcdheEcdsaWithAes128Ccm8:
case kEcdheEcdsaWithAes128GcmSha256:
rval = mEcdheEcdsaInfo.SetSecureKeys(mConf);
rval = mEcdheEcdsaInfo.SetSecureKeys(mSecureTransport.mConf);
VerifyOrExit(rval == 0);
break;
#endif
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
case kPskWithAes128Ccm8:
rval = mPskInfo.SetSecureKeys(mConf);
rval = mPskInfo.SetSecureKeys(mSecureTransport.mConf);
VerifyOrExit(rval == 0);
break;
#endif
@@ -425,7 +436,6 @@ int SecureTransport::SetApplicationSecureKeys(void)
LogCrit("Application Coap Secure: Not supported cipher.");
rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
ExitNow();
break;
}
exit:
@@ -480,21 +490,21 @@ exit:
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
void SecureTransport::EcdheEcdsaInfo::Init(void)
void SecureTransport::Extension::EcdheEcdsaInfo::Init(void)
{
mbedtls_x509_crt_init(&mCaChain);
mbedtls_x509_crt_init(&mOwnCert);
mbedtls_pk_init(&mPrivateKey);
}
void SecureTransport::EcdheEcdsaInfo::Free(void)
void SecureTransport::Extension::EcdheEcdsaInfo::Free(void)
{
mbedtls_x509_crt_free(&mCaChain);
mbedtls_x509_crt_free(&mOwnCert);
mbedtls_pk_free(&mPrivateKey);
}
int SecureTransport::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig)
int SecureTransport::Extension::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig)
{
int rval = 0;
@@ -528,10 +538,10 @@ exit:
return rval;
}
void SecureTransport::SetCertificate(const uint8_t *aX509Certificate,
uint32_t aX509CertLength,
const uint8_t *aPrivateKey,
uint32_t aPrivateKeyLength)
void SecureTransport::Extension::SetCertificate(const uint8_t *aX509Certificate,
uint32_t aX509CertLength,
const uint8_t *aPrivateKey,
uint32_t aPrivateKeyLength)
{
OT_ASSERT(aX509CertLength > 0);
OT_ASSERT(aX509Certificate != nullptr);
@@ -544,10 +554,12 @@ void SecureTransport::SetCertificate(const uint8_t *aX509Certificate,
mEcdheEcdsaInfo.mPrivateKeySrc = aPrivateKey;
mEcdheEcdsaInfo.mPrivateKeyLength = aPrivateKeyLength;
mCipherSuite = mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256;
mSecureTransport.mCipherSuite =
mSecureTransport.mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256;
}
void SecureTransport::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, uint32_t aX509CaCertChainLength)
void SecureTransport::Extension::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain,
uint32_t aX509CaCertChainLength)
{
OT_ASSERT(aX509CaCertChainLength > 0);
OT_ASSERT(aX509CaCertificateChain != nullptr);
@@ -560,16 +572,16 @@ void SecureTransport::SetCaCertificateChain(const uint8_t *aX509CaCertificateCha
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
int SecureTransport::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const
int SecureTransport::Extension::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const
{
return mbedtls_ssl_conf_psk(&aConfig, static_cast<const unsigned char *>(mPreSharedKey), mPreSharedKeyLength,
static_cast<const unsigned char *>(mPreSharedKeyIdentity), mPreSharedKeyIdLength);
}
void SecureTransport::SetPreSharedKey(const uint8_t *aPsk,
uint16_t aPskLength,
const uint8_t *aPskIdentity,
uint16_t aPskIdLength)
void SecureTransport::Extension::SetPreSharedKey(const uint8_t *aPsk,
uint16_t aPskLength,
const uint8_t *aPskIdentity,
uint16_t aPskIdLength)
{
OT_ASSERT(aPsk != nullptr);
OT_ASSERT(aPskIdentity != nullptr);
@@ -581,30 +593,37 @@ void SecureTransport::SetPreSharedKey(const uint8_t *aPsk,
mPskInfo.mPreSharedKeyIdentity = aPskIdentity;
mPskInfo.mPreSharedKeyIdLength = aPskIdLength;
mCipherSuite = kPskWithAes128Ccm8;
mSecureTransport.mCipherSuite = kPskWithAes128Ccm8;
}
#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
Error SecureTransport::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLength, size_t aCertBufferSize)
Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerCert,
size_t *aCertLength,
size_t aCertBufferSize)
{
Error error = kErrorNone;
VerifyOrExit(IsStateConnected(), error = kErrorInvalidState);
VerifyOrExit(mSecureTransport.IsStateConnected(), error = kErrorInvalidState);
#if (MBEDTLS_VERSION_NUMBER >= 0x03010000)
VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p,
mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) == 0,
error = kErrorNoBufs);
#else
VerifyOrExit(
mbedtls_base64_encode(
aPeerCert, aCertBufferSize, aCertLength,
mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p),
mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) == 0,
mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p,
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) == 0,
error = kErrorNoBufs);
#else
VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength,
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)
->MBEDTLS_PRIVATE(peer_cert)
->MBEDTLS_PRIVATE(raw)
.MBEDTLS_PRIVATE(p),
mSecureTransport.mSsl.MBEDTLS_PRIVATE(session)
->MBEDTLS_PRIVATE(peer_cert)
->MBEDTLS_PRIVATE(raw)
.MBEDTLS_PRIVATE(len)) == 0,
error = kErrorNoBufs);
#endif
exit:
@@ -613,17 +632,17 @@ exit:
#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
#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 SecureTransport::Extension::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));
mbedtls_x509_crt *peerCert = const_cast<mbedtls_x509_crt *>(mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl));
VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs);
attributeBufferSize = *aAttributeLength;
@@ -650,30 +669,30 @@ exit:
return error;
}
Error SecureTransport::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor,
uint8_t *aAttributeBuffer,
size_t *aAttributeLength)
Error SecureTransport::Extension::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor,
uint8_t *aAttributeBuffer,
size_t *aAttributeLength)
{
const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSsl);
const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSecureTransport.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)
Error SecureTransport::Extension::GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor,
uint8_t *aAttributeBuffer,
size_t *aAttributeLength)
{
const mbedtls_x509_crt *cert = &mEcdheEcdsaInfo.mOwnCert;
return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength);
}
Error SecureTransport::GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
int aThreadOidDescriptor,
uint8_t *aAttributeBuffer,
size_t *aAttributeLength)
Error SecureTransport::Extension::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),
+302 -206
View File
@@ -88,6 +88,9 @@ namespace ot {
namespace MeshCoP {
/**
* Represents a secure transport, used as base class for `Dtls` and `Tls`.
*/
class SecureTransport : public InstanceLocator
{
public:
@@ -132,14 +135,233 @@ public:
*/
typedef void (*AutoCloseCallback)(void *aContext);
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
/**
* Initializes the SecureTransport object.
* Represents an API extension for a `SecureTransport` (DTLS or TLS).
*
* @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.
* The `Extension` provides support for additional cipher suites along with related methods to configure them.
* This class decouples this functionality from the common `SecureTransport` object, allowing this to be added
* to any class.
*
* The general pattern to use the `Extension` class is to have it be inherited by classes that want to provide the
* same methods for configuring ciphers (e.g. `SetPreSharedKey()` or `SetCertificate()`). An `Extension` should
* then be associated with a `SecureTransport` (or any of its subclasses).
*/
explicit SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport = true);
class Extension
{
friend SecureTransport;
public:
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
/**
* Sets the Pre-Shared Key (PSK) for sessions-identified by a PSK.
*
* DTLS mode "PSK with AES 128 CCM 8" for Application CoAPS.
*
* @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);
#endif
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
/**
* Sets a reference to the own x509 certificate with corresponding private key.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @param[in] aX509Certificate A pointer to the PEM formatted X509 certificate.
* @param[in] aX509CertLength 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 *aX509Certificate,
uint32_t aX509CertLength,
const uint8_t *aPrivateKey,
uint32_t aPrivateKeyLength);
/**
* Sets the trusted top level CAs. It is needed for validate the certificate of the peer.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @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);
/**
* Extracts public key from it's own certificate.
*
* @returns Public key from own certificate in form of entire ASN.1 field.
*/
const mbedtls_asn1_buf &GetOwnPublicKey(void) const { return mEcdheEcdsaInfo.mOwnCert.pk_raw; }
#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.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @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 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)
/**
* 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.
*
* @param[in] aVerifyPeerCertificate true, if the peer certificate should verify.
*/
void SetSslAuthMode(bool aVerifyPeerCertificate)
{
mSecureTransport.mVerifyPeerCertificate = aVerifyPeerCertificate;
}
protected:
explicit Extension(SecureTransport &aSecureTransport)
: mSecureTransport(aSecureTransport)
{
}
private:
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
struct EcdheEcdsaInfo : public Clearable<EcdheEcdsaInfo>
{
EcdheEcdsaInfo(void) { Clear(); }
void Init(void);
void Free(void);
int SetSecureKeys(mbedtls_ssl_config &aConfig);
const uint8_t *mCaChainSrc;
const uint8_t *mOwnCertSrc;
const uint8_t *mPrivateKeySrc;
uint32_t mOwnCertLength;
uint32_t mCaChainLength;
uint32_t mPrivateKeyLength;
mbedtls_x509_crt mCaChain;
mbedtls_x509_crt mOwnCert;
mbedtls_pk_context mPrivateKey;
};
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
struct PskInfo : public Clearable<PskInfo>
{
PskInfo(void) { Clear(); }
int SetSecureKeys(mbedtls_ssl_config &aConfig) const;
const uint8_t *mPreSharedKey;
const uint8_t *mPreSharedKeyIdentity;
uint16_t mPreSharedKeyLength;
uint16_t mPreSharedKeyIdLength;
};
#endif
int SetApplicationSecureKeys(void);
Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
int aThreadOidDescriptor,
uint8_t *aAttributeBuffer,
size_t *aAttributeLength);
SecureTransport &mSecureTransport;
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
EcdheEcdsaInfo mEcdheEcdsaInfo;
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
PskInfo mPskInfo;
#endif
};
#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE
/**
* Opens the socket.
@@ -258,161 +480,6 @@ public:
*/
Error SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
/**
* Sets the Pre-Shared Key (PSK) for sessions-identified by a PSK.
*
* DTLS mode "PSK with AES 128 CCM 8" for Application CoAPS.
*
* @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.
*
* @retval kErrorNone Successfully set the PSK.
*/
void SetPreSharedKey(const uint8_t *aPsk, uint16_t aPskLength, const uint8_t *aPskIdentity, uint16_t aPskIdLength);
#endif
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
/**
* Sets a reference to the own x509 certificate with corresponding private key.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @param[in] aX509Certificate A pointer to the PEM formatted X509 certificate.
* @param[in] aX509CertLength 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 *aX509Certificate,
uint32_t aX509CertLength,
const uint8_t *aPrivateKey,
uint32_t aPrivateKeyLength);
/**
* Sets the trusted top level CAs. It is needed for validate the certificate of the peer.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @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);
/**
* Extracts public key from it's own certificate.
*
* @returns Public key from own certificate in form of entire ASN.1 field.
*/
const mbedtls_asn1_buf &GetOwnPublicKey(void) const { return mEcdheEcdsaInfo.mOwnCert.pk_raw; }
#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.
*
* DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS.
*
* @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 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)
/**
* 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.
*
* @param[in] aVerifyPeerCertificate true, if the peer certificate should verify.
*/
void SetSslAuthMode(bool aVerifyPeerCertificate) { mVerifyPeerCertificate = aVerifyPeerCertificate; }
#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE
/**
* Sends data within the session.
*
@@ -440,6 +507,13 @@ public:
*/
void HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
protected:
SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport);
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
void SetExtension(Extension &aExtension) { mExtension = &aExtension; }
#endif
private:
static constexpr uint16_t kMaxContentLen = OPENTHREAD_CONFIG_DTLS_MAX_CONTENT_LEN;
static constexpr uint32_t kGuardTimeNewConnectionMilli = 2000;
@@ -474,39 +548,6 @@ private:
kUnspecifiedCipherSuite,
};
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
struct EcdheEcdsaInfo : public Clearable<EcdheEcdsaInfo>
{
EcdheEcdsaInfo(void) { Clear(); }
void Init(void);
void Free(void);
int SetSecureKeys(mbedtls_ssl_config &aConfig);
const uint8_t *mCaChainSrc;
const uint8_t *mOwnCertSrc;
const uint8_t *mPrivateKeySrc;
uint32_t mOwnCertLength;
uint32_t mCaChainLength;
uint32_t mPrivateKeyLength;
mbedtls_x509_crt mCaChain;
mbedtls_x509_crt mOwnCert;
mbedtls_pk_context mPrivateKey;
};
#endif
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
struct PskInfo : public Clearable<PskInfo>
{
PskInfo(void) { Clear(); }
int SetSecureKeys(mbedtls_ssl_config &aConfig) const;
const uint8_t *mPreSharedKey;
const uint8_t *mPreSharedKeyIdentity;
uint16_t mPreSharedKeyLength;
uint16_t mPreSharedKeyIdLength;
};
#endif
bool IsStateClosed(void) const { return mState == kStateClosed; }
bool IsStateOpen(void) const { return mState == kStateOpen; }
bool IsStateInitializing(void) const { return mState == kStateInitializing; }
@@ -519,14 +560,6 @@ private:
void FreeMbedtls(void);
Error Setup(bool aClient);
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
int SetApplicationSecureKeys(void);
Error GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert,
int aThreadOidDescriptor,
uint8_t *aAttributeBuffer,
size_t *aAttributeLength);
#endif
static bool IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext);
static void HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr);
@@ -633,14 +666,77 @@ private:
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C)
mbedtls_ssl_cookie_ctx mCookieCtx;
#endif
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
EcdheEcdsaInfo mEcdheEcdsaInfo;
#endif
#if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
PskInfo mPskInfo;
#if OPENTHREAD_CONFIG_TLS_API_ENABLE
Extension *mExtension;
#endif
};
/**
* Represents a DTLS instance.
*/
class Dtls : public SecureTransport
{
public:
/**
* Initializes the `Dtls` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not.
*/
Dtls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity)
: SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ true)
{
}
};
#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
/**
* Represents an extended DTLS instance providing `Dtls::Extension` APIs.
*/
class DtlsExtended : public Dtls
{
public:
/**
* Initializes the `DtlsExtended` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not.
* @param[in] aExtension An extension providing additional configuration methods.
*/
DtlsExtended(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, Extension &aExtension)
: Dtls(aInstance, aLayerTwoSecurity)
{
SetExtension(aExtension);
}
};
#endif
#if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
/**
* Represents a TLS instance.
*/
class Tls : public SecureTransport
{
public:
/**
* Initializes the `Tls` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aLayerTwoSecurity Specifies whether to use layer two security or not.
* @param[in] aExtension An extension providing additional configuration methods.
*/
Tls(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, Extension &aExtension)
: SecureTransport(aInstance, aLayerTwoSecurity, /* aDatagramTransport */ false)
{
SetExtension(aExtension);
}
};
#endif
} // namespace MeshCoP
} // namespace ot
+6 -6
View File
@@ -112,7 +112,7 @@ exit:
return error;
}
Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
Error TcatAgent::Connected(MeshCoP::Tls::Extension &aTls)
{
size_t len;
Error error;
@@ -120,13 +120,13 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
len = sizeof(mCommissionerAuthorizationField);
SuccessOrExit(
error = aTlsContext.GetThreadAttributeFromPeerCertificate(
error = aTls.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(
SuccessOrExit(error = aTls.GetThreadAttributeFromOwnCertificate(
kCertificateAuthorizationField, reinterpret_cast<uint8_t *>(&mDeviceAuthorizationField), &len));
VerifyOrExit(len == sizeof(mDeviceAuthorizationField), error = kErrorParse);
VerifyOrExit((mDeviceAuthorizationField.mHeader & kCommissionerFlag) == 0, error = kErrorParse);
@@ -136,7 +136,7 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
mCommissionerHasExtendedPanId = false;
len = sizeof(mCommissionerDomainName) - 1;
if (aTlsContext.GetThreadAttributeFromPeerCertificate(
if (aTls.GetThreadAttributeFromPeerCertificate(
kCertificateDomainName, reinterpret_cast<uint8_t *>(&mCommissionerDomainName), &len) == kErrorNone)
{
mCommissionerDomainName.m8[len] = '\0';
@@ -144,7 +144,7 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
}
len = sizeof(mCommissionerNetworkName) - 1;
if (aTlsContext.GetThreadAttributeFromPeerCertificate(
if (aTls.GetThreadAttributeFromPeerCertificate(
kCertificateNetworkName, reinterpret_cast<uint8_t *>(&mCommissionerNetworkName), &len) == kErrorNone)
{
mCommissionerNetworkName.m8[len] = '\0';
@@ -152,7 +152,7 @@ Error TcatAgent::Connected(MeshCoP::SecureTransport &aTlsContext)
}
len = sizeof(mCommissionerExtendedPanId);
if (aTlsContext.GetThreadAttributeFromPeerCertificate(
if (aTls.GetThreadAttributeFromPeerCertificate(
kCertificateExtendedPanId, reinterpret_cast<uint8_t *>(&mCommissionerExtendedPanId), &len) == kErrorNone)
{
if (len == sizeof(mCommissionerExtendedPanId))
+1 -1
View File
@@ -334,7 +334,7 @@ public:
bool GetInstallCodeVerifyStatus(void) const { return mInstallCodeVerified; }
private:
Error Connected(MeshCoP::SecureTransport &aTlsContext);
Error Connected(MeshCoP::Tls::Extension &aTls);
void Disconnected(void);
Error HandleSingleTlv(const Message &aIncomingMessage, Message &aOutgoingMessage);
+8 -21
View File
@@ -48,7 +48,8 @@ RegisterLogModule("BleSecure");
BleSecure::BleSecure(Instance &aInstance)
: InstanceLocator(aInstance)
, mTls(aInstance, kNoLinkSecurity, /* aDatagramTransport */ false)
, MeshCoP::Tls::Extension(mTls)
, mTls(aInstance, kNoLinkSecurity, *this)
, mTcatAgent(aInstance)
, mTlvMode(false)
, mReceivedMessage(nullptr)
@@ -164,26 +165,12 @@ void BleSecure::Disconnect(void)
void BleSecure::SetPsk(const MeshCoP::JoinerPskd &aPskd)
{
static_assert(static_cast<uint16_t>(MeshCoP::JoinerPskd::kMaxLength) <=
static_cast<uint16_t>(MeshCoP::SecureTransport::kPskMaxLength),
static_cast<uint16_t>(MeshCoP::Tls::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;
@@ -318,14 +305,14 @@ Error BleSecure::HandleBleMtuUpdate(uint16_t aMtu)
return error;
}
void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext)
void BleSecure::HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent, void *aContext)
{
return static_cast<BleSecure *>(aContext)->HandleTlsConnectEvent(aEvent);
}
void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent)
void BleSecure::HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent)
{
if (aEvent == MeshCoP::SecureTransport::kConnected)
if (aEvent == MeshCoP::Tls::kConnected)
{
Error err;
@@ -333,7 +320,7 @@ void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEv
{
mReceivedMessage = Get<MessagePool>().Allocate(Message::kTypeBle);
}
err = mTcatAgent.Connected(mTls);
err = mTcatAgent.Connected(*this);
if (err != kErrorNone)
{
@@ -353,7 +340,7 @@ void BleSecure::HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEv
}
}
mConnectCallback.InvokeIfSet(&GetInstance(), aEvent == MeshCoP::SecureTransport::kConnected, true);
mConnectCallback.InvokeIfSet(&GetInstance(), aEvent == MeshCoP::Tls::kConnected, true);
exit:
return;
+4 -166
View File
@@ -48,7 +48,7 @@ namespace ot {
namespace Ble {
class BleSecure : public InstanceLocator, private NonCopyable
class BleSecure : public InstanceLocator, public MeshCoP::Tls::Extension, private NonCopyable
{
public:
/**
@@ -187,168 +187,6 @@ public:
*/
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);
}
/**
* Extracts public key from it's own certificate.
*
* @returns Public key from own certificate in form of entire ASN.1 field.
*/
const mbedtls_asn1_buf &GetOwnPublicKey(void) const { return mTls.GetOwnPublicKey(); }
/**
* 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.
*
@@ -447,8 +285,8 @@ private:
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 HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent, void *aContext);
void HandleTlsConnectEvent(MeshCoP::SecureTransport::ConnectEvent aEvent);
static void HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent, void *aContext);
void HandleTlsConnectEvent(MeshCoP::Tls::ConnectEvent aEvent);
static void HandleTlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
void HandleTlsReceive(uint8_t *aBuf, uint16_t aLength);
@@ -460,7 +298,7 @@ private:
using TxTask = TaskletIn<BleSecure, &BleSecure::HandleTransmit>;
MeshCoP::SecureTransport mTls;
MeshCoP::Tls mTls;
MeshCoP::TcatAgent mTcatAgent;
Callback<ConnectCallback> mConnectCallback;
Callback<ReceiveCallback> mReceiveCallback;
+2 -1
View File
@@ -273,7 +273,8 @@ Message::Priority Agent::DscpToPriority(uint8_t aDscp)
#if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
SecureAgent::SecureAgent(Instance &aInstance)
: Coap::CoapSecureBase(aInstance, kNoLinkSecurity)
: Coap::CoapSecureBase(aInstance, mDtls)
, mDtls(aInstance, kNoLinkSecurity)
{
SetResourceHandler(&HandleResource);
}
+2
View File
@@ -213,6 +213,8 @@ private:
Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
bool HandleResource(const char *aUriPath, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
MeshCoP::Dtls mDtls;
};
#endif