Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / CASESession.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 implements the the CHIP CASE Session object that provides
22  *      APIs for constructing a secure session using a certificate from the device's
23  *      operational credentials.
24  *
25  */
26 #include <transport/CASESession.h>
27
28 #include <inttypes.h>
29 #include <string.h>
30
31 #include <core/CHIPEncoding.h>
32 #include <core/CHIPSafeCasts.h>
33 #include <protocols/Protocols.h>
34 #include <support/CHIPMem.h>
35 #include <support/CodeUtils.h>
36 #include <support/SafeInt.h>
37 #include <transport/SecureSessionMgr.h>
38
39 namespace chip {
40
41 using namespace Crypto;
42
43 CASESession::CASESession() {}
44
45 CASESession::~CASESession()
46 {
47     // Let's clear out any security state stored in the object, before destroying it.
48     Clear();
49 }
50
51 void CASESession::Clear()
52 {
53     // This function zeroes out and resets the memory used by the object.
54     // It's done so that no security related information will be leaked.
55     mNextExpectedMsg = Protocols::SecureChannel::MsgType::CASE_SigmaErr;
56     mLocalNodeId     = kUndefinedNodeId;
57     mPairingComplete = false;
58     mConnectionState.Reset();
59 }
60
61 CHIP_ERROR
62 CASESession::WaitForSessionEstablishment(NodeId myNodeId, uint16_t myKeyId, SessionEstablishmentDelegate * delegate)
63 {
64     return CHIP_NO_ERROR;
65 }
66
67 CHIP_ERROR CASESession::AttachHeaderAndSend(Protocols::SecureChannel::MsgType msgType, System::PacketBufferHandle msgBuf)
68 {
69     PayloadHeader payloadHeader;
70
71     payloadHeader.SetMessageType(msgType);
72
73     CHIP_ERROR err = payloadHeader.EncodeBeforeData(msgBuf);
74     SuccessOrExit(err);
75
76     err = mDelegate->SendSessionEstablishmentMessage(PacketHeader()
77                                                          .SetSourceNodeId(mLocalNodeId)
78                                                          .SetDestinationNodeId(mConnectionState.GetPeerNodeId())
79                                                          .SetEncryptionKeyID(mConnectionState.GetLocalKeyID()),
80                                                      mConnectionState.GetPeerAddress(), std::move(msgBuf));
81     SuccessOrExit(err);
82
83 exit:
84     return err;
85 }
86
87 CHIP_ERROR CASESession::EstablishSession(const Transport::PeerAddress peerAddress, NodeId myNodeId, NodeId peerNodeId,
88                                          uint16_t myKeyId, SessionEstablishmentDelegate * delegate)
89 {
90     CHIP_ERROR err = CHIP_NO_ERROR;
91
92     mDelegate = delegate;
93     mConnectionState.SetPeerAddress(peerAddress);
94     mConnectionState.SetPeerNodeId(peerNodeId);
95
96     err = SendSigmaR1();
97     SuccessOrExit(err);
98
99 exit:
100     if (err != CHIP_NO_ERROR)
101     {
102         Clear();
103     }
104     return err;
105 }
106
107 CHIP_ERROR CASESession::DeriveSecureSession(SecureSession & session)
108 {
109     CHIP_ERROR err = CHIP_NO_ERROR;
110
111     VerifyOrExit(mPairingComplete, err = CHIP_ERROR_INCORRECT_STATE);
112
113     // TODO: Use asymmetric keypair to create the secure session
114     // err = session.Init();
115     err = CHIP_ERROR_NOT_IMPLEMENTED;
116     SuccessOrExit(err);
117
118 exit:
119     return err;
120 }
121
122 CHIP_ERROR CASESession::SendSigmaR1()
123 {
124     uint16_t data_len = 0;
125
126     System::PacketBufferHandle msg_R1;
127
128     msg_R1 = System::PacketBufferHandle::New(data_len);
129     VerifyOrReturnError(!msg_R1.IsNull(), CHIP_SYSTEM_ERROR_NO_MEMORY);
130
131     // TODO: Construct SigmaR1 message in form of the following structure
132     // https://github.com/project-chip/connectedhomeip/issues/4469
133     /*
134     struct SigmaR1
135     {
136         uint8_t random[32];
137         uint8_t sessionid[2];
138         TrustedRootIdentifier trusted_roots[];
139         CipherSuite cipher_suites[];
140         KeyShare key_shares[];
141         Extensions extensions[];
142     };
143     */
144
145     msg_R1->SetDataLength(data_len);
146     mNextExpectedMsg = Protocols::SecureChannel::MsgType::CASE_SigmaR2;
147
148     // Call delegate to send the msg to peer
149     ReturnErrorOnFailure(AttachHeaderAndSend(Protocols::SecureChannel::MsgType::CASE_SigmaR1, std::move(msg_R1)));
150
151     ChipLogDetail(Inet, "Sent SigmaR1 msg");
152
153     return CHIP_NO_ERROR;
154 }
155
156 CHIP_ERROR CASESession::HandleSigmaR1_and_SendSigmaR2(const PacketHeader & header, const System::PacketBufferHandle & msg)
157 {
158     CHIP_ERROR err = CHIP_NO_ERROR;
159
160     uint16_t data_len = 0;
161
162     const uint8_t * buf = msg->Start();
163
164     System::PacketBufferHandle msg_R2;
165
166     ChipLogDetail(Inet, "Received SigmaR1 msg");
167
168     VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
169
170     // TODO: Verify received SigmaR1 message.
171     // https://github.com/project-chip/connectedhomeip/issues/4469
172
173     mConnectionState.SetPeerKeyID(header.GetEncryptionKeyID());
174
175     msg_R2 = System::PacketBufferHandle::New(data_len);
176     VerifyOrExit(!msg_R2.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
177
178     // TODO: Construct SigmaR2 message in form of the following structure
179     // https://github.com/project-chip/connectedhomeip/issues/4469
180     /*
181     struct SigmaR2Encrypted
182     {
183         opaque responder_identity;
184         opaque signature;
185     };
186
187     struct SigmaR2
188     {
189         uint8_t[32] random;
190         uint8_t sessionid[2];
191         TrustedRootIdentifier trusted_root;
192         CipherSuite cipher_suite;
193         KeyShare key_share;
194         SigmaR2Encrypted encrypted_r2;
195     };
196     */
197
198     msg_R2->SetDataLength(data_len);
199     mNextExpectedMsg = Protocols::SecureChannel::MsgType::CASE_SigmaR3;
200
201     // Call delegate to send the msg to peer
202     err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::CASE_SigmaR2, std::move(msg_R2));
203     SuccessOrExit(err);
204
205     ChipLogDetail(Inet, "Sent SigmaR2 msg");
206
207 exit:
208
209     if (err != CHIP_NO_ERROR)
210     {
211         SendErrorMsg(SigmaErrorType::kUnexpected);
212     }
213     return err;
214 }
215
216 CHIP_ERROR CASESession::HandleSigmaR2_and_SendSigmaR3(const PacketHeader & header, const System::PacketBufferHandle & msg)
217 {
218     CHIP_ERROR err = CHIP_NO_ERROR;
219
220     uint16_t data_len = 0;
221
222     const uint8_t * buf = msg->Start();
223
224     System::PacketBufferHandle msg_R3;
225
226     ChipLogDetail(Inet, "Received SigmaR2 msg");
227
228     // TODO: Verify received SigmaR2 message.
229     // https://github.com/project-chip/connectedhomeip/issues/4469
230
231     mConnectionState.SetPeerKeyID(header.GetEncryptionKeyID());
232
233     VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
234
235     msg_R3 = System::PacketBufferHandle::New(data_len);
236     VerifyOrExit(!msg_R3.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
237
238     // TODO: Construct SigmaR3 message in form of the following structure
239     // https://github.com/project-chip/connectedhomeip/issues/4469
240     /*
241     struct SigmaR3Encrypted
242     {
243         opaque initiator_identity;
244         opaque signature;
245     };
246
247     struct SigmaR3
248     {
249         SigmaR3Encrypted encrypted_r3;
250     };
251     */
252
253     msg_R3->SetDataLength(data_len);
254
255     // Call delegate to send the Msg3 to peer
256     err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::CASE_SigmaR3, std::move(msg_R3));
257     SuccessOrExit(err);
258
259     ChipLogDetail(Inet, "Sent SigmaR3 msg");
260
261     mPairingComplete = true;
262
263     // Call delegate to indicate pairing completion
264     mDelegate->OnSessionEstablished();
265
266 exit:
267
268     if (err != CHIP_NO_ERROR)
269     {
270         SendErrorMsg(SigmaErrorType::kUnexpected);
271     }
272     return err;
273 }
274
275 CHIP_ERROR CASESession::HandleSigmaR3(const PacketHeader & header, const System::PacketBufferHandle & msg)
276 {
277     CHIP_ERROR err = CHIP_NO_ERROR;
278
279     ChipLogDetail(Inet, "Received SigmaR3 msg");
280
281     // TODO: Verify received SigmaR3 message.
282     // https://github.com/project-chip/connectedhomeip/issues/4469
283
284     mNextExpectedMsg = Protocols::SecureChannel::MsgType::CASE_SigmaErr;
285
286     VerifyOrExit(header.GetSourceNodeId().ValueOr(kUndefinedNodeId) == mConnectionState.GetPeerNodeId(),
287                  err = CHIP_ERROR_WRONG_NODE_ID);
288     VerifyOrExit(header.GetEncryptionKeyID() == mConnectionState.GetPeerKeyID(), err = CHIP_ERROR_INVALID_KEY_ID);
289
290     mPairingComplete = true;
291
292     // Call delegate to indicate pairing completion
293     mDelegate->OnSessionEstablished();
294
295 exit:
296
297     if (err != CHIP_NO_ERROR)
298     {
299         SendErrorMsg(SigmaErrorType::kUnexpected);
300     }
301     return err;
302 }
303
304 void CASESession::SendErrorMsg(SigmaErrorType errorCode)
305 {
306     CHIP_ERROR err = CHIP_NO_ERROR;
307
308     System::PacketBufferHandle msg;
309     uint16_t msglen      = sizeof(SigmaErrorMsg);
310     SigmaErrorMsg * pMsg = nullptr;
311
312     msg = System::PacketBufferHandle::New(msglen);
313     VerifyOrExit(!msg.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
314
315     pMsg        = reinterpret_cast<SigmaErrorMsg *>(msg->Start());
316     pMsg->error = errorCode;
317
318     msg->SetDataLength(msglen);
319
320     err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::CASE_SigmaErr, std::move(msg));
321     SuccessOrExit(err);
322
323 exit:
324     Clear();
325 }
326
327 void CASESession::HandleErrorMsg(const PacketHeader & header, const System::PacketBufferHandle & msg)
328 {
329     // Error message processing
330     const uint8_t * buf  = msg->Start();
331     size_t buflen        = msg->DataLength();
332     SigmaErrorMsg * pMsg = nullptr;
333
334     VerifyOrExit(buf != nullptr, ChipLogError(Inet, "Null error msg received during pairing"));
335     static_assert(sizeof(SigmaErrorMsg) == sizeof(uint8_t),
336                   "Assuming size of SigmaErrorMsg message is 1 octet, so that endian-ness conversion is not needed");
337     VerifyOrExit(buflen == sizeof(SigmaErrorMsg), ChipLogError(Inet, "Error msg with incorrect length received during pairing"));
338
339     pMsg = reinterpret_cast<SigmaErrorMsg *>(msg->Start());
340     ChipLogError(Inet, "Received error (%d) during CASE pairing process", pMsg->error);
341
342 exit:
343     Clear();
344 }
345
346 CHIP_ERROR CASESession::HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
347                                           System::PacketBufferHandle msg)
348 {
349     CHIP_ERROR err = CHIP_NO_ERROR;
350     PayloadHeader payloadHeader;
351
352     Protocols::SecureChannel::MsgType msgType;
353
354     VerifyOrExit(!msg.IsNull(), err = CHIP_ERROR_INVALID_ARGUMENT);
355
356     err = payloadHeader.DecodeAndConsume(msg);
357     SuccessOrExit(err);
358
359     VerifyOrExit(payloadHeader.HasProtocol(Protocols::SecureChannel::Id), err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
360
361     msgType = static_cast<Protocols::SecureChannel::MsgType>(payloadHeader.GetMessageType());
362     VerifyOrExit(msgType == mNextExpectedMsg, err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
363
364     mConnectionState.SetPeerAddress(peerAddress);
365     VerifyOrExit(mLocalNodeId == packetHeader.GetDestinationNodeId().Value(), err = CHIP_ERROR_WRONG_NODE_ID);
366
367     switch (msgType)
368     {
369     case Protocols::SecureChannel::MsgType::CASE_SigmaR1:
370         err = HandleSigmaR1_and_SendSigmaR2(packetHeader, msg);
371         break;
372
373     case Protocols::SecureChannel::MsgType::CASE_SigmaR2:
374         err = HandleSigmaR2_and_SendSigmaR3(packetHeader, msg);
375         break;
376
377     case Protocols::SecureChannel::MsgType::CASE_SigmaR3:
378         err = HandleSigmaR3(packetHeader, msg);
379         break;
380
381     case Protocols::SecureChannel::MsgType::CASE_SigmaErr:
382         HandleErrorMsg(packetHeader, msg);
383         break;
384
385     default:
386         SendErrorMsg(SigmaErrorType::kUnexpected);
387         err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
388         break;
389     };
390
391 exit:
392
393     // Call delegate to indicate session establishment failure.
394     if (err != CHIP_NO_ERROR)
395     {
396         mDelegate->OnSessionEstablishmentError(err);
397     }
398
399     return err;
400 }
401
402 } // namespace chip