diff --git a/src/core/meshcop/secure_transport.cpp b/src/core/meshcop/secure_transport.cpp index 0859847dd6a..fadf58bd014 100644 --- a/src/core/meshcop/secure_transport.cpp +++ b/src/core/meshcop/secure_transport.cpp @@ -72,6 +72,9 @@ const int SecureTransport::kCipherSuites[][2] = { #endif }; +//--------------------------------------------------------------------------------------------------------------------- +// SecureTransport + SecureTransport::SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport) : InstanceLocator(aInstance) , mLayerTwoSecurity(aLayerTwoSecurity) @@ -410,40 +413,6 @@ Error SecureTransport::Setup(bool aClient) return Crypto::MbedTls::MapError(rval); } -#if OPENTHREAD_CONFIG_TLS_API_ENABLE -int SecureTransport::Extension::SetApplicationSecureKeys(void) -{ - int rval = 0; - - switch (mSecureTransport.mCipherSuite) - { -#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - case kEcdheEcdsaWithAes128Ccm8: - case kEcdheEcdsaWithAes128GcmSha256: - rval = mEcdheEcdsaInfo.SetSecureKeys(mSecureTransport.mConf); - VerifyOrExit(rval == 0); - break; -#endif - -#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - case kPskWithAes128Ccm8: - rval = mPskInfo.SetSecureKeys(mSecureTransport.mConf); - VerifyOrExit(rval == 0); - break; -#endif - - default: - LogCrit("Application Coap Secure: Not supported cipher."); - rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - ExitNow(); - } - -exit: - return rval; -} - -#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE - void SecureTransport::Close(void) { Disconnect(kDisconnectedLocalClosed); @@ -487,709 +456,744 @@ Error SecureTransport::SetPsk(const uint8_t *aPsk, uint8_t aPskLength) return error; } -#if OPENTHREAD_CONFIG_TLS_API_ENABLE -#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +Error SecureTransport::Send(Message &aMessage, uint16_t aLength) +{ + Error error = kErrorNone; + uint8_t buffer[kApplicationDataMaxLength]; -void SecureTransport::Extension::EcdheEcdsaInfo::Init(void) + VerifyOrExit(aLength <= kApplicationDataMaxLength, error = kErrorNoBufs); + + // Store message specific sub type. + if (aMessage.GetSubType() != Message::kSubTypeNone) + { + mMessageSubType = aMessage.GetSubType(); + } + + aMessage.ReadBytes(0, buffer, aLength); + + SuccessOrExit(error = Crypto::MbedTls::MapError(mbedtls_ssl_write(&mSsl, buffer, aLength))); + + aMessage.Free(); + +exit: + return error; +} + +bool SecureTransport::IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext) { - mbedtls_x509_crt_init(&mCaChain); - mbedtls_x509_crt_init(&mOwnCert); - mbedtls_pk_init(&mPrivateKey); + return +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + mbedtls_ssl_is_handshake_over(aSslContext); +#else + (aSslContext->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER); +#endif } -void SecureTransport::Extension::EcdheEcdsaInfo::Free(void) +int SecureTransport::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength) { - mbedtls_x509_crt_free(&mCaChain); - mbedtls_x509_crt_free(&mOwnCert); - mbedtls_pk_free(&mPrivateKey); + return static_cast(aContext)->HandleMbedtlsTransmit(aBuf, aLength); } -int SecureTransport::Extension::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) +int SecureTransport::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength) { - int rval = 0; + Error error = kErrorNone; + Message *message = mSocket.NewMessage(); + int rval; - if (mCaChainSrc != nullptr) + VerifyOrExit(message != nullptr, error = kErrorNoBufs); + message->SetSubType(mMessageSubType); + message->SetLinkSecurityEnabled(mLayerTwoSecurity); + + SuccessOrExit(error = message->AppendBytes(aBuf, static_cast(aLength))); + + if (mTransportCallback.IsSet()) { - rval = mbedtls_x509_crt_parse(&mCaChain, static_cast(mCaChainSrc), - static_cast(mCaChainLength)); - VerifyOrExit(rval == 0); - mbedtls_ssl_conf_ca_chain(&aConfig, &mCaChain, nullptr); + error = mTransportCallback.Invoke(*message, mMessageInfo); + } + else + { + error = mSocket.SendTo(*message, mMessageInfo); } - if (mOwnCertSrc != nullptr && mPrivateKeySrc != nullptr) +exit: + FreeMessageOnError(message, error); + mMessageSubType = Message::kSubTypeNone; + + switch (error) { - rval = mbedtls_x509_crt_parse(&mOwnCert, static_cast(mOwnCertSrc), - static_cast(mOwnCertLength)); - VerifyOrExit(rval == 0); + case kErrorNone: + rval = static_cast(aLength); + break; -#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) - rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast(mPrivateKeySrc), - static_cast(mPrivateKeyLength), nullptr, 0, - Crypto::MbedTls::CryptoSecurePrng, nullptr); -#else - rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast(mPrivateKeySrc), - static_cast(mPrivateKeyLength), nullptr, 0); -#endif - VerifyOrExit(rval == 0); - rval = mbedtls_ssl_conf_own_cert(&aConfig, &mOwnCert, &mPrivateKey); + case kErrorNoBufs: + rval = MBEDTLS_ERR_SSL_WANT_WRITE; + break; + + default: + LogWarnOnError(error, "HandleMbedtlsTransmit"); + rval = MBEDTLS_ERR_NET_SEND_FAILED; + break; } -exit: return rval; } -void SecureTransport::Extension::SetCertificate(const uint8_t *aX509Certificate, - uint32_t aX509CertLength, - const uint8_t *aPrivateKey, - uint32_t aPrivateKeyLength) +int SecureTransport::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength) { - OT_ASSERT(aX509CertLength > 0); - OT_ASSERT(aX509Certificate != nullptr); + return static_cast(aContext)->HandleMbedtlsReceive(aBuf, aLength); +} - OT_ASSERT(aPrivateKeyLength > 0); - OT_ASSERT(aPrivateKey != nullptr); +int SecureTransport::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength) +{ + int rval = MBEDTLS_ERR_SSL_WANT_READ; + uint16_t readLength; - mEcdheEcdsaInfo.mOwnCertSrc = aX509Certificate; - mEcdheEcdsaInfo.mOwnCertLength = aX509CertLength; - mEcdheEcdsaInfo.mPrivateKeySrc = aPrivateKey; - mEcdheEcdsaInfo.mPrivateKeyLength = aPrivateKeyLength; + VerifyOrExit(mReceiveMessage != nullptr); - mSecureTransport.mCipherSuite = - mSecureTransport.mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256; + readLength = mReceiveMessage->ReadBytes(mReceiveMessage->GetOffset(), aBuf, static_cast(aLength)); + VerifyOrExit(readLength > 0); + + mReceiveMessage->MoveOffset(readLength); + rval = static_cast(readLength); + +exit: + return rval; } -void SecureTransport::Extension::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, - uint32_t aX509CaCertChainLength) +int SecureTransport::HandleMbedtlsGetTimer(void *aContext) { - OT_ASSERT(aX509CaCertChainLength > 0); - OT_ASSERT(aX509CaCertificateChain != nullptr); - - mEcdheEcdsaInfo.mCaChainSrc = aX509CaCertificateChain; - mEcdheEcdsaInfo.mCaChainLength = aX509CaCertChainLength; + return static_cast(aContext)->HandleMbedtlsGetTimer(); } -#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +int SecureTransport::HandleMbedtlsGetTimer(void) +{ + int rval; -#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + if (!mTimerSet) + { + rval = -1; + } + else if (!mTimer.IsRunning()) + { + rval = 2; + } + else if (mTimerIntermediate <= TimerMilli::GetNow()) + { + rval = 1; + } + else + { + rval = 0; + } -int SecureTransport::Extension::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const + return rval; +} + +void SecureTransport::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish) { - return mbedtls_ssl_conf_psk(&aConfig, static_cast(mPreSharedKey), mPreSharedKeyLength, - static_cast(mPreSharedKeyIdentity), mPreSharedKeyIdLength); + static_cast(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish); } -void SecureTransport::Extension::SetPreSharedKey(const uint8_t *aPsk, - uint16_t aPskLength, - const uint8_t *aPskIdentity, - uint16_t aPskIdLength) +void SecureTransport::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish) { - OT_ASSERT(aPsk != nullptr); - OT_ASSERT(aPskIdentity != nullptr); - OT_ASSERT(aPskLength > 0); - OT_ASSERT(aPskIdLength > 0); + if (aFinish == 0) + { + mTimerSet = false; + mTimer.Stop(); + } + else + { + mTimerSet = true; + mTimer.Start(aFinish); + mTimerIntermediate = TimerMilli::GetNow() + aIntermediate; + } +} - mPskInfo.mPreSharedKey = aPsk; - mPskInfo.mPreSharedKeyLength = aPskLength; - mPskInfo.mPreSharedKeyIdentity = aPskIdentity; - mPskInfo.mPreSharedKeyIdLength = aPskIdLength; +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) - mSecureTransport.mCipherSuite = kPskWithAes128Ccm8; +void SecureTransport::HandleMbedtlsExportKeys(void *aContext, + mbedtls_ssl_key_export_type aType, + const unsigned char *aMasterSecret, + size_t aMasterSecretLen, + const unsigned char aClientRandom[32], + const unsigned char aServerRandom[32], + mbedtls_tls_prf_types aTlsPrfType) +{ + static_cast(aContext)->HandleMbedtlsExportKeys(aType, aMasterSecret, aMasterSecretLen, + aClientRandom, aServerRandom, aTlsPrfType); } -#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - -#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerCert, - size_t *aCertLength, - size_t aCertBufferSize) +void SecureTransport::HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType, + const unsigned char *aMasterSecret, + size_t aMasterSecretLen, + const unsigned char aClientRandom[32], + const unsigned char aServerRandom[32], + mbedtls_tls_prf_types aTlsPrfType) { - Error error = kErrorNone; + Crypto::Sha256::Hash kek; + Crypto::Sha256 sha256; + unsigned char keyBlock[kSecureTransportKeyBlockSize]; + unsigned char randBytes[2 * kSecureTransportRandomBufferSize]; - VerifyOrExit(mSecureTransport.IsStateConnected(), error = kErrorInvalidState); + VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8); + VerifyOrExit(aType == MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET); -#if (MBEDTLS_VERSION_NUMBER >= 0x03010000) - VerifyOrExit( - 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 + memcpy(randBytes, aServerRandom, kSecureTransportRandomBufferSize); + memcpy(randBytes + kSecureTransportRandomBufferSize, aClientRandom, kSecureTransportRandomBufferSize); + + // Retrieve the Key block from Master secret + mbedtls_ssl_tls_prf(aTlsPrfType, aMasterSecret, aMasterSecretLen, "key expansion", randBytes, sizeof(randBytes), + keyBlock, sizeof(keyBlock)); + + sha256.Start(); + sha256.Update(keyBlock, kSecureTransportKeyBlockSize); + sha256.Finish(kek); + + Get().SetKek(kek.GetBytes()); exit: - return error; + return; } -#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -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_ssl_get_peer_cert(&mSecureTransport.mSsl)); +#else - VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs); - attributeBufferSize = *aAttributeLength; - *aAttributeLength = 0; +int SecureTransport::HandleMbedtlsExportKeys(void *aContext, + const unsigned char *aMasterSecret, + const unsigned char *aKeyBlock, + size_t aMacLength, + size_t aKeyLength, + size_t aIvLength) +{ + return static_cast(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength, + aKeyLength, aIvLength); +} - VerifyOrExit(aAttributeBuffer != nullptr, error = kErrorNoBufs); - VerifyOrExit(peerCert != nullptr, error = kErrorInvalidState); +int SecureTransport::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret, + const unsigned char *aKeyBlock, + size_t aMacLength, + size_t aKeyLength, + size_t aIvLength) +{ + OT_UNUSED_VARIABLE(aMasterSecret); - data = mbedtls_asn1_find_named_data(&peerCert->subject, aOid, aOidLength); - VerifyOrExit(data != nullptr, error = kErrorNotFound); + Crypto::Sha256::Hash kek; + Crypto::Sha256 sha256; - length = data->val.len; - VerifyOrExit(length <= attributeBufferSize, error = kErrorNoBufs); - *aAttributeLength = length; + VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8); - if (aAsn1Type != nullptr) - { - *aAsn1Type = data->val.tag; - } + sha256.Start(); + sha256.Update(aKeyBlock, 2 * static_cast(aMacLength + aKeyLength + aIvLength)); + sha256.Finish(kek); - memcpy(aAttributeBuffer, data->val.p, length); + Get().SetKek(kek.GetBytes()); exit: - return error; + return 0; } -Error SecureTransport::Extension::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) -{ - const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl); +#endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000) - return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); +void SecureTransport::HandleTimer(Timer &aTimer) +{ + static_cast(static_cast(aTimer).GetContext())->HandleTimer(); } -#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - -Error SecureTransport::Extension::GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) +void SecureTransport::HandleTimer(void) { - const mbedtls_x509_crt *cert = &mEcdheEcdsaInfo.mOwnCert; - - return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); + if (IsStateConnectingOrConnected()) + { + Process(); + } + else if (IsStateCloseNotify()) + { + if ((mMaxConnectionAttempts > 0) && (mRemainingConnectionAttempts == 0)) + { + Close(); + mConnectEvent = kDisconnectedMaxAttempts; + mAutoCloseCallback.InvokeIfSet(); + } + else + { + SetState(kStateOpen); + mTimer.Stop(); + } + mConnectedCallback.InvokeIfSet(mConnectEvent); + } } -Error SecureTransport::Extension::GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert, - int aThreadOidDescriptor, - uint8_t *aAttributeBuffer, - size_t *aAttributeLength) +void SecureTransport::Process(void) { - Error error = kErrorNotFound; - char oid[9] = {0x2B, 0x06, 0x01, 0x04, 0x01, static_cast(0x82), static_cast(0xDF), - 0x2A, 0x00}; // 1.3.6.1.4.1.44970.0 - mbedtls_x509_buf v3_ext; - unsigned char *p, *end, *endExtData; - size_t len; - size_t attributeBufferSize; - mbedtls_x509_buf extnOid; - int ret, isCritical; + uint8_t buf[kMaxContentLen]; + int rval; + ConnectEvent disconnectEvent; + bool shouldReset; - VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs); - attributeBufferSize = *aAttributeLength; - *aAttributeLength = 0; + while (IsStateConnectingOrConnected()) + { + if (IsStateConnecting()) + { + rval = mbedtls_ssl_handshake(&mSsl); - VerifyOrExit(aCert != nullptr, error = kErrorInvalidState); - v3_ext = aCert->v3_ext; - p = v3_ext.p; - VerifyOrExit(p != nullptr, error = kErrorInvalidState); - end = p + v3_ext.len; - VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0, - error = kErrorParse); - VerifyOrExit(end == p + len, error = kErrorParse); + if (IsMbedtlsHandshakeOver(&mSsl)) + { + SetState(kStateConnected); + mConnectEvent = kConnected; + mConnectedCallback.InvokeIfSet(mConnectEvent); + } + } + else + { + rval = mbedtls_ssl_read(&mSsl, buf, sizeof(buf)); - VerifyOrExit(aThreadOidDescriptor < 128, error = kErrorNotImplemented); - oid[sizeof(oid) - 1] = static_cast(aThreadOidDescriptor); + if (rval > 0) + { + mReceiveCallback.InvokeIfSet(buf, static_cast(rval)); + continue; + } + } - while (p < end) - { - isCritical = 0; - VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0, - error = kErrorParse); - endExtData = p + len; + // Check `rval` to determine if the connection should be + // disconnected, reset, or if we should wait. - // Get extension ID - VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &extnOid.len, MBEDTLS_ASN1_OID) == 0, error = kErrorParse); - extnOid.tag = MBEDTLS_ASN1_OID; - extnOid.p = p; - p += extnOid.len; + disconnectEvent = kConnected; + shouldReset = true; - // Get optional critical - ret = mbedtls_asn1_get_bool(&p, endExtData, &isCritical); - VerifyOrExit(ret == 0 || ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = kErrorParse); + switch (rval) + { + case 0: + case MBEDTLS_ERR_SSL_WANT_READ: + case MBEDTLS_ERR_SSL_WANT_WRITE: + shouldReset = false; + break; - // Data must be octet string type, see https://datatracker.ietf.org/doc/html/rfc5280#section-4.1 - VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &len, MBEDTLS_ASN1_OCTET_STRING) == 0, error = kErrorParse); - VerifyOrExit(endExtData == p + len, error = kErrorParse); + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + disconnectEvent = kDisconnectedPeerClosed; + break; - // TODO: extensions with isCritical == 1 that are unknown should lead to rejection of the entire cert. - if (extnOid.len == sizeof(oid) && memcmp(extnOid.p, oid, sizeof(oid)) == 0) - { - // per RFC 5280, octet string must contain ASN.1 Type Length Value octets - VerifyOrExit(len >= 2, error = kErrorParse); - VerifyOrExit(*(p + 1) == len - 2, error = kErrorParse); // check TLV Length, not Type. - *aAttributeLength = len - 2; // strip the ASN.1 Type Length bytes from embedded TLV + case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: + break; - if (aAttributeBuffer != nullptr) + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: + disconnectEvent = kDisconnectedError; + break; + + case MBEDTLS_ERR_SSL_INVALID_MAC: + if (!IsMbedtlsHandshakeOver(&mSsl)) { - VerifyOrExit(*aAttributeLength <= attributeBufferSize, error = kErrorNoBufs); - memcpy(aAttributeBuffer, p + 2, *aAttributeLength); + mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC); + disconnectEvent = kDisconnectedError; + } + break; + + default: + if (!IsMbedtlsHandshakeOver(&mSsl)) + { + mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); + disconnectEvent = kDisconnectedError; } - error = kErrorNone; break; } - p += len; - } -exit: - return error; -} + if (disconnectEvent != kConnected) + { + Disconnect(disconnectEvent); + } + else if (shouldReset) + { + mbedtls_ssl_session_reset(&mSsl); -#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE + if (mCipherSuite == kEcjpakeWithAes128Ccm8) + { + mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength); + } + } -Error SecureTransport::Send(Message &aMessage, uint16_t aLength) + break; // from `while()` loop + } +} + +void SecureTransport::HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr) { - Error error = kErrorNone; - uint8_t buffer[kApplicationDataMaxLength]; + static_cast(aContext)->HandleMbedtlsDebug(aLevel, aFile, aLine, aStr); +} - VerifyOrExit(aLength <= kApplicationDataMaxLength, error = kErrorNoBufs); +void SecureTransport::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr) +{ + LogLevel logLevel = kLogLevelDebg; - // Store message specific sub type. - if (aMessage.GetSubType() != Message::kSubTypeNone) + switch (aLevel) { - mMessageSubType = aMessage.GetSubType(); - } + case 1: + logLevel = kLogLevelCrit; + break; - aMessage.ReadBytes(0, buffer, aLength); + case 2: + logLevel = kLogLevelWarn; + break; - SuccessOrExit(error = Crypto::MbedTls::MapError(mbedtls_ssl_write(&mSsl, buffer, aLength))); + case 3: + logLevel = kLogLevelInfo; + break; - aMessage.Free(); + case 4: + default: + break; + } -exit: - return error; -} + LogAt(logLevel, "[%u] %s", mSocket.GetSockName().mPort, aStr); -bool SecureTransport::IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext) -{ - return -#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) - mbedtls_ssl_is_handshake_over(aSslContext); -#else - (aSslContext->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER); -#endif + OT_UNUSED_VARIABLE(aStr); + OT_UNUSED_VARIABLE(aFile); + OT_UNUSED_VARIABLE(aLine); + OT_UNUSED_VARIABLE(logLevel); } -int SecureTransport::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength) -{ - return static_cast(aContext)->HandleMbedtlsTransmit(aBuf, aLength); -} +#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) -int SecureTransport::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength) +const char *SecureTransport::StateToString(State aState) { - Error error = kErrorNone; - Message *message = mSocket.NewMessage(); - int rval; + static const char *const kStateStrings[] = { + "Closed", // (0) kStateClosed + "Open", // (1) kStateOpen + "Initializing", // (2) kStateInitializing + "Connecting", // (3) kStateConnecting + "Connected", // (4) kStateConnected + "CloseNotify", // (5) kStateCloseNotify + }; - VerifyOrExit(message != nullptr, error = kErrorNoBufs); - message->SetSubType(mMessageSubType); - message->SetLinkSecurityEnabled(mLayerTwoSecurity); + struct EnumCheck + { + InitEnumValidatorCounter(); + ValidateNextEnum(kStateClosed); + ValidateNextEnum(kStateOpen); + ValidateNextEnum(kStateInitializing); + ValidateNextEnum(kStateConnecting); + ValidateNextEnum(kStateConnected); + ValidateNextEnum(kStateCloseNotify); + }; - SuccessOrExit(error = message->AppendBytes(aBuf, static_cast(aLength))); + return kStateStrings[aState]; +} - if (mTransportCallback.IsSet()) - { - error = mTransportCallback.Invoke(*message, mMessageInfo); - } - else - { - error = mSocket.SendTo(*message, mMessageInfo); - } +#endif -exit: - FreeMessageOnError(message, error); - mMessageSubType = Message::kSubTypeNone; +//--------------------------------------------------------------------------------------------------------------------- +// SecureTransport::Extension - switch (error) +#if OPENTHREAD_CONFIG_TLS_API_ENABLE + +int SecureTransport::Extension::SetApplicationSecureKeys(void) +{ + int rval = 0; + + switch (mSecureTransport.mCipherSuite) { - case kErrorNone: - rval = static_cast(aLength); +#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + case kEcdheEcdsaWithAes128Ccm8: + case kEcdheEcdsaWithAes128GcmSha256: + rval = mEcdheEcdsaInfo.SetSecureKeys(mSecureTransport.mConf); + VerifyOrExit(rval == 0); break; +#endif - case kErrorNoBufs: - rval = MBEDTLS_ERR_SSL_WANT_WRITE; +#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + case kPskWithAes128Ccm8: + rval = mPskInfo.SetSecureKeys(mSecureTransport.mConf); + VerifyOrExit(rval == 0); break; +#endif default: - LogWarnOnError(error, "HandleMbedtlsTransmit"); - rval = MBEDTLS_ERR_NET_SEND_FAILED; - break; + LogCrit("Application Coap Secure: Not supported cipher."); + rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + ExitNow(); } +exit: return rval; } -int SecureTransport::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength) -{ - return static_cast(aContext)->HandleMbedtlsReceive(aBuf, aLength); -} +#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -int SecureTransport::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength) +void SecureTransport::Extension::EcdheEcdsaInfo::Init(void) { - int rval = MBEDTLS_ERR_SSL_WANT_READ; - uint16_t readLength; - - VerifyOrExit(mReceiveMessage != nullptr); - - readLength = mReceiveMessage->ReadBytes(mReceiveMessage->GetOffset(), aBuf, static_cast(aLength)); - VerifyOrExit(readLength > 0); - - mReceiveMessage->MoveOffset(readLength); - rval = static_cast(readLength); - -exit: - return rval; + mbedtls_x509_crt_init(&mCaChain); + mbedtls_x509_crt_init(&mOwnCert); + mbedtls_pk_init(&mPrivateKey); } -int SecureTransport::HandleMbedtlsGetTimer(void *aContext) +void SecureTransport::Extension::EcdheEcdsaInfo::Free(void) { - return static_cast(aContext)->HandleMbedtlsGetTimer(); + mbedtls_x509_crt_free(&mCaChain); + mbedtls_x509_crt_free(&mOwnCert); + mbedtls_pk_free(&mPrivateKey); } -int SecureTransport::HandleMbedtlsGetTimer(void) +int SecureTransport::Extension::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) { - int rval; + int rval = 0; - if (!mTimerSet) - { - rval = -1; - } - else if (!mTimer.IsRunning()) - { - rval = 2; - } - else if (mTimerIntermediate <= TimerMilli::GetNow()) + if (mCaChainSrc != nullptr) { - rval = 1; + rval = mbedtls_x509_crt_parse(&mCaChain, static_cast(mCaChainSrc), + static_cast(mCaChainLength)); + VerifyOrExit(rval == 0); + mbedtls_ssl_conf_ca_chain(&aConfig, &mCaChain, nullptr); } - else + + if (mOwnCertSrc != nullptr && mPrivateKeySrc != nullptr) { - rval = 0; + rval = mbedtls_x509_crt_parse(&mOwnCert, static_cast(mOwnCertSrc), + static_cast(mOwnCertLength)); + VerifyOrExit(rval == 0); + +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) + rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast(mPrivateKeySrc), + static_cast(mPrivateKeyLength), nullptr, 0, + Crypto::MbedTls::CryptoSecurePrng, nullptr); +#else + rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast(mPrivateKeySrc), + static_cast(mPrivateKeyLength), nullptr, 0); +#endif + VerifyOrExit(rval == 0); + rval = mbedtls_ssl_conf_own_cert(&aConfig, &mOwnCert, &mPrivateKey); } +exit: return rval; } -void SecureTransport::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish) +void SecureTransport::Extension::SetCertificate(const uint8_t *aX509Certificate, + uint32_t aX509CertLength, + const uint8_t *aPrivateKey, + uint32_t aPrivateKeyLength) { - static_cast(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish); + OT_ASSERT(aX509CertLength > 0); + OT_ASSERT(aX509Certificate != nullptr); + + OT_ASSERT(aPrivateKeyLength > 0); + OT_ASSERT(aPrivateKey != nullptr); + + mEcdheEcdsaInfo.mOwnCertSrc = aX509Certificate; + mEcdheEcdsaInfo.mOwnCertLength = aX509CertLength; + mEcdheEcdsaInfo.mPrivateKeySrc = aPrivateKey; + mEcdheEcdsaInfo.mPrivateKeyLength = aPrivateKeyLength; + + mSecureTransport.mCipherSuite = + mSecureTransport.mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256; } -void SecureTransport::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish) +void SecureTransport::Extension::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, + uint32_t aX509CaCertChainLength) { - if (aFinish == 0) - { - mTimerSet = false; - mTimer.Stop(); - } - else - { - mTimerSet = true; - mTimer.Start(aFinish); - mTimerIntermediate = TimerMilli::GetNow() + aIntermediate; - } + OT_ASSERT(aX509CaCertChainLength > 0); + OT_ASSERT(aX509CaCertificateChain != nullptr); + + mEcdheEcdsaInfo.mCaChainSrc = aX509CaCertificateChain; + mEcdheEcdsaInfo.mCaChainLength = aX509CaCertChainLength; } -#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -void SecureTransport::HandleMbedtlsExportKeys(void *aContext, - mbedtls_ssl_key_export_type aType, - const unsigned char *aMasterSecret, - size_t aMasterSecretLen, - const unsigned char aClientRandom[32], - const unsigned char aServerRandom[32], - mbedtls_tls_prf_types aTlsPrfType) +#ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +int SecureTransport::Extension::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const { - static_cast(aContext)->HandleMbedtlsExportKeys(aType, aMasterSecret, aMasterSecretLen, - aClientRandom, aServerRandom, aTlsPrfType); + return mbedtls_ssl_conf_psk(&aConfig, static_cast(mPreSharedKey), mPreSharedKeyLength, + static_cast(mPreSharedKeyIdentity), mPreSharedKeyIdLength); } -void SecureTransport::HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType, - const unsigned char *aMasterSecret, - size_t aMasterSecretLen, - const unsigned char aClientRandom[32], - const unsigned char aServerRandom[32], - mbedtls_tls_prf_types aTlsPrfType) -{ - Crypto::Sha256::Hash kek; - Crypto::Sha256 sha256; - unsigned char keyBlock[kSecureTransportKeyBlockSize]; - unsigned char randBytes[2 * kSecureTransportRandomBufferSize]; - - VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8); - VerifyOrExit(aType == MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET); +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); + OT_ASSERT(aPskLength > 0); + OT_ASSERT(aPskIdLength > 0); - memcpy(randBytes, aServerRandom, kSecureTransportRandomBufferSize); - memcpy(randBytes + kSecureTransportRandomBufferSize, aClientRandom, kSecureTransportRandomBufferSize); + mPskInfo.mPreSharedKey = aPsk; + mPskInfo.mPreSharedKeyLength = aPskLength; + mPskInfo.mPreSharedKeyIdentity = aPskIdentity; + mPskInfo.mPreSharedKeyIdLength = aPskIdLength; - // Retrieve the Key block from Master secret - mbedtls_ssl_tls_prf(aTlsPrfType, aMasterSecret, aMasterSecretLen, "key expansion", randBytes, sizeof(randBytes), - keyBlock, sizeof(keyBlock)); + mSecureTransport.mCipherSuite = kPskWithAes128Ccm8; +} - sha256.Start(); - sha256.Update(keyBlock, kSecureTransportKeyBlockSize); - sha256.Finish(kek); +#endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - Get().SetKek(kek.GetBytes()); +#if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerCert, + size_t *aCertLength, + size_t aCertBufferSize) +{ + Error error = kErrorNone; -exit: - return; -} + VerifyOrExit(mSecureTransport.IsStateConnected(), error = kErrorInvalidState); +#if (MBEDTLS_VERSION_NUMBER >= 0x03010000) + VerifyOrExit( + 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 -int SecureTransport::HandleMbedtlsExportKeys(void *aContext, - const unsigned char *aMasterSecret, - const unsigned char *aKeyBlock, - size_t aMacLength, - size_t aKeyLength, - size_t aIvLength) -{ - return static_cast(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength, - aKeyLength, aIvLength); +exit: + return error; } +#endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) -int SecureTransport::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret, - const unsigned char *aKeyBlock, - size_t aMacLength, - size_t aKeyLength, - size_t aIvLength) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +Error SecureTransport::Extension::GetPeerSubjectAttributeByOid(const char *aOid, + size_t aOidLength, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength, + int *aAsn1Type) { - OT_UNUSED_VARIABLE(aMasterSecret); + Error error = kErrorNone; + const mbedtls_asn1_named_data *data; + size_t length; + size_t attributeBufferSize; + mbedtls_x509_crt *peerCert = const_cast(mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl)); - Crypto::Sha256::Hash kek; - Crypto::Sha256 sha256; + VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs); + attributeBufferSize = *aAttributeLength; + *aAttributeLength = 0; - VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8); + VerifyOrExit(aAttributeBuffer != nullptr, error = kErrorNoBufs); + VerifyOrExit(peerCert != nullptr, error = kErrorInvalidState); - sha256.Start(); - sha256.Update(aKeyBlock, 2 * static_cast(aMacLength + aKeyLength + aIvLength)); - sha256.Finish(kek); + data = mbedtls_asn1_find_named_data(&peerCert->subject, aOid, aOidLength); + VerifyOrExit(data != nullptr, error = kErrorNotFound); - Get().SetKek(kek.GetBytes()); + length = data->val.len; + VerifyOrExit(length <= attributeBufferSize, error = kErrorNoBufs); + *aAttributeLength = length; -exit: - return 0; -} + if (aAsn1Type != nullptr) + { + *aAsn1Type = data->val.tag; + } -#endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000) + memcpy(aAttributeBuffer, data->val.p, length); -void SecureTransport::HandleTimer(Timer &aTimer) -{ - static_cast(static_cast(aTimer).GetContext())->HandleTimer(); +exit: + return error; } -void SecureTransport::HandleTimer(void) +Error SecureTransport::Extension::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength) { - if (IsStateConnectingOrConnected()) - { - Process(); - } - else if (IsStateCloseNotify()) - { - if ((mMaxConnectionAttempts > 0) && (mRemainingConnectionAttempts == 0)) - { - Close(); - mConnectEvent = kDisconnectedMaxAttempts; - mAutoCloseCallback.InvokeIfSet(); - } - else - { - SetState(kStateOpen); - mTimer.Stop(); - } - mConnectedCallback.InvokeIfSet(mConnectEvent); - } + const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(&mSecureTransport.mSsl); + + return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); } -void SecureTransport::Process(void) +#endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + +Error SecureTransport::Extension::GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, + uint8_t *aAttributeBuffer, + size_t *aAttributeLength) { - uint8_t buf[kMaxContentLen]; - int rval; - ConnectEvent disconnectEvent; - bool shouldReset; + const mbedtls_x509_crt *cert = &mEcdheEcdsaInfo.mOwnCert; - while (IsStateConnectingOrConnected()) - { - if (IsStateConnecting()) - { - rval = mbedtls_ssl_handshake(&mSsl); + return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); +} - if (IsMbedtlsHandshakeOver(&mSsl)) - { - SetState(kStateConnected); - mConnectEvent = kConnected; - mConnectedCallback.InvokeIfSet(mConnectEvent); - } - } - else - { - rval = mbedtls_ssl_read(&mSsl, buf, sizeof(buf)); +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(0x82), static_cast(0xDF), + 0x2A, 0x00}; // 1.3.6.1.4.1.44970.0 + mbedtls_x509_buf v3_ext; + unsigned char *p, *end, *endExtData; + size_t len; + size_t attributeBufferSize; + mbedtls_x509_buf extnOid; + int ret, isCritical; - if (rval > 0) - { - mReceiveCallback.InvokeIfSet(buf, static_cast(rval)); - continue; - } - } + VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs); + attributeBufferSize = *aAttributeLength; + *aAttributeLength = 0; - // Check `rval` to determine if the connection should be - // disconnected, reset, or if we should wait. + VerifyOrExit(aCert != nullptr, error = kErrorInvalidState); + v3_ext = aCert->v3_ext; + p = v3_ext.p; + VerifyOrExit(p != nullptr, error = kErrorInvalidState); + end = p + v3_ext.len; + VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0, + error = kErrorParse); + VerifyOrExit(end == p + len, error = kErrorParse); - disconnectEvent = kConnected; - shouldReset = true; + VerifyOrExit(aThreadOidDescriptor < 128, error = kErrorNotImplemented); + oid[sizeof(oid) - 1] = static_cast(aThreadOidDescriptor); - switch (rval) - { - case 0: - case MBEDTLS_ERR_SSL_WANT_READ: - case MBEDTLS_ERR_SSL_WANT_WRITE: - shouldReset = false; - break; + while (p < end) + { + isCritical = 0; + VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0, + error = kErrorParse); + endExtData = p + len; - case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: - disconnectEvent = kDisconnectedPeerClosed; - break; + // Get extension ID + VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &extnOid.len, MBEDTLS_ASN1_OID) == 0, error = kErrorParse); + extnOid.tag = MBEDTLS_ASN1_OID; + extnOid.p = p; + p += extnOid.len; - case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: - break; + // Get optional critical + ret = mbedtls_asn1_get_bool(&p, endExtData, &isCritical); + VerifyOrExit(ret == 0 || ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = kErrorParse); - case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: - disconnectEvent = kDisconnectedError; - break; + // Data must be octet string type, see https://datatracker.ietf.org/doc/html/rfc5280#section-4.1 + VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &len, MBEDTLS_ASN1_OCTET_STRING) == 0, error = kErrorParse); + VerifyOrExit(endExtData == p + len, error = kErrorParse); - case MBEDTLS_ERR_SSL_INVALID_MAC: - if (!IsMbedtlsHandshakeOver(&mSsl)) - { - mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC); - disconnectEvent = kDisconnectedError; - } - break; + // TODO: extensions with isCritical == 1 that are unknown should lead to rejection of the entire cert. + if (extnOid.len == sizeof(oid) && memcmp(extnOid.p, oid, sizeof(oid)) == 0) + { + // per RFC 5280, octet string must contain ASN.1 Type Length Value octets + VerifyOrExit(len >= 2, error = kErrorParse); + VerifyOrExit(*(p + 1) == len - 2, error = kErrorParse); // check TLV Length, not Type. + *aAttributeLength = len - 2; // strip the ASN.1 Type Length bytes from embedded TLV - default: - if (!IsMbedtlsHandshakeOver(&mSsl)) + if (aAttributeBuffer != nullptr) { - mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); - disconnectEvent = kDisconnectedError; + VerifyOrExit(*aAttributeLength <= attributeBufferSize, error = kErrorNoBufs); + memcpy(aAttributeBuffer, p + 2, *aAttributeLength); } + error = kErrorNone; break; } - - if (disconnectEvent != kConnected) - { - Disconnect(disconnectEvent); - } - else if (shouldReset) - { - mbedtls_ssl_session_reset(&mSsl); - - if (mCipherSuite == kEcjpakeWithAes128Ccm8) - { - mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength); - } - } - - break; // from `while()` loop - } -} - -void SecureTransport::HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr) -{ - static_cast(aContext)->HandleMbedtlsDebug(aLevel, aFile, aLine, aStr); -} - -void SecureTransport::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr) -{ - LogLevel logLevel = kLogLevelDebg; - - switch (aLevel) - { - case 1: - logLevel = kLogLevelCrit; - break; - - case 2: - logLevel = kLogLevelWarn; - break; - - case 3: - logLevel = kLogLevelInfo; - break; - - case 4: - default: - break; + p += len; } - LogAt(logLevel, "[%u] %s", mSocket.GetSockName().mPort, aStr); - - OT_UNUSED_VARIABLE(aStr); - OT_UNUSED_VARIABLE(aFile); - OT_UNUSED_VARIABLE(aLine); - OT_UNUSED_VARIABLE(logLevel); -} - -#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) - -const char *SecureTransport::StateToString(State aState) -{ - static const char *const kStateStrings[] = { - "Closed", // (0) kStateClosed - "Open", // (1) kStateOpen - "Initializing", // (2) kStateInitializing - "Connecting", // (3) kStateConnecting - "Connected", // (4) kStateConnected - "CloseNotify", // (5) kStateCloseNotify - }; - - struct EnumCheck - { - InitEnumValidatorCounter(); - ValidateNextEnum(kStateClosed); - ValidateNextEnum(kStateOpen); - ValidateNextEnum(kStateInitializing); - ValidateNextEnum(kStateConnecting); - ValidateNextEnum(kStateConnected); - ValidateNextEnum(kStateCloseNotify); - }; - - return kStateStrings[aState]; +exit: + return error; } -#endif +#endif // OPENTHREAD_CONFIG_TLS_API_ENABLE } // namespace MeshCoP } // namespace ot