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