[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:
Abtin Keshavarzian
2026-06-09 08:40:38 -07:00
committed by GitHub
parent a49c1f5c98
commit 1b80561802
4 changed files with 52 additions and 55 deletions
-14
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+2 -2
View File
@@ -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