/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *    Copyright (c) 2019 Google LLC.
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file implements objects for modeling and working with
 *      CHIP certificates.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <stddef.h>

#include <credentials/CHIPCert.h>
#include <credentials/CHIPCertificateSet.h>
#include <lib/asn1/ASN1.h>
#include <lib/asn1/ASN1Macros.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/TLV.h>
#include <lib/support/BytesToHex.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/ScopedBuffer.h>
#include <lib/support/TimeUtils.h>
#include <protocols/Protocols.h>

namespace chip {
namespace Credentials {

using namespace chip::ASN1;
using namespace chip::TLV;
using namespace chip::Protocols;
using namespace chip::Crypto;

extern CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData);
extern CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData);

ChipCertificateSet::ChipCertificateSet()
{
    mCerts               = nullptr;
    mCertCount           = 0;
    mMaxCerts            = 0;
    mMemoryAllocInternal = false;
}

ChipCertificateSet::~ChipCertificateSet()
{
    Release();
}

CHIP_ERROR ChipCertificateSet::Init(uint8_t maxCertsArraySize)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(maxCertsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
    mCerts = reinterpret_cast<ChipCertificateData *>(chip::Platform::MemoryAlloc(sizeof(ChipCertificateData) * maxCertsArraySize));
    VerifyOrExit(mCerts != nullptr, err = CHIP_ERROR_NO_MEMORY);

    mMaxCerts            = maxCertsArraySize;
    mMemoryAllocInternal = true;

    Clear();

exit:
    if (err != CHIP_NO_ERROR)
    {
        Release();
    }

    return err;
}

CHIP_ERROR ChipCertificateSet::Init(ChipCertificateData * certsArray, uint8_t certsArraySize)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    VerifyOrExit(certsArray != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrExit(certsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);

    mCerts               = certsArray;
    mMaxCerts            = certsArraySize;
    mMemoryAllocInternal = false;

    Clear();

exit:
    return err;
}

void ChipCertificateSet::Release()
{
    if (mMemoryAllocInternal)
    {
        if (mCerts != nullptr)
        {
            Clear();
            chip::Platform::MemoryFree(mCerts);
            mCerts = nullptr;
        }
    }
}

void ChipCertificateSet::Clear()
{
    for (int i = 0; i < mMaxCerts; i++)
    {
        mCerts[i].Clear();
    }

    mCertCount = 0;
}

CHIP_ERROR ChipCertificateSet::LoadCert(const ByteSpan chipCert, BitFlags<CertDecodeFlags> decodeFlags)
{
    TLVReader reader;

    reader.Init(chipCert);

    ReturnErrorOnFailure(reader.Next(kTLVType_Structure, AnonymousTag()));

    return LoadCert(reader, decodeFlags, chipCert);
}

CHIP_ERROR ChipCertificateSet::LoadCert(TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags, ByteSpan chipCert)
{
    ASN1Writer writer; // ASN1Writer is used to encode TBS portion of the certificate for the purpose of signature
                       // validation, which should be performed on the TBS data encoded in ASN.1 DER form.
    ChipCertificateData cert;
    cert.Clear();

    // Must be positioned on the structure element representing the certificate.
    VerifyOrReturnError(reader.GetType() == kTLVType_Structure, CHIP_ERROR_INVALID_ARGUMENT);

    cert.mCertificate = chipCert;

    {
        TLVType containerType;

        // Enter the certificate structure...
        ReturnErrorOnFailure(reader.EnterContainer(containerType));

        // If requested to generate the TBSHash.
        if (decodeFlags.Has(CertDecodeFlags::kGenerateTBSHash))
        {
            chip::Platform::ScopedMemoryBuffer<uint8_t> asn1TBSBuf;
            ReturnErrorCodeIf(!asn1TBSBuf.Alloc(kMaxCHIPCertDecodeBufLength), CHIP_ERROR_NO_MEMORY);

            // Initialize an ASN1Writer and convert the TBS (to-be-signed) portion of the certificate to ASN.1 DER
            // encoding. At the same time, parse various components within the certificate and set the corresponding
            // fields in the CertificateData object.
            writer.Init(asn1TBSBuf.Get(), kMaxCHIPCertDecodeBufLength);
            ReturnErrorOnFailure(DecodeConvertTBSCert(reader, writer, cert));

            // Generate a SHA hash of the encoded TBS certificate.
            chip::Crypto::Hash_SHA256(asn1TBSBuf.Get(), writer.GetLengthWritten(), cert.mTBSHash);

            cert.mCertFlags.Set(CertFlags::kTBSHashPresent);
        }
        else
        {
            // Initialize an ASN1Writer as a NullWriter.
            writer.InitNullWriter();
            ReturnErrorOnFailure(DecodeConvertTBSCert(reader, writer, cert));
        }

        // Verify the cert has both the Subject Key Id and Authority Key Id extensions present.
        // Only certs with both these extensions are supported for the purposes of certificate validation.
        VerifyOrReturnError(cert.mCertFlags.HasAll(CertFlags::kExtPresent_SubjectKeyId, CertFlags::kExtPresent_AuthKeyId),
                            CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);

        // Verify the cert was signed with ECDSA-SHA256. This is the only signature algorithm currently supported.
        VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);

        // Decode the certificate's signature...
        ReturnErrorOnFailure(DecodeECDSASignature(reader, cert));

        // Verify no more elements in the certificate.
        ReturnErrorOnFailure(reader.VerifyEndOfContainer());

        ReturnErrorOnFailure(reader.ExitContainer(containerType));
    }

    // If requested by the caller, mark the certificate as trusted.
    if (decodeFlags.Has(CertDecodeFlags::kIsTrustAnchor))
    {
        cert.mCertFlags.Set(CertFlags::kIsTrustAnchor);
    }

    // Check if this cert matches any currently loaded certificates
    for (uint32_t i = 0; i < mCertCount; i++)
    {
        if (cert.IsEqual(mCerts[i]))
        {
            // This cert is already loaded. Let's skip adding this cert.
            return CHIP_NO_ERROR;
        }
    }

    // Verify we have room for the new certificate.
    VerifyOrReturnError(mCertCount < mMaxCerts, CHIP_ERROR_NO_MEMORY);

    new (&mCerts[mCertCount]) ChipCertificateData(cert);
    mCertCount++;

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipCertificateSet::ReleaseLastCert()
{
    ChipCertificateData * lastCert = (mCertCount > 0) ? &mCerts[mCertCount - 1] : nullptr;
    VerifyOrReturnError(lastCert != nullptr, CHIP_ERROR_INTERNAL);

    lastCert->~ChipCertificateData();
    --mCertCount;

    return CHIP_NO_ERROR;
}

