3 * Copyright (c) 2020-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 implements the CHIP SPAKE2P Session object that provides
22 * APIs for constructing spake2p messages and establishing encryption
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)
30 #include <transport/PASESession.h>
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>
48 using namespace Crypto;
50 const char * kSpake2pContext = "CHIP PAKE V1 Commissioning";
51 const char * kSpake2pI2RSessionInfo = "Commissioning I2R Key";
52 const char * kSpake2pR2ISessionInfo = "Commissioning R2I Key";
54 static constexpr uint32_t kSpake2p_Iteration_Count = 100;
55 static const char * kSpake2pKeyExchangeSalt = "SPAKE2P Key Salt";
57 PASESession::PASESession() {}
59 PASESession::~PASESession()
61 // Let's clear out any security state stored in the object, before destroying it.
65 void PASESession::Clear()
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;
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();
82 chip::Platform::MemoryFree(mSalt);
86 mPairingComplete = false;
87 mComputeVerifier = true;
88 mConnectionState.Reset();
91 CHIP_ERROR PASESession::Serialize(PASESessionSerialized & output)
93 CHIP_ERROR error = CHIP_NO_ERROR;
94 uint16_t serializedLen = 0;
95 PASESessionSerializable serializable;
97 VerifyOrExit(BASE64_ENCODED_LEN(sizeof(serializable)) <= sizeof(output.inner), error = CHIP_ERROR_INVALID_ARGUMENT);
99 error = ToSerializable(serializable);
100 SuccessOrExit(error);
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';
112 CHIP_ERROR PASESession::Deserialize(PASESessionSerialized & input)
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;
120 VerifyOrExit(len < sizeof(PASESessionSerialized), error = CHIP_ERROR_INVALID_ARGUMENT);
121 VerifyOrExit(CanCastTo<uint16_t>(len), error = CHIP_ERROR_INVALID_ARGUMENT);
123 memset(&serializable, 0, sizeof(serializable));
125 Base64Decode(Uint8::to_const_char(input.inner), static_cast<uint16_t>(len), Uint8::to_uchar((uint8_t *) &serializable));
127 VerifyOrExit(deserializedLen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
128 VerifyOrExit(deserializedLen <= sizeof(serializable), error = CHIP_ERROR_INVALID_ARGUMENT);
130 error = FromSerializable(serializable);
136 CHIP_ERROR PASESession::ToSerializable(PASESessionSerializable & serializable)
138 CHIP_ERROR error = CHIP_NO_ERROR;
140 VerifyOrExit(CanCastTo<uint16_t>(mKeLen), error = CHIP_ERROR_INTERNAL);
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();
148 memcpy(serializable.mKe, mKe, mKeLen);
154 CHIP_ERROR PASESession::FromSerializable(const PASESessionSerializable & serializable)
156 CHIP_ERROR error = CHIP_NO_ERROR;
158 mPairingComplete = (serializable.mPairingComplete == 1);
159 mKeLen = static_cast<size_t>(serializable.mKeLen);
161 VerifyOrExit(mKeLen <= sizeof(mKe), error = CHIP_ERROR_INVALID_ARGUMENT);
162 memset(mKe, 0, sizeof(mKe));
163 memcpy(mKe, serializable.mKe, mKeLen);
165 mConnectionState.SetLocalKeyID(serializable.mLocalKeyId);
166 mConnectionState.SetPeerKeyID(serializable.mPeerKeyId);
172 CHIP_ERROR PASESession::Init(uint16_t myKeyId, uint32_t setupCode, SessionEstablishmentDelegate * delegate)
174 CHIP_ERROR err = CHIP_NO_ERROR;
176 VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
178 // Reset any state maintained by PASESession object (in case it's being reused for pairing)
181 err = mCommissioningHash.Begin();
184 err = mCommissioningHash.AddData(Uint8::from_const_char(kSpake2pContext), strlen(kSpake2pContext));
187 mDelegate = delegate;
188 mConnectionState.SetLocalKeyID(myKeyId);
189 mSetupPINCode = setupCode;
190 mComputeVerifier = true;
196 CHIP_ERROR PASESession::ComputePASEVerifier(uint32_t setUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
197 PASEVerifier & verifier)
199 uint8_t littleEndianSetupPINCode[sizeof(uint32_t)];
200 Encoding::LittleEndian::Put32(littleEndianSetupPINCode, setUpPINCode);
202 return pbkdf2_sha256(littleEndianSetupPINCode, sizeof(littleEndianSetupPINCode), salt, saltLen, pbkdf2IterCount,
203 sizeof(PASEVerifier), &verifier[0][0]);
206 CHIP_ERROR PASESession::GeneratePASEVerifier(PASEVerifier & verifier, bool useRandomPIN, uint32_t & setupPIN)
210 ReturnErrorOnFailure(DRBG_get_bytes(reinterpret_cast<uint8_t *>(&setupPIN), sizeof(setupPIN)));
212 // Use only kSetupPINCodeFieldLengthInBits bits out of the code
213 setupPIN &= ((1 << kSetupPINCodeFieldLengthInBits) - 1);
215 else if (setupPIN >= (1 << kSetupPINCodeFieldLengthInBits))
217 return CHIP_ERROR_INVALID_ARGUMENT;
220 return PASESession::ComputePASEVerifier(setupPIN, kSpake2p_Iteration_Count,
221 reinterpret_cast<const unsigned char *>(kSpake2pKeyExchangeSalt),
222 strlen(kSpake2pKeyExchangeSalt), verifier);
225 CHIP_ERROR PASESession::SetupSpake2p(uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen)
227 CHIP_ERROR err = CHIP_NO_ERROR;
228 uint8_t context[32] = {
232 if (mComputeVerifier)
234 VerifyOrExit(salt != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
235 VerifyOrExit(saltLen > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
237 err = PASESession::ComputePASEVerifier(mSetupPINCode, pbkdf2IterCount, salt, saltLen, mPASEVerifier);
241 err = mCommissioningHash.Finish(context);
244 err = mSpake2p.Init(context, sizeof(context));
251 CHIP_ERROR PASESession::WaitForPairing(uint32_t mySetUpPINCode, uint32_t pbkdf2IterCount, const uint8_t * salt, size_t saltLen,
252 uint16_t myKeyId, SessionEstablishmentDelegate * delegate)
254 CHIP_ERROR err = CHIP_NO_ERROR;
256 VerifyOrExit(salt != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
257 VerifyOrExit(saltLen > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
259 err = Init(myKeyId, mySetUpPINCode, delegate);
262 VerifyOrExit(CanCastTo<uint16_t>(saltLen), err = CHIP_ERROR_INVALID_ARGUMENT);
263 mSaltLength = static_cast<uint16_t>(saltLen);
265 if (mSalt != nullptr)
267 chip::Platform::MemoryFree(mSalt);
271 mSalt = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(mSaltLength));
272 VerifyOrExit(mSalt != nullptr, err = CHIP_ERROR_NO_MEMORY);
274 memmove(mSalt, salt, mSaltLength);
276 mIterationCount = pbkdf2IterCount;
278 mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamRequest;
279 mPairingComplete = false;
281 ChipLogDetail(Ble, "Waiting for PBKDF param request");
284 if (err != CHIP_NO_ERROR)
291 CHIP_ERROR PASESession::WaitForPairing(const PASEVerifier & verifier, uint16_t myKeyId, SessionEstablishmentDelegate * delegate)
293 CHIP_ERROR err = WaitForPairing(0, kSpake2p_Iteration_Count, reinterpret_cast<const unsigned char *>(kSpake2pKeyExchangeSalt),
294 strlen(kSpake2pKeyExchangeSalt), myKeyId, delegate);
297 memmove(&mPASEVerifier, verifier, sizeof(verifier));
298 mComputeVerifier = false;
301 if (err != CHIP_NO_ERROR)
308 CHIP_ERROR PASESession::AttachHeaderAndSend(Protocols::SecureChannel::MsgType msgType, System::PacketBufferHandle msgBuf)
310 PayloadHeader payloadHeader;
312 payloadHeader.SetMessageType(msgType);
314 CHIP_ERROR err = payloadHeader.EncodeBeforeData(msgBuf);
317 err = mDelegate->SendSessionEstablishmentMessage(PacketHeader().SetEncryptionKeyID(mConnectionState.GetLocalKeyID()),
318 mConnectionState.GetPeerAddress(), std::move(msgBuf));
325 CHIP_ERROR PASESession::Pair(const Transport::PeerAddress peerAddress, uint32_t peerSetUpPINCode, uint16_t myKeyId,
326 SessionEstablishmentDelegate * delegate)
328 CHIP_ERROR err = Init(myKeyId, peerSetUpPINCode, delegate);
331 mConnectionState.SetPeerAddress(peerAddress);
333 err = SendPBKDFParamRequest();
337 if (err != CHIP_NO_ERROR)
344 CHIP_ERROR PASESession::Pair(const Transport::PeerAddress peerAddress, const PASEVerifier & verifier, uint16_t myKeyId,
345 SessionEstablishmentDelegate * delegate)
347 CHIP_ERROR err = Init(myKeyId, 0, delegate);
350 mConnectionState.SetPeerAddress(peerAddress);
352 memmove(&mPASEVerifier, verifier, sizeof(verifier));
353 mComputeVerifier = false;
355 err = SendPBKDFParamRequest();
359 if (err != CHIP_NO_ERROR)
366 CHIP_ERROR PASESession::DeriveSecureSession(const uint8_t * info, size_t info_len, SecureSession & session)
368 CHIP_ERROR err = CHIP_NO_ERROR;
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);
374 err = session.InitFromSecret(mKe, mKeLen, nullptr, 0, info, info_len);
381 CHIP_ERROR PASESession::SendPBKDFParamRequest()
383 CHIP_ERROR err = CHIP_NO_ERROR;
385 System::PacketBufferHandle req = System::PacketBufferHandle::New(kPBKDFParamRandomNumberSize);
386 VerifyOrExit(!req.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
388 err = DRBG_get_bytes(req->Start(), kPBKDFParamRandomNumberSize);
391 req->SetDataLength(kPBKDFParamRandomNumberSize);
393 // Update commissioning hash with the pbkdf2 param request that's being sent.
394 err = mCommissioningHash.AddData(req->Start(), req->DataLength());
397 mNextExpectedMsg = Protocols::SecureChannel::MsgType::PBKDFParamResponse;
399 err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PBKDFParamRequest, std::move(req));
402 ChipLogDetail(Ble, "Sent PBKDF param request");
406 if (err != CHIP_NO_ERROR)
413 CHIP_ERROR PASESession::HandlePBKDFParamRequest(const PacketHeader & header, const System::PacketBufferHandle & msg)
415 CHIP_ERROR err = CHIP_NO_ERROR;
417 // Request message processing
418 const uint8_t * req = msg->Start();
419 size_t reqlen = msg->DataLength();
421 VerifyOrExit(req != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
422 VerifyOrExit(reqlen == kPBKDFParamRandomNumberSize, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
424 ChipLogDetail(Ble, "Received PBKDF param request");
426 // Update commissioning hash with the received pbkdf2 param request
427 err = mCommissioningHash.AddData(req, reqlen);
430 err = SendPBKDFParamResponse();
435 if (err != CHIP_NO_ERROR)
437 SendErrorMsg(Spake2pErrorType::kUnexpected);
442 CHIP_ERROR PASESession::SendPBKDFParamResponse()
444 CHIP_ERROR err = CHIP_NO_ERROR;
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;
450 size_t sizeof_point = sizeof(mPoint);
452 uint8_t * msg = nullptr;
454 resp = System::PacketBufferHandle::New(resplen);
455 VerifyOrExit(!resp.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
459 // Fill in the random value
460 err = DRBG_get_bytes(msg, kPBKDFParamRandomNumberSize);
463 // Let's construct the rest of the message using BufferWriter
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);
472 resp->SetDataLength(static_cast<uint16_t>(resplen));
474 // Update commissioning hash with the pbkdf2 param response that's being sent.
475 err = mCommissioningHash.AddData(resp->Start(), resp->DataLength());
478 err = SetupSpake2p(mIterationCount, mSalt, mSaltLength);
481 err = mSpake2p.ComputeL(mPoint, &sizeof_point, &mPASEVerifier[1][0], kSpake2p_WS_Length);
484 mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p1;
486 err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PBKDFParamResponse, std::move(resp));
489 ChipLogDetail(Ble, "Sent PBKDF param response");
495 CHIP_ERROR PASESession::HandlePBKDFParamResponse(const PacketHeader & header, const System::PacketBufferHandle & msg)
497 CHIP_ERROR err = CHIP_NO_ERROR;
499 // Response message processing
500 const uint8_t * resp = msg->Start();
501 size_t resplen = msg->DataLength();
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);
508 ChipLogDetail(Ble, "Received PBKDF param response");
510 VerifyOrExit(resp != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
511 VerifyOrExit(resplen >= fixed_resplen, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
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);
519 VerifyOrExit(resplen == fixed_resplen + saltlen, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
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);
525 // Update commissioning hash with the received pbkdf2 param response
526 err = mCommissioningHash.AddData(resp, resplen);
529 err = SetupSpake2p(static_cast<uint32_t>(iterCount), msgptr, saltlen);
537 if (err != CHIP_NO_ERROR)
539 SendErrorMsg(Spake2pErrorType::kUnexpected);
544 CHIP_ERROR PASESession::SendMsg1()
546 uint8_t X[kMAX_Point_Length];
547 size_t X_len = sizeof(X);
549 System::PacketBufferHandle msg_pA;
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);
555 err = mSpake2p.ComputeRoundOne(X, &X_len);
558 msg_pA = System::PacketBufferHandle::NewWithData(&X[0], X_len);
559 VerifyOrExit(!msg_pA.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
561 mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p2;
563 // Call delegate to send the Msg1 to peer
564 err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p1, std::move(msg_pA));
567 ChipLogDetail(Ble, "Sent spake2p msg1");
573 CHIP_ERROR PASESession::HandleMsg1_and_SendMsg2(const PacketHeader & header, const System::PacketBufferHandle & msg)
575 CHIP_ERROR err = CHIP_NO_ERROR;
577 uint8_t Y[kMAX_Point_Length];
578 size_t Y_len = sizeof(Y);
580 uint8_t verifier[kMAX_Hash_Length];
581 size_t verifier_len = kMAX_Hash_Length;
583 uint16_t data_len; // To be initialized once we compute it.
585 const uint8_t * buf = msg->Start();
586 size_t buf_len = msg->DataLength();
588 ChipLogDetail(Ble, "Received spake2p msg1");
590 VerifyOrExit(buf != nullptr, err = CHIP_ERROR_MESSAGE_INCOMPLETE);
591 VerifyOrExit(buf_len == kMAX_Point_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
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));
597 err = mSpake2p.ComputeRoundOne(Y, &Y_len);
600 err = mSpake2p.ComputeRoundTwo(buf, buf_len, verifier, &verifier_len);
603 mConnectionState.SetPeerKeyID(header.GetEncryptionKeyID());
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);
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);
617 mNextExpectedMsg = Protocols::SecureChannel::MsgType::PASE_Spake2p3;
619 // Call delegate to send the Msg2 to peer
620 err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p2, bbuf.Finalize());
624 ChipLogDetail(Ble, "Sent spake2p msg2");
628 if (err != CHIP_NO_ERROR)
630 SendErrorMsg(Spake2pErrorType::kUnexpected);
635 CHIP_ERROR PASESession::HandleMsg2_and_SendMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg)
637 CHIP_ERROR err = CHIP_NO_ERROR;
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
643 const uint8_t * buf = msg->Start();
644 size_t buf_len = msg->DataLength();
646 System::PacketBufferHandle resp;
648 Spake2pErrorType spake2pErr = Spake2pErrorType::kUnexpected;
650 ChipLogDetail(Ble, "Received spake2p msg2");
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);
655 err = mSpake2p.ComputeRoundTwo(buf, kMAX_Point_Length, verifier, &verifier_len_raw);
657 VerifyOrExit(CanCastTo<uint16_t>(verifier_len_raw), err = CHIP_ERROR_INVALID_MESSAGE_LENGTH);
658 verifier_len = static_cast<uint16_t>(verifier_len_raw);
660 mConnectionState.SetPeerKeyID(header.GetEncryptionKeyID());
663 Encoding::PacketBufferWriter bbuf(System::PacketBufferHandle::New(verifier_len));
664 VerifyOrExit(!bbuf.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
666 bbuf.Put(verifier, verifier_len);
667 VerifyOrExit(bbuf.Fit(), err = CHIP_ERROR_NO_MEMORY);
669 // Call delegate to send the Msg3 to peer
670 err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2p3, bbuf.Finalize());
674 ChipLogDetail(Ble, "Sent spake2p msg3");
677 const uint8_t * hash = &buf[kMAX_Point_Length];
678 err = mSpake2p.KeyConfirm(hash, kMAX_Hash_Length);
679 if (err != CHIP_NO_ERROR)
681 spake2pErr = Spake2pErrorType::kInvalidKeyConfirmation;
685 err = mSpake2p.GetKeys(mKe, &mKeLen);
689 mPairingComplete = true;
691 // Call delegate to indicate pairing completion
692 mDelegate->OnSessionEstablished();
696 if (err != CHIP_NO_ERROR)
698 SendErrorMsg(spake2pErr);
703 CHIP_ERROR PASESession::HandleMsg3(const PacketHeader & header, const System::PacketBufferHandle & msg)
705 CHIP_ERROR err = CHIP_NO_ERROR;
706 const uint8_t * hash = msg->Start();
707 Spake2pErrorType spake2pErr = Spake2pErrorType::kUnexpected;
709 ChipLogDetail(Ble, "Received spake2p msg3");
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;
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);
719 err = mSpake2p.KeyConfirm(hash, kMAX_Hash_Length);
720 if (err != CHIP_NO_ERROR)
722 spake2pErr = Spake2pErrorType::kInvalidKeyConfirmation;
726 err = mSpake2p.GetKeys(mKe, &mKeLen);
729 mPairingComplete = true;
731 // Call delegate to indicate pairing completion
732 mDelegate->OnSessionEstablished();
736 if (err != CHIP_NO_ERROR)
738 SendErrorMsg(spake2pErr);
743 void PASESession::SendErrorMsg(Spake2pErrorType errorCode)
745 CHIP_ERROR err = CHIP_NO_ERROR;
747 System::PacketBufferHandle msg;
748 uint16_t msglen = sizeof(Spake2pErrorMsg);
749 Spake2pErrorMsg * pMsg = nullptr;
751 msg = System::PacketBufferHandle::New(msglen);
752 VerifyOrExit(!msg.IsNull(), err = CHIP_SYSTEM_ERROR_NO_MEMORY);
754 pMsg = reinterpret_cast<Spake2pErrorMsg *>(msg->Start());
755 pMsg->error = errorCode;
757 msg->SetDataLength(msglen);
759 err = AttachHeaderAndSend(Protocols::SecureChannel::MsgType::PASE_Spake2pError, std::move(msg));
766 void PASESession::HandleErrorMsg(const PacketHeader & header, const System::PacketBufferHandle & msg)
768 // Request message processing
769 const uint8_t * buf = msg->Start();
770 size_t buflen = msg->DataLength();
771 Spake2pErrorMsg * pMsg = nullptr;
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"));
776 pMsg = reinterpret_cast<Spake2pErrorMsg *>(msg->Start());
777 ChipLogError(Ble, "Received error (%d) during pairing process", pMsg->error);
783 CHIP_ERROR PASESession::HandlePeerMessage(const PacketHeader & packetHeader, const Transport::PeerAddress & peerAddress,
784 System::PacketBufferHandle msg)
786 CHIP_ERROR err = CHIP_NO_ERROR;
787 PayloadHeader payloadHeader;
789 VerifyOrExit(!msg.IsNull(), err = CHIP_ERROR_INVALID_ARGUMENT);
791 err = payloadHeader.DecodeAndConsume(msg);
794 VerifyOrExit(payloadHeader.HasMessageType(mNextExpectedMsg), err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
796 mConnectionState.SetPeerAddress(peerAddress);
798 switch (static_cast<Protocols::SecureChannel::MsgType>(payloadHeader.GetMessageType()))
800 case Protocols::SecureChannel::MsgType::PBKDFParamRequest:
801 err = HandlePBKDFParamRequest(packetHeader, msg);
804 case Protocols::SecureChannel::MsgType::PBKDFParamResponse:
805 err = HandlePBKDFParamResponse(packetHeader, msg);
808 case Protocols::SecureChannel::MsgType::PASE_Spake2p1:
809 err = HandleMsg1_and_SendMsg2(packetHeader, msg);
812 case Protocols::SecureChannel::MsgType::PASE_Spake2p2:
813 err = HandleMsg2_and_SendMsg3(packetHeader, msg);
816 case Protocols::SecureChannel::MsgType::PASE_Spake2p3:
817 err = HandleMsg3(packetHeader, msg);
821 err = CHIP_ERROR_INVALID_MESSAGE_TYPE;
827 // Call delegate to indicate pairing failure
828 if (err != CHIP_NO_ERROR)
830 mDelegate->OnSessionEstablishmentError(err);