-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Python] Add python commissioning flow #85
base: master
Are you sure you want to change the base?
Changes from all commits
7336446
4f5b153
f1964ff
6f2ff6a
3bb6133
e8e8f38
4f7e943
ebba2b0
4911d6e
d5b50e7
0e73f29
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
#include "ChipDeviceController-ScriptDevicePairingDelegate.h" | ||
#include "ChipDeviceController-StorageDelegate.h" | ||
|
||
#include "controller/python/chip/crypto/p256keypair.h" | ||
#include "controller/python/chip/interaction_model/Delegate.h" | ||
|
||
#include <controller/CHIPDeviceController.h> | ||
|
@@ -36,6 +37,7 @@ | |
#include <lib/support/TestGroupData.h> | ||
#include <lib/support/logging/CHIPLogging.h> | ||
|
||
#include <controller/python/chip/commissioning/PlaceholderOperationalCredentialsIssuer.h> | ||
#include <controller/python/chip/native/PyChipError.h> | ||
#include <credentials/GroupDataProviderImpl.h> | ||
#include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h> | ||
|
@@ -57,6 +59,8 @@ const chip::Credentials::AttestationTrustStore * GetTestFileAttestationTrustStor | |
|
||
return &attestationTrustStore; | ||
} | ||
|
||
chip::Python::PlaceholderOperationalCredentialsIssuer sPlaceholderOperationalCredentialsIssuer; | ||
} // namespace | ||
|
||
namespace chip { | ||
|
@@ -369,11 +373,74 @@ void pychip_OnCommissioningStatusUpdate(chip::PeerId peerId, chip::Controller::C | |
return sTestCommissioner.OnCommissioningStatusUpdate(peerId, stageCompleted, err); | ||
} | ||
|
||
/** | ||
* Allocates a controller that does not use auto-commisioning. | ||
* | ||
* TODO(#25214): Need clean up API | ||
* | ||
*/ | ||
PyChipError pychip_OpCreds_AllocateControllerForPythonCommissioningFLow(chip::Controller::DeviceCommissioner ** outDevCtrl, | ||
chip::python::pychip_P256Keypair * operationalKey, | ||
uint8_t * noc, uint32_t nocLen, uint8_t * icac, | ||
uint32_t icacLen, uint8_t * rcac, uint32_t rcacLen, | ||
const uint8_t * ipk, uint32_t ipkLen, | ||
chip::VendorId adminVendorId, bool enableServerInteractions) | ||
{ | ||
ReturnErrorCodeIf(nocLen > Controller::kMaxCHIPDERCertLength, ToPyChipError(CHIP_ERROR_NO_MEMORY)); | ||
ReturnErrorCodeIf(icacLen > Controller::kMaxCHIPDERCertLength, ToPyChipError(CHIP_ERROR_NO_MEMORY)); | ||
ReturnErrorCodeIf(rcacLen > Controller::kMaxCHIPDERCertLength, ToPyChipError(CHIP_ERROR_NO_MEMORY)); | ||
|
||
ChipLogDetail(Controller, "Creating New Device Controller"); | ||
|
||
auto devCtrl = std::make_unique<chip::Controller::DeviceCommissioner>(); | ||
VerifyOrReturnError(devCtrl != nullptr, ToPyChipError(CHIP_ERROR_NO_MEMORY)); | ||
|
||
Controller::SetupParams initParams; | ||
initParams.pairingDelegate = &sPairingDelegate; | ||
initParams.operationalCredentialsDelegate = &sPlaceholderOperationalCredentialsIssuer; | ||
initParams.operationalKeypair = operationalKey; | ||
initParams.controllerRCAC = ByteSpan(rcac, rcacLen); | ||
initParams.controllerICAC = ByteSpan(icac, icacLen); | ||
initParams.controllerNOC = ByteSpan(noc, nocLen); | ||
initParams.enableServerInteractions = enableServerInteractions; | ||
initParams.controllerVendorId = adminVendorId; | ||
initParams.permitMultiControllerFabrics = true; | ||
initParams.hasExternallyOwnedOperationalKeypair = true; | ||
|
||
CHIP_ERROR err = Controller::DeviceControllerFactory::GetInstance().SetupCommissioner(initParams, *devCtrl); | ||
VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); | ||
|
||
// Setup IPK in Group Data Provider for controller after Commissioner init which sets-up the fabric table entry | ||
uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 }; | ||
chip::MutableByteSpan compressedFabricIdSpan(compressedFabricId); | ||
|
||
err = devCtrl->GetCompressedFabricIdBytes(compressedFabricIdSpan); | ||
VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); | ||
|
||
ChipLogProgress(Support, "Setting up group data for Fabric Index %u with Compressed Fabric ID:", | ||
static_cast<unsigned>(devCtrl->GetFabricIndex())); | ||
ChipLogByteSpan(Support, compressedFabricIdSpan); | ||
|
||
chip::ByteSpan fabricIpk = | ||
(ipk == nullptr) ? chip::GroupTesting::DefaultIpkValue::GetDefaultIpk() : chip::ByteSpan(ipk, ipkLen); | ||
err = | ||
chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, devCtrl->GetFabricIndex(), fabricIpk, compressedFabricIdSpan); | ||
VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); | ||
|
||
*outDevCtrl = devCtrl.release(); | ||
|
||
return ToPyChipError(CHIP_NO_ERROR); | ||
} | ||
|
||
// TODO(#25214): Need clean up API | ||
PyChipError pychip_OpCreds_AllocateController(OpCredsContext * context, chip::Controller::DeviceCommissioner ** outDevCtrl, | ||
FabricId fabricId, chip::NodeId nodeId, chip::VendorId adminVendorId, | ||
const char * paaTrustStorePath, bool useTestCommissioner, | ||
bool enableServerInteractions, CASEAuthTag * caseAuthTags, uint32_t caseAuthTagLen) | ||
bool enableServerInteractions, CASEAuthTag * caseAuthTags, uint32_t caseAuthTagLen, | ||
chip::python::pychip_P256Keypair * operationalKey) | ||
{ | ||
CHIP_ERROR err = CHIP_NO_ERROR; | ||
|
||
ChipLogDetail(Controller, "Creating New Device Controller"); | ||
|
||
VerifyOrReturnError(context != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT)); | ||
|
@@ -393,8 +460,18 @@ PyChipError pychip_OpCreds_AllocateController(OpCredsContext * context, chip::Co | |
SetDeviceAttestationVerifier(GetDefaultDACVerifier(testingRootStore)); | ||
|
||
chip::Crypto::P256Keypair ephemeralKey; | ||
CHIP_ERROR err = ephemeralKey.Initialize(chip::Crypto::ECPKeyTarget::ECDSA); | ||
VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); | ||
chip::Crypto::P256Keypair * controllerKeyPair; | ||
|
||
if (operationalKey == nullptr) | ||
{ | ||
err = ephemeralKey.Initialize(chip::Crypto::ECPKeyTarget::ECDSA); | ||
VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); | ||
controllerKeyPair = &ephemeralKey; | ||
Comment on lines
+467
to
+469
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The "ephemeralKey" here will actually go out of scope. We cannot have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By using |
||
} | ||
else | ||
{ | ||
controllerKeyPair = operationalKey; | ||
} | ||
|
||
chip::Platform::ScopedMemoryBuffer<uint8_t> noc; | ||
ReturnErrorCodeIf(!noc.Alloc(Controller::kMaxCHIPDERCertLength), ToPyChipError(CHIP_ERROR_NO_MEMORY)); | ||
|
@@ -419,19 +496,21 @@ PyChipError pychip_OpCreds_AllocateController(OpCredsContext * context, chip::Co | |
|
||
memcpy(catValues.values.data(), caseAuthTags, caseAuthTagLen * sizeof(CASEAuthTag)); | ||
|
||
err = context->mAdapter->GenerateNOCChain(nodeId, fabricId, catValues, ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan); | ||
err = | ||
context->mAdapter->GenerateNOCChain(nodeId, fabricId, catValues, controllerKeyPair->Pubkey(), rcacSpan, icacSpan, nocSpan); | ||
VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); | ||
|
||
Controller::SetupParams initParams; | ||
initParams.pairingDelegate = &sPairingDelegate; | ||
initParams.operationalCredentialsDelegate = context->mAdapter.get(); | ||
initParams.operationalKeypair = &ephemeralKey; | ||
initParams.controllerRCAC = rcacSpan; | ||
initParams.controllerICAC = icacSpan; | ||
initParams.controllerNOC = nocSpan; | ||
initParams.enableServerInteractions = enableServerInteractions; | ||
initParams.controllerVendorId = adminVendorId; | ||
initParams.permitMultiControllerFabrics = true; | ||
initParams.pairingDelegate = &sPairingDelegate; | ||
initParams.operationalCredentialsDelegate = context->mAdapter.get(); | ||
initParams.operationalKeypair = controllerKeyPair; | ||
initParams.controllerRCAC = rcacSpan; | ||
initParams.controllerICAC = icacSpan; | ||
initParams.controllerNOC = nocSpan; | ||
initParams.enableServerInteractions = enableServerInteractions; | ||
initParams.controllerVendorId = adminVendorId; | ||
initParams.permitMultiControllerFabrics = true; | ||
initParams.hasExternallyOwnedOperationalKeypair = operationalKey != nullptr; | ||
|
||
if (useTestCommissioner) | ||
{ | ||
|
@@ -505,6 +584,22 @@ PyChipError pychip_DeviceController_DeleteDeviceController(chip::Controller::Dev | |
return ToPyChipError(CHIP_NO_ERROR); | ||
} | ||
|
||
PyChipError pychip_DeviceController_SetIpk(chip::Controller::DeviceCommissioner * devCtrl, const uint8_t * ipk, size_t ipkLen) | ||
{ | ||
VerifyOrReturnError(ipk != nullptr, ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT)); | ||
|
||
uint8_t compressedFabricId[sizeof(uint64_t)] = { 0 }; | ||
chip::MutableByteSpan compressedFabricIdSpan(compressedFabricId); | ||
|
||
CHIP_ERROR err = devCtrl->GetCompressedFabricIdBytes(compressedFabricIdSpan); | ||
VerifyOrReturnError(err == CHIP_NO_ERROR, ToPyChipError(err)); | ||
|
||
err = chip::Credentials::SetSingleIpkEpochKey(&sGroupDataProvider, devCtrl->GetFabricIndex(), ByteSpan(ipk, ipkLen), | ||
compressedFabricIdSpan); | ||
|
||
return ToPyChipError(err); | ||
} | ||
|
||
bool pychip_TestCommissionerUsed() | ||
{ | ||
return sTestCommissioner.GetTestCommissionerUsed(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Over time, we have to move to not having this passed in, and rather use an OperationalKeystore instance. We need a TODO for this, since in the future, the
operationalKey
would not be passed-in.It would have been more future-proof to avoid directly passing the key