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 : /* The port used for operational communication to listen for and send messages over UDP/TCP.
165 : * The default value of `0` will pick any available port. */
166 : uint16_t listenPort = 0;
167 :
168 : // MUST NOT be null during initialization: every application must define the
169 : // data model it wants to use. Backwards-compatibility can use `CodegenDataModelProviderInstance`
170 : // for ember/zap-generated models.
171 : chip::app::DataModel::Provider * dataModelProvider = nullptr;
172 :
173 : std::optional<Inet::InterfaceId> interfaceId;
174 :
175 : // The minimum backoff interval for LIT devices. This is used to calculate the sigma1
176 : // retransmission timeout for LIT devices, ensuring it's at least `minimumLITBackoffInterval`.
177 : // Specifically, the timeout is `max(LIT activeRetransTimeout,
178 : // minimumLITBackoffInterval)`. This prevents issues with MRP retransmission in Thread
179 : // networks when activeRetransTimeout is too small.
180 : // Note: Setting this parameter to a nonzero value is not spec-compliant.
181 : Optional<uint32_t> minimumLITBackoffInterval;
182 : };
183 :
184 : class DeviceControllerFactory
185 : {
186 : public:
187 : static DeviceControllerFactory & GetInstance()
188 : {
189 : static DeviceControllerFactory instance;
190 : return instance;
191 : }
192 :
193 : CHIP_ERROR Init(FactoryInitParams params);
194 :
195 : // Shuts down matter and frees the system state.
196 : //
197 : // Must not be called while any controllers are alive, or while any calls
198 : // to RetainSystemState or EnsureAndRetainSystemState have not been balanced
199 : // by a call to ReleaseSystemState.
200 : void Shutdown();
201 :
202 : CHIP_ERROR SetupController(SetupParams params, DeviceController & controller);
203 : CHIP_ERROR SetupCommissioner(SetupParams params, DeviceCommissioner & commissioner);
204 :
205 : // ----- IO -----
206 : /**
207 : * @brief
208 : * Start the event loop task within the CHIP stack
209 : * @return CHIP_ERROR The return status
210 : */
211 : CHIP_ERROR ServiceEvents();
212 :
213 : ~DeviceControllerFactory();
214 : DeviceControllerFactory(DeviceControllerFactory const &) = delete;
215 : void operator=(DeviceControllerFactory const &) = delete;
216 :
217 : //
218 : // Some clients do not prefer a complete shutdown of the stack being initiated if
219 : // all device controllers have ceased to exist. To avoid that, this method has been
220 : // created to permit retention of the underlying system state.
221 : //
222 : // Calls to this method must be balanced by calling ReleaseSystemState before Shutdown.
223 : //
224 : void RetainSystemState();
225 :
226 : //
227 : // To initiate shutdown of the stack upon termination of all resident controllers in the
228 : // system, invoke this method to decrement the refcount on the system state and consequently,
229 : // shut-down the stack.
230 : //
231 : // This should only be invoked if a matching call to RetainSystemState() was called prior.
232 : //
233 : // Returns true if stack was shut down in response to this call, or false otherwise.
234 : //
235 : bool ReleaseSystemState();
236 :
237 : // Like RetainSystemState(), but will re-initialize the system state first if necessary.
238 : // Calls to this method must be balanced by calling ReleaseSystemState before Shutdown.
239 : CHIP_ERROR EnsureAndRetainSystemState();
240 :
241 : //
242 : // Retrieve a read-only pointer to the system state object that contains pointers to key stack
243 : // singletons. If the pointer is null, it indicates that the DeviceControllerFactory has yet to
244 : // be initialized properly, or has already been shut-down.
245 : //
246 : // This pointer ceases to be valid after a call to Shutdown has been made, or if all active
247 : // DeviceController instances have gone to 0. Consequently, care has to be taken to correctly
248 : // sequence the shutting down of active controllers with any entity that interacts with objects
249 : // present in the system state object. If de-coupling is desired, RetainSystemState and
250 : // ReleaseSystemState can be used to avoid this.
251 : //
252 : const DeviceControllerSystemState * GetSystemState() const { return mSystemState; }
253 :
254 : class ControllerFabricDelegate final : public chip::FabricTable::Delegate
255 : {
256 : public:
257 0 : CHIP_ERROR Init(SessionResumptionStorage * sessionResumptionStorage, Credentials::GroupDataProvider * groupDataProvider)
258 : {
259 0 : VerifyOrReturnError(sessionResumptionStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
260 0 : VerifyOrReturnError(groupDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
261 :
262 0 : mSessionResumptionStorage = sessionResumptionStorage;
263 0 : mGroupDataProvider = groupDataProvider;
264 0 : return CHIP_NO_ERROR;
265 : };
266 :
267 0 : void OnFabricRemoved(const chip::FabricTable & fabricTable, FabricIndex fabricIndex) override
268 : {
269 : (void) fabricTable;
270 0 : if (mGroupDataProvider != nullptr)
271 : {
272 0 : TEMPORARY_RETURN_IGNORED mGroupDataProvider->RemoveFabric(fabricIndex);
273 : }
274 0 : ClearCASEResumptionStateOnFabricChange(fabricIndex);
275 0 : };
276 :
277 0 : void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override
278 : {
279 : (void) fabricTable;
280 0 : ClearCASEResumptionStateOnFabricChange(fabricIndex);
281 0 : }
282 :
283 : private:
284 0 : void ClearCASEResumptionStateOnFabricChange(chip::FabricIndex fabricIndex)
285 : {
286 0 : VerifyOrReturn(mSessionResumptionStorage != nullptr);
287 0 : CHIP_ERROR err = mSessionResumptionStorage->DeleteAll(fabricIndex);
288 0 : if (err != CHIP_NO_ERROR)
289 : {
290 0 : ChipLogError(Controller,
291 : "Warning, failed to delete session resumption state for fabric index 0x%x: %" CHIP_ERROR_FORMAT,
292 : static_cast<unsigned>(fabricIndex), err.Format());
293 : }
294 : }
295 :
296 : Credentials::GroupDataProvider * mGroupDataProvider = nullptr;
297 : SessionResumptionStorage * mSessionResumptionStorage = nullptr;
298 : };
299 :
300 : private:
301 : DeviceControllerFactory() {}
302 : void PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params);
303 : CHIP_ERROR InitSystemState(FactoryInitParams params);
304 : CHIP_ERROR ReinitSystemStateIfNecessary();
305 : void ControllerInitialized(const DeviceController & controller);
306 :
307 : uint16_t mListenPort;
308 : std::optional<Inet::InterfaceId> mInterfaceId;
309 :
310 : DeviceControllerSystemState * mSystemState = nullptr;
311 : PersistentStorageDelegate * mFabricIndependentStorage = nullptr;
312 : Crypto::OperationalKeystore * mOperationalKeystore = nullptr;
313 : Credentials::OperationalCertificateStore * mOpCertStore = nullptr;
314 : Credentials::CertificateValidityPolicy * mCertificateValidityPolicy = nullptr;
315 : SessionResumptionStorage * mSessionResumptionStorage = nullptr;
316 : app::DataModel::Provider * mDataModelProvider = nullptr;
317 : bool mEnableServerInteractions = false;
318 : };
319 :
320 : } // namespace Controller
321 : } // namespace chip
|