| /* |
| * |
| * Copyright (c) 2020 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 "commands/clusters/SubscriptionsCommands.h" |
| #include "commands/common/Commands.h" |
| #include "commands/example/ExampleCredentialIssuerCommands.h" |
| #include <zap-generated/cluster/Commands.h> |
| |
| #include "CastingServer.h" |
| #include "CastingUtils.h" |
| #if defined(ENABLE_CHIP_SHELL) |
| #include "CastingShellCommands.h" |
| #include <lib/shell/Engine.h> // nogncheck |
| #include <thread> |
| #endif |
| |
| #include "LinuxCommissionableDataProvider.h" |
| #include "Options.h" |
| #include <credentials/DeviceAttestationCredsProvider.h> |
| #include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h> |
| #include <credentials/attestation_verifier/DeviceAttestationVerifier.h> |
| #include <credentials/examples/DeviceAttestationCredsExample.h> |
| #include <platform/TestOnlyCommissionableDataProvider.h> |
| |
| using namespace chip; |
| using chip::ArgParser::HelpOptions; |
| using chip::ArgParser::OptionDef; |
| using chip::ArgParser::OptionSet; |
| |
| #if defined(ENABLE_CHIP_SHELL) |
| using chip::Shell::Engine; |
| #endif |
| |
| CHIP_ERROR InitCommissionableDataProvider(LinuxCommissionableDataProvider & provider, LinuxDeviceOptions & options) |
| { |
| chip::Optional<uint32_t> setupPasscode; |
| |
| if (options.payload.setUpPINCode != 0) |
| { |
| setupPasscode.SetValue(options.payload.setUpPINCode); |
| } |
| else if (!options.spake2pVerifier.HasValue()) |
| { |
| uint32_t defaultTestPasscode = 0; |
| chip::DeviceLayer::TestOnlyCommissionableDataProvider TestOnlyCommissionableDataProvider; |
| VerifyOrDie(TestOnlyCommissionableDataProvider.GetSetupPasscode(defaultTestPasscode) == CHIP_NO_ERROR); |
| |
| ChipLogError(Support, |
| "*** WARNING: Using temporary passcode %u due to no neither --passcode or --spake2p-verifier-base64 " |
| "given on command line. This is temporary and will disappear. Please update your scripts " |
| "to explicitly configure onboarding credentials. ***", |
| static_cast<unsigned>(defaultTestPasscode)); |
| setupPasscode.SetValue(defaultTestPasscode); |
| options.payload.setUpPINCode = defaultTestPasscode; |
| } |
| else |
| { |
| // Passcode is 0, so will be ignored, and verifier will take over. Onboarding payload |
| // printed for debug will be invalid, but if the onboarding payload had been given |
| // properly to the commissioner later, PASE will succeed. |
| } |
| |
| // Default to minimum PBKDF iterations |
| uint32_t spake2pIterationCount = chip::Crypto::kSpake2p_Min_PBKDF_Iterations; |
| if (options.spake2pIterations != 0) |
| { |
| spake2pIterationCount = options.spake2pIterations; |
| } |
| ChipLogError(Support, "PASE PBKDF iterations set to %u", static_cast<unsigned>(spake2pIterationCount)); |
| |
| return provider.Init(options.spake2pVerifier, options.spake2pSalt, spake2pIterationCount, setupPasscode, |
| options.payload.discriminator.GetLongValue()); |
| } |
| |
| // To hold SPAKE2+ verifier, discriminator, passcode |
| LinuxCommissionableDataProvider gCommissionableDataProvider; |
| |
| // For shell and command line processing of commands |
| ExampleCredentialIssuerCommands gCredIssuerCommands; |
| Commands gCommands; |
| |
| CHIP_ERROR ProcessClusterCommand(int argc, char ** argv) |
| { |
| if (!CastingServer::GetInstance()->GetActiveTargetVideoPlayer()->IsInitialized()) |
| { |
| CastingServer::GetInstance()->SetDefaultFabricIndex(OnConnectionSuccess, OnConnectionFailure, OnNewOrUpdatedEndpoint); |
| } |
| gCommands.Run(argc, argv); |
| return CHIP_NO_ERROR; |
| } |
| |
| int main(int argc, char * argv[]) |
| { |
| VerifyOrDie(CHIP_NO_ERROR == chip::Platform::MemoryInit()); |
| VerifyOrDie(CHIP_NO_ERROR == chip::DeviceLayer::PlatformMgr().InitChipStack()); |
| |
| #if defined(ENABLE_CHIP_SHELL) |
| Engine::Root().Init(); |
| std::thread shellThread([]() { Engine::Root().RunMainLoop(); }); |
| Shell::RegisterCastingCommands(); |
| #endif |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init(CHIP_CONFIG_KVS_PATH); |
| |
| // Init the commissionable data provider based on command line options |
| // to handle custom verifiers, discriminators, etc. |
| err = InitCommissionableDataProvider(gCommissionableDataProvider, LinuxDeviceOptions::GetInstance()); |
| SuccessOrExit(err); |
| DeviceLayer::SetCommissionableDataProvider(&gCommissionableDataProvider); |
| |
| // Initialize device attestation config |
| SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); |
| |
| // Initialize device attestation verifier from a constant version |
| { |
| // TODO: Replace testingRootStore with a AttestationTrustStore that has the necessary official PAA roots available |
| const chip::Credentials::AttestationTrustStore * testingRootStore = chip::Credentials::GetTestAttestationTrustStore(); |
| SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); |
| } |
| |
| SuccessOrExit(err = CastingServer::GetInstance()->PreInit()); |
| |
| // Enter commissioning mode, open commissioning window |
| static chip::CommonCaseDeviceServerInitParams initParams; |
| VerifyOrDie(CHIP_NO_ERROR == initParams.InitializeStaticResourcesBeforeServerInit()); |
| VerifyOrDie(CHIP_NO_ERROR == chip::Server::GetInstance().Init(initParams)); |
| |
| if (argc > 1) |
| { |
| ChipLogProgress(AppServer, "Command line parameters detected. Skipping auto-start."); |
| } |
| else if (ConnectToCachedVideoPlayer() == CHIP_NO_ERROR) |
| { |
| ChipLogProgress(AppServer, "Skipping commissioner discovery / User directed commissioning flow."); |
| } |
| else |
| { |
| // Send discover commissioners request |
| SuccessOrExit(err = CastingServer::GetInstance()->DiscoverCommissioners()); |
| |
| // Give commissioners some time to respond and then ScheduleWork to initiate commissioning |
| DeviceLayer::SystemLayer().StartTimer( |
| chip::System::Clock::Milliseconds32(kCommissionerDiscoveryTimeoutInMs), |
| [](System::Layer *, void *) { chip::DeviceLayer::PlatformMgr().ScheduleWork(InitCommissioningFlow); }, nullptr); |
| } |
| |
| registerClusters(gCommands, &gCredIssuerCommands); |
| registerCommandsSubscriptions(gCommands, &gCredIssuerCommands); |
| |
| if (argc > 1) |
| { |
| // if there are command-line arguments, then automatically start server |
| ProcessClusterCommand(argc, argv); |
| } |
| |
| DeviceLayer::PlatformMgr().RunEventLoop(); |
| exit: |
| #if defined(ENABLE_CHIP_SHELL) |
| shellThread.join(); |
| #endif |
| if (err != CHIP_NO_ERROR) |
| { |
| ChipLogError(AppServer, "Failed to run TV Casting App: %s", ErrorStr(err)); |
| // End the program with non zero error code to indicate an error. |
| return 1; |
| } |
| return 0; |
| } |