const ChipCertificateData * ChipCertificateSet::FindCert(const CertificateKeyId & subjectKeyId) const
{
    for (uint8_t i = 0; i < mCertCount; i++)
    {
        ChipCertificateData & cert = mCerts[i];
        if (cert.mSubjectKeyId.data_equal(subjectKeyId))
        {
            return &cert;
        }
    }

    return nullptr;
}

bool ChipCertificateSet::IsCertInTheSet(const ChipCertificateData * cert) const
{
    for (uint8_t i = 0; i < mCertCount; i++)
    {
        if (cert == &mCerts[i])
        {
            return true;
        }
    }

    return false;
}

CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context)
{
    VerifyOrReturnError(IsCertInTheSet(cert), CHIP_ERROR_INVALID_ARGUMENT);

    context.mTrustAnchor = nullptr;

    return ValidateCert(cert, context, 0);
}

CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
                                             ValidationContext & context, const ChipCertificateData ** certData)
{
    context.mTrustAnchor = nullptr;

    return FindValidCert(subjectDN, subjectKeyId, context, 0, certData);
}

CHIP_ERROR ChipCertificateSet::VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert)
{
#ifdef ENABLE_HSM_ECDSA_VERIFY
    P256PublicKeyHSM caPublicKey;
#else
    P256PublicKey caPublicKey;
#endif
    P256ECDSASignature signature;

    VerifyOrReturnError((cert != nullptr) && (caCert != nullptr), CHIP_ERROR_INVALID_ARGUMENT);
    ReturnErrorOnFailure(signature.SetLength(cert->mSignature.size()));
    memcpy(signature.Bytes(), cert->mSignature.data(), cert->mSignature.size());

    memcpy(caPublicKey, caCert->mPublicKey.data(), caCert->mPublicKey.size());

    ReturnErrorOnFailure(caPublicKey.ECDSA_validate_hash_signature(cert->mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature));

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context, uint8_t depth)
{
    CHIP_ERROR err                     = CHIP_NO_ERROR;
    const ChipCertificateData * caCert = nullptr;
    CertType certType;

    err = cert->mSubjectDN.GetCertType(certType);
    SuccessOrExit(err);

    // Certificate with future-extension marked as "critical" is not allowed.
    VerifyOrExit(!cert->mCertFlags.Has(CertFlags::kExtPresent_FutureIsCritical), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);

    // If the depth is greater than 0 then the certificate is required to be a CA certificate...
    if (depth > 0)
    {
        // Verify the isCA flag is present.
        VerifyOrExit(cert->mCertFlags.Has(CertFlags::kIsCA), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);

        // Verify the key usage extension is present and contains the 'keyCertSign' flag.
        VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && cert->mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign),
                     err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);

        // Verify that the certificate type is set to Root or ICA.
        VerifyOrExit(certType == CertType::kICA || certType == CertType::kRoot, err = CHIP_ERROR_WRONG_CERT_TYPE);

        // If a path length constraint was included, verify the cert depth vs. the specified constraint.
        //
        // From the RFC, the path length constraint "gives the maximum number of non-self-issued
        // intermediate certificates that may follow this certificate in a valid certification path.
        // (Note: The last certificate in the certification path is not an intermediate certificate,
        // and is not included in this limit...)"
        //
        if (cert->mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
        {
            VerifyOrExit((depth - 1) <= cert->mPathLenConstraint, err = CHIP_ERROR_CERT_PATH_LEN_CONSTRAINT_EXCEEDED);
        }
    }

    // Otherwise verify the desired certificate usages/purposes/type given in the validation context...
    else
    {
        // If a set of desired key usages has been specified, verify that the key usage extension exists
        // in the certificate and that the corresponding usages are supported.
        if (context.mRequiredKeyUsages.HasAny())
        {
            VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) &&
                             cert->mKeyUsageFlags.HasAll(context.mRequiredKeyUsages),
                         err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
        }

        // If a set of desired key purposes has been specified, verify that the extended key usage extension
        // exists in the certificate and that the corresponding purposes are supported.
        if (context.mRequiredKeyPurposes.HasAny())
        {
            VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) &&
                             cert->mKeyPurposeFlags.HasAll(context.mRequiredKeyPurposes),
                         err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
        }

        // If a required certificate type has been specified, verify it against the current certificate's type.
        if (context.mRequiredCertType != CertType::kNotSpecified)
        {
            VerifyOrExit(certType == context.mRequiredCertType, err = CHIP_ERROR_WRONG_CERT_TYPE);
        }
    }

    // Verify NotBefore and NotAfter validity of the certificates.
    //
    // See also ASN1ToChipEpochTime().
    //
    // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no
    // well-defined expiration date'.  In CHIP TLV-encoded certificates, this
    // special value is represented as a CHIP Epoch time value of 0 sec
    // (2000-01-01 00:00:00 UTC).
    CertificateValidityResult validityResult;
    if (context.mEffectiveTime.Is<CurrentChipEpochTime>())
    {
        if (context.mEffectiveTime.Get<CurrentChipEpochTime>().count() < cert->mNotBeforeTime)
        {
            ChipLogDetail(SecureChannel, "Certificate's mNotBeforeTime (%" PRIu32 ") is after current time (%" PRIu32 ")",
                          cert->mNotBeforeTime, context.mEffectiveTime.Get<CurrentChipEpochTime>().count());
            validityResult = CertificateValidityResult::kNotYetValid;
        }
        else if (cert->mNotAfterTime != kNullCertTime &&
                 context.mEffectiveTime.Get<CurrentChipEpochTime>().count() > cert->mNotAfterTime)
        {
            ChipLogDetail(SecureChannel, "Certificate's mNotAfterTime (%" PRIu32 ") is before current time (%" PRIu32 ")",
                          cert->mNotAfterTime, context.mEffectiveTime.Get<CurrentChipEpochTime>().count());
            validityResult = CertificateValidityResult::kExpired;
        }
        else
        {
            validityResult = CertificateValidityResult::kValid;
        }
    }
    else if (context.mEffectiveTime.Is<LastKnownGoodChipEpochTime>())
    {
        // Last Known Good Time may not be moved forward except at the time of
        // commissioning or firmware update, so we can't use it to validate
        // NotBefore.  However, so long as firmware build times are properly
        // recorded and certificates loaded during commissioning are in fact
        // valid at the time of commissioning, observing a NotAfter that falls
        // before Last Known Good Time is a reliable indicator that the
        // certificate in question is expired.  Check for this.
        if (cert->mNotAfterTime != 0 && context.mEffectiveTime.Get<LastKnownGoodChipEpochTime>().count() > cert->mNotAfterTime)
        {
            ChipLogDetail(SecureChannel, "Certificate's mNotAfterTime (%" PRIu32 ") is before last known good time (%" PRIu32 ")",
                          cert->mNotAfterTime, context.mEffectiveTime.Get<LastKnownGoodChipEpochTime>().count());
            validityResult = CertificateValidityResult::kExpiredAtLastKnownGoodTime;
        }
        else
        {
            validityResult = CertificateValidityResult::kNotExpiredAtLastKnownGoodTime;
        }
    }
    else
    {
        validityResult = CertificateValidityResult::kTimeUnknown;
    }

    if (context.mValidityPolicy != nullptr)
    {
        SuccessOrExit(err = context.mValidityPolicy->ApplyCertificateValidityPolicy(cert, depth, validityResult));
    }
    else
    {
        SuccessOrExit(err = CertificateValidityPolicy::ApplyDefaultPolicy(cert, depth, validityResult));
    }

    // If the certificate itself is trusted, then it is implicitly valid.  Record this certificate as the trust
    // anchor and return success.
    if (cert->mCertFlags.Has(CertFlags::kIsTrustAnchor))
    {
        context.mTrustAnchor = cert;
        ExitNow(err = CHIP_NO_ERROR);
    }

    // Otherwise we must validate the certificate by looking for a chain of valid certificates up to a trusted
    // certificate known as the 'trust anchor'.

    // Fail validation if the certificate is self-signed. Since we don't trust this certificate (see the check above) and
    // it has no path we can follow to a trust anchor, it can't be considered valid.
    if (cert->mIssuerDN.IsEqual(cert->mSubjectDN) && cert->mAuthKeyId.data_equal(cert->mSubjectKeyId))
    {
        ExitNow(err = CHIP_ERROR_CERT_NOT_TRUSTED);
    }

    // Verify that the certificate depth is less than the total number of certificates. It is technically possible to create
    // a circular chain of certificates.  Limiting the maximum depth of the certificate path prevents infinite
    // recursion in such a case.
    VerifyOrExit(depth < mCertCount, err = CHIP_ERROR_CERT_PATH_TOO_LONG);

    // Verify that a hash of the 'to-be-signed' portion of the certificate has been computed. We will need this to
    // verify the cert's signature below.
    VerifyOrExit(cert->mCertFlags.Has(CertFlags::kTBSHashPresent), err = CHIP_ERROR_INVALID_ARGUMENT);

    // Search for a valid CA certificate that matches the Issuer DN and Authority Key Id of the current certificate.
    // Fail if no acceptable certificate is found.
    err = FindValidCert(cert->mIssuerDN, cert->mAuthKeyId, context, static_cast<uint8_t>(depth + 1), &caCert);
    if (err != CHIP_NO_ERROR)
    {
        ExitNow(err = CHIP_ERROR_CA_CERT_NOT_FOUND);
    }

    // Verify signature of the current certificate against public key of the CA certificate. If signature verification
    // succeeds, the current certificate is valid.
    err = VerifySignature(cert, caCert);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
                                             ValidationContext & context, uint8_t depth, const ChipCertificateData ** certData)
{
    CHIP_ERROR err;

    *certData = nullptr;

    // Default error if we don't find any matching cert.
    err = (depth > 0) ? CHIP_ERROR_CA_CERT_NOT_FOUND : CHIP_ERROR_CERT_NOT_FOUND;

    // Fail immediately if neither of the input criteria are specified.
    if (subjectDN.IsEmpty() && subjectKeyId.empty())
    {
        ExitNow();
    }

    // For each cert in the set...
    for (uint8_t i = 0; i < mCertCount; i++)
    {
        ChipCertificateData * candidateCert = &mCerts[i];

        // Skip the certificate if its subject DN and key id do not match the input criteria.
        if (!subjectDN.IsEmpty() && !candidateCert->mSubjectDN.IsEqual(subjectDN))
        {
            continue;
        }
        if (!subjectKeyId.empty() && !candidateCert->mSubjectKeyId.data_equal(subjectKeyId))
        {
            continue;
        }

        // Attempt to validate the cert.  If the cert is valid, return it to the caller. Otherwise,
        // save the returned error and continue searching.  If there are no other matching certs this
        // will be the error returned to the caller.
        err = ValidateCert(candidateCert, context, depth);
        if (err == CHIP_NO_ERROR)
        {
            *certData = candidateCert;
            ExitNow();
        }
    }

exit:
    return err;
}

