Skip to content

Commit aa3d16f

Browse files
Allow generation of no-ICAC cert chains in Python tests (project-chip#38445)
* Allow generation of no-ICAC cert chains in Python tests - Allow generation of no-ICAC cert chains (valid) in Python tests - Cache steps list to avoid possible recursive calls in upcoming PR in matter_testing_support.py Testing done: - All existing tests still pass * Restyled by clang-format * Fix lint * Backport project-chip#38467 --------- Co-authored-by: Restyled.io <[email protected]>
1 parent ff5490a commit aa3d16f

File tree

8 files changed

+135
-74
lines changed

8 files changed

+135
-74
lines changed

src/controller/ExampleOperationalCredentialsIssuer.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDele
182182
{
183183
ChipLogProgress(Controller, "Couldn't get %s from storage: %s", kOperationalCredentialsIssuerKeypairStorage, ErrorStr(err));
184184
// Storage doesn't have an existing keypair. Let's create one and add it to the storage.
185-
ReturnErrorOnFailure(mIssuer.Initialize(Crypto::ECPKeyTarget::ECDSA));
186-
ReturnErrorOnFailure(mIssuer.Serialize(serializedKey));
185+
ReturnErrorOnFailure(mRootIssuer.Initialize(Crypto::ECPKeyTarget::ECDSA));
186+
ReturnErrorOnFailure(mRootIssuer.Serialize(serializedKey));
187187

188188
PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsIssuerKeypairStorage, key,
189189
ReturnErrorOnFailure(
@@ -192,7 +192,7 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDele
192192
else
193193
{
194194
// Use the keypair from the storage
195-
ReturnErrorOnFailure(mIssuer.Deserialize(serializedKey));
195+
ReturnErrorOnFailure(mRootIssuer.Deserialize(serializedKey));
196196
}
197197

198198
{
@@ -251,16 +251,16 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation(
251251
rcac.reduce_size(rcacBufLen);
252252
ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(rcac, rcac_dn));
253253
ReturnErrorOnFailure(rcac_dn.GetCertChipId(rcacId));
254-
VerifyOrReturnError(rcacId == mIssuerId, CHIP_ERROR_INTERNAL);
254+
VerifyOrReturnError(rcacId == mRootIssuerId, CHIP_ERROR_INTERNAL);
255255
}
256256
// If root certificate not found in the storage, generate new root certificate.
257257
else
258258
{
259-
ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(mIssuerId));
259+
ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(mRootIssuerId));
260260

261261
ChipLogProgress(Controller, "Generating RCAC");
262262
ReturnErrorOnFailure(IssueX509Cert(mNow, mValidity, rcac_dn, rcac_dn, CertType::kRcac, mUseMaximallySizedCerts,
263-
mIssuer.Pubkey(), mIssuer, rcac));
263+
mRootIssuer.Pubkey(), mRootIssuer, rcac));
264264
VerifyOrReturnError(CanCastTo<uint16_t>(rcac.size()), CHIP_ERROR_INTERNAL);
265265

266266
// Re-extract DN based on final generated cert
@@ -296,7 +296,7 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation(
296296

297297
ChipLogProgress(Controller, "Generating ICAC");
298298
ReturnErrorOnFailure(IssueX509Cert(mNow, mValidity, rcac_dn, icac_dn, CertType::kIcac, mUseMaximallySizedCerts,
299-
mIntermediateIssuer.Pubkey(), mIssuer, icac));
299+
mIntermediateIssuer.Pubkey(), mRootIssuer, icac));
300300
VerifyOrReturnError(CanCastTo<uint16_t>(icac.size()), CHIP_ERROR_INTERNAL);
301301

