Skip to content

Commit

Permalink
Implement CASE session resumption (#16741)
Browse files Browse the repository at this point in the history
* Implement CASE session resumption

* Fix span usage

* Introduce SimpleSessionResumptionStorage as an example implementation.

* Allow inject session resumption storage for server
  • Loading branch information
kghost authored and pull[bot] committed Dec 19, 2023
1 parent 066f072 commit 7e883fa
Show file tree
Hide file tree
Showing 34 changed files with 1,014 additions and 604 deletions.
3 changes: 3 additions & 0 deletions examples/pump-app/cc13x2x7_26x2x7/args.gni
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ chip_enable_ota_requestor = true
# BLE options
chip_config_network_layer_ble = true

# Disable session resumption due to lack of code space
chip_enable_session_resumption = false

# Disable lock tracking, since our FreeRTOS configuration does not set
# INCLUDE_xSemaphoreGetMutexHolder
chip_stack_lock_tracking = "none"
9 changes: 5 additions & 4 deletions examples/tv-casting-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,11 @@ class TargetVideoPlayerInfo
}

chip::DeviceProxyInitParams initParams = {
.sessionManager = &(server->GetSecureSessionManager()),
.exchangeMgr = &(server->GetExchangeManager()),
.fabricTable = &(server->GetFabricTable()),
.clientPool = &gCASEClientPool,
.sessionManager = &(server->GetSecureSessionManager()),
.sessionResumptionStorage = server->GetSessionResumptionStorage(),
.exchangeMgr = &(server->GetExchangeManager()),
.fabricTable = &(server->GetFabricTable()),
.clientPool = &gCASEClientPool,
};

PeerId peerID = fabric->GetPeerIdForNode(nodeId);
Expand Down
6 changes: 5 additions & 1 deletion src/app/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ declare_args() {
# Enable strict schema checks.
chip_enable_schema_check =
is_debug && (current_os == "linux" || current_os == "mac")
chip_enable_session_resumption = true
}

buildconfig_header("app_buildconfig") {
header = "AppBuildConfig.h"
header_dir = "app"

defines = [ "CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK=${chip_enable_schema_check}" ]
defines = [
"CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK=${chip_enable_schema_check}",
"CHIP_CONFIG_ENABLE_SESSION_RESUMPTION=${chip_enable_session_resumption}",
]
}