ChipCertificateData::ChipCertificateData() {}

ChipCertificateData::~ChipCertificateData() {}

void ChipCertificateData::Clear()
{
    mSubjectDN.Clear();
    mIssuerDN.Clear();
    mSubjectKeyId      = CertificateKeyId();
    mAuthKeyId         = CertificateKeyId();
    mNotBeforeTime     = 0;
    mNotAfterTime      = 0;
    mPublicKey         = P256PublicKeySpan();
    mPubKeyCurveOID    = 0;
    mPubKeyAlgoOID     = 0;
    mSigAlgoOID        = 0;
    mPathLenConstraint = 0;
    mCertFlags.ClearAll();
    mKeyUsageFlags.ClearAll();
    mKeyPurposeFlags.ClearAll();
    mSignature = P256ECDSASignatureSpan();

    memset(mTBSHash, 0, sizeof(mTBSHash));
}

bool ChipCertificateData::IsEqual(const ChipCertificateData & other) const
{
    // TODO - Add an operator== on BitFlags class.
    return mSubjectDN.IsEqual(other.mSubjectDN) && mIssuerDN.IsEqual(other.mIssuerDN) &&
        mSubjectKeyId.data_equal(other.mSubjectKeyId) && mAuthKeyId.data_equal(other.mAuthKeyId) &&
        (mNotBeforeTime == other.mNotBeforeTime) && (mNotAfterTime == other.mNotAfterTime) &&
        mPublicKey.data_equal(other.mPublicKey) && (mPubKeyCurveOID == other.mPubKeyCurveOID) &&
        (mPubKeyAlgoOID == other.mPubKeyAlgoOID) && (mSigAlgoOID == other.mSigAlgoOID) &&
        (mCertFlags.Raw() == other.mCertFlags.Raw()) && (mKeyUsageFlags.Raw() == other.mKeyUsageFlags.Raw()) &&
        (mKeyPurposeFlags.Raw() == other.mKeyPurposeFlags.Raw()) && (mPathLenConstraint == other.mPathLenConstraint) &&
        mSignature.data_equal(other.mSignature) && (memcmp(mTBSHash, other.mTBSHash, sizeof(mTBSHash)) == 0);
}