302302
// Re-extract DN based on final generated cert
@@ -313,8 +313,22 @@ CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation(
313313
ReturnErrorOnFailure(noc_dn.AddCATs(cats));
314314

315315
ChipLogProgress(Controller, "Generating NOC");
316-
return IssueX509Cert(mNow, mValidity, icac_dn, noc_dn, CertType::kNoc, mUseMaximallySizedCerts, pubkey, mIntermediateIssuer,
317-
noc);
316+
if (mAlwaysOmitIcac)
317+
{
318+
icac.reduce_size(0);
319+
err = IssueX509Cert(mNow, mValidity, rcac_dn, noc_dn, CertType::kNoc, mUseMaximallySizedCerts, pubkey, mRootIssuer, noc);
320+
}
321+
else
322+
{
323+
err = IssueX509Cert(mNow, mValidity, icac_dn, noc_dn, CertType::kNoc, mUseMaximallySizedCerts, pubkey, mIntermediateIssuer,
324+
noc);
325+
}
326+
327+
if (err != CHIP_NO_ERROR)
328+
{
329+
ChipLogError(Controller, "Failed to Generate NOC: %" CHIP_ERROR_FORMAT, err.Format());
330+
}
331+
return err;
318332
}
319333

320334
CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce,

src/controller/ExampleOperationalCredentialsIssuer.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent
6767

6868
void SetMaximallyLargeCertsUsed(bool areMaximallyLargeCertsUsed) { mUseMaximallySizedCerts = areMaximallyLargeCertsUsed; }
6969

70+
// When enabled, chains will be Root -> NOC, for the given fabric ID, and not include an ICAC.
71+
void SetAlwaysOmitIcac(bool enabled) { mAlwaysOmitIcac = enabled; }
72+
7073
void SetFabricIdForNextNOCRequest(FabricId fabricId) override { mNextFabricId = fabricId; }
7174

7275
void SetCATValuesForNextNOCRequest(CATValues cats) { mNextCATs = cats; }
@@ -84,7 +87,7 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent
8487
[[deprecated("This class stores the encryption key in clear storage. Don't use it for production code.")]] CHIP_ERROR
8588
Initialize(PersistentStorageDelegate & storage);
8689

87-
void SetIssuerId(uint32_t id) { mIssuerId = id; }
90+
void SetIssuerId(uint32_t id) { mRootIssuerId = id; }
8891

8992
void SetCurrentEpoch(uint32_t epoch) { mNow = epoch; }
9093

@@ -109,10 +112,10 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent
109112
MutableByteSpan & noc);
110113

111114
private:
112-
Crypto::P256Keypair mIssuer;
115+
Crypto::P256Keypair mRootIssuer;
113116
Crypto::P256Keypair mIntermediateIssuer;
114117
bool mInitialized = false;
115-
uint32_t mIssuerId = 1;
118+
uint32_t mRootIssuerId = 1;
116119
uint32_t mIntermediateIssuerId = 2;
117120
uint32_t mNow = 0;
118121

@@ -122,6 +125,7 @@ class DLL_EXPORT ExampleOperationalCredentialsIssuer : public OperationalCredent
122125
NodeId mNextAvailableNodeId = 1;
123126
PersistentStorageDelegate * mStorage = nullptr;
124127
bool mUseMaximallySizedCerts = false;
128+
bool mAlwaysOmitIcac = false;
125129

126130
NodeId mNextRequestedNodeId = 1;
127131
FabricId mNextFabricId = 1;