static_library("app") {
Expand Down
3 changes: 2 additions & 1 deletion src/app/CASEClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ CHIP_ERROR CASEClient::EstablishSession(PeerId peer, const Transport::PeerAddres

mCASESession.SetGroupDataProvider(mInitParams.groupDataProvider);
ReturnErrorOnFailure(mCASESession.EstablishSession(*mInitParams.sessionManager, peerAddress, mInitParams.fabricInfo,
peer.GetNodeId(), exchange, this, mInitParams.mrpLocalConfig));
peer.GetNodeId(), exchange, mInitParams.sessionResumptionStorage, this,
mInitParams.mrpLocalConfig));
mConnectionSuccessCallback = onConnection;
mConnectionFailureCallback = onFailure;
mConectionContext = context;
Expand Down
9 changes: 5 additions & 4 deletions src/app/CASEClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ typedef void (*OnCASEConnectionFailure)(void * context, CASEClient * client, CHI

struct CASEClientInitParams
{
SessionManager * sessionManager = nullptr;
Messaging::ExchangeManager * exchangeMgr = nullptr;
FabricInfo * fabricInfo = nullptr;
Credentials::GroupDataProvider * groupDataProvider = nullptr;
SessionManager * sessionManager = nullptr;
SessionResumptionStorage * sessionResumptionStorage = nullptr;
Messaging::ExchangeManager * exchangeMgr = nullptr;
FabricInfo * fabricInfo = nullptr;
Credentials::GroupDataProvider * groupDataProvider = nullptr;

Optional<ReliableMessageProtocolConfig> mrpLocalConfig = Optional<ReliableMessageProtocolConfig>::Missing();
};
Expand Down
6 changes: 3 additions & 3 deletions src/app/OperationalDeviceProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ bool OperationalDeviceProxy::GetAddress(Inet::IPAddress & addr, uint16_t & port)

CHIP_ERROR OperationalDeviceProxy::EstablishConnection()
{
mCASEClient =
mInitParams.clientPool->Allocate(CASEClientInitParams{ mInitParams.sessionManager, mInitParams.exchangeMgr, mFabricInfo,
mInitParams.groupDataProvider, mInitParams.mrpLocalConfig });
mCASEClient = mInitParams.clientPool->Allocate(
CASEClientInitParams{ mInitParams.sessionManager, mInitParams.sessionResumptionStorage, mInitParams.exchangeMgr,
mFabricInfo, mInitParams.groupDataProvider, mInitParams.mrpLocalConfig });
ReturnErrorCodeIf(mCASEClient == nullptr, CHIP_ERROR_NO_MEMORY);
CHIP_ERROR err =
mCASEClient->EstablishSession(mPeerId, mDeviceAddress, mMRPConfig, HandleCASEConnected, HandleCASEConnectionFailure, this);
Expand Down
12 changes: 7 additions & 5 deletions src/app/OperationalDeviceProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,19 @@ namespace chip {

struct DeviceProxyInitParams
{
SessionManager * sessionManager = nullptr;
Messaging::ExchangeManager * exchangeMgr = nullptr;
FabricTable * fabricTable = nullptr;
CASEClientPoolDelegate * clientPool = nullptr;
Credentials::GroupDataProvider * groupDataProvider = nullptr;
SessionManager * sessionManager = nullptr;
SessionResumptionStorage * sessionResumptionStorage = nullptr;
Messaging::ExchangeManager * exchangeMgr = nullptr;
FabricTable * fabricTable = nullptr;
CASEClientPoolDelegate * clientPool = nullptr;
Credentials::GroupDataProvider * groupDataProvider = nullptr;

Optional<ReliableMessageProtocolConfig> mrpLocalConfig = Optional<ReliableMessageProtocolConfig>::Missing();

CHIP_ERROR Validate() const
{
ReturnErrorCodeIf(sessionManager == nullptr, CHIP_ERROR_INCORRECT_STATE);
// sessionResumptionStorage can be nullptr when resumption is disabled
ReturnErrorCodeIf(exchangeMgr == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(fabricTable == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(groupDataProvider == nullptr, CHIP_ERROR_INCORRECT_STATE);
Expand Down
6 changes: 4 additions & 2 deletions src/app/server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
mCommissioningWindowManager.SetAppDelegate(initParams.appDelegate);

// Initialize PersistentStorageDelegate-based storage
mDeviceStorage = initParams.persistentStorageDelegate;
mDeviceStorage = initParams.persistentStorageDelegate;
mSessionResumptionStorage = initParams.sessionResumptionStorage;

// Set up attribute persistence before we try to bring up the data model
// handler.
Expand Down Expand Up @@ -237,6 +238,7 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
caseSessionManagerConfig = {
.sessionInitParams = {
.sessionManager = &mSessions,
.sessionResumptionStorage = mSessionResumptionStorage,
.exchangeMgr = &mExchangeMgr,
.fabricTable = &mFabrics,
.clientPool = &mCASEClientPool,
Expand All @@ -255,7 +257,7 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
#if CONFIG_NETWORK_LAYER_BLE
chip::DeviceLayer::ConnectivityMgr().GetBleLayer(),
#endif
&mSessions, &mFabrics, mGroupsProvider);
&mSessions, &mFabrics, mSessionResumptionStorage, mGroupsProvider);
SuccessOrExit(err);

// This code is necessary to restart listening to existing groups after a reboot
Expand Down
21 changes: 21 additions & 0 deletions src/app/server/Server.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#pragma once

#include <app/AppBuildConfig.h>

#include <access/AccessControl.h>
#include <access/examples/ExampleAccessControlDelegate.h>
#include <app/CASEClientPool.h>
Expand All @@ -38,6 +40,9 @@
#include <protocols/secure_channel/MessageCounterManager.h>
#include <protocols/secure_channel/PASESession.h>
#include <protocols/secure_channel/RendezvousParameters.h>
#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION
#include <protocols/secure_channel/SimpleSessionResumptionStorage.h>
#endif
#include <protocols/user_directed_commissioning/UserDirectedCommissioning.h>
#include <transport/SessionManager.h>
#include <transport/TransportMgr.h>
Expand Down Expand Up @@ -83,6 +88,9 @@ struct ServerInitParams
// Persistent storage delegate: MUST be injected. Used to maintain storage by much common code.
// Must be initialized before being provided.
PersistentStorageDelegate * persistentStorageDelegate = nullptr;
// Session resumption storage: Optional. Support session resumption when provided.
// Must be initialized before being provided.
SessionResumptionStorage * sessionResumptionStorage = nullptr;
// Group data provider: MUST be injected. Used to maintain critical keys such as the Identity
// Protection Key (IPK) for CASE. Must be initialized before being provided.
Credentials::GroupDataProvider * groupDataProvider = nullptr;
Expand Down Expand Up @@ -139,6 +147,9 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams
{
static chip::KvsPersistentStorageDelegate sKvsPersistenStorageDelegate;
static chip::Credentials::GroupDataProviderImpl sGroupDataProvider;
#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION
static chip::SimpleSessionResumptionStorage sSessionResumptionStorage;
#endif

// KVS-based persistent storage delegate injection
chip::DeviceLayer::PersistedStorage::KeyValueStoreManager & kvsManager = DeviceLayer::PersistedStorage::KeyValueStoreMgr();
Expand All @@ -150,6 +161,13 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams
ReturnErrorOnFailure(sGroupDataProvider.Init());
this->groupDataProvider = &sGroupDataProvider;

#if CHIP_CONFIG_ENABLE_SESSION_RESUMPTION
ReturnErrorOnFailure(sSessionResumptionStorage.Init(&sKvsPersistenStorageDelegate));
this->sessionResumptionStorage = &sSessionResumptionStorage;
#else
this->sessionResumptionStorage = nullptr;
#endif

// Inject access control delegate
this->accessDelegate = Access::Examples::GetAccessControlDelegate(&sKvsPersistenStorageDelegate);

Expand Down Expand Up @@ -198,6 +216,8 @@ class Server

SessionManager & GetSecureSessionManager() { return mSessions; }

SessionResumptionStorage * GetSessionResumptionStorage() { return mSessionResumptionStorage; }

TransportMgrBase & GetTransportManager() { return mTransports; }

Credentials::GroupDataProvider * GetGroupDataProvider() { return mGroupsProvider; }
Expand Down Expand Up @@ -313,6 +333,7 @@ class Server
CommissioningWindowManager mCommissioningWindowManager;

PersistentStorageDelegate * mDeviceStorage;
SessionResumptionStorage * mSessionResumptionStorage;
Credentials::GroupDataProvider * mGroupsProvider;
app::DefaultAttributePersistenceProvider mAttributePersister;
GroupDataProviderListener mListener;
Expand Down
11 changes: 7 additions & 4 deletions src/app/tests/TestOperationalDeviceProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void TestOperationalDeviceProxy_EstablishSessionDirectly(nlTestSuite * inSuite,
Platform::MemoryInit();
TestTransportMgr transportMgr;
SessionManager sessionManager;
SessionResumptionStorage sessionResumptionStorage;
ExchangeManager exchangeMgr;
Inet::UDPEndPointManagerImpl udpEndPointManager;
System::LayerImpl systemLayer;
Expand All @@ -61,17 +62,19 @@ void TestOperationalDeviceProxy_EstablishSessionDirectly(nlTestSuite * inSuite,
udpEndPointManager.Init(systemLayer);
transportMgr.Init(UdpListenParameters(udpEndPointManager).SetAddressType(Inet::IPAddressType::kIPv4).SetListenPort(CHIP_PORT));
sessionManager.Init(&systemLayer, &transportMgr, &messageCounterManager, &deviceStorage);
sessionResumptionStorage.Init(&deviceStorage);
exchangeMgr.Init(&sessionManager);
messageCounterManager.Init(&exchangeMgr);
groupDataProvider.SetPersistentStorage(&deviceStorage);
VerifyOrDie(groupDataProvider.Init() == CHIP_NO_ERROR);
// TODO: Set IPK in groupDataProvider

DeviceProxyInitParams params = {
.sessionManager = &sessionManager,
.exchangeMgr = &exchangeMgr,
.fabricInfo = fabric,
.groupDataProvider = &groupDataProvider,
.sessionManager = &sessionManager,
.sessionResumptionStorage = &sessionResumptionStorage,
.exchangeMgr = &exchangeMgr,
.fabricInfo = fabric,
.groupDataProvider = &groupDataProvider,
};
NodeId mockNodeId = 1;
OperationalDeviceProxy device(params, PeerId().SetNodeId(mockNodeId));
Expand Down
29 changes: 17 additions & 12 deletions src/controller/CHIPDeviceControllerFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

#include <app/server/Dnssd.h>
#include <protocols/secure_channel/CASEServer.h>
#include <protocols/secure_channel/SimpleSessionResumptionStorage.h>

using namespace chip::Inet;
using namespace chip::System;
Expand Down Expand Up @@ -146,13 +147,16 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
#endif
));

stateParams.fabricTable = chip::Platform::New<FabricTable>();
stateParams.sessionMgr = chip::Platform::New<SessionManager>();
stateParams.exchangeMgr = chip::Platform::New<Messaging::ExchangeManager>();
stateParams.messageCounterManager = chip::Platform::New<secure_channel::MessageCounterManager>();
stateParams.groupDataProvider = params.groupDataProvider;
stateParams.fabricTable = chip::Platform::New<FabricTable>();
stateParams.sessionMgr = chip::Platform::New<SessionManager>();
SimpleSessionResumptionStorage * sessionResumptionStorage = chip::Platform::New<SimpleSessionResumptionStorage>();
stateParams.sessionResumptionStorage = sessionResumptionStorage;
stateParams.exchangeMgr = chip::Platform::New<Messaging::ExchangeManager>();
stateParams.messageCounterManager = chip::Platform::New<secure_channel::MessageCounterManager>();
stateParams.groupDataProvider = params.groupDataProvider;

ReturnErrorOnFailure(stateParams.fabricTable->Init(params.fabricIndependentStorage));
ReturnErrorOnFailure(sessionResumptionStorage->Init(params.fabricIndependentStorage));

auto delegate = chip::Platform::MakeUnique<ControllerFabricDelegate>();
ReturnErrorOnFailure(delegate->Init(stateParams.sessionMgr, stateParams.groupDataProvider));
Expand Down Expand Up @@ -186,7 +190,7 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
#if CONFIG_NETWORK_LAYER_BLE
nullptr,
#endif
stateParams.sessionMgr, stateParams.fabricTable, stateParams.groupDataProvider));
stateParams.sessionMgr, stateParams.fabricTable, stateParams.sessionResumptionStorage, stateParams.groupDataProvider));

//
// We need to advertise the port that we're listening to for unsolicited messages over UDP. However, we have both a IPv4
Expand Down Expand Up @@ -218,12 +222,13 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
stateParams.caseClientPool = Platform::New<DeviceControllerSystemStateParams::CASEClientPool>();

DeviceProxyInitParams deviceInitParams = {
.sessionManager = stateParams.sessionMgr,
.exchangeMgr = stateParams.exchangeMgr,
.fabricTable = stateParams.fabricTable,
.clientPool = stateParams.caseClientPool,
.groupDataProvider = stateParams.groupDataProvider,
.mrpLocalConfig = Optional<ReliableMessageProtocolConfig>::Value(GetLocalMRPConfig()),
.sessionManager = stateParams.sessionMgr,
.sessionResumptionStorage = stateParams.sessionResumptionStorage,
.exchangeMgr = stateParams.exchangeMgr,
.fabricTable = stateParams.fabricTable,
.clientPool = stateParams.caseClientPool,
.groupDataProvider = stateParams.groupDataProvider,
.mrpLocalConfig = Optional<ReliableMessageProtocolConfig>::Value(GetLocalMRPConfig()),
};

CASESessionManagerConfig sessionManagerConfig = {
Expand Down
1 change: 1 addition & 0 deletions src/controller/CHIPDeviceControllerSystemState.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ struct DeviceControllerSystemStateParams
// Params that will be deallocated via Platform::Delete in
// DeviceControllerSystemState::Shutdown.
DeviceTransportMgr * transportMgr = nullptr;
SessionResumptionStorage * sessionResumptionStorage = nullptr;
SessionManager * sessionMgr = nullptr;
Messaging::ExchangeManager * exchangeMgr = nullptr;
secure_channel::MessageCounterManager * messageCounterManager = nullptr;
Expand Down
3 changes: 3 additions & 0 deletions src/credentials/FabricTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/CHIPTLV.h>
#include <lib/core/Optional.h>
#include <lib/core/ScopedNodeId.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/Span.h>
Expand Down Expand Up @@ -85,6 +86,8 @@ class DLL_EXPORT FabricInfo
}

NodeId GetNodeId() const { return mOperationalId.GetNodeId(); }
ScopedNodeId GetScopedNodeId() const { return ScopedNodeId(mOperationalId.GetNodeId(), mFabricIndex); }
ScopedNodeId GetScopedNodeIdForNode(const NodeId node) const { return ScopedNodeId(node, mFabricIndex); }
// TODO(#15049): Refactor/rename PeerId to OperationalId or OpId throughout source
PeerId GetPeerId() const { return mOperationalId; }
PeerId GetPeerIdForNode(const NodeId node) const
Expand Down
12 changes: 12 additions & 0 deletions src/crypto/CHIPCryptoPAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,18 @@ class CapacityBoundBuffer
ClearSecretData(&bytes[0], Cap);
}

CapacityBoundBuffer & operator=(const CapacityBoundBuffer & other)
{
// Guard self assignment
if (this == &other)
return *this;

ClearSecretData(&bytes[0], Cap);
SetLength(other.Length());
::memcpy(Bytes(), other.Bytes(), other.Length());
return *this;
}

/** @brief Set current length of the buffer that's being used
* @return Returns error if new length is > capacity
**/
Expand Down
2 changes: 1 addition & 1 deletion src/lib/core/CHIPConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -1669,7 +1669,7 @@ extern const char CHIP_NON_PRODUCTION_MARKER[];
* Maximum number of CASE sessions that a device caches, that can be resumed
*/
#ifndef CHIP_CONFIG_CASE_SESSION_RESUME_CACHE_SIZE
#define CHIP_CONFIG_CASE_SESSION_RESUME_CACHE_SIZE 4
#define CHIP_CONFIG_CASE_SESSION_RESUME_CACHE_SIZE 64
#endif

/**
Expand Down
8 changes: 8 additions & 0 deletions src/lib/support/DefaultStorageKeyAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ class DefaultStorageKeyAllocator
// FailSafeContext
const char * FailSafeContextKey() { return Format("g/fsc"); }

// Session resumption
const char * FabricSession(FabricIndex fabric, NodeId nodeId)
{
return Format("f/%x/s/%08" PRIX32 "%08" PRIX32, fabric, static_cast<uint32_t>(nodeId >> 32), static_cast<uint32_t>(nodeId));
}
const char * SessionResumptionIndex() { return Format("f/sri"); }
const char * SessionResumption(const char * resumptionIdBase64) { return Format("s/%s", resumptionIdBase64); }

// Access Control
const char * AccessControlExtensionEntry(FabricIndex fabric) { return Format("f/%x/ac/1", fabric); }

Expand Down
Loading

0 comments on commit 7e883fa

Please sign in to comment.