Skip to content

Commit d1d4399

Browse files
authored
Complete TC tests for TLS Certificate Management & fix impl (#41046)
* Complete TC tests * TC test check-in; tests should be complete, impl needs to be fixed to pass tests * TLS TC Tests Completed & all passing against impl * Python lint fixes * Python lint fixes * Fix camera app compile errors * Apply review comments
1 parent ade93ac commit d1d4399

File tree

15 files changed

+1242
-86
lines changed

15 files changed

+1242
-86
lines changed

examples/all-clusters-app/all-clusters-common/include/tls-certificate-management-instance.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ class TlsCertificateManagementCommandDelegate : public TlsCertificateManagementD
3636
TlsCertificateManagementCommandDelegate(Tls::CertificateTable & certificateTable) : mCertificateTable(certificateTable) {}
3737
~TlsCertificateManagementCommandDelegate() = default;
3838

39-
Protocols::InteractionModel::ClusterStatusCode ProvisionRootCert(EndpointId matterEndpoint, FabricIndex fabric,
40-
const ProvisionRootCertificateType & provisionReq,
41-
Tls::TLSCAID & outCaid) override;
39+
Protocols::InteractionModel::Status ProvisionRootCert(EndpointId matterEndpoint, FabricIndex fabric,
40+
const ProvisionRootCertificateType & provisionReq,
41+
Tls::TLSCAID & outCaid) override;
4242

4343
CHIP_ERROR LoadedRootCerts(EndpointId matterEndpoint, FabricIndex fabric,
4444
LoadedRootCertificateCallback loadedCallback) const override;
@@ -56,9 +56,8 @@ class TlsCertificateManagementCommandDelegate : public TlsCertificateManagementD
5656
Protocols::InteractionModel::Status GenerateClientCsr(EndpointId matterEndpoint, FabricIndex fabric,
5757
const ClientCsrType & request,
5858
GeneratedCsrCallback loadedCallback) const override;
59-
Protocols::InteractionModel::ClusterStatusCode
60-
ProvisionClientCert(EndpointId matterEndpoint, FabricIndex fabric,
61-
const ProvisionClientCertificateType & provisionReq) override;
59+
Protocols::InteractionModel::Status ProvisionClientCert(EndpointId matterEndpoint, FabricIndex fabric,
60+
const ProvisionClientCertificateType & provisionReq) override;
6261

6362
CHIP_ERROR LoadedClientCerts(EndpointId matterEndpoint, FabricIndex fabric,
6463
LoadedClientCertificateCallback loadedCallback) const override;
@@ -73,7 +72,7 @@ class TlsCertificateManagementCommandDelegate : public TlsCertificateManagementD
7372
LoadedClientCertificateCallback loadedCallback) const override;
7473
Protocols::InteractionModel::Status RemoveClientCert(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCCDID id) override;
7574

76-
static inline TlsCertificateManagementCommandDelegate & getInstance() { return instance; }
75+
static inline TlsCertificateManagementCommandDelegate & GetInstance() { return instance; }
7776
};
7877

7978
} // namespace Clusters

examples/all-clusters-app/all-clusters-common/include/tls-client-management-instance.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ class TlsClientManagementCommandDelegate : public TlsClientManagementDelegate
6161
Protocols::InteractionModel::ClusterStatusCode RemoveProvisionedEndpointByID(EndpointId matterEndpoint, FabricIndex fabric,
6262
uint16_t endpointID) override;
6363

64+
CHIP_ERROR RootCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCAID id) override;
65+
CHIP_ERROR ClientCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCCDID id) override;
66+
6467
static inline TlsClientManagementCommandDelegate & GetInstance() { return instance; }
6568

6669
uint16_t GetEndpointId(Provisioned * provisioned);

examples/all-clusters-app/all-clusters-common/src/tls-certificate-management-instance.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <clusters/TlsCertificateManagement/Commands.h>
2323
#include <crypto/CHIPCryptoPAL.h>
2424
#include <tls-certificate-management-instance.h>
25+
#include <tls-client-management-instance.h>
2526

