Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2020-2022 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 the CHIP SPAKE2P Session object that provides 22 : * APIs for constructing spake2p messages and establishing encryption 23 : * keys. 24 : * 25 : */ 26 : 27 : #pragma once 28 : 29 : #include <crypto/CHIPCryptoPAL.h> 30 : #include <lib/support/Base64.h> 31 : #include <messaging/ExchangeContext.h> 32 : #include <messaging/ExchangeDelegate.h> 33 : #include <messaging/ExchangeMessageDispatch.h> 34 : #include <protocols/secure_channel/Constants.h> 35 : #include <protocols/secure_channel/PairingSession.h> 36 : #include <protocols/secure_channel/SessionEstablishmentExchangeDispatch.h> 37 : #include <system/SystemPacketBuffer.h> 38 : #include <transport/CryptoContext.h> 39 : #include <transport/raw/MessageHeader.h> 40 : #include <transport/raw/PeerAddress.h> 41 : 42 : namespace chip { 43 : 44 : extern const char kSpake2pI2RSessionInfo[]; 45 : extern const char kSpake2pR2ISessionInfo[]; 46 : 47 : inline constexpr uint16_t kPBKDFParamRandomNumberSize = 32; 48 : 49 : using namespace Crypto; 50 : 51 : struct PASESessionSerialized; 52 : 53 : struct PASESessionSerializable 54 : { 55 : uint16_t mKeLen; 56 : uint8_t mKe[kMAX_Hash_Length]; 57 : uint8_t mPairingComplete; 58 : uint16_t mLocalSessionId; 59 : uint16_t mPeerSessionId; 60 : }; 61 : 62 : class DLL_EXPORT PASESession : public Messaging::UnsolicitedMessageHandler, 63 : public Messaging::ExchangeDelegate, 64 : public PairingSession 65 : { 66 : public: 67 : ~PASESession() override; 68 : 69 7 : Transport::SecureSession::Type GetSecureSessionType() const override { return Transport::SecureSession::Type::kPASE; } 70 40 : ScopedNodeId GetPeer() const override 71 : { 72 40 : return ScopedNodeId(NodeIdFromPAKEKeyId(kDefaultCommissioningPasscodeId), kUndefinedFabricIndex); 73 : } 74 : 75 10 : ScopedNodeId GetLocalScopedNodeId() const override 76 : { 77 : // For PASE, source is always the undefined node ID 78 10 : return ScopedNodeId(); 79 : } 80 : 81 30 : CATValues GetPeerCATs() const override { return CATValues(); }; 82 : 83 : CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override; 84 : 85 : /** 86 : * @brief 87 : * Initialize using PASE verifier and wait for pairing requests. 88 : * 89 : * @param sessionManager session manager from which to allocate a secure session object 90 : * @param verifier PASE verifier to be used for SPAKE2P pairing 91 : * @param pbkdf2IterCount Iteration count for PBKDF2 function 92 : * @param salt Salt to be used for SPAKE2P operation 93 : * @param delegate Callback object 94 : * 95 : * @return CHIP_ERROR The result of initialization 96 : */ 97 : CHIP_ERROR WaitForPairing(SessionManager & sessionManager, const Spake2pVerifier & verifier, uint32_t pbkdf2IterCount, 98 : const ByteSpan & salt, Optional<ReliableMessageProtocolConfig> mrpLocalConfig, 99 : SessionEstablishmentDelegate * delegate); 100 : 101 : /** 102 : * @brief 103 : * Create a pairing request using peer's setup PIN code. 104 : * 105 : * @param sessionManager session manager from which to allocate a secure session object 106 : * @param peerSetUpPINCode Setup PIN code of the peer device 107 : * @param exchangeCtxt The exchange context to send and receive messages with the peer 108 : * Note: It's expected that the caller of this API hands over the 109 : * ownership of the exchangeCtxt to PASESession object. PASESession 110 : * will close the exchange on (successful/failed) handshake completion. 111 : * @param delegate Callback object 112 : * 113 : * @return CHIP_ERROR The result of initialization 114 : */ 115 : CHIP_ERROR Pair(SessionManager & sessionManager, uint32_t peerSetUpPINCode, 116 : Optional<ReliableMessageProtocolConfig> mrpLocalConfig, Messaging::ExchangeContext * exchangeCtxt, 117 : SessionEstablishmentDelegate * delegate); 118 : 119 : /** 120 : * @brief 121 : * Generate a new PASE verifier. 122 : * 123 : * @param verifier The generated PASE verifier 124 : * @param pbkdf2IterCount Iteration count for PBKDF2 function 125 : * @param salt Salt to be used for SPAKE2P operation 126 : * @param useRandomPIN Generate a random setup PIN, if true. Else, use the provided PIN 127 : * @param setupPIN Provided setup PIN (if useRandomPIN is false), or the generated PIN 128 : * 129 : * @return CHIP_ERROR The result of PASE verifier generation 130 : */ 131 : static CHIP_ERROR GeneratePASEVerifier(Spake2pVerifier & verifier, uint32_t pbkdf2IterCount, const ByteSpan & salt, 132 : bool useRandomPIN, uint32_t & setupPIN); 133 : 134 : /** 135 : * @brief 136 : * Derive a secure session from the paired session. The API will return error if called before pairing is established. 137 : * 138 : * @param session Reference to the secure session that will be initialized once pairing is complete 139 : * @return CHIP_ERROR The result of session derivation 140 : */ 141 : CHIP_ERROR DeriveSecureSession(CryptoContext & session) const override; 142 : 143 : // TODO: remove Clear, we should create a new instance instead reset the old instance. 144 : /** @brief This function zeroes out and resets the memory used by the object. 145 : **/ 146 : void Clear(); 147 : 148 : //// ExchangeDelegate Implementation //// 149 : /** 150 : * @brief 151 : * This function is the called by exchange context or exchange manager when it receives 152 : * a CHIP message corresponding to the context, or registered unsolicited message handler. 153 : * 154 : * Note: If the function is called by unsolicited message handler, the ownership of the 155 : * provide exchange context is handed over to PASE Session object. The PASE Session 156 : * object ensures that the exchange will be closed on completion of the handshake. 157 : * 158 : * @param[in] ec A pointer to the ExchangeContext object. 159 : * @param[in] payloadHeader A reference to the PayloadHeader object. 160 : * @param[in] payload A handle to the PacketBuffer object holding the message payload. 161 : */ 162 : CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, 163 : System::PacketBufferHandle && payload) override; 164 : 165 : /** 166 : * @brief 167 : * This function is the protocol callback to invoke when the timeout for the receipt 168 : * of a response message has expired. 169 : * 170 : * @param[in] ec A pointer to the ExchangeContext object. 171 : */ 172 : void OnResponseTimeout(Messaging::ExchangeContext * ec) override; 173 : 174 14 : Messaging::ExchangeMessageDispatch & GetMessageDispatch() override { return SessionEstablishmentExchangeDispatch::Instance(); } 175 : 176 : //// SessionDelegate //// 177 : void OnSessionReleased() override; 178 : 179 : private: 180 : enum Spake2pErrorType : uint8_t 181 : { 182 : kInvalidKeyConfirmation = 0x00, 183 : kUnexpected = 0xff, 184 : }; 185 : 186 : CHIP_ERROR Init(SessionManager & sessionManager, uint32_t setupCode, SessionEstablishmentDelegate * delegate); 187 : 188 : CHIP_ERROR ValidateReceivedMessage(Messaging::ExchangeContext * exchange, const PayloadHeader & payloadHeader, 189 : const System::PacketBufferHandle & msg); 190 : 191 : CHIP_ERROR SetupSpake2p(); 192 : 193 : CHIP_ERROR SendPBKDFParamRequest(); 194 : CHIP_ERROR HandlePBKDFParamRequest(System::PacketBufferHandle && msg); 195 : 196 : CHIP_ERROR SendPBKDFParamResponse(ByteSpan initiatorRandom, bool initiatorHasPBKDFParams); 197 : CHIP_ERROR HandlePBKDFParamResponse(System::PacketBufferHandle && msg); 198 : 199 : CHIP_ERROR SendMsg1(); 200 : 201 : CHIP_ERROR HandleMsg1_and_SendMsg2(System::PacketBufferHandle && msg); 202 : CHIP_ERROR HandleMsg2_and_SendMsg3(System::PacketBufferHandle && msg); 203 : CHIP_ERROR HandleMsg3(System::PacketBufferHandle && msg); 204 : 205 : void OnSuccessStatusReport() override; 206 : CHIP_ERROR OnFailureStatusReport(Protocols::SecureChannel::GeneralStatusCode generalCode, uint16_t protocolCode) override; 207 : 208 : void Finish(); 209 : 210 : // mNextExpectedMsg is set when we are expecting a message. 211 : Optional<Protocols::SecureChannel::MsgType> mNextExpectedMsg; 212 : 213 : Spake2p_P256_SHA256_HKDF_HMAC mSpake2p; 214 : 215 : Spake2pVerifier mPASEVerifier; 216 : 217 : uint32_t mSetupPINCode; 218 : 219 : bool mHavePBKDFParameters = false; 220 : 221 : uint8_t mPBKDFLocalRandomData[kPBKDFParamRandomNumberSize]; 222 : 223 : Hash_SHA256_stream mCommissioningHash; 224 : uint32_t mIterationCount = 0; 225 : uint16_t mSaltLength = 0; 226 : uint8_t * mSalt = nullptr; 227 : 228 : struct Spake2pErrorMsg 229 : { 230 : Spake2pErrorType error; 231 : }; 232 : 233 : protected: 234 : uint8_t mKe[kMAX_Hash_Length]; 235 : 236 : size_t mKeLen = sizeof(mKe); 237 : 238 : bool mPairingComplete = false; 239 : }; 240 : 241 : // The following constants are node IDs that test devices and test controllers use. 242 : inline constexpr chip::NodeId kTestControllerNodeId = 112233; 243 : inline constexpr chip::NodeId kTestDeviceNodeId = 12344321; 244 : 245 : } // namespace chip