Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * DeviceControllerFactory is a singleton utility class that manages the
22 : * runtime DeviceControllerSystemState and provides APIs to setup DeviceControllers
23 : * and DeviceCommissioners.
24 : *
25 : * Together with the SystemState this class implicitly manages the lifecycle of the underlying
26 : * CHIP stack. It lazily initializes the CHIPStack when setting up Controllers if the SystemState
27 : * was previously shutdown.
28 : */
29 :
30 : #pragma once
31 :
32 : #include <controller/CHIPDeviceController.h>
33 : #include <controller/CHIPDeviceControllerSystemState.h>
34 : #include <credentials/GroupDataProvider.h>
35 : #include <credentials/OperationalCertificateStore.h>
36 : #include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
37 : #include <inet/InetInterface.h>
38 : #include <lib/support/TimerDelegate.h>
39 : #include <protocols/secure_channel/SessionResumptionStorage.h>
40 :
41 : #include <optional>
42 :
43 : namespace chip {
44 :
45 : namespace Controller {
46 :
47 : struct SetupParams
48 : {
49 : OperationalCredentialsDelegate * operationalCredentialsDelegate = nullptr;
50 :
51 : /* The following keypair must correspond to the public key used for generating
52 : controllerNOC. It's used by controller to establish CASE sessions with devices */
53 : Crypto::P256Keypair * operationalKeypair = nullptr;
54 :
55 : /**
56 : * Controls whether or not the operationalKeypair should be owned by the
57 : * caller. By default, this is false, but if the keypair cannot be
58 : * serialized, then setting this to true will allow the caller to manage
59 : * this keypair's lifecycle.
60 : */
61 : bool hasExternallyOwnedOperationalKeypair = false;
62 :
63 : /* The following certificates must be in x509 DER format */
64 : ByteSpan controllerNOC;
65 : ByteSpan controllerICAC;
66 : ByteSpan controllerRCAC;
67 :
68 : //
69 : // This must be set to a valid, operational VendorId value associated with
70 : // the controller/commissioner.
71 : //
72 : chip::VendorId controllerVendorId = VendorId::Unspecified;
73 :
74 : // The Device Pairing Delegated used to initialize a Commissioner
75 : DevicePairingDelegate * pairingDelegate = nullptr;
76 :
77 : /**
78 : * Controls whether we permit multiple DeviceController instances to exist
79 : * on the same logical fabric (identified by the tuple of the fabric's
80 : * root public key + fabric id).
81 : *
82 : * Each controller instance will be associated with its own FabricIndex.
83 : * This pivots the FabricTable to tracking identities instead of fabrics,
84 : * represented by FabricInfo instances that can have colliding logical fabrics.
85 : *
86 : */
87 : bool permitMultiControllerFabrics = false;
88 :
89 : //
90 : // Controls enabling server cluster interactions on a controller. This in turn
91 : // causes the following to get enabled:
92 : //
93 : // - CASEServer to listen for unsolicited Sigma1 messages.
94 : // - Advertisement of active controller operational identities.
95 : //
96 : bool enableServerInteractions = false;
97 :
98 : /**
99 : * Controls whether shutdown of the controller removes the corresponding
100 : * entry from the in-memory fabric table, but NOT from storage.
101 : *
102 : * Note that this means that after controller shutdown the storage and
103 : * in-memory versions of the fabric table will be out of sync.
104 : * For compatibility reasons this is the default behavior.
105 : *
106 : * @see deleteFromFabricTableOnShutdown
107 : */
108 : bool removeFromFabricTableOnShutdown = true;
109 :
110 : /**
111 : * Controls whether shutdown of the controller deletes the corresponding
112 : * entry from the fabric table (both in-memory and storage).
113 : *
114 : * If both `removeFromFabricTableOnShutdown` and this setting are true,
115 : * this setting will take precedence.
116 : *
117 : * @see removeFromFabricTableOnShutdown
118 : */
119 : bool deleteFromFabricTableOnShutdown = false;
120 :
121 : /**
122 : * Specifies whether to utilize the fabric table entry for the given FabricIndex
123 : * for initialization. If provided and neither the operational key pair nor the NOC
124 : * chain are provided, then attempt to locate a fabric corresponding to the given FabricIndex.
125 : */
126 : chip::Optional<FabricIndex> fabricIndex;
127 :
128 : Credentials::DeviceAttestationVerifier * deviceAttestationVerifier = nullptr;
129 : CommissioningDelegate * defaultCommissioner = nullptr;
130 : };
131 :
132 : // TODO everything other than the fabric storage, group data provider, OperationalKeystore,
133 : // OperationalCertificateStore, SessionKeystore, and SessionResumptionStorage here should
134 : // be removed. We're blocked because of the need to support !CHIP_DEVICE_LAYER
135 : struct FactoryInitParams
136 : {
137 : System::Layer * systemLayer = nullptr;
138 : PersistentStorageDelegate * fabricIndependentStorage = nullptr;
139 : Credentials::CertificateValidityPolicy * certificateValidityPolicy = nullptr;
140 : Credentials::GroupDataProvider * groupDataProvider = nullptr;
141 : TimerDelegate * timerDelegate = nullptr;
142 : Crypto::SessionKeystore * sessionKeystore = nullptr;
143 : Inet::EndPointManager<Inet::TCPEndPoint> * tcpEndPointManager = nullptr;
144 : Inet::EndPointManager<Inet::UDPEndPoint> * udpEndPointManager = nullptr;
145 : FabricTable * fabricTable = nullptr;
146 : Crypto::OperationalKeystore * operationalKeystore = nullptr;
147 : Credentials::OperationalCertificateStore * opCertStore = nullptr;
148 : SessionResumptionStorage * sessionResumptionStorage = nullptr;
149 : #if CONFIG_NETWORK_LAYER_BLE
150 : Ble::BleLayer * bleLayer = nullptr;
151 : #endif
152 : #if CHIP_DEVICE_CONFIG_ENABLE_WIFIPAF
153 : WiFiPAF::WiFiPAFLayer * wifipaf_layer = nullptr;
154 : #endif
155 :
156 : //
157 : // Controls enabling server cluster interactions on a controller. This in turn
158 : // causes the following to get enabled:
159 : //
160 : // - Advertisement of active controller operational identities.
161 : //
162 : bool enableServerInteractions = false;
163 :
164 : // Controls whether the controller factory initialization is prevented from
165 : // overwriting the global DnssdServer's secured port. When running in a
166 : // combined server/controller app where the server's port is primary, this
167 : // must be set to true to keep DNS-SD advertising the server's port.
168 : bool preventDnssdPortOverwrite = false;
169 :
170 : /* The port used for operational communication to listen for and send messages over UDP/TCP.
171 : * The default value of `0` will pick any available port. */
172 : uint16_t listenPort = 0;
173 :
174 : // MUST NOT be null during initialization: every application must define the
175 : // data model it wants to use. Backwards-compatibility can use `CodegenDataModelProviderInstance`
176 : // for ember/zap-generated models.
177 : chip::app::DataModel::Provider * dataModelProvider = nullptr;
178 :
179 : std::optional<Inet::InterfaceId> interfaceId;
180 :
181 : // The minimum backoff interval for LIT devices. This is used to calculate the sigma1
182 : // retransmission timeout for LIT devices, ensuring it's at least `minimumLITBackoffInterval`.
183 : // Specifically, the timeout is `max(LIT activeRetransTimeout,
184 : // minimumLITBackoffInterval)`. This prevents issues with MRP retransmission in Thread
185 : // networks when activeRetransTimeout is too small.
186 : // Note: Setting this parameter to a nonzero value is not spec-compliant.
187 : Optional<uint32_t> minimumLITBackoffInterval;
188 : };
189 :
190 : class DeviceControllerFactory
191 : {
192 : public:
193 : static DeviceControllerFactory & GetInstance()
194 : {
195 : static DeviceControllerFactory instance;
196 : return instance;
197 : }
198 :
199 : CHIP_ERROR Init(FactoryInitParams params);
200 :
201 : // Shuts down matter and frees the system state.
202 : //
203 : // Must not be called while any controllers are alive, or while any calls
204 : // to RetainSystemState or EnsureAndRetainSystemState have not been balanced
205 : // by a call to ReleaseSystemState.
206 : void Shutdown();
207 :
208 : CHIP_ERROR SetupController(SetupParams params, DeviceController & controller);
209 : CHIP_ERROR SetupCommissioner(SetupParams params, DeviceCommissioner & commissioner);
210 :
211 : // ----- IO -----
212 : /**
213 : * @brief
214 : * Start the event loop task within the CHIP stack
215 : * @return CHIP_ERROR The return status
216 : */
217 : CHIP_ERROR ServiceEvents();
218 :
219 : ~DeviceControllerFactory();
220 : DeviceControllerFactory(DeviceControllerFactory const &) = delete;
221 : void operator=(DeviceControllerFactory const &) = delete;
222 :
223 : //
224 : // Some clients do not prefer a complete shutdown of the stack being initiated if
225 : // all device controllers have ceased to exist. To avoid that, this method has been
226 : // created to permit retention of the underlying system state.
227 : //
228 : // Calls to this method must be balanced by calling ReleaseSystemState before Shutdown.
229 : //
230 : void RetainSystemState();
231 :
232 : //
233 : // To initiate shutdown of the stack upon termination of all resident controllers in the
234 : // system, invoke this method to decrement the refcount on the system state and consequently,
235 : // shut-down the stack.
236 : //
237 : // This should only be invoked if a matching call to RetainSystemState() was called prior.
238 : //
239 : // Returns true if stack was shut down in response to this call, or false otherwise.
240 : //
241 : bool ReleaseSystemState();
242 :
243 : // Like RetainSystemState(), but will re-initialize the system state first if necessary.
244 : // Calls to this method must be balanced by calling ReleaseSystemState before Shutdown.
245 : CHIP_ERROR EnsureAndRetainSystemState();
246 :
247 : //
248 : // Retrieve a read-only pointer to the system state object that contains pointers to key stack
249 : // singletons. If the pointer is null, it indicates that the DeviceControllerFactory has yet to
250 : // be initialized properly, or has already been shut-down.
251 : //
252 : // This pointer ceases to be valid after a call to Shutdown has been made, or if all active
253 : // DeviceController instances have gone to 0. Consequently, care has to be taken to correctly
254 : // sequence the shutting down of active controllers with any entity that interacts with objects
255 : // present in the system state object. If de-coupling is desired, RetainSystemState and
256 : // ReleaseSystemState can be used to avoid this.
257 : //
258 : const DeviceControllerSystemState * GetSystemState() const { return mSystemState; }
259 :
260 : class ControllerFabricDelegate final : public chip::FabricTable::Delegate
261 : {
262 : public:
263 0 : CHIP_ERROR Init(SessionResumptionStorage * sessionResumptionStorage, Credentials::GroupDataProvider * groupDataProvider)
264 : {
265 0 : VerifyOrReturnError(sessionResumptionStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
266 0 : VerifyOrReturnError(groupDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
267 :
268 0 : mSessionResumptionStorage = sessionResumptionStorage;
269 0 : mGroupDataProvider = groupDataProvider;
270 0 : return CHIP_NO_ERROR;
271 : };
272 :
273 0 : void OnFabricRemoved(const chip::FabricTable & fabricTable, FabricIndex fabricIndex) override
274 : {
275 : (void) fabricTable;
276 0 : if (mGroupDataProvider != nullptr)
277 : {
278 0 : TEMPORARY_RETURN_IGNORED mGroupDataProvider->RemoveFabric(fabricIndex);
279 : }
280 0 : ClearCASEResumptionStateOnFabricChange(fabricIndex);
281 0 : };
282 :
283 0 : void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override
284 : {
285 : (void) fabricTable;
286 0 : ClearCASEResumptionStateOnFabricChange(fabricIndex);
287 0 : }
288 :
289 : private:
290 0 : void ClearCASEResumptionStateOnFabricChange(chip::FabricIndex fabricIndex)
291 : {
292 0 : VerifyOrReturn(mSessionResumptionStorage != nullptr);
293 0 : CHIP_ERROR err = mSessionResumptionStorage->DeleteAll(fabricIndex);
294 0 : if (err != CHIP_NO_ERROR)
295 : {
296 0 : ChipLogError(Controller,
297 : "Warning, failed to delete session resumption state for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
298 : static_cast<unsigned>(fabricIndex), err.Format());
299 : }
300 : }
301 :
302 : Credentials::GroupDataProvider * mGroupDataProvider = nullptr;
303 : SessionResumptionStorage * mSessionResumptionStorage = nullptr;
304 : };
305 :
306 : private:
307 : DeviceControllerFactory() {}
308 : void PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params);
309 : CHIP_ERROR InitSystemState(FactoryInitParams params);
310 : CHIP_ERROR ReinitSystemStateIfNecessary();
311 : void ControllerInitialized(const DeviceController & controller);
312 :
313 : uint16_t mListenPort;
314 : std::optional<Inet::InterfaceId> mInterfaceId;
315 :
316 : DeviceControllerSystemState * mSystemState = nullptr;
317 : PersistentStorageDelegate * mFabricIndependentStorage = nullptr;
318 : Crypto::OperationalKeystore * mOperationalKeystore = nullptr;
319 : Credentials::OperationalCertificateStore * mOpCertStore = nullptr;
320 : Credentials::CertificateValidityPolicy * mCertificateValidityPolicy = nullptr;
321 : SessionResumptionStorage * mSessionResumptionStorage = nullptr;
322 : app::DataModel::Provider * mDataModelProvider = nullptr;
323 : bool mEnableServerInteractions = false;
324 : bool mPreventDnssdPortOverwrite = false;
325 : };
326 :
327 : } // namespace Controller
328 : } // namespace chip
|