void ValidationContext::Reset()
{
    mEffectiveTime  = EffectiveTime{};
    mTrustAnchor    = nullptr;
    mValidityPolicy = nullptr;
    mRequiredKeyUsages.ClearAll();
    mRequiredKeyPurposes.ClearAll();
    mRequiredCertType = CertType::kNotSpecified;
}

bool ChipRDN::IsEqual(const ChipRDN & other) const
{
    if (mAttrOID == kOID_Unknown || mAttrOID == kOID_NotSpecified || mAttrOID != other.mAttrOID ||
        mAttrIsPrintableString != other.mAttrIsPrintableString)
    {
        return false;
    }

    if (IsChipDNAttr(mAttrOID))
    {
        return mChipVal == other.mChipVal;
    }

    return mString.data_equal(other.mString);
}

ChipDN::ChipDN()
{
    Clear();
}

ChipDN::~ChipDN() {}

void ChipDN::Clear()
{
    for (auto & dn : rdn)
    {
        dn.Clear();
    }
}

uint8_t ChipDN::RDNCount() const
{
    uint8_t count;

    for (count = 0; count < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES; count++)
    {
        if (rdn[count].IsEmpty())
        {
            break;
        }
    }

    return count;
}

CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, uint64_t val)
{
    uint8_t rdnCount = RDNCount();

    VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
    VerifyOrReturnError(IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);

    if (IsChip32bitDNAttr(oid))
    {
        VerifyOrReturnError(CanCastTo<uint32_t>(val), CHIP_ERROR_INVALID_ARGUMENT);
    }

    rdn[rdnCount].mAttrOID               = oid;
    rdn[rdnCount].mChipVal               = val;
    rdn[rdnCount].mAttrIsPrintableString = false;

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDN::AddCATs(const chip::CATValues & cats)
{
    VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_INVALID_ARGUMENT);

    for (auto & cat : cats.values)
    {
        if (cat != kUndefinedCAT)
        {
            ReturnErrorOnFailure(AddAttribute_MatterCASEAuthTag(cat));
        }
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, CharSpan val, bool isPrintableString)
{
    uint8_t rdnCount = RDNCount();

    VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
    VerifyOrReturnError(!IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(oid != kOID_NotSpecified, CHIP_ERROR_INVALID_ARGUMENT);

    rdn[rdnCount].mAttrOID               = oid;
    rdn[rdnCount].mString                = val;
    rdn[rdnCount].mAttrIsPrintableString = isPrintableString;

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDN::GetCertType(CertType & certType) const
{
    CertType lCertType   = CertType::kNotSpecified;
    bool fabricIdPresent = false;
    bool catsPresent     = false;
    uint8_t rdnCount     = RDNCount();

    certType = CertType::kNotSpecified;

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        if (rdn[i].mAttrOID == kOID_AttributeType_MatterRCACId)
        {
            VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);

            lCertType = CertType::kRoot;
        }
        else if (rdn[i].mAttrOID == kOID_AttributeType_MatterICACId)
        {
            VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);

            lCertType = CertType::kICA;
        }
        else if (rdn[i].mAttrOID == kOID_AttributeType_MatterNodeId)
        {
            VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
            VerifyOrReturnError(IsOperationalNodeId(rdn[i].mChipVal), CHIP_ERROR_WRONG_NODE_ID);
            lCertType = CertType::kNode;
        }
        else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFirmwareSigningId)
        {
            VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);

            lCertType = CertType::kFirmwareSigning;
        }
        else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFabricId)
        {
            // Only one fabricId attribute is allowed per DN.
            VerifyOrReturnError(!fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
            VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
            fabricIdPresent = true;
        }
        else if (rdn[i].mAttrOID == kOID_AttributeType_MatterCASEAuthTag)
        {
            VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
            VerifyOrReturnError(IsValidCASEAuthTag(static_cast<CASEAuthTag>(rdn[i].mChipVal)), CHIP_ERROR_WRONG_CERT_DN);
            catsPresent = true;
        }
    }

    if (lCertType == CertType::kNode)
    {
        VerifyOrReturnError(fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
    }
    else
    {
        VerifyOrReturnError(!catsPresent, CHIP_ERROR_WRONG_CERT_DN);
    }

    certType = lCertType;

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDN::GetCertChipId(uint64_t & chipId) const
{
    uint8_t rdnCount = RDNCount();

    chipId = 0;

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        switch (rdn[i].mAttrOID)
        {
        case kOID_AttributeType_MatterRCACId:
        case kOID_AttributeType_MatterICACId:
        case kOID_AttributeType_MatterNodeId:
        case kOID_AttributeType_MatterFirmwareSigningId:
            VerifyOrReturnError(chipId == 0, CHIP_ERROR_WRONG_CERT_DN);

            chipId = rdn[i].mChipVal;
            break;
        default:
            break;
        }
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDN::GetCertFabricId(uint64_t & fabricId) const
{
    uint8_t rdnCount = RDNCount();

    fabricId = kUndefinedFabricId;

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        switch (rdn[i].mAttrOID)
        {
        case kOID_AttributeType_MatterFabricId:
            // Ensure only one FabricID RDN present, since start value is kUndefinedFabricId, which is reserved and never seen.
            VerifyOrReturnError(fabricId == kUndefinedFabricId, CHIP_ERROR_WRONG_CERT_DN);
            VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
            fabricId = rdn[i].mChipVal;
            break;
        default:
            break;
        }
    }

    VerifyOrReturnError(IsValidFabricId(fabricId), CHIP_ERROR_WRONG_CERT_DN);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDN::EncodeToTLV(TLVWriter & writer, Tag tag) const
{
    TLVType outerContainer;
    uint8_t rdnCount = RDNCount();

    ReturnErrorOnFailure(writer.StartContainer(tag, kTLVType_List, outerContainer));

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        // Derive the TLV tag number from the enum value assigned to the attribute type OID. For attributes that can be
        // either UTF8String or PrintableString, use the high bit in the tag number to distinguish the two.
        uint8_t tlvTagNum = GetOIDEnum(rdn[i].mAttrOID);
        if (rdn[i].mAttrIsPrintableString)
        {
            tlvTagNum |= 0x80;
        }

        if (IsChipDNAttr(rdn[i].mAttrOID))
        {
            ReturnErrorOnFailure(writer.Put(ContextTag(tlvTagNum), rdn[i].mChipVal));
        }
        else
        {
            ReturnErrorOnFailure(writer.PutString(ContextTag(tlvTagNum), rdn[i].mString));
        }
    }

    return writer.EndContainer(outerContainer);
}

CHIP_ERROR ChipDN::DecodeFromTLV(TLVReader & reader)
{
    CHIP_ERROR err;
    TLVType outerContainer;

    static constexpr uint32_t kOID_AttributeIsPrintableString_Flag = 0x00000080;
    static constexpr uint32_t kOID_AttributeType_Mask              = 0x0000007F;

    VerifyOrReturnError(reader.GetType() == kTLVType_List, CHIP_ERROR_WRONG_TLV_TYPE);

    // Enter the List TLV element that represents the DN in TLV format.
    ReturnErrorOnFailure(reader.EnterContainer(outerContainer));

    // Read the RDN attributes in the List.
    while ((err = reader.Next()) == CHIP_NO_ERROR)
    {
        // Get the TLV tag, make sure it is a context tag and extract the context tag number.
        Tag tlvTag = reader.GetTag();
        VerifyOrReturnError(IsContextTag(tlvTag), CHIP_ERROR_INVALID_TLV_TAG);
        uint32_t tlvTagNum = TagNumFromTag(tlvTag);

        // Derive the OID of the corresponding ASN.1 attribute from the TLV tag number.
        // The numeric value of the OID is encoded in the bottom 7 bits of the TLV tag number.
        // This eliminates the need for a translation table/switch statement but has the
        // effect of tying the two encodings together.
        //
        // NOTE: In the event that the computed OID value is not one that we recognize
        // (specifically, is not in the table of OIDs defined in ASN1OID.h) then the
        // macro call below that encodes the attribute's object id (ASN1_ENCODE_OBJECT_ID)
        // will fail for lack of the OID's encoded representation.  Given this there's no
        // need to test the validity of the OID here.
        //
        OID attrOID = GetOID(kOIDCategory_AttributeType, static_cast<uint8_t>(tlvTagNum & kOID_AttributeType_Mask));

        bool attrIsPrintableString = (tlvTagNum & kOID_AttributeIsPrintableString_Flag) == kOID_AttributeIsPrintableString_Flag;

        // For 64-bit CHIP-defined DN attributes.
        if (IsChip64bitDNAttr(attrOID))
        {
            uint64_t chipAttr;
            VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
            ReturnErrorOnFailure(reader.Get(chipAttr));
            if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
            {
                VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
            }
            else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
            {
                VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
            }
            ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
        }
        // For 32-bit CHIP-defined DN attributes.
        else if (IsChip32bitDNAttr(attrOID))
        {
            uint32_t chipAttr;
            VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
            ReturnErrorOnFailure(reader.Get(chipAttr));
            if (attrOID == chip::ASN1::kOID_AttributeType_MatterCASEAuthTag)
            {
                VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
            }
            ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
        }
        // Otherwise the attribute is one of the supported X.509 attributes
        else
        {
            CharSpan asn1Attr;
            ReturnErrorOnFailure(reader.Get(asn1Attr));
            ReturnErrorOnFailure(AddAttribute(attrOID, asn1Attr, attrIsPrintableString));
        }
    }
    VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
    ReturnErrorOnFailure(reader.ExitContainer(outerContainer));

    return CHIP_NO_ERROR;
}

CHIP_ERROR ChipDN::EncodeToASN1(ASN1Writer & writer) const
{
    CHIP_ERROR err   = CHIP_NO_ERROR;
    uint8_t rdnCount = RDNCount();

    ASN1_START_SEQUENCE
    {
        for (uint8_t i = 0; i < rdnCount; i++)
        {
            ASN1_START_SET
            {
                char chipAttrStr[kChip64bitAttrUTF8Length];
                CharSpan asn1Attr;
                uint8_t asn1Tag;
                chip::ASN1::OID attrOID = rdn[i].mAttrOID;

                if (IsChip64bitDNAttr(attrOID))
                {
                    ReturnErrorOnFailure(
                        Encoding::Uint64ToHex(rdn[i].mChipVal, chipAttrStr, sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
                    asn1Attr = CharSpan(chipAttrStr, kChip64bitAttrUTF8Length);
                    asn1Tag  = kASN1UniversalTag_UTF8String;
                }
                else if (IsChip32bitDNAttr(attrOID))
                {
                    ReturnErrorOnFailure(Encoding::Uint32ToHex(static_cast<uint32_t>(rdn[i].mChipVal), chipAttrStr,
                                                               sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
                    asn1Attr = CharSpan(chipAttrStr, kChip32bitAttrUTF8Length);
                    asn1Tag  = kASN1UniversalTag_UTF8String;
                }
                else
                {
                    asn1Attr = rdn[i].mString;

                    // Determine the appropriate ASN.1 tag for the DN attribute.
                    // - DomainComponent is always an IA5String.
                    // - For all other ASN.1 defined attributes, bit 0x80 in the TLV tag value conveys whether the attribute
                    //   is a UTF8String or a PrintableString (in some cases the certificate generator has a choice).
                    if (attrOID == kOID_AttributeType_DomainComponent)
                    {
                        asn1Tag = kASN1UniversalTag_IA5String;
                    }
                    else
                    {
                        asn1Tag = rdn[i].mAttrIsPrintableString ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String;
                    }
                }

                // AttributeTypeAndValue ::= SEQUENCE
                ASN1_START_SEQUENCE
                {
                    // type AttributeType
                    // AttributeType ::= OBJECT IDENTIFIER
                    ASN1_ENCODE_OBJECT_ID(attrOID);

                    VerifyOrReturnError(CanCastTo<uint16_t>(asn1Attr.size()), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);

                    // value AttributeValue
                    // AttributeValue ::= ANY -- DEFINED BY AttributeType
                    ReturnErrorOnFailure(writer.PutString(asn1Tag, asn1Attr.data(), static_cast<uint16_t>(asn1Attr.size())));
                }
                ASN1_END_SEQUENCE;
            }
            ASN1_END_SET;
        }
    }
    ASN1_END_SEQUENCE;

exit:
    return err;
}

CHIP_ERROR ChipDN::DecodeFromASN1(ASN1Reader & reader)
{
    CHIP_ERROR err;

    // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
    ASN1_PARSE_ENTER_SEQUENCE
    {
        while ((err = reader.Next()) == CHIP_NO_ERROR)
        {
            // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
            ASN1_ENTER_SET
            {
                // AttributeTypeAndValue ::= SEQUENCE
                ASN1_PARSE_ENTER_SEQUENCE
                {
                    // type AttributeType
                    // AttributeType ::= OBJECT IDENTIFIER
                    OID attrOID;
                    ASN1_PARSE_OBJECT_ID(attrOID);
                    VerifyOrReturnError(GetOIDCategory(attrOID) == kOIDCategory_AttributeType, ASN1_ERROR_INVALID_ENCODING);

                    // AttributeValue ::= ANY -- DEFINED BY AttributeType
                    ASN1_PARSE_ANY;

                    uint8_t attrTag = reader.GetTag();

                    // Can only support UTF8String, PrintableString and IA5String.
                    VerifyOrReturnError(reader.GetClass() == kASN1TagClass_Universal &&
                                            (attrTag == kASN1UniversalTag_PrintableString ||
                                             attrTag == kASN1UniversalTag_UTF8String || attrTag == kASN1UniversalTag_IA5String),
                                        ASN1_ERROR_UNSUPPORTED_ENCODING);

                    // CHIP attributes must be UTF8Strings.
                    if (IsChipDNAttr(attrOID))
                    {
                        VerifyOrReturnError(attrTag == kASN1UniversalTag_UTF8String, ASN1_ERROR_INVALID_ENCODING);
                    }

                    // If 64-bit CHIP attribute.
                    if (IsChip64bitDNAttr(attrOID))
                    {
                        uint64_t chipAttr;
                        VerifyOrReturnError(Encoding::UppercaseHexToUint64(reinterpret_cast<const char *>(reader.GetValue()),
                                                                           static_cast<size_t>(reader.GetValueLen()),
                                                                           chipAttr) == sizeof(uint64_t),
                                            ASN1_ERROR_INVALID_ENCODING);

                        if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
                        {
                            VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
                        }
                        else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
                        {
                            VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_WRONG_CERT_DN);
                        }

                        ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
                    }
                    // If 32-bit CHIP attribute.
                    else if (IsChip32bitDNAttr(attrOID))
                    {
                        CASEAuthTag chipAttr;
                        VerifyOrReturnError(Encoding::UppercaseHexToUint32(reinterpret_cast<const char *>(reader.GetValue()),
                                                                           reader.GetValueLen(), chipAttr) == sizeof(CASEAuthTag),
                                            ASN1_ERROR_INVALID_ENCODING);

                        VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_WRONG_CERT_DN);

                        ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
                    }
                    // Otherwise, it is a string.
                    else
                    {
                        ReturnErrorOnFailure(AddAttribute(attrOID,
                                                          CharSpan(Uint8::to_const_char(reader.GetValue()), reader.GetValueLen()),
                                                          attrTag == kASN1UniversalTag_PrintableString));
                    }
                }
                ASN1_EXIT_SEQUENCE;

                // Only one AttributeTypeAndValue allowed per RDN.
                err = reader.Next();
                ReturnErrorCodeIf(err == CHIP_NO_ERROR, ASN1_ERROR_UNSUPPORTED_ENCODING);
                VerifyOrReturnError(err == ASN1_END, err);
            }
            ASN1_EXIT_SET;
        }
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

bool ChipDN::IsEqual(const ChipDN & other) const
{
    bool res         = true;
    uint8_t rdnCount = RDNCount();

    VerifyOrExit(rdnCount > 0, res = false);
    VerifyOrExit(rdnCount == other.RDNCount(), res = false);

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        VerifyOrExit(rdn[i].IsEqual(other.rdn[i]), res = false);
    }

exit:
    return res;
}

DLL_EXPORT CHIP_ERROR ASN1ToChipEpochTime(const chip::ASN1::ASN1UniversalTime & asn1Time, uint32_t & epochTime)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    // In CHIP certificate it is represented as a CHIP Epoch time value of 0 sec (2000-01-01 00:00:00 UTC).
    //
    // While it is not conventional to use this special value for NotBefore, for simplicity we convert all
    // time values of 99991231235959Z to CHIP epoch zero seconds.  ChipEpochToASN1Time performs the inverse
    // translation for conversions in the other direction.
    //
    // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses 99991231235959Z
    // for NotBefore, this will be converted to the CHIP Epoch time value of 0 and consuming code will
    // handle this transparently, as logic considering a NotBefore time at the CHIP epoch will evaluate all
    // possible unsigned offsets from the CHIP epoch as valid, which is equivalent to ignoring NotBefore.
    //
    // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses a NotBefore time
    // at the CHIP epoch itself, 2000-01-01 00:00:00, a resultant conversion to CHIP TLV certificate format
    // will appear to have an invalid TBS signature when the symmetric ChipEpochToASN1Time produces
    // 99991231235959Z for NotBefore during signature validation.
    //
    // Thus such certificates, when passing through this code, will not appear valid.  This should be
    // immediately evident at commissioning time.
    if ((asn1Time.Year == kX509NoWellDefinedExpirationDateYear) && (asn1Time.Month == kMonthsPerYear) &&
        (asn1Time.Day == kMaxDaysPerMonth) && (asn1Time.Hour == kHoursPerDay - 1) && (asn1Time.Minute == kMinutesPerHour - 1) &&
        (asn1Time.Second == kSecondsPerMinute - 1))
    {
        epochTime = kNullCertTime;
    }
    else
    {
        if (!CalendarToChipEpochTime(asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute, asn1Time.Second,
                                     epochTime))
        {
            ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
        }
    }

exit:
    return err;
}

DLL_EXPORT CHIP_ERROR ChipEpochToASN1Time(uint32_t epochTime, chip::ASN1::ASN1UniversalTime & asn1Time)
{
    // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
    // In CHIP certificate it is represented as a CHIP Epoch time value of 0 secs (2000-01-01 00:00:00 UTC).
    //
    // For simplicity and symmetry with ASN1ToChipEpochTime, this method makes this conversion for all
    // times, which in consuming code can create a conversion from CHIP epoch 0 seconds to 99991231235959Z
    // for NotBefore, which is not conventional.
    //
    // If an original X509 certificate encloses a NotBefore time that is the CHIP Epoch itself, 2000-01-01
    // 00:00:00, the resultant X509 certificate in a conversion back from CHIP TLV format using this time
    // conversion method will instead enclose the NotBefore time 99991231235959Z, which will invalidiate the
    // TBS signature.  Thus, certificates with this specific attribute are not usable with this code.
    // Attempted installation of such certficates will fail during commissioning.
    if (epochTime == kNullCertTime)
    {
        asn1Time.Year   = kX509NoWellDefinedExpirationDateYear;
        asn1Time.Month  = kMonthsPerYear;
        asn1Time.Day    = kMaxDaysPerMonth;
        asn1Time.Hour   = kHoursPerDay - 1;
        asn1Time.Minute = kMinutesPerHour - 1;
        asn1Time.Second = kSecondsPerMinute - 1;
    }
    else
    {
        ChipEpochToCalendarTime(epochTime, asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute,
                                asn1Time.Second);
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ValidateChipRCAC(const ByteSpan & rcac)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;
    ValidationContext validContext;
    CertType certType;

    // Note that this function doesn't check RCAC NotBefore / NotAfter time validity.
    // It is assumed that RCAC should be valid at the time of installation by definition.

    ReturnErrorOnFailure(certSet.Init(&certData, 1));

    ReturnErrorOnFailure(certSet.LoadCert(rcac, CertDecodeFlags::kGenerateTBSHash));

    ReturnErrorOnFailure(certData.mSubjectDN.GetCertType(certType));
    VerifyOrReturnError(certType == CertType::kRoot, CHIP_ERROR_WRONG_CERT_TYPE);

    VerifyOrReturnError(certData.mSubjectDN.IsEqual(certData.mIssuerDN), CHIP_ERROR_WRONG_CERT_TYPE);

    VerifyOrReturnError(certData.mSubjectKeyId.data_equal(certData.mAuthKeyId), CHIP_ERROR_WRONG_CERT_TYPE);

    VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kIsCA), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    if (certData.mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
    {
        VerifyOrReturnError(certData.mPathLenConstraint <= 1, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
    }

    VerifyOrReturnError(certData.mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);

    return ChipCertificateSet::VerifySignature(&certData, &certData);
}

CHIP_ERROR ConvertIntegerDERToRaw(ByteSpan derInt, uint8_t * rawInt, const uint16_t rawIntLen)
{
    VerifyOrReturnError(!derInt.empty(), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(rawInt != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    const uint8_t * derIntData = derInt.data();
    size_t derIntLen           = derInt.size();

    /* one leading zero is allowed for positive integer in ASN1 DER format */
    if (*derIntData == 0)
    {
        derIntData++;
        derIntLen--;
    }

    VerifyOrReturnError(derIntLen <= rawIntLen, CHIP_ERROR_INVALID_ARGUMENT);

    if (derIntLen > 0)
    {
        VerifyOrReturnError(*derIntData != 0, CHIP_ERROR_INVALID_ARGUMENT);
    }

    memset(rawInt, 0, (rawIntLen - derIntLen));
    memcpy(rawInt + (rawIntLen - derIntLen), derIntData, derIntLen);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, MutableByteSpan & derSig)
{
    ASN1Writer writer;

    writer.Init(derSig);

    ReturnErrorOnFailure(ConvertECDSASignatureRawToDER(rawSig, writer));

    derSig.reduce_size(writer.GetLengthWritten());

    return CHIP_NO_ERROR;
}

CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, ASN1Writer & writer)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    uint8_t derInt[kP256_FE_Length + kEmitDerIntegerWithoutTagOverhead];

    VerifyOrReturnError(!rawSig.empty(), CHIP_ERROR_INVALID_ARGUMENT);

    // Ecdsa-Sig-Value ::= SEQUENCE
    ASN1_START_SEQUENCE
    {
        // r INTEGER
        {
            MutableByteSpan derIntSpan(derInt, sizeof(derInt));
            ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data()), derIntSpan));
            ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
                                                 static_cast<uint16_t>(derIntSpan.size())));
        }

        // s INTEGER
        {
            MutableByteSpan derIntSpan(derInt, sizeof(derInt));
            ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data() + kP256_FE_Length), derIntSpan));
            ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
                                                 static_cast<uint16_t>(derIntSpan.size())));
        }
    }
    ASN1_END_SEQUENCE;

