LCOV - code coverage report
Current view: top level - credentials - PersistentStorageOpCertStore.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 197 222 88.7 %
Date: 2024-02-15 08:20:41 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /*
       2             :  *    Copyright (c) 2022 Project CHIP Authors
       3             :  *    All rights reserved.
       4             :  *
       5             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6             :  *    you may not use this file except in compliance with the License.
       7             :  *    You may obtain a copy of the License at
       8             :  *
       9             :  *        http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  *    Unless required by applicable law or agreed to in writing, software
      12             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  *    See the License for the specific language governing permissions and
      15             :  *    limitations under the License.
      16             :  */
      17             : 
      18             : #include <credentials/CHIPCert.h>
      19             : #include <lib/core/CHIPError.h>
      20             : #include <lib/core/CHIPPersistentStorageDelegate.h>
      21             : #include <lib/core/DataModelTypes.h>
      22             : #include <lib/core/TLV.h>
      23             : #include <lib/support/CHIPMem.h>
      24             : #include <lib/support/CodeUtils.h>
      25             : #include <lib/support/DefaultStorageKeyAllocator.h>
      26             : #include <lib/support/SafeInt.h>
      27             : #include <lib/support/ScopedBuffer.h>
      28             : 
      29             : #include "PersistentStorageOpCertStore.h"
      30             : 
      31             : namespace chip {
      32             : namespace Credentials {
      33             : 
      34             : namespace {
      35             : 
      36             : using CertChainElement = OperationalCertificateStore::CertChainElement;
      37             : 
      38        4120 : StorageKeyName GetStorageKeyForCert(FabricIndex fabricIndex, CertChainElement element)
      39             : {
      40        4120 :     switch (element)
      41             :     {
      42        1380 :     case CertChainElement::kNoc:
      43        1380 :         return DefaultStorageKeyAllocator::FabricNOC(fabricIndex);
      44             :         break;
      45        1354 :     case CertChainElement::kIcac:
      46        1354 :         return DefaultStorageKeyAllocator::FabricICAC(fabricIndex);
      47             :         break;
      48        1386 :     case CertChainElement::kRcac:
      49        1386 :         return DefaultStorageKeyAllocator::FabricRCAC(fabricIndex);
      50             :         break;
      51           0 :     default:
      52           0 :         break;
      53             :     }
      54             : 
      55           0 :     return StorageKeyName::Uninitialized();
      56             : }
      57             : 
      58        2030 : bool StorageHasCertificate(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element)
      59             : {
      60        2030 :     StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
      61             : 
      62        2030 :     if (!storageKey)
      63             :     {
      64           0 :         return false;
      65             :     }
      66             : 
      67             :     // TODO(#16958): need to actually read the cert to know if it's there due to platforms not
      68             :     //               properly enforcing CHIP_ERROR_BUFFER_TOO_SMALL behavior needed by
      69             :     //               PersistentStorageDelegate.
      70             :     uint8_t placeHolderCertBuffer[kMaxCHIPCertLength];
      71             : 
      72        2030 :     uint16_t keySize = sizeof(placeHolderCertBuffer);
      73        2030 :     CHIP_ERROR err   = storage->SyncGetKeyValue(storageKey.KeyName(), &placeHolderCertBuffer[0], keySize);
      74             : 
      75        2030 :     return (err == CHIP_NO_ERROR);
      76        2030 : }
      77             : 
      78         139 : CHIP_ERROR LoadCertFromStorage(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element,
      79             :                                MutableByteSpan & outCert)
      80             : {
      81         139 :     StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
      82         139 :     if (!storageKey)
      83             :     {
      84           0 :         return CHIP_ERROR_INTERNAL;
      85             :     }
      86             : 
      87         139 :     uint16_t keySize = static_cast<uint16_t>(outCert.size());
      88         139 :     CHIP_ERROR err   = storage->SyncGetKeyValue(storageKey.KeyName(), outCert.data(), keySize);
      89             : 
      90             :     // Not finding an ICAC means we don't have one, so adjust to meet the API contract, where
      91             :     // outCert.empty() will be true;
      92         139 :     if ((element == CertChainElement::kIcac) && (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND))
      93             :     {
      94           2 :         outCert.reduce_size(0);
      95           2 :         return CHIP_ERROR_NOT_FOUND;
      96             :     }
      97             : 
      98         137 :     if (err == CHIP_NO_ERROR)
      99             :     {
     100         133 :         outCert.reduce_size(keySize);
     101             :     }
     102           4 :     else if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
     103             :     {
     104             :         // Convert persisted storage error to CHIP_ERROR_NOT_FOUND so that
     105             :         // `PersistentStorageOpCertStore::GetCertificate` doesn't need to convert.
     106           4 :         err = CHIP_ERROR_NOT_FOUND;
     107             :     }
     108             : 
     109         137 :     return err;
     110         139 : }
     111             : 
     112        1903 : CHIP_ERROR SaveCertToStorage(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element,
     113             :                              const ByteSpan & cert)
     114             : {
     115        1903 :     StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
     116        1903 :     if (!storageKey)
     117             :     {
     118           0 :         return CHIP_ERROR_INTERNAL;
     119             :     }
     120             : 
     121             :     // If provided an empty ICAC, we delete the ICAC key previously used. If not there, it's OK
     122        1903 :     if ((element == CertChainElement::kIcac) && (cert.empty()))
     123             :     {
     124           9 :         CHIP_ERROR err = storage->SyncDeleteKeyValue(storageKey.KeyName());
     125           9 :         if ((err == CHIP_NO_ERROR) || (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND))
     126             :         {
     127           9 :             return CHIP_NO_ERROR;
     128             :         }
     129           0 :         return err;
     130             :     }
     131             : 
     132        1894 :     return storage->SyncSetKeyValue(storageKey.KeyName(), cert.data(), static_cast<uint16_t>(cert.size()));
     133        1903 : }
     134             : 
     135          48 : CHIP_ERROR DeleteCertFromStorage(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element)
     136             : {
     137          48 :     StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
     138          48 :     if (!storageKey)
     139             :     {
     140           0 :         return CHIP_ERROR_INTERNAL;
     141             :     }
     142          48 :     return storage->SyncDeleteKeyValue(storageKey.KeyName());
     143          48 : }
     144             : 
     145             : } // namespace
     146             : 
     147        1314 : bool PersistentStorageOpCertStore::HasPendingRootCert() const
     148             : {
     149        1314 :     if (mStorage == nullptr)
     150             :     {
     151           0 :         return false;
     152             :     }
     153             : 
     154        1314 :     return (mPendingRcac.Get() != nullptr) && mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled);
     155             : }
     156             : 
     157         678 : bool PersistentStorageOpCertStore::HasPendingNocChain() const
     158             : {
     159         678 :     if (mStorage == nullptr)
     160             :     {
     161           0 :         return false;
     162             :     }
     163             : 
     164         678 :     return (mPendingNoc.Get() != nullptr) && mStateFlags.HasAny(StateFlags::kAddNewOpCertsCalled, StateFlags::kUpdateOpCertsCalled);
     165             : }
     166             : 
     167         648 : bool PersistentStorageOpCertStore::HasCertificateForFabric(FabricIndex fabricIndex, CertChainElement element) const
     168             : {
     169         648 :     if ((mStorage == nullptr) || !IsValidFabricIndex(fabricIndex))
     170             :     {
     171           0 :         return false;
     172             :     }
     173             : 
     174             :     // FabricIndex matches pending, we MAY have some pending data
     175         648 :     if (fabricIndex == mPendingFabricIndex)
     176             :     {
     177         641 :         switch (element)
     178             :         {
     179         628 :         case CertChainElement::kRcac:
     180         628 :             if (mPendingRcac.Get() != nullptr)
     181             :             {
     182         628 :                 return true;
     183             :             }
     184           0 :             break;
     185           2 :         case CertChainElement::kIcac:
     186           2 :             if (mPendingIcac.Get() != nullptr)
     187             :             {
     188           0 :                 return true;
     189             :             }
     190             :             // If we have a pending NOC and no pending ICAC, don't delegate to storage, return not found here
     191             :             // since in the pending state, there truly is nothing.
     192           2 :             if (mPendingNoc.Get() != nullptr)
     193             :             {
     194           1 :                 return false;
     195             :             }
     196           1 :             break;
     197          11 :         case CertChainElement::kNoc:
     198          11 :             if (mPendingNoc.Get() != nullptr)
     199             :             {
     200          10 :                 return true;
     201             :             }
     202           1 :             break;
     203           0 :         default:
     204           0 :             return false;
     205             :         }
     206             :     }
     207             : 
     208           9 :     return StorageHasCertificate(mStorage, fabricIndex, element);
     209             : }
     210             : 
     211         653 : CHIP_ERROR PersistentStorageOpCertStore::AddNewTrustedRootCertForFabric(FabricIndex fabricIndex, const ByteSpan & rcac)
     212             : {
     213         653 :     ReturnErrorCodeIf(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
     214         652 :     ReturnErrorCodeIf(!IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     215         651 :     ReturnErrorCodeIf(rcac.empty() || (rcac.size() > Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
     216             : 
     217         651 :     ReturnErrorCodeIf(mStateFlags.HasAny(StateFlags::kUpdateOpCertsCalled, StateFlags::kAddNewTrustedRootCalled,
     218             :                                          StateFlags::kAddNewOpCertsCalled),
     219             :                       CHIP_ERROR_INCORRECT_STATE);
     220         649 :     ReturnErrorCodeIf(StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac), CHIP_ERROR_INCORRECT_STATE);
     221             : 
     222         648 :     Platform::ScopedMemoryBufferWithSize<uint8_t> rcacBuf;
     223         648 :     ReturnErrorCodeIf(!rcacBuf.Alloc(rcac.size()), CHIP_ERROR_NO_MEMORY);
     224         648 :     memcpy(rcacBuf.Get(), rcac.data(), rcac.size());
     225             : 
     226         648 :     mPendingRcac = std::move(rcacBuf);
     227             : 
     228         648 :     mPendingFabricIndex = fabricIndex;
     229         648 :     mStateFlags.Set(StateFlags::kAddNewTrustedRootCalled);
     230             : 
     231         648 :     return CHIP_NO_ERROR;
     232         648 : }
     233             : 
     234         652 : CHIP_ERROR PersistentStorageOpCertStore::AddNewOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc,
     235             :                                                                 const ByteSpan & icac)
     236             : {
     237         652 :     ReturnErrorCodeIf(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
     238         652 :     ReturnErrorCodeIf(!IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     239         652 :     ReturnErrorCodeIf(noc.empty() || (noc.size() > Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
     240         652 :     ReturnErrorCodeIf(icac.size() > Credentials::kMaxCHIPCertLength, CHIP_ERROR_INVALID_ARGUMENT);
     241             : 
     242             :     // Can't have called UpdateOpCertsForFabric first, or called with pending certs
     243         652 :     ReturnErrorCodeIf(mStateFlags.HasAny(StateFlags::kUpdateOpCertsCalled, StateFlags::kAddNewOpCertsCalled),
     244             :                       CHIP_ERROR_INCORRECT_STATE);
     245             : 
     246             :     // Need to have trusted roots installed to make the chain valid
     247         649 :     ReturnErrorCodeIf(!mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled), CHIP_ERROR_INCORRECT_STATE);
     248             : 
     249             :     // fabricIndex must match the current pending fabric
     250         649 :     ReturnErrorCodeIf(fabricIndex != mPendingFabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX);
     251             : 
     252             :     // Can't have persisted NOC/ICAC for same fabric if adding
     253         648 :     ReturnErrorCodeIf(StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kNoc), CHIP_ERROR_INCORRECT_STATE);
     254         647 :     ReturnErrorCodeIf(StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kIcac), CHIP_ERROR_INCORRECT_STATE);
     255             : 
     256         647 :     Platform::ScopedMemoryBufferWithSize<uint8_t> nocBuf;
     257         647 :     ReturnErrorCodeIf(!nocBuf.Alloc(noc.size()), CHIP_ERROR_NO_MEMORY);
     258         647 :     memcpy(nocBuf.Get(), noc.data(), noc.size());
     259             : 
     260         647 :     Platform::ScopedMemoryBufferWithSize<uint8_t> icacBuf;
     261         647 :     if (icac.size() > 0)
     262             :     {
     263         636 :         ReturnErrorCodeIf(!icacBuf.Alloc(icac.size()), CHIP_ERROR_NO_MEMORY);
     264         636 :         memcpy(icacBuf.Get(), icac.data(), icac.size());
     265             :     }
     266             : 
     267         647 :     mPendingNoc  = std::move(nocBuf);
     268         647 :     mPendingIcac = std::move(icacBuf);
     269             : 
     270         647 :     mStateFlags.Set(StateFlags::kAddNewOpCertsCalled);
     271             : 
     272         647 :     return CHIP_NO_ERROR;
     273         647 : }
     274             : 
     275          12 : CHIP_ERROR PersistentStorageOpCertStore::UpdateOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc,
     276             :                                                                 const ByteSpan & icac)
     277             : {
     278          12 :     ReturnErrorCodeIf(mStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
     279          11 :     ReturnErrorCodeIf(!IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     280          11 :     ReturnErrorCodeIf(noc.empty() || (noc.size() > Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
     281          11 :     ReturnErrorCodeIf(icac.size() > Credentials::kMaxCHIPCertLength, CHIP_ERROR_INVALID_ARGUMENT);
     282             : 
     283             :     // Can't have called AddNewOpCertsForFabric first, and should never get here after AddNewTrustedRootCertForFabric.
     284          11 :     ReturnErrorCodeIf(mStateFlags.HasAny(StateFlags::kAddNewOpCertsCalled, StateFlags::kAddNewTrustedRootCalled),
     285             :                       CHIP_ERROR_INCORRECT_STATE);
     286             : 
     287             :     // Can't have already pending NOC from UpdateOpCerts not yet committed
     288          10 :     ReturnErrorCodeIf(mStateFlags.Has(StateFlags::kUpdateOpCertsCalled), CHIP_ERROR_INCORRECT_STATE);
     289             : 
     290             :     // Need to have trusted roots installed to make the chain valid
     291           9 :     ReturnErrorCodeIf(!StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac), CHIP_ERROR_INCORRECT_STATE);
     292             : 
     293             :     // Must have persisted NOC for same fabric if updating
     294           8 :     ReturnErrorCodeIf(!StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kNoc), CHIP_ERROR_INCORRECT_STATE);
     295             : 
     296             :     // Don't check for ICAC, we may not have had one before, but assume that if NOC is there, a
     297             :     // previous chain was at least partially there
     298             : 
     299           8 :     Platform::ScopedMemoryBufferWithSize<uint8_t> nocBuf;
     300           8 :     ReturnErrorCodeIf(!nocBuf.Alloc(noc.size()), CHIP_ERROR_NO_MEMORY);
     301           8 :     memcpy(nocBuf.Get(), noc.data(), noc.size());
     302             : 
     303           8 :     Platform::ScopedMemoryBufferWithSize<uint8_t> icacBuf;
     304           8 :     if (icac.size() > 0)
     305             :     {
     306           3 :         ReturnErrorCodeIf(!icacBuf.Alloc(icac.size()), CHIP_ERROR_NO_MEMORY);
     307           3 :         memcpy(icacBuf.Get(), icac.data(), icac.size());
     308             :     }
     309             : 
     310           8 :     mPendingNoc  = std::move(nocBuf);
     311           8 :     mPendingIcac = std::move(icacBuf);
     312             : 
     313             :     // For NOC update, UpdateOpCertsForFabric is what determines the pending fabric index,
     314             :     // not a previous AddNewTrustedRootCertForFabric call.
     315           8 :     mPendingFabricIndex = fabricIndex;
     316             : 
     317           8 :     mStateFlags.Set(StateFlags::kUpdateOpCertsCalled);
     318             : 
     319           8 :     return CHIP_NO_ERROR;
     320           8 : }
     321             : 
     322         638 : CHIP_ERROR PersistentStorageOpCertStore::CommitOpCertsForFabric(FabricIndex fabricIndex)
     323             : {
     324         638 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     325         638 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     326             : 
     327         637 :     VerifyOrReturnError(HasPendingNocChain(), CHIP_ERROR_INCORRECT_STATE);
     328         636 :     if (HasPendingRootCert())
     329             :     {
     330             :         // Neither of these conditions should have occurred based on other interlocks, but since
     331             :         // committing certificates is a dangerous operation, we absolutely validate our assumptions.
     332         631 :         ReturnErrorCodeIf(mStateFlags.Has(StateFlags::kUpdateOpCertsCalled), CHIP_ERROR_INCORRECT_STATE);
     333         631 :         ReturnErrorCodeIf(!mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled), CHIP_ERROR_INCORRECT_STATE);
     334             :     }
     335             : 
     336             :     // TODO: Handle transaction marking to revert partial certs at next boot if we get interrupted by reboot.
     337             : 
     338             :     // Start committing NOC first so we don't have dangling roots if one was added.
     339         636 :     ByteSpan pendingNocSpan{ mPendingNoc.Get(), mPendingNoc.AllocatedSize() };
     340         636 :     CHIP_ERROR nocErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kNoc, pendingNocSpan);
     341             : 
     342             :     // ICAC storage handles deleting on empty/missing
     343         636 :     ByteSpan pendingIcacSpan{ mPendingIcac.Get(), mPendingIcac.AllocatedSize() };
     344         636 :     CHIP_ERROR icacErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kIcac, pendingIcacSpan);
     345             : 
     346         636 :     CHIP_ERROR rcacErr = CHIP_NO_ERROR;
     347         636 :     if (HasPendingRootCert())
     348             :     {
     349         631 :         ByteSpan pendingRcacSpan{ mPendingRcac.Get(), mPendingRcac.AllocatedSize() };
     350         631 :         rcacErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kRcac, pendingRcacSpan);
     351             :     }
     352             : 
     353             :     // Remember which was the first error, and if any error occurred.
     354         636 :     CHIP_ERROR stickyErr = nocErr;
     355         636 :     stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : icacErr;
     356         636 :     stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : rcacErr;
     357             : 
     358         636 :     if (stickyErr != CHIP_NO_ERROR)
     359             :     {
     360             :         // On Adds rather than updates, remove anything possibly stored for the new fabric on partial
     361             :         // failure.
     362           0 :         if (mStateFlags.Has(StateFlags::kAddNewOpCertsCalled))
     363             :         {
     364           0 :             (void) DeleteCertFromStorage(mStorage, mPendingFabricIndex, CertChainElement::kNoc);
     365           0 :             (void) DeleteCertFromStorage(mStorage, mPendingFabricIndex, CertChainElement::kIcac);
     366             :         }
     367           0 :         if (mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled))
     368             :         {
     369           0 :             (void) DeleteCertFromStorage(mStorage, mPendingFabricIndex, CertChainElement::kRcac);
     370             :         }
     371           0 :         if (mStateFlags.Has(StateFlags::kUpdateOpCertsCalled))
     372             :         {
     373             :             // Can't do anything to clean-up here, but pretty sure the fabric is broken now...
     374             :             // TODO: Handle transaction marking to revert certs if somehow failing store on update by pre-backing-up opcerts
     375             :         }
     376             : 
     377           0 :         return stickyErr;
     378             :     }
     379             : 
     380             :     // If we got here, we succeeded and can reset the pending certs: next `GetCertificate` will use the stored certs
     381         636 :     RevertPendingOpCerts();
     382         636 :     return CHIP_NO_ERROR;
     383             : }
     384             : 
     385          20 : bool PersistentStorageOpCertStore::HasAnyCertificateForFabric(FabricIndex fabricIndex) const
     386             : {
     387          20 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);
     388             : 
     389          20 :     bool rcacMissing = !StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac);
     390          20 :     bool icacMissing = !StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kIcac);
     391          20 :     bool nocMissing  = !StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kNoc);
     392          20 :     bool anyPending  = (mPendingRcac.Get() != nullptr) || (mPendingIcac.Get() != nullptr) || (mPendingNoc.Get() != nullptr);
     393             : 
     394          20 :     if (rcacMissing && icacMissing && nocMissing && !anyPending)
     395             :     {
     396           4 :         return false;
     397             :     }
     398             : 
     399          16 :     return true;
     400             : }
     401             : 
     402          21 : CHIP_ERROR PersistentStorageOpCertStore::RemoveOpCertsForFabric(FabricIndex fabricIndex)
     403             : {
     404          21 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     405          20 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     406             : 
     407             :     // If there was *no* state, pending or persisted, we have an error
     408          20 :     ReturnErrorCodeIf(!HasAnyCertificateForFabric(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     409             : 
     410             :     // Clear any pending state
     411          16 :     RevertPendingOpCerts();
     412             : 
     413             :     // Remove all persisted certs for the given fabric, blindly
     414          16 :     CHIP_ERROR nocErr  = DeleteCertFromStorage(mStorage, fabricIndex, CertChainElement::kNoc);
     415          16 :     CHIP_ERROR icacErr = DeleteCertFromStorage(mStorage, fabricIndex, CertChainElement::kIcac);
     416          16 :     CHIP_ERROR rcacErr = DeleteCertFromStorage(mStorage, fabricIndex, CertChainElement::kRcac);
     417             : 
     418             :     // Ignore missing cert errors
     419          16 :     nocErr  = (nocErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) ? CHIP_NO_ERROR : nocErr;
     420          16 :     icacErr = (icacErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) ? CHIP_NO_ERROR : icacErr;
     421          16 :     rcacErr = (rcacErr == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) ? CHIP_NO_ERROR : rcacErr;
     422             : 
     423             :     // Find the first error and return that
     424          16 :     CHIP_ERROR stickyErr = nocErr;
     425          16 :     stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : icacErr;
     426          16 :     stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : rcacErr;
     427             : 
     428          16 :     return stickyErr;
     429             : }
     430             : 
     431        2136 : CHIP_ERROR PersistentStorageOpCertStore::GetPendingCertificate(FabricIndex fabricIndex, CertChainElement element,
     432             :                                                                MutableByteSpan & outCertificate) const
     433             : {
     434        2136 :     if (fabricIndex != mPendingFabricIndex)
     435             :     {
     436         132 :         return CHIP_ERROR_NOT_FOUND;
     437             :     }
     438             : 
     439             :     // FabricIndex matches pending, we MAY have some pending data
     440        2004 :     switch (element)
     441             :     {
     442         700 :     case CertChainElement::kRcac:
     443         700 :         if (mPendingRcac.Get() != nullptr)
     444             :         {
     445         693 :             ByteSpan rcacSpan{ mPendingRcac.Get(), mPendingRcac.AllocatedSize() };
     446         693 :             return CopySpanToMutableSpan(rcacSpan, outCertificate);
     447             :         }
     448           7 :         break;
     449         652 :     case CertChainElement::kIcac:
     450         652 :         if (mPendingIcac.Get() != nullptr)
     451             :         {
     452         639 :             ByteSpan icacSpan{ mPendingIcac.Get(), mPendingIcac.AllocatedSize() };
     453         639 :             return CopySpanToMutableSpan(icacSpan, outCertificate);
     454             :         }
     455          13 :         break;
     456         652 :     case CertChainElement::kNoc:
     457         652 :         if (mPendingNoc.Get() != nullptr)
     458             :         {
     459         652 :             ByteSpan nocSpan{ mPendingNoc.Get(), mPendingNoc.AllocatedSize() };
     460         652 :             return CopySpanToMutableSpan(nocSpan, outCertificate);
     461             :         }
     462           0 :         break;
     463           0 :     default:
     464           0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     465             :     }
     466             : 
     467          20 :     return CHIP_ERROR_NOT_FOUND;
     468             : }
     469             : 
     470        2136 : CHIP_ERROR PersistentStorageOpCertStore::GetCertificate(FabricIndex fabricIndex, CertChainElement element,
     471             :                                                         MutableByteSpan & outCertificate) const
     472             : {
     473        2136 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     474        2136 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     475             : 
     476             :     // Handle case of pending data
     477        2136 :     CHIP_ERROR err = GetPendingCertificate(fabricIndex, element, outCertificate);
     478        2136 :     if ((err == CHIP_NO_ERROR) || (err != CHIP_ERROR_NOT_FOUND))
     479             :     {
     480             :         // Found in pending, or got a deeper error: return the pending cert status.
     481        1984 :         return err;
     482             :     }
     483             : 
     484             :     // If we have a pending NOC and no pending ICAC, don't delegate to storage, return not found here
     485             :     // since in the pending state, there truly is nothing.
     486             : 
     487         152 :     if ((err == CHIP_ERROR_NOT_FOUND) && (element == CertChainElement::kIcac) && (mPendingNoc.Get() != nullptr))
     488             :     {
     489             :         // Don't delegate to storage if we just have a pending NOC and are missing the ICAC
     490          13 :         return CHIP_ERROR_NOT_FOUND;
     491             :     }
     492             : 
     493             :     // Not found in pending, let's look in persisted
     494         139 :     return LoadCertFromStorage(mStorage, fabricIndex, element, outCertificate);
     495             : }
     496             : 
     497             : } // namespace Credentials
     498             : } // namespace chip

Generated by: LCOV version 1.14