3 * Copyright (c) 2021 Project CHIP Authors
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file defines functions for encoding and decoding CHIP messages.
22 * The encoded messages contain CHIP packet header, encrypted payload
23 * header, encrypted payload and message authentication code, as per
24 * CHIP specifications.
28 #include <support/CodeUtils.h>
29 #include <support/SafeInt.h>
30 #include <transport/SecureMessageCodec.h>
32 // Maximum length of application data that can be encrypted as one block.
33 // The limit is derived from IPv6 MTU (1280 bytes) - expected header overheads.
34 // This limit would need additional reviews once we have formalized Secure Transport header.
36 // TODO: this should be checked within the transport message sending instead of the session management layer.
37 static const size_t kMax_SecureSDU_Length = 1024;
41 using System::PacketBuffer;
42 using System::PacketBufferHandle;
44 namespace SecureMessageCodec {
46 CHIP_ERROR Encode(NodeId localNodeId, Transport::PeerConnectionState * state, PayloadHeader & payloadHeader,
47 PacketHeader & packetHeader, System::PacketBufferHandle & msgBuf)
49 VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
50 VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
51 VerifyOrReturnError(msgBuf->TotalLength() < kMax_SecureSDU_Length, CHIP_ERROR_INVALID_MESSAGE_LENGTH);
53 uint32_t msgId = state->GetSendMessageIndex();
55 static_assert(std::is_same<decltype(msgBuf->TotalLength()), uint16_t>::value,
56 "Addition to generate payloadLength might overflow");
59 .SetSourceNodeId(localNodeId) //
60 .SetMessageId(msgId) //
61 .SetEncryptionKeyID(state->GetPeerKeyID());
63 if (state->GetPeerNodeId() != kUndefinedNodeId)
65 packetHeader.SetDestinationNodeId(state->GetPeerNodeId());
68 packetHeader.GetFlags().Set(Header::FlagValues::kSecure);
70 ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(msgBuf));
72 uint8_t * data = msgBuf->Start();
73 uint16_t totalLen = msgBuf->TotalLength();
75 MessageAuthenticationCode mac;
76 ReturnErrorOnFailure(state->EncryptBeforeSend(data, totalLen, data, packetHeader, mac));
79 ReturnErrorOnFailure(mac.Encode(packetHeader, &data[totalLen], msgBuf->AvailableDataLength(), &taglen));
81 VerifyOrReturnError(CanCastTo<uint16_t>(totalLen + taglen), CHIP_ERROR_INTERNAL);
82 msgBuf->SetDataLength(static_cast<uint16_t>(totalLen + taglen));
84 ChipLogDetail(Inet, "Secure message was encrypted: Msg ID %u", msgId);
86 state->IncrementSendMessageIndex();
90 CHIP_ERROR Decode(Transport::PeerConnectionState * state, PayloadHeader & payloadHeader, const PacketHeader & packetHeader,
91 System::PacketBufferHandle & msg)
93 ReturnErrorCodeIf(msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
95 uint8_t * data = msg->Start();
96 uint16_t len = msg->DataLength();
98 PacketBufferHandle origMsg;
99 #if CHIP_SYSTEM_CONFIG_USE_LWIP
100 /* This is a workaround for the case where PacketBuffer payload is not
101 allocated as an inline buffer to PacketBuffer structure */
102 origMsg = std::move(msg);
103 msg = PacketBufferHandle::New(len);
104 VerifyOrReturnError(!msg.IsNull(), CHIP_ERROR_NO_MEMORY);
105 msg->SetDataLength(len);
108 uint16_t footerLen = MessageAuthenticationCode::TagLenForEncryptionType(packetHeader.GetEncryptionType());
109 VerifyOrReturnError(footerLen <= len, CHIP_ERROR_INVALID_MESSAGE_LENGTH);
112 MessageAuthenticationCode mac;
113 ReturnErrorOnFailure(mac.Decode(packetHeader, &data[len - footerLen], footerLen, &taglen));
114 VerifyOrReturnError(taglen == footerLen, CHIP_ERROR_INTERNAL);
116 len = static_cast<uint16_t>(len - taglen);
117 msg->SetDataLength(len);
119 uint8_t * plainText = msg->Start();
120 ReturnErrorOnFailure(state->DecryptOnReceive(data, len, plainText, packetHeader, mac));
122 ReturnErrorOnFailure(payloadHeader.DecodeAndConsume(msg));
123 return CHIP_NO_ERROR;
126 } // namespace SecureMessageCodec