Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : * All rights reserved.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * This file implements the CHIP Connection object that maintains a UDP connection.
23 : * TODO This class should be extended to support TCP as well...
24 : *
25 : */
26 :
27 : #include "SessionManager.h"
28 :
29 : #include <inttypes.h>
30 : #include <string.h>
31 :
32 : #include "transport/TraceMessage.h"
33 : #include <app/util/basic-types.h>
34 : #include <credentials/GroupDataProvider.h>
35 : #include <inttypes.h>
36 : #include <lib/core/CHIPKeyIds.h>
37 : #include <lib/core/Global.h>
38 : #include <lib/support/CodeUtils.h>
39 : #include <lib/support/SafeInt.h>
40 : #include <lib/support/logging/CHIPLogging.h>
41 : #include <platform/CHIPDeviceLayer.h>
42 : #include <protocols/Protocols.h>
43 : #include <protocols/secure_channel/Constants.h>
44 : #include <tracing/macros.h>
45 : #include <transport/GroupPeerMessageCounter.h>
46 : #include <transport/GroupSession.h>
47 : #include <transport/SecureMessageCodec.h>
48 : #include <transport/TracingStructs.h>
49 : #include <transport/TransportMgr.h>
50 :
51 : namespace chip {
52 :
53 : using System::PacketBufferHandle;
54 : using Transport::GroupPeerTable;
55 : using Transport::PeerAddress;
56 : using Transport::SecureSession;
57 :
58 : namespace {
59 : Global<GroupPeerTable> gGroupPeerTable;
60 : } // namespace
61 :
62 7876 : uint32_t EncryptedPacketBufferHandle::GetMessageCounter() const
63 : {
64 7876 : PacketHeader header;
65 7876 : uint16_t headerSize = 0;
66 7876 : CHIP_ERROR err = header.Decode((*this)->Start(), (*this)->DataLength(), &headerSize);
67 :
68 7876 : if (err == CHIP_NO_ERROR)
69 : {
70 7876 : return header.GetMessageCounter();
71 : }
72 :
73 0 : ChipLogError(Inet, "Failed to decode EncryptedPacketBufferHandle header with error: %" CHIP_ERROR_FORMAT, err.Format());
74 :
75 0 : return 0;
76 7876 : }
77 :
78 101 : SessionManager::SessionManager() : mState(State::kNotReady) {}
79 :
80 101 : SessionManager::~SessionManager()
81 : {
82 101 : this->Shutdown();
83 101 : }
84 :
85 334 : CHIP_ERROR SessionManager::Init(System::Layer * systemLayer, TransportMgrBase * transportMgr,
86 : Transport::MessageCounterManagerInterface * messageCounterManager,
87 : chip::PersistentStorageDelegate * storageDelegate, FabricTable * fabricTable,
88 : Crypto::SessionKeystore & sessionKeystore)
89 : {
90 334 : VerifyOrReturnError(mState == State::kNotReady, CHIP_ERROR_INCORRECT_STATE);
91 334 : VerifyOrReturnError(transportMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
92 334 : VerifyOrReturnError(storageDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
93 334 : VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
94 334 : ReturnErrorOnFailure(fabricTable->AddFabricDelegate(this));
95 :
96 334 : mState = State::kInitialized;
97 334 : mSystemLayer = systemLayer;
98 334 : mTransportMgr = transportMgr;
99 334 : mMessageCounterManager = messageCounterManager;
100 334 : mFabricTable = fabricTable;
101 334 : mSessionKeystore = &sessionKeystore;
102 :
103 334 : mSecureSessions.Init();
104 :
105 334 : mGlobalUnencryptedMessageCounter.Init();
106 :
107 334 : ReturnErrorOnFailure(mGroupClientCounter.Init(storageDelegate));
108 :
109 334 : mTransportMgr->SetSessionManager(this);
110 :
111 334 : return CHIP_NO_ERROR;
112 : }
113 :
114 434 : void SessionManager::Shutdown()
115 : {
116 434 : if (mFabricTable != nullptr)
117 : {
118 334 : mFabricTable->RemoveFabricDelegate(this);
119 334 : mFabricTable = nullptr;
120 : }
121 :
122 : // Ensure that we don't create new sessions as we iterate our session table.
123 434 : mState = State::kNotReady;
124 :
125 434 : mSecureSessions.ForEachSession([&](auto session) {
126 1204 : session->MarkForEviction();
127 1204 : return Loop::Continue;
128 : });
129 :
130 434 : mMessageCounterManager = nullptr;
131 :
132 434 : mSystemLayer = nullptr;
133 434 : mTransportMgr = nullptr;
134 434 : mCB = nullptr;
135 434 : }
136 :
137 : /**
138 : * @brief Notification that a fabric was removed.
139 : * This function doesn't call ExpireAllSessionsForFabric
140 : * since the CASE session might still be open to send a response
141 : * on the removed fabric.
142 : */
143 5 : void SessionManager::FabricRemoved(FabricIndex fabricIndex)
144 : {
145 5 : gGroupPeerTable->FabricRemoved(fabricIndex);
146 5 : }
147 :
148 9587 : CHIP_ERROR SessionManager::PrepareMessage(const SessionHandle & sessionHandle, PayloadHeader & payloadHeader,
149 : System::PacketBufferHandle && message, EncryptedPacketBufferHandle & preparedMessage)
150 : {
151 : MATTER_TRACE_SCOPE("PrepareMessage", "SessionManager");
152 :
153 9587 : PacketHeader packetHeader;
154 9587 : bool isControlMsg = IsControlMessage(payloadHeader);
155 9587 : if (isControlMsg)
156 : {
157 0 : packetHeader.SetSecureSessionControlMsg(true);
158 : }
159 :
160 : #if CHIP_PROGRESS_LOGGING
161 : NodeId destination;
162 : FabricIndex fabricIndex;
163 : #endif // CHIP_PROGRESS_LOGGING
164 :
165 9587 : PeerAddress destination_address;
166 :
167 9587 : switch (sessionHandle->GetSessionType())
168 : {
169 1 : case Transport::Session::SessionType::kGroupOutgoing: {
170 1 : auto groupSession = sessionHandle->AsOutgoingGroupSession();
171 1 : auto * groups = Credentials::GetGroupDataProvider();
172 1 : VerifyOrReturnError(nullptr != groups, CHIP_ERROR_INTERNAL);
173 :
174 1 : const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
175 1 : VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
176 :
177 1 : packetHeader.SetDestinationGroupId(groupSession->GetGroupId());
178 1 : packetHeader.SetMessageCounter(mGroupClientCounter.GetCounter(isControlMsg));
179 1 : mGroupClientCounter.IncrementCounter(isControlMsg);
180 1 : packetHeader.SetSessionType(Header::SessionType::kGroupSession);
181 1 : NodeId sourceNodeId = fabric->GetNodeId();
182 1 : packetHeader.SetSourceNodeId(sourceNodeId);
183 :
184 1 : if (!packetHeader.IsValidGroupMsg())
185 : {
186 0 : return CHIP_ERROR_INTERNAL;
187 : }
188 :
189 1 : destination_address = Transport::PeerAddress::Multicast(fabric->GetFabricId(), groupSession->GetGroupId());
190 :
191 : // Trace before any encryption
192 : MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kGroupMessage, &payloadHeader, &packetHeader,
193 : chip::ByteSpan(message->Start(), message->TotalLength()));
194 :
195 1 : CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
196 :
197 : Crypto::SymmetricKeyContext * keyContext =
198 1 : groups->GetKeyContext(groupSession->GetFabricIndex(), groupSession->GetGroupId());
199 1 : VerifyOrReturnError(nullptr != keyContext, CHIP_ERROR_INTERNAL);
200 :
201 1 : packetHeader.SetSessionId(keyContext->GetKeyHash());
202 : CryptoContext::NonceStorage nonce;
203 1 : CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(), sourceNodeId);
204 1 : CHIP_ERROR err = SecureMessageCodec::Encrypt(CryptoContext(keyContext), nonce, payloadHeader, packetHeader, message);
205 1 : keyContext->Release();
206 1 : ReturnErrorOnFailure(err);
207 :
208 : #if CHIP_PROGRESS_LOGGING
209 1 : destination = NodeIdFromGroupId(groupSession->GetGroupId());
210 1 : fabricIndex = groupSession->GetFabricIndex();
211 : #endif // CHIP_PROGRESS_LOGGING
212 : }
213 1 : break;
214 9488 : case Transport::Session::SessionType::kSecure: {
215 9488 : SecureSession * session = sessionHandle->AsSecureSession();
216 9488 : if (session == nullptr)
217 : {
218 2 : return CHIP_ERROR_NOT_CONNECTED;
219 : }
220 :
221 9488 : MessageCounter & counter = session->GetSessionMessageCounter().GetLocalMessageCounter();
222 : uint32_t messageCounter;
223 9488 : ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
224 : packetHeader
225 9487 : .SetMessageCounter(messageCounter) //
226 9487 : .SetSessionId(session->GetPeerSessionId()) //
227 9487 : .SetSessionType(Header::SessionType::kUnicastSession);
228 :
229 9487 : destination_address = session->GetPeerAddress();
230 :
231 : // Trace before any encryption
232 : MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kSecureSession, &payloadHeader, &packetHeader,
233 : chip::ByteSpan(message->Start(), message->TotalLength()));
234 9487 : CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
235 :
236 : CryptoContext::NonceStorage nonce;
237 9487 : NodeId sourceNodeId = session->GetLocalScopedNodeId().GetNodeId();
238 9487 : CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), messageCounter, sourceNodeId);
239 :
240 9487 : ReturnErrorOnFailure(SecureMessageCodec::Encrypt(session->GetCryptoContext(), nonce, payloadHeader, packetHeader, message));
241 :
242 : #if CHIP_PROGRESS_LOGGING
243 9486 : destination = session->GetPeerNodeId();
244 9486 : fabricIndex = session->GetFabricIndex();
245 : #endif // CHIP_PROGRESS_LOGGING
246 : }
247 9486 : break;
248 98 : case Transport::Session::SessionType::kUnauthenticated: {
249 98 : MessageCounter & counter = mGlobalUnencryptedMessageCounter;
250 : uint32_t messageCounter;
251 98 : ReturnErrorOnFailure(counter.AdvanceAndConsume(messageCounter));
252 98 : packetHeader.SetMessageCounter(messageCounter);
253 98 : Transport::UnauthenticatedSession * session = sessionHandle->AsUnauthenticatedSession();
254 98 : switch (session->GetSessionRole())
255 : {
256 58 : case Transport::UnauthenticatedSession::SessionRole::kInitiator:
257 58 : packetHeader.SetSourceNodeId(session->GetEphemeralInitiatorNodeID());
258 58 : break;
259 40 : case Transport::UnauthenticatedSession::SessionRole::kResponder:
260 40 : packetHeader.SetDestinationNodeId(session->GetEphemeralInitiatorNodeID());
261 40 : break;
262 : }
263 :
264 98 : auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
265 98 : destination_address = unauthenticated->GetPeerAddress();
266 :
267 : // Trace after all headers are settled.
268 : MATTER_LOG_MESSAGE_SEND(chip::Tracing::OutgoingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
269 : chip::ByteSpan(message->Start(), message->TotalLength()));
270 98 : CHIP_TRACE_MESSAGE_SENT(payloadHeader, packetHeader, destination_address, message->Start(), message->TotalLength());
271 :
272 98 : ReturnErrorOnFailure(payloadHeader.EncodeBeforeData(message));
273 :
274 : #if CHIP_PROGRESS_LOGGING
275 98 : destination = kUndefinedNodeId;
276 98 : fabricIndex = kUndefinedFabricIndex;
277 : #endif // CHIP_PROGRESS_LOGGING
278 : }
279 98 : break;
280 0 : default:
281 0 : return CHIP_ERROR_INTERNAL;
282 : }
283 :
284 : #if CHIP_PROGRESS_LOGGING
285 9585 : CompressedFabricId compressedFabricId = kUndefinedCompressedFabricId;
286 :
287 9585 : if (fabricIndex != kUndefinedFabricIndex && mFabricTable != nullptr)
288 : {
289 9440 : auto fabricInfo = mFabricTable->FindFabricWithIndex(fabricIndex);
290 9440 : if (fabricInfo)
291 : {
292 9440 : compressedFabricId = fabricInfo->GetCompressedFabricId();
293 : }
294 : }
295 :
296 9585 : auto * protocolName = Protocols::GetProtocolName(payloadHeader.GetProtocolID());
297 9585 : auto * msgTypeName = Protocols::GetMessageTypeName(payloadHeader.GetProtocolID(), payloadHeader.GetMessageType());
298 :
299 : //
300 : // 32-bit value maximum = 10 chars + text preamble (6) + trailer (1) + null (1) + 2 buffer = 20
301 : //
302 : char ackBuf[20];
303 9585 : ackBuf[0] = '\0';
304 9585 : if (payloadHeader.GetAckMessageCounter().HasValue())
305 : {
306 7877 : snprintf(ackBuf, sizeof(ackBuf), " (Ack:" ChipLogFormatMessageCounter ")", payloadHeader.GetAckMessageCounter().Value());
307 : }
308 :
309 9585 : char addressStr[Transport::PeerAddress::kMaxToStringSize] = { 0 };
310 9585 : destination_address.ToString(addressStr);
311 :
312 : // Work around pigweed not allowing more than 14 format args in a log
313 : // message when using tokenized logs.
314 : char typeStr[4 + 1 + 2 + 1];
315 9585 : snprintf(typeStr, sizeof(typeStr), "%04X:%02X", payloadHeader.GetProtocolID().GetProtocolId(), payloadHeader.GetMessageType());
316 :
317 : //
318 : // Legend that can be used to decode this log line can be found in messaging/README.md
319 : //
320 9585 : ChipLogProgress(ExchangeManager,
321 : "<<< [E:" ChipLogFormatExchangeId " S:%u M:" ChipLogFormatMessageCounter
322 : "%s] (%s) Msg TX to %u:" ChipLogFormatX64 " [%04X] [%s] --- Type %s (%s:%s)",
323 : ChipLogValueExchangeIdFromSentHeader(payloadHeader), sessionHandle->SessionIdForLogging(),
324 : packetHeader.GetMessageCounter(), ackBuf, Transport::GetSessionTypeString(sessionHandle), fabricIndex,
325 : ChipLogValueX64(destination), static_cast<uint16_t>(compressedFabricId), addressStr, typeStr, protocolName,
326 : msgTypeName);
327 : #endif
328 :
329 9585 : ReturnErrorOnFailure(packetHeader.EncodeBeforeData(message));
330 9585 : preparedMessage = EncryptedPacketBufferHandle::MarkEncrypted(std::move(message));
331 :
332 9585 : return CHIP_NO_ERROR;
333 9587 : }
334 :
335 9619 : CHIP_ERROR SessionManager::SendPreparedMessage(const SessionHandle & sessionHandle,
336 : const EncryptedPacketBufferHandle & preparedMessage)
337 : {
338 9619 : VerifyOrReturnError(mState == State::kInitialized, CHIP_ERROR_INCORRECT_STATE);
339 9619 : VerifyOrReturnError(!preparedMessage.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
340 :
341 9619 : Transport::PeerAddress multicastAddress; // Only used for the group case
342 : const Transport::PeerAddress * destination;
343 :
344 9619 : switch (sessionHandle->GetSessionType())
345 : {
346 1 : case Transport::Session::SessionType::kGroupOutgoing: {
347 1 : auto groupSession = sessionHandle->AsOutgoingGroupSession();
348 :
349 1 : const FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex());
350 1 : VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
351 :
352 1 : multicastAddress = Transport::PeerAddress::Multicast(fabric->GetFabricId(), groupSession->GetGroupId());
353 1 : destination = &multicastAddress;
354 : }
355 1 : break;
356 9517 : case Transport::Session::SessionType::kSecure: {
357 : // Find an active connection to the specified peer node
358 9517 : SecureSession * secure = sessionHandle->AsSecureSession();
359 :
360 : // This marks any connection where we send data to as 'active'
361 9517 : secure->MarkActive();
362 :
363 9517 : destination = &secure->GetPeerAddress();
364 : }
365 9517 : break;
366 101 : case Transport::Session::SessionType::kUnauthenticated: {
367 101 : auto unauthenticated = sessionHandle->AsUnauthenticatedSession();
368 101 : unauthenticated->MarkActive();
369 101 : destination = &unauthenticated->GetPeerAddress();
370 : }
371 101 : break;
372 0 : default:
373 0 : return CHIP_ERROR_INTERNAL;
374 : }
375 :
376 19238 : PacketBufferHandle msgBuf = preparedMessage.CastToWritable();
377 9619 : VerifyOrReturnError(!msgBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
378 9619 : VerifyOrReturnError(!msgBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
379 :
380 : #if CHIP_SYSTEM_CONFIG_MULTICAST_HOMING
381 9619 : if (sessionHandle->GetSessionType() == Transport::Session::SessionType::kGroupOutgoing)
382 : {
383 1 : chip::Inet::InterfaceIterator interfaceIt;
384 1 : chip::Inet::InterfaceId interfaceId = chip::Inet::InterfaceId::Null();
385 : chip::Inet::IPAddress addr;
386 1 : bool interfaceFound = false;
387 :
388 3 : while (interfaceIt.Next())
389 : {
390 : char name[chip::Inet::InterfaceId::kMaxIfNameLength];
391 2 : interfaceIt.GetInterfaceName(name, chip::Inet::InterfaceId::kMaxIfNameLength);
392 2 : if (interfaceIt.SupportsMulticast() && interfaceIt.IsUp())
393 : {
394 1 : interfaceId = interfaceIt.GetInterfaceId();
395 1 : if (CHIP_NO_ERROR == interfaceId.GetLinkLocalAddr(&addr))
396 : {
397 1 : ChipLogDetail(Inet, "Interface %s has a link local address", name);
398 :
399 1 : interfaceFound = true;
400 1 : PacketBufferHandle tempBuf = msgBuf.CloneData();
401 1 : VerifyOrReturnError(!tempBuf.IsNull(), CHIP_ERROR_INVALID_ARGUMENT);
402 1 : VerifyOrReturnError(!tempBuf->HasChainedBuffer(), CHIP_ERROR_INVALID_MESSAGE_LENGTH);
403 :
404 1 : destination = &(multicastAddress.SetInterface(interfaceId));
405 1 : if (mTransportMgr != nullptr)
406 : {
407 1 : if (CHIP_NO_ERROR != mTransportMgr->SendMessage(*destination, std::move(tempBuf)))
408 : {
409 0 : ChipLogError(Inet, "Failed to send Multicast message on interface %s", name);
410 : }
411 : else
412 : {
413 1 : ChipLogDetail(Inet, "Successfully send Multicast message on interface %s", name);
414 : }
415 : }
416 1 : }
417 : }
418 : }
419 :
420 1 : if (!interfaceFound)
421 : {
422 0 : ChipLogError(Inet, "No valid Interface found.. Sending to the default one.. ");
423 : }
424 : else
425 : {
426 : // Always return No error, because we expect some interface to fails and others to always succeed (e.g. lo interface)
427 1 : return CHIP_NO_ERROR;
428 : }
429 1 : }
430 :
431 : #endif // CHIP_SYSTEM_CONFIG_MULTICAST_HOMING
432 :
433 9618 : if (mTransportMgr != nullptr)
434 : {
435 9618 : return mTransportMgr->SendMessage(*destination, std::move(msgBuf));
436 : }
437 :
438 0 : ChipLogError(Inet, "The transport manager is not initialized. Unable to send the message");
439 0 : return CHIP_ERROR_INCORRECT_STATE;
440 : }
441 :
442 0 : void SessionManager::ExpireAllSessions(const ScopedNodeId & node)
443 : {
444 0 : ChipLogDetail(Inet, "Expiring all sessions for node " ChipLogFormatScopedNodeId "!!", ChipLogValueScopedNodeId(node));
445 :
446 0 : ForEachMatchingSession(node, [](auto * session) { session->MarkForEviction(); });
447 0 : }
448 :
449 2 : void SessionManager::ExpireAllSessionsForFabric(FabricIndex fabricIndex)
450 : {
451 2 : ChipLogDetail(Inet, "Expiring all sessions for fabric 0x%x!!", static_cast<unsigned>(fabricIndex));
452 :
453 8 : ForEachMatchingSession(fabricIndex, [](auto * session) { session->MarkForEviction(); });
454 2 : }
455 :
456 0 : CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(const ScopedNodeId & node)
457 : {
458 0 : ChipLogDetail(Inet, "Expiring all sessions to peer " ChipLogFormatScopedNodeId " that are on the same logical fabric!!",
459 : ChipLogValueScopedNodeId(node));
460 :
461 0 : return ForEachMatchingSessionOnLogicalFabric(node, [](auto * session) { session->MarkForEviction(); });
462 : }
463 :
464 0 : CHIP_ERROR SessionManager::ExpireAllSessionsOnLogicalFabric(FabricIndex fabricIndex)
465 : {
466 0 : ChipLogDetail(Inet, "Expiring all sessions on the same logical fabric as fabric 0x%x!!", static_cast<unsigned>(fabricIndex));
467 :
468 0 : return ForEachMatchingSessionOnLogicalFabric(fabricIndex, [](auto * session) { session->MarkForEviction(); });
469 : }
470 :
471 0 : void SessionManager::ExpireAllPASESessions()
472 : {
473 0 : ChipLogDetail(Inet, "Expiring all PASE sessions");
474 0 : mSecureSessions.ForEachSession([&](auto session) {
475 0 : if (session->GetSecureSessionType() == Transport::SecureSession::Type::kPASE)
476 : {
477 0 : session->MarkForEviction();
478 : }
479 0 : return Loop::Continue;
480 : });
481 0 : }
482 :
483 0 : void SessionManager::MarkSessionsAsDefunct(const ScopedNodeId & node, const Optional<Transport::SecureSession::Type> & type)
484 : {
485 0 : mSecureSessions.ForEachSession([&node, &type](auto session) {
486 0 : if (session->IsActiveSession() && session->GetPeer() == node &&
487 0 : (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
488 : {
489 0 : session->MarkAsDefunct();
490 : }
491 0 : return Loop::Continue;
492 : });
493 0 : }
494 :
495 0 : void SessionManager::UpdateAllSessionsPeerAddress(const ScopedNodeId & node, const Transport::PeerAddress & addr)
496 : {
497 0 : mSecureSessions.ForEachSession([&node, &addr](auto session) {
498 : // Arguably we should only be updating active and defunct sessions, but there is no harm
499 : // in updating evicted sessions.
500 0 : if (session->GetPeer() == node && Transport::SecureSession::Type::kCASE == session->GetSecureSessionType())
501 : {
502 0 : session->SetPeerAddress(addr);
503 : }
504 0 : return Loop::Continue;
505 : });
506 0 : }
507 :
508 133656 : Optional<SessionHandle> SessionManager::AllocateSession(SecureSession::Type secureSessionType,
509 : const ScopedNodeId & sessionEvictionHint)
510 : {
511 133656 : VerifyOrReturnValue(mState == State::kInitialized, NullOptional);
512 133656 : return mSecureSessions.CreateNewSecureSession(secureSessionType, sessionEvictionHint);
513 : }
514 :
515 1269 : CHIP_ERROR SessionManager::InjectPaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId, NodeId peerNodeId,
516 : uint16_t peerSessionId, FabricIndex fabric,
517 : const Transport::PeerAddress & peerAddress, CryptoContext::SessionRole role)
518 : {
519 1269 : NodeId localNodeId = kUndefinedNodeId;
520 : Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
521 : chip::Transport::SecureSession::Type::kPASE, localSessionId, localNodeId, peerNodeId, CATValues{}, peerSessionId, fabric,
522 1269 : GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
523 1269 : VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
524 1269 : SecureSession * secureSession = session.Value()->AsSecureSession();
525 1269 : secureSession->SetPeerAddress(peerAddress);
526 :
527 1269 : size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
528 1269 : ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
529 1269 : ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
530 : *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
531 1269 : secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
532 1269 : sessionHolder.Grab(session.Value());
533 1269 : return CHIP_NO_ERROR;
534 1269 : }
535 :
536 17 : CHIP_ERROR SessionManager::InjectCaseSessionWithTestKey(SessionHolder & sessionHolder, uint16_t localSessionId,
537 : uint16_t peerSessionId, NodeId localNodeId, NodeId peerNodeId,
538 : FabricIndex fabric, const Transport::PeerAddress & peerAddress,
539 : CryptoContext::SessionRole role, const CATValues & cats)
540 : {
541 : Optional<SessionHandle> session = mSecureSessions.CreateNewSecureSessionForTest(
542 : chip::Transport::SecureSession::Type::kCASE, localSessionId, localNodeId, peerNodeId, cats, peerSessionId, fabric,
543 17 : GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig()));
544 17 : VerifyOrReturnError(session.HasValue(), CHIP_ERROR_NO_MEMORY);
545 17 : SecureSession * secureSession = session.Value()->AsSecureSession();
546 17 : secureSession->SetPeerAddress(peerAddress);
547 :
548 17 : size_t secretLen = CHIP_CONFIG_TEST_SHARED_SECRET_LENGTH;
549 17 : ByteSpan secret(reinterpret_cast<const uint8_t *>(CHIP_CONFIG_TEST_SHARED_SECRET_VALUE), secretLen);
550 17 : ReturnErrorOnFailure(secureSession->GetCryptoContext().InitFromSecret(
551 : *mSessionKeystore, secret, ByteSpan(), CryptoContext::SessionInfoType::kSessionEstablishment, role));
552 17 : secureSession->GetSessionMessageCounter().GetPeerMessageCounter().SetCounter(Transport::PeerMessageCounter::kInitialSyncValue);
553 17 : sessionHolder.Grab(session.Value());
554 17 : return CHIP_NO_ERROR;
555 17 : }
556 :
557 9507 : void SessionManager::OnMessageReceived(const PeerAddress & peerAddress, System::PacketBufferHandle && msg)
558 : {
559 9507 : PacketHeader partialPacketHeader;
560 :
561 9507 : CHIP_ERROR err = partialPacketHeader.DecodeFixed(msg);
562 9507 : if (err != CHIP_NO_ERROR)
563 : {
564 0 : ChipLogError(Inet, "Failed to decode packet header: %" CHIP_ERROR_FORMAT, err.Format());
565 0 : return;
566 : }
567 :
568 9507 : if (partialPacketHeader.IsEncrypted())
569 : {
570 9411 : if (partialPacketHeader.IsGroupSession())
571 : {
572 6 : SecureGroupMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
573 : }
574 : else
575 : {
576 9405 : SecureUnicastMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
577 : }
578 : }
579 : else
580 : {
581 96 : UnauthenticatedMessageDispatch(partialPacketHeader, peerAddress, std::move(msg));
582 : }
583 9507 : }
584 :
585 96 : void SessionManager::UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader,
586 : const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
587 : {
588 : MATTER_TRACE_SCOPE("Unauthenticated Message Dispatch", "SessionManager");
589 :
590 : // Drop unsecured messages with privacy enabled.
591 96 : if (partialPacketHeader.HasPrivacyFlag())
592 : {
593 0 : ChipLogError(Inet, "Dropping unauthenticated message with privacy flag set");
594 0 : return;
595 : }
596 :
597 96 : PacketHeader packetHeader;
598 96 : ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
599 :
600 96 : Optional<NodeId> source = packetHeader.GetSourceNodeId();
601 96 : Optional<NodeId> destination = packetHeader.GetDestinationNodeId();
602 :
603 96 : if ((source.HasValue() && destination.HasValue()) || (!source.HasValue() && !destination.HasValue()))
604 : {
605 0 : ChipLogProgress(Inet,
606 : "Received malformed unsecure packet with source 0x" ChipLogFormatX64 " destination 0x" ChipLogFormatX64,
607 : ChipLogValueX64(source.ValueOr(kUndefinedNodeId)), ChipLogValueX64(destination.ValueOr(kUndefinedNodeId)));
608 0 : return; // ephemeral node id is only assigned to the initiator, there should be one and only one node id exists.
609 : }
610 :
611 96 : Optional<SessionHandle> optionalSession;
612 96 : if (source.HasValue())
613 : {
614 : // Assume peer is the initiator, we are the responder.
615 56 : optionalSession = mUnauthenticatedSessions.FindOrAllocateResponder(source.Value(), GetDefaultMRPConfig());
616 56 : if (!optionalSession.HasValue())
617 : {
618 0 : ChipLogError(Inet, "UnauthenticatedSession exhausted");
619 0 : return;
620 : }
621 : }
622 : else
623 : {
624 : // Assume peer is the responder, we are the initiator.
625 40 : optionalSession = mUnauthenticatedSessions.FindInitiator(destination.Value());
626 40 : if (!optionalSession.HasValue())
627 : {
628 0 : ChipLogProgress(Inet, "Received unknown unsecure packet for initiator 0x" ChipLogFormatX64,
629 : ChipLogValueX64(destination.Value()));
630 0 : return;
631 : }
632 : }
633 :
634 96 : const SessionHandle & session = optionalSession.Value();
635 96 : Transport::UnauthenticatedSession * unsecuredSession = session->AsUnauthenticatedSession();
636 96 : unsecuredSession->SetPeerAddress(peerAddress);
637 96 : SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
638 :
639 96 : unsecuredSession->MarkActiveRx();
640 :
641 96 : PayloadHeader payloadHeader;
642 96 : ReturnOnFailure(payloadHeader.DecodeAndConsume(msg));
643 :
644 : // Verify message counter
645 96 : CHIP_ERROR err = unsecuredSession->GetPeerMessageCounter().VerifyUnencrypted(packetHeader.GetMessageCounter());
646 96 : if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
647 : {
648 0 : ChipLogDetail(Inet,
649 : "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
650 : " on exchange " ChipLogFormatExchangeId,
651 : packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
652 0 : isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
653 0 : err = CHIP_NO_ERROR;
654 : }
655 : else
656 : {
657 : // VerifyUnencrypted always returns one of CHIP_NO_ERROR or
658 : // CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED.
659 96 : unsecuredSession->GetPeerMessageCounter().CommitUnencrypted(packetHeader.GetMessageCounter());
660 : }
661 96 : if (mCB != nullptr)
662 : {
663 : MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kUnauthenticated, &payloadHeader, &packetHeader,
664 : unsecuredSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));
665 :
666 96 : CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, unsecuredSession, peerAddress, msg->Start(), msg->TotalLength());
667 96 : mCB->OnMessageReceived(packetHeader, payloadHeader, session, isDuplicate, std::move(msg));
668 : }
669 : else
670 : {
671 0 : ChipLogError(Inet, "Received UNSECURED message was not processed.");
672 : }
673 96 : }
674 :
675 9405 : void SessionManager::SecureUnicastMessageDispatch(const PacketHeader & partialPacketHeader,
676 : const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
677 : {
678 : MATTER_TRACE_SCOPE("Secure Unicast Message Dispatch", "SessionManager");
679 :
680 9405 : CHIP_ERROR err = CHIP_NO_ERROR;
681 :
682 9405 : Optional<SessionHandle> session = mSecureSessions.FindSecureSessionByLocalKey(partialPacketHeader.GetSessionId());
683 :
684 9405 : PayloadHeader payloadHeader;
685 :
686 : // Drop secure unicast messages with privacy enabled.
687 9405 : if (partialPacketHeader.HasPrivacyFlag())
688 : {
689 1 : ChipLogError(Inet, "Dropping secure unicast message with privacy flag set");
690 1 : return;
691 : }
692 :
693 9404 : PacketHeader packetHeader;
694 9404 : ReturnOnFailure(packetHeader.DecodeAndConsume(msg));
695 :
696 9404 : SessionMessageDelegate::DuplicateMessage isDuplicate = SessionMessageDelegate::DuplicateMessage::No;
697 :
698 9404 : if (msg.IsNull())
699 : {
700 0 : ChipLogError(Inet, "Secure transport received Unicast NULL packet, discarding");
701 0 : return;
702 : }
703 :
704 9404 : if (!session.HasValue())
705 : {
706 10 : ChipLogError(Inet, "Data received on an unknown session (LSID=%d). Dropping it!", packetHeader.GetSessionId());
707 10 : return;
708 : }
709 :
710 9394 : Transport::SecureSession * secureSession = session.Value()->AsSecureSession();
711 :
712 : // We need to allow through messages even on sessions that are pending
713 : // evictions, because for some cases (UpdateNOC, RemoveFabric, etc) there
714 : // can be a single exchange alive on the session waiting for a MRP ack, and
715 : // we need to make sure to send the ack through. The exchange manager is
716 : // responsible for ensuring that such messages do not lead to new exchange
717 : // creation.
718 9394 : if (!secureSession->IsDefunct() && !secureSession->IsActiveSession() && !secureSession->IsPendingEviction())
719 : {
720 0 : ChipLogError(Inet, "Secure transport received message on a session in an invalid state (state = '%s')",
721 : secureSession->GetStateStr());
722 0 : return;
723 : }
724 :
725 : // Decrypt and verify the message before message counter verification or any further processing.
726 : CryptoContext::NonceStorage nonce;
727 : // PASE Sessions use the undefined node ID of all zeroes, since there is no node ID to use
728 : // and the key is short-lived and always different for each PASE session.
729 9402 : CryptoContext::BuildNonce(nonce, packetHeader.GetSecurityFlags(), packetHeader.GetMessageCounter(),
730 9402 : secureSession->GetSecureSessionType() == SecureSession::Type::kCASE ? secureSession->GetPeerNodeId()
731 : : kUndefinedNodeId);
732 9394 : if (SecureMessageCodec::Decrypt(secureSession->GetCryptoContext(), nonce, payloadHeader, packetHeader, msg) != CHIP_NO_ERROR)
733 : {
734 3 : ChipLogError(Inet, "Secure transport received message, but failed to decode/authenticate it, discarding");
735 3 : return;
736 : }
737 :
738 9391 : err =
739 9391 : secureSession->GetSessionMessageCounter().GetPeerMessageCounter().VerifyEncryptedUnicast(packetHeader.GetMessageCounter());
740 9391 : if (err == CHIP_ERROR_DUPLICATE_MESSAGE_RECEIVED)
741 : {
742 8 : ChipLogDetail(Inet,
743 : "Received a duplicate message with MessageCounter:" ChipLogFormatMessageCounter
744 : " on exchange " ChipLogFormatExchangeId,
745 : packetHeader.GetMessageCounter(), ChipLogValueExchangeIdFromReceivedHeader(payloadHeader));
746 8 : isDuplicate = SessionMessageDelegate::DuplicateMessage::Yes;
747 8 : err = CHIP_NO_ERROR;
748 : }
749 9391 : if (err != CHIP_NO_ERROR)
750 : {
751 0 : ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
752 0 : return;
753 : }
754 :
755 9391 : secureSession->MarkActiveRx();
756 :
757 9391 : if (isDuplicate == SessionMessageDelegate::DuplicateMessage::Yes && !payloadHeader.NeedsAck())
758 : {
759 : // If it's a duplicate message, but doesn't require an ack, let's drop it right here to save CPU
760 : // cycles on further message processing.
761 2 : return;
762 : }
763 :
764 9389 : if (isDuplicate == SessionMessageDelegate::DuplicateMessage::No)
765 : {
766 9383 : secureSession->GetSessionMessageCounter().GetPeerMessageCounter().CommitEncryptedUnicast(packetHeader.GetMessageCounter());
767 : }
768 :
769 : // TODO: once mDNS address resolution is available reconsider if this is required
770 : // This updates the peer address once a packet is received from a new address
771 : // and serves as a way to auto-detect peer changing IPs.
772 9389 : if (secureSession->GetPeerAddress() != peerAddress)
773 : {
774 225 : secureSession->SetPeerAddress(peerAddress);
775 : }
776 :
777 9389 : if (mCB != nullptr)
778 : {
779 : MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kSecureUnicast, &payloadHeader, &packetHeader,
780 : secureSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));
781 9389 : CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeader, secureSession, peerAddress, msg->Start(), msg->TotalLength());
782 9389 : mCB->OnMessageReceived(packetHeader, payloadHeader, session.Value(), isDuplicate, std::move(msg));
783 : }
784 : else
785 : {
786 0 : ChipLogError(Inet, "Received SECURED message was not processed.");
787 : }
788 9436 : }
789 :
790 : /**
791 : * Helper function to implement a single attempt to decrypt a groupcast message
792 : * using the given group key and privacy setting.
793 : *
794 : * @param[in] partialPacketHeader The partial packet header with non-obfuscated message fields (result of calling DecodeFixed).
795 : * @param[out] packetHeaderCopy A copy of the packet header, to be filled with privacy decrypted fields
796 : * @param[out] payloadHeader The payload header of the decrypted message
797 : * @param[in] applyPrivacy Whether to apply privacy deobfuscation
798 : * @param[out] msgCopy A copy of the message, to be filled with the decrypted message
799 : * @param[in] mac The MAC of the message
800 : * @param[in] groupContext The group context to use for decryption key material
801 : *
802 : * @return true if the message was decrypted successfully
803 : * @return false if the message could not be decrypted
804 : */
805 8 : static bool GroupKeyDecryptAttempt(const PacketHeader & partialPacketHeader, PacketHeader & packetHeaderCopy,
806 : PayloadHeader & payloadHeader, bool applyPrivacy, System::PacketBufferHandle & msgCopy,
807 : const MessageAuthenticationCode & mac,
808 : const Credentials::GroupDataProvider::GroupSession & groupContext)
809 : {
810 8 : bool decrypted = false;
811 8 : CryptoContext context(groupContext.keyContext);
812 :
813 8 : if (applyPrivacy)
814 : {
815 : // Perform privacy deobfuscation, if applicable.
816 3 : uint8_t * privacyHeader = partialPacketHeader.PrivacyHeader(msgCopy->Start());
817 3 : size_t privacyLength = partialPacketHeader.PrivacyHeaderLength();
818 3 : if (CHIP_NO_ERROR != context.PrivacyDecrypt(privacyHeader, privacyLength, privacyHeader, partialPacketHeader, mac))
819 : {
820 0 : return false;
821 : }
822 : }
823 :
824 8 : if (packetHeaderCopy.DecodeAndConsume(msgCopy) != CHIP_NO_ERROR)
825 : {
826 0 : ChipLogError(Inet, "Failed to decode Groupcast packet header. Discarding.");
827 0 : return false;
828 : }
829 :
830 : // Optimization to reduce number of decryption attempts
831 8 : GroupId groupId = packetHeaderCopy.GetDestinationGroupId().Value();
832 8 : if (groupId != groupContext.group_id)
833 : {
834 3 : return false;
835 : }
836 :
837 : CryptoContext::NonceStorage nonce;
838 5 : CryptoContext::BuildNonce(nonce, packetHeaderCopy.GetSecurityFlags(), packetHeaderCopy.GetMessageCounter(),
839 5 : packetHeaderCopy.GetSourceNodeId().Value());
840 5 : decrypted = (CHIP_NO_ERROR == SecureMessageCodec::Decrypt(context, nonce, payloadHeader, packetHeaderCopy, msgCopy));
841 :
842 5 : return decrypted;
843 8 : }
844 :
845 6 : void SessionManager::SecureGroupMessageDispatch(const PacketHeader & partialPacketHeader,
846 : const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
847 : {
848 : MATTER_TRACE_SCOPE("Group Message Dispatch", "SessionManager");
849 :
850 6 : PayloadHeader payloadHeader;
851 6 : PacketHeader packetHeaderCopy; /// Packet header decoded per group key, with privacy decrypted fields
852 6 : System::PacketBufferHandle msgCopy;
853 6 : Credentials::GroupDataProvider * groups = Credentials::GetGroupDataProvider();
854 6 : VerifyOrReturn(nullptr != groups);
855 6 : CHIP_ERROR err = CHIP_NO_ERROR;
856 :
857 6 : if (!partialPacketHeader.HasDestinationGroupId())
858 : {
859 0 : return; // malformed packet
860 : }
861 :
862 : // Check if Message Header is valid first
863 6 : if (!(partialPacketHeader.IsValidMCSPMsg() || partialPacketHeader.IsValidGroupMsg()))
864 : {
865 0 : ChipLogError(Inet, "Invalid condition found in packet header");
866 0 : return;
867 : }
868 :
869 : // Trial decryption with GroupDataProvider
870 6 : Credentials::GroupDataProvider::GroupSession groupContext;
871 6 : auto iter = groups->IterateGroupSessions(partialPacketHeader.GetSessionId());
872 6 : if (iter == nullptr)
873 : {
874 0 : ChipLogError(Inet, "Failed to retrieve Groups iterator. Discarding everything");
875 0 : return;
876 : }
877 :
878 : // Extract MIC from the end of the message.
879 6 : uint8_t * data = msg->Start();
880 6 : uint16_t len = msg->DataLength();
881 6 : uint16_t footerLen = partialPacketHeader.MICTagLength();
882 6 : VerifyOrReturn(footerLen <= len);
883 :
884 6 : uint16_t taglen = 0;
885 : MessageAuthenticationCode mac;
886 6 : ReturnOnFailure(mac.Decode(partialPacketHeader, &data[len - footerLen], footerLen, &taglen));
887 6 : VerifyOrReturn(taglen == footerLen);
888 :
889 6 : bool decrypted = false;
890 12 : while (!decrypted && iter->Next(groupContext))
891 : {
892 6 : CryptoContext context(groupContext.keyContext);
893 6 : msgCopy = msg.CloneData();
894 6 : if (msgCopy.IsNull())
895 : {
896 0 : ChipLogError(Inet, "Failed to clone Groupcast message buffer. Discarding.");
897 0 : return;
898 : }
899 :
900 6 : bool privacy = partialPacketHeader.HasPrivacyFlag();
901 : decrypted =
902 6 : GroupKeyDecryptAttempt(partialPacketHeader, packetHeaderCopy, payloadHeader, privacy, msgCopy, mac, groupContext);
903 :
904 : #if CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2
905 6 : if (privacy && !decrypted)
906 : {
907 : // Try processing the P=1 message again without privacy as a work-around for invalid early-SVE2 nodes.
908 2 : msgCopy = msg.CloneData();
909 2 : if (msgCopy.IsNull())
910 : {
911 0 : ChipLogError(Inet, "Failed to clone Groupcast message buffer. Discarding.");
912 0 : return;
913 : }
914 : decrypted =
915 2 : GroupKeyDecryptAttempt(partialPacketHeader, packetHeaderCopy, payloadHeader, false, msgCopy, mac, groupContext);
916 : }
917 : #endif // CHIP_CONFIG_PRIVACY_ACCEPT_NONSPEC_SVE2
918 6 : }
919 6 : iter->Release();
920 :
921 6 : if (!decrypted)
922 : {
923 1 : ChipLogError(Inet, "Failed to decrypt group message. Discarding everything");
924 1 : return;
925 : }
926 5 : msg = std::move(msgCopy);
927 :
928 : // MCSP check
929 5 : if (packetHeaderCopy.IsValidMCSPMsg())
930 : {
931 : // TODO: When MCSP Msg, create Secure Session instead of a Group session
932 :
933 : // TODO
934 : // if (packetHeaderCopy.GetDestinationNodeId().Value() == ThisDeviceNodeID)
935 : // {
936 : // MCSP processing..
937 : // }
938 :
939 0 : return;
940 : }
941 :
942 : // Group Messages should never send an Ack
943 5 : if (payloadHeader.NeedsAck())
944 : {
945 0 : ChipLogError(Inet, "Unexpected ACK requested for group message");
946 0 : return;
947 : }
948 :
949 : // Handle Group message counter here spec 4.7.3
950 : // spec 4.5.1.2 for msg counter
951 5 : Transport::PeerMessageCounter * counter = nullptr;
952 :
953 5 : if (CHIP_NO_ERROR ==
954 15 : gGroupPeerTable->FindOrAddPeer(groupContext.fabric_index, packetHeaderCopy.GetSourceNodeId().Value(),
955 10 : packetHeaderCopy.IsSecureSessionControlMsg(), counter))
956 : {
957 :
958 5 : if (Credentials::GroupDataProvider::SecurityPolicy::kTrustFirst == groupContext.security_policy)
959 : {
960 4 : err = counter->VerifyOrTrustFirstGroup(packetHeaderCopy.GetMessageCounter());
961 : }
962 : else
963 : {
964 :
965 : // TODO support cache and sync with MCSP. Issue #11689
966 1 : ChipLogError(Inet, "Received Group Msg with key policy Cache and Sync, but MCSP is not implemented");
967 1 : return;
968 :
969 : // cache and sync
970 : // err = counter->VerifyGroup(packetHeaderCopy.GetMessageCounter());
971 : }
972 :
973 4 : if (err != CHIP_NO_ERROR)
974 : {
975 : // Exit now, since Group Messages don't have acks or responses of any kind.
976 1 : ChipLogError(Inet, "Message counter verify failed, err = %" CHIP_ERROR_FORMAT, err.Format());
977 1 : return;
978 : }
979 : }
980 : else
981 : {
982 0 : ChipLogError(Inet,
983 : "Group Counter Tables full or invalid NodeId/FabricIndex after decryption of message, dropping everything");
984 0 : return;
985 : }
986 :
987 3 : counter->CommitGroup(packetHeaderCopy.GetMessageCounter());
988 :
989 3 : if (mCB != nullptr)
990 : {
991 : // TODO : When MCSP is done, clean up session creation logic
992 3 : Transport::IncomingGroupSession groupSession(groupContext.group_id, groupContext.fabric_index,
993 3 : packetHeaderCopy.GetSourceNodeId().Value());
994 :
995 : MATTER_LOG_MESSAGE_RECEIVED(chip::Tracing::IncomingMessageType::kGroupMessage, &payloadHeader, &packetHeaderCopy,
996 : &groupSession, &peerAddress, chip::ByteSpan(msg->Start(), msg->TotalLength()));
997 :
998 3 : CHIP_TRACE_MESSAGE_RECEIVED(payloadHeader, packetHeaderCopy, &groupSession, peerAddress, msg->Start(), msg->TotalLength());
999 3 : mCB->OnMessageReceived(packetHeaderCopy, payloadHeader, SessionHandle(groupSession),
1000 3 : SessionMessageDelegate::DuplicateMessage::No, std::move(msg));
1001 3 : }
1002 : else
1003 : {
1004 0 : ChipLogError(Inet, "Received GROUP message was not processed.");
1005 : }
1006 12 : }
1007 :
1008 1 : Optional<SessionHandle> SessionManager::FindSecureSessionForNode(ScopedNodeId peerNodeId,
1009 : const Optional<Transport::SecureSession::Type> & type)
1010 : {
1011 1 : SecureSession * found = nullptr;
1012 :
1013 1 : mSecureSessions.ForEachSession([&peerNodeId, &type, &found](auto session) {
1014 4 : if (session->IsActiveSession() && session->GetPeer() == peerNodeId &&
1015 2 : (!type.HasValue() || type.Value() == session->GetSecureSessionType()))
1016 : {
1017 : //
1018 : // Select the active session with the most recent activity to return back to the caller.
1019 : //
1020 2 : if ((found == nullptr) || (found->GetLastActivityTime() < session->GetLastActivityTime()))
1021 : {
1022 2 : found = session;
1023 : }
1024 : }
1025 :
1026 2 : return Loop::Continue;
1027 : });
1028 :
1029 1 : return found != nullptr ? MakeOptional<SessionHandle>(*found) : Optional<SessionHandle>::Missing();
1030 : }
1031 :
1032 : /**
1033 : * Provides a means to get diagnostic information such as number of sessions.
1034 : */
1035 0 : [[maybe_unused]] CHIP_ERROR SessionManager::ForEachSessionHandle(void * context, SessionHandleCallback lambda)
1036 : {
1037 0 : mSecureSessions.ForEachSession([&](auto session) {
1038 0 : SessionHandle handle(*session);
1039 0 : lambda(context, handle);
1040 0 : return Loop::Continue;
1041 0 : });
1042 0 : return CHIP_NO_ERROR;
1043 : }
1044 :
1045 : } // namespace chip
|