mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 09:27:47 +00:00
[mle] introduce AesCcmAuthData for message security processing (#13210)
This commit refactors `Mle::ProcessMessageSecurity()` to use a new packed structure, `AesCcmAuthData`, to represent the authenticated data used during AES-CCM security processing. The `AesCcmAuthData` structure encapsulates the sender and receiver IPv6 addresses along with the Auxiliary Security Header. By packing these fields together, we can pass them as a single contiguous buffer to `AesCcm::Header()`. This eliminates the need for multiple separate calls to `AesCcm::Header()` and allows the removal of the generic template-based `Header<ObjectType>()` method in the `AesCcm` class. Callers to `ProcessMessageSecurity()` have been updated to populate the `AesCcmAuthData` structure before passing it for processing.
This commit is contained in:
@@ -142,20 +142,6 @@ public:
|
||||
*/
|
||||
void Header(const void *aHeader, uint32_t aHeaderLength);
|
||||
|
||||
/**
|
||||
* Processes the header.
|
||||
*
|
||||
* @tparam ObjectType The object type.
|
||||
*
|
||||
* @param[in] aObject A reference to the object to add to header.
|
||||
*/
|
||||
template <typename ObjectType> void Header(const ObjectType &aObject)
|
||||
{
|
||||
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
|
||||
|
||||
Header(&aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the payload.
|
||||
*
|
||||
|
||||
+28
-34
@@ -1499,11 +1499,10 @@ exit:
|
||||
}
|
||||
#endif
|
||||
|
||||
Error Mle::ProcessMessageSecurity(Crypto::AesCcm::Mode aMode,
|
||||
Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
uint16_t aCmdOffset,
|
||||
const SecurityHeader &aHeader)
|
||||
Error Mle::ProcessMessageSecurity(Crypto::AesCcm::Mode aMode,
|
||||
Message &aMessage,
|
||||
uint16_t aCmdOffset,
|
||||
const AesCcmAuthData &aAuthData)
|
||||
{
|
||||
// This method performs MLE message security. Based on `aMode` it
|
||||
// can be used to encrypt and append tag to `aMessage` or to
|
||||
@@ -1528,20 +1527,14 @@ Error Mle::ProcessMessageSecurity(Crypto::AesCcm::Mode aMode,
|
||||
uint8_t tag[kMleSecurityTagSize];
|
||||
Mac::ExtAddress extAddress;
|
||||
uint32_t keySequence;
|
||||
uint16_t payloadLength = aMessage.GetLength() - aCmdOffset;
|
||||
const Ip6::Address *senderAddress = &aMessageInfo.GetSockAddr();
|
||||
const Ip6::Address *receiverAddress = &aMessageInfo.GetPeerAddr();
|
||||
uint16_t payloadLength = aMessage.GetLength() - aCmdOffset;
|
||||
|
||||
switch (aMode)
|
||||
{
|
||||
case Crypto::AesCcm::kEncrypt:
|
||||
// Use the initialized values for `senderAddress`,
|
||||
// `receiverAddress` and `payloadLength`
|
||||
break;
|
||||
|
||||
case Crypto::AesCcm::kDecrypt:
|
||||
senderAddress = &aMessageInfo.GetPeerAddr();
|
||||
receiverAddress = &aMessageInfo.GetSockAddr();
|
||||
// Ensure message contains command field (uint8_t) and
|
||||
// tag. Then exclude the tag from payload to decrypt.
|
||||
VerifyOrExit(aCmdOffset + sizeof(uint8_t) + kMleSecurityTagSize <= aMessage.GetLength(), error = kErrorParse);
|
||||
@@ -1549,21 +1542,18 @@ Error Mle::ProcessMessageSecurity(Crypto::AesCcm::Mode aMode,
|
||||
break;
|
||||
}
|
||||
|
||||
extAddress.SetFromIid(senderAddress->GetIid());
|
||||
nonce.InitFrom(extAddress, aHeader.GetFrameCounter(), Mac::Frame::kSecurityEncMic32);
|
||||
extAddress.SetFromIid(aAuthData.mSenderAddr.GetIid());
|
||||
nonce.InitFrom(extAddress, aAuthData.mSecurityHeader.GetFrameCounter(), Mac::Frame::kSecurityEncMic32);
|
||||
|
||||
keySequence = aHeader.GetKeyId();
|
||||
keySequence = aAuthData.mSecurityHeader.GetKeyId();
|
||||
|
||||
aesCcm.SetKey(keySequence == Get<KeyManager>().GetCurrentKeySequence()
|
||||
? Get<KeyManager>().GetCurrentMleKey()
|
||||
: Get<KeyManager>().GetTemporaryMleKey(keySequence));
|
||||
|
||||
aesCcm.Init(sizeof(Ip6::Address) + sizeof(Ip6::Address) + sizeof(SecurityHeader), payloadLength,
|
||||
kMleSecurityTagSize, &nonce, sizeof(nonce));
|
||||
aesCcm.Init(sizeof(AesCcmAuthData), payloadLength, kMleSecurityTagSize, &nonce, sizeof(nonce));
|
||||
|
||||
aesCcm.Header(*senderAddress);
|
||||
aesCcm.Header(*receiverAddress);
|
||||
aesCcm.Header(aHeader);
|
||||
aesCcm.Header(&aAuthData, sizeof(AesCcmAuthData));
|
||||
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
if (aMode == Crypto::AesCcm::kDecrypt)
|
||||
@@ -1596,7 +1586,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
Error error = kErrorNone;
|
||||
RxInfo rxInfo(aMessage, aMessageInfo);
|
||||
uint8_t securitySuite;
|
||||
SecurityHeader header;
|
||||
AesCcmAuthData authData;
|
||||
uint32_t keySequence;
|
||||
uint32_t frameCounter;
|
||||
Mac::ExtAddress extAddr;
|
||||
@@ -1641,15 +1631,17 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
|
||||
VerifyOrExit(!IsDisabled());
|
||||
VerifyOrExit(securitySuite == k154Security, error = kErrorParse);
|
||||
|
||||
SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(header));
|
||||
SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(authData.mSecurityHeader));
|
||||
|
||||
VerifyOrExit(header.IsSecurityControlValid(), error = kErrorParse);
|
||||
VerifyOrExit(authData.mSecurityHeader.IsSecurityControlValid(), error = kErrorParse);
|
||||
|
||||
keySequence = header.GetKeyId();
|
||||
frameCounter = header.GetFrameCounter();
|
||||
keySequence = authData.mSecurityHeader.GetKeyId();
|
||||
frameCounter = authData.mSecurityHeader.GetFrameCounter();
|
||||
|
||||
SuccessOrExit(
|
||||
error = ProcessMessageSecurity(Crypto::AesCcm::kDecrypt, aMessage, aMessageInfo, aMessage.GetOffset(), header));
|
||||
authData.mSenderAddr = aMessageInfo.GetPeerAddr();
|
||||
authData.mReceiverAddr = aMessageInfo.GetSockAddr();
|
||||
|
||||
SuccessOrExit(error = ProcessMessageSecurity(Crypto::AesCcm::kDecrypt, aMessage, aMessage.GetOffset(), authData));
|
||||
|
||||
IgnoreError(aMessage.ReadAtAndAdvanceOffset(command));
|
||||
|
||||
@@ -3901,18 +3893,20 @@ Error Mle::TxMessage::SendTo(const Ip6::Address &aDestination)
|
||||
|
||||
if (securitySuite == k154Security)
|
||||
{
|
||||
SecurityHeader header;
|
||||
AesCcmAuthData authData;
|
||||
|
||||
// Update the fields in the security header
|
||||
|
||||
IgnoreError(Read(offset, header));
|
||||
header.SetFrameCounter(Get<KeyManager>().GetMleFrameCounter());
|
||||
header.SetKeyId(Get<KeyManager>().GetCurrentKeySequence());
|
||||
Write(offset, header);
|
||||
IgnoreError(Read(offset, authData.mSecurityHeader));
|
||||
authData.mSecurityHeader.SetFrameCounter(Get<KeyManager>().GetMleFrameCounter());
|
||||
authData.mSecurityHeader.SetKeyId(Get<KeyManager>().GetCurrentKeySequence());
|
||||
Write(offset, authData.mSecurityHeader);
|
||||
offset += sizeof(SecurityHeader);
|
||||
|
||||
SuccessOrExit(
|
||||
error = Get<Mle>().ProcessMessageSecurity(Crypto::AesCcm::kEncrypt, *this, messageInfo, offset, header));
|
||||
authData.mSenderAddr = messageInfo.GetSockAddr();
|
||||
authData.mReceiverAddr = messageInfo.GetPeerAddr();
|
||||
|
||||
SuccessOrExit(error = Get<Mle>().ProcessMessageSecurity(Crypto::AesCcm::kEncrypt, *this, offset, authData));
|
||||
|
||||
Get<KeyManager>().IncrementMleFrameCounter();
|
||||
}
|
||||
|
||||
+22
-5
@@ -1829,6 +1829,24 @@ private:
|
||||
uint8_t mKeyIndex;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
static_assert(sizeof(SecurityHeader) == 10, "SecurityHeader is not packed");
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct AesCcmAuthData
|
||||
{
|
||||
// Represents the authenticated data used during MLE AES-CCM
|
||||
// security processing. It includes the sender and receiver
|
||||
// IPv6 addresses followed by the Aux Security Header.
|
||||
|
||||
Ip6::Address mSenderAddr;
|
||||
Ip6::Address mReceiverAddr;
|
||||
SecurityHeader mSecurityHeader;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
static_assert(sizeof(AesCcmAuthData) == 42, "AesCcmAuthData is not packed");
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
class ParentCandidate : public Parent
|
||||
@@ -2385,11 +2403,10 @@ private:
|
||||
bool HasUnregisteredAddress(void) const;
|
||||
bool ShouldRegisterUnicastAddrWithParent(const Ip6::Netif::UnicastAddress &aUnicastAddress) const;
|
||||
bool ShouldRegisterMulticastAddrsWithParent(void) const;
|
||||
Error ProcessMessageSecurity(Crypto::AesCcm::Mode aMode,
|
||||
Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
uint16_t aCmdOffset,
|
||||
const SecurityHeader &aHeader);
|
||||
Error ProcessMessageSecurity(Crypto::AesCcm::Mode aMode,
|
||||
Message &aMessage,
|
||||
uint16_t aCmdOffset,
|
||||
const AesCcmAuthData &aAuthData);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
|
||||
void InformPreviousParent(void);
|
||||
|
||||
@@ -226,7 +226,7 @@ void TestInPlaceAesCcmProcessing(void)
|
||||
|
||||
// Encrypt in place
|
||||
aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
|
||||
aesCcm.Header(header);
|
||||
aesCcm.Header(&header, sizeof(header));
|
||||
aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, Crypto::AesCcm::kEncrypt);
|
||||
|
||||
// Append the tag
|
||||
@@ -237,7 +237,7 @@ void TestInPlaceAesCcmProcessing(void)
|
||||
|
||||
// Decrypt in place
|
||||
aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
|
||||
aesCcm.Header(header);
|
||||
aesCcm.Header(&header, sizeof(header));
|
||||
aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, Crypto::AesCcm::kDecrypt);
|
||||
|
||||
// Check the tag against what is the message
|
||||
|
||||
Reference in New Issue
Block a user