Matter SDK Coverage Report
Current view: top level - credentials - CHIPCert.cpp (source / functions) Coverage Total Hit
Test: SHA:09f6fdf93a7e847a42518c076e487f336877a722 Lines: 95.6 % 707 676
Test Date: 2025-06-07 07:10:33 Functions: 92.8 % 69 64

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2022 Project CHIP Authors
       4              :  *    Copyright (c) 2019 Google LLC.
       5              :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       6              :  *    All rights reserved.
       7              :  *
       8              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       9              :  *    you may not use this file except in compliance with the License.
      10              :  *    You may obtain a copy of the License at
      11              :  *
      12              :  *        http://www.apache.org/licenses/LICENSE-2.0
      13              :  *
      14              :  *    Unless required by applicable law or agreed to in writing, software
      15              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      16              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      17              :  *    See the License for the specific language governing permissions and
      18              :  *    limitations under the License.
      19              :  */
      20              : 
      21              : /**
      22              :  *    @file
      23              :  *      This file implements objects for modeling and working with
      24              :  *      CHIP certificates.
      25              :  *
      26              :  */
      27              : 
      28              : #include <stddef.h>
      29              : 
      30              : #include <credentials/CHIPCert_Internal.h>
      31              : #include <credentials/CHIPCertificateSet.h>
      32              : #include <lib/asn1/ASN1.h>
      33              : #include <lib/asn1/ASN1Macros.h>
      34              : #include <lib/core/CHIPCore.h>
      35              : #include <lib/core/CHIPSafeCasts.h>
      36              : #include <lib/core/TLV.h>
      37              : #include <lib/support/BytesToHex.h>
      38              : #include <lib/support/CHIPMem.h>
      39              : #include <lib/support/CodeUtils.h>
      40              : #include <lib/support/SafeInt.h>
      41              : #include <lib/support/ScopedBuffer.h>
      42              : #include <lib/support/TimeUtils.h>
      43              : #include <protocols/Protocols.h>
      44              : 
      45              : namespace chip {
      46              : namespace Credentials {
      47              : 
      48              : using namespace chip::ASN1;
      49              : using namespace chip::TLV;
      50              : using namespace chip::Protocols;
      51              : using namespace chip::Crypto;
      52              : 
      53          931 : ChipCertificateSet::ChipCertificateSet()
      54              : {
      55          931 :     mCerts               = nullptr;
      56          931 :     mCertCount           = 0;
      57          931 :     mMaxCerts            = 0;
      58          931 :     mMemoryAllocInternal = false;
      59          931 : }
      60              : 
      61          931 : ChipCertificateSet::~ChipCertificateSet()
      62              : {
      63          931 :     Release();
      64          931 : }
      65              : 
      66          863 : CHIP_ERROR ChipCertificateSet::Init(uint8_t maxCertsArraySize)
      67              : {
      68          863 :     CHIP_ERROR err = CHIP_NO_ERROR;
      69              : 
      70          863 :     VerifyOrExit(maxCertsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
      71          863 :     mCerts = reinterpret_cast<ChipCertificateData *>(chip::Platform::MemoryAlloc(sizeof(ChipCertificateData) * maxCertsArraySize));
      72          863 :     VerifyOrExit(mCerts != nullptr, err = CHIP_ERROR_NO_MEMORY);
      73              : 
      74          863 :     mMaxCerts            = maxCertsArraySize;
      75          863 :     mMemoryAllocInternal = true;
      76              : 
      77          863 :     Clear();
      78              : 
      79          863 : exit:
      80          863 :     if (err != CHIP_NO_ERROR)
      81              :     {
      82            0 :         Release();
      83              :     }
      84              : 
      85          863 :     return err;
      86              : }
      87              : 
      88          126 : CHIP_ERROR ChipCertificateSet::Init(ChipCertificateData * certsArray, uint8_t certsArraySize)
      89              : {
      90          126 :     CHIP_ERROR err = CHIP_NO_ERROR;
      91              : 
      92          126 :     VerifyOrExit(certsArray != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
      93          126 :     VerifyOrExit(certsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
      94              : 
      95          126 :     mCerts               = certsArray;
      96          126 :     mMaxCerts            = certsArraySize;
      97          126 :     mMemoryAllocInternal = false;
      98              : 
      99          126 :     Clear();
     100              : 
     101          126 : exit:
     102          126 :     return err;
     103              : }
     104              : 
     105          997 : void ChipCertificateSet::Release()
     106              : {
     107          997 :     if (mMemoryAllocInternal)
     108              :     {
     109          870 :         if (mCerts != nullptr)
     110              :         {
     111          863 :             Clear();
     112          863 :             chip::Platform::MemoryFree(mCerts);
     113          863 :             mCerts = nullptr;
     114              :         }
     115              :     }
     116          997 : }
     117              : 
     118         1904 : void ChipCertificateSet::Clear()
     119              : {
     120         7458 :     for (int i = 0; i < mMaxCerts; i++)
     121              :     {
     122         5554 :         mCerts[i].Clear();
     123              :     }
     124              : 
     125         1904 :     mCertCount = 0;
     126         1904 : }
     127              : 
     128         2640 : CHIP_ERROR ChipCertificateSet::LoadCert(const ByteSpan chipCert, BitFlags<CertDecodeFlags> decodeFlags)
     129              : {
     130         2640 :     TLVReader reader;
     131              : 
     132         2640 :     reader.Init(chipCert);
     133         2640 :     return LoadCert(reader, decodeFlags, chipCert);
     134              : }
     135              : 
     136         2640 : CHIP_ERROR ChipCertificateSet::LoadCert(TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags, ByteSpan chipCert)
     137              : {
     138         2640 :     ChipCertificateData cert;
     139         2640 :     ReturnErrorOnFailure(DecodeChipCert(reader, cert, decodeFlags));
     140              : 
     141              :     // Verify the cert has both the Subject Key Id and Authority Key Id extensions present.
     142              :     // Only certs with both these extensions are supported for the purposes of certificate validation.
     143         2557 :     VerifyOrReturnError(cert.mCertFlags.HasAll(CertFlags::kExtPresent_SubjectKeyId, CertFlags::kExtPresent_AuthKeyId),
     144              :                         CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
     145              : 
     146              :     // Verify the cert was signed with ECDSA-SHA256. This is the only signature algorithm currently supported.
     147         2551 :     VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
     148              : 
     149              :     // Check if this cert matches any currently loaded certificates
     150         4941 :     for (uint32_t i = 0; i < mCertCount; i++)
     151              :     {
     152         2392 :         if (cert.IsEqual(mCerts[i]))
     153              :         {
     154              :             // This cert is already loaded. Let's skip adding this cert.
     155            2 :             return CHIP_NO_ERROR;
     156              :         }
     157              :     }
     158              : 
     159              :     // Verify we have room for the new certificate.
     160         2549 :     VerifyOrReturnError(mCertCount < mMaxCerts, CHIP_ERROR_NO_MEMORY);
     161              : 
     162         2549 :     new (&mCerts[mCertCount]) ChipCertificateData(cert);
     163         2549 :     mCertCount++;
     164              : 
     165         2549 :     return CHIP_NO_ERROR;
     166         2640 : }
     167              : 
     168            0 : CHIP_ERROR ChipCertificateSet::ReleaseLastCert()
     169              : {
     170            0 :     ChipCertificateData * lastCert = (mCertCount > 0) ? &mCerts[mCertCount - 1] : nullptr;
     171            0 :     VerifyOrReturnError(lastCert != nullptr, CHIP_ERROR_INTERNAL);
     172              : 
     173            0 :     lastCert->~ChipCertificateData();
     174            0 :     --mCertCount;
     175              : 
     176            0 :     return CHIP_NO_ERROR;
     177              : }
     178              : 
     179            0 : const ChipCertificateData * ChipCertificateSet::FindCert(const CertificateKeyId & subjectKeyId) const
     180              : {
     181            0 :     for (uint8_t i = 0; i < mCertCount; i++)
     182              :     {
     183            0 :         ChipCertificateData & cert = mCerts[i];
     184            0 :         if (cert.mSubjectKeyId.data_equal(subjectKeyId))
     185              :         {
     186            0 :             return &cert;
     187              :         }
     188              :     }
     189              : 
     190            0 :     return nullptr;
     191              : }
     192              : 
     193          134 : bool ChipCertificateSet::IsCertInTheSet(const ChipCertificateData * cert) const
     194              : {
     195          376 :     for (uint8_t i = 0; i < mCertCount; i++)
     196              :     {
     197          376 :         if (cert == &mCerts[i])
     198              :         {
     199          134 :             return true;
     200              :         }
     201              :     }
     202              : 
     203            0 :     return false;
     204              : }
     205              : 
     206          134 : CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context)
     207              : {
     208          134 :     VerifyOrReturnError(IsCertInTheSet(cert), CHIP_ERROR_INVALID_ARGUMENT);
     209              : 
     210          134 :     context.mTrustAnchor = nullptr;
     211              : 
     212          134 :     return ValidateCert(cert, context, 0);
     213              : }
     214              : 
     215          808 : CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
     216              :                                              ValidationContext & context, const ChipCertificateData ** certData)
     217              : {
     218          808 :     context.mTrustAnchor = nullptr;
     219              : 
     220          808 :     return FindValidCert(subjectDN, subjectKeyId, context, 0, certData);
     221              : }
     222              : 
     223            0 : CHIP_ERROR ChipCertificateSet::VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert)
     224              : {
     225            0 :     VerifyOrReturnError((cert != nullptr) && (caCert != nullptr), CHIP_ERROR_INVALID_ARGUMENT);
     226            0 :     return VerifyCertSignature(*cert, *caCert);
     227              : }
     228              : 
     229         1674 : CHIP_ERROR VerifyCertSignature(const ChipCertificateData & cert, const ChipCertificateData & signer)
     230              : {
     231         1674 :     VerifyOrReturnError(cert.mCertFlags.Has(CertFlags::kTBSHashPresent), CHIP_ERROR_INVALID_ARGUMENT);
     232         1673 :     VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
     233              : 
     234              : #ifdef ENABLE_HSM_ECDSA_VERIFY
     235              :     P256PublicKeyHSM signerPublicKey;
     236              : #else
     237         1673 :     P256PublicKey signerPublicKey;
     238              : #endif
     239         1673 :     P256ECDSASignature signature;
     240              : 
     241         1673 :     ReturnErrorOnFailure(signature.SetLength(cert.mSignature.size()));
     242         1673 :     memcpy(signature.Bytes(), cert.mSignature.data(), cert.mSignature.size());
     243              : 
     244         1673 :     memcpy(signerPublicKey, signer.mPublicKey.data(), signer.mPublicKey.size());
     245              : 
     246         1673 :     ReturnErrorOnFailure(
     247              :         signerPublicKey.ECDSA_validate_hash_signature(cert.mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature));
     248              : 
     249         1670 :     return CHIP_NO_ERROR;
     250         1673 : }
     251              : 
     252         2615 : CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context, uint8_t depth)
     253              : {
     254         2615 :     CHIP_ERROR err                     = CHIP_NO_ERROR;
     255         2615 :     const ChipCertificateData * caCert = nullptr;
     256              :     CertType certType;
     257              : 
     258         2615 :     err = cert->mSubjectDN.GetCertType(certType);
     259         2615 :     SuccessOrExit(err);
     260              : 
     261              :     // Certificate with future-extension marked as "critical" is not allowed.
     262         2615 :     VerifyOrExit(!cert->mCertFlags.Has(CertFlags::kExtPresent_FutureIsCritical), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
     263              : 
     264              :     // If the depth is greater than 0 then the certificate is required to be a CA certificate...
     265         2614 :     if (depth > 0)
     266              :     {
     267              :         // Verify the isCA flag is present.
     268         1673 :         VerifyOrExit(cert->mCertFlags.Has(CertFlags::kIsCA), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
     269              : 
     270              :         // Verify the key usage extension is present and contains the 'keyCertSign' flag.
     271         1672 :         VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && cert->mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign),
     272              :                      err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
     273              : 
     274              :         // Verify that the certificate type is set to Root or ICA.
     275         1670 :         VerifyOrExit(certType == CertType::kICA || certType == CertType::kRoot, err = CHIP_ERROR_WRONG_CERT_TYPE);
     276              : 
     277              :         // If a path length constraint was included, verify the cert depth vs. the specified constraint.
     278              :         //
     279              :         // From the RFC, the path length constraint "gives the maximum number of non-self-issued
     280              :         // intermediate certificates that may follow this certificate in a valid certification path.
     281              :         // (Note: The last certificate in the certification path is not an intermediate certificate,
     282              :         // and is not included in this limit...)"
     283              :         //
     284         1670 :         if (cert->mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
     285              :         {
     286           23 :             VerifyOrExit((depth - 1) <= cert->mPathLenConstraint, err = CHIP_ERROR_CERT_PATH_LEN_CONSTRAINT_EXCEEDED);
     287              :         }
     288              :     }
     289              : 
     290              :     // Otherwise verify the desired certificate usages/purposes/type given in the validation context...
     291              :     else
     292              :     {
     293              :         // If a set of desired key usages has been specified, verify that the key usage extension exists
     294              :         // in the certificate and that the corresponding usages are supported.
     295          941 :         if (context.mRequiredKeyUsages.HasAny())
     296              :         {
     297          923 :             VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) &&
     298              :                              cert->mKeyUsageFlags.HasAll(context.mRequiredKeyUsages),
     299              :                          err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
     300              :         }
     301              : 
     302              :         // If a set of desired key purposes has been specified, verify that the extended key usage extension
     303              :         // exists in the certificate and that the corresponding purposes are supported.
     304          909 :         if (context.mRequiredKeyPurposes.HasAny())
     305              :         {
     306          905 :             VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) &&
     307              :                              cert->mKeyPurposeFlags.HasAll(context.mRequiredKeyPurposes),
     308              :                          err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
     309              :         }
     310              : 
     311              :         // If a required certificate type has been specified, verify it against the current certificate's type.
     312          893 :         if (context.mRequiredCertType != CertType::kNotSpecified)
     313              :         {
     314            2 :             VerifyOrExit(certType == context.mRequiredCertType, err = CHIP_ERROR_WRONG_CERT_TYPE);
     315              :         }
     316              :     }
     317              : 
     318              :     // Verify NotBefore and NotAfter validity of the certificates.
     319              :     //
     320              :     // See also ASN1ToChipEpochTime().
     321              :     //
     322              :     // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no
     323              :     // well-defined expiration date'.  In CHIP TLV-encoded certificates, this
     324              :     // special value is represented as a CHIP Epoch time value of 0 sec
     325              :     // (2000-01-01 00:00:00 UTC).
     326              :     CertificateValidityResult validityResult;
     327         2561 :     if (context.mEffectiveTime.Is<CurrentChipEpochTime>())
     328              :     {
     329          198 :         if (context.mEffectiveTime.Get<CurrentChipEpochTime>().count() < cert->mNotBeforeTime)
     330              :         {
     331           13 :             ChipLogDetail(SecureChannel, "Certificate's mNotBeforeTime (%" PRIu32 ") is after current time (%" PRIu32 ")",
     332              :                           cert->mNotBeforeTime, context.mEffectiveTime.Get<CurrentChipEpochTime>().count());
     333           13 :             validityResult = CertificateValidityResult::kNotYetValid;
     334              :         }
     335          370 :         else if (cert->mNotAfterTime != kNullCertTime &&
     336          185 :                  context.mEffectiveTime.Get<CurrentChipEpochTime>().count() > cert->mNotAfterTime)
     337              :         {
     338           13 :             ChipLogDetail(SecureChannel, "Certificate's mNotAfterTime (%" PRIu32 ") is before current time (%" PRIu32 ")",
     339              :                           cert->mNotAfterTime, context.mEffectiveTime.Get<CurrentChipEpochTime>().count());
     340           13 :             validityResult = CertificateValidityResult::kExpired;
     341              :         }
     342              :         else
     343              :         {
     344          172 :             validityResult = CertificateValidityResult::kValid;
     345              :         }
     346              :     }
     347         2363 :     else if (context.mEffectiveTime.Is<LastKnownGoodChipEpochTime>())
     348              :     {
     349              :         // Last Known Good Time may not be moved forward except at the time of
     350              :         // commissioning or firmware update, so we can't use it to validate
     351              :         // NotBefore.  However, so long as firmware build times are properly
     352              :         // recorded and certificates loaded during commissioning are in fact
     353              :         // valid at the time of commissioning, observing a NotAfter that falls
     354              :         // before Last Known Good Time is a reliable indicator that the
     355              :         // certificate in question is expired.  Check for this.
     356           87 :         if (cert->mNotAfterTime != 0 && context.mEffectiveTime.Get<LastKnownGoodChipEpochTime>().count() > cert->mNotAfterTime)
     357              :         {
     358           19 :             ChipLogDetail(SecureChannel, "Certificate's mNotAfterTime (%" PRIu32 ") is before last known good time (%" PRIu32 ")",
     359              :                           cert->mNotAfterTime, context.mEffectiveTime.Get<LastKnownGoodChipEpochTime>().count());
     360           19 :             validityResult = CertificateValidityResult::kExpiredAtLastKnownGoodTime;
     361              :         }
     362              :         else
     363              :         {
     364           68 :             validityResult = CertificateValidityResult::kNotExpiredAtLastKnownGoodTime;
     365              :         }
     366              :     }
     367              :     else
     368              :     {
     369         2276 :         validityResult = CertificateValidityResult::kTimeUnknown;
     370              :     }
     371              : 
     372         2561 :     if (context.mValidityPolicy != nullptr)
     373              :     {
     374         2372 :         SuccessOrExit(err = context.mValidityPolicy->ApplyCertificateValidityPolicy(cert, depth, validityResult));
     375              :     }
     376              :     else
     377              :     {
     378          189 :         SuccessOrExit(err = CertificateValidityPolicy::ApplyDefaultPolicy(cert, depth, validityResult));
     379              :     }
     380              : 
     381              :     // If the certificate itself is trusted, then it is implicitly valid.  Record this certificate as the trust
     382              :     // anchor and return success.
     383         2528 :     if (cert->mCertFlags.Has(CertFlags::kIsTrustAnchor))
     384              :     {
     385          846 :         context.mTrustAnchor = cert;
     386          846 :         ExitNow(err = CHIP_NO_ERROR);
     387              :     }
     388              : 
     389              :     // Otherwise we must validate the certificate by looking for a chain of valid certificates up to a trusted
     390              :     // certificate known as the 'trust anchor'.
     391              : 
     392              :     // Fail validation if the certificate is self-signed. Since we don't trust this certificate (see the check above) and
     393              :     // it has no path we can follow to a trust anchor, it can't be considered valid.
     394         1682 :     if (cert->mIssuerDN.IsEqual(cert->mSubjectDN) && cert->mAuthKeyId.data_equal(cert->mSubjectKeyId))
     395              :     {
     396            2 :         ExitNow(err = CHIP_ERROR_CERT_NOT_TRUSTED);
     397              :     }
     398              : 
     399              :     // Verify that the certificate depth is less than the total number of certificates. It is technically possible to create
     400              :     // a circular chain of certificates.  Limiting the maximum depth of the certificate path prevents infinite
     401              :     // recursion in such a case.
     402         1680 :     VerifyOrExit(depth < mCertCount, err = CHIP_ERROR_CERT_PATH_TOO_LONG);
     403              : 
     404              :     // Search for a valid CA certificate that matches the Issuer DN and Authority Key Id of the current certificate.
     405              :     // Fail if no acceptable certificate is found.
     406         1680 :     err = FindValidCert(cert->mIssuerDN, cert->mAuthKeyId, context, static_cast<uint8_t>(depth + 1), &caCert);
     407         1680 :     if (err != CHIP_NO_ERROR)
     408              :     {
     409           18 :         ChipLogError(SecureChannel, "Failed to find valid cert during chain traversal: %" CHIP_ERROR_FORMAT, err.Format());
     410           18 :         ExitNow(err = CHIP_ERROR_CA_CERT_NOT_FOUND);
     411              :     }
     412              : 
     413              :     // Verify signature of the current certificate against public key of the CA certificate. If signature verification
     414              :     // succeeds, the current certificate is valid.
     415         1662 :     err = VerifyCertSignature(*cert, *caCert);
     416         1662 :     SuccessOrExit(err);
     417              : 
     418         2615 : exit:
     419         2615 :     return err;
     420              : }
     421              : 
     422         2488 : CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
     423              :                                              ValidationContext & context, uint8_t depth, const ChipCertificateData ** certData)
     424              : {
     425              :     CHIP_ERROR err;
     426              : 
     427         2488 :     *certData = nullptr;
     428              : 
     429              :     // Default error if we don't find any matching cert.
     430         2488 :     err = (depth > 0) ? CHIP_ERROR_CA_CERT_NOT_FOUND : CHIP_ERROR_CERT_NOT_FOUND;
     431              : 
     432              :     // For each cert in the set...
     433         4966 :     for (uint8_t i = 0; i < mCertCount; i++)
     434              :     {
     435         4932 :         ChipCertificateData * candidateCert = &mCerts[i];
     436              : 
     437              :         // Skip the certificate if its subject DN and key id do not match the input criteria.
     438         4932 :         if (!candidateCert->mSubjectDN.IsEqual(subjectDN))
     439              :         {
     440         2447 :             continue;
     441              :         }
     442         2485 :         if (!candidateCert->mSubjectKeyId.data_equal(subjectKeyId))
     443              :         {
     444            4 :             continue;
     445              :         }
     446              : 
     447              :         // Attempt to validate the cert.  If the cert is valid, return it to the caller. Otherwise,
     448              :         // save the returned error and continue searching.  If there are no other matching certs this
     449              :         // will be the error returned to the caller.
     450         2481 :         err = ValidateCert(candidateCert, context, depth);
     451         2481 :         if (err == CHIP_NO_ERROR)
     452              :         {
     453         2454 :             *certData = candidateCert;
     454         2454 :             ExitNow();
     455              :         }
     456              :     }
     457              : 
     458           34 : exit:
     459         2488 :     return err;
     460              : }
     461              : 
     462         3150 : ChipCertificateData::ChipCertificateData() {}
     463              : 
     464         3150 : ChipCertificateData::~ChipCertificateData() {}
     465              : 
     466         8603 : void ChipCertificateData::Clear()
     467              : {
     468         8603 :     mSerialNumber = ByteSpan();
     469         8603 :     mSubjectDN.Clear();
     470         8603 :     mIssuerDN.Clear();
     471         8603 :     mSubjectKeyId      = CertificateKeyId();
     472         8603 :     mAuthKeyId         = CertificateKeyId();
     473         8603 :     mNotBeforeTime     = 0;
     474         8603 :     mNotAfterTime      = 0;
     475         8603 :     mPublicKey         = P256PublicKeySpan();
     476         8603 :     mPubKeyCurveOID    = 0;
     477         8603 :     mPubKeyAlgoOID     = 0;
     478         8603 :     mSigAlgoOID        = 0;
     479         8603 :     mPathLenConstraint = 0;
     480         8603 :     mCertFlags.ClearAll();
     481         8603 :     mKeyUsageFlags.ClearAll();
     482         8603 :     mKeyPurposeFlags.ClearAll();
     483         8603 :     mSignature = P256ECDSASignatureSpan();
     484              : 
     485         8603 :     memset(mTBSHash, 0, sizeof(mTBSHash));
     486         8603 : }
     487              : 
     488         2392 : bool ChipCertificateData::IsEqual(const ChipCertificateData & other) const
     489              : {
     490              :     // TODO - Add an operator== on BitFlags class.
     491         2398 :     return mSubjectDN.IsEqual(other.mSubjectDN) && mIssuerDN.IsEqual(other.mIssuerDN) &&
     492            6 :         mSubjectKeyId.data_equal(other.mSubjectKeyId) && mAuthKeyId.data_equal(other.mAuthKeyId) &&
     493            6 :         (mNotBeforeTime == other.mNotBeforeTime) && (mNotAfterTime == other.mNotAfterTime) &&
     494            6 :         mPublicKey.data_equal(other.mPublicKey) && (mPubKeyCurveOID == other.mPubKeyCurveOID) &&
     495            6 :         (mPubKeyAlgoOID == other.mPubKeyAlgoOID) && (mSigAlgoOID == other.mSigAlgoOID) &&
     496            7 :         (mCertFlags.Raw() == other.mCertFlags.Raw()) && (mKeyUsageFlags.Raw() == other.mKeyUsageFlags.Raw()) &&
     497            6 :         (mKeyPurposeFlags.Raw() == other.mKeyPurposeFlags.Raw()) && (mPathLenConstraint == other.mPathLenConstraint) &&
     498         2397 :         mSignature.data_equal(other.mSignature) && (memcmp(mTBSHash, other.mTBSHash, sizeof(mTBSHash)) == 0);
     499              : }
     500              : 
     501          883 : void ValidationContext::Reset()
     502              : {
     503          883 :     mEffectiveTime  = EffectiveTime{};
     504          883 :     mTrustAnchor    = nullptr;
     505          883 :     mValidityPolicy = nullptr;
     506          883 :     mRequiredKeyUsages.ClearAll();
     507          883 :     mRequiredKeyPurposes.ClearAll();
     508          883 :     mRequiredCertType = CertType::kNotSpecified;
     509          883 : }
     510              : 
     511         5996 : bool ChipRDN::IsEqual(const ChipRDN & other) const
     512              : {
     513         5996 :     if (mAttrOID == kOID_Unknown || mAttrOID == kOID_NotSpecified || mAttrOID != other.mAttrOID ||
     514         4196 :         mAttrIsPrintableString != other.mAttrIsPrintableString)
     515              :     {
     516         1800 :         return false;
     517              :     }
     518              : 
     519         4196 :     if (IsChipDNAttr(mAttrOID))
     520              :     {
     521         4182 :         return mChipVal == other.mChipVal;
     522              :     }
     523              : 
     524           14 :     return mString.data_equal(other.mString);
     525              : }
     526              : 
     527        40788 : ChipDN::ChipDN()
     528              : {
     529         6798 :     Clear();
     530         6798 : }
     531              : 
     532         7029 : ChipDN::~ChipDN() {}
     533              : 
     534        24034 : void ChipDN::Clear()
     535              : {
     536       144204 :     for (auto & dn : rdn)
     537              :     {
     538       120170 :         dn.Clear();
     539              :     }
     540        24034 : }
     541              : 
     542        44458 : uint8_t ChipDN::RDNCount() const
     543              : {
     544              :     uint8_t count;
     545              : 
     546       104923 :     for (count = 0; count < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES; count++)
     547              :     {
     548       104776 :         if (rdn[count].IsEmpty())
     549              :         {
     550        44311 :             break;
     551              :         }
     552              :     }
     553              : 
     554        44458 :     return count;
     555              : }
     556              : 
     557        10358 : CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, uint64_t val)
     558              : {
     559        10358 :     uint8_t rdnCount = RDNCount();
     560              : 
     561        10358 :     VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
     562        10358 :     VerifyOrReturnError(IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);
     563              : 
     564        10358 :     if (IsChip32bitDNAttr(oid))
     565              :     {
     566          132 :         VerifyOrReturnError(CanCastTo<uint32_t>(val), CHIP_ERROR_INVALID_ARGUMENT);
     567              :     }
     568              : 
     569        10358 :     rdn[rdnCount].mAttrOID               = oid;
     570        10358 :     rdn[rdnCount].mChipVal               = val;
     571        10358 :     rdn[rdnCount].mAttrIsPrintableString = false;
     572              : 
     573        10358 :     return CHIP_NO_ERROR;
     574              : }
     575              : 
     576            3 : CHIP_ERROR ChipDN::AddCATs(const chip::CATValues & cats)
     577              : {
     578            3 :     VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_INVALID_ARGUMENT);
     579              : 
     580           12 :     for (auto & cat : cats.values)
     581              :     {
     582            9 :         if (cat != kUndefinedCAT)
     583              :         {
     584            1 :             ReturnErrorOnFailure(AddAttribute_MatterCASEAuthTag(cat));
     585              :         }
     586              :     }
     587              : 
     588            3 :     return CHIP_NO_ERROR;
     589              : }
     590              : 
     591          152 : CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, CharSpan val, bool isPrintableString)
     592              : {
     593          152 :     uint8_t rdnCount = RDNCount();
     594              : 
     595          152 :     VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
     596          151 :     VerifyOrReturnError(!IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);
     597          151 :     VerifyOrReturnError(oid != kOID_NotSpecified, CHIP_ERROR_INVALID_ARGUMENT);
     598              : 
     599          151 :     rdn[rdnCount].mAttrOID               = oid;
     600          151 :     rdn[rdnCount].mString                = val;
     601          151 :     rdn[rdnCount].mAttrIsPrintableString = isPrintableString;
     602              : 
     603          151 :     return CHIP_NO_ERROR;
     604              : }
     605              : 
     606         3134 : CHIP_ERROR ChipDN::GetCertType(CertType & certType) const
     607              : {
     608         3134 :     CertType lCertType   = CertType::kNotSpecified;
     609         3134 :     bool fabricIdPresent = false;
     610         3134 :     bool catsPresent     = false;
     611         3134 :     uint8_t rdnCount     = RDNCount();
     612              : 
     613         3143 :     if (rdnCount == 1 && rdn[0].mAttrOID == kOID_AttributeType_CommonName && !rdn[0].mAttrIsPrintableString &&
     614            9 :         rdn[0].mString.data_equal(kNetworkIdentityCN))
     615              :     {
     616            9 :         certType = CertType::kNetworkIdentity;
     617            9 :         return CHIP_NO_ERROR;
     618              :     }
     619              : 
     620         3125 :     certType = CertType::kNotSpecified;
     621              : 
     622         8288 :     for (uint8_t i = 0; i < rdnCount; i++)
     623              :     {
     624         5175 :         if (rdn[i].mAttrOID == kOID_AttributeType_MatterRCACId)
     625              :         {
     626         1008 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     627              : 
     628         1006 :             lCertType = CertType::kRoot;
     629              :         }
     630         4167 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterICACId)
     631              :         {
     632          985 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     633              : 
     634          983 :             lCertType = CertType::kICA;
     635              :         }
     636         3182 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterVidVerificationSignerId)
     637              :         {
     638            9 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     639              : 
     640            9 :             lCertType = CertType::kVidVerificationSigner;
     641              :         }
     642         3173 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterNodeId)
     643              :         {
     644         1115 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     645         1113 :             VerifyOrReturnError(IsOperationalNodeId(rdn[i].mChipVal), CHIP_ERROR_WRONG_NODE_ID);
     646         1113 :             lCertType = CertType::kNode;
     647              :         }
     648         2058 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFirmwareSigningId)
     649              :         {
     650            2 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     651              : 
     652            2 :             lCertType = CertType::kFirmwareSigning;
     653              :         }
     654         2056 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFabricId)
     655              :         {
     656              :             // Only one fabricId attribute is allowed per DN.
     657         1983 :             VerifyOrReturnError(!fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
     658         1977 :             VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
     659         1977 :             fabricIdPresent = true;
     660              :         }
     661           73 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterCASEAuthTag)
     662              :         {
     663           41 :             VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
     664           41 :             VerifyOrReturnError(IsValidCASEAuthTag(static_cast<CASEAuthTag>(rdn[i].mChipVal)), CHIP_ERROR_WRONG_CERT_DN);
     665           41 :             catsPresent = true;
     666              :         }
     667              :     }
     668              : 
     669         3113 :     if (lCertType == CertType::kNode)
     670              :     {
     671         1109 :         VerifyOrReturnError(fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
     672              :     }
     673              :     else
     674              :     {
     675         2004 :         VerifyOrReturnError(!catsPresent, CHIP_ERROR_WRONG_CERT_DN);
     676              :     }
     677              : 
     678         3106 :     if (lCertType == CertType::kVidVerificationSigner)
     679              :     {
     680            9 :         VerifyOrReturnError(!fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
     681              :         // Lack of NodeID already checked since presence of NodeID will be detected as CertType::kNode.
     682              :     }
     683              : 
     684         3106 :     certType = lCertType;
     685              : 
     686         3106 :     return CHIP_NO_ERROR;
     687              : }
     688              : 
     689           13 : CHIP_ERROR ChipDN::GetCertChipId(uint64_t & chipId) const
     690              : {
     691           13 :     uint8_t rdnCount = RDNCount();
     692           13 :     bool foundId     = false;
     693              : 
     694           13 :     chipId = 0;
     695              : 
     696           38 :     for (uint8_t i = 0; i < rdnCount; i++)
     697              :     {
     698           25 :         switch (rdn[i].mAttrOID)
     699              :         {
     700           12 :         case kOID_AttributeType_MatterRCACId:
     701              :         case kOID_AttributeType_MatterICACId:
     702              :         case kOID_AttributeType_MatterNodeId:
     703              :         case kOID_AttributeType_MatterFirmwareSigningId:
     704              :         case kOID_AttributeType_MatterVidVerificationSignerId:
     705           12 :             VerifyOrReturnError(!foundId, CHIP_ERROR_WRONG_CERT_DN);
     706              : 
     707           12 :             chipId  = rdn[i].mChipVal;
     708           12 :             foundId = true;
     709           12 :             break;
     710           13 :         default:
     711           13 :             break;
     712              :         }
     713              :     }
     714              : 
     715           13 :     VerifyOrReturnError(foundId, CHIP_ERROR_WRONG_CERT_DN);
     716           12 :     return CHIP_NO_ERROR;
     717              : }
     718              : 
     719            1 : CHIP_ERROR ChipDN::GetCertFabricId(uint64_t & fabricId) const
     720              : {
     721            1 :     uint8_t rdnCount = RDNCount();
     722              : 
     723            1 :     fabricId = kUndefinedFabricId;
     724              : 
     725            6 :     for (uint8_t i = 0; i < rdnCount; i++)
     726              :     {
     727            5 :         switch (rdn[i].mAttrOID)
     728              :         {
     729            1 :         case kOID_AttributeType_MatterFabricId:
     730              :             // Ensure only one FabricID RDN present, since start value is kUndefinedFabricId, which is reserved and never seen.
     731            1 :             VerifyOrReturnError(fabricId == kUndefinedFabricId, CHIP_ERROR_WRONG_CERT_DN);
     732            1 :             VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
     733            1 :             fabricId = rdn[i].mChipVal;
     734            1 :             break;
     735            4 :         default:
     736            4 :             break;
     737              :         }
     738              :     }
     739              : 
     740            1 :     VerifyOrReturnError(IsValidFabricId(fabricId), CHIP_ERROR_WRONG_CERT_DN);
     741            1 :     return CHIP_NO_ERROR;
     742              : }
     743              : 
     744          308 : CHIP_ERROR ChipDN::EncodeToTLV(TLVWriter & writer, Tag tag) const
     745              : {
     746              :     TLVType outerContainer;
     747          308 :     uint8_t rdnCount = RDNCount();
     748              : 
     749          308 :     ReturnErrorOnFailure(writer.StartContainer(tag, kTLVType_List, outerContainer));
     750              : 
     751          803 :     for (uint8_t i = 0; i < rdnCount; i++)
     752              :     {
     753              :         // Derive the TLV tag number from the enum value assigned to the attribute type OID. For attributes that can be
     754              :         // either UTF8String or PrintableString, use the high bit in the tag number to distinguish the two.
     755          496 :         uint8_t tlvTagNum = GetOIDEnum(rdn[i].mAttrOID);
     756          496 :         if (rdn[i].mAttrIsPrintableString)
     757              :         {
     758            3 :             tlvTagNum |= 0x80;
     759              :         }
     760              : 
     761          496 :         if (IsChipDNAttr(rdn[i].mAttrOID))
     762              :         {
     763          469 :             ReturnErrorOnFailure(writer.Put(ContextTag(tlvTagNum), rdn[i].mChipVal));
     764              :         }
     765              :         else
     766              :         {
     767           27 :             ReturnErrorOnFailure(writer.PutString(ContextTag(tlvTagNum), rdn[i].mString));
     768              :         }
     769              :     }
     770              : 
     771          307 :     return writer.EndContainer(outerContainer);
     772              : }
     773              : 
     774         5992 : CHIP_ERROR ChipDN::DecodeFromTLV(TLVReader & reader)
     775              : {
     776              :     CHIP_ERROR err;
     777              :     TLVType outerContainer;
     778              : 
     779              :     static constexpr uint32_t kOID_AttributeIsPrintableString_Flag = 0x00000080;
     780              :     static constexpr uint32_t kOID_AttributeType_Mask              = 0x0000007F;
     781              : 
     782         5992 :     VerifyOrReturnError(reader.GetType() == kTLVType_List, CHIP_ERROR_WRONG_TLV_TYPE);
     783              : 
     784              :     // Enter the List TLV element that represents the DN in TLV format.
     785         5992 :     ReturnErrorOnFailure(reader.EnterContainer(outerContainer));
     786              : 
     787              :     // Read the RDN attributes in the List.
     788        15741 :     while ((err = reader.Next()) == CHIP_NO_ERROR)
     789              :     {
     790              :         // Get the TLV tag, make sure it is a context tag and extract the context tag number.
     791         9770 :         Tag tlvTag = reader.GetTag();
     792         9791 :         VerifyOrReturnError(IsContextTag(tlvTag), CHIP_ERROR_INVALID_TLV_TAG);
     793         9770 :         uint32_t tlvTagNum = TagNumFromTag(tlvTag);
     794              : 
     795              :         // Derive the OID of the corresponding ASN.1 attribute from the TLV tag number.
     796              :         // The numeric value of the OID is encoded in the bottom 7 bits of the TLV tag number.
     797              :         // This eliminates the need for a translation table/switch statement but has the
     798              :         // effect of tying the two encodings together.
     799              :         //
     800              :         // NOTE: In the event that the computed OID value is not one that we recognize
     801              :         // (specifically, is not in the table of OIDs defined in ASN1OID.h) then the
     802              :         // macro call below that encodes the attribute's object id (ASN1_ENCODE_OBJECT_ID)
     803              :         // will fail for lack of the OID's encoded representation.  Given this there's no
     804              :         // need to test the validity of the OID here.
     805              :         //
     806         9770 :         OID attrOID = GetOID(kOIDCategory_AttributeType, static_cast<uint8_t>(tlvTagNum & kOID_AttributeType_Mask));
     807              : 
     808         9770 :         bool attrIsPrintableString = (tlvTagNum & kOID_AttributeIsPrintableString_Flag) == kOID_AttributeIsPrintableString_Flag;
     809              : 
     810              :         // For 64-bit CHIP-defined DN attributes.
     811         9770 :         if (IsChip64bitDNAttr(attrOID))
     812              :         {
     813              :             uint64_t chipAttr;
     814         9560 :             VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
     815         9549 :             ReturnErrorOnFailure(reader.Get(chipAttr));
     816         9549 :             if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
     817              :             {
     818         1090 :                 VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
     819              :             }
     820         8459 :             else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
     821              :             {
     822         3584 :                 VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
     823              :             }
     824         9538 :             ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     825              :         }
     826              :         // For 32-bit CHIP-defined DN attributes.
     827          221 :         else if (IsChip32bitDNAttr(attrOID))
     828              :         {
     829              :             uint32_t chipAttr;
     830          134 :             VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
     831          124 :             ReturnErrorOnFailure(reader.Get(chipAttr));
     832          124 :             if (attrOID == chip::ASN1::kOID_AttributeType_MatterCASEAuthTag)
     833              :             {
     834          124 :                 VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
     835              :             }
     836          114 :             ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     837              :         }
     838              :         // Otherwise the attribute is one of the supported X.509 attributes
     839              :         else
     840              :         {
     841           97 :             CharSpan asn1Attr;
     842           97 :             ReturnErrorOnFailure(reader.Get(asn1Attr));
     843           97 :             ReturnErrorOnFailure(AddAttribute(attrOID, asn1Attr, attrIsPrintableString));
     844              :         }
     845              :     }
     846         5971 :     VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
     847         5971 :     ReturnErrorOnFailure(reader.ExitContainer(outerContainer));
     848              : 
     849         5971 :     return CHIP_NO_ERROR;
     850              : }
     851              : 
     852         6401 : CHIP_ERROR ChipDN::EncodeToASN1(ASN1Writer & writer) const
     853              : {
     854         6401 :     CHIP_ERROR err   = CHIP_NO_ERROR;
     855         6401 :     uint8_t rdnCount = RDNCount();
     856              : 
     857         6401 :     ASN1_START_SEQUENCE
     858              :     {
     859        16780 :         for (uint8_t i = 0; i < rdnCount; i++)
     860              :         {
     861        10380 :             ASN1_START_SET
     862              :             {
     863              :                 char chipAttrStr[kChip64bitAttrUTF8Length];
     864        10380 :                 CharSpan asn1Attr;
     865              :                 uint8_t asn1Tag;
     866        10380 :                 chip::ASN1::OID attrOID = rdn[i].mAttrOID;
     867              : 
     868        10380 :                 if (IsChip64bitDNAttr(attrOID))
     869              :                 {
     870        10136 :                     ReturnErrorOnFailure(
     871              :                         Encoding::Uint64ToHex(rdn[i].mChipVal, chipAttrStr, sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
     872        10136 :                     asn1Attr = CharSpan(chipAttrStr, kChip64bitAttrUTF8Length);
     873        10136 :                     asn1Tag  = kASN1UniversalTag_UTF8String;
     874              :                 }
     875          244 :                 else if (IsChip32bitDNAttr(attrOID))
     876              :                 {
     877          121 :                     ReturnErrorOnFailure(Encoding::Uint32ToHex(static_cast<uint32_t>(rdn[i].mChipVal), chipAttrStr,
     878              :                                                                sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
     879          121 :                     asn1Attr = CharSpan(chipAttrStr, kChip32bitAttrUTF8Length);
     880          121 :                     asn1Tag  = kASN1UniversalTag_UTF8String;
     881              :                 }
     882              :                 else
     883              :                 {
     884          123 :                     asn1Attr = rdn[i].mString;
     885              : 
     886              :                     // Determine the appropriate ASN.1 tag for the DN attribute.
     887              :                     // - DomainComponent is always an IA5String.
     888              :                     // - For all other ASN.1 defined attributes, bit 0x80 in the TLV tag value conveys whether the attribute
     889              :                     //   is a UTF8String or a PrintableString (in some cases the certificate generator has a choice).
     890          123 :                     if (attrOID == kOID_AttributeType_DomainComponent)
     891              :                     {
     892            0 :                         asn1Tag = kASN1UniversalTag_IA5String;
     893              :                     }
     894              :                     else
     895              :                     {
     896          123 :                         asn1Tag = rdn[i].mAttrIsPrintableString ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String;
     897              :                     }
     898              :                 }
     899              : 
     900              :                 // AttributeTypeAndValue ::= SEQUENCE
     901        10380 :                 ASN1_START_SEQUENCE
     902              :                 {
     903              :                     // type AttributeType
     904              :                     // AttributeType ::= OBJECT IDENTIFIER
     905        10380 :                     ASN1_ENCODE_OBJECT_ID(attrOID);
     906              : 
     907        10380 :                     VerifyOrReturnError(CanCastTo<uint16_t>(asn1Attr.size()), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
     908              : 
     909              :                     // value AttributeValue
     910              :                     // AttributeValue ::= ANY -- DEFINED BY AttributeType
     911        10380 :                     ReturnErrorOnFailure(writer.PutString(asn1Tag, asn1Attr.data(), static_cast<uint16_t>(asn1Attr.size())));
     912              :                 }
     913        10379 :                 ASN1_END_SEQUENCE;
     914              :             }
     915        10379 :             ASN1_END_SET;
     916              :         }
     917              :     }
     918         6400 :     ASN1_END_SEQUENCE;
     919              : 
     920         6400 : exit:
     921         6400 :     return err;
     922              : }
     923              : 
     924          325 : CHIP_ERROR ChipDN::DecodeFromASN1(ASN1Reader & reader)
     925              : {
     926              :     CHIP_ERROR err;
     927              : 
     928              :     // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
     929          325 :     ASN1_PARSE_ENTER_SEQUENCE
     930              :     {
     931          844 :         while ((err = reader.Next()) == CHIP_NO_ERROR)
     932              :         {
     933              :             // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
     934          526 :             ASN1_ENTER_SET
     935              :             {
     936              :                 // AttributeTypeAndValue ::= SEQUENCE
     937          526 :                 ASN1_PARSE_ENTER_SEQUENCE
     938              :                 {
     939              :                     // type AttributeType
     940              :                     // AttributeType ::= OBJECT IDENTIFIER
     941              :                     OID attrOID;
     942          526 :                     ASN1_PARSE_OBJECT_ID(attrOID);
     943          533 :                     VerifyOrReturnError(GetOIDCategory(attrOID) == kOIDCategory_AttributeType, ASN1_ERROR_INVALID_ENCODING);
     944              : 
     945              :                     // AttributeValue ::= ANY -- DEFINED BY AttributeType
     946          526 :                     ASN1_PARSE_ANY;
     947              : 
     948          526 :                     uint8_t attrTag = reader.GetTag();
     949              : 
     950              :                     // Can only support UTF8String, PrintableString and IA5String.
     951          526 :                     VerifyOrReturnError(reader.GetClass() == kASN1TagClass_Universal &&
     952              :                                             (attrTag == kASN1UniversalTag_PrintableString ||
     953              :                                              attrTag == kASN1UniversalTag_UTF8String || attrTag == kASN1UniversalTag_IA5String),
     954              :                                         ASN1_ERROR_UNSUPPORTED_ENCODING);
     955              : 
     956              :                     // CHIP attributes must be UTF8Strings.
     957          526 :                     if (IsChipDNAttr(attrOID))
     958              :                     {
     959          497 :                         VerifyOrReturnError(attrTag == kASN1UniversalTag_UTF8String, ASN1_ERROR_INVALID_ENCODING);
     960              :                     }
     961              : 
     962              :                     // If 64-bit CHIP attribute.
     963          526 :                     if (IsChip64bitDNAttr(attrOID))
     964              :                     {
     965              :                         uint64_t chipAttr;
     966          488 :                         VerifyOrReturnError(Encoding::UppercaseHexToUint64(reinterpret_cast<const char *>(reader.GetValue()),
     967              :                                                                            static_cast<size_t>(reader.GetValueLen()),
     968              :                                                                            chipAttr) == sizeof(uint64_t),
     969              :                                             ASN1_ERROR_INVALID_ENCODING);
     970              : 
     971          484 :                         if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
     972              :                         {
     973           67 :                             VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
     974              :                         }
     975          417 :                         else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
     976              :                         {
     977          165 :                             VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_WRONG_CERT_DN);
     978              :                         }
     979              : 
     980          480 :                         ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     981              :                     }
     982              :                     // If 32-bit CHIP attribute.
     983           42 :                     else if (IsChip32bitDNAttr(attrOID))
     984              :                     {
     985              :                         CASEAuthTag chipAttr;
     986           16 :                         VerifyOrReturnError(Encoding::UppercaseHexToUint32(reinterpret_cast<const char *>(reader.GetValue()),
     987              :                                                                            reader.GetValueLen(), chipAttr) == sizeof(CASEAuthTag),
     988              :                                             ASN1_ERROR_INVALID_ENCODING);
     989              : 
     990           13 :                         VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_WRONG_CERT_DN);
     991              : 
     992           10 :                         ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     993              :                     }
     994              :                     // Otherwise, it is a string.
     995              :                     else
     996              :                     {
     997           29 :                         ReturnErrorOnFailure(AddAttribute(attrOID,
     998              :                                                           CharSpan(Uint8::to_const_char(reader.GetValue()), reader.GetValueLen()),
     999              :                                                           attrTag == kASN1UniversalTag_PrintableString));
    1000              :                     }
    1001              :                 }
    1002          519 :                 ASN1_EXIT_SEQUENCE;
    1003              : 
    1004              :                 // Only one AttributeTypeAndValue allowed per RDN.
    1005          519 :                 err = reader.Next();
    1006          519 :                 VerifyOrReturnError(err != CHIP_NO_ERROR, ASN1_ERROR_UNSUPPORTED_ENCODING);
    1007          519 :                 VerifyOrReturnError(err == ASN1_END, err);
    1008              :             }
    1009          519 :             ASN1_EXIT_SET;
    1010              :         }
    1011              :     }
    1012          318 :     ASN1_EXIT_SEQUENCE;
    1013              : 
    1014          318 : exit:
    1015          318 :     return err;
    1016              : }
    1017              : 
    1018         9067 : bool ChipDN::IsEqual(const ChipDN & other) const
    1019              : {
    1020         9067 :     bool res         = true;
    1021         9067 :     uint8_t rdnCount = RDNCount();
    1022              : 
    1023         9067 :     VerifyOrExit(rdnCount > 0, res = false);
    1024         9067 :     VerifyOrExit(rdnCount == other.RDNCount(), res = false);
    1025              : 
    1026         8546 :     for (uint8_t i = 0; i < rdnCount; i++)
    1027              :     {
    1028         5996 :         VerifyOrExit(rdn[i].IsEqual(other.rdn[i]), res = false);
    1029              :     }
    1030              : 
    1031         2550 : exit:
    1032         9067 :     return res;
    1033              : }
    1034              : 
    1035          445 : DLL_EXPORT CHIP_ERROR ASN1ToChipEpochTime(const chip::ASN1::ASN1UniversalTime & asn1Time, uint32_t & epochTime)
    1036              : {
    1037          445 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1038              :     // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    1039              :     // In CHIP certificate it is represented as a CHIP Epoch time value of 0 sec (2000-01-01 00:00:00 UTC).
    1040              :     //
    1041              :     // While it is not conventional to use this special value for NotBefore, for simplicity we convert all
    1042              :     // time values of 99991231235959Z to CHIP epoch zero seconds.  ChipEpochToASN1Time performs the inverse
    1043              :     // translation for conversions in the other direction.
    1044              :     //
    1045              :     // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses 99991231235959Z
    1046              :     // for NotBefore, this will be converted to the CHIP Epoch time value of 0 and consuming code will
    1047              :     // handle this transparently, as logic considering a NotBefore time at the CHIP epoch will evaluate all
    1048              :     // possible unsigned offsets from the CHIP epoch as valid, which is equivalent to ignoring NotBefore.
    1049              :     //
    1050              :     // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses a NotBefore time
    1051              :     // at the CHIP epoch itself, 2000-01-01 00:00:00, a resultant conversion to CHIP TLV certificate format
    1052              :     // will appear to have an invalid TBS signature when the symmetric ChipEpochToASN1Time produces
    1053              :     // 99991231235959Z for NotBefore during signature validation.
    1054              :     //
    1055              :     // Thus such certificates, when passing through this code, will not appear valid.  This should be
    1056              :     // immediately evident at commissioning time.
    1057          445 :     if ((asn1Time.Year == kX509NoWellDefinedExpirationDateYear) && (asn1Time.Month == kMonthsPerYear) &&
    1058            4 :         (asn1Time.Day == kMaxDaysPerMonth) && (asn1Time.Hour == kHoursPerDay - 1) && (asn1Time.Minute == kMinutesPerHour - 1) &&
    1059            4 :         (asn1Time.Second == kSecondsPerMinute - 1))
    1060              :     {
    1061            4 :         epochTime = kNullCertTime;
    1062              :     }
    1063              :     else
    1064              :     {
    1065          441 :         if (!CalendarToChipEpochTime(asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute, asn1Time.Second,
    1066              :                                      epochTime))
    1067              :         {
    1068            0 :             ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
    1069              :         }
    1070              :     }
    1071              : 
    1072          441 : exit:
    1073          445 :     return err;
    1074              : }
    1075              : 
    1076         6417 : DLL_EXPORT CHIP_ERROR ChipEpochToASN1Time(uint32_t epochTime, chip::ASN1::ASN1UniversalTime & asn1Time)
    1077              : {
    1078              :     // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    1079              :     // In CHIP certificate it is represented as a CHIP Epoch time value of 0 secs (2000-01-01 00:00:00 UTC).
    1080              :     //
    1081              :     // For simplicity and symmetry with ASN1ToChipEpochTime, this method makes this conversion for all
    1082              :     // times, which in consuming code can create a conversion from CHIP epoch 0 seconds to 99991231235959Z
    1083              :     // for NotBefore, which is not conventional.
    1084              :     //
    1085              :     // If an original X509 certificate encloses a NotBefore time that is the CHIP Epoch itself, 2000-01-01
    1086              :     // 00:00:00, the resultant X509 certificate in a conversion back from CHIP TLV format using this time
    1087              :     // conversion method will instead enclose the NotBefore time 99991231235959Z, which will invalidiate the
    1088              :     // TBS signature.  Thus, certificates with this specific attribute are not usable with this code.
    1089              :     // Attempted installation of such certficates will fail during commissioning.
    1090         6417 :     if (epochTime == kNullCertTime)
    1091              :     {
    1092           19 :         asn1Time.Year   = kX509NoWellDefinedExpirationDateYear;
    1093           19 :         asn1Time.Month  = kMonthsPerYear;
    1094           19 :         asn1Time.Day    = kMaxDaysPerMonth;
    1095           19 :         asn1Time.Hour   = kHoursPerDay - 1;
    1096           19 :         asn1Time.Minute = kMinutesPerHour - 1;
    1097           19 :         asn1Time.Second = kSecondsPerMinute - 1;
    1098              :     }
    1099              :     else
    1100              :     {
    1101         6398 :         ChipEpochToCalendarTime(epochTime, asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute,
    1102         6398 :                                 asn1Time.Second);
    1103              :     }
    1104              : 
    1105         6417 :     return CHIP_NO_ERROR;
    1106              : }
    1107              : 
    1108           52 : static CHIP_ERROR ValidateCertificateType(const ChipCertificateData & certData, CertType expectedType)
    1109              : {
    1110              :     CertType certType;
    1111           52 :     ReturnErrorOnFailure(certData.mSubjectDN.GetCertType(certType));
    1112           44 :     VerifyOrReturnError(certType == expectedType, CHIP_ERROR_WRONG_CERT_TYPE);
    1113           18 :     return CHIP_NO_ERROR;
    1114              : }
    1115              : 
    1116           92 : CHIP_ERROR ValidateChipRCAC(const ByteSpan & rcac)
    1117              : {
    1118           92 :     ChipCertificateSet certSet;
    1119           92 :     ChipCertificateData certData;
    1120           92 :     ValidationContext validContext;
    1121              : 
    1122              :     // Note that this function doesn't check RCAC NotBefore / NotAfter time validity.
    1123              :     // It is assumed that RCAC should be valid at the time of installation by definition.
    1124              : 
    1125           92 :     ReturnErrorOnFailure(certSet.Init(&certData, 1));
    1126              : 
    1127           92 :     ReturnErrorOnFailure(certSet.LoadCert(rcac, CertDecodeFlags::kGenerateTBSHash));
    1128              : 
    1129           44 :     ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kRoot));
    1130              : 
    1131           10 :     VerifyOrReturnError(certData.mSubjectDN.IsEqual(certData.mIssuerDN), CHIP_ERROR_WRONG_CERT_TYPE);
    1132              : 
    1133           10 :     VerifyOrReturnError(certData.mSubjectKeyId.data_equal(certData.mAuthKeyId), CHIP_ERROR_WRONG_CERT_TYPE);
    1134              : 
    1135            9 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kIsCA), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    1136            7 :     if (certData.mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
    1137              :     {
    1138            1 :         VerifyOrReturnError(certData.mPathLenConstraint <= 1, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    1139              :     }
    1140              : 
    1141            7 :     VerifyOrReturnError(certData.mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    1142              : 
    1143            5 :     return VerifyCertSignature(certData, certData);
    1144           92 : }
    1145              : 
    1146          240 : CHIP_ERROR ConvertIntegerDERToRaw(ByteSpan derInt, uint8_t * rawInt, const uint16_t rawIntLen)
    1147              : {
    1148          240 :     VerifyOrReturnError(!derInt.empty(), CHIP_ERROR_INVALID_ARGUMENT);
    1149          240 :     VerifyOrReturnError(rawInt != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1150              : 
    1151          240 :     const uint8_t * derIntData = derInt.data();
    1152          240 :     size_t derIntLen           = derInt.size();
    1153              : 
    1154              :     /* one leading zero is allowed for positive integer in ASN1 DER format */
    1155          240 :     if (*derIntData == 0)
    1156              :     {
    1157          129 :         derIntData++;
    1158          129 :         derIntLen--;
    1159              :     }
    1160              : 
    1161          240 :     VerifyOrReturnError(derIntLen <= rawIntLen, CHIP_ERROR_INVALID_ARGUMENT);
    1162              : 
    1163          240 :     if (derIntLen > 0)
    1164              :     {
    1165          240 :         VerifyOrReturnError(*derIntData != 0, CHIP_ERROR_INVALID_ARGUMENT);
    1166              :     }
    1167              : 
    1168          240 :     memset(rawInt, 0, (rawIntLen - derIntLen));
    1169          240 :     memcpy(rawInt + (rawIntLen - derIntLen), derIntData, derIntLen);
    1170              : 
    1171          240 :     return CHIP_NO_ERROR;
    1172              : }
    1173              : 
    1174            0 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, MutableByteSpan & derSig)
    1175              : {
    1176            0 :     VerifyOrReturnError(derSig.size() >= kMax_ECDSA_Signature_Length_Der, CHIP_ERROR_BUFFER_TOO_SMALL);
    1177              : 
    1178              :     ASN1Writer writer;
    1179            0 :     writer.Init(derSig);
    1180            0 :     ReturnErrorOnFailure(ConvertECDSASignatureRawToDER(rawSig, writer));
    1181            0 :     derSig.reduce_size(writer.GetLengthWritten());
    1182              : 
    1183            0 :     return CHIP_NO_ERROR;
    1184              : }
    1185              : 
    1186          125 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, ASN1Writer & writer)
    1187              : {
    1188          125 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1189              :     uint8_t derInt[kP256_FE_Length + kEmitDerIntegerWithoutTagOverhead];
    1190              : 
    1191              :     // Ecdsa-Sig-Value ::= SEQUENCE
    1192          125 :     ASN1_START_SEQUENCE
    1193              :     {
    1194              :         // r INTEGER
    1195              :         {
    1196          125 :             MutableByteSpan derIntSpan(derInt, sizeof(derInt));
    1197          125 :             ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data()), derIntSpan));
    1198          125 :             ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
    1199              :                                                  static_cast<uint16_t>(derIntSpan.size())));
    1200              :         }
    1201              : 
    1202              :         // s INTEGER
    1203              :         {
    1204          125 :             MutableByteSpan derIntSpan(derInt, sizeof(derInt));
    1205          125 :             ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data() + kP256_FE_Length), derIntSpan));
    1206          125 :             ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
    1207              :                                                  static_cast<uint16_t>(derIntSpan.size())));
    1208              :         }
    1209              :     }
    1210          125 :     ASN1_END_SEQUENCE;
    1211              : 
    1212          125 : exit:
    1213          125 :     return err;
    1214              : }
    1215              : 
    1216            1 : CHIP_ERROR ConvertECDSAKeypairRawToDER(const P256SerializedKeypair & rawKeypair, MutableByteSpan & outDerKeypair)
    1217              : {
    1218            1 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1219              : 
    1220              :     // The raw key pair contains the public key followed by the private key
    1221            1 :     VerifyOrReturnError(rawKeypair.Length() == kP256_PublicKey_Length + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT);
    1222            1 :     FixedByteSpan<kP256_PublicKey_Length> publicKey(rawKeypair.ConstBytes());
    1223            1 :     FixedByteSpan<kP256_PrivateKey_Length> privateKey(rawKeypair.ConstBytes() + kP256_PublicKey_Length);
    1224              : 
    1225              :     ASN1Writer writer;
    1226            1 :     writer.Init(outDerKeypair);
    1227              : 
    1228              :     // ECPrivateKey ::= SEQUENCE
    1229            1 :     ASN1_START_SEQUENCE
    1230              :     {
    1231              :         // version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1)
    1232            1 :         ASN1_ENCODE_INTEGER(1);
    1233              : 
    1234              :         // privateKey OCTET STRING
    1235            1 :         ASN1_ENCODE_OCTET_STRING(privateKey.data(), privateKey.size());
    1236              : 
    1237              :         // parameters [0] ECParameters {{ NamedCurve }} OPTIONAL
    1238            1 :         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0);
    1239              :         {
    1240            1 :             ASN1_ENCODE_OBJECT_ID(kOID_EllipticCurve_prime256v1);
    1241              :         }
    1242            1 :         ASN1_END_CONSTRUCTED;
    1243              : 
    1244              :         // publicKey  [1] BIT STRING OPTIONAL
    1245            1 :         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 1);
    1246              :         {
    1247            1 :             ReturnErrorOnFailure(writer.PutBitString(0, publicKey.data(), publicKey.size()));
    1248              :         }
    1249            1 :         ASN1_END_CONSTRUCTED;
    1250              :     }
    1251            1 :     ASN1_END_SEQUENCE;
    1252              : 
    1253            1 :     outDerKeypair.reduce_size(writer.GetLengthWritten());
    1254            1 : exit:
    1255            1 :     return err;
    1256              : }
    1257              : 
    1258          889 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ChipCertificateData & opcert, NodeId * outNodeId, FabricId * outFabricId)
    1259              : {
    1260              :     // Since we assume the cert is pre-validated, we are going to assume that
    1261              :     // its subject in fact has both a node id and a fabric id.
    1262          889 :     VerifyOrReturnError(outNodeId != nullptr && outFabricId != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1263          889 :     NodeId nodeId      = 0;
    1264          889 :     FabricId fabricId  = kUndefinedFabricId;
    1265          889 :     bool foundNodeId   = false;
    1266          889 :     bool foundFabricId = false;
    1267              : 
    1268          889 :     const ChipDN & subjectDN = opcert.mSubjectDN;
    1269         2711 :     for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    1270              :     {
    1271         1822 :         const auto & rdn = subjectDN.rdn[i];
    1272         1822 :         if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterNodeId)
    1273              :         {
    1274          889 :             nodeId      = rdn.mChipVal;
    1275          889 :             foundNodeId = true;
    1276              :         }
    1277          933 :         else if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
    1278              :         {
    1279          889 :             fabricId      = rdn.mChipVal;
    1280          889 :             foundFabricId = true;
    1281              :         }
    1282              :     }
    1283          889 :     if (!foundNodeId || !foundFabricId)
    1284              :     {
    1285            0 :         return CHIP_ERROR_NOT_FOUND;
    1286              :     }
    1287              : 
    1288          889 :     *outNodeId   = nodeId;
    1289          889 :     *outFabricId = fabricId;
    1290          889 :     return CHIP_NO_ERROR;
    1291              : }
    1292              : 
    1293           10 : CHIP_ERROR ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
    1294              :                                                               FabricId & fabricId, NodeId & nodeId)
    1295              : {
    1296           10 :     Crypto::P256PublicKey rootPubKey;
    1297           10 :     Credentials::P256PublicKeySpan rootPubKeySpan;
    1298           10 :     ReturnErrorOnFailure(ExtractPublicKeyFromChipCert(rcac, rootPubKeySpan));
    1299           10 :     rootPubKey = Crypto::P256PublicKey(rootPubKeySpan);
    1300           10 :     ReturnErrorOnFailure(Credentials::ExtractNodeIdFabricIdFromOpCert(noc, &nodeId, &fabricId));
    1301           10 :     ReturnErrorOnFailure(GenerateCompressedFabricId(rootPubKey, fabricId, compressedFabricId));
    1302           10 :     return CHIP_NO_ERROR;
    1303           10 : }
    1304              : 
    1305            0 : CHIP_ERROR ExtractNodeIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
    1306              :                                                       NodeId & nodeId)
    1307              : {
    1308              :     FabricId fabricId;
    1309            0 :     ReturnErrorOnFailure(ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(rcac, noc, compressedFabricId, fabricId, nodeId));
    1310            0 :     return CHIP_NO_ERROR;
    1311              : }
    1312              : 
    1313         1545 : CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId * fabricId)
    1314              : {
    1315         1545 :     const ChipDN & subjectDN = cert.mSubjectDN;
    1316         3078 :     for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    1317              :     {
    1318         2274 :         const auto & rdn = subjectDN.rdn[i];
    1319         2274 :         if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
    1320              :         {
    1321          741 :             *fabricId = rdn.mChipVal;
    1322          741 :             return CHIP_NO_ERROR;
    1323              :         }
    1324              :     }
    1325              : 
    1326          804 :     return CHIP_ERROR_NOT_FOUND;
    1327              : }
    1328              : 
    1329           33 : CHIP_ERROR ExtractCATsFromOpCert(const ByteSpan & opcert, CATValues & cats)
    1330              : {
    1331           33 :     ChipCertificateSet certSet;
    1332           33 :     ChipCertificateData certData;
    1333              : 
    1334           33 :     ReturnErrorOnFailure(certSet.Init(&certData, 1));
    1335              : 
    1336           33 :     ReturnErrorOnFailure(certSet.LoadCert(opcert, BitFlags<CertDecodeFlags>()));
    1337              : 
    1338           32 :     return ExtractCATsFromOpCert(certData, cats);
    1339           33 : }
    1340              : 
    1341           43 : CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, CATValues & cats)
    1342              : {
    1343           43 :     uint8_t catCount = 0;
    1344              :     CertType certType;
    1345              : 
    1346           43 :     ReturnErrorOnFailure(opcert.mSubjectDN.GetCertType(certType));
    1347           43 :     VerifyOrReturnError(certType == CertType::kNode, CHIP_ERROR_INVALID_ARGUMENT);
    1348              : 
    1349           42 :     const ChipDN & subjectDN = opcert.mSubjectDN;
    1350          150 :     for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    1351              :     {
    1352          108 :         const auto & rdn = subjectDN.rdn[i];
    1353          108 :         if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterCASEAuthTag)
    1354              :         {
    1355              :             // This error should never happen in practice because valid NOC cannot have more
    1356              :             // than kMaxSubjectCATAttributeCount CATs in its subject. The check that it is
    1357              :             // valid NOC was done above.
    1358           18 :             VerifyOrReturnError(catCount != cats.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
    1359           18 :             VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn.mChipVal), CHIP_ERROR_INVALID_ARGUMENT);
    1360           18 :             cats.values[catCount++] = static_cast<CASEAuthTag>(rdn.mChipVal);
    1361              :         }
    1362              :     }
    1363          150 :     for (size_t i = catCount; i < cats.size(); ++i)
    1364              :     {
    1365          108 :         cats.values[i] = kUndefinedCAT;
    1366              :     }
    1367              : 
    1368              :     // Make sure the set contained valid data, otherwise it's an invalid cert
    1369           42 :     VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_WRONG_CERT_DN);
    1370              : 
    1371           41 :     return CHIP_NO_ERROR;
    1372              : }
    1373              : 
    1374           11 : CHIP_ERROR ExtractFabricIdFromCert(const ByteSpan & opcert, FabricId * fabricId)
    1375              : {
    1376           11 :     ChipCertificateData certData;
    1377           11 :     ReturnErrorOnFailure(DecodeChipCert(opcert, certData));
    1378           11 :     return ExtractFabricIdFromCert(certData, fabricId);
    1379           11 : }
    1380              : 
    1381          106 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ByteSpan & opcert, NodeId * nodeId, FabricId * fabricId)
    1382              : {
    1383          106 :     ChipCertificateData certData;
    1384          106 :     ReturnErrorOnFailure(DecodeChipCert(opcert, certData));
    1385          106 :     return ExtractNodeIdFabricIdFromOpCert(certData, nodeId, fabricId);
    1386          106 : }
    1387              : 
    1388          103 : CHIP_ERROR ExtractPublicKeyFromChipCert(const ByteSpan & chipCert, P256PublicKeySpan & publicKey)
    1389              : {
    1390          103 :     ChipCertificateData certData;
    1391          103 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1392          103 :     publicKey = certData.mPublicKey;
    1393          103 :     return CHIP_NO_ERROR;
    1394          103 : }
    1395              : 
    1396           24 : CHIP_ERROR ExtractNotBeforeFromChipCert(const ByteSpan & chipCert, chip::System::Clock::Seconds32 & notBeforeChipEpochTime)
    1397              : {
    1398           24 :     ChipCertificateData certData;
    1399           24 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1400           24 :     notBeforeChipEpochTime = chip::System::Clock::Seconds32(certData.mNotBeforeTime);
    1401           24 :     return CHIP_NO_ERROR;
    1402           24 : }
    1403              : 
    1404           16 : CHIP_ERROR ExtractSKIDFromChipCert(const ByteSpan & chipCert, CertificateKeyId & skid)
    1405              : {
    1406           16 :     ChipCertificateData certData;
    1407           16 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1408           16 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_AuthKeyId), CHIP_ERROR_NOT_FOUND);
    1409           15 :     skid = certData.mSubjectKeyId;
    1410           15 :     return CHIP_NO_ERROR;
    1411           16 : }
    1412              : 
    1413           41 : CHIP_ERROR ExtractSubjectDNFromChipCert(const ByteSpan & chipCert, ChipDN & dn)
    1414              : {
    1415           41 :     ChipCertificateData certData;
    1416           41 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1417           41 :     dn = certData.mSubjectDN;
    1418           41 :     return CHIP_NO_ERROR;
    1419           41 : }
    1420              : 
    1421           10 : CHIP_ERROR ExtractSubjectDNFromX509Cert(const ByteSpan & x509Cert, ChipDN & dn)
    1422              : {
    1423              :     CHIP_ERROR err;
    1424              :     ASN1Reader reader;
    1425              : 
    1426           10 :     VerifyOrReturnError(CanCastTo<uint32_t>(x509Cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1427              : 
    1428           10 :     reader.Init(x509Cert);
    1429              : 
    1430              :     // Certificate ::= SEQUENCE
    1431           10 :     ASN1_PARSE_ENTER_SEQUENCE
    1432              :     {
    1433              :         // tbsCertificate TBSCertificate,
    1434              :         // TBSCertificate ::= SEQUENCE
    1435           10 :         ASN1_PARSE_ENTER_SEQUENCE
    1436              :         {
    1437              :             // Skip version [0] EXPLICIT Version DEFAULT v1
    1438           10 :             ASN1_PARSE_ELEMENT(kASN1TagClass_ContextSpecific, 0);
    1439              : 
    1440              :             // Skip serialNumber CertificateSerialNumber
    1441           10 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
    1442              : 
    1443              :             // Skip signature AlgorithmIdentifier
    1444           10 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
    1445              : 
    1446              :             // Skip issuer Name
    1447           10 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
    1448              : 
    1449              :             // Skip validity Validity,
    1450           10 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
    1451              : 
    1452              :             // Decode subject Name,
    1453           10 :             ReturnErrorOnFailure(dn.DecodeFromASN1(reader));
    1454              :         }
    1455           10 :         ASN1_SKIP_AND_EXIT_SEQUENCE;
    1456              :     }
    1457           10 :     ASN1_SKIP_AND_EXIT_SEQUENCE;
    1458              : 
    1459           10 : exit:
    1460           10 :     return err;
    1461              : }
    1462              : 
    1463          189 : CHIP_ERROR CertificateValidityPolicy::ApplyDefaultPolicy(const ChipCertificateData * cert, uint8_t depth,
    1464              :                                                          CertificateValidityResult result)
    1465              : {
    1466          189 :     switch (result)
    1467              :     {
    1468          183 :     case CertificateValidityResult::kValid:
    1469              :     case CertificateValidityResult::kNotExpiredAtLastKnownGoodTime:
    1470              :     // By default, we do not enforce certificate validity based upon a Last
    1471              :     // Known Good Time source.  However, implementations may always inject a
    1472              :     // policy that does enforce based upon this.
    1473              :     case CertificateValidityResult::kExpiredAtLastKnownGoodTime:
    1474              :     case CertificateValidityResult::kTimeUnknown:
    1475          183 :         return CHIP_NO_ERROR;
    1476              : 
    1477            3 :     case CertificateValidityResult::kNotYetValid:
    1478            3 :         return CHIP_ERROR_CERT_NOT_VALID_YET;
    1479              : 
    1480            3 :     case CertificateValidityResult::kExpired:
    1481            3 :         return CHIP_ERROR_CERT_EXPIRED;
    1482              : 
    1483            0 :     default:
    1484            0 :         return CHIP_ERROR_INTERNAL;
    1485              :     }
    1486              : }
    1487              : 
    1488           15 : void InitNetworkIdentitySubject(ChipDN & name)
    1489              : {
    1490           15 :     name.Clear();
    1491           15 :     CHIP_ERROR err = name.AddAttribute_CommonName(kNetworkIdentityCN, /* not printable */ false);
    1492           15 :     VerifyOrDie(err == CHIP_NO_ERROR); // AddAttribute can't fail in this case
    1493           15 : }
    1494              : 
    1495            4 : static CHIP_ERROR CalculateKeyIdentifierSha256(const P256PublicKeySpan & publicKey, MutableCertificateKeyId outKeyId)
    1496              : {
    1497              :     uint8_t hash[kSHA256_Hash_Length];
    1498              :     static_assert(outKeyId.size() <= sizeof(hash)); // truncating 32 bytes down to 20
    1499            4 :     ReturnErrorOnFailure(Hash_SHA256(publicKey.data(), publicKey.size(), hash));
    1500            4 :     memcpy(outKeyId.data(), hash, outKeyId.size());
    1501            4 :     return CHIP_NO_ERROR;
    1502              : }
    1503              : 
    1504            6 : static CHIP_ERROR ValidateChipNetworkIdentity(const ChipCertificateData & certData)
    1505              : {
    1506            6 :     ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kNetworkIdentity));
    1507              : 
    1508            6 :     VerifyOrReturnError(certData.mSerialNumber.data_equal(kNetworkIdentitySerialNumberBytes), CHIP_ERROR_WRONG_CERT_TYPE);
    1509            6 :     VerifyOrReturnError(certData.mNotBeforeTime == kNetworkIdentityNotBeforeTime, CHIP_ERROR_WRONG_CERT_TYPE);
    1510            6 :     VerifyOrReturnError(certData.mNotAfterTime == kNetworkIdentityNotAfterTime, CHIP_ERROR_WRONG_CERT_TYPE);
    1511            6 :     VerifyOrReturnError(certData.mIssuerDN.IsEqual(certData.mSubjectDN), CHIP_ERROR_WRONG_CERT_TYPE);
    1512              : 
    1513            6 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_BasicConstraints) &&
    1514              :                             !certData.mCertFlags.Has(CertFlags::kIsCA),
    1515              :                         CHIP_ERROR_WRONG_CERT_TYPE);
    1516            6 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) &&
    1517              :                             certData.mKeyUsageFlags == kNetworkIdentityKeyUsage,
    1518              :                         CHIP_ERROR_WRONG_CERT_TYPE);
    1519            6 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) &&
    1520              :                             certData.mKeyPurposeFlags == kNetworkIdentityKeyPurpose,
    1521              :                         CHIP_ERROR_WRONG_CERT_TYPE);
    1522              : 
    1523            6 :     ReturnErrorOnFailure(VerifyCertSignature(certData, certData));
    1524            6 :     return CHIP_NO_ERROR;
    1525              : }
    1526              : 
    1527            4 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert)
    1528              : {
    1529            4 :     ChipCertificateData certData;
    1530            4 :     ReturnErrorOnFailure(DecodeChipCert(cert, certData, CertDecodeFlags::kGenerateTBSHash));
    1531            4 :     ReturnErrorOnFailure(ValidateChipNetworkIdentity(certData));
    1532            4 :     return CHIP_NO_ERROR;
    1533            4 : }
    1534              : 
    1535            2 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId)
    1536              : {
    1537            2 :     ChipCertificateData certData;
    1538            2 :     ReturnErrorOnFailure(DecodeChipCert(cert, certData, CertDecodeFlags::kGenerateTBSHash));
    1539            2 :     ReturnErrorOnFailure(ValidateChipNetworkIdentity(certData));
    1540            2 :     ReturnErrorOnFailure(CalculateKeyIdentifierSha256(certData.mPublicKey, outKeyId));
    1541            2 :     return CHIP_NO_ERROR;
    1542            2 : }
    1543              : 
    1544            2 : CHIP_ERROR ExtractIdentifierFromChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId)
    1545              : {
    1546            2 :     ChipCertificateData certData;
    1547            2 :     ReturnErrorOnFailure(DecodeChipCert(cert, certData));
    1548            2 :     ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kNetworkIdentity));
    1549            2 :     ReturnErrorOnFailure(CalculateKeyIdentifierSha256(certData.mPublicKey, outKeyId));
    1550            2 :     return CHIP_NO_ERROR;
    1551            2 : }
    1552              : 
    1553            1 : static CHIP_ERROR GenerateNetworkIdentitySignature(const P256Keypair & keypair, P256ECDSASignature & signature)
    1554              : {
    1555              :     // Create a buffer and writer to capture the TBS (to-be-signed) portion of the certificate.
    1556            1 :     chip::Platform::ScopedMemoryBuffer<uint8_t> asn1TBSBuf;
    1557            1 :     VerifyOrReturnError(asn1TBSBuf.Alloc(kNetworkIdentityTBSLength), CHIP_ERROR_NO_MEMORY);
    1558              : 
    1559              :     ASN1Writer writer;
    1560            1 :     writer.Init(asn1TBSBuf.Get(), kNetworkIdentityTBSLength);
    1561              : 
    1562              :     // Generate the TBSCertificate and sign it
    1563            1 :     ReturnErrorOnFailure(EncodeNetworkIdentityTBSCert(keypair.Pubkey(), writer));
    1564            1 :     ReturnErrorOnFailure(keypair.ECDSA_sign_msg(asn1TBSBuf.Get(), writer.GetLengthWritten(), signature));
    1565              : 
    1566            1 :     return CHIP_NO_ERROR;
    1567            1 : }
    1568              : 
    1569            1 : static CHIP_ERROR EncodeCompactIdentityCert(TLVWriter & writer, Tag tag, const P256PublicKeySpan & publicKey,
    1570              :                                             const P256ECDSASignatureSpan & signature)
    1571              : {
    1572              :     TLVType containerType;
    1573            1 :     ReturnErrorOnFailure(writer.StartContainer(tag, kTLVType_Structure, containerType));
    1574            1 :     ReturnErrorOnFailure(writer.Put(ContextTag(kTag_EllipticCurvePublicKey), publicKey));
    1575            1 :     ReturnErrorOnFailure(writer.Put(ContextTag(kTag_ECDSASignature), signature));
    1576            1 :     ReturnErrorOnFailure(writer.EndContainer(containerType));
    1577            1 :     return CHIP_NO_ERROR;
    1578              : }
    1579              : 
    1580            1 : CHIP_ERROR NewChipNetworkIdentity(const Crypto::P256Keypair & keypair, MutableByteSpan & outCompactCert)
    1581              : {
    1582            1 :     VerifyOrReturnError(!outCompactCert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
    1583            1 :     VerifyOrReturnError(CanCastTo<uint32_t>(outCompactCert.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1584              : 
    1585            1 :     Crypto::P256ECDSASignature signature;
    1586            1 :     ReturnErrorOnFailure(GenerateNetworkIdentitySignature(keypair, signature));
    1587              : 
    1588            1 :     TLVWriter writer;
    1589            1 :     writer.Init(outCompactCert);
    1590              : 
    1591            1 :     P256PublicKeySpan publicKeySpan(keypair.Pubkey().ConstBytes());
    1592            1 :     P256ECDSASignatureSpan signatureSpan(signature.ConstBytes());
    1593            1 :     ReturnErrorOnFailure(EncodeCompactIdentityCert(writer, AnonymousTag(), publicKeySpan, signatureSpan));
    1594              : 
    1595            1 :     outCompactCert.reduce_size(writer.GetLengthWritten());
    1596            1 :     return CHIP_NO_ERROR;
    1597            1 : }
    1598              : 
    1599              : } // namespace Credentials
    1600              : } // namespace chip
        

Generated by: LCOV version 2.0-1