src/controller/python/ChipDeviceController-IssueNocChain.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,17 @@ void pychip_DeviceController_IssueNOCChainCallback(void * context, CHIP_ERROR st
8080
chipRcacSpan = MutableByteSpan(chipRcac.Get(), Credentials::kMaxCHIPCertLength);
8181

8282
SuccessOrExit(err = ConvertX509CertToChipCert(noc, chipNocSpan));
83-
SuccessOrExit(err = ConvertX509CertToChipCert(icac, chipIcacSpan));
8483
SuccessOrExit(err = ConvertX509CertToChipCert(rcac, chipRcacSpan));
8584

85+
if (!icac.empty())
86+
{
87+
SuccessOrExit(err = ConvertX509CertToChipCert(icac, chipIcacSpan));
88+
}
89+
else
90+
{
91+
chipIcacSpan.reduce_size(0);
92+
}
93+
8694
exit:
8795
if (err == CHIP_NO_ERROR)
8896
{

src/controller/python/OpCredsBinding.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ class OperationalCredentialsAdapter : public OperationalCredentialsDelegate
9292
return mExampleOpCredsIssuer.GenerateNOCChainAfterValidation(nodeId, fabricId, cats, pubKey, rcac, icac, noc);
9393
}
9494

95+
void SetAlwaysOmitIcac(bool enabled) { mExampleOpCredsIssuer.SetAlwaysOmitIcac(enabled); }
96+
9597
void SetMaximallyLargeCertsUsed(bool enabled) { mExampleOpCredsIssuer.SetMaximallyLargeCertsUsed(enabled); }
9698

9799
void SetCertificateValidityPeriod(uint32_t validity) { mExampleOpCredsIssuer.SetCertificateValidityPeriod(validity); }
@@ -652,6 +654,15 @@ PyChipError pychip_OpCreds_SetMaximallyLargeCertsUsed(OpCredsContext * context,
652654
return ToPyChipError(CHIP_NO_ERROR);
653655
}
654656

657+
PyChipError pychip_OpCreds_SetAlwaysOmitIcac(OpCredsContext * context, bool enabled)
658+
{
659+
VerifyOrReturnError(context != nullptr && context->mAdapter != nullptr, ToPyChipError(CHIP_ERROR_INCORRECT_STATE));
660+
661+
context->mAdapter->SetAlwaysOmitIcac(enabled);
662+
663+
return ToPyChipError(CHIP_NO_ERROR);
664+
}
665+
655666
PyChipError pychip_OpCreds_SetCertificateValidityPeriod(OpCredsContext * context, uint32_t validity)
656667
{
657668
VerifyOrReturnError(context != nullptr && context->mAdapter != nullptr, ToPyChipError(CHIP_ERROR_INCORRECT_STATE));

src/controller/python/chip/CertificateAuthority.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ def __init__(self, chipStack: ChipStack.ChipStack, caIndex: int, persistentStora
8080
self._Handle().pychip_OpCreds_SetMaximallyLargeCertsUsed.restype = PyChipError
8181
self._Handle().pychip_OpCreds_SetMaximallyLargeCertsUsed.argtypes = [ctypes.c_void_p, ctypes.c_bool]
8282

83+
self._Handle().pychip_OpCreds_SetAlwaysOmitIcac.restype = PyChipError
84+
self._Handle().pychip_OpCreds_SetAlwaysOmitIcac.argtypes = [ctypes.c_void_p, ctypes.c_bool]
85+
8386
self._Handle().pychip_OpCreds_SetCertificateValidityPeriod.restype = PyChipError
8487
self._Handle().pychip_OpCreds_SetCertificateValidityPeriod.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
8588

@@ -88,6 +91,7 @@ def __init__(self, chipStack: ChipStack.ChipStack, caIndex: int, persistentStora
8891

8992
self._persistentStorage = persistentStorage
9093
self._maximizeCertChains = False
94+
self._alwaysOmitIcac = False
9195
self._certificateValidityPeriodSec = CERTIFICATE_VALIDITY_PERIOD_SEC
9296

9397
self._closure = self._chipStack.Call(
@@ -196,6 +200,10 @@ def adminList(self) -> list[FabricAdmin.FabricAdmin]:
196200
def maximizeCertChains(self) -> bool:
197201
return self._maximizeCertChains
198202

203+
@property
204+
def alwaysOmitIcac(self) -> bool:
205+
return self._alwaysOmitIcac
206+
199207
@property
200208
def certificateValidityPeriodSec(self) -> int:
201209
return self._certificateValidityPeriodSec
@@ -208,6 +216,14 @@ def maximizeCertChains(self, enabled: bool):
208216

209217
self._maximizeCertChains = enabled
210218

219+
@alwaysOmitIcac.setter
220+
def alwaysOmitIcac(self, enabled: bool):
221+
self._chipStack.Call(
222+
lambda: self._Handle().pychip_OpCreds_SetAlwaysOmitIcac(ctypes.c_void_p(self._closure), ctypes.c_bool(enabled))
223+
).raise_on_error()
224+
225+
self._alwaysOmitIcac = enabled
226+
211227
@certificateValidityPeriodSec.setter
212228
def certificateValidityPeriodSec(self, validity: int):
213229
if validity < 0:

0 commit comments

Comments
 (0)