Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021-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 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 : #pragma once
27 :
28 : #include <credentials/CHIPCert.h>
29 : #include <credentials/CertificateValidityPolicy.h>
30 : #include <credentials/FabricTable.h>
31 : #include <credentials/GroupDataProvider.h>
32 : #include <crypto/CHIPCryptoPAL.h>
33 : #include <lib/core/ScopedNodeId.h>
34 : #include <lib/core/TLV.h>
35 : #include <lib/support/Base64.h>
36 : #include <lib/support/CHIPMem.h>
37 : #include <messaging/ExchangeContext.h>
38 : #include <messaging/ExchangeDelegate.h>
39 : #include <messaging/ReliableMessageProtocolConfig.h>
40 : #include <protocols/secure_channel/CASEDestinationId.h>
41 : #include <protocols/secure_channel/Constants.h>
42 : #include <protocols/secure_channel/PairingSession.h>
43 : #include <protocols/secure_channel/SessionEstablishmentExchangeDispatch.h>
44 : #include <protocols/secure_channel/SessionResumptionStorage.h>
45 : #include <system/SystemClock.h>
46 : #include <system/SystemPacketBuffer.h>
47 : #include <system/TLVPacketBufferBackingStore.h>
48 : #include <transport/CryptoContext.h>
49 : #include <transport/raw/MessageHeader.h>
50 : #include <transport/raw/PeerAddress.h>
51 :
52 : namespace chip {
53 :
54 : // TODO: temporary derive from Messaging::UnsolicitedMessageHandler, actually the CASEServer should be the umh, it will be fixed
55 : // when implementing concurrent CASE session.
56 : class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
57 : public Messaging::ExchangeDelegate,
58 : public FabricTable::Delegate,
59 : public PairingSession
60 : {
61 : public:
62 : ~CASESession() override;
63 :
64 1 : Transport::SecureSession::Type GetSecureSessionType() const override { return Transport::SecureSession::Type::kCASE; }
65 129 : ScopedNodeId GetPeer() const override { return ScopedNodeId(mPeerNodeId, GetFabricIndex()); }
66 16 : ScopedNodeId GetLocalScopedNodeId() const override { return ScopedNodeId(mLocalNodeId, GetFabricIndex()); }
67 16 : CATValues GetPeerCATs() const override { return mPeerCATs; };
68 :
69 : /**
70 : * @brief
71 : * Initialize using configured fabrics and wait for session establishment requests (as a responder).
72 : *
73 : * @param sessionManager session manager from which to allocate a secure session object
74 : * @param fabricTable Table of fabrics that are currently configured on the device
75 : * @param policy Optional application-provided certificate validity policy
76 : * @param delegate Callback object
77 : * @param previouslyEstablishedPeer If a session had previously been established successfully to a peer, this should
78 : * be set to its scoped node-id. Else, this should be initialized to a
79 : * default-constructed ScopedNodeId().
80 : * @param mrpLocalConfig MRP configuration to encode into Sigma2. If not provided, it won't be encoded.
81 : *
82 : * @return CHIP_ERROR The result of initialization
83 : */
84 : CHIP_ERROR PrepareForSessionEstablishment(SessionManager & sessionManager, FabricTable * fabricTable,
85 : SessionResumptionStorage * sessionResumptionStorage,
86 : Credentials::CertificateValidityPolicy * policy,
87 : SessionEstablishmentDelegate * delegate,
88 : const ScopedNodeId & previouslyEstablishedPeer,
89 : Optional<ReliableMessageProtocolConfig> mrpLocalConfig);
90 :
91 : /**
92 : * @brief
93 : * Create and send session establishment request (as an initiator) using device's operational credentials.
94 : *
95 : * @param sessionManager session manager from which to allocate a secure session object
96 : * @param fabricTable The fabric table that contains a fabric in common with the peer
97 : * @param peerScopedNodeId Node to which we want to establish a session
98 : * @param exchangeCtxt The exchange context to send and receive messages with the peer
99 : * @param policy Optional application-provided certificate validity policy
100 : * @param delegate Callback object
101 : *
102 : * @return CHIP_ERROR The result of initialization
103 : */
104 : CHIP_ERROR
105 : EstablishSession(SessionManager & sessionManager, FabricTable * fabricTable, ScopedNodeId peerScopedNodeId,
106 : Messaging::ExchangeContext * exchangeCtxt, SessionResumptionStorage * sessionResumptionStorage,
107 : Credentials::CertificateValidityPolicy * policy, SessionEstablishmentDelegate * delegate,
108 : Optional<ReliableMessageProtocolConfig> mrpLocalConfig);
109 :
110 : /**
111 : * @brief Set the Group Data Provider which will be used to look up IPKs
112 : *
113 : * The GroupDataProvider set MUST have key sets available through `GetIpkKeySet` method
114 : * for the FabricIndex that is associated with the CASESession's FabricInfo.
115 : *
116 : * @param groupDataProvider - Pointer to the group data provider (if nullptr, will error at start of
117 : * establishment, not here).
118 : */
119 1 : void SetGroupDataProvider(Credentials::GroupDataProvider * groupDataProvider) { mGroupDataProvider = groupDataProvider; }
120 :
121 : /**
122 : * @brief
123 : * Derive a secure session from the established session. The API will return error if called before session is established.
124 : *
125 : * @param session Reference to the secure session that will be initialized once session establishment is complete
126 : * @return CHIP_ERROR The result of session derivation
127 : */
128 : CHIP_ERROR DeriveSecureSession(CryptoContext & session) override;
129 :
130 : //// UnsolicitedMessageHandler Implementation ////
131 3 : CHIP_ERROR OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate) override
132 : {
133 3 : newDelegate = this;
134 3 : return CHIP_NO_ERROR;
135 : }
136 :
137 : //// ExchangeDelegate Implementation ////
138 : CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
139 : System::PacketBufferHandle && payload) override;
140 : void OnResponseTimeout(Messaging::ExchangeContext * ec) override;
141 23 : Messaging::ExchangeMessageDispatch & GetMessageDispatch() override { return SessionEstablishmentExchangeDispatch::Instance(); }
142 :
143 : //// SessionDelegate ////
144 : void OnSessionReleased() override;
145 :
146 : //// FabricTable::Delegate Implementation ////
147 0 : void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override
148 : {
149 : (void) fabricTable;
150 0 : InvalidateIfPendingEstablishmentOnFabric(fabricIndex);
151 0 : }
152 5 : void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override
153 : {
154 : (void) fabricTable;
155 5 : InvalidateIfPendingEstablishmentOnFabric(fabricIndex);
156 5 : }
157 :
158 145 : FabricIndex GetFabricIndex() const { return mFabricIndex; }
159 :
160 : // Compute our Sigma1 response timeout. This can give consumers an idea of
161 : // how long it will take to detect that our Sigma1 did not get through.
162 : static System::Clock::Timeout ComputeSigma1ResponseTimeout(const ReliableMessageProtocolConfig & remoteMrpConfig);
163 :
164 : // Compute our Sigma2 response timeout. This can give consumers an idea of
165 : // how long it will take to detect that our Sigma1 did not get through.
166 : static System::Clock::Timeout ComputeSigma2ResponseTimeout(const ReliableMessageProtocolConfig & remoteMrpConfig);
167 :
168 : // TODO: remove Clear, we should create a new instance instead reset the old instance.
169 : /** @brief This function zeroes out and resets the memory used by the object.
170 : **/
171 : void Clear();
172 :
173 : enum class State : uint8_t
174 : {
175 : kInitialized = 0,
176 : kSentSigma1 = 1,
177 : kSentSigma2 = 2,
178 : kSentSigma3 = 3,
179 : kSentSigma1Resume = 4,
180 : kSentSigma2Resume = 5,
181 : kFinished = 6,
182 : kFinishedViaResume = 7,
183 : kSendSigma3Pending = 8,
184 : kHandleSigma3Pending = 9,
185 : };
186 :
187 9 : State GetState() { return mState; }
188 :
189 : // Returns true if the CASE session handshake was stuck due to failing to schedule work on the Matter thread.
190 : // If this function returns true, the CASE session has been reset and is ready for a new session establishment.
191 : bool InvokeBackgroundWorkWatchdog();
192 :
193 : protected:
194 : // Helper Enum for use in HandleSigma1_and_SendSigma2
195 : enum class Step : uint8_t
196 : {
197 : kSendSigma2,
198 : kSendSigma2Resume,
199 : };
200 : // Making NextStep a Variant allows HandleSigma() to return either a Step value (indicating
201 : // the next Sigma step to send) or a CHIP_ERROR (indicating a failure that will trigger
202 : // a Status Report).
203 : using NextStep = Variant<Step, CHIP_ERROR>;
204 : // This struct only serves as a base struct for EncodeSigma1Inputs and ParsedSigma1
205 : struct Sigma1Param
206 : {
207 : ByteSpan initiatorRandom;
208 : uint16_t initiatorSessionId;
209 : ByteSpan destinationId;
210 : bool sessionResumptionRequested = false;
211 : ByteSpan resumptionId;
212 : ByteSpan initiatorResumeMIC;
213 : };
214 :
215 : struct EncodeSigma1Inputs : Sigma1Param
216 : {
217 : const Crypto::P256PublicKey * initiatorEphPubKey = nullptr;
218 : const ReliableMessageProtocolConfig * initiatorMrpConfig = nullptr;
219 : uint8_t initiatorResume1MICBuffer[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES];
220 : };
221 :
222 : struct ParsedSigma1 : Sigma1Param
223 : {
224 : // Backed by: Sigma1 PacketBuffer passed to the method HandleSigma1()
225 : // Lifetime: Valid for the lifetime of the TLVReader, which takes ownership of the Sigma1 PacketBuffer in the HandleSigma1()
226 : // method.
227 : ByteSpan initiatorEphPubKey;
228 : bool initiatorSessionParamStructPresent = false;
229 : SessionParameters initiatorSessionParams;
230 : };
231 :
232 : struct EncodeSigma2Inputs
233 : {
234 : uint8_t responderRandom[kSigmaParamRandomNumberSize];
235 : uint16_t responderSessionId;
236 : const Crypto::P256PublicKey * responderEphPubKey = nullptr;
237 : // ScopedMemoryBufferWithSize is not used for msgR2Encrypted since encrypted2Length might differ from the allocated buffer
238 : // size
239 : Platform::ScopedMemoryBuffer<uint8_t> msgR2Encrypted;
240 : size_t encrypted2Length = 0;
241 : const ReliableMessageProtocolConfig * responderMrpConfig;
242 : };
243 : struct ParsedSigma2
244 : {
245 : // Below ByteSpans are Backed by: Sigma2 PacketBuffer passed to the method HandleSigma2()
246 : // Lifetime: Valid for the lifetime of the TLVReader, which takes ownership of the Sigma2 PacketBuffer in the HandleSigma2()
247 : // method.
248 : ByteSpan responderRandom;
249 : ByteSpan responderEphPubKey;
250 :
251 : Platform::ScopedMemoryBufferWithSize<uint8_t> msgR2Encrypted;
252 : Platform::ScopedMemoryBufferWithSize<uint8_t> msgR2Decrypted;
253 : // Below ByteSpans are Backed by: msgR2Encrypted buffer
254 : // Lifetime: Valid as long as msgR2Encrypted is not released
255 : MutableByteSpan msgR2EncryptedPayload;
256 : ByteSpan msgR2MIC;
257 : SessionParameters responderSessionParams;
258 : uint16_t responderSessionId;
259 : bool responderSessionParamStructPresent = false;
260 : };
261 :
262 : struct ParsedSigma2TBEData
263 : {
264 : // Below ByteSpans are Backed by: msgR2Decrypted Buffer, member of ParsedSigma2 struct
265 : // Lifetime: Valid for the lifetime of the instance of ParsedSigma2 that contains the msgR2Decrypted Buffer.
266 : ByteSpan responderNOC;
267 : ByteSpan responderICAC;
268 : ByteSpan resumptionId;
269 : Crypto::P256ECDSASignature tbsData2Signature;
270 : };
271 :
272 : struct EncodeSigma2ResumeInputs
273 : {
274 : ByteSpan resumptionId;
275 : uint8_t sigma2ResumeMICBuffer[Crypto::CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES];
276 : MutableByteSpan sigma2ResumeMIC{ sigma2ResumeMICBuffer };
277 : uint16_t responderSessionId;
278 : const ReliableMessageProtocolConfig * responderMrpConfig;
279 : };
280 :
281 : struct ParsedSigma2Resume
282 : {
283 : // Below ByteSpans are Backed by: Sigma2Resume PacketBuffer passed to the method HandleSigma2Resume()
284 : // Lifetime: Valid for the lifetime of the TLVReader, which takes ownership of the Sigma2Resume PacketBuffer in the
285 : // HandleSigma2Resume() method.
286 : ByteSpan resumptionId;
287 : ByteSpan sigma2ResumeMIC;
288 : SessionParameters responderSessionParams;
289 : uint16_t responderSessionId;
290 : bool responderSessionParamStructPresent = false;
291 : };
292 :
293 : struct SendSigma3Data
294 : {
295 : FabricIndex fabricIndex;
296 :
297 : // Use one or the other
298 : const FabricTable * fabricTable;
299 : const Crypto::OperationalKeystore * keystore;
300 :
301 : chip::Platform::ScopedMemoryBuffer<uint8_t> msgR3Signed;
302 : MutableByteSpan msgR3SignedSpan;
303 :
304 : chip::Platform::ScopedMemoryBuffer<uint8_t> msg_R3_Encrypted;
305 : size_t msg_r3_encrypted_len;
306 :
307 : chip::Platform::ScopedMemoryBuffer<uint8_t> icacBuf;
308 : MutableByteSpan icaCert;
309 :
310 : chip::Platform::ScopedMemoryBuffer<uint8_t> nocBuf;
311 : MutableByteSpan nocCert;
312 :
313 : Crypto::P256ECDSASignature tbsData3Signature;
314 : };
315 :
316 : struct HandleSigma3Data
317 : {
318 : chip::Platform::ScopedMemoryBuffer<uint8_t> msgR3Signed;
319 : MutableByteSpan msgR3SignedSpan;
320 :
321 : // Below ByteSpans are Backed by: msgR3Encrypted Buffer, local to the HandleSigma3a() method,
322 : // The Spans are later modified to point to the msgR3Signed member of this struct.
323 : ByteSpan initiatorNOC;
324 : ByteSpan initiatorICAC;
325 :
326 : uint8_t rootCertBuf[Credentials::kMaxCHIPCertLength];
327 : ByteSpan fabricRCAC;
328 :
329 : Crypto::P256ECDSASignature tbsData3Signature;
330 :
331 : FabricId fabricId;
332 : NodeId initiatorNodeId;
333 :
334 : Credentials::ValidationContext validContext;
335 : };
336 :
337 : /**
338 : * @brief Encodes a Sigma1 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle
339 : * outparam.
340 : *
341 : * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the
342 : * method.
343 : *
344 : * @param inParam a struct containing all the values that will be encoded into TLV format
345 : *
346 : **/
347 : static CHIP_ERROR EncodeSigma1(System::PacketBufferHandle & outMsg, EncodeSigma1Inputs & inParam);
348 :
349 : /**
350 : * Parse a Sigma1 message. This function will return success only if the
351 : * message passes schema checks. Specifically:
352 : * * The tags come in order.
353 : * * The required tags are present.
354 : * * The values for the tags that are present satisfy schema requirements
355 : * (e.g. constraints on octet string lengths)
356 : * * Either resumptionID and initiatorResume1MICBuffer are both present or both are
357 : * absent.
358 : *
359 : * On success, the members of outParam will be set to the values corresponding to the message.
360 : * These values will be valid as long as the buffer that the passed-in tlvReader is reading from is valid.
361 : *
362 : * On success, either the sessionResumptionRequested field will be set to true
363 : * and the resumptionID and initiatorResumeMIC fields will be set to
364 : * valid values, or the sessionResumptionRequested field will be set to false.
365 : *
366 : * @note Calls to this function must always be made with a newly created and fresh ParsedSigma1 parameter.
367 : */
368 : static CHIP_ERROR ParseSigma1(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma1 & parsedMessage);
369 :
370 : /**
371 : * Parse a Sigma2 message. This function will return success only if the
372 : * message passes schema checks.
373 : *
374 : * @param tlvReader a reference to the TLVReader that has ownership of the Sigma2 PacketBuffer.
375 : * @param outParsedSigma2 a reference to ParsedSigma2. All members of parsedMessage will stay valid as long as tlvReader is
376 : * valid.
377 : *
378 : * @note Calls to this function must always be made with a newly created and fresh ParsedSigma2 parameter.
379 : **/
380 : static CHIP_ERROR ParseSigma2(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma2 & outParsedSigma2);
381 :
382 : /**
383 : * Parse a decrypted TBEData2Encrypted message. This function will return success only if the message passes schema checks.
384 : *
385 : * @param tlvReader a reference to the TLVReader that points to the decrypted TBEData2Encrypted buffer (i.e.
386 : * msgR2Decrypted member of ParsedSigma2 struct)
387 : * @param outParsedSigma2TBEData a reference to ParsedSigma2TBEData. All members of parsedMessage will stay valid as long
388 : * as the msgR2Decrypted member of ParsedSigma2 is valid
389 : *
390 : * @note Calls to this function must always be made with a newly created and fresh ParsedSigma2TBEData parameter.
391 : **/
392 : static CHIP_ERROR ParseSigma2TBEData(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma2TBEData & outParsedSigma2TBEData);
393 :
394 : /**
395 : * Parse a Sigma2Resume message. This function will return success only if the
396 : * message passes schema checks.
397 : *
398 : * @param tlvReader a reference to the TLVReader that has ownership of the Sigma2Resume PacketBuffer.
399 : * @param outParsedSigma2Resume a reference to ParsedSigma2Resume. All members of parsedMessage will stay valid as long
400 : * as tlvReader is valid.
401 : *
402 : * @note Calls to this function must always be made with a newly created and fresh ParsedSigma2Resume parameter.
403 : **/
404 : static CHIP_ERROR ParseSigma2Resume(TLV::ContiguousBufferTLVReader & tlvReader, ParsedSigma2Resume & outParsedSigma2Resume);
405 :
406 : /**
407 : * @brief Encodes a Sigma2 message into TLV format and allocates a buffer for it, which is owned by the PacketBufferHandle
408 : * outparam.
409 : *
410 : * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the
411 : * method.
412 : *
413 : * @param inParam a struct containing all the values that will be encoded into TLV format
414 : *
415 : * @note The inParam member msgR2Encrypted will be freed after encoding it.
416 : **/
417 :
418 : static CHIP_ERROR EncodeSigma2(System::PacketBufferHandle & outMsg, EncodeSigma2Inputs & inParam);
419 :
420 : /**
421 : * @brief Encodes a Sigma2_Resume message into TLV format and allocates a buffer for it, which is owned by the
422 : * PacketBufferHandle outparam.
423 : *
424 : * @param outMsg PacketBufferHandle passed by reference. A new buffer will be allocated and assigned to it within the
425 : * method.
426 : *
427 : * @param inParam a struct containing all the values that will be encoded into TLV format
428 : *
429 : **/
430 : static CHIP_ERROR EncodeSigma2Resume(System::PacketBufferHandle & outMsg, EncodeSigma2ResumeInputs & inParam);
431 :
432 : /**
433 : * Parse a Sigma3 message. This function will return success only if the
434 : * message passes schema checks.
435 : *
436 : * @param tlvReader a reference to the TLVReader that has ownership of the Sigma3 PacketBuffer.
437 : *
438 : * @param outMsgR3Encrypted The encrypted3 (TBEData3Encrypted) TLV element. This will be a buffer that is owned by the caller
439 : * but is allocated and initialised within ParseSigma3. Calls to this function must always be made with
440 : * a newly created and fresh outMsgR3Encrypted
441 : *
442 : * @param outMsgR3EncryptedPayload reference to a span that will be set to point to the payload of outMsgR3Encrypted within
443 : * ParseSigma3. Calls to this function must always be made with a newly created and fresh
444 : * outMsgR3MIC
445 : *
446 : * @param outMsgR3MIC reference to a span that will be set to point to the MIC of outMsgR3Encrypted within ParseSigma3.
447 : * Calls to this function must always be made with a newly created and fresh outMsgR3MIC
448 : *
449 : * @note all out parameters will be valid as long the Buffer outMsgR3Encrypted is valid.
450 : **/
451 : static CHIP_ERROR ParseSigma3(TLV::ContiguousBufferTLVReader & tlvReader,
452 : Platform::ScopedMemoryBufferWithSize<uint8_t> & outMsgR3Encrypted,
453 : MutableByteSpan & outMsgR3EncryptedPayload, ByteSpan & outMsgR3MIC);
454 :
455 : /**
456 : * Parse a decrypted TBEData3Encrypted message. This function will return success only if the
457 : * message passes schema checks.
458 : *
459 : * @param tlvReader a reference to the TLVReader that points to the decrypted TBEData3Encrypted buffer.
460 : * @param data a reference to HandleSigma3Data.
461 : *
462 : **/
463 : static CHIP_ERROR ParseSigma3TBEData(TLV::ContiguousBufferTLVReader & tlvReader, HandleSigma3Data & data);
464 :
465 : private:
466 : friend class TestCASESession;
467 :
468 : using AutoReleaseSessionKey = Crypto::AutoReleaseSymmetricKey<Crypto::Aes128KeyHandle>;
469 :
470 : /*
471 : * Initialize the object given a reference to the SessionManager, certificate validity policy and a delegate which will be
472 : * notified of any further progress on this session.
473 : *
474 : * If we're either establishing or finished establishing a session to a peer in either initiator or responder
475 : * roles, the node id of that peer should be provided in sessionEvictionHint. Else, it should be initialized
476 : * to a default-constructed ScopedNodeId().
477 : *
478 : */
479 : CHIP_ERROR Init(SessionManager & sessionManager, Credentials::CertificateValidityPolicy * policy,
480 : SessionEstablishmentDelegate * delegate, const ScopedNodeId & sessionEvictionHint);
481 :
482 : // On success, sets mIpk to the correct value for outgoing Sigma1 based on internal state
483 : CHIP_ERROR RecoverInitiatorIpk();
484 : // On success, sets locally maching mFabricInfo in internal state to the entry matched by
485 : // destinationId/initiatorRandom from processing of Sigma1, and sets mIpk to the right IPK.
486 : CHIP_ERROR FindLocalNodeFromDestinationId(const ByteSpan & destinationId, const ByteSpan & initiatorRandom);
487 :
488 : CHIP_ERROR SendSigma1();
489 : CHIP_ERROR HandleSigma1_and_SendSigma2(System::PacketBufferHandle && msg);
490 : NextStep HandleSigma1(System::PacketBufferHandle && msg);
491 : CHIP_ERROR TryResumeSession(SessionResumptionStorage::ConstResumptionIdView resumptionId, ByteSpan resume1MIC,
492 : ByteSpan initiatorRandom);
493 :
494 : CHIP_ERROR PrepareSigma2(EncodeSigma2Inputs & output);
495 : CHIP_ERROR PrepareSigma2Resume(EncodeSigma2ResumeInputs & output);
496 : CHIP_ERROR SendSigma2(System::PacketBufferHandle && msg_R2);
497 : CHIP_ERROR SendSigma2Resume(System::PacketBufferHandle && msg_R2_resume);
498 :
499 : CHIP_ERROR HandleSigma2_and_SendSigma3(System::PacketBufferHandle && msg);
500 : CHIP_ERROR HandleSigma2(System::PacketBufferHandle && msg);
501 : CHIP_ERROR HandleSigma2Resume(System::PacketBufferHandle && msg);
502 :
503 : CHIP_ERROR SendSigma3a();
504 : static CHIP_ERROR SendSigma3b(SendSigma3Data & data, bool & cancel);
505 : CHIP_ERROR SendSigma3c(SendSigma3Data & data, CHIP_ERROR status);
506 :
507 : CHIP_ERROR HandleSigma3a(System::PacketBufferHandle && msg);
508 : static CHIP_ERROR HandleSigma3b(HandleSigma3Data & data, bool & cancel);
509 : CHIP_ERROR HandleSigma3c(HandleSigma3Data & data, CHIP_ERROR status);
510 :
511 : CHIP_ERROR SendSigma2Resume();
512 :
513 : CHIP_ERROR DeriveSigmaKey(const ByteSpan & salt, const ByteSpan & info, AutoReleaseSessionKey & key) const;
514 : CHIP_ERROR ConstructSaltSigma2(const ByteSpan & rand, const Crypto::P256PublicKey & pubkey, const ByteSpan & ipk,
515 : MutableByteSpan & salt);
516 : CHIP_ERROR ConstructTBSData(const ByteSpan & senderNOC, const ByteSpan & senderICAC, const ByteSpan & senderPubKey,
517 : const ByteSpan & receiverPubKey, MutableByteSpan & outTbsData);
518 : CHIP_ERROR ConstructSaltSigma3(const ByteSpan & ipk, MutableByteSpan & salt);
519 :
520 : CHIP_ERROR ConstructSigmaResumeKey(const ByteSpan & initiatorRandom, const ByteSpan & resumptionID, const ByteSpan & skInfo,
521 : const ByteSpan & nonce, AutoReleaseSessionKey & resumeKey);
522 :
523 : CHIP_ERROR GenerateSigmaResumeMIC(const ByteSpan & initiatorRandom, const ByteSpan & resumptionID, const ByteSpan & skInfo,
524 : const ByteSpan & nonce, MutableByteSpan & resumeMIC);
525 : CHIP_ERROR ValidateSigmaResumeMIC(const ByteSpan & resumeMIC, const ByteSpan & initiatorRandom, const ByteSpan & resumptionID,
526 : const ByteSpan & skInfo, const ByteSpan & nonce);
527 :
528 : void OnSuccessStatusReport() override;
529 : CHIP_ERROR OnFailureStatusReport(Protocols::SecureChannel::GeneralStatusCode generalCode, uint16_t protocolCode,
530 : Optional<uintptr_t> protocolData) override;
531 :
532 : void AbortPendingEstablish(CHIP_ERROR err);
533 :
534 : CHIP_ERROR GetHardcodedTime();
535 :
536 : CHIP_ERROR SetEffectiveTime();
537 :
538 : CHIP_ERROR ValidateReceivedMessage(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
539 : const System::PacketBufferHandle & msg);
540 :
541 : void InvalidateIfPendingEstablishmentOnFabric(FabricIndex fabricIndex);
542 :
543 : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
544 : static void HandleConnectionAttemptComplete(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr);
545 : static void HandleConnectionClosed(Transport::ActiveTCPConnectionState * conn, CHIP_ERROR conErr);
546 :
547 : // Context to pass down when connecting to peer
548 : Transport::AppTCPConnectionCallbackCtxt mTCPConnCbCtxt;
549 : // Pointer to the underlying TCP connection state. Returned by the
550 : // TCPConnect() method (on the connection Initiator side) when an
551 : // ActiveTCPConnectionState object is allocated. This connection
552 : // context is used on the CASE Initiator side to facilitate the
553 : // invocation of the callbacks when the connection is established/closed.
554 : //
555 : // This pointer must be nulled out when the connection is closed.
556 : Transport::ActiveTCPConnectionState * mPeerConnState = nullptr;
557 : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
558 :
559 : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
560 : void SetStopSigmaHandshakeAt(Optional<State> state) { mStopHandshakeAtState = state; }
561 : #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
562 :
563 : Crypto::Hash_SHA256_stream mCommissioningHash;
564 : Crypto::P256PublicKey mRemotePubKey;
565 : Crypto::P256Keypair * mEphemeralKey = nullptr;
566 : Crypto::P256ECDHDerivedSecret mSharedSecret;
567 : Credentials::ValidationContext mValidContext;
568 : Credentials::GroupDataProvider * mGroupDataProvider = nullptr;
569 :
570 : uint8_t mMessageDigest[Crypto::kSHA256_Hash_Length];
571 : uint8_t mIPK[kIPKSize];
572 :
573 : SessionResumptionStorage * mSessionResumptionStorage = nullptr;
574 : SessionManager * mSessionManager = nullptr;
575 :
576 : FabricTable * mFabricsTable = nullptr;
577 : FabricIndex mFabricIndex = kUndefinedFabricIndex;
578 : NodeId mPeerNodeId = kUndefinedNodeId;
579 : NodeId mLocalNodeId = kUndefinedNodeId;
580 : CATValues mPeerCATs;
581 :
582 : SessionResumptionStorage::ResumptionIdStorage mResumeResumptionId; // ResumptionId which is used to resume this session
583 : SessionResumptionStorage::ResumptionIdStorage mNewResumptionId; // ResumptionId which is stored to resume future session
584 : // Sigma1 initiator random, maintained to be reused post-Sigma1, such as when generating Sigma2 S2RK key
585 : uint8_t mInitiatorRandom[kSigmaParamRandomNumberSize];
586 :
587 : template <class DATA>
588 : class WorkHelper;
589 : Platform::SharedPtr<WorkHelper<SendSigma3Data>> mSendSigma3Helper;
590 : Platform::SharedPtr<WorkHelper<HandleSigma3Data>> mHandleSigma3Helper;
591 :
592 : State mState;
593 :
594 : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
595 : Optional<State> mStopHandshakeAtState = Optional<State>::Missing();
596 : #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
597 :
598 : SessionEstablishmentStage MapCASEStateToSessionEstablishmentStage(State caseState);
599 : };
600 :
601 : } // namespace chip
|