LCOV - code coverage report
Current view: top level - controller - ExampleOperationalCredentialsIssuer.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 0 193 0.0 %
Date: 2024-02-15 08:20:41 Functions: 0 5 0.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 :     ReturnErrorCodeIf(!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 :         ReturnErrorCodeIf(!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 :         ReturnErrorCodeIf(!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 :         ReturnErrorCodeIf(!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             :     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 :     ReturnErrorCodeIf(!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 :     ReturnErrorCodeIf(!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 :     ReturnErrorCodeIf(!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 :     ReturnErrorCodeIf(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 1.14