blob: f5815922cc14eb113aab388e58052fe315d1ff3f [file] [log] [blame]
Jerry Johnsf68cd642022-01-28 16:39:08 -08001/*
2 *
Evgeny Margolisa8dcee42022-03-23 09:50:37 -07003 * Copyright (c) 2020-2022 Project CHIP Authors
Jerry Johnsf68cd642022-01-28 16:39:08 -08004 * Copyright (c) 2019-2020 Google LLC.
5 * Copyright (c) 2013-2018 Nest Labs, Inc.
6 * All rights reserved.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include <type_traits>
22
Jerry Johnsf68cd642022-01-28 16:39:08 -080023#include "ChipDeviceController-ScriptDevicePairingDelegate.h"
24#include "ChipDeviceController-StorageDelegate.h"
25
Song GUOe75d35a2023-03-01 08:57:22 +080026#include "controller/python/chip/crypto/p256keypair.h"
Jerry Johnsf68cd642022-01-28 16:39:08 -080027#include "controller/python/chip/interaction_model/Delegate.h"
28
Song GUOd8e7e432024-06-04 17:53:30 +000029#include <app/icd/client/DefaultICDClientStorage.h>
Jerry Johnsf68cd642022-01-28 16:39:08 -080030#include <controller/CHIPDeviceController.h>
31#include <controller/CHIPDeviceControllerFactory.h>
32#include <controller/ExampleOperationalCredentialsIssuer.h>
33#include <lib/support/BytesToHex.h>
34#include <lib/support/CHIPMem.h>
35#include <lib/support/CodeUtils.h>
36#include <lib/support/DLLUtil.h>
37#include <lib/support/ScopedBuffer.h>
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -040038#include <lib/support/TestGroupData.h>
Jerry Johnsf68cd642022-01-28 16:39:08 -080039#include <lib/support/logging/CHIPLogging.h>
40
Song GUOe75d35a2023-03-01 08:57:22 +080041#include <controller/python/chip/commissioning/PlaceholderOperationalCredentialsIssuer.h>
Song GUOb9d32ec2022-10-24 14:40:11 +080042#include <controller/python/chip/native/PyChipError.h>
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -040043#include <credentials/GroupDataProviderImpl.h>
Tennessee Carmel-Veilleux22fb6c32022-02-22 16:49:16 -050044#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
45#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
Vijay Selvaraj395bb1f2022-03-23 15:36:37 -040046#include <credentials/attestation_verifier/FileAttestationTrustStore.h>
Jerry Johnsf68cd642022-01-28 16:39:08 -080047
48using namespace chip;
49
Jerry Johnsf68cd642022-01-28 16:39:08 -080050using Py_GenerateNOCChainFunc = void (*)(void * pyContext, const char * csrElements, const char * attestationSignature,
51 const char * dac, const char * pai, const char * paa,
52 Controller::OnNOCChainGeneration onNocChainGenerationFunc);
53using Py_SetNodeIdForNextNOCRequest = void (*)(void * pyContext, NodeId nodeId);
54using Py_SetFabricIdForNextNOCRequest = void (*)(void * pyContext, FabricId fabricId);
55
Vijay Selvaraj395bb1f2022-03-23 15:36:37 -040056namespace {
57const chip::Credentials::AttestationTrustStore * GetTestFileAttestationTrustStore(const char * paaTrustStorePath)
58{
59 static chip::Credentials::FileAttestationTrustStore attestationTrustStore{ paaTrustStorePath };
60
61 return &attestationTrustStore;
62}
Song GUOe75d35a2023-03-01 08:57:22 +080063
64chip::Python::PlaceholderOperationalCredentialsIssuer sPlaceholderOperationalCredentialsIssuer;
Vijay Selvaraj395bb1f2022-03-23 15:36:37 -040065} // namespace
66
Jerry Johnsf68cd642022-01-28 16:39:08 -080067namespace chip {
68namespace Controller {
69namespace Python {
70
71class OperationalCredentialsAdapter : public OperationalCredentialsDelegate
72{
73public:
74 OperationalCredentialsAdapter(uint32_t fabricCredentialsIndex) : mExampleOpCredsIssuer(fabricCredentialsIndex) {}
75
76 CHIP_ERROR Initialize(PersistentStorageDelegate & storageDelegate) { return mExampleOpCredsIssuer.Initialize(storageDelegate); }
77
Evgeny Margolisa8dcee42022-03-23 09:50:37 -070078 CHIP_ERROR GenerateNOCChain(NodeId nodeId, FabricId fabricId, const CATValues & cats, const Crypto::P256PublicKey & pubKey,
79 MutableByteSpan & rcac, MutableByteSpan & icac, MutableByteSpan & noc)
Jerry Johnsf68cd642022-01-28 16:39:08 -080080 {
Evgeny Margolisa8dcee42022-03-23 09:50:37 -070081 return mExampleOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, pubKey, rcac, icac, noc);
Jerry Johnsf68cd642022-01-28 16:39:08 -080082 }
83
Tennessee Carmel-Veilleuxdfc1a702022-08-19 18:20:12 -040084 void SetMaximallyLargeCertsUsed(bool enabled) { mExampleOpCredsIssuer.SetMaximallyLargeCertsUsed(enabled); }
85
Jerry Johnsf68cd642022-01-28 16:39:08 -080086private:
C Freemana208c3d2022-04-04 08:23:45 -040087 CHIP_ERROR GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce, const ByteSpan & attestationSignature,
88 const ByteSpan & attestationChallenge, const ByteSpan & DAC, const ByteSpan & PAI,
Jerry Johnsf68cd642022-01-28 16:39:08 -080089 Callback::Callback<OnNOCChainGeneration> * onCompletion) override
90 {
C Freemana208c3d2022-04-04 08:23:45 -040091 return mExampleOpCredsIssuer.GenerateNOCChain(csrElements, csrNonce, attestationSignature, attestationChallenge, DAC, PAI,
92 onCompletion);
Jerry Johnsf68cd642022-01-28 16:39:08 -080093 }
94
95 void SetNodeIdForNextNOCRequest(NodeId nodeId) override { mExampleOpCredsIssuer.SetNodeIdForNextNOCRequest(nodeId); }
96
97 void SetFabricIdForNextNOCRequest(FabricId fabricId) override { mExampleOpCredsIssuer.SetFabricIdForNextNOCRequest(fabricId); }
98
99 ExampleOperationalCredentialsIssuer mExampleOpCredsIssuer;
100};
101
102} // namespace Python
103} // namespace Controller
104} // namespace chip
105
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -0400106extern chip::Credentials::GroupDataProviderImpl sGroupDataProvider;
Jerry Johnsf68cd642022-01-28 16:39:08 -0800107extern chip::Controller::ScriptDevicePairingDelegate sPairingDelegate;
Song GUOd8e7e432024-06-04 17:53:30 +0000108extern chip::app::DefaultICDClientStorage sICDClientStorage;
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -0400109
C Freeman8ffe4222022-02-02 14:21:16 -0500110class TestCommissioner : public chip::Controller::AutoCommissioner
111{
112public:
Andrei Litvin0c06ba52022-04-07 05:19:33 -1000113 TestCommissioner() { Reset(); }
C Freeman8ffe4222022-02-02 14:21:16 -0500114 ~TestCommissioner() {}
C Freemanc3b18102022-04-04 16:17:09 -0400115 CHIP_ERROR SetCommissioningParameters(const chip::Controller::CommissioningParameters & params) override
116 {
117 mIsWifi = false;
118 mIsThread = false;
119 if (params.GetWiFiCredentials().HasValue())
120 {
121 mIsWifi = true;
122 }
123 else if (params.GetThreadOperationalDataset().HasValue())
124 {
125 mIsThread = true;
126 }
127 return chip::Controller::AutoCommissioner::SetCommissioningParameters(params);
128 }
C Freeman8ffe4222022-02-02 14:21:16 -0500129 CHIP_ERROR CommissioningStepFinished(CHIP_ERROR err,
130 chip::Controller::CommissioningDelegate::CommissioningReport report) override
131 {
C Freemanc3b18102022-04-04 16:17:09 -0400132 mTestCommissionerUsed = true;
133 if (mFailOnReportAfterStage == report.stageCompleted)
134 {
135 return CHIP_ERROR_INTERNAL;
136 }
137 if (mSimulateFailureOnStage == report.stageCompleted)
138 {
139 // Pretend we received an error from the device during this stage
140 err = CHIP_ERROR_INTERNAL;
141 }
C Freeman89d538c2023-01-26 12:29:48 -0500142 if (mPrematureCompleteAfter == report.stageCompleted)
143 {
144 auto commissioner = chip::Controller::AutoCommissioner::GetCommissioner();
145 auto proxy = chip::Controller::AutoCommissioner::GetCommissioneeDeviceProxy();
146 auto stage = chip::Controller::CommissioningStage::kSendComplete;
147 auto params = chip::Controller::CommissioningParameters();
148 commissioner->PerformCommissioningStep(proxy, stage, params, this, 0, GetCommandTimeout(proxy, stage));
149 return CHIP_NO_ERROR;
150 }
151
152 if (mPrematureCompleteAfter != chip::Controller::CommissioningStage::kError &&
153 report.stageCompleted == chip::Controller::CommissioningStage::kSendComplete)
154 {
155 if (report.Is<chip::Controller::CommissioningErrorInfo>())
156 {
157 uint8_t code = chip::to_underlying(report.Get<chip::Controller::CommissioningErrorInfo>().commissioningError);
158 mCompletionError = chip::ChipError(chip::ChipError::SdkPart::kIMClusterStatus, code);
159 }
160 else
161 {
162 mCompletionError = err;
163 }
164 }
Song GUO8e3d98c2023-12-14 12:11:32 +0800165 if (report.stageCompleted == chip::Controller::CommissioningStage::kReadCommissioningInfo2)
C Freemanac3535b2023-07-18 13:32:59 -0400166 {
167 mReadCommissioningInfo = report.Get<chip::Controller::ReadCommissioningInfo>();
168 }
169 if (report.stageCompleted == chip::Controller::CommissioningStage::kConfigureTimeZone)
170 {
171 mNeedsDST = report.Get<chip::Controller::TimeZoneResponseInfo>().requiresDSTOffsets;
172 }
C Freeman89d538c2023-01-26 12:29:48 -0500173
C Freeman8ffe4222022-02-02 14:21:16 -0500174 return chip::Controller::AutoCommissioner::CommissioningStepFinished(err, report);
175 }
C Freemanc3b18102022-04-04 16:17:09 -0400176 // This will cause the COMMISSIONER to fail after the given stage. Setting this to kSecurePairing will cause the
177 // StartCommissioning call to fail.
178 bool SimulateFailAfter(chip::Controller::CommissioningStage stage)
179 {
180 ChipLogProgress(Controller, "setting simulate fail after stage %s", chip::Controller::StageToString(stage));
181 if (!ValidStage(stage) && stage != chip::Controller::CommissioningStage::kError)
182 {
183 return false;
184 }
185 mSimulateFailureOnStage = stage;
186 return true;
187 }
188 bool SimulateFailOnReport(chip::Controller::CommissioningStage stage)
189 {
190 if (!ValidStage(stage) && stage != chip::Controller::CommissioningStage::kError)
191 {
192 return false;
193 }
194 mFailOnReportAfterStage = stage;
195 return true;
196 }
C Freeman89d538c2023-01-26 12:29:48 -0500197 bool PrematureCompleteAfter(chip::Controller::CommissioningStage stage)
198 {
199 if (!ValidStage(stage) && stage != chip::Controller::CommissioningStage::kError)
200 {
201 return false;
202 }
203 mPrematureCompleteAfter = stage;
204 return true;
205 }
C Freemanc3b18102022-04-04 16:17:09 -0400206 bool CheckCallbacks()
207 {
208 bool successFailureOk;
209 bool updatesOk;
210 if (mFailOnReportAfterStage != chip::Controller::CommissioningStage::kError)
211 {
212 successFailureOk = mReceivedCommissioningFailureStage == mFailOnReportAfterStage && !mReceivedCommissioningSuccess;
213 updatesOk = StatusUpdatesOk(mFailOnReportAfterStage);
214 }
215 else if (mSimulateFailureOnStage != chip::Controller::CommissioningStage::kError)
216 {
217 successFailureOk = mReceivedCommissioningFailureStage == mSimulateFailureOnStage && !mReceivedCommissioningSuccess;
218 updatesOk = StatusUpdatesOk(mSimulateFailureOnStage);
219 }
220 else
221 {
222 successFailureOk = mReceivedCommissioningSuccess;
223 updatesOk = StatusUpdatesOk(chip::Controller::CommissioningStage::kError);
224 }
225 ChipLogProgress(Controller, "Checking callbacks: success failure ok? %d updates ok? %d", successFailureOk, updatesOk);
226 return successFailureOk && updatesOk;
227 }
228 bool CheckPaseConnection(NodeId nodeId)
229 {
230 bool paseShouldBeOpen = false;
231 if (chip::to_underlying(mFailOnReportAfterStage) >=
232 chip::to_underlying(chip::Controller::CommissioningStage::kWiFiNetworkSetup) ||
233 chip::to_underlying(mSimulateFailureOnStage) >=
234 chip::to_underlying(chip::Controller::CommissioningStage::kWiFiNetworkSetup))
235 {
236 // Pase should be open still
237 paseShouldBeOpen = true;
238 }
239 CommissioneeDeviceProxy * proxy;
240 bool paseIsOpen =
241 (chip::Controller::AutoCommissioner::GetCommissioner()->GetDeviceBeingCommissioned(nodeId, &proxy) == CHIP_NO_ERROR);
242 ChipLogProgress(Controller, "Checking pase connection state: Should be open? %d is open? %d", paseShouldBeOpen, paseIsOpen);
243
244 return paseShouldBeOpen == paseIsOpen;
245 }
C Freemanac3535b2023-07-18 13:32:59 -0400246 bool CheckStageSuccessful(uint8_t stage) { return mReceivedStageSuccess[stage]; }
C Freemanc3b18102022-04-04 16:17:09 -0400247 void Reset()
248 {
249 mTestCommissionerUsed = false;
250 mReceivedCommissioningSuccess = false;
251 mReceivedCommissioningFailureStage = chip::Controller::CommissioningStage::kError;
252 for (size_t i = 0; i < kNumCommissioningStages; ++i)
253 {
254 mReceivedStageSuccess[i] = false;
255 mReceivedStageFailure[i] = false;
256 }
257 mSimulateFailureOnStage = chip::Controller::CommissioningStage::kError;
258 mFailOnReportAfterStage = chip::Controller::CommissioningStage::kError;
C Freeman89d538c2023-01-26 12:29:48 -0500259 mPrematureCompleteAfter = chip::Controller::CommissioningStage::kError;
C Freemanac3535b2023-07-18 13:32:59 -0400260 mReadCommissioningInfo = chip::Controller::ReadCommissioningInfo();
261 mNeedsDST = false;
Stefan Agner16a79eb2024-06-19 16:26:32 +0200262 mCompletionError = CHIP_NO_ERROR;
C Freemanc3b18102022-04-04 16:17:09 -0400263 }
264 bool GetTestCommissionerUsed() { return mTestCommissionerUsed; }
265 void OnCommissioningSuccess(chip::PeerId peerId) { mReceivedCommissioningSuccess = true; }
266 void OnCommissioningFailure(chip::PeerId peerId, CHIP_ERROR error, chip::Controller::CommissioningStage stageFailed,
267 chip::Optional<chip::Credentials::AttestationVerificationResult> additionalErrorInfo)
268 {
269 mReceivedCommissioningFailureStage = stageFailed;
270 }
271 void OnCommissioningStatusUpdate(chip::PeerId peerId, chip::Controller::CommissioningStage stageCompleted, CHIP_ERROR error)
272 {
273 if (error == CHIP_NO_ERROR)
274 {
275 mReceivedStageSuccess[chip::to_underlying(stageCompleted)] = true;
276 }
277 else
278 {
279 mReceivedStageFailure[chip::to_underlying(stageCompleted)] = true;
280 }
C Freeman89d538c2023-01-26 12:29:48 -0500281 if (stageCompleted == chip::Controller::CommissioningStage::kCleanup &&
282 mPrematureCompleteAfter != chip::Controller::CommissioningStage::kError)
283 {
284 // We need to manually clean up the proxy here because we're doing bad things in the name of testing
285 ChipLogProgress(Controller, "Cleaning up dangling proxies");
286 auto commissioner = chip::Controller::AutoCommissioner::GetCommissioner();
287 auto proxy = chip::Controller::AutoCommissioner::GetCommissioneeDeviceProxy();
288 if (proxy != nullptr)
289 {
290 commissioner->StopPairing(proxy->GetDeviceId());
291 }
292 }
C Freemanc3b18102022-04-04 16:17:09 -0400293 }
294
C Freeman89d538c2023-01-26 12:29:48 -0500295 CHIP_ERROR GetCompletionError() { return mCompletionError; }
296
C Freemanc3b18102022-04-04 16:17:09 -0400297private:
298 static constexpr uint8_t kNumCommissioningStages = chip::to_underlying(chip::Controller::CommissioningStage::kCleanup) + 1;
299 chip::Controller::CommissioningStage mSimulateFailureOnStage = chip::Controller::CommissioningStage::kError;
300 chip::Controller::CommissioningStage mFailOnReportAfterStage = chip::Controller::CommissioningStage::kError;
C Freeman89d538c2023-01-26 12:29:48 -0500301 chip::Controller::CommissioningStage mPrematureCompleteAfter = chip::Controller::CommissioningStage::kError;
C Freemanc3b18102022-04-04 16:17:09 -0400302 bool mTestCommissionerUsed = false;
303 bool mReceivedCommissioningSuccess = false;
304 chip::Controller::CommissioningStage mReceivedCommissioningFailureStage = chip::Controller::CommissioningStage::kError;
305 bool mReceivedStageSuccess[kNumCommissioningStages];
306 bool mReceivedStageFailure[kNumCommissioningStages];
C Freeman89d538c2023-01-26 12:29:48 -0500307 bool mIsWifi = false;
308 bool mIsThread = false;
309 CHIP_ERROR mCompletionError = CHIP_NO_ERROR;
C Freemanac3535b2023-07-18 13:32:59 -0400310 // Contains information about whether the device needs time sync
311 chip::Controller::ReadCommissioningInfo mReadCommissioningInfo;
312 bool mNeedsDST = false;
C Freemanc3b18102022-04-04 16:17:09 -0400313 bool ValidStage(chip::Controller::CommissioningStage stage)
314 {
C Freemanac3535b2023-07-18 13:32:59 -0400315 switch (stage)
C Freemanc3b18102022-04-04 16:17:09 -0400316 {
C Freemanac3535b2023-07-18 13:32:59 -0400317 case chip::Controller::CommissioningStage::kWiFiNetworkEnable:
318 case chip::Controller::CommissioningStage::kFailsafeBeforeWiFiEnable:
319 case chip::Controller::CommissioningStage::kWiFiNetworkSetup:
320 return mIsWifi;
321 case chip::Controller::CommissioningStage::kThreadNetworkEnable:
322 case chip::Controller::CommissioningStage::kFailsafeBeforeThreadEnable:
323 case chip::Controller::CommissioningStage::kThreadNetworkSetup:
324 return mIsThread;
325 case chip::Controller::CommissioningStage::kConfigureUTCTime:
326 return mReadCommissioningInfo.requiresUTC;
327 case chip::Controller::CommissioningStage::kConfigureTimeZone:
328 return mReadCommissioningInfo.requiresTimeZone && mParams.GetTimeZone().HasValue();
329 case chip::Controller::CommissioningStage::kConfigureTrustedTimeSource:
330 return mReadCommissioningInfo.requiresTrustedTimeSource && mParams.GetTrustedTimeSource().HasValue();
331 case chip::Controller::CommissioningStage::kConfigureDefaultNTP:
332 return mReadCommissioningInfo.requiresDefaultNTP && mParams.GetDefaultNTP().HasValue();
333 case chip::Controller::CommissioningStage::kConfigureDSTOffset:
334 return mNeedsDST && mParams.GetDSTOffsets().HasValue();
335 case chip::Controller::CommissioningStage::kError:
336 case chip::Controller::CommissioningStage::kSecurePairing:
Vijay Selvarajbe9389c2024-05-09 15:05:38 -0400337 // "not valid" because attestation verification always fails after entering revocation check step
338 case chip::Controller::CommissioningStage::kAttestationVerification:
C Freemanc3b18102022-04-04 16:17:09 -0400339 return false;
C Freemanac3535b2023-07-18 13:32:59 -0400340 default:
341 return true;
C Freemanc3b18102022-04-04 16:17:09 -0400342 }
C Freemanc3b18102022-04-04 16:17:09 -0400343 }
344 bool StatusUpdatesOk(chip::Controller::CommissioningStage failedStage)
345 {
346 // Because we're just simulating a failure here, we will have received a success callback even for the failed stage.
347 for (uint8_t i = 0; i < kNumCommissioningStages; ++i)
348 {
349 if (mReceivedStageFailure[i])
350 {
351 return false;
352 }
353 if (!ValidStage(static_cast<chip::Controller::CommissioningStage>(i)))
354 {
355 continue;
356 }
357 // Anything above our current stage we won't have received a callback for. We also expect that the "failed" stage will
358 // have a success callback because we're just faking the failure here and overwriting error.
359 if (i == chip::to_underlying(failedStage))
360 {
361 break;
362 }
363 }
364 return true;
365 }
C Freeman8ffe4222022-02-02 14:21:16 -0500366};
367TestCommissioner sTestCommissioner;
Jerry Johnsf68cd642022-01-28 16:39:08 -0800368
369extern "C" {
370struct OpCredsContext
371{
372 Platform::UniquePtr<Controller::Python::OperationalCredentialsAdapter> mAdapter;
373 void * mPyContext;
374};
375
Jerry Johnsc517ba22022-08-18 09:48:09 -0700376void * pychip_OpCreds_InitializeDelegate(void * pyContext, uint32_t fabricCredentialsIndex,
377 Controller::Python::StorageAdapter * storageAdapter)
Jerry Johnsf68cd642022-01-28 16:39:08 -0800378{
379 auto context = Platform::MakeUnique<OpCredsContext>();
380 context->mAdapter = Platform::MakeUnique<Controller::Python::OperationalCredentialsAdapter>(fabricCredentialsIndex);
381
Jerry Johnsc517ba22022-08-18 09:48:09 -0700382 if (context->mAdapter->Initialize(*storageAdapter) != CHIP_NO_ERROR)
Jerry Johnsf68cd642022-01-28 16:39:08 -0800383 {
384 return nullptr;
385 }
386
387 return context.release();
388}
389
C Freemanc3b18102022-04-04 16:17:09 -0400390void pychip_OnCommissioningSuccess(PeerId peerId)
391{
392 sTestCommissioner.OnCommissioningSuccess(peerId);
393}
394void pychip_OnCommissioningFailure(chip::PeerId peerId, CHIP_ERROR error, chip::Controller::CommissioningStage stageFailed,
395 chip::Optional<chip::Credentials::AttestationVerificationResult> additionalErrorInfo)
396{
397 sTestCommissioner.OnCommissioningFailure(peerId, error, stageFailed, additionalErrorInfo);
398}
399void pychip_OnCommissioningStatusUpdate(chip::PeerId peerId, chip::Controller::CommissioningStage stageCompleted, CHIP_ERROR err)
400{
401 return sTestCommissioner.OnCommissioningStatusUpdate(peerId, stageCompleted, err);
402}
403
Song GUOe75d35a2023-03-01 08:57:22 +0800404/**
405 * Allocates a controller that does not use auto-commisioning.
406 *
407 * TODO(#25214): Need clean up API
408 *
409 */
tianfeng.yangb4a62132024-04-17 21:53:13 +0800410PyChipError pychip_OpCreds_AllocateControllerForPythonCommissioningFLow(
411 chip::Controller::DeviceCommissioner ** outDevCtrl, chip::Controller::ScriptDevicePairingDelegate ** outPairingDelegate,
412 chip::python::pychip_P256Keypair * operationalKey, uint8_t * noc, uint32_t nocLen, uint8_t * icac, uint32_t icacLen,
413 uint8_t * rcac, uint32_t rcacLen, const uint8_t * ipk, uint32_t ipkLen, chip::VendorId adminVendorId,
414 bool enableServerInteractions)
Song GUOe75d35a2023-03-01 08:57:22 +0800415{
416 ReturnErrorCodeIf(nocLen > Controller::kMaxCHIPDERCertLength, ToPyChipError(CHIP_ERROR_NO_MEMORY));
417 ReturnErrorCodeIf(icacLen > Controller::kMaxCHIPDERCertLength, ToPyChipError(CHIP_ERROR_NO_MEMORY));
418 ReturnErrorCodeIf(rcacLen > Controller::kMaxCHIPDERCertLength, ToPyChipError(CHIP_ERROR_NO_MEMORY));
419
420 ChipLogDetail(Controller, "Creating New Device Controller");
421
tianfeng.yangb4a62132024-04-17 21:53:13 +0800422 auto pairingDelegate = std::make_unique<chip::Controller::ScriptDevicePairingDelegate>();
423 VerifyOrReturnError(pairingDelegate != nullptr, ToPyChipError(CHIP_ERROR_NO_MEMORY));
Song GUOe75d35a2023-03-01 08:57:22 +0800424 auto devCtrl = std::make_unique<chip::Controller::DeviceCommissioner>();
425 VerifyOrReturnError(devCtrl != nullptr, ToPyChipError(CHIP_ERROR_NO_MEMORY));
426
427 Controller::SetupParams initParams;
tianfeng.yangb4a62132024-04-17 21:53:13 +0800428 initParams.pairingDelegate = pairingDelegate.get();
Song GUOe75d35a2023-03-01 08:57:22 +0800429 initParams.operationalCredentialsDelegate = &sPlaceholderOperationalCredentialsIssuer;
430 initParams.operationalKeypair = operationalKey;
431 initParams.controllerRCAC = ByteSpan(rcac, rcacLen);
432 initParams.controllerICAC = ByteSpan(icac, icacLen);
433 initParams.controllerNOC = ByteSpan(noc, nocLen);
434 initParams.enableServerInteractions = enableServerInteractions;
435 initParams.controllerVendorId = adminVendorId;
436 initParams.permitMultiControllerFabrics = true;
437 initParams.hasExternallyOwnedOperationalKeypair = true;
438
439 CHIP_ERROR err = Controller::DeviceControllerFactory::GetInstance().SetupCommissioner(initParams, *devCtrl);
440 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
441
442 // Setup IPK in Group Data Provider for controller after Commissioner init which sets-up the fabric table entry
443 uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 };
444 chip::MutableByteSpan compressedFabricIdSpan(compressedFabricId);
445
446 err = devCtrl->GetCompressedFabricIdBytes(compressedFabricIdSpan);
447 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
448
449 ChipLogProgress(Support, "Setting up group data for Fabric Index %u with Compressed Fabric ID:",
450 static_cast<unsigned>(devCtrl->GetFabricIndex()));
451 ChipLogByteSpan(Support, compressedFabricIdSpan);
452
453 chip::ByteSpan fabricIpk =
454 (ipk == nullptr) ? chip::GroupTesting::DefaultIpkValue::GetDefaultIpk() : chip::ByteSpan(ipk, ipkLen);
455 err =
456 chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, devCtrl->GetFabricIndex(), fabricIpk, compressedFabricIdSpan);
457 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
458
tianfeng.yangb4a62132024-04-17 21:53:13 +0800459 *outDevCtrl = devCtrl.release();
460 *outPairingDelegate = pairingDelegate.release();
Song GUOe75d35a2023-03-01 08:57:22 +0800461
462 return ToPyChipError(CHIP_NO_ERROR);
463}
464
465// TODO(#25214): Need clean up API
Song GUOb9d32ec2022-10-24 14:40:11 +0800466PyChipError pychip_OpCreds_AllocateController(OpCredsContext * context, chip::Controller::DeviceCommissioner ** outDevCtrl,
tianfeng.yangb4a62132024-04-17 21:53:13 +0800467 chip::Controller::ScriptDevicePairingDelegate ** outPairingDelegate,
Song GUOb9d32ec2022-10-24 14:40:11 +0800468 FabricId fabricId, chip::NodeId nodeId, chip::VendorId adminVendorId,
469 const char * paaTrustStorePath, bool useTestCommissioner,
Song GUOe75d35a2023-03-01 08:57:22 +0800470 bool enableServerInteractions, CASEAuthTag * caseAuthTags, uint32_t caseAuthTagLen,
471 chip::python::pychip_P256Keypair * operationalKey)
Jerry Johnsf68cd642022-01-28 16:39:08 -0800472{
Song GUOe75d35a2023-03-01 08:57:22 +0800473 CHIP_ERROR err = CHIP_NO_ERROR;
474
Jerry Johnsf68cd642022-01-28 16:39:08 -0800475 ChipLogDetail(Controller, "Creating New Device Controller");
476
Song GUOb9d32ec2022-10-24 14:40:11 +0800477 VerifyOrReturnError(context != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800478
tianfeng.yangb4a62132024-04-17 21:53:13 +0800479 auto pairingDelegate = std::make_unique<chip::Controller::ScriptDevicePairingDelegate>();
480 VerifyOrReturnError(pairingDelegate != nullptr, ToPyChipError(CHIP_ERROR_NO_MEMORY));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800481 auto devCtrl = std::make_unique<chip::Controller::DeviceCommissioner>();
Song GUOb9d32ec2022-10-24 14:40:11 +0800482 VerifyOrReturnError(devCtrl != nullptr, ToPyChipError(CHIP_ERROR_NO_MEMORY));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800483
Stefan Agner51d67c42022-05-04 19:20:48 +0200484 if (paaTrustStorePath == nullptr)
485 {
486 paaTrustStorePath = "./credentials/development/paa-root-certs";
487 }
Jerry Johnsc517ba22022-08-18 09:48:09 -0700488
Stefan Agner51d67c42022-05-04 19:20:48 +0200489 ChipLogProgress(Support, "Using device attestation PAA trust store path %s.", paaTrustStorePath);
490
Jerry Johnsf68cd642022-01-28 16:39:08 -0800491 // Initialize device attestation verifier
Stefan Agner51d67c42022-05-04 19:20:48 +0200492 const chip::Credentials::AttestationTrustStore * testingRootStore = GetTestFileAttestationTrustStore(paaTrustStorePath);
Jerry Johnsf68cd642022-01-28 16:39:08 -0800493 SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore));
494
495 chip::Crypto::P256Keypair ephemeralKey;
Song GUOe75d35a2023-03-01 08:57:22 +0800496 chip::Crypto::P256Keypair * controllerKeyPair;
497
498 if (operationalKey == nullptr)
499 {
500 err = ephemeralKey.Initialize(chip::Crypto::ECPKeyTarget::ECDSA);
501 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
502 controllerKeyPair = &ephemeralKey;
503 }
504 else
505 {
506 controllerKeyPair = operationalKey;
507 }
Jerry Johnsf68cd642022-01-28 16:39:08 -0800508
509 chip::Platform::ScopedMemoryBuffer<uint8_t> noc;
Song GUOb9d32ec2022-10-24 14:40:11 +0800510 ReturnErrorCodeIf(!noc.Alloc(Controller::kMaxCHIPDERCertLength), ToPyChipError(CHIP_ERROR_NO_MEMORY));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800511 MutableByteSpan nocSpan(noc.Get(), Controller::kMaxCHIPDERCertLength);
512
513 chip::Platform::ScopedMemoryBuffer<uint8_t> icac;
Song GUOb9d32ec2022-10-24 14:40:11 +0800514 ReturnErrorCodeIf(!icac.Alloc(Controller::kMaxCHIPDERCertLength), ToPyChipError(CHIP_ERROR_NO_MEMORY));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800515 MutableByteSpan icacSpan(icac.Get(), Controller::kMaxCHIPDERCertLength);
516
517 chip::Platform::ScopedMemoryBuffer<uint8_t> rcac;
Song GUOb9d32ec2022-10-24 14:40:11 +0800518 ReturnErrorCodeIf(!rcac.Alloc(Controller::kMaxCHIPDERCertLength), ToPyChipError(CHIP_ERROR_NO_MEMORY));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800519 MutableByteSpan rcacSpan(rcac.Get(), Controller::kMaxCHIPDERCertLength);
520
Jerry Johns3f695872022-08-18 20:25:15 -0700521 CATValues catValues;
522
Tennessee Carmel-Veilleuxdfc1a702022-08-19 18:20:12 -0400523 if (caseAuthTagLen > kMaxSubjectCATAttributeCount)
Jerry Johns3f695872022-08-18 20:25:15 -0700524 {
Tennessee Carmel-Veilleuxdfc1a702022-08-19 18:20:12 -0400525 ChipLogError(Controller, "Too many of CASE Tags (%u) exceeds kMaxSubjectCATAttributeCount",
526 static_cast<unsigned>(caseAuthTagLen));
Song GUOb9d32ec2022-10-24 14:40:11 +0800527 return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT);
Jerry Johns3f695872022-08-18 20:25:15 -0700528 }
529
530 memcpy(catValues.values.data(), caseAuthTags, caseAuthTagLen * sizeof(CASEAuthTag));
531
Song GUOe75d35a2023-03-01 08:57:22 +0800532 err =
533 context->mAdapter->GenerateNOCChain(nodeId, fabricId, catValues, controllerKeyPair->Pubkey(), rcacSpan, icacSpan, nocSpan);
Song GUOb9d32ec2022-10-24 14:40:11 +0800534 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800535
536 Controller::SetupParams initParams;
tianfeng.yangb4a62132024-04-17 21:53:13 +0800537 initParams.pairingDelegate = pairingDelegate.get();
Song GUOe75d35a2023-03-01 08:57:22 +0800538 initParams.operationalCredentialsDelegate = context->mAdapter.get();
539 initParams.operationalKeypair = controllerKeyPair;
540 initParams.controllerRCAC = rcacSpan;
541 initParams.controllerICAC = icacSpan;
542 initParams.controllerNOC = nocSpan;
543 initParams.enableServerInteractions = enableServerInteractions;
544 initParams.controllerVendorId = adminVendorId;
545 initParams.permitMultiControllerFabrics = true;
546 initParams.hasExternallyOwnedOperationalKeypair = operationalKey != nullptr;
Jerry Johns75372d82022-03-01 06:32:40 -0800547
C Freeman8ffe4222022-02-02 14:21:16 -0500548 if (useTestCommissioner)
549 {
550 initParams.defaultCommissioner = &sTestCommissioner;
tianfeng.yangb4a62132024-04-17 21:53:13 +0800551 pairingDelegate->SetCommissioningSuccessCallback(pychip_OnCommissioningSuccess);
552 pairingDelegate->SetCommissioningFailureCallback(pychip_OnCommissioningFailure);
553 pairingDelegate->SetCommissioningStatusUpdateCallback(pychip_OnCommissioningStatusUpdate);
C Freeman8ffe4222022-02-02 14:21:16 -0500554 }
Jerry Johnsf68cd642022-01-28 16:39:08 -0800555
556 err = Controller::DeviceControllerFactory::GetInstance().SetupCommissioner(initParams, *devCtrl);
Song GUOb9d32ec2022-10-24 14:40:11 +0800557 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800558
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -0400559 // Setup IPK in Group Data Provider for controller after Commissioner init which sets-up the fabric table entry
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -0400560 uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 };
561 chip::MutableByteSpan compressedFabricIdSpan(compressedFabricId);
562
Tennessee Carmel-Veilleuxe5e09f52022-06-24 16:57:34 -0400563 err = devCtrl->GetCompressedFabricIdBytes(compressedFabricIdSpan);
Song GUOb9d32ec2022-10-24 14:40:11 +0800564 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -0400565
566 ChipLogProgress(Support, "Setting up group data for Fabric Index %u with Compressed Fabric ID:",
Tennessee Carmel-Veilleuxe5e09f52022-06-24 16:57:34 -0400567 static_cast<unsigned>(devCtrl->GetFabricIndex()));
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -0400568 ChipLogByteSpan(Support, compressedFabricIdSpan);
569
570 chip::ByteSpan defaultIpk = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
Tennessee Carmel-Veilleuxe5e09f52022-06-24 16:57:34 -0400571 err =
572 chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, devCtrl->GetFabricIndex(), defaultIpk, compressedFabricIdSpan);
Song GUOb9d32ec2022-10-24 14:40:11 +0800573 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
Tennessee Carmel-Veilleux1c03d9c2022-03-30 17:44:08 -0400574
Song GUOd8e7e432024-06-04 17:53:30 +0000575 sICDClientStorage.UpdateFabricList(devCtrl->GetFabricIndex());
576 pairingDelegate->SetFabricIndex(devCtrl->GetFabricIndex());
577
tianfeng.yangb4a62132024-04-17 21:53:13 +0800578 *outDevCtrl = devCtrl.release();
579 *outPairingDelegate = pairingDelegate.release();
Jerry Johnsf68cd642022-01-28 16:39:08 -0800580
Song GUOb9d32ec2022-10-24 14:40:11 +0800581 return ToPyChipError(CHIP_NO_ERROR);
Jerry Johnsf68cd642022-01-28 16:39:08 -0800582}
583
Terence Hampsonec2b5e32023-02-22 13:22:02 -0500584PyChipError pychip_OpCreds_InitGroupTestingData(chip::Controller::DeviceCommissioner * devCtrl)
585{
586 VerifyOrReturnError(devCtrl != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT));
587
588 uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 };
589 chip::MutableByteSpan compressedFabricIdSpan(compressedFabricId);
590
591 CHIP_ERROR err = devCtrl->GetCompressedFabricIdBytes(compressedFabricIdSpan);
592 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
593
594 err = chip::GroupTesting::InitData(&sGroupDataProvider, devCtrl->GetFabricIndex(), compressedFabricIdSpan);
595
596 return ToPyChipError(err);
597}
598
Song GUOb9d32ec2022-10-24 14:40:11 +0800599PyChipError pychip_OpCreds_SetMaximallyLargeCertsUsed(OpCredsContext * context, bool enabled)
Tennessee Carmel-Veilleuxdfc1a702022-08-19 18:20:12 -0400600{
Song GUOb9d32ec2022-10-24 14:40:11 +0800601 VerifyOrReturnError(context != nullptr && context->mAdapter != nullptr, ToPyChipError(CHIP_ERROR_INCORRECT_STATE));
Tennessee Carmel-Veilleuxdfc1a702022-08-19 18:20:12 -0400602
603 context->mAdapter->SetMaximallyLargeCertsUsed(enabled);
604
Song GUOb9d32ec2022-10-24 14:40:11 +0800605 return ToPyChipError(CHIP_NO_ERROR);
Tennessee Carmel-Veilleuxdfc1a702022-08-19 18:20:12 -0400606}
607
Jerry Johnsf68cd642022-01-28 16:39:08 -0800608void pychip_OpCreds_FreeDelegate(OpCredsContext * context)
609{
610 Platform::Delete(context);
611}
612
tianfeng.yangb4a62132024-04-17 21:53:13 +0800613PyChipError pychip_DeviceController_DeleteDeviceController(chip::Controller::DeviceCommissioner * devCtrl,
614 chip::Controller::ScriptDevicePairingDelegate * pairingDelegate)
Jerry Johnsf68cd642022-01-28 16:39:08 -0800615{
Andrei Litvin697b1552022-04-06 10:45:26 -1000616 if (devCtrl != nullptr)
Jerry Johnsf68cd642022-01-28 16:39:08 -0800617 {
618 devCtrl->Shutdown();
619 delete devCtrl;
620 }
621
tianfeng.yangb4a62132024-04-17 21:53:13 +0800622 if (pairingDelegate != nullptr)
623 {
624 delete pairingDelegate;
625 }
626
Song GUOb9d32ec2022-10-24 14:40:11 +0800627 return ToPyChipError(CHIP_NO_ERROR);
Jerry Johnsf68cd642022-01-28 16:39:08 -0800628}
C Freeman8ffe4222022-02-02 14:21:16 -0500629
Song GUOe75d35a2023-03-01 08:57:22 +0800630PyChipError pychip_DeviceController_SetIpk(chip::Controller::DeviceCommissioner * devCtrl, const uint8_t * ipk, size_t ipkLen)
631{
632 VerifyOrReturnError(ipk != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT));
633
634 uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 };
635 chip::MutableByteSpan compressedFabricIdSpan(compressedFabricId);
636
637 CHIP_ERROR err = devCtrl->GetCompressedFabricIdBytes(compressedFabricIdSpan);
638 VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err));
639
640 err = chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, devCtrl->GetFabricIndex(), ByteSpan(ipk, ipkLen),
641 compressedFabricIdSpan);
642
643 return ToPyChipError(err);
644}
645
C Freeman8ffe4222022-02-02 14:21:16 -0500646bool pychip_TestCommissionerUsed()
647{
C Freemanc3b18102022-04-04 16:17:09 -0400648 return sTestCommissioner.GetTestCommissionerUsed();
649}
650
651bool pychip_TestCommissioningCallbacks()
652{
653 return sTestCommissioner.CheckCallbacks();
654}
655
C Freemanac3535b2023-07-18 13:32:59 -0400656bool pychip_TestCommissioningStageSuccessful(uint8_t stage)
657{
658 return sTestCommissioner.CheckStageSuccessful(stage);
659}
660
C Freemanc3b18102022-04-04 16:17:09 -0400661bool pychip_TestPaseConnection(NodeId nodeId)
662{
663 return sTestCommissioner.CheckPaseConnection(nodeId);
664}
665
666void pychip_ResetCommissioningTests()
667{
668 sTestCommissioner.Reset();
669}
670
671// Returns True if this is a valid test, false otherwise
672bool pychip_SetTestCommissionerSimulateFailureOnStage(uint8_t failStage)
673{
674 return sTestCommissioner.SimulateFailAfter(static_cast<chip::Controller::CommissioningStage>(failStage));
675}
676bool pychip_SetTestCommissionerSimulateFailureOnReport(uint8_t failStage)
677{
678 return sTestCommissioner.SimulateFailOnReport(static_cast<chip::Controller::CommissioningStage>(failStage));
Jerry Johnsf68cd642022-01-28 16:39:08 -0800679}
C Freeman89d538c2023-01-26 12:29:48 -0500680bool pychip_SetTestCommissionerPrematureCompleteAfter(uint8_t stage)
681{
682 return sTestCommissioner.PrematureCompleteAfter(static_cast<chip::Controller::CommissioningStage>(stage));
683}
684
685PyChipError pychip_GetCompletionError()
686{
687 return ToPyChipError(sTestCommissioner.GetCompletionError());
688}
C Freeman8ffe4222022-02-02 14:21:16 -0500689
690} // extern "C"