| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- /*
- *
- * Copyright (c) 2021-2022 Project CHIP Authors
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <platform/CHIPDeviceLayer.h>
- #include <platform/PlatformManager.h>
- #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
- #include <app/clusters/network-commissioning/network-commissioning.h>
- #include <app/server/Dnssd.h>
- #include <app/server/OnboardingCodesUtil.h>
- #include <app/server/Server.h>
- #include <crypto/CHIPCryptoPAL.h>
- #include <crypto/RawKeySessionKeystore.h>
- #include <lib/core/CHIPError.h>
- #include <lib/core/NodeId.h>
- #include <lib/support/logging/CHIPLogging.h>
- #include <credentials/DeviceAttestationConstructor.h>
- #include <credentials/DeviceAttestationVendorReserved.h>
- #include <credentials/GroupDataProviderImpl.h>
- #include <credentials/attestation_verifier/DacOnlyPartialAttestationVerifier.h>
- #include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
- #include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
- #include <credentials/examples/DeviceAttestationCredsExample.h>
- #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>
- #include <platform/CommissionableDataProvider.h>
- #include <platform/DeviceInstanceInfoProvider.h>
- #include <platform/DiagnosticDataProvider.h>
- #include <platform/TestOnlyCommissionableDataProvider.h>
- #include <controller/CHIPDeviceControllerFactory.h>
- #include <controller/ExampleOperationalCredentialsIssuer.h>
- #include <lib/core/CHIPPersistentStorageDelegate.h>
- #include <platform/KeyValueStoreManager.h>
- #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
- #include "TraceHandlers.h"
- #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
- #include <signal.h>
- #include "CommissionerMain.h"
- using namespace chip;
- using namespace chip::Credentials;
- using namespace chip::DeviceLayer;
- using namespace chip::Inet;
- using namespace chip::Transport;
- using namespace chip::app::Clusters;
- using namespace ::chip::Messaging;
- using namespace ::chip::Controller;
- class MyServerStorageDelegate : public PersistentStorageDelegate
- {
- CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override
- {
- ChipLogProgress(AppServer, "Retrieving value from server storage.");
- size_t bytesRead = 0;
- CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size, &bytesRead);
- if (err == CHIP_NO_ERROR)
- {
- ChipLogProgress(AppServer, "Retrieved value from server storage.");
- }
- size = static_cast<uint16_t>(bytesRead);
- return err;
- }
- CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override
- {
- ChipLogProgress(AppServer, "Stored value in server storage");
- return PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
- }
- CHIP_ERROR SyncDeleteKeyValue(const char * key) override
- {
- ChipLogProgress(AppServer, "Delete value in server storage");
- return PersistedStorage::KeyValueStoreMgr().Delete(key);
- }
- };
- class MyCommissionerCallback : public CommissionerCallback
- {
- void ReadyForCommissioning(uint32_t pincode, uint16_t longDiscriminator, PeerAddress peerAddress) override
- {
- CommissionerPairOnNetwork(pincode, longDiscriminator, peerAddress);
- }
- };
- AutoCommissioner gAutoCommissioner;
- DeviceCommissioner gCommissioner;
- CommissionerDiscoveryController gCommissionerDiscoveryController;
- MyCommissionerCallback gCommissionerCallback;
- MyServerStorageDelegate gServerStorage;
- ExampleOperationalCredentialsIssuer gOpCredsIssuer;
- NodeId gLocalId = kMaxOperationalNodeId;
- Credentials::GroupDataProviderImpl gGroupDataProvider;
- Crypto::RawKeySessionKeystore gSessionKeystore;
- CHIP_ERROR InitCommissioner(uint16_t commissionerPort, uint16_t udcListenPort, FabricId fabricId)
- {
- Controller::FactoryInitParams factoryParams;
- Controller::SetupParams params;
- // use a different listen port for the commissioner than the default used by chip-tool.
- factoryParams.listenPort = commissionerPort;
- factoryParams.fabricIndependentStorage = &gServerStorage;
- factoryParams.fabricTable = &Server::GetInstance().GetFabricTable();
- factoryParams.sessionKeystore = &gSessionKeystore;
- gGroupDataProvider.SetStorageDelegate(&gServerStorage);
- gGroupDataProvider.SetSessionKeystore(factoryParams.sessionKeystore);
- ReturnErrorOnFailure(gGroupDataProvider.Init());
- factoryParams.groupDataProvider = &gGroupDataProvider;
- params.operationalCredentialsDelegate = &gOpCredsIssuer;
- uint16_t vendorId;
- DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendorId);
- ChipLogProgress(Support, " ----- Commissioner using vendorId 0x%04X", vendorId);
- params.controllerVendorId = static_cast<VendorId>(vendorId);
- ReturnErrorOnFailure(gOpCredsIssuer.Initialize(gServerStorage));
- if (fabricId != kUndefinedFabricId)
- {
- gOpCredsIssuer.SetFabricIdForNextNOCRequest(fabricId);
- }
- // No need to explicitly set the UDC port since we will use default
- ChipLogProgress(Support, " ----- UDC listening on port %d", udcListenPort);
- ReturnErrorOnFailure(gCommissioner.SetUdcListenPort(udcListenPort));
- // Initialize device attestation verifier
- // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available
- const Credentials::AttestationTrustStore * testingRootStore = Credentials::GetTestAttestationTrustStore();
- SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
- Platform::ScopedMemoryBuffer<uint8_t> noc;
- VerifyOrReturnError(noc.Alloc(Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
- MutableByteSpan nocSpan(noc.Get(), Controller::kMaxCHIPDERCertLength);
- Platform::ScopedMemoryBuffer<uint8_t> icac;
- VerifyOrReturnError(icac.Alloc(Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
- MutableByteSpan icacSpan(icac.Get(), Controller::kMaxCHIPDERCertLength);
- Platform::ScopedMemoryBuffer<uint8_t> rcac;
- VerifyOrReturnError(rcac.Alloc(Controller::kMaxCHIPDERCertLength), CHIP_ERROR_NO_MEMORY);
- MutableByteSpan rcacSpan(rcac.Get(), Controller::kMaxCHIPDERCertLength);
- Crypto::P256Keypair ephemeralKey;
- ReturnErrorOnFailure(ephemeralKey.Initialize(Crypto::ECPKeyTarget::ECDSA));
- ReturnErrorOnFailure(gOpCredsIssuer.GenerateNOCChainAfterValidation(gLocalId, /* fabricId = */ 1, chip::kUndefinedCATs,
- ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan));
- params.operationalKeypair = &ephemeralKey;
- params.controllerRCAC = rcacSpan;
- params.controllerICAC = icacSpan;
- params.controllerNOC = nocSpan;
- params.defaultCommissioner = &gAutoCommissioner;
- // assign prefered feature settings
- CommissioningParameters commissioningParams = gAutoCommissioner.GetCommissioningParameters();
- commissioningParams.SetCheckForMatchingFabric(true);
- gAutoCommissioner.SetCommissioningParameters(commissioningParams);
- auto & factory = Controller::DeviceControllerFactory::GetInstance();
- ReturnErrorOnFailure(factory.Init(factoryParams));
- ReturnErrorOnFailure(factory.SetupCommissioner(params, gCommissioner));
- FabricIndex fabricIndex = gCommissioner.GetFabricIndex();
- VerifyOrReturnError(fabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INTERNAL);
- uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 };
- MutableByteSpan compressedFabricIdSpan(compressedFabricId);
- ReturnErrorOnFailure(gCommissioner.GetCompressedFabricIdBytes(compressedFabricIdSpan));
- ChipLogProgress(Support,
- "Setting up group data for Fabric Index %u with Compressed Fabric ID:", static_cast<unsigned>(fabricIndex));
- 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();
- ReturnLogErrorOnFailure(
- chip::Credentials::SetSingleIpkEpochKey(&gGroupDataProvider, fabricIndex, defaultIpk, compressedFabricIdSpan));
- gCommissionerDiscoveryController.SetUserDirectedCommissioningServer(gCommissioner.GetUserDirectedCommissioningServer());
- gCommissionerDiscoveryController.SetCommissionerCallback(&gCommissionerCallback);
- // advertise operational since we are an admin
- app::DnssdServer::Instance().AdvertiseOperational();
- ChipLogProgress(Support,
- "InitCommissioner nodeId=0x" ChipLogFormatX64 " fabric.fabricId=0x" ChipLogFormatX64 " fabricIndex=0x%x",
- ChipLogValueX64(gCommissioner.GetNodeId()), ChipLogValueX64(fabricId), static_cast<unsigned>(fabricIndex));
- return CHIP_NO_ERROR;
- }
- void ShutdownCommissioner()
- {
- UserDirectedCommissioningServer * udcServer = gCommissioner.GetUserDirectedCommissioningServer();
- if (udcServer != nullptr)
- {
- udcServer->SetUserConfirmationProvider(nullptr);
- }
- gCommissioner.Shutdown();
- }
- class PairingCommand : public Controller::DevicePairingDelegate
- {
- public:
- PairingCommand() :
- mOnDeviceConnectedCallback(OnDeviceConnectedFn, this),
- mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this){};
- /////////// DevicePairingDelegate Interface /////////
- void OnStatusUpdate(Controller::DevicePairingDelegate::Status status) override;
- void OnPairingComplete(CHIP_ERROR error) override;
- void OnPairingDeleted(CHIP_ERROR error) override;
- void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error) override;
- void OnCommissioningStatusUpdate(PeerId peerId, CommissioningStage stageCompleted, CHIP_ERROR error) override;
- void OnReadCommissioningInfo(const ReadCommissioningInfo & info) override;
- void OnFabricCheck(NodeId matchingNodeId) override;
- private:
- #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- static void OnDeviceConnectedFn(void * context, chip::Messaging::ExchangeManager & exchangeMgr,
- const chip::SessionHandle & sessionHandle);
- static void OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error);
- chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
- chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
- #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- };
- PairingCommand gPairingCommand;
- NodeId gRemoteId = kTestDeviceNodeId;
- void PairingCommand::OnStatusUpdate(DevicePairingDelegate::Status status)
- {
- switch (status)
- {
- case DevicePairingDelegate::Status::SecurePairingSuccess:
- ChipLogProgress(AppServer, "Secure Pairing Success");
- break;
- case DevicePairingDelegate::Status::SecurePairingFailed:
- ChipLogError(AppServer, "Secure Pairing Failed");
- break;
- }
- }
- void PairingCommand::OnPairingComplete(CHIP_ERROR err)
- {
- if (err == CHIP_NO_ERROR)
- {
- ChipLogProgress(AppServer, "Pairing Success");
- }
- else
- {
- ChipLogProgress(AppServer, "Pairing Failure: %s", ErrorStr(err));
- }
- }
- void PairingCommand::OnPairingDeleted(CHIP_ERROR err)
- {
- if (err == CHIP_NO_ERROR)
- {
- ChipLogProgress(AppServer, "Pairing Deleted Success");
- }
- else
- {
- ChipLogProgress(AppServer, "Pairing Deleted Failure: %s", ErrorStr(err));
- }
- }
- void PairingCommand::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err)
- {
- if (err == CHIP_NO_ERROR)
- {
- #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- ChipLogProgress(AppServer, "Device commissioning completed with success - getting OperationalDeviceProxy");
- gCommissioner.GetConnectedDevice(gAutoCommissioner.GetCommissioningParameters().GetRemoteNodeId().ValueOr(nodeId),
- &mOnDeviceConnectedCallback, &mOnDeviceConnectionFailureCallback);
- #else // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- ChipLogProgress(AppServer, "Device commissioning completed with success");
- #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- }
- else
- {
- ChipLogProgress(AppServer, "Device commissioning Failure: %s", ErrorStr(err));
- #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
- if (cdc != nullptr)
- {
- cdc->CommissioningFailed(err);
- }
- #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- }
- }
- void PairingCommand::OnCommissioningStatusUpdate(PeerId peerId, CommissioningStage stageCompleted, CHIP_ERROR error)
- {
- ChipLogProgress(AppServer, "OnCommissioningStatusUpdate - stageCompleted='%s' error='%s'", StageToString(stageCompleted),
- ErrorStr(error));
- // if we have successfully finished attestation AND this device already has a NodeId on our fabric
- // then stop commissioning and attempt to connect to it.
- if (stageCompleted == CommissioningStage::kAttestationVerification && error == CHIP_NO_ERROR &&
- gAutoCommissioner.GetCommissioningParameters().GetRemoteNodeId().HasValue())
- {
- gAutoCommissioner.StopCommissioning();
- }
- }
- void PairingCommand::OnReadCommissioningInfo(const ReadCommissioningInfo & info)
- {
- ChipLogProgress(AppServer, "OnReadCommissioningInfo - vendorId=0x%04X productId=0x%04X", info.basic.vendorId,
- info.basic.productId);
- }
- void PairingCommand::OnFabricCheck(NodeId matchingNodeId)
- {
- if (matchingNodeId != kUndefinedNodeId)
- {
- ChipLogProgress(AppServer, "ALREADY ON FABRIC WITH nodeId=0x" ChipLogFormatX64, ChipLogValueX64(matchingNodeId));
- // wait until attestation verification before cancelling so we can validate vid/pid
- }
- }
- #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- void PairingCommand::OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr,
- const SessionHandle & sessionHandle)
- {
- ChipLogProgress(Controller, "OnDeviceConnectedFn");
- CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
- if (cdc != nullptr)
- {
- uint16_t vendorId = gAutoCommissioner.GetCommissioningParameters().GetRemoteVendorId().Value();
- uint16_t productId = gAutoCommissioner.GetCommissioningParameters().GetRemoteProductId().Value();
- ChipLogProgress(Support, " ----- AutoCommissioner -- Commissionee vendorId=0x%04X productId=0x%04X", vendorId, productId);
- cdc->CommissioningSucceeded(vendorId, productId, gRemoteId, exchangeMgr, sessionHandle);
- }
- }
- void PairingCommand::OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR err)
- {
- ChipLogProgress(Controller, "OnDeviceConnectionFailureFn - attempt to get OperationalDeviceProxy failed");
- CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
- {
- cdc->CommissioningFailed(err);
- }
- }
- #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED
- CHIP_ERROR CommissionerPairOnNetwork(uint32_t pincode, uint16_t disc, Transport::PeerAddress address)
- {
- RendezvousParameters params = RendezvousParameters().SetSetupPINCode(pincode).SetDiscriminator(disc).SetPeerAddress(address);
- gOpCredsIssuer.GetRandomOperationalNodeId(&gRemoteId);
- gCommissioner.RegisterPairingDelegate(&gPairingCommand);
- gCommissioner.PairDevice(gRemoteId, params);
- return CHIP_NO_ERROR;
- }
- CHIP_ERROR CommissionerPairUDC(uint32_t pincode, size_t index)
- {
- UDCClientState * state = gCommissioner.GetUserDirectedCommissioningServer()->GetUDCClients().GetUDCClientState(index);
- if (state == nullptr)
- {
- ChipLogProgress(AppServer, "udc client[%ld] null \r\n", static_cast<long>(index));
- return CHIP_ERROR_KEY_NOT_FOUND;
- }
- else
- {
- Transport::PeerAddress peerAddress = state->GetPeerAddress();
- state->SetUDCClientProcessingState(UDCClientProcessingState::kCommissioningNode);
- return CommissionerPairOnNetwork(pincode, state->GetLongDiscriminator(), peerAddress);
- }
- }
- DeviceCommissioner * GetDeviceCommissioner()
- {
- return &gCommissioner;
- }
- CommissionerDiscoveryController * GetCommissionerDiscoveryController()
- {
- return &gCommissionerDiscoveryController;
- }
- #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
|