Matter SDK Coverage Report
Current view: top level - controller - ExampleOperationalCredentialsIssuer.cpp (source / functions) Coverage Total Hit
Test: SHA:c5aeaea5470ddad6464d5b62caddeb9f1efd6a41 Lines: 72.2 % 198 143
Test Date: 2025-07-25 07:10:31 Functions: 80.0 % 5 4

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021-2022 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : #include <algorithm>
      20              : #include <controller/ExampleOperationalCredentialsIssuer.h>
      21              : #include <credentials/CHIPCert.h>
      22              : #include <lib/core/TLV.h>
      23              : #include <lib/support/CHIPMem.h>
      24              : #include <lib/support/CodeUtils.h>
      25              : #include <lib/support/PersistentStorageMacros.h>
      26              : #include <lib/support/SafeInt.h>
      27              : #include <lib/support/ScopedBuffer.h>
      28              : #include <lib/support/TestGroupData.h>
      29              : 
      30              : namespace chip {
      31              : namespace Controller {
      32              : 
      33              : constexpr char kOperationalCredentialsIssuerKeypairStorage[]             = "ExampleOpCredsCAKey";
      34              : constexpr char kOperationalCredentialsIntermediateIssuerKeypairStorage[] = "ExampleOpCredsICAKey";
      35              : constexpr char kOperationalCredentialsRootCertificateStorage[]           = "ExampleCARootCert";
      36              : constexpr char kOperationalCredentialsIntermediateCertificateStorage[]   = "ExampleCAIntermediateCert";
      37              : 
      38              : using namespace Credentials;
      39              : using namespace Crypto;
      40              : using namespace TLV;
      41              : 
      42              : namespace {
      43              : 
      44              : enum CertType : uint8_t
      45              : {
      46              :     kRcac = 0,
      47              :     kIcac = 1,
      48              :     kNoc  = 2
      49              : };
      50              : 
      51            6 : CHIP_ERROR IssueX509Cert(uint32_t now, uint32_t validity, ChipDN issuerDn, ChipDN desiredDn, CertType certType, bool maximizeSize,
      52              :                          const Crypto::P256PublicKey & subjectPublicKey, Crypto::P256Keypair & issuerKeypair,
      53              :                          MutableByteSpan & outX509Cert)
      54              : {
      55            6 :     constexpr size_t kDERCertFutureExtEncodingOverhead = 12;
      56            6 :     constexpr size_t kTLVCertFutureExtEncodingOverhead = kDERCertFutureExtEncodingOverhead + 5;
      57            6 :     constexpr size_t kMaxCertPaddingLength             = 200;
      58            6 :     constexpr size_t kTLVDesiredSize                   = kMaxCHIPCertLength;
      59            6 :     constexpr uint8_t sOID_Extension_SubjectAltName[]  = { 0x55, 0x1d, 0x11 };
      60              : 
      61            6 :     Platform::ScopedMemoryBuffer<uint8_t> derBuf;
      62            6 :     VerifyOrReturnError(derBuf.Alloc(kMaxDERCertLength), CHIP_ERROR_NO_MEMORY);
      63            6 :     MutableByteSpan derSpan{ derBuf.Get(), kMaxDERCertLength };
      64              : 
      65            6 :     int64_t serialNumber = 1;
      66              : 
      67            6 :     switch (certType)
      68              :     {
      69            2 :     case CertType::kRcac: {
      70            2 :         X509CertRequestParams rcacRequest = { serialNumber, now, now + validity, desiredDn, desiredDn };
      71            2 :         ReturnErrorOnFailure(NewRootX509Cert(rcacRequest, issuerKeypair, derSpan));
      72            2 :         break;
      73            2 :     }
      74            2 :     case CertType::kIcac: {
      75            2 :         X509CertRequestParams icacRequest = { serialNumber, now, now + validity, desiredDn, issuerDn };
      76            2 :         ReturnErrorOnFailure(NewICAX509Cert(icacRequest, subjectPublicKey, issuerKeypair, derSpan));
      77            2 :         break;
      78            2 :     }
      79            2 :     case CertType::kNoc: {
      80            2 :         X509CertRequestParams nocRequest = { serialNumber, now, now + validity, desiredDn, issuerDn };
      81            2 :         ReturnErrorOnFailure(NewNodeOperationalX509Cert(nocRequest, subjectPublicKey, issuerKeypair, derSpan));
      82            2 :         break;
      83            2 :     }
      84            0 :     default:
      85            0 :         return CHIP_ERROR_INVALID_ARGUMENT;
      86              :     }
      87              : 
      88            6 :     if (maximizeSize)
      89              :     {
      90            3 :         Platform::ScopedMemoryBuffer<uint8_t> paddedTlvBuf;
      91            3 :         VerifyOrReturnError(paddedTlvBuf.Alloc(kMaxCHIPCertLength + kMaxCertPaddingLength), CHIP_ERROR_NO_MEMORY);
      92            3 :         MutableByteSpan paddedTlvSpan{ paddedTlvBuf.Get(), kMaxCHIPCertLength + kMaxCertPaddingLength };
      93            3 :         ReturnErrorOnFailure(ConvertX509CertToChipCert(derSpan, paddedTlvSpan));
      94              : 
      95            3 :         Platform::ScopedMemoryBuffer<uint8_t> paddedDerBuf;
      96            3 :         VerifyOrReturnError(paddedDerBuf.Alloc(kMaxDERCertLength + kMaxCertPaddingLength), CHIP_ERROR_NO_MEMORY);
      97            3 :         MutableByteSpan paddedDerSpan{ paddedDerBuf.Get(), kMaxDERCertLength + kMaxCertPaddingLength };
      98              : 
      99            3 :         Platform::ScopedMemoryBuffer<char> fillerBuf;
     100            3 :         VerifyOrReturnError(fillerBuf.Alloc(kMaxCertPaddingLength), CHIP_ERROR_NO_MEMORY);
     101            3 :         memset(fillerBuf.Get(), 'A', kMaxCertPaddingLength);
     102              : 
     103            3 :         int derPaddingLen = static_cast<int>(kMaxDERCertLength - kDERCertFutureExtEncodingOverhead - derSpan.size());
     104            3 :         int tlvPaddingLen = static_cast<int>(kTLVDesiredSize - kTLVCertFutureExtEncodingOverhead - paddedTlvSpan.size());
     105            3 :         size_t paddingLen = 0;
     106            3 :         if (derPaddingLen >= 1 && tlvPaddingLen >= 1)
     107              :         {
     108            3 :             paddingLen = std::min(static_cast<size_t>(std::min(derPaddingLen, tlvPaddingLen)), kMaxCertPaddingLength);
     109              :         }
     110              : 
     111            3 :         for (; paddingLen > 0; paddingLen--)
     112              :         {
     113            3 :             paddedDerSpan = MutableByteSpan{ paddedDerBuf.Get(), kMaxDERCertLength + kMaxCertPaddingLength };
     114            3 :             paddedTlvSpan = MutableByteSpan{ paddedTlvBuf.Get(), kMaxCHIPCertLength + kMaxCertPaddingLength };
     115              : 
     116            3 :             Optional<FutureExtension> futureExt;
     117              :             FutureExtension ext = { ByteSpan(sOID_Extension_SubjectAltName),
     118            3 :                                     ByteSpan(reinterpret_cast<uint8_t *>(fillerBuf.Get()), paddingLen) };
     119            3 :             futureExt.SetValue(ext);
     120              : 
     121            3 :             switch (certType)
     122              :             {
     123            1 :             case CertType::kRcac: {
     124            1 :                 X509CertRequestParams rcacRequest = { serialNumber, now, now + validity, desiredDn, desiredDn, futureExt };
     125            1 :                 ReturnErrorOnFailure(NewRootX509Cert(rcacRequest, issuerKeypair, paddedDerSpan));
     126            1 :                 break;
     127            1 :             }
     128            1 :             case CertType::kIcac: {
     129            1 :                 X509CertRequestParams icacRequest = { serialNumber, now, now + validity, desiredDn, issuerDn, futureExt };
     130            1 :                 ReturnErrorOnFailure(NewICAX509Cert(icacRequest, subjectPublicKey, issuerKeypair, paddedDerSpan));
     131            1 :                 break;
     132            1 :             }
     133            1 :             case CertType::kNoc: {
     134            1 :                 X509CertRequestParams nocRequest = { serialNumber, now, now + validity, desiredDn, issuerDn, futureExt };
     135            1 :                 ReturnErrorOnFailure(NewNodeOperationalX509Cert(nocRequest, subjectPublicKey, issuerKeypair, paddedDerSpan));
     136            1 :                 break;
     137            1 :             }
     138            0 :             default:
     139            0 :                 return CHIP_ERROR_INVALID_ARGUMENT;
     140              :             }
     141              : 
     142            3 :             ReturnErrorOnFailure(ConvertX509CertToChipCert(paddedDerSpan, paddedTlvSpan));
     143              : 
     144            3 :             if (paddedDerSpan.size() <= kMaxDERCertLength && paddedTlvSpan.size() <= kMaxCHIPCertLength)
     145              :             {
     146            3 :                 ChipLogProgress(Controller, "Generated maximized certificate with %u DER bytes, %u TLV bytes",
     147              :                                 static_cast<unsigned>(paddedDerSpan.size()), static_cast<unsigned>(paddedTlvSpan.size()));
     148            3 :                 return CopySpanToMutableSpan(paddedDerSpan, outX509Cert);
     149              :             }
     150              :         }
     151            9 :     }
     152              : 
     153            3 :     return CopySpanToMutableSpan(derSpan, outX509Cert);
     154            6 : }
     155              : 
     156              : } // namespace
     157              : 
     158            2 : CHIP_ERROR ExampleOperationalCredentialsIssuer::Initialize(PersistentStorageDelegate & storage)
     159              : {
     160              :     using namespace ASN1;
     161              :     ASN1UniversalTime effectiveTime;
     162              :     CHIP_ERROR err;
     163              : 
     164              :     // Initializing the default start validity to start of 2021. The default validity duration is 10 years.
     165            2 :     CHIP_ZERO_AT(effectiveTime);
     166            2 :     effectiveTime.Year  = 2021;
     167            2 :     effectiveTime.Month = 1;
     168            2 :     effectiveTime.Day   = 1;
     169            2 :     ReturnErrorOnFailure(ASN1ToChipEpochTime(effectiveTime, mNow));
     170              : 
     171            2 :     Crypto::P256SerializedKeypair serializedKey;
     172              :     {
     173              :         // Scope for keySize, because we use it as an in/out param.
     174            2 :         uint16_t keySize = static_cast<uint16_t>(serializedKey.Capacity());
     175              : 
     176            2 :         PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsIssuerKeypairStorage, key,
     177              :                           err = storage.SyncGetKeyValue(key, serializedKey.Bytes(), keySize));
     178            2 :         serializedKey.SetLength(keySize);
     179              :     }
     180              : 
     181            2 :     if (err != CHIP_NO_ERROR)
     182              :     {
     183            2 :         ChipLogProgress(Controller, "Couldn't get %s from storage: %" CHIP_ERROR_FORMAT,
     184              :                         kOperationalCredentialsIssuerKeypairStorage, err.Format());
     185              :         // Storage doesn't have an existing keypair. Let's create one and add it to the storage.
     186            2 :         ReturnErrorOnFailure(mRootIssuer.Initialize(Crypto::ECPKeyTarget::ECDSA));
     187            2 :         ReturnErrorOnFailure(mRootIssuer.Serialize(serializedKey));
     188              : 
     189            2 :         PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsIssuerKeypairStorage, key,
     190              :                           ReturnErrorOnFailure(
     191              :                               storage.SyncSetKeyValue(key, serializedKey.Bytes(), static_cast<uint16_t>(serializedKey.Length()))));
     192              :     }
     193              :     else
     194              :     {
     195              :         // Use the keypair from the storage
     196            0 :         ReturnErrorOnFailure(mRootIssuer.Deserialize(serializedKey));
     197              :     }
     198              : 
     199              :     {
     200              :         // Scope for keySize, because we use it as an in/out param.
     201            2 :         uint16_t keySize = static_cast<uint16_t>(serializedKey.Capacity());
     202              : 
     203            2 :         PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsIntermediateIssuerKeypairStorage, key,
     204              :                           err = storage.SyncGetKeyValue(key, serializedKey.Bytes(), keySize));
     205            2 :         serializedKey.SetLength(keySize);
     206              :     }
     207              : 
     208            2 :     if (err != CHIP_NO_ERROR)
     209              :     {
     210            2 :         ChipLogProgress(Controller, "Couldn't get %s from storage: %" CHIP_ERROR_FORMAT,
     211              :                         kOperationalCredentialsIntermediateIssuerKeypairStorage, err.Format());
     212              :         // Storage doesn't have an existing keypair. Let's create one and add it to the storage.
     213            2 :         ReturnErrorOnFailure(mIntermediateIssuer.Initialize(Crypto::ECPKeyTarget::ECDSA));
     214            2 :         ReturnErrorOnFailure(mIntermediateIssuer.Serialize(serializedKey));
     215              : 
     216            2 :         PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsIntermediateIssuerKeypairStorage, key,
     217              :                           ReturnErrorOnFailure(
     218              :                               storage.SyncSetKeyValue(key, serializedKey.Bytes(), static_cast<uint16_t>(serializedKey.Length()))));
     219              :     }
     220              :     else
     221              :     {
     222              :         // Use the keypair from the storage
     223            0 :         ReturnErrorOnFailure(mIntermediateIssuer.Deserialize(serializedKey));
     224              :     }
     225              : 
     226            2 :     mStorage     = &storage;
     227            2 :     mInitialized = true;
     228            2 :     return CHIP_NO_ERROR;
     229            2 : }
     230              : 
     231            2 : CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChainAfterValidation(NodeId nodeId, FabricId fabricId,
     232              :                                                                                 const CATValues & cats,
     233              :                                                                                 const Crypto::P256PublicKey & pubkey,
     234              :                                                                                 MutableByteSpan & rcac, MutableByteSpan & icac,
     235              :                                                                                 MutableByteSpan & noc)
     236              : {
     237            2 :     ChipDN rcac_dn;
     238            2 :     CHIP_ERROR err      = CHIP_NO_ERROR;
     239            2 :     uint16_t rcacBufLen = static_cast<uint16_t>(std::min(rcac.size(), static_cast<size_t>(UINT16_MAX)));
     240            2 :     PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsRootCertificateStorage, key,
     241              :                       err = mStorage->SyncGetKeyValue(key, rcac.data(), rcacBufLen));
     242              :     // Always regenerate RCAC on maximally sized certs. The keys remain the same, so everything is fine.
     243            2 :     if (mUseMaximallySizedCerts)
     244              :     {
     245            1 :         err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
     246              :     }
     247              : 
     248            2 :     if (err == CHIP_NO_ERROR)
     249              :     {
     250              :         uint64_t rcacId;
     251              :         // Found root certificate in the storage.
     252            0 :         rcac.reduce_size(rcacBufLen);
     253            0 :         ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(rcac, rcac_dn));
     254            0 :         ReturnErrorOnFailure(rcac_dn.GetCertChipId(rcacId));
     255            0 :         VerifyOrReturnError(rcacId == mRootIssuerId, CHIP_ERROR_INTERNAL);
     256              :     }
     257              :     // If root certificate not found in the storage, generate new root certificate.
     258              :     else
     259              :     {
     260            2 :         ReturnErrorOnFailure(rcac_dn.AddAttribute_MatterRCACId(mRootIssuerId));
     261              : 
     262            2 :         ChipLogProgress(Controller, "Generating RCAC");
     263            2 :         ReturnErrorOnFailure(IssueX509Cert(mNow, mValidity, rcac_dn, rcac_dn, CertType::kRcac, mUseMaximallySizedCerts,
     264              :                                            mRootIssuer.Pubkey(), mRootIssuer, rcac));
     265            2 :         VerifyOrReturnError(CanCastTo<uint16_t>(rcac.size()), CHIP_ERROR_INTERNAL);
     266              : 
     267              :         // Re-extract DN based on final generated cert
     268            2 :         rcac_dn = ChipDN{};
     269            2 :         ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(rcac, rcac_dn));
     270              : 
     271            2 :         PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsRootCertificateStorage, key,
     272              :                           ReturnErrorOnFailure(mStorage->SyncSetKeyValue(key, rcac.data(), static_cast<uint16_t>(rcac.size()))));
     273              :     }
     274              : 
     275            2 :     ChipDN icac_dn;
     276            2 :     uint16_t icacBufLen = static_cast<uint16_t>(std::min(icac.size(), static_cast<size_t>(UINT16_MAX)));
     277            2 :     PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsIntermediateCertificateStorage, key,
     278              :                       err = mStorage->SyncGetKeyValue(key, icac.data(), icacBufLen));
     279              :     // Always regenerate ICAC on maximally sized certs. The keys remain the same, so everything is fine.
     280            2 :     if (mUseMaximallySizedCerts)
     281              :     {
     282            1 :         err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
     283              :     }
     284            2 :     if (err == CHIP_NO_ERROR)
     285              :     {
     286              :         uint64_t icacId;
     287              :         // Found intermediate certificate in the storage.
     288            0 :         icac.reduce_size(icacBufLen);
     289            0 :         ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(icac, icac_dn));
     290            0 :         ReturnErrorOnFailure(icac_dn.GetCertChipId(icacId));
     291            0 :         VerifyOrReturnError(icacId == mIntermediateIssuerId, CHIP_ERROR_INTERNAL);
     292              :     }
     293              :     // If intermediate certificate not found in the storage, generate new intermediate certificate.
     294              :     else
     295              :     {
     296            2 :         ReturnErrorOnFailure(icac_dn.AddAttribute_MatterICACId(mIntermediateIssuerId));
     297              : 
     298            2 :         ChipLogProgress(Controller, "Generating ICAC");
     299            2 :         ReturnErrorOnFailure(IssueX509Cert(mNow, mValidity, rcac_dn, icac_dn, CertType::kIcac, mUseMaximallySizedCerts,
     300              :                                            mIntermediateIssuer.Pubkey(), mRootIssuer, icac));
     301            2 :         VerifyOrReturnError(CanCastTo<uint16_t>(icac.size()), CHIP_ERROR_INTERNAL);
     302              : 
     303              :         // Re-extract DN based on final generated cert
     304            2 :         icac_dn = ChipDN{};
     305            2 :         ReturnErrorOnFailure(ExtractSubjectDNFromX509Cert(icac, icac_dn));
     306              : 
     307            2 :         PERSISTENT_KEY_OP(mIndex, kOperationalCredentialsIntermediateCertificateStorage, key,
     308              :                           ReturnErrorOnFailure(mStorage->SyncSetKeyValue(key, icac.data(), static_cast<uint16_t>(icac.size()))));
     309              :     }
     310              : 
     311            2 :     ChipDN noc_dn;
     312            2 :     ReturnErrorOnFailure(noc_dn.AddAttribute_MatterFabricId(fabricId));
     313            2 :     ReturnErrorOnFailure(noc_dn.AddAttribute_MatterNodeId(nodeId));
     314            2 :     ReturnErrorOnFailure(noc_dn.AddCATs(cats));
     315              : 
     316            2 :     ChipLogProgress(Controller, "Generating NOC");
     317            2 :     if (mAlwaysOmitIcac)
     318              :     {
     319            0 :         icac.reduce_size(0);
     320            0 :         err = IssueX509Cert(mNow, mValidity, rcac_dn, noc_dn, CertType::kNoc, mUseMaximallySizedCerts, pubkey, mRootIssuer, noc);
     321              :     }
     322              :     else
     323              :     {
     324            2 :         err = IssueX509Cert(mNow, mValidity, icac_dn, noc_dn, CertType::kNoc, mUseMaximallySizedCerts, pubkey, mIntermediateIssuer,
     325              :                             noc);
     326              :     }
     327              : 
     328            2 :     if (err != CHIP_NO_ERROR)
     329              :     {
     330            0 :         ChipLogError(Controller, "Failed to Generate NOC: %" CHIP_ERROR_FORMAT, err.Format());
     331              :     }
     332            2 :     return err;
     333            2 : }
     334              : 
     335            0 : CHIP_ERROR ExampleOperationalCredentialsIssuer::GenerateNOCChain(const ByteSpan & csrElements, const ByteSpan & csrNonce,
     336              :                                                                  const ByteSpan & attestationSignature,
     337              :                                                                  const ByteSpan & attestationChallenge, const ByteSpan & DAC,
     338              :                                                                  const ByteSpan & PAI,
     339              :                                                                  Callback::Callback<OnNOCChainGeneration> * onCompletion)
     340              : {
     341            0 :     VerifyOrReturnError(mInitialized, CHIP_ERROR_UNINITIALIZED);
     342              :     // At this point, Credential issuer may wish to validate the CSR information
     343              :     (void) attestationChallenge;
     344              :     (void) csrNonce;
     345              : 
     346              :     NodeId assignedId;
     347            0 :     if (mNodeIdRequested)
     348              :     {
     349            0 :         assignedId       = mNextRequestedNodeId;
     350            0 :         mNodeIdRequested = false;
     351              :     }
     352              :     else
     353              :     {
     354            0 :         assignedId = mNextAvailableNodeId++;
     355              :     }
     356              : 
     357            0 :     ChipLogProgress(Controller, "Verifying Certificate Signing Request");
     358            0 :     TLVReader reader;
     359            0 :     reader.Init(csrElements);
     360              : 
     361            0 :     if (reader.GetType() == kTLVType_NotSpecified)
     362              :     {
     363            0 :         ReturnErrorOnFailure(reader.Next());
     364              :     }
     365              : 
     366            0 :     ReturnErrorOnFailure(reader.Expect(kTLVType_Structure, AnonymousTag()));
     367              : 
     368              :     TLVType containerType;
     369            0 :     ReturnErrorOnFailure(reader.EnterContainer(containerType));
     370            0 :     ReturnErrorOnFailure(reader.Next(kTLVType_ByteString, TLV::ContextTag(1)));
     371              : 
     372            0 :     ByteSpan csr(reader.GetReadPoint(), reader.GetLength());
     373            0 :     reader.ExitContainer(containerType);
     374              : 
     375            0 :     P256PublicKey pubkey;
     376            0 :     ReturnErrorOnFailure(VerifyCertificateSigningRequest(csr.data(), csr.size(), pubkey));
     377              : 
     378            0 :     chip::Platform::ScopedMemoryBuffer<uint8_t> noc;
     379            0 :     VerifyOrReturnError(noc.Alloc(kMaxDERCertLength), CHIP_ERROR_NO_MEMORY);
     380            0 :     MutableByteSpan nocSpan(noc.Get(), kMaxDERCertLength);
     381              : 
     382            0 :     chip::Platform::ScopedMemoryBuffer<uint8_t> icac;
     383            0 :     VerifyOrReturnError(icac.Alloc(kMaxDERCertLength), CHIP_ERROR_NO_MEMORY);
     384            0 :     MutableByteSpan icacSpan(icac.Get(), kMaxDERCertLength);
     385              : 
     386            0 :     chip::Platform::ScopedMemoryBuffer<uint8_t> rcac;
     387            0 :     VerifyOrReturnError(rcac.Alloc(kMaxDERCertLength), CHIP_ERROR_NO_MEMORY);
     388            0 :     MutableByteSpan rcacSpan(rcac.Get(), kMaxDERCertLength);
     389              : 
     390            0 :     ReturnErrorOnFailure(
     391              :         GenerateNOCChainAfterValidation(assignedId, mNextFabricId, mNextCATs, pubkey, rcacSpan, icacSpan, nocSpan));
     392              : 
     393              :     // TODO(#13825): Should always generate some IPK. Using a temporary fixed value until APIs are plumbed in to set it end-to-end
     394              :     // TODO: Force callers to set IPK if used before GenerateNOCChain will succeed.
     395            0 :     ByteSpan defaultIpkSpan = chip::GroupTesting::DefaultIpkValue::GetDefaultIpk();
     396              : 
     397              :     // The below static assert validates a key assumption in types used (needed for public API conformance)
     398              :     static_assert(CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES == kAES_CCM128_Key_Length, "IPK span sizing must match");
     399              : 
     400              :     // Prepare IPK to be sent back. A more fully-fledged operational credentials delegate
     401              :     // would obtain a suitable key per fabric.
     402              :     uint8_t ipkValue[CHIP_CRYPTO_SYMMETRIC_KEY_LENGTH_BYTES];
     403            0 :     Crypto::IdentityProtectionKeySpan ipkSpan(ipkValue);
     404              : 
     405            0 :     VerifyOrReturnError(defaultIpkSpan.size() == sizeof(ipkValue), CHIP_ERROR_INTERNAL);
     406            0 :     memcpy(&ipkValue[0], defaultIpkSpan.data(), defaultIpkSpan.size());
     407              : 
     408              :     // Callback onto commissioner.
     409            0 :     ChipLogProgress(Controller, "Providing certificate chain to the commissioner");
     410            0 :     onCompletion->mCall(onCompletion->mContext, CHIP_NO_ERROR, nocSpan, icacSpan, rcacSpan, MakeOptional(ipkSpan),
     411            0 :                         Optional<NodeId>());
     412            0 :     return CHIP_NO_ERROR;
     413            0 : }
     414              : 
     415            3 : CHIP_ERROR ExampleOperationalCredentialsIssuer::GetRandomOperationalNodeId(NodeId * aNodeId)
     416              : {
     417            3 :     for (int i = 0; i < 10; ++i)
     418              :     {
     419            3 :         CHIP_ERROR err = DRBG_get_bytes(reinterpret_cast<uint8_t *>(aNodeId), sizeof(*aNodeId));
     420            3 :         if (err != CHIP_NO_ERROR)
     421              :         {
     422            3 :             return err;
     423              :         }
     424              : 
     425            3 :         if (IsOperationalNodeId(*aNodeId))
     426              :         {
     427            3 :             return CHIP_NO_ERROR;
     428              :         }
     429              :     }
     430              : 
     431              :     // Terrible, universe-ending luck (chances are 1 in 2^280 or so here, if our
     432              :     // DRBG is good).
     433            0 :     return CHIP_ERROR_INTERNAL;
     434              : }
     435              : 
     436              : } // namespace Controller
     437              : } // namespace chip
        

Generated by: LCOV version 2.0-1