2627
using namespace chip;
2728
using namespace chip::app;
@@ -135,31 +136,31 @@ struct InlineEncodableClientCert : RefEncodableClientCert
135136
InlineEncodableClientCert() : RefEncodableClientCert(inlineCertificate) {}
136137
};
137138

138-
static constexpr uint8_t kMaxRootCerts = 254;
139-
static constexpr uint8_t kMaxClientCerts = 254;
139+
static constexpr uint8_t kMaxRootCerts = kMaxRootCertificatesPerFabric;
140+
static constexpr uint8_t kMaxClientCerts = kMaxClientCertificatesPerFabric;
140141

141142
CHIP_ERROR FingerprintMatch(const ByteSpan & fingerprint, const ByteSpan & cert, bool & outMatch)
142143
{
143-
std::array<uint8_t, chip::Crypto::kSHA1_Hash_Length> fingerprintPayload = { 0 };
144+
std::array<uint8_t, chip::Crypto::kSHA256_Hash_Length> fingerprintPayload = { 0 };
144145
MutableByteSpan calculatedFingerprint(fingerprintPayload);
145-
ReturnErrorOnFailure(Hash_SHA1(cert.data(), cert.size(), fingerprintPayload.data()));
146+
ReturnErrorOnFailure(Hash_SHA256(cert.data(), cert.size(), fingerprintPayload.data()));
146147
outMatch = fingerprint.data_equal(calculatedFingerprint);
147148
return CHIP_NO_ERROR;
148149
}
149150

150-
ClusterStatusCode TlsCertificateManagementCommandDelegate::ProvisionRootCert(EndpointId matterEndpoint, FabricIndex fabric,
151-
const ProvisionRootCertificateType & provisionReq,
152-
Tls::TLSCAID & outCaid)
151+
Status TlsCertificateManagementCommandDelegate::ProvisionRootCert(EndpointId matterEndpoint, FabricIndex fabric,
152+
const ProvisionRootCertificateType & provisionReq,
153+
Tls::TLSCAID & outCaid)
153154
{
154155
auto localId = provisionReq.caid.IsNull() ? Optional<Tls::TLSCAID>() : Optional<Tls::TLSCAID>(provisionReq.caid.Value());
155156
UniquePtr<InlineBufferedRootCert> certBuffer(New<InlineBufferedRootCert>());
156-
VerifyOrReturnError(certBuffer, ClusterStatusCode(CHIP_ERROR_NO_MEMORY));
157+
VerifyOrReturnError(certBuffer, Status::ResourceExhausted);
157158

158159
auto result = mCertificateTable.UpsertRootCertificateEntry(fabric, localId, certBuffer->buffer, provisionReq.certificate);
159160

160-
VerifyOrReturnValue(result == CHIP_NO_ERROR, ClusterStatusCode(Status::Failure));
161+
VerifyOrReturnValue(result == CHIP_NO_ERROR, Status::Failure);
161162
outCaid = localId.Value();
162-
return ClusterStatusCode(Status::Success);
163+
return Status::Success;
163164
}
164165