exit:
    return err;
}

CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ChipCertificateData & opcert, NodeId * outNodeId, FabricId * outFabricId)
{
    // Since we assume the cert is pre-validated, we are going to assume that
    // its subject in fact has both a node id and a fabric id.
    ReturnErrorCodeIf(outNodeId == nullptr || outFabricId == nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    NodeId nodeId      = 0;
    FabricId fabricId  = kUndefinedFabricId;
    bool foundNodeId   = false;
    bool foundFabricId = false;

    const ChipDN & subjectDN = opcert.mSubjectDN;
    for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    {
        const auto & rdn = subjectDN.rdn[i];
        if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterNodeId)
        {
            nodeId      = rdn.mChipVal;
            foundNodeId = true;
        }
        else if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
        {
            fabricId      = rdn.mChipVal;
            foundFabricId = true;
        }
    }
    if (!foundNodeId || !foundFabricId)
    {
        return CHIP_ERROR_NOT_FOUND;
    }

    *outNodeId   = nodeId;
    *outFabricId = fabricId;
    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
                                                              FabricId & fabricId, NodeId & nodeId)
{
    Crypto::P256PublicKey rootPubKey;
    Credentials::P256PublicKeySpan rootPubKeySpan;
    ReturnErrorOnFailure(ExtractPublicKeyFromChipCert(rcac, rootPubKeySpan));
    rootPubKey = Crypto::P256PublicKey(rootPubKeySpan);
    ReturnErrorOnFailure(Credentials::ExtractNodeIdFabricIdFromOpCert(noc, &nodeId, &fabricId));
    ReturnErrorOnFailure(GenerateCompressedFabricId(rootPubKey, fabricId, compressedFabricId));
    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractNodeIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
                                                      NodeId & nodeId)
{
    FabricId fabricId;
    ReturnErrorOnFailure(ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(rcac, noc, compressedFabricId, fabricId, nodeId));
    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId * fabricId)
{
    const ChipDN & subjectDN = cert.mSubjectDN;
    for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    {
        const auto & rdn = subjectDN.rdn[i];
        if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
        {
            *fabricId = rdn.mChipVal;
            return CHIP_NO_ERROR;
        }
    }

    return CHIP_ERROR_NOT_FOUND;
}

