Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement CASE processing of IPK #16737

Merged
merged 21 commits into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions examples/chip-tool/commands/common/CHIPCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,20 @@ CHIP_ERROR CHIPCommand::Run()
ReturnLogErrorOnFailure(mDefaultStorage.Init());

chip::Controller::FactoryInitParams factoryInitParams;

factoryInitParams.fabricIndependentStorage = &mDefaultStorage;
uint16_t port = mDefaultStorage.GetListenPort();

// Init group data provider that will be used for all group keys and IPKs for the
// chip-tool-configured fabrics. This is OK to do once since the fabric tables
// and the DeviceControllerFactory all "share" in the same underlying data.
// Different commissioner implementations may want to use alternate implementations
// of GroupDataProvider for injection through factoryInitParams.
mGroupDataProvider.SetStorageDelegate(&mDefaultStorage);
ReturnLogErrorOnFailure(mGroupDataProvider.Init());
chip::Credentials::SetGroupDataProvider(&mGroupDataProvider);
factoryInitParams.groupDataProvider = &mGroupDataProvider;
tcarmelveilleux marked this conversation as resolved.
Show resolved Hide resolved

uint16_t port = mDefaultStorage.GetListenPort();
if (port != 0)
{
// Make sure different commissioners run on different ports.
Expand Down Expand Up @@ -94,8 +106,7 @@ CHIP_ERROR CHIPCommand::Run()
ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityBeta, kIdentityBetaFabricId, trustStore));
ReturnLogErrorOnFailure(InitializeCommissioner(kIdentityGamma, kIdentityGammaFabricId, trustStore));

// Initialize Group Data
ReturnLogErrorOnFailure(chip::GroupTesting::InitProvider(mDefaultStorage));
// Initialize Group Data, including IPK
for (auto it = mCommissioners.begin(); it != mCommissioners.end(); it++)
{
chip::FabricInfo * fabric = it->second->GetFabricInfo();
Expand All @@ -104,7 +115,17 @@ CHIP_ERROR CHIPCommand::Run()
uint8_t compressed_fabric_id[sizeof(uint64_t)];
chip::MutableByteSpan compressed_fabric_id_span(compressed_fabric_id);
ReturnLogErrorOnFailure(fabric->GetCompressedId(compressed_fabric_id_span));
ReturnLogErrorOnFailure(chip::GroupTesting::InitData(fabric->GetFabricIndex(), compressed_fabric_id_span));

ReturnLogErrorOnFailure(
chip::GroupTesting::InitData(&mGroupDataProvider, fabric->GetFabricIndex(), compressed_fabric_id_span));

// Configure the default IPK for all fabrics used by CHIP-tool. The epoch
// key is the same, but the derived keys will be different for each fabric.
// This has to be done here after we know the Compressed Fabric ID of all
// chip-tool-managed fabrics
chip::ByteSpan defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
ReturnLogErrorOnFailure(chip::Credentials::SetSingleIpkEpochKey(&mGroupDataProvider, fabric->GetFabricIndex(),
defaultIpk, compressed_fabric_id_span));
}
}
chip::DeviceLayer::PlatformMgr().ScheduleWork(RunQueuedCommand, reinterpret_cast<intptr_t>(this));
Expand Down Expand Up @@ -260,7 +281,8 @@ CHIP_ERROR CHIPCommand::InitializeCommissioner(std::string key, chip::FabricId f
commissionerParams.controllerNOC = nocSpan;
}

commissionerParams.storageDelegate = &mCommissionerStorage;
commissionerParams.storageDelegate = &mCommissionerStorage;
// TODO: Initialize IPK epoch key in ExampleOperationalCredentials issuer rather than relying on DefaultIpkValue
commissionerParams.operationalCredentialsDelegate = mCredIssuerCmds->GetCredentialIssuer();
commissionerParams.controllerVendorId = chip::VendorId::TestVendor1;

Expand Down
5 changes: 5 additions & 0 deletions examples/chip-tool/commands/common/CHIPCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "Command.h"
#include <commands/common/CredentialIssuerCommands.h>
#include <commands/example/ExampleCredentialIssuerCommands.h>
#include <credentials/GroupDataProviderImpl.h>

#pragma once

Expand Down Expand Up @@ -52,6 +53,9 @@ class CHIPCommand : public Command
using PeerId = ::chip::PeerId;
using PeerAddress = ::chip::Transport::PeerAddress;

static constexpr uint16_t kMaxGroupsPerFabric = 5;
static constexpr uint16_t kMaxGroupKeysPerFabric = 8;

