Matter SDK Coverage Report
Current view: top level - credentials - CHIPCert.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 95.6 % 701 670
Test Date: 2025-01-17 19:00:11 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          882 : ChipCertificateSet::ChipCertificateSet()
      54              : {
      55          882 :     mCerts               = nullptr;
      56          882 :     mCertCount           = 0;
      57          882 :     mMaxCerts            = 0;
      58          882 :     mMemoryAllocInternal = false;
      59          882 : }
      60              : 
      61          882 : ChipCertificateSet::~ChipCertificateSet()
      62              : {
      63          882 :     Release();
      64          882 : }
      65              : 
      66          819 : CHIP_ERROR ChipCertificateSet::Init(uint8_t maxCertsArraySize)
      67              : {
      68          819 :     CHIP_ERROR err = CHIP_NO_ERROR;
      69              : 
      70          819 :     VerifyOrExit(maxCertsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
      71          819 :     mCerts = reinterpret_cast<ChipCertificateData *>(chip::Platform::MemoryAlloc(sizeof(ChipCertificateData) * maxCertsArraySize));
      72          819 :     VerifyOrExit(mCerts != nullptr, err = CHIP_ERROR_NO_MEMORY);
      73              : 
      74          819 :     mMaxCerts            = maxCertsArraySize;
      75          819 :     mMemoryAllocInternal = true;
      76              : 
      77          819 :     Clear();
      78              : 
      79          819 : exit:
      80          819 :     if (err != CHIP_NO_ERROR)
      81              :     {
      82            0 :         Release();
      83              :     }
      84              : 
      85          819 :     return err;
      86              : }
      87              : 
      88          121 : CHIP_ERROR ChipCertificateSet::Init(ChipCertificateData * certsArray, uint8_t certsArraySize)
      89              : {
      90          121 :     CHIP_ERROR err = CHIP_NO_ERROR;
      91              : 
      92          121 :     VerifyOrExit(certsArray != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
      93          121 :     VerifyOrExit(certsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
      94              : 
      95          121 :     mCerts               = certsArray;
      96          121 :     mMaxCerts            = certsArraySize;
      97          121 :     mMemoryAllocInternal = false;
      98              : 
      99          121 :     Clear();
     100              : 
     101          121 : exit:
     102          121 :     return err;
     103              : }
     104              : 
     105          948 : void ChipCertificateSet::Release()
     106              : {
     107          948 :     if (mMemoryAllocInternal)
     108              :     {
     109          826 :         if (mCerts != nullptr)
     110              :         {
     111          819 :             Clear();
     112          819 :             chip::Platform::MemoryFree(mCerts);
     113          819 :             mCerts = nullptr;
     114              :         }
     115              :     }
     116          948 : }
     117              : 
     118         1811 : void ChipCertificateSet::Clear()
     119              : {
     120         7096 :     for (int i = 0; i < mMaxCerts; i++)
     121              :     {
     122         5285 :         mCerts[i].Clear();
     123              :     }
     124              : 
     125         1811 :     mCertCount = 0;
     126         1811 : }
     127              : 
     128         2517 : CHIP_ERROR ChipCertificateSet::LoadCert(const ByteSpan chipCert, BitFlags<CertDecodeFlags> decodeFlags)
     129              : {
     130         2517 :     TLVReader reader;
     131              : 
     132         2517 :     reader.Init(chipCert);
     133         2517 :     return LoadCert(reader, decodeFlags, chipCert);
     134              : }
     135              : 
     136         2517 : CHIP_ERROR ChipCertificateSet::LoadCert(TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags, ByteSpan chipCert)
     137              : {
     138         2517 :     ChipCertificateData cert;
     139         2517 :     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         2434 :     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         2428 :     VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
     148              : 
     149              :     // Check if this cert matches any currently loaded certificates
     150         4714 :     for (uint32_t i = 0; i < mCertCount; i++)
     151              :     {
     152         2288 :         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         2426 :     VerifyOrReturnError(mCertCount < mMaxCerts, CHIP_ERROR_NO_MEMORY);
     161              : 
     162         2426 :     new (&mCerts[mCertCount]) ChipCertificateData(cert);
     163         2426 :     mCertCount++;
     164              : 
     165         2426 :     return CHIP_NO_ERROR;
     166         2517 : }
     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          764 : CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
     216              :                                              ValidationContext & context, const ChipCertificateData ** certData)
     217              : {
     218          764 :     context.mTrustAnchor = nullptr;
     219              : 
     220          764 :     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         1592 : CHIP_ERROR VerifyCertSignature(const ChipCertificateData & cert, const ChipCertificateData & signer)
     230              : {
     231         1592 :     VerifyOrReturnError(cert.mCertFlags.Has(CertFlags::kTBSHashPresent), CHIP_ERROR_INVALID_ARGUMENT);
     232         1591 :     VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
     233              : 
     234              : #ifdef ENABLE_HSM_ECDSA_VERIFY
     235              :     P256PublicKeyHSM signerPublicKey;
     236              : #else
     237         1591 :     P256PublicKey signerPublicKey;
     238              : #endif
     239         1591 :     P256ECDSASignature signature;
     240              : 
     241         1591 :     ReturnErrorOnFailure(signature.SetLength(cert.mSignature.size()));
     242         1591 :     memcpy(signature.Bytes(), cert.mSignature.data(), cert.mSignature.size());
     243              : 
     244         1591 :     memcpy(signerPublicKey, signer.mPublicKey.data(), signer.mPublicKey.size());
     245              : 
     246         1591 :     ReturnErrorOnFailure(
     247              :         signerPublicKey.ECDSA_validate_hash_signature(cert.mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature));
     248              : 
     249         1588 :     return CHIP_NO_ERROR;
     250         1591 : }
     251              : 
     252         2489 : CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context, uint8_t depth)
     253              : {
     254         2489 :     CHIP_ERROR err                     = CHIP_NO_ERROR;
     255         2489 :     const ChipCertificateData * caCert = nullptr;
     256              :     CertType certType;
     257              : 
     258         2489 :     err = cert->mSubjectDN.GetCertType(certType);
     259         2489 :     SuccessOrExit(err);
     260              : 
     261              :     // Certificate with future-extension marked as "critical" is not allowed.
     262         2489 :     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         2488 :     if (depth > 0)
     266              :     {
     267              :         // Verify the isCA flag is present.
     268         1591 :         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         1590 :         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         1588 :         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         1588 :         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          897 :         if (context.mRequiredKeyUsages.HasAny())
     296              :         {
     297          879 :             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          865 :         if (context.mRequiredKeyPurposes.HasAny())
     305              :         {
     306          861 :             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          849 :         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         2435 :     if (context.mEffectiveTime.Is<CurrentChipEpochTime>())
     328              :     {
     329          190 :         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          354 :         else if (cert->mNotAfterTime != kNullCertTime &&
     336          177 :                  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          164 :             validityResult = CertificateValidityResult::kValid;
     345              :         }
     346              :     }
     347         2245 :     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         2158 :         validityResult = CertificateValidityResult::kTimeUnknown;
     370              :     }
     371              : 
     372         2435 :     if (context.mValidityPolicy != nullptr)
     373              :     {
     374         2254 :         SuccessOrExit(err = context.mValidityPolicy->ApplyCertificateValidityPolicy(cert, depth, validityResult));
     375              :     }
     376              :     else
     377              :     {
     378          181 :         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         2402 :     if (cert->mCertFlags.Has(CertFlags::kIsTrustAnchor))
     384              :     {
     385          802 :         context.mTrustAnchor = cert;
     386          802 :         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         1600 :     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         1598 :     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         1598 :     err = FindValidCert(cert->mIssuerDN, cert->mAuthKeyId, context, static_cast<uint8_t>(depth + 1), &caCert);
     407         1598 :     if (err != CHIP_NO_ERROR)
     408              :     {
     409           18 :         ExitNow(err = CHIP_ERROR_CA_CERT_NOT_FOUND);
     410              :     }
     411              : 
     412              :     // Verify signature of the current certificate against public key of the CA certificate. If signature verification
     413              :     // succeeds, the current certificate is valid.
     414         1580 :     err = VerifyCertSignature(*cert, *caCert);
     415         1580 :     SuccessOrExit(err);
     416              : 
     417         2489 : exit:
     418         2489 :     return err;
     419              : }
     420              : 
     421         2362 : CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
     422              :                                              ValidationContext & context, uint8_t depth, const ChipCertificateData ** certData)
     423              : {
     424              :     CHIP_ERROR err;
     425              : 
     426         2362 :     *certData = nullptr;
     427              : 
     428              :     // Default error if we don't find any matching cert.
     429         2362 :     err = (depth > 0) ? CHIP_ERROR_CA_CERT_NOT_FOUND : CHIP_ERROR_CERT_NOT_FOUND;
     430              : 
     431              :     // For each cert in the set...
     432         4728 :     for (uint8_t i = 0; i < mCertCount; i++)
     433              :     {
     434         4694 :         ChipCertificateData * candidateCert = &mCerts[i];
     435              : 
     436              :         // Skip the certificate if its subject DN and key id do not match the input criteria.
     437         4694 :         if (!candidateCert->mSubjectDN.IsEqual(subjectDN))
     438              :         {
     439         2335 :             continue;
     440              :         }
     441         2359 :         if (!candidateCert->mSubjectKeyId.data_equal(subjectKeyId))
     442              :         {
     443            4 :             continue;
     444              :         }
     445              : 
     446              :         // Attempt to validate the cert.  If the cert is valid, return it to the caller. Otherwise,
     447              :         // save the returned error and continue searching.  If there are no other matching certs this
     448              :         // will be the error returned to the caller.
     449         2355 :         err = ValidateCert(candidateCert, context, depth);
     450         2355 :         if (err == CHIP_NO_ERROR)
     451              :         {
     452         2328 :             *certData = candidateCert;
     453         2328 :             ExitNow();
     454              :         }
     455              :     }
     456              : 
     457           34 : exit:
     458         2362 :     return err;
     459              : }
     460              : 
     461         2991 : ChipCertificateData::ChipCertificateData() {}
     462              : 
     463         2991 : ChipCertificateData::~ChipCertificateData() {}
     464              : 
     465         8179 : void ChipCertificateData::Clear()
     466              : {
     467         8179 :     mSerialNumber = ByteSpan();
     468         8179 :     mSubjectDN.Clear();
     469         8179 :     mIssuerDN.Clear();
     470         8179 :     mSubjectKeyId      = CertificateKeyId();
     471         8179 :     mAuthKeyId         = CertificateKeyId();
     472         8179 :     mNotBeforeTime     = 0;
     473         8179 :     mNotAfterTime      = 0;
     474         8179 :     mPublicKey         = P256PublicKeySpan();
     475         8179 :     mPubKeyCurveOID    = 0;
     476         8179 :     mPubKeyAlgoOID     = 0;
     477         8179 :     mSigAlgoOID        = 0;
     478         8179 :     mPathLenConstraint = 0;
     479         8179 :     mCertFlags.ClearAll();
     480         8179 :     mKeyUsageFlags.ClearAll();
     481         8179 :     mKeyPurposeFlags.ClearAll();
     482         8179 :     mSignature = P256ECDSASignatureSpan();
     483              : 
     484         8179 :     memset(mTBSHash, 0, sizeof(mTBSHash));
     485         8179 : }
     486              : 
     487         2288 : bool ChipCertificateData::IsEqual(const ChipCertificateData & other) const
     488              : {
     489              :     // TODO - Add an operator== on BitFlags class.
     490         2294 :     return mSubjectDN.IsEqual(other.mSubjectDN) && mIssuerDN.IsEqual(other.mIssuerDN) &&
     491            6 :         mSubjectKeyId.data_equal(other.mSubjectKeyId) && mAuthKeyId.data_equal(other.mAuthKeyId) &&
     492            6 :         (mNotBeforeTime == other.mNotBeforeTime) && (mNotAfterTime == other.mNotAfterTime) &&
     493            6 :         mPublicKey.data_equal(other.mPublicKey) && (mPubKeyCurveOID == other.mPubKeyCurveOID) &&
     494            6 :         (mPubKeyAlgoOID == other.mPubKeyAlgoOID) && (mSigAlgoOID == other.mSigAlgoOID) &&
     495            7 :         (mCertFlags.Raw() == other.mCertFlags.Raw()) && (mKeyUsageFlags.Raw() == other.mKeyUsageFlags.Raw()) &&
     496            6 :         (mKeyPurposeFlags.Raw() == other.mKeyPurposeFlags.Raw()) && (mPathLenConstraint == other.mPathLenConstraint) &&
     497         2293 :         mSignature.data_equal(other.mSignature) && (memcmp(mTBSHash, other.mTBSHash, sizeof(mTBSHash)) == 0);
     498              : }
     499              : 
     500          838 : void ValidationContext::Reset()
     501              : {
     502          838 :     mEffectiveTime  = EffectiveTime{};
     503          838 :     mTrustAnchor    = nullptr;
     504          838 :     mValidityPolicy = nullptr;
     505          838 :     mRequiredKeyUsages.ClearAll();
     506          838 :     mRequiredKeyPurposes.ClearAll();
     507          838 :     mRequiredCertType = CertType::kNotSpecified;
     508          838 : }
     509              : 
     510         5692 : bool ChipRDN::IsEqual(const ChipRDN & other) const
     511              : {
     512         5692 :     if (mAttrOID == kOID_Unknown || mAttrOID == kOID_NotSpecified || mAttrOID != other.mAttrOID ||
     513         3968 :         mAttrIsPrintableString != other.mAttrIsPrintableString)
     514              :     {
     515         1724 :         return false;
     516              :     }
     517              : 
     518         3968 :     if (IsChipDNAttr(mAttrOID))
     519              :     {
     520         3954 :         return mChipVal == other.mChipVal;
     521              :     }
     522              : 
     523           14 :     return mString.data_equal(other.mString);
     524              : }
     525              : 
     526        38250 : ChipDN::ChipDN()
     527              : {
     528         6375 :     Clear();
     529         6375 : }
     530              : 
     531         6530 : ChipDN::~ChipDN() {}
     532              : 
     533        22760 : void ChipDN::Clear()
     534              : {
     535       136560 :     for (auto & dn : rdn)
     536              :     {
     537       113800 :         dn.Clear();
     538              :     }
     539        22760 : }
     540              : 
     541        41910 : uint8_t ChipDN::RDNCount() const
     542              : {
     543              :     uint8_t count;
     544              : 
     545        99074 :     for (count = 0; count < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES; count++)
     546              :     {
     547        98927 :         if (rdn[count].IsEmpty())
     548              :         {
     549        41763 :             break;
     550              :         }
     551              :     }
     552              : 
     553        41910 :     return count;
     554              : }
     555              : 
     556         9745 : CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, uint64_t val)
     557              : {
     558         9745 :     uint8_t rdnCount = RDNCount();
     559              : 
     560         9745 :     VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
     561         9745 :     VerifyOrReturnError(IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);
     562              : 
     563         9745 :     if (IsChip32bitDNAttr(oid))
     564              :     {
     565          132 :         VerifyOrReturnError(CanCastTo<uint32_t>(val), CHIP_ERROR_INVALID_ARGUMENT);
     566              :     }
     567              : 
     568         9745 :     rdn[rdnCount].mAttrOID               = oid;
     569         9745 :     rdn[rdnCount].mChipVal               = val;
     570         9745 :     rdn[rdnCount].mAttrIsPrintableString = false;
     571              : 
     572         9745 :     return CHIP_NO_ERROR;
     573              : }
     574              : 
     575            1 : CHIP_ERROR ChipDN::AddCATs(const chip::CATValues & cats)
     576              : {
     577            1 :     VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_INVALID_ARGUMENT);
     578              : 
     579            4 :     for (auto & cat : cats.values)
     580              :     {
     581            3 :         if (cat != kUndefinedCAT)
     582              :         {
     583            1 :             ReturnErrorOnFailure(AddAttribute_MatterCASEAuthTag(cat));
     584              :         }
     585              :     }
     586              : 
     587            1 :     return CHIP_NO_ERROR;
     588              : }
     589              : 
     590          152 : CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, CharSpan val, bool isPrintableString)
     591              : {
     592          152 :     uint8_t rdnCount = RDNCount();
     593              : 
     594          152 :     VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
     595          151 :     VerifyOrReturnError(!IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);
     596          151 :     VerifyOrReturnError(oid != kOID_NotSpecified, CHIP_ERROR_INVALID_ARGUMENT);
     597              : 
     598          151 :     rdn[rdnCount].mAttrOID               = oid;
     599          151 :     rdn[rdnCount].mString                = val;
     600          151 :     rdn[rdnCount].mAttrIsPrintableString = isPrintableString;
     601              : 
     602          151 :     return CHIP_NO_ERROR;
     603              : }
     604              : 
     605         2877 : CHIP_ERROR ChipDN::GetCertType(CertType & certType) const
     606              : {
     607         2877 :     CertType lCertType   = CertType::kNotSpecified;
     608         2877 :     bool fabricIdPresent = false;
     609         2877 :     bool catsPresent     = false;
     610         2877 :     uint8_t rdnCount     = RDNCount();
     611              : 
     612         2886 :     if (rdnCount == 1 && rdn[0].mAttrOID == kOID_AttributeType_CommonName && !rdn[0].mAttrIsPrintableString &&
     613            9 :         rdn[0].mString.data_equal(kNetworkIdentityCN))
     614              :     {
     615            9 :         certType = CertType::kNetworkIdentity;
     616            9 :         return CHIP_NO_ERROR;
     617              :     }
     618              : 
     619         2868 :     certType = CertType::kNotSpecified;
     620              : 
     621         7627 :     for (uint8_t i = 0; i < rdnCount; i++)
     622              :     {
     623         4771 :         if (rdn[i].mAttrOID == kOID_AttributeType_MatterRCACId)
     624              :         {
     625          924 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     626              : 
     627          922 :             lCertType = CertType::kRoot;
     628              :         }
     629         3847 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterICACId)
     630              :         {
     631          911 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     632              : 
     633          909 :             lCertType = CertType::kICA;
     634              :         }
     635         2936 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterNodeId)
     636              :         {
     637         1026 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     638         1024 :             VerifyOrReturnError(IsOperationalNodeId(rdn[i].mChipVal), CHIP_ERROR_WRONG_NODE_ID);
     639         1024 :             lCertType = CertType::kNode;
     640              :         }
     641         1910 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFirmwareSigningId)
     642              :         {
     643            2 :             VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
     644              : 
     645            2 :             lCertType = CertType::kFirmwareSigning;
     646              :         }
     647         1908 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFabricId)
     648              :         {
     649              :             // Only one fabricId attribute is allowed per DN.
     650         1835 :             VerifyOrReturnError(!fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
     651         1829 :             VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
     652         1829 :             fabricIdPresent = true;
     653              :         }
     654           73 :         else if (rdn[i].mAttrOID == kOID_AttributeType_MatterCASEAuthTag)
     655              :         {
     656           41 :             VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
     657           41 :             VerifyOrReturnError(IsValidCASEAuthTag(static_cast<CASEAuthTag>(rdn[i].mChipVal)), CHIP_ERROR_WRONG_CERT_DN);
     658           41 :             catsPresent = true;
     659              :         }
     660              :     }
     661              : 
     662         2856 :     if (lCertType == CertType::kNode)
     663              :     {
     664         1020 :         VerifyOrReturnError(fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
     665              :     }
     666              :     else
     667              :     {
     668         1836 :         VerifyOrReturnError(!catsPresent, CHIP_ERROR_WRONG_CERT_DN);
     669              :     }
     670              : 
     671         2850 :     certType = lCertType;
     672              : 
     673         2850 :     return CHIP_NO_ERROR;
     674              : }
     675              : 
     676           12 : CHIP_ERROR ChipDN::GetCertChipId(uint64_t & chipId) const
     677              : {
     678           12 :     uint8_t rdnCount = RDNCount();
     679           12 :     bool foundId     = false;
     680              : 
     681           12 :     chipId = 0;
     682              : 
     683           36 :     for (uint8_t i = 0; i < rdnCount; i++)
     684              :     {
     685           24 :         switch (rdn[i].mAttrOID)
     686              :         {
     687           11 :         case kOID_AttributeType_MatterRCACId:
     688              :         case kOID_AttributeType_MatterICACId:
     689              :         case kOID_AttributeType_MatterNodeId:
     690              :         case kOID_AttributeType_MatterFirmwareSigningId:
     691           11 :             VerifyOrReturnError(!foundId, CHIP_ERROR_WRONG_CERT_DN);
     692              : 
     693           11 :             chipId  = rdn[i].mChipVal;
     694           11 :             foundId = true;
     695           11 :             break;
     696           13 :         default:
     697           13 :             break;
     698              :         }
     699              :     }
     700              : 
     701           12 :     VerifyOrReturnError(foundId, CHIP_ERROR_WRONG_CERT_DN);
     702           11 :     return CHIP_NO_ERROR;
     703              : }
     704              : 
     705            1 : CHIP_ERROR ChipDN::GetCertFabricId(uint64_t & fabricId) const
     706              : {
     707            1 :     uint8_t rdnCount = RDNCount();
     708              : 
     709            1 :     fabricId = kUndefinedFabricId;
     710              : 
     711            6 :     for (uint8_t i = 0; i < rdnCount; i++)
     712              :     {
     713            5 :         switch (rdn[i].mAttrOID)
     714              :         {
     715            1 :         case kOID_AttributeType_MatterFabricId:
     716              :             // Ensure only one FabricID RDN present, since start value is kUndefinedFabricId, which is reserved and never seen.
     717            1 :             VerifyOrReturnError(fabricId == kUndefinedFabricId, CHIP_ERROR_WRONG_CERT_DN);
     718            1 :             VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
     719            1 :             fabricId = rdn[i].mChipVal;
     720            1 :             break;
     721            4 :         default:
     722            4 :             break;
     723              :         }
     724              :     }
     725              : 
     726            1 :     VerifyOrReturnError(IsValidFabricId(fabricId), CHIP_ERROR_WRONG_CERT_DN);
     727            1 :     return CHIP_NO_ERROR;
     728              : }
     729              : 
     730          250 : CHIP_ERROR ChipDN::EncodeToTLV(TLVWriter & writer, Tag tag) const
     731              : {
     732              :     TLVType outerContainer;
     733          250 :     uint8_t rdnCount = RDNCount();
     734              : 
     735          250 :     ReturnErrorOnFailure(writer.StartContainer(tag, kTLVType_List, outerContainer));
     736              : 
     737          663 :     for (uint8_t i = 0; i < rdnCount; i++)
     738              :     {
     739              :         // Derive the TLV tag number from the enum value assigned to the attribute type OID. For attributes that can be
     740              :         // either UTF8String or PrintableString, use the high bit in the tag number to distinguish the two.
     741          414 :         uint8_t tlvTagNum = GetOIDEnum(rdn[i].mAttrOID);
     742          414 :         if (rdn[i].mAttrIsPrintableString)
     743              :         {
     744            3 :             tlvTagNum |= 0x80;
     745              :         }
     746              : 
     747          414 :         if (IsChipDNAttr(rdn[i].mAttrOID))
     748              :         {
     749          387 :             ReturnErrorOnFailure(writer.Put(ContextTag(tlvTagNum), rdn[i].mChipVal));
     750              :         }
     751              :         else
     752              :         {
     753           27 :             ReturnErrorOnFailure(writer.PutString(ContextTag(tlvTagNum), rdn[i].mString));
     754              :         }
     755              :     }
     756              : 
     757          249 :     return writer.EndContainer(outerContainer);
     758              : }
     759              : 
     760         5682 : CHIP_ERROR ChipDN::DecodeFromTLV(TLVReader & reader)
     761              : {
     762              :     CHIP_ERROR err;
     763              :     TLVType outerContainer;
     764              : 
     765              :     static constexpr uint32_t kOID_AttributeIsPrintableString_Flag = 0x00000080;
     766              :     static constexpr uint32_t kOID_AttributeType_Mask              = 0x0000007F;
     767              : 
     768         5682 :     VerifyOrReturnError(reader.GetType() == kTLVType_List, CHIP_ERROR_WRONG_TLV_TYPE);
     769              : 
     770              :     // Enter the List TLV element that represents the DN in TLV format.
     771         5682 :     ReturnErrorOnFailure(reader.EnterContainer(outerContainer));
     772              : 
     773              :     // Read the RDN attributes in the List.
     774        14954 :     while ((err = reader.Next()) == CHIP_NO_ERROR)
     775              :     {
     776              :         // Get the TLV tag, make sure it is a context tag and extract the context tag number.
     777         9293 :         Tag tlvTag = reader.GetTag();
     778         9314 :         VerifyOrReturnError(IsContextTag(tlvTag), CHIP_ERROR_INVALID_TLV_TAG);
     779         9293 :         uint32_t tlvTagNum = TagNumFromTag(tlvTag);
     780              : 
     781              :         // Derive the OID of the corresponding ASN.1 attribute from the TLV tag number.
     782              :         // The numeric value of the OID is encoded in the bottom 7 bits of the TLV tag number.
     783              :         // This eliminates the need for a translation table/switch statement but has the
     784              :         // effect of tying the two encodings together.
     785              :         //
     786              :         // NOTE: In the event that the computed OID value is not one that we recognize
     787              :         // (specifically, is not in the table of OIDs defined in ASN1OID.h) then the
     788              :         // macro call below that encodes the attribute's object id (ASN1_ENCODE_OBJECT_ID)
     789              :         // will fail for lack of the OID's encoded representation.  Given this there's no
     790              :         // need to test the validity of the OID here.
     791              :         //
     792         9293 :         OID attrOID = GetOID(kOIDCategory_AttributeType, static_cast<uint8_t>(tlvTagNum & kOID_AttributeType_Mask));
     793              : 
     794         9293 :         bool attrIsPrintableString = (tlvTagNum & kOID_AttributeIsPrintableString_Flag) == kOID_AttributeIsPrintableString_Flag;
     795              : 
     796              :         // For 64-bit CHIP-defined DN attributes.
     797         9293 :         if (IsChip64bitDNAttr(attrOID))
     798              :         {
     799              :             uint64_t chipAttr;
     800         9083 :             VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
     801         9072 :             ReturnErrorOnFailure(reader.Get(chipAttr));
     802         9072 :             if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
     803              :             {
     804         1030 :                 VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
     805              :             }
     806         8042 :             else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
     807              :             {
     808         3417 :                 VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
     809              :             }
     810         9061 :             ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     811              :         }
     812              :         // For 32-bit CHIP-defined DN attributes.
     813          221 :         else if (IsChip32bitDNAttr(attrOID))
     814              :         {
     815              :             uint32_t chipAttr;
     816          134 :             VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
     817          124 :             ReturnErrorOnFailure(reader.Get(chipAttr));
     818          124 :             if (attrOID == chip::ASN1::kOID_AttributeType_MatterCASEAuthTag)
     819              :             {
     820          124 :                 VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
     821              :             }
     822          114 :             ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     823              :         }
     824              :         // Otherwise the attribute is one of the supported X.509 attributes
     825              :         else
     826              :         {
     827           97 :             CharSpan asn1Attr;
     828           97 :             ReturnErrorOnFailure(reader.Get(asn1Attr));
     829           97 :             ReturnErrorOnFailure(AddAttribute(attrOID, asn1Attr, attrIsPrintableString));
     830              :         }
     831              :     }
     832         5661 :     VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
     833         5661 :     ReturnErrorOnFailure(reader.ExitContainer(outerContainer));
     834              : 
     835         5661 :     return CHIP_NO_ERROR;
     836              : }
     837              : 
     838         5963 : CHIP_ERROR ChipDN::EncodeToASN1(ASN1Writer & writer) const
     839              : {
     840         5963 :     CHIP_ERROR err   = CHIP_NO_ERROR;
     841         5963 :     uint8_t rdnCount = RDNCount();
     842              : 
     843         5963 :     ASN1_START_SEQUENCE
     844              :     {
     845        15687 :         for (uint8_t i = 0; i < rdnCount; i++)
     846              :         {
     847         9725 :             ASN1_START_SET
     848              :             {
     849              :                 char chipAttrStr[kChip64bitAttrUTF8Length];
     850         9725 :                 CharSpan asn1Attr;
     851              :                 uint8_t asn1Tag;
     852         9725 :                 chip::ASN1::OID attrOID = rdn[i].mAttrOID;
     853              : 
     854         9725 :                 if (IsChip64bitDNAttr(attrOID))
     855              :                 {
     856         9481 :                     ReturnErrorOnFailure(
     857              :                         Encoding::Uint64ToHex(rdn[i].mChipVal, chipAttrStr, sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
     858         9481 :                     asn1Attr = CharSpan(chipAttrStr, kChip64bitAttrUTF8Length);
     859         9481 :                     asn1Tag  = kASN1UniversalTag_UTF8String;
     860              :                 }
     861          244 :                 else if (IsChip32bitDNAttr(attrOID))
     862              :                 {
     863          121 :                     ReturnErrorOnFailure(Encoding::Uint32ToHex(static_cast<uint32_t>(rdn[i].mChipVal), chipAttrStr,
     864              :                                                                sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
     865          121 :                     asn1Attr = CharSpan(chipAttrStr, kChip32bitAttrUTF8Length);
     866          121 :                     asn1Tag  = kASN1UniversalTag_UTF8String;
     867              :                 }
     868              :                 else
     869              :                 {
     870          123 :                     asn1Attr = rdn[i].mString;
     871              : 
     872              :                     // Determine the appropriate ASN.1 tag for the DN attribute.
     873              :                     // - DomainComponent is always an IA5String.
     874              :                     // - For all other ASN.1 defined attributes, bit 0x80 in the TLV tag value conveys whether the attribute
     875              :                     //   is a UTF8String or a PrintableString (in some cases the certificate generator has a choice).
     876          123 :                     if (attrOID == kOID_AttributeType_DomainComponent)
     877              :                     {
     878            0 :                         asn1Tag = kASN1UniversalTag_IA5String;
     879              :                     }
     880              :                     else
     881              :                     {
     882          123 :                         asn1Tag = rdn[i].mAttrIsPrintableString ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String;
     883              :                     }
     884              :                 }
     885              : 
     886              :                 // AttributeTypeAndValue ::= SEQUENCE
     887         9725 :                 ASN1_START_SEQUENCE
     888              :                 {
     889              :                     // type AttributeType
     890              :                     // AttributeType ::= OBJECT IDENTIFIER
     891         9725 :                     ASN1_ENCODE_OBJECT_ID(attrOID);
     892              : 
     893         9725 :                     VerifyOrReturnError(CanCastTo<uint16_t>(asn1Attr.size()), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
     894              : 
     895              :                     // value AttributeValue
     896              :                     // AttributeValue ::= ANY -- DEFINED BY AttributeType
     897         9725 :                     ReturnErrorOnFailure(writer.PutString(asn1Tag, asn1Attr.data(), static_cast<uint16_t>(asn1Attr.size())));
     898              :                 }
     899         9724 :                 ASN1_END_SEQUENCE;
     900              :             }
     901         9724 :             ASN1_END_SET;
     902              :         }
     903              :     }
     904         5962 :     ASN1_END_SEQUENCE;
     905              : 
     906         5962 : exit:
     907         5962 :     return err;
     908              : }
     909              : 
     910          263 : CHIP_ERROR ChipDN::DecodeFromASN1(ASN1Reader & reader)
     911              : {
     912              :     CHIP_ERROR err;
     913              : 
     914              :     // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
     915          263 :     ASN1_PARSE_ENTER_SEQUENCE
     916              :     {
     917          696 :         while ((err = reader.Next()) == CHIP_NO_ERROR)
     918              :         {
     919              :             // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
     920          440 :             ASN1_ENTER_SET
     921              :             {
     922              :                 // AttributeTypeAndValue ::= SEQUENCE
     923          440 :                 ASN1_PARSE_ENTER_SEQUENCE
     924              :                 {
     925              :                     // type AttributeType
     926              :                     // AttributeType ::= OBJECT IDENTIFIER
     927              :                     OID attrOID;
     928          440 :                     ASN1_PARSE_OBJECT_ID(attrOID);
     929          447 :                     VerifyOrReturnError(GetOIDCategory(attrOID) == kOIDCategory_AttributeType, ASN1_ERROR_INVALID_ENCODING);
     930              : 
     931              :                     // AttributeValue ::= ANY -- DEFINED BY AttributeType
     932          440 :                     ASN1_PARSE_ANY;
     933              : 
     934          440 :                     uint8_t attrTag = reader.GetTag();
     935              : 
     936              :                     // Can only support UTF8String, PrintableString and IA5String.
     937          440 :                     VerifyOrReturnError(reader.GetClass() == kASN1TagClass_Universal &&
     938              :                                             (attrTag == kASN1UniversalTag_PrintableString ||
     939              :                                              attrTag == kASN1UniversalTag_UTF8String || attrTag == kASN1UniversalTag_IA5String),
     940              :                                         ASN1_ERROR_UNSUPPORTED_ENCODING);
     941              : 
     942              :                     // CHIP attributes must be UTF8Strings.
     943          440 :                     if (IsChipDNAttr(attrOID))
     944              :                     {
     945          411 :                         VerifyOrReturnError(attrTag == kASN1UniversalTag_UTF8String, ASN1_ERROR_INVALID_ENCODING);
     946              :                     }
     947              : 
     948              :                     // If 64-bit CHIP attribute.
     949          440 :                     if (IsChip64bitDNAttr(attrOID))
     950              :                     {
     951              :                         uint64_t chipAttr;
     952          402 :                         VerifyOrReturnError(Encoding::UppercaseHexToUint64(reinterpret_cast<const char *>(reader.GetValue()),
     953              :                                                                            static_cast<size_t>(reader.GetValueLen()),
     954              :                                                                            chipAttr) == sizeof(uint64_t),
     955              :                                             ASN1_ERROR_INVALID_ENCODING);
     956              : 
     957          398 :                         if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
     958              :                         {
     959           55 :                             VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
     960              :                         }
     961          343 :                         else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
     962              :                         {
     963          141 :                             VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_WRONG_CERT_DN);
     964              :                         }
     965              : 
     966          394 :                         ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     967              :                     }
     968              :                     // If 32-bit CHIP attribute.
     969           42 :                     else if (IsChip32bitDNAttr(attrOID))
     970              :                     {
     971              :                         CASEAuthTag chipAttr;
     972           16 :                         VerifyOrReturnError(Encoding::UppercaseHexToUint32(reinterpret_cast<const char *>(reader.GetValue()),
     973              :                                                                            reader.GetValueLen(), chipAttr) == sizeof(CASEAuthTag),
     974              :                                             ASN1_ERROR_INVALID_ENCODING);
     975              : 
     976           13 :                         VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_WRONG_CERT_DN);
     977              : 
     978           10 :                         ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
     979              :                     }
     980              :                     // Otherwise, it is a string.
     981              :                     else
     982              :                     {
     983           29 :                         ReturnErrorOnFailure(AddAttribute(attrOID,
     984              :                                                           CharSpan(Uint8::to_const_char(reader.GetValue()), reader.GetValueLen()),
     985              :                                                           attrTag == kASN1UniversalTag_PrintableString));
     986              :                     }
     987              :                 }
     988          433 :                 ASN1_EXIT_SEQUENCE;
     989              : 
     990              :                 // Only one AttributeTypeAndValue allowed per RDN.
     991          433 :                 err = reader.Next();
     992          433 :                 VerifyOrReturnError(err != CHIP_NO_ERROR, ASN1_ERROR_UNSUPPORTED_ENCODING);
     993          433 :                 VerifyOrReturnError(err == ASN1_END, err);
     994              :             }
     995          433 :             ASN1_EXIT_SET;
     996              :         }
     997              :     }
     998          256 :     ASN1_EXIT_SEQUENCE;
     999              : 
    1000          256 : exit:
    1001          256 :     return err;
    1002              : }
    1003              : 
    1004         8635 : bool ChipDN::IsEqual(const ChipDN & other) const
    1005              : {
    1006         8635 :     bool res         = true;
    1007         8635 :     uint8_t rdnCount = RDNCount();
    1008              : 
    1009         8635 :     VerifyOrExit(rdnCount > 0, res = false);
    1010         8635 :     VerifyOrExit(rdnCount == other.RDNCount(), res = false);
    1011              : 
    1012         8108 :     for (uint8_t i = 0; i < rdnCount; i++)
    1013              :     {
    1014         5692 :         VerifyOrExit(rdn[i].IsEqual(other.rdn[i]), res = false);
    1015              :     }
    1016              : 
    1017         2416 : exit:
    1018         8635 :     return res;
    1019              : }
    1020              : 
    1021          380 : DLL_EXPORT CHIP_ERROR ASN1ToChipEpochTime(const chip::ASN1::ASN1UniversalTime & asn1Time, uint32_t & epochTime)
    1022              : {
    1023          380 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1024              :     // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    1025              :     // In CHIP certificate it is represented as a CHIP Epoch time value of 0 sec (2000-01-01 00:00:00 UTC).
    1026              :     //
    1027              :     // While it is not conventional to use this special value for NotBefore, for simplicity we convert all
    1028              :     // time values of 99991231235959Z to CHIP epoch zero seconds.  ChipEpochToASN1Time performs the inverse
    1029              :     // translation for conversions in the other direction.
    1030              :     //
    1031              :     // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses 99991231235959Z
    1032              :     // for NotBefore, this will be converted to the CHIP Epoch time value of 0 and consuming code will
    1033              :     // handle this transparently, as logic considering a NotBefore time at the CHIP epoch will evaluate all
    1034              :     // possible unsigned offsets from the CHIP epoch as valid, which is equivalent to ignoring NotBefore.
    1035              :     //
    1036              :     // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses a NotBefore time
    1037              :     // at the CHIP epoch itself, 2000-01-01 00:00:00, a resultant conversion to CHIP TLV certificate format
    1038              :     // will appear to have an invalid TBS signature when the symmetric ChipEpochToASN1Time produces
    1039              :     // 99991231235959Z for NotBefore during signature validation.
    1040              :     //
    1041              :     // Thus such certificates, when passing through this code, will not appear valid.  This should be
    1042              :     // immediately evident at commissioning time.
    1043          380 :     if ((asn1Time.Year == kX509NoWellDefinedExpirationDateYear) && (asn1Time.Month == kMonthsPerYear) &&
    1044            4 :         (asn1Time.Day == kMaxDaysPerMonth) && (asn1Time.Hour == kHoursPerDay - 1) && (asn1Time.Minute == kMinutesPerHour - 1) &&
    1045            4 :         (asn1Time.Second == kSecondsPerMinute - 1))
    1046              :     {
    1047            4 :         epochTime = kNullCertTime;
    1048              :     }
    1049              :     else
    1050              :     {
    1051          376 :         if (!CalendarToChipEpochTime(asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute, asn1Time.Second,
    1052              :                                      epochTime))
    1053              :         {
    1054            0 :             ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
    1055              :         }
    1056              :     }
    1057              : 
    1058          376 : exit:
    1059          380 :     return err;
    1060              : }
    1061              : 
    1062         5979 : DLL_EXPORT CHIP_ERROR ChipEpochToASN1Time(uint32_t epochTime, chip::ASN1::ASN1UniversalTime & asn1Time)
    1063              : {
    1064              :     // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    1065              :     // In CHIP certificate it is represented as a CHIP Epoch time value of 0 secs (2000-01-01 00:00:00 UTC).
    1066              :     //
    1067              :     // For simplicity and symmetry with ASN1ToChipEpochTime, this method makes this conversion for all
    1068              :     // times, which in consuming code can create a conversion from CHIP epoch 0 seconds to 99991231235959Z
    1069              :     // for NotBefore, which is not conventional.
    1070              :     //
    1071              :     // If an original X509 certificate encloses a NotBefore time that is the CHIP Epoch itself, 2000-01-01
    1072              :     // 00:00:00, the resultant X509 certificate in a conversion back from CHIP TLV format using this time
    1073              :     // conversion method will instead enclose the NotBefore time 99991231235959Z, which will invalidiate the
    1074              :     // TBS signature.  Thus, certificates with this specific attribute are not usable with this code.
    1075              :     // Attempted installation of such certficates will fail during commissioning.
    1076         5979 :     if (epochTime == kNullCertTime)
    1077              :     {
    1078           19 :         asn1Time.Year   = kX509NoWellDefinedExpirationDateYear;
    1079           19 :         asn1Time.Month  = kMonthsPerYear;
    1080           19 :         asn1Time.Day    = kMaxDaysPerMonth;
    1081           19 :         asn1Time.Hour   = kHoursPerDay - 1;
    1082           19 :         asn1Time.Minute = kMinutesPerHour - 1;
    1083           19 :         asn1Time.Second = kSecondsPerMinute - 1;
    1084              :     }
    1085              :     else
    1086              :     {
    1087         5960 :         ChipEpochToCalendarTime(epochTime, asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute,
    1088         5960 :                                 asn1Time.Second);
    1089              :     }
    1090              : 
    1091         5979 :     return CHIP_NO_ERROR;
    1092              : }
    1093              : 
    1094           52 : static CHIP_ERROR ValidateCertificateType(const ChipCertificateData & certData, CertType expectedType)
    1095              : {
    1096              :     CertType certType;
    1097           52 :     ReturnErrorOnFailure(certData.mSubjectDN.GetCertType(certType));
    1098           44 :     VerifyOrReturnError(certType == expectedType, CHIP_ERROR_WRONG_CERT_TYPE);
    1099           18 :     return CHIP_NO_ERROR;
    1100              : }
    1101              : 
    1102           92 : CHIP_ERROR ValidateChipRCAC(const ByteSpan & rcac)
    1103              : {
    1104           92 :     ChipCertificateSet certSet;
    1105           92 :     ChipCertificateData certData;
    1106           92 :     ValidationContext validContext;
    1107              : 
    1108              :     // Note that this function doesn't check RCAC NotBefore / NotAfter time validity.
    1109              :     // It is assumed that RCAC should be valid at the time of installation by definition.
    1110              : 
    1111           92 :     ReturnErrorOnFailure(certSet.Init(&certData, 1));
    1112              : 
    1113           92 :     ReturnErrorOnFailure(certSet.LoadCert(rcac, CertDecodeFlags::kGenerateTBSHash));
    1114              : 
    1115           44 :     ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kRoot));
    1116              : 
    1117           10 :     VerifyOrReturnError(certData.mSubjectDN.IsEqual(certData.mIssuerDN), CHIP_ERROR_WRONG_CERT_TYPE);
    1118              : 
    1119           10 :     VerifyOrReturnError(certData.mSubjectKeyId.data_equal(certData.mAuthKeyId), CHIP_ERROR_WRONG_CERT_TYPE);
    1120              : 
    1121            9 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kIsCA), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    1122            7 :     if (certData.mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
    1123              :     {
    1124            1 :         VerifyOrReturnError(certData.mPathLenConstraint <= 1, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    1125              :     }
    1126              : 
    1127            7 :     VerifyOrReturnError(certData.mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    1128              : 
    1129            5 :     return VerifyCertSignature(certData, certData);
    1130           92 : }
    1131              : 
    1132          182 : CHIP_ERROR ConvertIntegerDERToRaw(ByteSpan derInt, uint8_t * rawInt, const uint16_t rawIntLen)
    1133              : {
    1134          182 :     VerifyOrReturnError(!derInt.empty(), CHIP_ERROR_INVALID_ARGUMENT);
    1135          182 :     VerifyOrReturnError(rawInt != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1136              : 
    1137          182 :     const uint8_t * derIntData = derInt.data();
    1138          182 :     size_t derIntLen           = derInt.size();
    1139              : 
    1140              :     /* one leading zero is allowed for positive integer in ASN1 DER format */
    1141          182 :     if (*derIntData == 0)
    1142              :     {
    1143           87 :         derIntData++;
    1144           87 :         derIntLen--;
    1145              :     }
    1146              : 
    1147          182 :     VerifyOrReturnError(derIntLen <= rawIntLen, CHIP_ERROR_INVALID_ARGUMENT);
    1148              : 
    1149          182 :     if (derIntLen > 0)
    1150              :     {
    1151          182 :         VerifyOrReturnError(*derIntData != 0, CHIP_ERROR_INVALID_ARGUMENT);
    1152              :     }
    1153              : 
    1154          182 :     memset(rawInt, 0, (rawIntLen - derIntLen));
    1155          182 :     memcpy(rawInt + (rawIntLen - derIntLen), derIntData, derIntLen);
    1156              : 
    1157          182 :     return CHIP_NO_ERROR;
    1158              : }
    1159              : 
    1160            0 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, MutableByteSpan & derSig)
    1161              : {
    1162            0 :     VerifyOrReturnError(derSig.size() >= kMax_ECDSA_Signature_Length_Der, CHIP_ERROR_BUFFER_TOO_SMALL);
    1163              : 
    1164              :     ASN1Writer writer;
    1165            0 :     writer.Init(derSig);
    1166            0 :     ReturnErrorOnFailure(ConvertECDSASignatureRawToDER(rawSig, writer));
    1167            0 :     derSig.reduce_size(writer.GetLengthWritten());
    1168              : 
    1169            0 :     return CHIP_NO_ERROR;
    1170              : }
    1171              : 
    1172           93 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, ASN1Writer & writer)
    1173              : {
    1174           93 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1175              :     uint8_t derInt[kP256_FE_Length + kEmitDerIntegerWithoutTagOverhead];
    1176              : 
    1177              :     // Ecdsa-Sig-Value ::= SEQUENCE
    1178           93 :     ASN1_START_SEQUENCE
    1179              :     {
    1180              :         // r INTEGER
    1181              :         {
    1182           93 :             MutableByteSpan derIntSpan(derInt, sizeof(derInt));
    1183           93 :             ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data()), derIntSpan));
    1184           93 :             ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
    1185              :                                                  static_cast<uint16_t>(derIntSpan.size())));
    1186              :         }
    1187              : 
    1188              :         // s INTEGER
    1189              :         {
    1190           93 :             MutableByteSpan derIntSpan(derInt, sizeof(derInt));
    1191           93 :             ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data() + kP256_FE_Length), derIntSpan));
    1192           93 :             ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
    1193              :                                                  static_cast<uint16_t>(derIntSpan.size())));
    1194              :         }
    1195              :     }
    1196           93 :     ASN1_END_SEQUENCE;
    1197              : 
    1198           93 : exit:
    1199           93 :     return err;
    1200              : }
    1201              : 
    1202            1 : CHIP_ERROR ConvertECDSAKeypairRawToDER(const P256SerializedKeypair & rawKeypair, MutableByteSpan & outDerKeypair)
    1203              : {
    1204            1 :     CHIP_ERROR err = CHIP_NO_ERROR;
    1205              : 
    1206              :     // The raw key pair contains the public key followed by the private key
    1207            1 :     VerifyOrReturnError(rawKeypair.Length() == kP256_PublicKey_Length + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT);
    1208            1 :     FixedByteSpan<kP256_PublicKey_Length> publicKey(rawKeypair.ConstBytes());
    1209            1 :     FixedByteSpan<kP256_PrivateKey_Length> privateKey(rawKeypair.ConstBytes() + kP256_PublicKey_Length);
    1210              : 
    1211              :     ASN1Writer writer;
    1212            1 :     writer.Init(outDerKeypair);
    1213              : 
    1214              :     // ECPrivateKey ::= SEQUENCE
    1215            1 :     ASN1_START_SEQUENCE
    1216              :     {
    1217              :         // version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1)
    1218            1 :         ASN1_ENCODE_INTEGER(1);
    1219              : 
    1220              :         // privateKey OCTET STRING
    1221            1 :         ASN1_ENCODE_OCTET_STRING(privateKey.data(), privateKey.size());
    1222              : 
    1223              :         // parameters [0] ECParameters {{ NamedCurve }} OPTIONAL
    1224            1 :         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0);
    1225              :         {
    1226            1 :             ASN1_ENCODE_OBJECT_ID(kOID_EllipticCurve_prime256v1);
    1227              :         }
    1228            1 :         ASN1_END_CONSTRUCTED;
    1229              : 
    1230              :         // publicKey  [1] BIT STRING OPTIONAL
    1231            1 :         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 1);
    1232              :         {
    1233            1 :             ReturnErrorOnFailure(writer.PutBitString(0, publicKey.data(), publicKey.size()));
    1234              :         }
    1235            1 :         ASN1_END_CONSTRUCTED;
    1236              :     }
    1237            1 :     ASN1_END_SEQUENCE;
    1238              : 
    1239            1 :     outDerKeypair.reduce_size(writer.GetLengthWritten());
    1240            1 : exit:
    1241            1 :     return err;
    1242              : }
    1243              : 
    1244          836 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ChipCertificateData & opcert, NodeId * outNodeId, FabricId * outFabricId)
    1245              : {
    1246              :     // Since we assume the cert is pre-validated, we are going to assume that
    1247              :     // its subject in fact has both a node id and a fabric id.
    1248          836 :     VerifyOrReturnError(outNodeId != nullptr && outFabricId != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    1249          836 :     NodeId nodeId      = 0;
    1250          836 :     FabricId fabricId  = kUndefinedFabricId;
    1251          836 :     bool foundNodeId   = false;
    1252          836 :     bool foundFabricId = false;
    1253              : 
    1254          836 :     const ChipDN & subjectDN = opcert.mSubjectDN;
    1255         2552 :     for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    1256              :     {
    1257         1716 :         const auto & rdn = subjectDN.rdn[i];
    1258         1716 :         if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterNodeId)
    1259              :         {
    1260          836 :             nodeId      = rdn.mChipVal;
    1261          836 :             foundNodeId = true;
    1262              :         }
    1263          880 :         else if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
    1264              :         {
    1265          836 :             fabricId      = rdn.mChipVal;
    1266          836 :             foundFabricId = true;
    1267              :         }
    1268              :     }
    1269          836 :     if (!foundNodeId || !foundFabricId)
    1270              :     {
    1271            0 :         return CHIP_ERROR_NOT_FOUND;
    1272              :     }
    1273              : 
    1274          836 :     *outNodeId   = nodeId;
    1275          836 :     *outFabricId = fabricId;
    1276          836 :     return CHIP_NO_ERROR;
    1277              : }
    1278              : 
    1279           10 : CHIP_ERROR ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
    1280              :                                                               FabricId & fabricId, NodeId & nodeId)
    1281              : {
    1282           10 :     Crypto::P256PublicKey rootPubKey;
    1283           10 :     Credentials::P256PublicKeySpan rootPubKeySpan;
    1284           10 :     ReturnErrorOnFailure(ExtractPublicKeyFromChipCert(rcac, rootPubKeySpan));
    1285           10 :     rootPubKey = Crypto::P256PublicKey(rootPubKeySpan);
    1286           10 :     ReturnErrorOnFailure(Credentials::ExtractNodeIdFabricIdFromOpCert(noc, &nodeId, &fabricId));
    1287           10 :     ReturnErrorOnFailure(GenerateCompressedFabricId(rootPubKey, fabricId, compressedFabricId));
    1288           10 :     return CHIP_NO_ERROR;
    1289           10 : }
    1290              : 
    1291            0 : CHIP_ERROR ExtractNodeIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
    1292              :                                                       NodeId & nodeId)
    1293              : {
    1294              :     FabricId fabricId;
    1295            0 :     ReturnErrorOnFailure(ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(rcac, noc, compressedFabricId, fabricId, nodeId));
    1296            0 :     return CHIP_NO_ERROR;
    1297              : }
    1298              : 
    1299         1471 : CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId * fabricId)
    1300              : {
    1301         1471 :     const ChipDN & subjectDN = cert.mSubjectDN;
    1302         2935 :     for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    1303              :     {
    1304         2170 :         const auto & rdn = subjectDN.rdn[i];
    1305         2170 :         if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
    1306              :         {
    1307          706 :             *fabricId = rdn.mChipVal;
    1308          706 :             return CHIP_NO_ERROR;
    1309              :         }
    1310              :     }
    1311              : 
    1312          765 :     return CHIP_ERROR_NOT_FOUND;
    1313              : }
    1314              : 
    1315           28 : CHIP_ERROR ExtractCATsFromOpCert(const ByteSpan & opcert, CATValues & cats)
    1316              : {
    1317           28 :     ChipCertificateSet certSet;
    1318           28 :     ChipCertificateData certData;
    1319              : 
    1320           28 :     ReturnErrorOnFailure(certSet.Init(&certData, 1));
    1321              : 
    1322           28 :     ReturnErrorOnFailure(certSet.LoadCert(opcert, BitFlags<CertDecodeFlags>()));
    1323              : 
    1324           27 :     return ExtractCATsFromOpCert(certData, cats);
    1325           28 : }
    1326              : 
    1327           38 : CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, CATValues & cats)
    1328              : {
    1329           38 :     uint8_t catCount = 0;
    1330              :     CertType certType;
    1331              : 
    1332           38 :     ReturnErrorOnFailure(opcert.mSubjectDN.GetCertType(certType));
    1333           38 :     VerifyOrReturnError(certType == CertType::kNode, CHIP_ERROR_INVALID_ARGUMENT);
    1334              : 
    1335           37 :     const ChipDN & subjectDN = opcert.mSubjectDN;
    1336          135 :     for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    1337              :     {
    1338           98 :         const auto & rdn = subjectDN.rdn[i];
    1339           98 :         if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterCASEAuthTag)
    1340              :         {
    1341              :             // This error should never happen in practice because valid NOC cannot have more
    1342              :             // than kMaxSubjectCATAttributeCount CATs in its subject. The check that it is
    1343              :             // valid NOC was done above.
    1344           18 :             VerifyOrReturnError(catCount != cats.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
    1345           18 :             VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn.mChipVal), CHIP_ERROR_INVALID_ARGUMENT);
    1346           18 :             cats.values[catCount++] = static_cast<CASEAuthTag>(rdn.mChipVal);
    1347              :         }
    1348              :     }
    1349          130 :     for (size_t i = catCount; i < cats.size(); ++i)
    1350              :     {
    1351           93 :         cats.values[i] = kUndefinedCAT;
    1352              :     }
    1353              : 
    1354              :     // Make sure the set contained valid data, otherwise it's an invalid cert
    1355           37 :     VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_WRONG_CERT_DN);
    1356              : 
    1357           36 :     return CHIP_NO_ERROR;
    1358              : }
    1359              : 
    1360           11 : CHIP_ERROR ExtractFabricIdFromCert(const ByteSpan & opcert, FabricId * fabricId)
    1361              : {
    1362           11 :     ChipCertificateData certData;
    1363           11 :     ReturnErrorOnFailure(DecodeChipCert(opcert, certData));
    1364           11 :     return ExtractFabricIdFromCert(certData, fabricId);
    1365           11 : }
    1366              : 
    1367           97 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ByteSpan & opcert, NodeId * nodeId, FabricId * fabricId)
    1368              : {
    1369           97 :     ChipCertificateData certData;
    1370           97 :     ReturnErrorOnFailure(DecodeChipCert(opcert, certData));
    1371           97 :     return ExtractNodeIdFabricIdFromOpCert(certData, nodeId, fabricId);
    1372           97 : }
    1373              : 
    1374           92 : CHIP_ERROR ExtractPublicKeyFromChipCert(const ByteSpan & chipCert, P256PublicKeySpan & publicKey)
    1375              : {
    1376           92 :     ChipCertificateData certData;
    1377           92 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1378           92 :     publicKey = certData.mPublicKey;
    1379           92 :     return CHIP_NO_ERROR;
    1380           92 : }
    1381              : 
    1382           24 : CHIP_ERROR ExtractNotBeforeFromChipCert(const ByteSpan & chipCert, chip::System::Clock::Seconds32 & notBeforeChipEpochTime)
    1383              : {
    1384           24 :     ChipCertificateData certData;
    1385           24 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1386           24 :     notBeforeChipEpochTime = chip::System::Clock::Seconds32(certData.mNotBeforeTime);
    1387           24 :     return CHIP_NO_ERROR;
    1388           24 : }
    1389              : 
    1390           16 : CHIP_ERROR ExtractSKIDFromChipCert(const ByteSpan & chipCert, CertificateKeyId & skid)
    1391              : {
    1392           16 :     ChipCertificateData certData;
    1393           16 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1394           16 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_AuthKeyId), CHIP_ERROR_NOT_FOUND);
    1395           15 :     skid = certData.mSubjectKeyId;
    1396           15 :     return CHIP_NO_ERROR;
    1397           16 : }
    1398              : 
    1399           31 : CHIP_ERROR ExtractSubjectDNFromChipCert(const ByteSpan & chipCert, ChipDN & dn)
    1400              : {
    1401           31 :     ChipCertificateData certData;
    1402           31 :     ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
    1403           31 :     dn = certData.mSubjectDN;
    1404           31 :     return CHIP_NO_ERROR;
    1405           31 : }
    1406              : 
    1407            6 : CHIP_ERROR ExtractSubjectDNFromX509Cert(const ByteSpan & x509Cert, ChipDN & dn)
    1408              : {
    1409              :     CHIP_ERROR err;
    1410              :     ASN1Reader reader;
    1411              : 
    1412            6 :     VerifyOrReturnError(CanCastTo<uint32_t>(x509Cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1413              : 
    1414            6 :     reader.Init(x509Cert);
    1415              : 
    1416              :     // Certificate ::= SEQUENCE
    1417            6 :     ASN1_PARSE_ENTER_SEQUENCE
    1418              :     {
    1419              :         // tbsCertificate TBSCertificate,
    1420              :         // TBSCertificate ::= SEQUENCE
    1421            6 :         ASN1_PARSE_ENTER_SEQUENCE
    1422              :         {
    1423              :             // Skip version [0] EXPLICIT Version DEFAULT v1
    1424            6 :             ASN1_PARSE_ELEMENT(kASN1TagClass_ContextSpecific, 0);
    1425              : 
    1426              :             // Skip serialNumber CertificateSerialNumber
    1427            6 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
    1428              : 
    1429              :             // Skip signature AlgorithmIdentifier
    1430            6 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
    1431              : 
    1432              :             // Skip issuer Name
    1433            6 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
    1434              : 
    1435              :             // Skip validity Validity,
    1436            6 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
    1437              : 
    1438              :             // Decode subject Name,
    1439            6 :             ReturnErrorOnFailure(dn.DecodeFromASN1(reader));
    1440              :         }
    1441            6 :         ASN1_SKIP_AND_EXIT_SEQUENCE;
    1442              :     }
    1443            6 :     ASN1_SKIP_AND_EXIT_SEQUENCE;
    1444              : 
    1445            6 : exit:
    1446            6 :     return err;
    1447              : }
    1448              : 
    1449          181 : CHIP_ERROR CertificateValidityPolicy::ApplyDefaultPolicy(const ChipCertificateData * cert, uint8_t depth,
    1450              :                                                          CertificateValidityResult result)
    1451              : {
    1452          181 :     switch (result)
    1453              :     {
    1454          175 :     case CertificateValidityResult::kValid:
    1455              :     case CertificateValidityResult::kNotExpiredAtLastKnownGoodTime:
    1456              :     // By default, we do not enforce certificate validity based upon a Last
    1457              :     // Known Good Time source.  However, implementations may always inject a
    1458              :     // policy that does enforce based upon this.
    1459              :     case CertificateValidityResult::kExpiredAtLastKnownGoodTime:
    1460              :     case CertificateValidityResult::kTimeUnknown:
    1461          175 :         return CHIP_NO_ERROR;
    1462              : 
    1463            3 :     case CertificateValidityResult::kNotYetValid:
    1464            3 :         return CHIP_ERROR_CERT_NOT_VALID_YET;
    1465              : 
    1466            3 :     case CertificateValidityResult::kExpired:
    1467            3 :         return CHIP_ERROR_CERT_EXPIRED;
    1468              : 
    1469            0 :     default:
    1470            0 :         return CHIP_ERROR_INTERNAL;
    1471              :     }
    1472              : }
    1473              : 
    1474           15 : void InitNetworkIdentitySubject(ChipDN & name)
    1475              : {
    1476           15 :     name.Clear();
    1477           15 :     CHIP_ERROR err = name.AddAttribute_CommonName(kNetworkIdentityCN, /* not printable */ false);
    1478           15 :     VerifyOrDie(err == CHIP_NO_ERROR); // AddAttribute can't fail in this case
    1479           15 : }
    1480              : 
    1481            4 : static CHIP_ERROR CalculateKeyIdentifierSha256(const P256PublicKeySpan & publicKey, MutableCertificateKeyId outKeyId)
    1482              : {
    1483              :     uint8_t hash[kSHA256_Hash_Length];
    1484              :     static_assert(outKeyId.size() <= sizeof(hash)); // truncating 32 bytes down to 20
    1485            4 :     ReturnErrorOnFailure(Hash_SHA256(publicKey.data(), publicKey.size(), hash));
    1486            4 :     memcpy(outKeyId.data(), hash, outKeyId.size());
    1487            4 :     return CHIP_NO_ERROR;
    1488              : }
    1489              : 
    1490            6 : static CHIP_ERROR ValidateChipNetworkIdentity(const ChipCertificateData & certData)
    1491              : {
    1492            6 :     ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kNetworkIdentity));
    1493              : 
    1494            6 :     VerifyOrReturnError(certData.mSerialNumber.data_equal(kNetworkIdentitySerialNumberBytes), CHIP_ERROR_WRONG_CERT_TYPE);
    1495            6 :     VerifyOrReturnError(certData.mNotBeforeTime == kNetworkIdentityNotBeforeTime, CHIP_ERROR_WRONG_CERT_TYPE);
    1496            6 :     VerifyOrReturnError(certData.mNotAfterTime == kNetworkIdentityNotAfterTime, CHIP_ERROR_WRONG_CERT_TYPE);
    1497            6 :     VerifyOrReturnError(certData.mIssuerDN.IsEqual(certData.mSubjectDN), CHIP_ERROR_WRONG_CERT_TYPE);
    1498              : 
    1499            6 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_BasicConstraints) &&
    1500              :                             !certData.mCertFlags.Has(CertFlags::kIsCA),
    1501              :                         CHIP_ERROR_WRONG_CERT_TYPE);
    1502            6 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) &&
    1503              :                             certData.mKeyUsageFlags == kNetworkIdentityKeyUsage,
    1504              :                         CHIP_ERROR_WRONG_CERT_TYPE);
    1505            6 :     VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) &&
    1506              :                             certData.mKeyPurposeFlags == kNetworkIdentityKeyPurpose,
    1507              :                         CHIP_ERROR_WRONG_CERT_TYPE);
    1508              : 
    1509            6 :     ReturnErrorOnFailure(VerifyCertSignature(certData, certData));
    1510            6 :     return CHIP_NO_ERROR;
    1511              : }
    1512              : 
    1513            4 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert)
    1514              : {
    1515            4 :     ChipCertificateData certData;
    1516            4 :     ReturnErrorOnFailure(DecodeChipCert(cert, certData, CertDecodeFlags::kGenerateTBSHash));
    1517            4 :     ReturnErrorOnFailure(ValidateChipNetworkIdentity(certData));
    1518            4 :     return CHIP_NO_ERROR;
    1519            4 : }
    1520              : 
    1521            2 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId)
    1522              : {
    1523            2 :     ChipCertificateData certData;
    1524            2 :     ReturnErrorOnFailure(DecodeChipCert(cert, certData, CertDecodeFlags::kGenerateTBSHash));
    1525            2 :     ReturnErrorOnFailure(ValidateChipNetworkIdentity(certData));
    1526            2 :     ReturnErrorOnFailure(CalculateKeyIdentifierSha256(certData.mPublicKey, outKeyId));
    1527            2 :     return CHIP_NO_ERROR;
    1528            2 : }
    1529              : 
    1530            2 : CHIP_ERROR ExtractIdentifierFromChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId)
    1531              : {
    1532            2 :     ChipCertificateData certData;
    1533            2 :     ReturnErrorOnFailure(DecodeChipCert(cert, certData));
    1534            2 :     ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kNetworkIdentity));
    1535            2 :     ReturnErrorOnFailure(CalculateKeyIdentifierSha256(certData.mPublicKey, outKeyId));
    1536            2 :     return CHIP_NO_ERROR;
    1537            2 : }
    1538              : 
    1539            1 : static CHIP_ERROR GenerateNetworkIdentitySignature(const P256Keypair & keypair, P256ECDSASignature & signature)
    1540              : {
    1541              :     // Create a buffer and writer to capture the TBS (to-be-signed) portion of the certificate.
    1542            1 :     chip::Platform::ScopedMemoryBuffer<uint8_t> asn1TBSBuf;
    1543            1 :     VerifyOrReturnError(asn1TBSBuf.Alloc(kNetworkIdentityTBSLength), CHIP_ERROR_NO_MEMORY);
    1544              : 
    1545              :     ASN1Writer writer;
    1546            1 :     writer.Init(asn1TBSBuf.Get(), kNetworkIdentityTBSLength);
    1547              : 
    1548              :     // Generate the TBSCertificate and sign it
    1549            1 :     ReturnErrorOnFailure(EncodeNetworkIdentityTBSCert(keypair.Pubkey(), writer));
    1550            1 :     ReturnErrorOnFailure(keypair.ECDSA_sign_msg(asn1TBSBuf.Get(), writer.GetLengthWritten(), signature));
    1551              : 
    1552            1 :     return CHIP_NO_ERROR;
    1553            1 : }
    1554              : 
    1555            1 : static CHIP_ERROR EncodeCompactIdentityCert(TLVWriter & writer, Tag tag, const P256PublicKeySpan & publicKey,
    1556              :                                             const P256ECDSASignatureSpan & signature)
    1557              : {
    1558              :     TLVType containerType;
    1559            1 :     ReturnErrorOnFailure(writer.StartContainer(tag, kTLVType_Structure, containerType));
    1560            1 :     ReturnErrorOnFailure(writer.Put(ContextTag(kTag_EllipticCurvePublicKey), publicKey));
    1561            1 :     ReturnErrorOnFailure(writer.Put(ContextTag(kTag_ECDSASignature), signature));
    1562            1 :     ReturnErrorOnFailure(writer.EndContainer(containerType));
    1563            1 :     return CHIP_NO_ERROR;
    1564              : }
    1565              : 
    1566            1 : CHIP_ERROR NewChipNetworkIdentity(const Crypto::P256Keypair & keypair, MutableByteSpan & outCompactCert)
    1567              : {
    1568            1 :     VerifyOrReturnError(!outCompactCert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
    1569            1 :     VerifyOrReturnError(CanCastTo<uint32_t>(outCompactCert.size()), CHIP_ERROR_INVALID_ARGUMENT);
    1570              : 
    1571            1 :     Crypto::P256ECDSASignature signature;
    1572            1 :     ReturnErrorOnFailure(GenerateNetworkIdentitySignature(keypair, signature));
    1573              : 
    1574            1 :     TLVWriter writer;
    1575            1 :     writer.Init(outCompactCert);
    1576              : 
    1577            1 :     P256PublicKeySpan publicKeySpan(keypair.Pubkey().ConstBytes());
    1578            1 :     P256ECDSASignatureSpan signatureSpan(signature.ConstBytes());
    1579            1 :     ReturnErrorOnFailure(EncodeCompactIdentityCert(writer, AnonymousTag(), publicKeySpan, signatureSpan));
    1580              : 
    1581            1 :     outCompactCert.reduce_size(writer.GetLengthWritten());
    1582            1 :     return CHIP_NO_ERROR;
    1583            1 : }
    1584              : 
    1585              : } // namespace Credentials
    1586              : } // namespace chip
        

Generated by: LCOV version 2.0-1