mirror of
https://github.com/espressif/openthread.git
synced 2026-08-02 17:17:45 +00:00
[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:
committed by
Jonathan Hui
parent
f0d6007cc3
commit
53c02c6141
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user