LCOV - code coverage report
Current view: top level - credentials - CHIPCert.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 669 700 95.6 %
Date: 2024-02-15 08:20:41 Functions: 64 69 92.8 %

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

Generated by: LCOV version 1.14