CHIPCommand.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright (c) 2021 Project CHIP Authors
  3. * All rights reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #pragma once
  19. #ifdef CONFIG_USE_LOCAL_STORAGE
  20. #include <controller/ExamplePersistentStorage.h>
  21. #endif // CONFIG_USE_LOCAL_STORAGE
  22. #include "Command.h"
  23. #include <TracingCommandLineArgument.h>
  24. #include <commands/common/CredentialIssuerCommands.h>
  25. #include <commands/example/ExampleCredentialIssuerCommands.h>
  26. #include <credentials/GroupDataProviderImpl.h>
  27. #include <credentials/PersistentStorageOpCertStore.h>
  28. #include <crypto/PersistentStorageOperationalKeystore.h>
  29. #include <crypto/RawKeySessionKeystore.h>
  30. #pragma once
  31. inline constexpr const char kIdentityAlpha[] = "alpha";
  32. inline constexpr const char kIdentityBeta[] = "beta";
  33. inline constexpr const char kIdentityGamma[] = "gamma";
  34. // The null fabric commissioner is a commissioner that isn't on a fabric.
  35. // This is a legal configuration in which the commissioner delegates
  36. // operational communication and invocation of the commssioning complete
  37. // command to a separate on-fabric administrator node.
  38. //
  39. // The null-fabric-commissioner identity is provided here to demonstrate the
  40. // commissioner portion of such an architecture. The null-fabric-commissioner
  41. // can carry a commissioning flow up until the point of operational channel
  42. // (CASE) communcation.
  43. inline constexpr const char kIdentityNull[] = "null-fabric-commissioner";
  44. class CHIPCommand : public Command
  45. {
  46. public:
  47. using ChipDeviceCommissioner = ::chip::Controller::DeviceCommissioner;
  48. using ChipDeviceController = ::chip::Controller::DeviceController;
  49. using IPAddress = ::chip::Inet::IPAddress;
  50. using NodeId = ::chip::NodeId;
  51. using PeerId = ::chip::PeerId;
  52. using PeerAddress = ::chip::Transport::PeerAddress;
  53. static constexpr uint16_t kMaxGroupsPerFabric = 50;
  54. static constexpr uint16_t kMaxGroupKeysPerFabric = 25;
  55. CHIPCommand(const char * commandName, CredentialIssuerCommands * credIssuerCmds, const char * helpText = nullptr) :
  56. Command(commandName, helpText), mCredIssuerCmds(credIssuerCmds)
  57. {
  58. AddArgument("paa-trust-store-path", &mPaaTrustStorePath,
  59. "Path to directory holding PAA certificate information. Can be absolute or relative to the current working "
  60. "directory.");
  61. AddArgument("cd-trust-store-path", &mCDTrustStorePath,
  62. "Path to directory holding CD certificate information. Can be absolute or relative to the current working "
  63. "directory.");
  64. AddArgument("commissioner-name", &mCommissionerName,
  65. "Name of fabric to use. Valid values are \"alpha\", \"beta\", \"gamma\", and integers greater than or equal to "
  66. "4. The default if not specified is \"alpha\".");
  67. AddArgument("commissioner-nodeid", 0, UINT64_MAX, &mCommissionerNodeId,
  68. "The node id to use for chip-tool. If not provided, kTestControllerNodeId (112233, 0x1B669) will be used.");
  69. AddArgument("use-max-sized-certs", 0, 1, &mUseMaxSizedCerts,
  70. "Maximize the size of operational certificates. If not provided or 0 (\"false\"), normally sized operational "
  71. "certificates are generated.");
  72. AddArgument("only-allow-trusted-cd-keys", 0, 1, &mOnlyAllowTrustedCdKeys,
  73. "Only allow trusted CD verifying keys (disallow test keys). If not provided or 0 (\"false\"), untrusted CD "
  74. "verifying keys are allowed. If 1 (\"true\"), test keys are disallowed.");
  75. #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  76. AddArgument("trace_file", &mTraceFile);
  77. AddArgument("trace_log", 0, 1, &mTraceLog);
  78. AddArgument("trace_decode", 0, 1, &mTraceDecode);
  79. #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  80. AddArgument("trace-to", &mTraceTo, "Trace destinations, comma-separated (" SUPPORTED_COMMAND_LINE_TRACING_TARGETS ")");
  81. AddArgument("ble-adapter", 0, UINT16_MAX, &mBleAdapterId);
  82. AddArgument("storage-directory", &mStorageDirectory,
  83. "Directory to place chip-tool's storage files in. Defaults to $TMPDIR, with fallback to /tmp");
  84. AddArgument(
  85. "commissioner-vendor-id", 0, UINT16_MAX, &mCommissionerVendorId,
  86. "The vendor id to use for chip-tool. If not provided, chip::VendorId::TestVendor1 (65521, 0xFFF1) will be used.");
  87. }
  88. /////////// Command Interface /////////
  89. CHIP_ERROR Run() override;
  90. void SetCommandExitStatus(CHIP_ERROR status)
  91. {
  92. mCommandExitStatus = status;
  93. // In interactive mode the stack is not shut down once a command is ended.
  94. // That means calling `ErrorStr(err)` from the main thread when command
  95. // completion is signaled may race since `ErrorStr` uses a static sErrorStr
  96. // buffer for computing the error string. Call it here instead.
  97. if (IsInteractive() && CHIP_NO_ERROR != status)
  98. {
  99. ChipLogError(chipTool, "Run command failure: %s", chip::ErrorStr(status));
  100. }
  101. StopWaiting();
  102. }
  103. protected:
  104. // Will be called in a setting in which it's safe to touch the CHIP
  105. // stack. The rules for Run() are as follows:
  106. //
  107. // 1) If error is returned, Run() must not call SetCommandExitStatus.
  108. // 2) If success is returned Run() must either have called
  109. // SetCommandExitStatus() or scheduled async work that will do that.
  110. virtual CHIP_ERROR RunCommand() = 0;
  111. // Get the wait duration, in seconds, before the command times out.
  112. virtual chip::System::Clock::Timeout GetWaitDuration() const = 0;
  113. // Shut down the command. After a Shutdown call the command object is ready
  114. // to be used for another command invocation.
  115. virtual void Shutdown() { ResetArguments(); }
  116. // Clean up any resources allocated by the command. Some commands may hold
  117. // on to resources after Shutdown(), but Cleanup() will guarantee those are
  118. // cleaned up.
  119. virtual void Cleanup() {}
  120. // If true, skip calling Cleanup() when in interactive mode, so the command
  121. // can keep doing work as needed. Cleanup() will be called when quitting
  122. // interactive mode. This method will be called before Shutdown, so it can
  123. // use member values that Shutdown will normally reset.
  124. virtual bool DeferInteractiveCleanup() { return false; }
  125. // If true, the controller will be created with server capabilities enabled,
  126. // such as advertising operational nodes over DNS-SD and accepting incoming
  127. // CASE sessions.
  128. virtual bool NeedsOperationalAdvertising() { return false; }
  129. // Execute any deferred cleanups. Used when exiting interactive mode.
  130. static void ExecuteDeferredCleanups(intptr_t ignored);
  131. #ifdef CONFIG_USE_LOCAL_STORAGE
  132. PersistentStorage mDefaultStorage;
  133. // TODO: It's pretty weird that we re-init mCommissionerStorage for every
  134. // identity without shutting it down or something in between...
  135. PersistentStorage mCommissionerStorage;
  136. #endif // CONFIG_USE_LOCAL_STORAGE
  137. chip::PersistentStorageOperationalKeystore mOperationalKeystore;
  138. chip::Credentials::PersistentStorageOpCertStore mOpCertStore;
  139. chip::Crypto::RawKeySessionKeystore mSessionKeystore;
  140. static chip::Credentials::GroupDataProviderImpl sGroupDataProvider;
  141. CredentialIssuerCommands * mCredIssuerCmds;
  142. std::string GetIdentity();
  143. CHIP_ERROR GetIdentityNodeId(std::string identity, chip::NodeId * nodeId);
  144. CHIP_ERROR GetIdentityRootCertificate(std::string identity, chip::ByteSpan & span);
  145. void SetIdentity(const char * name);
  146. // This method returns the commissioner instance to be used for running the command.
  147. // The default commissioner instance name is "alpha", but it can be overridden by passing
  148. // --identity "instance name" when running a command.
  149. ChipDeviceCommissioner & CurrentCommissioner();
  150. ChipDeviceCommissioner & GetCommissioner(std::string identity);
  151. private:
  152. CHIP_ERROR MaybeSetUpStack();
  153. void MaybeTearDownStack();
  154. CHIP_ERROR EnsureCommissionerForIdentity(std::string identity);
  155. // Commissioners are keyed by name and local node id.
  156. struct CommissionerIdentity
  157. {
  158. bool operator<(const CommissionerIdentity & other) const
  159. {
  160. return mName < other.mName || (mName == other.mName && mLocalNodeId < other.mLocalNodeId);
  161. }
  162. std::string mName;
  163. chip::NodeId mLocalNodeId;
  164. uint8_t mRCAC[chip::Controller::kMaxCHIPDERCertLength] = {};
  165. uint8_t mICAC[chip::Controller::kMaxCHIPDERCertLength] = {};
  166. uint8_t mNOC[chip::Controller::kMaxCHIPDERCertLength] = {};
  167. size_t mRCACLen;
  168. size_t mICACLen;
  169. size_t mNOCLen;
  170. };
  171. // InitializeCommissioner uses various members, so can't be static. This is
  172. // obviously a little odd, since the commissioners are then shared across
  173. // multiple commands in interactive mode...
  174. CHIP_ERROR InitializeCommissioner(CommissionerIdentity & identity, chip::FabricId fabricId);
  175. void ShutdownCommissioner(const CommissionerIdentity & key);
  176. chip::FabricId CurrentCommissionerId();
  177. static std::map<CommissionerIdentity, std::unique_ptr<ChipDeviceCommissioner>> mCommissioners;
  178. static std::set<CHIPCommand *> sDeferredCleanups;
  179. chip::Optional<char *> mCommissionerName;
  180. chip::Optional<chip::NodeId> mCommissionerNodeId;
  181. chip::Optional<chip::VendorId> mCommissionerVendorId;
  182. chip::Optional<uint16_t> mBleAdapterId;
  183. chip::Optional<char *> mPaaTrustStorePath;
  184. chip::Optional<char *> mCDTrustStorePath;
  185. chip::Optional<bool> mUseMaxSizedCerts;
  186. chip::Optional<bool> mOnlyAllowTrustedCdKeys;
  187. // Cached trust store so commands other than the original startup command
  188. // can spin up commissioners as needed.
  189. static const chip::Credentials::AttestationTrustStore * sTrustStore;
  190. static void RunQueuedCommand(intptr_t commandArg);
  191. typedef decltype(RunQueuedCommand) MatterWorkCallback;
  192. static void RunCommandCleanup(intptr_t commandArg);
  193. // Do cleanup after a commmand is done running. Must happen with the
  194. // Matter stack locked.
  195. void CleanupAfterRun();
  196. // Run the given callback on the Matter thread. Return whether we managed
  197. // to successfully dispatch it to the Matter thread. If we did, *timedOut
  198. // will be set to whether we timed out or whether our mWaitingForResponse
  199. // got set to false by the callback itself.
  200. CHIP_ERROR RunOnMatterQueue(MatterWorkCallback callback, chip::System::Clock::Timeout timeout, bool * timedOut);
  201. CHIP_ERROR mCommandExitStatus = CHIP_ERROR_INTERNAL;
  202. CHIP_ERROR StartWaiting(chip::System::Clock::Timeout seconds);
  203. void StopWaiting();
  204. #if CONFIG_USE_SEPARATE_EVENTLOOP
  205. std::condition_variable cvWaitingForResponse;
  206. std::mutex cvWaitingForResponseMutex;
  207. bool mWaitingForResponse{ true };
  208. #endif // CONFIG_USE_SEPARATE_EVENTLOOP
  209. void StartTracing();
  210. void StopTracing();
  211. #if CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  212. chip::Optional<char *> mTraceFile;
  213. chip::Optional<bool> mTraceLog;
  214. chip::Optional<bool> mTraceDecode;
  215. #endif // CHIP_CONFIG_TRANSPORT_TRACE_ENABLED
  216. chip::CommandLineApp::TracingSetup mTracingSetup;
  217. chip::Optional<std::vector<std::string>> mTraceTo;
  218. };