CHIP_ERROR ExtractCATsFromOpCert(const ByteSpan & opcert, CATValues & cats)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;

    ReturnErrorOnFailure(certSet.Init(&certData, 1));

    ReturnErrorOnFailure(certSet.LoadCert(opcert, BitFlags<CertDecodeFlags>()));

    return ExtractCATsFromOpCert(certData, cats);
}

CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, CATValues & cats)
{
    uint8_t catCount = 0;
    CertType certType;

    ReturnErrorOnFailure(opcert.mSubjectDN.GetCertType(certType));
    VerifyOrReturnError(certType == CertType::kNode, CHIP_ERROR_INVALID_ARGUMENT);

    const ChipDN & subjectDN = opcert.mSubjectDN;
    for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
    {
        const auto & rdn = subjectDN.rdn[i];
        if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterCASEAuthTag)
        {
            // This error should never happen in practice because valid NOC cannot have more
            // than kMaxSubjectCATAttributeCount CATs in its subject. The check that it is
            // valid NOC was done above.
            ReturnErrorCodeIf(catCount == cats.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
            VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn.mChipVal), CHIP_ERROR_INVALID_ARGUMENT);
            cats.values[catCount++] = static_cast<CASEAuthTag>(rdn.mChipVal);
        }
    }
    for (size_t i = catCount; i < cats.size(); ++i)
    {
        cats.values[i] = kUndefinedCAT;
    }

    // Make sure the set contained valid data, otherwise it's an invalid cert
    VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_WRONG_CERT_DN);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractFabricIdFromCert(const ByteSpan & opcert, FabricId * fabricId)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;
    ReturnErrorOnFailure(certSet.Init(&certData, 1));
    ReturnErrorOnFailure(certSet.LoadCert(opcert, BitFlags<CertDecodeFlags>()));
    return ExtractFabricIdFromCert(certData, fabricId);
}

CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ByteSpan & opcert, NodeId * nodeId, FabricId * fabricId)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;

    ReturnErrorOnFailure(certSet.Init(&certData, 1));

    ReturnErrorOnFailure(certSet.LoadCert(opcert, BitFlags<CertDecodeFlags>()));

    return ExtractNodeIdFabricIdFromOpCert(certData, nodeId, fabricId);
}

CHIP_ERROR ExtractPublicKeyFromChipCert(const ByteSpan & chipCert, P256PublicKeySpan & publicKey)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;

    ReturnErrorOnFailure(certSet.Init(&certData, 1));

    ReturnErrorOnFailure(certSet.LoadCert(chipCert, BitFlags<CertDecodeFlags>()));

    publicKey = certData.mPublicKey;

    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractNotBeforeFromChipCert(const ByteSpan & chipCert, chip::System::Clock::Seconds32 & notBeforeChipEpochTime)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;

    ReturnErrorOnFailure(certSet.Init(&certData, 1));

    ReturnErrorOnFailure(certSet.LoadCert(chipCert, BitFlags<CertDecodeFlags>()));

    notBeforeChipEpochTime = chip::System::Clock::Seconds32(certData.mNotBeforeTime);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractSKIDFromChipCert(const ByteSpan & chipCert, CertificateKeyId & skid)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;

    ReturnErrorOnFailure(certSet.Init(&certData, 1));

    ReturnErrorOnFailure(certSet.LoadCert(chipCert, BitFlags<CertDecodeFlags>()));

    skid = certData.mSubjectKeyId;

    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractSubjectDNFromChipCert(const ByteSpan & chipCert, ChipDN & dn)
{
    ChipCertificateSet certSet;
    ChipCertificateData certData;

    ReturnErrorOnFailure(certSet.Init(&certData, 1));

    ReturnErrorOnFailure(certSet.LoadCert(chipCert, BitFlags<CertDecodeFlags>()));

    dn = certData.mSubjectDN;

    return CHIP_NO_ERROR;
}

