| /* |
| * |
| * Copyright (c) 2025 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /****************************************************************************' |
| * @file |
| * @brief Implementation for the TlsCertificateManagement Server Cluster |
| ***************************************************************************/ |
| |
| #include "tls-certificate-management-server.h" |
| |
| #include <app/AttributeAccessInterfaceRegistry.h> |
| #include <app/CommandHandlerInterfaceRegistry.h> |
| #include <app/ConcreteAttributePath.h> |
| #include <app/SafeAttributePersistenceProvider.h> |
| #include <app/server/Server.h> |
| #include <clusters/TlsCertificateManagement/Attributes.h> |
| #include <clusters/TlsCertificateManagement/Commands.h> |
| #include <clusters/TlsCertificateManagement/Metadata.h> |
| #include <clusters/TlsCertificateManagement/Structs.h> |
| #include <protocols/interaction_model/StatusCode.h> |
| |
| using namespace chip; |
| using namespace chip::app; |
| using namespace chip::app::Clusters; |
| using namespace chip::app::Clusters::Tls; |
| using namespace chip::app::Clusters::TlsCertificateManagement; |
| using namespace chip::app::Clusters::TlsCertificateManagement::Commands; |
| using namespace chip::app::Clusters::TlsCertificateManagement::Structs; |
| using namespace chip::app::Clusters::TlsCertificateManagement::Attributes; |
| using chip::Protocols::InteractionModel::Status; |
| |
| static constexpr uint16_t kSpecMaxCertBytes = 3000; |
| static constexpr uint16_t kSpecMaxFingerprintBytes = 64; |
| static constexpr uint16_t kMaxIntermediateCertificates = 10; |
| static constexpr uint16_t kNonceBytes = 32; |
| static constexpr uint16_t kMaxSignatureBytes = 128; |
| |
| TlsCertificateManagementServer::TlsCertificateManagementServer(EndpointId endpointId, TlsCertificateManagementDelegate & delegate, |
| Tls::CertificateDependencyChecker & dependencyChecker, |
| CertificateTable & certificateTable, uint8_t maxRootCertificates, |
| uint8_t maxClientCertificates) : |
| AttributeAccessInterface(MakeOptional(endpointId), TlsCertificateManagement::Id), |
| CommandHandlerInterface(MakeOptional(endpointId), TlsCertificateManagement::Id), mDelegate(delegate), |
| mDependencyChecker(dependencyChecker), mCertificateTable(certificateTable), mMaxRootCertificates(maxRootCertificates), |
| mMaxClientCertificates(maxClientCertificates) |
| { |
| VerifyOrDieWithMsg(mMaxRootCertificates >= 5, NotSpecified, "Spec requires MaxRootCertificates be >= 5"); |
| VerifyOrDieWithMsg(mMaxClientCertificates >= 5, NotSpecified, "Spec requires MaxClientCertificates be >= 5"); |
| mDelegate.SetTlsCertificateManagementServer(this); |
| } |
| |
| TlsCertificateManagementServer::~TlsCertificateManagementServer() |
| { |
| // null out the ref to us on the delegate |
| mDelegate.SetTlsCertificateManagementServer(nullptr); |
| |
| // unregister |
| CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); |
| AttributeAccessInterfaceRegistry::Instance().Unregister(this); |
| } |
| |
| CHIP_ERROR TlsCertificateManagementServer::Init() |
| { |
| mCertificateTable.Init(Server::GetInstance().GetPersistentStorage()); |
| |
| VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INTERNAL); |
| ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this)); |
| |
| return Server::GetInstance().GetFabricTable().AddFabricDelegate(this); |
| } |
| |
| CHIP_ERROR TlsCertificateManagementServer::Finish() |
| { |
| mCertificateTable.Finish(); |
| |
| Server::GetInstance().GetFabricTable().RemoveFabricDelegate(this); |
| CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this); |
| AttributeAccessInterfaceRegistry::Instance().Unregister(this); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| // AttributeAccessInterface |
| CHIP_ERROR TlsCertificateManagementServer::Read(const DataModel::ReadAttributeRequest & aRequest, AttributeValueEncoder & aEncoder) |
| { |
| const auto & aPath = aRequest.path; |
| bool largePayload = aRequest.readFlags.Has(DataModel::ReadFlags::kAllowsLargePayload); |
| VerifyOrDie(aPath.mClusterId == TlsCertificateManagement::Id); |
| |
| switch (aPath.mAttributeId) |
| { |
| case MaxRootCertificates::Id: |
| return aEncoder.Encode(mMaxRootCertificates); |
| case ProvisionedRootCertificates::Id: { |
| auto matterEndpoint = aPath.mEndpointId; |
| auto fabric = aEncoder.AccessingFabricIndex(); |
| return aEncoder.EncodeList([this, matterEndpoint, fabric, largePayload](const auto & encoder) -> CHIP_ERROR { |
| return EncodeProvisionedRootCertificates(matterEndpoint, fabric, largePayload, encoder); |
| }); |
| } |
| case MaxClientCertificates::Id: |
| return aEncoder.Encode(mMaxClientCertificates); |
| case ProvisionedClientCertificates::Id: { |
| auto matterEndpoint = aPath.mEndpointId; |
| auto fabric = aEncoder.AccessingFabricIndex(); |
| return aEncoder.EncodeList([this, matterEndpoint, fabric, largePayload](const auto & encoder) -> CHIP_ERROR { |
| return EncodeProvisionedClientCertificates(matterEndpoint, fabric, largePayload, encoder); |
| }); |
| } |
| case ClusterRevision::Id: |
| return aEncoder.Encode(kRevision); |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR |
| TlsCertificateManagementServer::EncodeProvisionedRootCertificates(EndpointId matterEndpoint, FabricIndex fabric, bool largePayload, |
| const AttributeValueEncoder::ListEncodeHelper & encoder) |
| { |
| return mDelegate.LoadedRootCerts(matterEndpoint, fabric, [&](auto & cert) -> CHIP_ERROR { |
| if (largePayload) |
| { |
| return encoder.Encode(cert); |
| } |
| |
| // Drop the certificate payload if transport doesn't support large payload |
| TLSCertStruct::Type idOnlyCert; |
| idOnlyCert.fabricIndex = cert.fabricIndex; |
| idOnlyCert.caid = cert.caid; |
| return encoder.Encode(idOnlyCert); |
| }); |
| } |
| |
| CHIP_ERROR |
| TlsCertificateManagementServer::EncodeProvisionedClientCertificates(EndpointId matterEndpoint, FabricIndex fabric, |
| bool largePayload, |
| const AttributeValueEncoder::ListEncodeHelper & encoder) |
| { |
| return mDelegate.LoadedClientCerts(matterEndpoint, fabric, [&](auto & cert) -> CHIP_ERROR { |
| if (largePayload) |
| { |
| return encoder.Encode(cert); |
| } |
| |
| // Drop the certificate payload if transport doesn't support large payload |
| TLSClientCertificateDetailStruct::Type idOnlyCert; |
| idOnlyCert.fabricIndex = cert.fabricIndex; |
| idOnlyCert.ccdid = cert.ccdid; |
| return encoder.Encode(idOnlyCert); |
| }); |
| } |
| |
| void TlsCertificateManagementServer::InvokeCommand(HandlerContext & ctx) |
| { |
| switch (ctx.mRequestPath.mCommandId) |
| { |
| case ProvisionRootCertificate::Id: |
| CommandHandlerInterface::HandleCommand<ProvisionRootCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleProvisionRootCertificate(innerCtx, req); }); |
| break; |
| case FindRootCertificate::Id: |
| CommandHandlerInterface::HandleCommand<FindRootCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleFindRootCertificate(innerCtx, req); }); |
| break; |
| case LookupRootCertificate::Id: |
| CommandHandlerInterface::HandleCommand<LookupRootCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleLookupRootCertificate(innerCtx, req); }); |
| break; |
| case RemoveRootCertificate::Id: |
| CommandHandlerInterface::HandleCommand<RemoveRootCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleRemoveRootCertificate(innerCtx, req); }); |
| break; |
| case ClientCSR::Id: |
| CommandHandlerInterface::HandleCommand<ClientCSR::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleGenerateClientCsr(innerCtx, req); }); |
| break; |
| case ProvisionClientCertificate::Id: |
| CommandHandlerInterface::HandleCommand<ProvisionClientCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleProvisionClientCertificate(innerCtx, req); }); |
| break; |
| case FindClientCertificate::Id: |
| CommandHandlerInterface::HandleCommand<FindClientCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleFindClientCertificate(innerCtx, req); }); |
| break; |
| case LookupClientCertificate::Id: |
| CommandHandlerInterface::HandleCommand<LookupClientCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleLookupClientCertificate(innerCtx, req); }); |
| break; |
| case RemoveClientCertificate::Id: |
| CommandHandlerInterface::HandleCommand<RemoveClientCertificate::DecodableType>( |
| ctx, [this](HandlerContext & innerCtx, const auto & req) { HandleRemoveClientCertificate(innerCtx, req); }); |
| break; |
| } |
| } |
| |
| void TlsCertificateManagementServer::HandleProvisionRootCertificate(HandlerContext & ctx, |
| const ProvisionRootCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: ProvisionRootCertificate"); |
| |
| VerifyOrReturn(req.certificate.size() <= kSpecMaxCertBytes, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| auto fabric = ctx.mCommandHandler.GetAccessingFabricIndex(); |
| DataModel::Nullable<Tls::TLSCAID> foundId; |
| auto lookupResult = |
| mDelegate.LookupRootCert(ctx.mRequestPath.mEndpointId, fabric, req.certificate, [&](auto & certificate) -> CHIP_ERROR { |
| foundId = certificate.caid; |
| return CHIP_NO_ERROR; |
| }); |
| if (lookupResult != CHIP_ERROR_NOT_FOUND) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::AlreadyExists); |
| return; |
| } |
| |
| if (req.caid.IsNull()) |
| { |
| uint8_t numRootCerts; |
| ReturnOnFailure(mCertificateTable.GetRootCertificateCount(fabric, numRootCerts), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure)); |
| VerifyOrReturn(numRootCerts < mMaxRootCertificates, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ResourceExhausted)); |
| } |
| else |
| { |
| auto caid = req.caid.Value(); |
| VerifyOrReturn(caid <= kMaxRootCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| ReturnOnFailure(mCertificateTable.HasRootCertificateEntry(fabric, caid), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound)); |
| } |
| |
| ReturnOnFailure(Crypto::IsCertificateValidAtCurrentTime(req.certificate), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError)); |
| |
| ProvisionRootCertificateResponse::Type response; |
| auto status = mDelegate.ProvisionRootCert(ctx.mRequestPath.mEndpointId, fabric, req, response.caid); |
| if (status != Status::Success) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); |
| return; |
| } |
| |
| VerifyOrDieWithMsg(response.caid <= kMaxRootCertId, NotSpecified, "Spec requires CAID to be < kMaxRootCertId"); |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| } |
| |
| void TlsCertificateManagementServer::HandleFindRootCertificate(HandlerContext & ctx, const FindRootCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: FindRootCertificate"); |
| CHIP_ERROR result; |
| if (req.caid.IsNull()) |
| { |
| result = mDelegate.RootCertsForFabric(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), |
| [&](auto & certs) -> CHIP_ERROR { |
| if (certs.size() == 0) |
| { |
| return CHIP_ERROR_NOT_FOUND; |
| } |
| FindRootCertificateResponse::Type response; |
| response.certificateDetails = certs; |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| return CHIP_NO_ERROR; |
| }); |
| } |
| else |
| { |
| VerifyOrReturn(req.caid.Value() <= kMaxRootCertId, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| result = mDelegate.FindRootCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), |
| req.caid.Value(), [&](auto & certificate) -> CHIP_ERROR { |
| FindRootCertificateResponse::Type response; |
| DataModel::List<const TLSCertStruct::Type> details(&certificate, 1); |
| response.certificateDetails = details; |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| return CHIP_NO_ERROR; |
| }); |
| } |
| if (result == CHIP_ERROR_NOT_FOUND) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); |
| } |
| else if (result != CHIP_NO_ERROR) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); |
| } |
| } |
| |
| void TlsCertificateManagementServer::HandleLookupRootCertificate(HandlerContext & ctx, |
| const LookupRootCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: LookupRootCertificate"); |
| VerifyOrReturn(req.fingerprint.size() <= kSpecMaxFingerprintBytes, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| auto result = mDelegate.LookupRootCertByFingerprint(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), |
| req.fingerprint, [&](auto & certificate) -> CHIP_ERROR { |
| LookupRootCertificateResponse::Type response; |
| response.caid = certificate.caid; |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| return CHIP_NO_ERROR; |
| }); |
| if (result == CHIP_ERROR_NOT_FOUND) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); |
| } |
| else if (result != CHIP_NO_ERROR) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); |
| } |
| } |
| |
| void TlsCertificateManagementServer::HandleRemoveRootCertificate(HandlerContext & ctx, |
| const RemoveRootCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: RemoveRootCertificate"); |
| |
| VerifyOrReturn(req.caid <= kMaxRootCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| ReturnOnFailure(mDependencyChecker.RootCertCanBeRemoved(ctx.mRequestPath.mEndpointId, |
| ctx.mCommandHandler.GetAccessingFabricIndex(), req.caid), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); |
| |
| auto result = mDelegate.RemoveRootCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), req.caid); |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, result); |
| } |
| |
| void TlsCertificateManagementServer::HandleGenerateClientCsr(HandlerContext & ctx, const ClientCSR::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: ClientCSR"); |
| |
| VerifyOrReturn(req.nonce.size() == kNonceBytes, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| auto fabric = ctx.mCommandHandler.GetAccessingFabricIndex(); |
| uint8_t numClientCerts; |
| VerifyOrReturn(mCertificateTable.GetClientCertificateCount(fabric, numClientCerts) == CHIP_NO_ERROR, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure)); |
| VerifyOrReturn(numClientCerts < mMaxClientCertificates, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ResourceExhausted)); |
| |
| auto status = mDelegate.GenerateClientCsr(ctx.mRequestPath.mEndpointId, fabric, req, [&](auto & response) -> Status { |
| VerifyOrDieWithMsg(response.ccdid <= kMaxClientCertId, NotSpecified, "Spec requires CCDID to be <= kMaxClientCertId"); |
| VerifyOrDieWithMsg(response.csr.size() <= 3000, NotSpecified, "Spec requires csr.size() to be <= 3000"); |
| VerifyOrDieWithMsg(response.nonceSignature.size() <= kMaxSignatureBytes, NotSpecified, |
| "Spec requires nonceSignature.size() to be < kMaxSignatureBytes"); |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| return Status::Success; |
| }); |
| |
| if (status != Status::Success) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); |
| } |
| } |
| |
| void TlsCertificateManagementServer::HandleProvisionClientCertificate(HandlerContext & ctx, |
| const ProvisionClientCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: ProvisionClientCertificate"); |
| |
| VerifyOrReturn(req.ccdid <= kMaxClientCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| VerifyOrReturn(req.clientCertificate.size() <= kSpecMaxCertBytes, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| ReturnOnFailure(Crypto::IsCertificateValidAtCurrentTime(req.clientCertificate), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError)); |
| size_t intermediateSize; |
| ReturnOnFailure(req.intermediateCertificates.ComputeSize(&intermediateSize), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand)); |
| VerifyOrReturn(intermediateSize <= kMaxIntermediateCertificates, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| auto srcIter = req.intermediateCertificates.begin(); |
| while (srcIter.Next()) |
| { |
| auto & cert = srcIter.GetValue(); |
| VerifyOrReturn(cert.size() <= kSpecMaxCertBytes, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| ReturnOnFailure(Crypto::IsCertificateValidAtCurrentTime(cert), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::DynamicConstraintError)); |
| } |
| ReturnOnFailure(srcIter.GetStatus(), ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidAction)); |
| |
| auto fabric = ctx.mCommandHandler.GetAccessingFabricIndex(); |
| DataModel::Nullable<Tls::TLSCCDID> foundId; |
| auto lookupResult = mDelegate.LookupClientCert(ctx.mRequestPath.mEndpointId, fabric, req.clientCertificate, |
| [&](auto & certificate) -> CHIP_ERROR { |
| foundId = certificate.ccdid; |
| return CHIP_NO_ERROR; |
| }); |
| if (lookupResult != CHIP_ERROR_NOT_FOUND) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::AlreadyExists); |
| return; |
| } |
| |
| ReturnOnFailure(mCertificateTable.HasClientCertificateEntry(fabric, req.ccdid), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound)); |
| |
| auto status = mDelegate.ProvisionClientCert(ctx.mRequestPath.mEndpointId, fabric, req); |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); |
| } |
| |
| void TlsCertificateManagementServer::HandleFindClientCertificate(HandlerContext & ctx, |
| const FindClientCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: FindClientCertificate"); |
| CHIP_ERROR result; |
| if (req.ccdid.IsNull()) |
| { |
| result = mDelegate.ClientCertsForFabric(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), |
| [&](auto & certs) -> CHIP_ERROR { |
| if (certs.size() == 0) |
| { |
| return CHIP_ERROR_NOT_FOUND; |
| } |
| FindClientCertificateResponse::Type response; |
| response.certificateDetails = certs; |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| return CHIP_NO_ERROR; |
| }); |
| } |
| else |
| { |
| VerifyOrReturn(req.ccdid.Value() <= kMaxRootCertId, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| result = |
| mDelegate.FindClientCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), req.ccdid.Value(), |
| [&](auto & certificate) -> CHIP_ERROR { |
| FindClientCertificateResponse::Type response; |
| DataModel::List<const TLSClientCertificateDetailStruct::Type> details(&certificate, 1); |
| response.certificateDetails = details; |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| return CHIP_NO_ERROR; |
| }); |
| } |
| if (result == CHIP_ERROR_NOT_FOUND) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); |
| } |
| else if (result != CHIP_NO_ERROR) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); |
| } |
| } |
| |
| void TlsCertificateManagementServer::HandleLookupClientCertificate(HandlerContext & ctx, |
| const LookupClientCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: LookupClientCertificate"); |
| |
| VerifyOrReturn(req.fingerprint.size() <= kSpecMaxFingerprintBytes, |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| auto result = |
| mDelegate.LookupClientCertByFingerprint(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), |
| req.fingerprint, [&](auto & certificate) -> CHIP_ERROR { |
| LookupClientCertificateResponse::Type response; |
| response.ccdid = certificate.ccdid; |
| ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); |
| return CHIP_NO_ERROR; |
| }); |
| if (result == CHIP_ERROR_NOT_FOUND) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); |
| } |
| else if (result != CHIP_NO_ERROR) |
| { |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); |
| } |
| } |
| |
| void TlsCertificateManagementServer::HandleRemoveClientCertificate(HandlerContext & ctx, |
| const RemoveClientCertificate::DecodableType & req) |
| { |
| ChipLogDetail(Zcl, "TlsCertificateManagement: RemoveClientCertificate"); |
| |
| VerifyOrReturn(req.ccdid <= kMaxClientCertId, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError)); |
| |
| ReturnOnFailure(mDependencyChecker.ClientCertCanBeRemoved(ctx.mRequestPath.mEndpointId, |
| ctx.mCommandHandler.GetAccessingFabricIndex(), req.ccdid), |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState)); |
| |
| auto result = |
| mDelegate.RemoveClientCert(ctx.mRequestPath.mEndpointId, ctx.mCommandHandler.GetAccessingFabricIndex(), req.ccdid); |
| ctx.mCommandHandler.AddStatus(ctx.mRequestPath, result); |
| } |
| |
| void TlsCertificateManagementServer::OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) |
| { |
| ReturnAndLogOnFailure(mCertificateTable.RemoveFabric(fabricIndex), Zcl, "Failed to remove TLS certificate data for fabric 0x%x", |
| fabricIndex); |
| } |
| |
| /** @brief TlsCertificateManagement Cluster Server Init |
| * |
| * Server Init |
| * |
| */ |
| void MatterTlsCertificateManagementPluginServerInitCallback() {} |