Matter SDK Coverage Report
Current view: top level - credentials - PersistentStorageOpCertStore.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 88.7 % 222 197
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 16 16

            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         4571 : StorageKeyName GetStorageKeyForCert(FabricIndex fabricIndex, CertChainElement element)
      39              : {
      40         4571 :     switch (element)
      41              :     {
      42         1530 :     case CertChainElement::kNoc:
      43         1530 :         return DefaultStorageKeyAllocator::FabricNOC(fabricIndex);
      44              :         break;
      45         1504 :     case CertChainElement::kIcac:
      46         1504 :         return DefaultStorageKeyAllocator::FabricICAC(fabricIndex);
      47              :         break;
      48         1537 :     case CertChainElement::kRcac:
      49         1537 :         return DefaultStorageKeyAllocator::FabricRCAC(fabricIndex);
      50              :         break;
      51            0 :     default:
      52            0 :         break;
      53              :     }
      54              : 
      55            0 :     return StorageKeyName::Uninitialized();
      56              : }
      57              : 
      58         2256 : bool StorageHasCertificate(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element)
      59              : {
      60         2256 :     StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
      61              : 
      62         2256 :     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         2256 :     uint16_t keySize = sizeof(placeHolderCertBuffer);
      73         2256 :     CHIP_ERROR err   = storage->SyncGetKeyValue(storageKey.KeyName(), &placeHolderCertBuffer[0], keySize);
      74              : 
      75         2256 :     return (err == CHIP_NO_ERROR);
      76         2256 : }
      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         2128 : CHIP_ERROR SaveCertToStorage(PersistentStorageDelegate * storage, FabricIndex fabricIndex, CertChainElement element,
     113              :                              const ByteSpan & cert)
     114              : {
     115         2128 :     StorageKeyName storageKey = GetStorageKeyForCert(fabricIndex, element);
     116         2128 :     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         2128 :     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         2119 :     return storage->SyncSetKeyValue(storageKey.KeyName(), cert.data(), static_cast<uint16_t>(cert.size()));
     133         2128 : }
     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         1464 : bool PersistentStorageOpCertStore::HasPendingRootCert() const
     148              : {
     149         1464 :     if (mStorage == nullptr)
     150              :     {
     151            0 :         return false;
     152              :     }
     153              : 
     154         1464 :     return (mPendingRcac.Get() != nullptr) && mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled);
     155              : }
     156              : 
     157          753 : bool PersistentStorageOpCertStore::HasPendingNocChain() const
     158              : {
     159          753 :     if (mStorage == nullptr)
     160              :     {
     161            0 :         return false;
     162              :     }
     163              : 
     164          753 :     return (mPendingNoc.Get() != nullptr) && mStateFlags.HasAny(StateFlags::kAddNewOpCertsCalled, StateFlags::kUpdateOpCertsCalled);
     165              : }
     166              : 
     167          723 : bool PersistentStorageOpCertStore::HasCertificateForFabric(FabricIndex fabricIndex, CertChainElement element) const
     168              : {
     169          723 :     if ((mStorage == nullptr) || !IsValidFabricIndex(fabricIndex))
     170              :     {
     171            0 :         return false;
     172              :     }
     173              : 
     174              :     // FabricIndex matches pending, we MAY have some pending data
     175          723 :     if (fabricIndex == mPendingFabricIndex)
     176              :     {
     177          716 :         switch (element)
     178              :         {
     179          703 :         case CertChainElement::kRcac:
     180          703 :             if (mPendingRcac.Get() != nullptr)
     181              :             {
     182          703 :                 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          729 : CHIP_ERROR PersistentStorageOpCertStore::AddNewTrustedRootCertForFabric(FabricIndex fabricIndex, const ByteSpan & rcac)
     212              : {
     213          729 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     214          728 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     215          727 :     VerifyOrReturnError(!rcac.empty() && (rcac.size() <= Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
     216              : 
     217          727 :     VerifyOrReturnError(!mStateFlags.HasAny(StateFlags::kUpdateOpCertsCalled, StateFlags::kAddNewTrustedRootCalled,
     218              :                                             StateFlags::kAddNewOpCertsCalled),
     219              :                         CHIP_ERROR_INCORRECT_STATE);
     220          725 :     VerifyOrReturnError(!StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac), CHIP_ERROR_INCORRECT_STATE);
     221              : 
     222          724 :     Platform::ScopedMemoryBufferWithSize<uint8_t> rcacBuf;
     223          724 :     VerifyOrReturnError(rcacBuf.Alloc(rcac.size()), CHIP_ERROR_NO_MEMORY);
     224          724 :     memcpy(rcacBuf.Get(), rcac.data(), rcac.size());
     225              : 
     226          724 :     mPendingRcac = std::move(rcacBuf);
     227              : 
     228          724 :     mPendingFabricIndex = fabricIndex;
     229          724 :     mStateFlags.Set(StateFlags::kAddNewTrustedRootCalled);
     230              : 
     231          724 :     return CHIP_NO_ERROR;
     232          724 : }
     233              : 
     234          727 : CHIP_ERROR PersistentStorageOpCertStore::AddNewOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc,
     235              :                                                                 const ByteSpan & icac)
     236              : {
     237          727 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     238          727 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     239          727 :     VerifyOrReturnError(!noc.empty() && (noc.size() <= Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
     240          727 :     VerifyOrReturnError(icac.size() <= Credentials::kMaxCHIPCertLength, CHIP_ERROR_INVALID_ARGUMENT);
     241              : 
     242              :     // Can't have called UpdateOpCertsForFabric first, or called with pending certs
     243          727 :     VerifyOrReturnError(!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          724 :     VerifyOrReturnError(mStateFlags.Has(StateFlags::kAddNewTrustedRootCalled), CHIP_ERROR_INCORRECT_STATE);
     248              : 
     249              :     // fabricIndex must match the current pending fabric
     250          724 :     VerifyOrReturnError(fabricIndex == mPendingFabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX);
     251              : 
     252              :     // Can't have persisted NOC/ICAC for same fabric if adding
     253          723 :     VerifyOrReturnError(!StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kNoc), CHIP_ERROR_INCORRECT_STATE);
     254          722 :     VerifyOrReturnError(!StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kIcac), CHIP_ERROR_INCORRECT_STATE);
     255              : 
     256          722 :     Platform::ScopedMemoryBufferWithSize<uint8_t> nocBuf;
     257          722 :     VerifyOrReturnError(nocBuf.Alloc(noc.size()), CHIP_ERROR_NO_MEMORY);
     258          722 :     memcpy(nocBuf.Get(), noc.data(), noc.size());
     259              : 
     260          722 :     Platform::ScopedMemoryBufferWithSize<uint8_t> icacBuf;
     261          722 :     if (icac.size() > 0)
     262              :     {
     263          711 :         VerifyOrReturnError(icacBuf.Alloc(icac.size()), CHIP_ERROR_NO_MEMORY);
     264          711 :         memcpy(icacBuf.Get(), icac.data(), icac.size());
     265              :     }
     266              : 
     267          722 :     mPendingNoc  = std::move(nocBuf);
     268          722 :     mPendingIcac = std::move(icacBuf);
     269              : 
     270          722 :     mStateFlags.Set(StateFlags::kAddNewOpCertsCalled);
     271              : 
     272          722 :     return CHIP_NO_ERROR;
     273          722 : }
     274              : 
     275           12 : CHIP_ERROR PersistentStorageOpCertStore::UpdateOpCertsForFabric(FabricIndex fabricIndex, const ByteSpan & noc,
     276              :                                                                 const ByteSpan & icac)
     277              : {
     278           12 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     279           11 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     280           11 :     VerifyOrReturnError(!noc.empty() && (noc.size() <= Credentials::kMaxCHIPCertLength), CHIP_ERROR_INVALID_ARGUMENT);
     281           11 :     VerifyOrReturnError(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 :     VerifyOrReturnError(!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 :     VerifyOrReturnError(!mStateFlags.Has(StateFlags::kUpdateOpCertsCalled), CHIP_ERROR_INCORRECT_STATE);
     289              : 
     290              :     // Need to have trusted roots installed to make the chain valid
     291            9 :     VerifyOrReturnError(StorageHasCertificate(mStorage, fabricIndex, CertChainElement::kRcac), CHIP_ERROR_INCORRECT_STATE);
     292              : 
     293              :     // Must have persisted NOC for same fabric if updating
     294            8 :     VerifyOrReturnError(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 :     VerifyOrReturnError(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 :         VerifyOrReturnError(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          713 : CHIP_ERROR PersistentStorageOpCertStore::CommitOpCertsForFabric(FabricIndex fabricIndex)
     323              : {
     324          713 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     325          713 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     326              : 
     327          712 :     VerifyOrReturnError(HasPendingNocChain(), CHIP_ERROR_INCORRECT_STATE);
     328          711 :     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          706 :         VerifyOrReturnError(!mStateFlags.Has(StateFlags::kUpdateOpCertsCalled), CHIP_ERROR_INCORRECT_STATE);
     333          706 :         VerifyOrReturnError(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          711 :     ByteSpan pendingNocSpan{ mPendingNoc.Get(), mPendingNoc.AllocatedSize() };
     340          711 :     CHIP_ERROR nocErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kNoc, pendingNocSpan);
     341              : 
     342              :     // ICAC storage handles deleting on empty/missing
     343          711 :     ByteSpan pendingIcacSpan{ mPendingIcac.Get(), mPendingIcac.AllocatedSize() };
     344          711 :     CHIP_ERROR icacErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kIcac, pendingIcacSpan);
     345              : 
     346          711 :     CHIP_ERROR rcacErr = CHIP_NO_ERROR;
     347          711 :     if (HasPendingRootCert())
     348              :     {
     349          706 :         ByteSpan pendingRcacSpan{ mPendingRcac.Get(), mPendingRcac.AllocatedSize() };
     350          706 :         rcacErr = SaveCertToStorage(mStorage, mPendingFabricIndex, CertChainElement::kRcac, pendingRcacSpan);
     351              :     }
     352              : 
     353              :     // Remember which was the first error, and if any error occurred.
     354          711 :     CHIP_ERROR stickyErr = nocErr;
     355          711 :     stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : icacErr;
     356          711 :     stickyErr            = (stickyErr != CHIP_NO_ERROR) ? stickyErr : rcacErr;
     357              : 
     358          711 :     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          711 :     RevertPendingOpCerts();
     382          711 :     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 :     VerifyOrReturnError(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         2364 : CHIP_ERROR PersistentStorageOpCertStore::GetPendingCertificate(FabricIndex fabricIndex, CertChainElement element,
     432              :                                                                MutableByteSpan & outCertificate) const
     433              : {
     434         2364 :     if (fabricIndex != mPendingFabricIndex)
     435              :     {
     436          132 :         return CHIP_ERROR_NOT_FOUND;
     437              :     }
     438              : 
     439              :     // FabricIndex matches pending, we MAY have some pending data
     440         2232 :     switch (element)
     441              :     {
     442          778 :     case CertChainElement::kRcac:
     443          778 :         if (mPendingRcac.Get() != nullptr)
     444              :         {
     445          771 :             ByteSpan rcacSpan{ mPendingRcac.Get(), mPendingRcac.AllocatedSize() };
     446          771 :             return CopySpanToMutableSpan(rcacSpan, outCertificate);
     447              :         }
     448            7 :         break;
     449          727 :     case CertChainElement::kIcac:
     450          727 :         if (mPendingIcac.Get() != nullptr)
     451              :         {
     452          714 :             ByteSpan icacSpan{ mPendingIcac.Get(), mPendingIcac.AllocatedSize() };
     453          714 :             return CopySpanToMutableSpan(icacSpan, outCertificate);
     454              :         }
     455           13 :         break;
     456          727 :     case CertChainElement::kNoc:
     457          727 :         if (mPendingNoc.Get() != nullptr)
     458              :         {
     459          727 :             ByteSpan nocSpan{ mPendingNoc.Get(), mPendingNoc.AllocatedSize() };
     460          727 :             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         2364 : CHIP_ERROR PersistentStorageOpCertStore::GetCertificate(FabricIndex fabricIndex, CertChainElement element,
     471              :                                                         MutableByteSpan & outCertificate) const
     472              : {
     473         2364 :     VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE);
     474         2364 :     VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
     475              : 
     476              :     // Handle case of pending data
     477         2364 :     CHIP_ERROR err = GetPendingCertificate(fabricIndex, element, outCertificate);
     478         2364 :     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         2212 :         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 2.0-1