CHIP_ERROR ExtractSubjectDNFromX509Cert(const ByteSpan & x509Cert, ChipDN & dn)
{
    CHIP_ERROR err;
    ASN1Reader reader;

    VerifyOrReturnError(CanCastTo<uint32_t>(x509Cert.size()), CHIP_ERROR_INVALID_ARGUMENT);

    reader.Init(x509Cert);

    // Certificate ::= SEQUENCE
    ASN1_PARSE_ENTER_SEQUENCE
    {
        // tbsCertificate TBSCertificate,
        // TBSCertificate ::= SEQUENCE
        ASN1_PARSE_ENTER_SEQUENCE
        {
            // Skip version [0] EXPLICIT Version DEFAULT v1
            ASN1_PARSE_ELEMENT(kASN1TagClass_ContextSpecific, 0);

            // Skip serialNumber CertificateSerialNumber
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);

            // Skip signature AlgorithmIdentifier
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);

            // Skip issuer Name
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);

            // Skip validity Validity,
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);

            // Decode subject Name,
            ReturnErrorOnFailure(dn.DecodeFromASN1(reader));
        }
        ASN1_SKIP_AND_EXIT_SEQUENCE;
    }
    ASN1_SKIP_AND_EXIT_SEQUENCE;

exit:
    return err;
}

CHIP_ERROR CertificateValidityPolicy::ApplyDefaultPolicy(const ChipCertificateData * cert, uint8_t depth,
                                                         CertificateValidityResult result)
{
    switch (result)
    {
    case CertificateValidityResult::kValid:
    case CertificateValidityResult::kNotExpiredAtLastKnownGoodTime:
    // By default, we do not enforce certificate validity based upon a Last
    // Known Good Time source.  However, implementations may always inject a
    // policy that does enforce based upon this.
    case CertificateValidityResult::kExpiredAtLastKnownGoodTime:
    case CertificateValidityResult::kTimeUnknown:
        return CHIP_NO_ERROR;

    case CertificateValidityResult::kNotYetValid:
        return CHIP_ERROR_CERT_NOT_VALID_YET;

    case CertificateValidityResult::kExpired:
        return CHIP_ERROR_CERT_EXPIRED;

    default:
        return CHIP_ERROR_INTERNAL;
    }
}

} // namespace Credentials
} // namespace chip
