/* * * Copyright (c) 2021-2022 Project CHIP Authors * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ChipThreadWork.h" using DeviceControllerFactory = chip::Controller::DeviceControllerFactory; namespace { const chip::Credentials::AttestationTrustStore * GetTestFileAttestationTrustStore(const char * paaTrustStorePath) { static chip::Credentials::FileAttestationTrustStore attestationTrustStore{ paaTrustStorePath }; return &attestationTrustStore; } class ServerStorageDelegate : public chip::PersistentStorageDelegate { public: CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override { size_t bytesRead = 0; CHIP_ERROR err = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size, &bytesRead); size = static_cast(bytesRead); return err; } CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override { return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size); } CHIP_ERROR SyncDeleteKeyValue(const char * key) override { return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key); } }; // FIXME: implement this class class ScriptDevicePairingDelegate final : public chip::Controller::DevicePairingDelegate { public: using OnPairingCompleteCallback = void (*)(CHIP_ERROR err); ~ScriptDevicePairingDelegate() = default; void OnPairingComplete(CHIP_ERROR error) override { if (mPairingComplete == nullptr) { ChipLogError(Controller, "Callback for pairing coomplete is not defined."); return; } mPairingComplete(error); } void SetPairingCompleteCallback(OnPairingCompleteCallback callback) { mPairingComplete = callback; } private: OnPairingCompleteCallback mPairingComplete = nullptr; }; ServerStorageDelegate gServerStorage; ScriptDevicePairingDelegate gPairingDelegate; chip::Credentials::GroupDataProviderImpl gGroupDataProvider; chip::Credentials::PersistentStorageOpCertStore gPersistentStorageOpCertStore; chip::Controller::ExampleOperationalCredentialsIssuer gOperationalCredentialsIssuer; chip::Crypto::RawKeySessionKeystore gSessionKeystore; } // namespace extern "C" void pychip_internal_PairingDelegate_SetPairingCompleteCallback(ScriptDevicePairingDelegate::OnPairingCompleteCallback callback) { gPairingDelegate.SetPairingCompleteCallback(callback); } extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_New(uint64_t localDeviceId, uint32_t localCommissionerCAT) { std::unique_ptr result; CHIP_ERROR err; chip::python::ChipMainThreadScheduleAndWait([&]() { result = std::make_unique(); // System and Inet layers explicitly passed to indicate that the CHIP stack is // already assumed initialized chip::Controller::SetupParams commissionerParams; chip::Controller::FactoryInitParams factoryParams; chip::Platform::ScopedMemoryBuffer noc; chip::Platform::ScopedMemoryBuffer icac; chip::Platform::ScopedMemoryBuffer rcac; chip::Crypto::P256Keypair ephemeralKey; // Initialize device attestation verifier // TODO: add option to pass in custom PAA Trust Store path to the python controller app const chip::Credentials::AttestationTrustStore * testingRootStore = GetTestFileAttestationTrustStore("./credentials/development/paa-root-certs"); chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier(testingRootStore)); factoryParams.fabricIndependentStorage = &gServerStorage; factoryParams.sessionKeystore = &gSessionKeystore; // Initialize group data provider for local group key state and IPKs gGroupDataProvider.SetStorageDelegate(&gServerStorage); gGroupDataProvider.SetSessionKeystore(factoryParams.sessionKeystore); err = gGroupDataProvider.Init(); SuccessOrExit(err); factoryParams.groupDataProvider = &gGroupDataProvider; err = gPersistentStorageOpCertStore.Init(&gServerStorage); SuccessOrExit(err); factoryParams.opCertStore = &gPersistentStorageOpCertStore; commissionerParams.pairingDelegate = &gPairingDelegate; err = ephemeralKey.Initialize(chip::Crypto::ECPKeyTarget::ECDSA); SuccessOrExit(err); err = gOperationalCredentialsIssuer.Initialize(gServerStorage); if (err != CHIP_NO_ERROR) { ChipLogError(Controller, "Operational credentials issuer initialization failed: %s", chip::ErrorStr(err)); ExitNow(); } VerifyOrExit(noc.Alloc(chip::Controller::kMaxCHIPDERCertLength), err = CHIP_ERROR_NO_MEMORY); VerifyOrExit(icac.Alloc(chip::Controller::kMaxCHIPDERCertLength), err = CHIP_ERROR_NO_MEMORY); VerifyOrExit(rcac.Alloc(chip::Controller::kMaxCHIPDERCertLength), err = CHIP_ERROR_NO_MEMORY); { uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 }; chip::MutableByteSpan compressedFabricIdSpan(compressedFabricId); chip::ByteSpan defaultIpk; chip::MutableByteSpan nocSpan(noc.Get(), chip::Controller::kMaxCHIPDERCertLength); chip::MutableByteSpan icacSpan(icac.Get(), chip::Controller::kMaxCHIPDERCertLength); chip::MutableByteSpan rcacSpan(rcac.Get(), chip::Controller::kMaxCHIPDERCertLength); err = gOperationalCredentialsIssuer.GenerateNOCChainAfterValidation( localDeviceId, /* fabricId = */ 1, { { localCommissionerCAT, chip::kUndefinedCAT, chip::kUndefinedCAT } }, ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan); SuccessOrExit(err); commissionerParams.operationalCredentialsDelegate = &gOperationalCredentialsIssuer; commissionerParams.operationalKeypair = &ephemeralKey; commissionerParams.controllerRCAC = rcacSpan; commissionerParams.controllerICAC = icacSpan; commissionerParams.controllerNOC = nocSpan; SuccessOrExit(err = DeviceControllerFactory::GetInstance().Init(factoryParams)); SuccessOrExit(err = DeviceControllerFactory::GetInstance().SetupCommissioner(commissionerParams, *result)); SuccessOrExit(err = result->GetCompressedFabricIdBytes(compressedFabricIdSpan)); ChipLogProgress(Support, "Setting up group data for Fabric Index %u with Compressed Fabric ID:", static_cast(result->GetFabricIndex())); ChipLogByteSpan(Support, compressedFabricIdSpan); defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk(); SuccessOrExit(err = chip::Credentials::SetSingleIpkEpochKey(&gGroupDataProvider, result->GetFabricIndex(), defaultIpk, compressedFabricIdSpan)); } exit: ChipLogProgress(Controller, "Commissioner initialization status: %s", chip::ErrorStr(err)); }); if (err != CHIP_NO_ERROR) { ChipLogError(Controller, "Commissioner initialization failed: %s", chip::ErrorStr(err)); return nullptr; } return result.release(); } /// Returns CHIP_ERROR corresponding to an UnpairDevice call extern "C" PyChipError pychip_internal_Commissioner_Unpair(chip::Controller::DeviceCommissioner * commissioner, uint64_t remoteDeviceId) { CHIP_ERROR err; chip::python::ChipMainThreadScheduleAndWait([&]() { err = commissioner->UnpairDevice(remoteDeviceId); }); return ToPyChipError(err); } extern "C" PyChipError pychip_internal_Commissioner_BleConnectForPairing(chip::Controller::DeviceCommissioner * commissioner, uint64_t remoteNodeId, uint32_t pinCode, uint16_t discriminator) { CHIP_ERROR err; chip::python::ChipMainThreadScheduleAndWait([&]() { chip::RendezvousParameters params; params.SetDiscriminator(discriminator).SetSetupPINCode(pinCode); #if CONFIG_NETWORK_LAYER_BLE params.SetBleLayer(chip::DeviceLayer::ConnectivityMgr().GetBleLayer()).SetPeerAddress(chip::Transport::PeerAddress::BLE()); #endif err = commissioner->PairDevice(remoteNodeId, params); }); return ToPyChipError(err); }