Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / SecureMessageCodec.cpp
1 /*
2  *
3  *    Copyright (c) 2021 Project CHIP Authors
4  *    All rights reserved.
5  *
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
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 /**
20  *    @file
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.
25  *
26  */
27
28 #include <support/CodeUtils.h>
29 #include <support/SafeInt.h>
30 #include <transport/SecureMessageCodec.h>
31
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.
35 //
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;
38
39 namespace chip {
40
41 using System::PacketBuffer;
42 using System::PacketBufferHandle;
43
44 namespace SecureMessageCodec {
45
46 CHIP_ERROR Encode(NodeId localNodeId, Transport::PeerConnectionState * state, PayloadHeader & payloadHeader,
47                   PacketHeader & packetHeader, System::PacketBufferHandle & msgBuf)
48 {
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);
52
53     uint32_t msgId = state->GetSendMessageIndex();
54
55     static_assert(std::is_same<decltype(msgBuf->TotalLength()), uint16_t>::value,
56                   "Addition to generate payloadLength might overflow");
57
58     packetHeader
59         .SetSourceNodeId(localNodeId) //
60         .SetMessageId(msgId)          //
61         .SetEncryptionKeyID(state->GetPeerKeyID());
62
63     if (state->GetPeerNodeId() != kUndefinedNodeId)
64     {
65         packetHeader.SetDestinationNodeId(state->GetPeerNodeId());
66     }
67
68     packetHeader.GetFlags().Set(Header::FlagValues::kSecure);
69
70     ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(msgBuf));
71
72     uint8_t * data    = msgBuf->Start();
73     uint16_t totalLen = msgBuf->TotalLength();
74
75     MessageAuthenticationCode mac;
76     ReturnErrorOnFailure(state->EncryptBeforeSend(data, totalLen, data, packetHeader, mac));
77
78     uint16_t taglen = 0;
79     ReturnErrorOnFailure(mac.Encode(packetHeader, &data[totalLen], msgBuf->AvailableDataLength(), &taglen));
80
81     VerifyOrReturnError(CanCastTo<uint16_t>(totalLen + taglen), CHIP_ERROR_INTERNAL);
82     msgBuf->SetDataLength(static_cast<uint16_t>(totalLen + taglen));
83
84     ChipLogDetail(Inet, "Secure message was encrypted: Msg ID %u", msgId);
85
86     state->IncrementSendMessageIndex();
87     return CHIP_NO_ERROR;
88 }
89
90 CHIP_ERROR Decode(Transport::PeerConnectionState * state, PayloadHeader & payloadHeader, const PacketHeader & packetHeader,
91                   System::PacketBufferHandle & msg)
92 {
93     ReturnErrorCodeIf(msg.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
94
95     uint8_t * data = msg->Start();
96     uint16_t len   = msg->DataLength();
97
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);
106 #endif
107
108     uint16_t footerLen = MessageAuthenticationCode::TagLenForEncryptionType(packetHeader.GetEncryptionType());
109     VerifyOrReturnError(footerLen <= len, CHIP_ERROR_INVALID_MESSAGE_LENGTH);
110
111     uint16_t taglen = 0;
112     MessageAuthenticationCode mac;
113     ReturnErrorOnFailure(mac.Decode(packetHeader, &data[len - footerLen], footerLen, &taglen));
114     VerifyOrReturnError(taglen == footerLen, CHIP_ERROR_INTERNAL);
115
116     len = static_cast<uint16_t>(len - taglen);
117     msg->SetDataLength(len);
118
119     uint8_t * plainText = msg->Start();
120     ReturnErrorOnFailure(state->DecryptOnReceive(data, len, plainText, packetHeader, mac));
121
122     ReturnErrorOnFailure(payloadHeader.DecodeAndConsume(msg));
123     return CHIP_NO_ERROR;
124 }
125
126 } // namespace SecureMessageCodec
127
128 } // namespace chip