Matter SDK Coverage Report
Current view: top level - controller - ExampleOperationalCredentialsIssuer.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 0.0 % 194 0
Test Date: 2025-01-17 19:00:11 Functions: 0.0 % 5 0

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

Generated by: LCOV version 2.0-1