165166
CHIP_ERROR TlsCertificateManagementCommandDelegate::LoadedRootCerts(EndpointId matterEndpoint, FabricIndex fabric,
@@ -252,9 +253,9 @@ CHIP_ERROR TlsCertificateManagementCommandDelegate::LookupRootCert(EndpointId ma
252253
const ByteSpan & certificate,
253254
LoadedRootCertificateCallback loadedCallback) const
254255
{
255-
std::array<uint8_t, chip::Crypto::kSHA1_Hash_Length> fingerprintPayload = { 0 };
256+
std::array<uint8_t, Crypto::kSHA256_Hash_Length> fingerprintPayload = { 0 };
256257
MutableByteSpan calculatedFingerprint(fingerprintPayload);
257-
ReturnErrorOnFailure(Hash_SHA1(certificate.data(), certificate.size(), fingerprintPayload.data()));
258+
ReturnErrorOnFailure(Hash_SHA256(certificate.data(), certificate.size(), fingerprintPayload.data()));
258259
return LookupRootCertByFingerprint(matterEndpoint, fabric, calculatedFingerprint, loadedCallback);
259260
}
260261

@@ -302,19 +303,25 @@ Status TlsCertificateManagementCommandDelegate::GenerateClientCsr(EndpointId mat
302303
return loadedCallback(csrResponse);
303304
}
304305

305-
ClusterStatusCode TlsCertificateManagementCommandDelegate::ProvisionClientCert(EndpointId matterEndpoint, FabricIndex fabric,
306-
const ProvisionClientCertificateType & provisionReq)
306+
Status TlsCertificateManagementCommandDelegate::ProvisionClientCert(EndpointId matterEndpoint, FabricIndex fabric,
307+
const ProvisionClientCertificateType & provisionReq)
307308
{
308309
UniquePtr<InlineBufferedClientCert> certBuffer(New<InlineBufferedClientCert>());
309-
VerifyOrReturnError(certBuffer, ClusterStatusCode(CHIP_ERROR_NO_MEMORY));
310+
VerifyOrReturnError(certBuffer, Status::ResourceExhausted);
311+
310312
TLSClientCertificateDetailStruct::DecodableType details;
311313
details.ccdid = provisionReq.ccdid;
312314
details.clientCertificate.SetValue(provisionReq.clientCertificate);
313315
details.intermediateCertificates.SetValue(provisionReq.intermediateCertificates);
314316
details.SetFabricIndex(fabric);
317+
315318
auto result = mCertificateTable.UpdateClientCertificateEntry(fabric, provisionReq.ccdid, certBuffer->buffer, details);
316-
ReturnValueOnFailure(result, ClusterStatusCode(Status::Failure));
317-
return ClusterStatusCode(Status::Success);
319+
if (result == CHIP_ERROR_INVALID_ARGUMENT)
320+
{
321+
return Status::DynamicConstraintError;
322+
}
323+
ReturnValueOnFailure(result, Status::Failure);
324+
return Status::Success;
318325
}
319326

320327
CHIP_ERROR TlsCertificateManagementCommandDelegate::LoadedClientCerts(EndpointId matterEndpoint, FabricIndex fabric,
@@ -413,13 +420,13 @@ CHIP_ERROR TlsCertificateManagementCommandDelegate::LookupClientCert(EndpointId
413420
const ByteSpan & certificate,
414421
LoadedClientCertificateCallback loadedCallback) const
415422
{
416-
std::array<uint8_t, chip::Crypto::kSHA1_Hash_Length> fingerprintPayload = { 0 };
423+
std::array<uint8_t, Crypto::kSHA256_Hash_Length> fingerprintPayload = { 0 };
417424
MutableByteSpan calculatedFingerprint(fingerprintPayload);
418-
ReturnErrorOnFailure(Hash_SHA1(certificate.data(), certificate.size(), fingerprintPayload.data()));
425+
ReturnErrorOnFailure(Hash_SHA256(certificate.data(), certificate.size(), fingerprintPayload.data()));
419426
return LookupClientCertByFingerprint(matterEndpoint, fabric, calculatedFingerprint, loadedCallback);
420427
}
421428

422-
Status TlsCertificateManagementCommandDelegate::RemoveClientCert(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCAID id)
429+
Status TlsCertificateManagementCommandDelegate::RemoveClientCert(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCCDID id)
423430
{
424431
VerifyOrReturnValue(matterEndpoint == EndpointId(1), Status::ConstraintError);
425432

@@ -436,9 +443,9 @@ Status TlsCertificateManagementCommandDelegate::RemoveClientCert(EndpointId matt
436443

437444
static CertificateTableImpl gCertificateTableInstance;
438445
TlsCertificateManagementCommandDelegate TlsCertificateManagementCommandDelegate::instance(gCertificateTableInstance);
439-
static TlsCertificateManagementServer gTlsCertificateManagementClusterServerInstance =
440-
TlsCertificateManagementServer(EndpointId(1), TlsCertificateManagementCommandDelegate::getInstance(), gCertificateTableInstance,
441-
kMaxRootCerts, kMaxClientCerts);
446+
static TlsCertificateManagementServer gTlsCertificateManagementClusterServerInstance = TlsCertificateManagementServer(
447+
EndpointId(1), TlsCertificateManagementCommandDelegate::GetInstance(), TlsClientManagementCommandDelegate::GetInstance(),
448+
gCertificateTableInstance, kMaxRootCerts, kMaxClientCerts);
442449

443450
void emberAfTlsCertificateManagementClusterInitCallback(EndpointId matterEndpoint)
444451
{

examples/all-clusters-app/all-clusters-common/src/tls-client-management-instance.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,33 @@ ClusterStatusCode TlsClientManagementCommandDelegate::RemoveProvisionedEndpointB
201201
return ClusterStatusCode(Status::Success);
202202
}
203203

204+
CHIP_ERROR TlsClientManagementCommandDelegate::RootCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCAID id)
205+
{
206+
auto i = mProvisioned.begin();
207+
for (; i != mProvisioned.end(); i++)
208+
{
209+
if (i->payload.caid == id)
210+
{
211+
return CHIP_ERROR_BAD_REQUEST;
212+
}
213+
}
214+
return CHIP_NO_ERROR;
215+
}
216+
217+
CHIP_ERROR TlsClientManagementCommandDelegate::ClientCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric,
218+
Tls::TLSCCDID id)
219+
{
220+
auto i = mProvisioned.begin();
221+
for (; i != mProvisioned.end(); i++)
222+
{
223+
if (i->payload.ccdid == id)
224+
{
225+
return CHIP_ERROR_BAD_REQUEST;
226+
}
227+
}
228+
return CHIP_NO_ERROR;
229+
}
230+
204231
static CertificateTableImpl gCertificateTableInstance;
205232
TlsClientManagementCommandDelegate TlsClientManagementCommandDelegate::instance(gCertificateTableInstance);
206233
static TlsClientManagementServer gTlsClientManagementClusterServerInstance = TlsClientManagementServer(

examples/camera-app/camera-common/src/camera-app.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ CameraApp::CameraApp(chip::EndpointId aClustersEndpoint, CameraDeviceInterface *
5252
&Clusters::TlsClientManagementCommandDelegate::GetInstance());
5353

5454
Clusters::PushAvStreamTransport::SetTlsCertificateManagementDelegate(
55-
mEndpoint, &Clusters::TlsCertificateManagementCommandDelegate::getInstance());
55+
mEndpoint, &Clusters::TlsCertificateManagementCommandDelegate::GetInstance());
5656
// Fetch all initialization parameters for CameraAVStreamMgmt Server
5757
BitFlags<CameraAvStreamManagement::Feature> avsmFeatures;
5858
BitFlags<CameraAvStreamManagement::OptionalAttribute> avsmOptionalAttrs;

src/app/clusters/push-av-stream-transport-server/tests/TestPushAVStreamTransportCluster.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,29 +391,41 @@ class TestTlsClientManagementDelegate : public TlsClientManagementDelegate
391391

392392
public:
393393
CHIP_ERROR GetProvisionedEndpointByIndex(EndpointId matterEndpoint, FabricIndex fabric, size_t index,
394-
EndpointStructType & endpoint) const
394+
EndpointStructType & endpoint) const override
395395
{
396396
return CHIP_NO_ERROR;
397397
}
398398

399399
Protocols::InteractionModel::ClusterStatusCode
400400
ProvisionEndpoint(EndpointId matterEndpoint, FabricIndex fabric,
401-
const TlsClientManagement::Commands::ProvisionEndpoint::DecodableType & provisionReq, uint16_t & endpointID)
401+
const TlsClientManagement::Commands::ProvisionEndpoint::DecodableType & provisionReq,
402+
uint16_t & endpointID) override
402403
{
403404
return ClusterStatusCode(Status::Success);
404405
}
405406

