Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / transport / PASESession.cpp
1 /*
2  *
3  *    Copyright (c) 2020-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 CHIP SPAKE2P Session object that provides
22  *      APIs for constructing spake2p messages and establishing encryption
23  *      keys.
24  *
25  *      The protocol for handling pA, pB, cB and cA is defined in SPAKE2
26  *      Plus specifications.
27  *      (https://www.ietf.org/id/draft-bar-cfrg-spake2plus-01.html)
28  *
29  */
30 #include <transport/PASESession.h>
31
32 #include <inttypes.h>
33 #include <string.h>
34
35 #include <core/CHIPEncoding.h>
36 #include <core/CHIPSafeCasts.h>
37 #include <protocols/Protocols.h>
38 #include <protocols/secure_channel/Constants.h>
39 #include <setup_payload/SetupPayload.h>
40 #include <support/BufferWriter.h>
41 #include <support/CHIPMem.h>
42 #include <support/CodeUtils.h>
43 #include <support/SafeInt.h>
44 #include <transport/SecureSessionMgr.h>
45
46 namespace chip {
47
48 using namespace Crypto;
49
50 const char * kSpake2pContext        = "CHIP PAKE V1 Commissioning";
51 const char * kSpake2pI2RSessionInfo = "Commissioning I2R Key";
52 const char * kSpake2pR2ISessionInfo = "Commissioning R2I Key";
53
54 static constexpr uint32_t kSpake2p_Iteration_Count = 100;
55 static const char * kSpake2pKeyExchangeSalt        = "SPAKE2P Key Salt";
56
57 PASESession::PASESession() {}
58
59 PASESession::~PASESession()
60 {
61     // Let's clear out any security state stored in the object, before destroying it.
62     Clear();
63 }
64
65 void PASESession::Clear()
66 {
67     // This function zeroes out and resets the memory used by the object.
68     // It's done so that no security related information will be leaked.
69     memset(&mPoint[0], 0, sizeof(mPoint));
70     memset(&mPASEVerifier[0][0], 0, sizeof(mPASEVerifier));
71     memset(&mKe[0], 0, sizeof(mKe));
72     mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError;
73
74     // Note: we don't need to explicitly clear the state of mSpake2p object.
75     //       Clearing the following state takes care of it.
76     mCommissioningHash.Clear();
77
78     mIterationCount = 0;
79     mSaltLength     = 0;
80     if (mSalt != nullptr)
81     {
82         chip::Platform::MemoryFree(mSalt);
83         mSalt = nullptr;
84     }
85     mKeLen           = sizeof(mKe);
86     mPairingComplete = false;
87     mComputeVerifier = true;
88     mConnectionState.Reset();
89 }
90
91 CHIP_ERROR PASESession::Serialize(PASESessionSerialized & output)
92 {
93     CHIP_ERROR error       = CHIP_NO_ERROR;
94     uint16_t serializedLen = 0;
95     PASESessionSerializable serializable;
96
97     VerifyOrExit(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
98
99     error = ToSerializable(serializable);
100     SuccessOrExit(error);
101
102     serializedLen = chip::Base64Encode(Uint8::to_const_uchar(reinterpret_cast<uint8_t *>(&serializable)),
103                                        static_cast<uint16_t>(sizeof(serializable)), Uint8::to_char(output.inner));
104     VerifyOrExit(serializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
105     VerifyOrExit(serializedLen < sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
106     output.inner[serializedLen] = '\0';
107
108 exit:
109     return error;
110 }
111
112 CHIP_ERROR PASESession::Deserialize(PASESessionSerialized & input)
113 {
114     CHIP_ERROR error = CHIP_NO_ERROR;
115     PASESessionSerializable serializable;
116     size_t maxlen            = BASE64_ENCODED_LEN(sizeof(serializable));
117     size_t len               = strnlen(Uint8::to_char(input.inner), maxlen);
118     uint16_t deserializedLen = 0;
119
120     VerifyOrExit(len < sizeof(PASESessionSerialized), error = CHIP_ERROR_INVALID_ARGUMENT);
121     VerifyOrExit(CanCastTo<uint16_t>(len), error = CHIP_ERROR_INVALID_ARGUMENT);
122
123     memset(&serializable, 0, sizeof(serializable));
124     deserializedLen =
125         Base64Decode(Uint8::to_const_char(input.inner), static_cast<uint16_t>(len), Uint8::to_uchar((uint8_t *) &serializable));
126
127     VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
128     VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT);
129
130     error = FromSerializable(serializable);
131
132 exit:
133     return error;
134 }
135
136 CHIP_ERROR PASESession::ToSerializable(PASESessionSerializable & serializable)
137 {
138     CHIP_ERROR error = CHIP_NO_ERROR;
139
140     VerifyOrExit(CanCastTo<uint16_t>(mKeLen), error = CHIP_ERROR_INTERNAL);
141
142     memset(&serializable, 0, sizeof(serializable));
143     serializable.mKeLen           = static_cast<uint16_t>(mKeLen);
144     serializable.mPairingComplete = (mPairingComplete) ? 1 : 0;
145     serializable.mLocalKeyId      = mConnectionState.GetLocalKeyID();
146     serializable.mPeerKeyId       = mConnectionState.GetPeerKeyID();
147
148     memcpy(serializable.mKe, mKe, mKeLen);
149
150 exit:
151     return error;
152 }
153
154 CHIP_ERROR PASESession::FromSerializable(const PASESessionSerializable & serializable)
155 {
156     CHIP_ERROR error = CHIP_NO_ERROR;
157
158     mPairingComplete = (serializable.mPairingComplete == 1);
159     mKeLen           = static_cast<size_t>(serializable.mKeLen);
160
161     VerifyOrExit(mKeLen <= sizeof(mKe), error = CHIP_ERROR_INVALID_ARGUMENT);
162     memset(mKe, 0, sizeof(mKe));
163     memcpy(mKe, serializable.mKe, mKeLen);
164
165     mConnectionState.SetLocalKeyID(serializable.mLocalKeyId);
166     mConnectionState.SetPeerKeyID(serializable.mPeerKeyId);
167
168 exit:
169     return error;
170 }
171
172 CHIP_ERROR PASESession::Init(uint16_t myKeyId, uint32_t setupCode, SessionEstablishmentDelegate * delegate)
173 {
174     CHIP_ERROR err = CHIP_NO_ERROR;
175
176     VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
177
178     // Reset any state maintained by PASESession object (in case it's being reused for pairing)
179     Clear();
180
181     err = mCommissioningHash.Begin();
182     SuccessOrExit(err);
183
184     err = mCommissioningHash.AddData(Uint8::from_const_char(kSpake2pContext), strlen(kSpake2pContext));
185     SuccessOrExit(err);
186
187     mDelegate = delegate;
188     mConnectionState.SetLocalKeyID(myKeyId);
189     mSetupPINCode    = setupCode;
190     mComputeVerifier = true;
191
192 exit:
193     return err;
194 }
195
196 CHIP_ERROR PASESession::ComputePASEVerifier(uint32_t setUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
197                                             PASEVerifier & verifier)
198 {
199     uint8_t littleEndianSetupPINCode[sizeof(uint32_t)];
200     Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setUpPINCode);
201
202     return pbkdf2_sha256(littleEndianSetupPINCode, sizeof(littleEndianSetupPINCode), salt, saltLen, pbkdf2IterCount,
203                          sizeof(PASEVerifier), &verifier[0][0]);
204 }
205
206 CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, bool useRandomPIN, uint32_t & setupPIN)
207 {
208     if (useRandomPIN)
209     {
210         ReturnErrorOnFailure(DRBG_get_bytes(reinterpret_cast<uint8_t *>(&setupPIN), sizeof(setupPIN)));
211
212         // Use only kSetupPINCodeFieldLengthInBits bits out of the code
213         setupPIN &= ((1 << kSetupPINCodeFieldLengthInBits) - 1);
214     }
215     else if (setupPIN >= (1 << kSetupPINCodeFieldLengthInBits))
216     {
217         return CHIP_ERROR_INVALID_ARGUMENT;
218     }
219
220     return PASESession::ComputePASEVerifier(setupPIN, kSpake2p_Iteration_Count,
221                                             reinterpret_cast<const unsigned char *>(kSpake2pKeyExchangeSalt),
222                                             strlen(kSpake2pKeyExchangeSalt), verifier);
223 }
224
225 CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen)
226 {
227     CHIP_ERROR err      = CHIP_NO_ERROR;
228     uint8_t context[32] = {
229         0,
230     };
231
232     if (mComputeVerifier)
233     {
234         VerifyOrExit(salt != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
235         VerifyOrExit(saltLen > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
236
237         err = PASESession::ComputePASEVerifier(mSetupPINCode, pbkdf2IterCount, salt, saltLen, mPASEVerifier);
238         SuccessOrExit(err);
239     }
240
241     err = mCommissioningHash.Finish(context);
242     SuccessOrExit(err);
243
244     err = mSpake2p.Init(context, sizeof(context));
245     SuccessOrExit(err);
246
247 exit:
248     return err;
249 }
250
251 CHIP_ERROR PASESession::WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
252                                        uint16_t myKeyId, SessionEstablishmentDelegate * delegate)
253 {
254     CHIP_ERROR err = CHIP_NO_ERROR;
255
256     VerifyOrExit(salt != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
257     VerifyOrExit(saltLen > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
258
259     err = Init(myKeyId, mySetUpPINCode, delegate);
260     SuccessOrExit(err);
261
262     VerifyOrExit(CanCastTo<uint16_t>(saltLen), err = CHIP_ERROR_INVALID_ARGUMENT);
263     mSaltLength = static_cast<uint16_t>(saltLen);
264
265     if (mSalt != nullptr)
266     {
267         chip::Platform::MemoryFree(mSalt);
268         mSalt = nullptr;
269     }
270
271     mSalt = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(mSaltLength));
272     VerifyOrExit(mSalt != nullptr, err = CHIP_ERROR_NO_MEMORY);
273
274     memmove(mSalt, salt, mSaltLength);
275
276     mIterationCount = pbkdf2IterCount;
277
278     mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamRequest;
279     mPairingComplete = false;
280
281     ChipLogDetail(Ble, "Waiting for PBKDF param request");
282
283 exit:
284     if (err != CHIP_NO_ERROR)
285     {
286         Clear();
287     }
288     return err;
289 }
290
291 CHIP_ERROR PASESession::WaitForPairing(const PASEVerifier & verifier, uint16_t myKeyId, SessionEstablishmentDelegate * delegate)
292 {
293     CHIP_ERROR err = WaitForPairing(0, kSpake2p_Iteration_Count, reinterpret_cast<const unsigned char *>(kSpake2pKeyExchangeSalt),
294                                     strlen(kSpake2pKeyExchangeSalt), myKeyId, delegate);
295     SuccessOrExit(err);
296
297     memmove(&mPASEVerifier, verifier, sizeof(verifier));
298     mComputeVerifier = false;
299
300 exit:
301     if (err != CHIP_NO_ERROR)
302     {
303         Clear();
304     }
305     return err;
306 }
307
308 CHIP_ERROR PASESession::AttachHeaderAndSend(Protocols::SecureChannel::MsgType msgType, System::PacketBufferHandle msgBuf)
309 {
310     PayloadHeader payloadHeader;
311
312     payloadHeader.SetMessageType(msgType);
313
314     CHIP_ERROR err = payloadHeader.EncodeBeforeData(msgBuf);
315     SuccessOrExit(err);
316
317     err = mDelegate->SendSessionEstablishmentMessage(PacketHeader().SetEncryptionKeyID(mConnectionState.GetLocalKeyID()),
318                                                      mConnectionState.GetPeerAddress(), std::move(msgBuf));
319     SuccessOrExit(err);
320
321 exit:
322     return err;
323 }
324
325 CHIP_ERROR PASESession::Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, uint16_t myKeyId,
326                              SessionEstablishmentDelegate * delegate)
327 {
328     CHIP_ERROR err = Init(myKeyId, peerSetUpPINCode, delegate);
329     SuccessOrExit(err);
330
331     mConnectionState.SetPeerAddress(peerAddress);
332
333     err = SendPBKDFParamRequest();
334     SuccessOrExit(err);
335
336 exit:
337     if (err != CHIP_NO_ERROR)
338     {
339         Clear();
340     }
341     return err;
342 }
343
344 CHIP_ERROR PASESession::Pair(const Transport::PeerAddress peerAddress, const PASEVerifier & verifier, uint16_t myKeyId,
345                              SessionEstablishmentDelegate * delegate)
346 {
347     CHIP_ERROR err = Init(myKeyId, 0, delegate);
348     SuccessOrExit(err);
349
350     mConnectionState.SetPeerAddress(peerAddress);
351
352     memmove(&mPASEVerifier, verifier, sizeof(verifier));
353     mComputeVerifier = false;
354
355     err = SendPBKDFParamRequest();
356     SuccessOrExit(err);
357
358 exit:
359     if (err != CHIP_NO_ERROR)
360     {
361         Clear();
362     }
363     return err;
364 }
365
366 CHIP_ERROR PASESession::DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session)
367 {
368     CHIP_ERROR err = CHIP_NO_ERROR;
369
370     VerifyOrExit(info != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
371     VerifyOrExit(info_len > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
372     VerifyOrExit(mPairingComplete, err = CHIP_ERROR_INCORRECT_STATE);
373
374     err = session.InitFromSecret(mKe, mKeLen, nullptr, 0, info, info_len);
375     SuccessOrExit(err);
376
377 exit:
378     return err;
379 }
380
381 CHIP_ERROR PASESession::SendPBKDFParamRequest()
382 {
383     CHIP_ERROR err = CHIP_NO_ERROR;
384
385     System::PacketBufferHandle req = System::PacketBufferHandle::New(kPBKDFParamRandomNumberSize);
386     VerifyOrExit(!req.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
387
388     err = DRBG_get_bytes(req->Start(), kPBKDFParamRandomNumberSize);
389     SuccessOrExit(err);
390
391     req->SetDataLength(kPBKDFParamRandomNumberSize);
392
393     // Update commissioning hash with the pbkdf2 param request that's being sent.
394     err = mCommissioningHash.AddData(req->Start(), req->DataLength());
395     SuccessOrExit(err);
396
397     mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamResponse;
398
399     err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PBKDFParamRequest, std::move(req));
400     SuccessOrExit(err);
401
402     ChipLogDetail(Ble, "Sent PBKDF param request");
403
404 exit:
405
406     if (err != CHIP_NO_ERROR)
407     {
408         Clear();
409     }
410     return err;
411 }
412
413 CHIP_ERROR PASESession::HandlePBKDFParamRequest(const PacketHeader & header, const System::PacketBufferHandle & msg)
414 {
415     CHIP_ERROR err = CHIP_NO_ERROR;
416
417     // Request message processing
418     const uint8_t * req = msg->Start();
419     size_t reqlen       = msg->DataLength();
420
421     VerifyOrExit(req != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
422     VerifyOrExit(reqlen == kPBKDFParamRandomNumberSize, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
423
424     ChipLogDetail(Ble, "Received PBKDF param request");
425
426     // Update commissioning hash with the received pbkdf2 param request
427     err = mCommissioningHash.AddData(req, reqlen);
428     SuccessOrExit(err);
429
430     err = SendPBKDFParamResponse();
431     SuccessOrExit(err);
432
433 exit:
434
435     if (err != CHIP_NO_ERROR)
436     {
437         SendErrorMsg(Spake2pErrorType::kUnexpected);
438     }
439     return err;
440 }
441
442 CHIP_ERROR PASESession::SendPBKDFParamResponse()
443 {
444     CHIP_ERROR err = CHIP_NO_ERROR;
445
446     System::PacketBufferHandle resp;
447     static_assert(CHAR_BIT == 8, "Assuming sizeof() returns octets here and for sizeof(mPoint)");
448     size_t resplen = kPBKDFParamRandomNumberSize + sizeof(uint64_t) + sizeof(uint32_t) + mSaltLength;
449
450     size_t sizeof_point = sizeof(mPoint);
451
452     uint8_t * msg = nullptr;
453
454     resp = System::PacketBufferHandle::New(resplen);
455     VerifyOrExit(!resp.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
456
457     msg = resp->Start();
458
459     // Fill in the random value
460     err = DRBG_get_bytes(msg, kPBKDFParamRandomNumberSize);
461     SuccessOrExit(err);
462
463     // Let's construct the rest of the message using BufferWriter
464     {
465         Encoding::LittleEndian::BufferWriter bbuf(&msg[kPBKDFParamRandomNumberSize], resplen - kPBKDFParamRandomNumberSize);
466         bbuf.Put64(mIterationCount);
467         bbuf.Put32(mSaltLength);
468         bbuf.Put(mSalt, mSaltLength);
469         VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_NO_MEMORY);
470     }
471
472     resp->SetDataLength(static_cast<uint16_t>(resplen));
473
474     // Update commissioning hash with the pbkdf2 param response that's being sent.
475     err = mCommissioningHash.AddData(resp->Start(), resp->DataLength());
476     SuccessOrExit(err);
477
478     err = SetupSpake2p(mIterationCount, mSalt, mSaltLength);
479     SuccessOrExit(err);
480
481     err = mSpake2p.ComputeL(mPoint, &sizeof_point, &mPASEVerifier[1][0], kSpake2p_WS_Length);
482     SuccessOrExit(err);
483
484     mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p1;
485
486     err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PBKDFParamResponse, std::move(resp));
487     SuccessOrExit(err);
488
489     ChipLogDetail(Ble, "Sent PBKDF param response");
490
491 exit:
492     return err;
493 }
494
495 CHIP_ERROR PASESession::HandlePBKDFParamResponse(const PacketHeader & header, const System::PacketBufferHandle & msg)
496 {
497     CHIP_ERROR err = CHIP_NO_ERROR;
498
499     // Response message processing
500     const uint8_t * resp = msg->Start();
501     size_t resplen       = msg->DataLength();
502
503     // This the fixed part of the message. The variable part of the message contains the salt.
504     // The length of the variable part is determined by the salt length in the fixed header.
505     static_assert(CHAR_BIT == 8, "Assuming that sizeof returns octets");
506     size_t fixed_resplen = kPBKDFParamRandomNumberSize + sizeof(uint64_t) + sizeof(uint32_t);
507
508     ChipLogDetail(Ble, "Received PBKDF param response");
509
510     VerifyOrExit(resp != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
511     VerifyOrExit(resplen >= fixed_resplen, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
512
513     {
514         // Let's skip the random number portion of the message
515         const uint8_t * msgptr = &resp[kPBKDFParamRandomNumberSize];
516         uint64_t iterCount     = chip::Encoding::LittleEndian::Read64(msgptr);
517         uint32_t saltlen       = chip::Encoding::LittleEndian::Read32(msgptr);
518
519         VerifyOrExit(resplen == fixed_resplen + saltlen, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
520
521         // Specifications allow message to carry a uint64_t sized iteration count. Current APIs are
522         // limiting it to uint32_t. Let's make sure it'll fit the size limit.
523         VerifyOrExit(CanCastTo<uint32_t>(iterCount), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
524
525         // Update commissioning hash with the received pbkdf2 param response
526         err = mCommissioningHash.AddData(resp, resplen);
527         SuccessOrExit(err);
528
529         err = SetupSpake2p(static_cast<uint32_t>(iterCount), msgptr, saltlen);
530         SuccessOrExit(err);
531     }
532
533     err = SendMsg1();
534     SuccessOrExit(err);
535
536 exit:
537     if (err != CHIP_NO_ERROR)
538     {
539         SendErrorMsg(Spake2pErrorType::kUnexpected);
540     }
541     return err;
542 }
543
544 CHIP_ERROR PASESession::SendMsg1()
545 {
546     uint8_t X[kMAX_Point_Length];
547     size_t X_len = sizeof(X);
548
549     System::PacketBufferHandle msg_pA;
550
551     CHIP_ERROR err = mSpake2p.BeginProver(reinterpret_cast<const uint8_t *>(""), 0, reinterpret_cast<const uint8_t *>(""), 0,
552                                           &mPASEVerifier[0][0], kSpake2p_WS_Length, &mPASEVerifier[1][0], kSpake2p_WS_Length);
553     SuccessOrExit(err);
554
555     err = mSpake2p.ComputeRoundOne(X, &X_len);
556     SuccessOrExit(err);
557
558     msg_pA = System::PacketBufferHandle::NewWithData(&X[0], X_len);
559     VerifyOrExit(!msg_pA.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
560
561     mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p2;
562
563     // Call delegate to send the Msg1 to peer
564     err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p1, std::move(msg_pA));
565     SuccessOrExit(err);
566
567     ChipLogDetail(Ble, "Sent spake2p msg1");
568
569 exit:
570     return err;
571 }
572
573 CHIP_ERROR PASESession::HandleMsg1_and_SendMsg2(const PacketHeader & header, const System::PacketBufferHandle & msg)
574 {
575     CHIP_ERROR err = CHIP_NO_ERROR;
576
577     uint8_t Y[kMAX_Point_Length];
578     size_t Y_len = sizeof(Y);
579
580     uint8_t verifier[kMAX_Hash_Length];
581     size_t verifier_len = kMAX_Hash_Length;
582
583     uint16_t data_len; // To be initialized once we compute it.
584
585     const uint8_t * buf = msg->Start();
586     size_t buf_len      = msg->DataLength();
587
588     ChipLogDetail(Ble, "Received spake2p msg1");
589
590     VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
591     VerifyOrExit(buf_len == kMAX_Point_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
592
593     err = mSpake2p.BeginVerifier(reinterpret_cast<const uint8_t *>(""), 0, reinterpret_cast<const uint8_t *>(""), 0,
594                                  &mPASEVerifier[0][0], kSpake2p_WS_Length, mPoint, sizeof(mPoint));
595     SuccessOrExit(err);
596
597     err = mSpake2p.ComputeRoundOne(Y, &Y_len);
598     SuccessOrExit(err);
599
600     err = mSpake2p.ComputeRoundTwo(buf, buf_len, verifier, &verifier_len);
601     SuccessOrExit(err);
602
603     mConnectionState.SetPeerKeyID(header.GetEncryptionKeyID());
604
605     // Make sure our addition doesn't overflow.
606     VerifyOrExit(UINTMAX_MAX - verifier_len >= Y_len, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
607     VerifyOrExit(CanCastTo<uint16_t>(Y_len + verifier_len), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
608     data_len = static_cast<uint16_t>(Y_len + verifier_len);
609
610     {
611         Encoding::PacketBufferWriter bbuf(System::PacketBufferHandle::New(data_len));
612         VerifyOrExit(!bbuf.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
613         bbuf.Put(&Y[0], Y_len);
614         bbuf.Put(verifier, verifier_len);
615         VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_NO_MEMORY);
616
617         mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p3;
618
619         // Call delegate to send the Msg2 to peer
620         err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p2, bbuf.Finalize());
621         SuccessOrExit(err);
622     }
623
624     ChipLogDetail(Ble, "Sent spake2p msg2");
625
626 exit:
627
628     if (err != CHIP_NO_ERROR)
629     {
630         SendErrorMsg(Spake2pErrorType::kUnexpected);
631     }
632     return err;
633 }
634
635 CHIP_ERROR PASESession::HandleMsg2_and_SendMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg)
636 {
637     CHIP_ERROR err = CHIP_NO_ERROR;
638
639     uint8_t verifier[kMAX_Hash_Length];
640     size_t verifier_len_raw = kMAX_Hash_Length;
641     uint16_t verifier_len; // To be inited one we check length is small enough
642
643     const uint8_t * buf = msg->Start();
644     size_t buf_len      = msg->DataLength();
645
646     System::PacketBufferHandle resp;
647
648     Spake2pErrorType spake2pErr = Spake2pErrorType::kUnexpected;
649
650     ChipLogDetail(Ble, "Received spake2p msg2");
651
652     VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
653     VerifyOrExit(buf_len == kMAX_Point_Length + kMAX_Hash_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
654
655     err = mSpake2p.ComputeRoundTwo(buf, kMAX_Point_Length, verifier, &verifier_len_raw);
656     SuccessOrExit(err);
657     VerifyOrExit(CanCastTo<uint16_t>(verifier_len_raw), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
658     verifier_len = static_cast<uint16_t>(verifier_len_raw);
659
660     mConnectionState.SetPeerKeyID(header.GetEncryptionKeyID());
661
662     {
663         Encoding::PacketBufferWriter bbuf(System::PacketBufferHandle::New(verifier_len));
664         VerifyOrExit(!bbuf.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
665
666         bbuf.Put(verifier, verifier_len);
667         VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_NO_MEMORY);
668
669         // Call delegate to send the Msg3 to peer
670         err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p3, bbuf.Finalize());
671         SuccessOrExit(err);
672     }
673
674     ChipLogDetail(Ble, "Sent spake2p msg3");
675
676     {
677         const uint8_t * hash = &buf[kMAX_Point_Length];
678         err                  = mSpake2p.KeyConfirm(hash, kMAX_Hash_Length);
679         if (err != CHIP_NO_ERROR)
680         {
681             spake2pErr = Spake2pErrorType::kInvalidKeyConfirmation;
682             SuccessOrExit(err);
683         }
684
685         err = mSpake2p.GetKeys(mKe, &mKeLen);
686         SuccessOrExit(err);
687     }
688
689     mPairingComplete = true;
690
691     // Call delegate to indicate pairing completion
692     mDelegate->OnSessionEstablished();
693
694 exit:
695
696     if (err != CHIP_NO_ERROR)
697     {
698         SendErrorMsg(spake2pErr);
699     }
700     return err;
701 }
702
703 CHIP_ERROR PASESession::HandleMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg)
704 {
705     CHIP_ERROR err              = CHIP_NO_ERROR;
706     const uint8_t * hash        = msg->Start();
707     Spake2pErrorType spake2pErr = Spake2pErrorType::kUnexpected;
708
709     ChipLogDetail(Ble, "Received spake2p msg3");
710
711     // We will set NextExpectedMsg to PASE_Spake2pError in all cases
712     // However, when we are using IP rendezvous, we might set it to PASE_Spake2p1.
713     mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2pError;
714
715     VerifyOrExit(hash != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
716     VerifyOrExit(msg->DataLength() == kMAX_Hash_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
717     VerifyOrExit(header.GetEncryptionKeyID() == mConnectionState.GetPeerKeyID(), err = CHIP_ERROR_INVALID_KEY_ID);
718
719     err = mSpake2p.KeyConfirm(hash, kMAX_Hash_Length);
720     if (err != CHIP_NO_ERROR)
721     {
722         spake2pErr = Spake2pErrorType::kInvalidKeyConfirmation;
723         SuccessOrExit(err);
724     }
725
726     err = mSpake2p.GetKeys(mKe, &mKeLen);
727     SuccessOrExit(err);
728
729     mPairingComplete = true;
730
731     // Call delegate to indicate pairing completion
732     mDelegate->OnSessionEstablished();
733
734 exit:
735
736     if (err != CHIP_NO_ERROR)
737     {
738         SendErrorMsg(spake2pErr);
739     }
740     return err;
741 }
742
743 void PASESession::SendErrorMsg(Spake2pErrorType errorCode)
744 {
745     CHIP_ERROR err = CHIP_NO_ERROR;
746
747     System::PacketBufferHandle msg;
748     uint16_t msglen        = sizeof(Spake2pErrorMsg);
749     Spake2pErrorMsg * pMsg = nullptr;
750
751     msg = System::PacketBufferHandle::New(msglen);
752     VerifyOrExit(!msg.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
753
754     pMsg        = reinterpret_cast<Spake2pErrorMsg *>(msg->Start());
755     pMsg->error = errorCode;
756
757     msg->SetDataLength(msglen);
758
759     err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2pError, std::move(msg));
760     SuccessOrExit(err);
761
762 exit:
763     Clear();
764 }
765
766 void PASESession::HandleErrorMsg(const PacketHeader & header, const System::PacketBufferHandle & msg)
767 {
768     // Request message processing
769     const uint8_t * buf    = msg->Start();
770     size_t buflen          = msg->DataLength();
771     Spake2pErrorMsg * pMsg = nullptr;
772
773     VerifyOrExit(buf != nullptr, ChipLogError(Ble, "Null error msg received during pairing"));
774     VerifyOrExit(buflen == sizeof(Spake2pErrorMsg), ChipLogError(Ble, "Error msg with incorrect length received during pairing"));
775
776     pMsg = reinterpret_cast<Spake2pErrorMsg *>(msg->Start());
777     ChipLogError(Ble, "Received error (%d) during pairing process", pMsg->error);
778
779 exit:
780     Clear();
781 }
782
783 CHIP_ERROR PASESession::HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
784                                           System::PacketBufferHandle msg)
785 {
786     CHIP_ERROR err = CHIP_NO_ERROR;
787     PayloadHeader payloadHeader;
788
789     VerifyOrExit(!msg.IsNull(), err = CHIP_ERROR_INVALID_ARGUMENT);
790
791     err = payloadHeader.DecodeAndConsume(msg);
792     SuccessOrExit(err);
793
794     VerifyOrExit(payloadHeader.HasMessageType(mNextExpectedMsg), err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
795
796     mConnectionState.SetPeerAddress(peerAddress);
797
798     switch (static_cast<Protocols::SecureChannel::MsgType>(payloadHeader.GetMessageType()))
799     {
800     case Protocols::SecureChannel::MsgType::PBKDFParamRequest:
801         err = HandlePBKDFParamRequest(packetHeader, msg);
802         break;
803
804     case Protocols::SecureChannel::MsgType::PBKDFParamResponse:
805         err = HandlePBKDFParamResponse(packetHeader, msg);
806         break;
807
808     case Protocols::SecureChannel::MsgType::PASE_Spake2p1:
809         err = HandleMsg1_and_SendMsg2(packetHeader, msg);
810         break;
811
812     case Protocols::SecureChannel::MsgType::PASE_Spake2p2:
813         err = HandleMsg2_and_SendMsg3(packetHeader, msg);
814         break;
815
816     case Protocols::SecureChannel::MsgType::PASE_Spake2p3:
817         err = HandleMsg3(packetHeader, msg);
818         break;
819
820     default:
821         err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
822         break;
823     };
824
825 exit:
826
827     // Call delegate to indicate pairing failure
828     if (err != CHIP_NO_ERROR)
829     {
830         mDelegate->OnSessionEstablishmentError(err);
831     }
832
833     return err;
834 }
835
836 } // namespace chip