CHIPCommand(const char * commandName, CredentialIssuerCommands * credIssuerCmds) :
Command(commandName), mCredIssuerCmds(credIssuerCmds)
{
Expand Down Expand Up @@ -91,6 +95,7 @@ class CHIPCommand : public Command

PersistentStorage mDefaultStorage;
PersistentStorage mCommissionerStorage;
chip::Credentials::GroupDataProviderImpl mGroupDataProvider{ kMaxGroupsPerFabric, kMaxGroupKeysPerFabric };
CredentialIssuerCommands * mCredIssuerCmds;

std::string GetIdentity();
Expand Down
23 changes: 23 additions & 0 deletions examples/platform/linux/AppMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#include <lib/support/CHIPMem.h>
#include <lib/support/ScopedBuffer.h>
#include <lib/support/TestGroupData.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <setup_payload/SetupPayload.h>

Expand Down Expand Up @@ -378,6 +379,7 @@ MyCommissionerCallback gCommissionerCallback;
MyServerStorageDelegate gServerStorage;
ExampleOperationalCredentialsIssuer gOpCredsIssuer;
NodeId gLocalId = kMaxOperationalNodeId;
Credentials::GroupDataProviderImpl gGroupDataProvider;

CHIP_ERROR InitCommissioner()
{
Expand All @@ -388,6 +390,10 @@ CHIP_ERROR InitCommissioner()
factoryParams.listenPort = LinuxDeviceOptions::GetInstance().securedCommissionerPort + 10;
factoryParams.fabricIndependentStorage = &gServerStorage;

gGroupDataProvider.SetStorageDelegate(&gServerStorage);
ReturnErrorOnFailure(gGroupDataProvider.Init());
factoryParams.groupDataProvider = &gGroupDataProvider;

params.storageDelegate = &gServerStorage;
params.operationalCredentialsDelegate = &gOpCredsIssuer;

Expand Down Expand Up @@ -427,6 +433,23 @@ CHIP_ERROR InitCommissioner()
auto & factory = Controller::DeviceControllerFactory::GetInstance();
ReturnErrorOnFailure(factory.Init(factoryParams));
ReturnErrorOnFailure(factory.SetupCommissioner(params, gCommissioner));

chip::FabricInfo * fabricInfo = gCommissioner.GetFabricInfo();
VerifyOrReturnError(fabricInfo != nullptr, CHIP_ERROR_INTERNAL);

uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 };
tcarmelveilleux marked this conversation as resolved.
Show resolved Hide resolved
MutableByteSpan compressedFabricIdSpan(compressedFabricId);
ReturnErrorOnFailure(fabricInfo->GetCompressedId(compressedFabricIdSpan));
ChipLogProgress(Support, "Setting up group data for Fabric Index %u with Compressed Fabric ID:",
static_cast<unsigned>(fabricInfo->GetFabricIndex()));
ChipLogByteSpan(Support, compressedFabricIdSpan);

// TODO: Once ExampleOperationalCredentialsIssuer has support, set default IPK on it as well so
// that commissioned devices get the IPK set from real values rather than "test-only" internal hookups.
ByteSpan defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
tcarmelveilleux marked this conversation as resolved.
Show resolved Hide resolved
ReturnLogErrorOnFailure(chip::Credentials::SetSingleIpkEpochKey(&gGroupDataProvider, fabricInfo->GetFabricIndex(), defaultIpk,
compressedFabricIdSpan));
tcarmelveilleux marked this conversation as resolved.
Show resolved Hide resolved

gCommissionerDiscoveryController.SetUserDirectedCommissioningServer(gCommissioner.GetUserDirectedCommissioningServer());
gCommissionerDiscoveryController.SetCommissionerCallback(&gCommissionerCallback);

Expand Down
1 change: 1 addition & 0 deletions src/app/CASEClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ CHIP_ERROR CASEClient::EstablishSession(PeerId peer, const Transport::PeerAddres
Messaging::ExchangeContext * exchange = mInitParams.exchangeMgr->NewContext(session.Value(), &mCASESession);
VerifyOrReturnError(exchange != nullptr, CHIP_ERROR_INTERNAL);

mCASESession.SetGroupDataProvider(mInitParams.groupDataProvider);
ReturnErrorOnFailure(mCASESession.EstablishSession(peerAddress, mInitParams.fabricInfo, peer.GetNodeId(), keyID, exchange, this,
mInitParams.mrpLocalConfig));
mConnectionSuccessCallback = onConnection;
Expand Down
10 changes: 6 additions & 4 deletions src/app/CASEClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#pragma once

#include <credentials/GroupDataProvider.h>
#include <messaging/ExchangeMgr.h>
#include <messaging/ReliableMessageProtocolConfig.h>
#include <protocols/secure_channel/CASESession.h>
Expand All @@ -31,10 +32,11 @@ typedef void (*OnCASEConnectionFailure)(void * context, CASEClient * client, CHI

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

Optional<ReliableMessageProtocolConfig> mrpLocalConfig = Optional<ReliableMessageProtocolConfig>::Missing();
};
Expand Down
4 changes: 3 additions & 1 deletion src/app/CASESessionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@

namespace chip {

CHIP_ERROR CASESessionManager::Init(chip::System::Layer * systemLayer)
CHIP_ERROR CASESessionManager::Init(chip::System::Layer * systemLayer, const CASESessionManagerConfig & params)
{
ReturnErrorOnFailure(params.sessionInitParams.Validate());
mConfig = params;
return AddressResolve::Resolver::Instance().Init(systemLayer);
}

Expand Down
12 changes: 2 additions & 10 deletions src/app/CASESessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,10 @@ struct CASESessionManagerConfig
class CASESessionManager
{
public:
CASESessionManager() = delete;

CASESessionManager(const CASESessionManagerConfig & params)
{
VerifyOrDie(params.sessionInitParams.Validate() == CHIP_NO_ERROR);

mConfig = params;
}

CASESessionManager() = default;
virtual ~CASESessionManager() {}

CHIP_ERROR Init(chip::System::Layer * systemLayer);
CHIP_ERROR Init(chip::System::Layer * systemLayer, const CASESessionManagerConfig & params);
void Shutdown() {}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/app/OperationalDeviceProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,9 @@ bool OperationalDeviceProxy::GetAddress(Inet::IPAddress & addr, uint16_t & port)

CHIP_ERROR OperationalDeviceProxy::EstablishConnection()
{
mCASEClient = mInitParams.clientPool->Allocate(CASEClientInitParams{
mInitParams.sessionManager, mInitParams.exchangeMgr, mInitParams.idAllocator, mFabricInfo, mInitParams.mrpLocalConfig });
mCASEClient = mInitParams.clientPool->Allocate(
CASEClientInitParams{ mInitParams.sessionManager, mInitParams.exchangeMgr, mInitParams.idAllocator, 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
22 changes: 15 additions & 7 deletions src/app/OperationalDeviceProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <app/DeviceProxy.h>
#include <app/util/attribute-filter.h>
#include <app/util/basic-types.h>
#include <credentials/GroupDataProvider.h>
#include <lib/address_resolve/AddressResolve.h>
#include <messaging/ExchangeContext.h>
#include <messaging/ExchangeDelegate.h>
Expand All @@ -48,11 +49,12 @@ namespace chip {

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

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

Expand All @@ -62,6 +64,7 @@ struct DeviceProxyInitParams
ReturnErrorCodeIf(exchangeMgr == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(idAllocator == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(fabricTable == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(groupDataProvider == nullptr, CHIP_ERROR_INCORRECT_STATE);
ReturnErrorCodeIf(clientPool == nullptr, CHIP_ERROR_INCORRECT_STATE);

return CHIP_NO_ERROR;
Expand Down Expand Up @@ -91,10 +94,15 @@ class DLL_EXPORT OperationalDeviceProxy : public DeviceProxy,
~OperationalDeviceProxy() override;
OperationalDeviceProxy(DeviceProxyInitParams & params, PeerId peerId) : mSecureSession(*this)
{
VerifyOrReturn(params.Validate() == CHIP_NO_ERROR);
mInitParams = params;
// Do not do worse
tcarmelveilleux marked this conversation as resolved.
Show resolved Hide resolved
if (params.Validate() != CHIP_NO_ERROR)
{
mState = State::Uninitialized;
return;
}

mSystemLayer = params.exchangeMgr->GetSessionManager()->SystemLayer();
mInitParams = params;
mPeerId = peerId;
mFabricInfo = params.fabricTable->FindFabricWithCompressedId(peerId.GetCompressedFabricId());
mState = State::NeedsAddress;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <credentials/DeviceAttestationConstructor.h>
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/FabricTable.h>
#include <credentials/GroupDataProvider.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/PeerId.h>
Expand Down Expand Up @@ -589,6 +590,7 @@ bool emberAfOperationalCredentialsClusterAddNOCCallback(app::CommandHandler * co
CHIP_ERROR err = CHIP_NO_ERROR;
FabricIndex fabricIndex = 0;
Credentials::GroupDataProvider::KeySet keyset;
FabricInfo * newFabricInfo = nullptr;

uint8_t compressed_fabric_id_buffer[sizeof(uint64_t)];
MutableByteSpan compressed_fabric_id(compressed_fabric_id_buffer);
Expand Down Expand Up @@ -640,11 +642,17 @@ bool emberAfOperationalCredentialsClusterAddNOCCallback(app::CommandHandler * co
// Set the Identity Protection Key (IPK)
VerifyOrExit(ipkValue.size() == Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES,
nocResponse = ConvertToNOCResponseStatus(CHIP_ERROR_INVALID_ARGUMENT));
keyset.keyset_id = 0; // The IPK SHALL be the operational group key under GroupKeySetID of 0
// The IPK SHALL be the operational group key under GroupKeySetID of 0
keyset.keyset_id = Credentials::GroupDataProvider::kIdentityProtectionKeySetId;
keyset.policy = GroupKeyManagement::GroupKeySecurityPolicy::kTrustFirst;
keyset.num_keys_used = 1;
memcpy(keyset.epoch_keys[0].key, ipkValue.data(), Crypto::CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES);
err = gFabricBeingCommissioned.GetCompressedId(compressed_fabric_id);

newFabricInfo = Server::GetInstance().GetFabricTable().FindFabricWithIndex(fabricIndex);
VerifyOrExit(newFabricInfo != nullptr, nocResponse = ConvertToNOCResponseStatus(CHIP_ERROR_INTERNAL));
err = newFabricInfo->GetCompressedId(compressed_fabric_id);
VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

err = groups->SetKeySet(fabricIndex, compressed_fabric_id, keyset);
VerifyOrExit(err == CHIP_NO_ERROR, nocResponse = ConvertToNOCResponseStatus(err));

Expand Down
43 changes: 22 additions & 21 deletions src/app/server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <lib/dnssd/ServiceNaming.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ErrorStr.h>
#include <lib/support/TestGroupData.h>
#include <lib/support/logging/CHIPLogging.h>
#include <messaging/ExchangeMgr.h>
#include <platform/CHIPDeviceLayer.h>
Expand All @@ -46,7 +47,6 @@
#include <system/SystemPacketBuffer.h>
#include <system/TLVPacketBufferBackingStore.h>
#include <transport/SessionManager.h>

using namespace chip::DeviceLayer;

using chip::kMinValidFabricIndex;
Expand Down Expand Up @@ -85,26 +85,11 @@ static ::chip::PersistedCounter sGlobalEventIdCounter;
static ::chip::app::CircularEventBuffer sLoggingBuffer[CHIP_NUM_EVENT_LOGGING_BUFFERS];
#endif // CHIP_CONFIG_ENABLE_SERVER_IM_EVENT

Server::Server() :
mCASESessionManager(CASESessionManagerConfig {
.sessionInitParams = {
.sessionManager = &mSessions,
.exchangeMgr = &mExchangeMgr,
.idAllocator = &mSessionIDAllocator,
.fabricTable = &mFabrics,
.clientPool = &mCASEClientPool,
},
#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0
.dnsCache = nullptr,
#endif
.devicePool = &mDevicePool,
})
{}

CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint16_t unsecureServicePort,
Inet::InterfaceId interfaceId)
{
Access::AccessControl::Delegate * accessDelegate = nullptr;
CASESessionManagerConfig caseSessionManagerConfig;

mSecuredServicePort = secureServicePort;
mUnsecuredServicePort = unsecureServicePort;
Expand Down Expand Up @@ -178,7 +163,7 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint
err = mSessions.Init(&DeviceLayer::SystemLayer(), &mTransports, &mMessageCounterManager, &mDeviceStorage, &GetFabricTable());
SuccessOrExit(err);

err = mFabricDelegate.Init(&mSessions);
err = mFabricDelegate.Init(this);
SuccessOrExit(err);
mFabrics.AddFabricDelegate(&mFabricDelegate);

Expand Down Expand Up @@ -243,15 +228,31 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint
app::DnssdServer::Instance().StartServer();
#endif

caseSessionManagerConfig = {
.sessionInitParams = {
.sessionManager = &mSessions,
.exchangeMgr = &mExchangeMgr,
.idAllocator = &mSessionIDAllocator,
.fabricTable = &mFabrics,
.clientPool = &mCASEClientPool,
.groupDataProvider = &mGroupsProvider,
},
#if CHIP_CONFIG_MDNS_CACHE_SIZE > 0
.dnsCache = nullptr,
#endif
.devicePool = &mDevicePool,
};

err = mCASESessionManager.Init(&DeviceLayer::SystemLayer(), caseSessionManagerConfig);
SuccessOrExit(err);

err = mCASEServer.ListenForSessionEstablishment(&mExchangeMgr, &mTransports,
#if CONFIG_NETWORK_LAYER_BLE
chip::DeviceLayer::ConnectivityMgr().GetBleLayer(),
#endif
&mSessions, &mFabrics);
&mSessions, &mFabrics, &mGroupsProvider);
SuccessOrExit(err);

err = mCASESessionManager.Init(&DeviceLayer::SystemLayer());

// This code is necessary to restart listening to existing groups after a reboot
// Each manufacturer needs to validate that they can rejoin groups by placing this code at the appropriate location for them
//
Expand Down
Loading