406407
Protocols::InteractionModel::Status FindProvisionedEndpointByID(EndpointId matterEndpoint, FabricIndex fabric,
407-
uint16_t endpointID, EndpointStructType & endpoint) const
408+
uint16_t endpointID,
409+
EndpointStructType & endpoint) const override
408410
{
409411
return Status::Success;
410412
}
411413

412414
Protocols::InteractionModel::ClusterStatusCode RemoveProvisionedEndpointByID(EndpointId matterEndpoint, FabricIndex fabric,
413-
uint16_t endpointID)
415+
uint16_t endpointID) override
414416
{
415417
return ClusterStatusCode(Status::Success);
416418
}
419+
420+
CHIP_ERROR RootCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCAID id) override
421+
{
422+
return CHIP_NO_ERROR;
423+
}
424+
425+
CHIP_ERROR ClientCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCCDID id) override
426+
{
427+
return CHIP_NO_ERROR;
428+
}
417429
};
418430

419431
class TestPushAVStreamTransportServerLogic : public ::testing::Test

src/app/clusters/tls-certificate-management-server/CertificateTable.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,38 @@ class CertificateTable
191191
}
192192
};
193193

194+
/** @brief
195+
* Defines methods for implementing application-specific logic for checking if a certificate
196+
* has no blocking dependencies and can be removed.
197+
*/
198+
class CertificateDependencyChecker
199+
{
200+
public:
201+
CertificateDependencyChecker() = default;
202+
203+
virtual ~CertificateDependencyChecker() = default;
204+
205+
/**
206+
* @brief Checks whether the root certificate with the given (matterEndpoint, fabric, id) has no dependencies
207+
*
208+
* @param[in] matterEndpoint The matter endpoint to query against
209+
* @param[in] fabric The fabric the certificate is associated with
210+
* @param[in] id The id of the root certificate to remove.
211+
* @return CHIP_NO_ERROR if the certificate can be removed.
212+
*/
213+
virtual CHIP_ERROR RootCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCAID id) = 0;
214+
215+
/**
216+
* @brief Checks whether the client certificate with the given (matterEndpoint, fabric, id) has no dependencies
217+
*
218+
* @param[in] matterEndpoint The matter endpoint to query against
219+
* @param[in] fabric The fabric the certificate is associated with
220+
* @param[in] id The id of the client certificate to remove.
221+
* @return CHIP_NO_ERROR if the certificate can be removed.
222+
*/
223+
virtual CHIP_ERROR ClientCertCanBeRemoved(EndpointId matterEndpoint, FabricIndex fabric, Tls::TLSCCDID id) = 0;
224+
};
225+
194226
} // namespace Tls
195227
} // namespace Clusters
196228

src/app/clusters/tls-certificate-management-server/CertificateTableImpl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,15 @@ CHIP_ERROR CertificateTableImpl::UpdateClientCertificateEntry(FabricIndex fabric
672672
ClientCertWithKey certWithKey;
673673
CertificateId localId(id);
674674
ReturnErrorOnFailure(mClientCertificates.GetTableEntry(fabric_index, localId, certWithKey, buffer));
675+
Crypto::P256PublicKey certPubKey;
676+
ReturnErrorOnFailure(Crypto::ExtractPubkeyFromX509Cert(entry.clientCertificate.Value().Value(), certPubKey));
677+
Crypto::P256Keypair keyPair;
678+
ReturnErrorOnFailure(keyPair.Deserialize(certWithKey.key));
679+
auto & storedPubKey = keyPair.Pubkey();
680+
if (!ByteSpan(storedPubKey, storedPubKey.Length()).data_equal(ByteSpan(certPubKey, certPubKey.Length())))
681+
{
682+
return CHIP_ERROR_INVALID_ARGUMENT;
683+
}
675684
certWithKey.detail = entry;
676685
certWithKey.detail.ccdid = id;
677686

0 commit comments

Comments
 (0)