/*
 *
 *    Copyright (c) 2020-2021 Project CHIP Authors
 *    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 methods for converting a standard X.509
 *      certificate to a CHIP TLV-encoded certificate.
 *
 */

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <stddef.h>

#include <credentials/CHIPCert.h>
#include <lib/asn1/ASN1.h>
#include <lib/asn1/ASN1Macros.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/CHIPTLV.h>
#include <lib/core/Optional.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.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;

static CHIP_ERROR ParseChipAttribute(ASN1Reader & reader, uint64_t & chipAttrOut)
{
    CHIP_ERROR err        = CHIP_NO_ERROR;
    const uint8_t * value = reader.GetValue();
    uint32_t valueLen     = reader.GetValueLen();

    chipAttrOut = 0;

    VerifyOrExit(value != nullptr, err = ASN1_ERROR_INVALID_ENCODING);
    VerifyOrExit(valueLen == kChip32bitAttrUTF8Length || valueLen == kChip64bitAttrUTF8Length, err = ASN1_ERROR_INVALID_ENCODING);

    for (uint32_t i = 0; i < valueLen; i++)
    {
        chipAttrOut <<= 4;
        uint8_t ch = value[i];
        if (ch >= '0' && ch <= '9')
        {
            chipAttrOut |= (ch - '0');
        }
        // CHIP Id attribute encodings only support uppercase chars.
        else if (ch >= 'A' && ch <= 'F')
        {
            chipAttrOut |= (ch - 'A' + 10);
        }
        else
        {
            ExitNow(err = ASN1_ERROR_INVALID_ENCODING);
        }
    }

exit:
    return err;
}

static CHIP_ERROR ConvertDistinguishedName(ASN1Reader & reader, TLVWriter & writer, Tag tag, uint64_t & subjectOrIssuer,
                                           Optional<uint64_t> & fabric)
{
    CHIP_ERROR err;
    TLVType outerContainer;
    OID attrOID;

    err = writer.StartContainer(tag, kTLVType_List, outerContainer);
    SuccessOrExit(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
                    ASN1_PARSE_OBJECT_ID(attrOID);
                    VerifyOrExit(GetOIDCategory(attrOID) == kOIDCategory_AttributeType, err = ASN1_ERROR_INVALID_ENCODING);

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

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

                    // CHIP attributes must be UTF8Strings.
                    if (IsChipDNAttr(attrOID))
                    {
                        VerifyOrExit(reader.GetTag() == kASN1UniversalTag_UTF8String, err = ASN1_ERROR_INVALID_ENCODING);
                    }

                    // 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(attrOID);
                    if (reader.GetTag() == kASN1UniversalTag_PrintableString)
                    {
                        tlvTagNum |= 0x80;
                    }

                    // If the attribute is a CHIP-defined attribute that contains a 64-bit or 32-bit value.
                    if (IsChipDNAttr(attrOID))
                    {
                        // Parse the attribute string into a CHIP attribute.
                        uint64_t chipAttr;
                        err = ParseChipAttribute(reader, chipAttr);
                        SuccessOrExit(err);

                        // Write the CHIP attribute value into the TLV.
                        err = writer.Put(ContextTag(tlvTagNum), chipAttr);
                        SuccessOrExit(err);

                        // Certificates use a combination of OIDs for Issuer and Subject.
                        // NOC: Issuer  = kOID_AttributeType_ChipRootId or kOID_AttributeType_ChipICAId
                        //      Subject = kOID_AttributeType_ChipNodeId
                        // ICA: Issuer  = kOID_AttributeType_ChipRootId
                        //      Subject = kOID_AttributeType_ChipICAId
                        // Root: Issuer = kOID_AttributeType_ChipRootId
                        //      Subject = kOID_AttributeType_ChipRootId
                        //
                        // This function is called first for the Issuer DN, and later for Subject DN.
                        // Since the caller knows if Issuer or Subject DN is being parsed, it's left up to
                        // the caller to use the returned value (subjectOrIssuer) appropriately.
                        if (attrOID == chip::ASN1::kOID_AttributeType_ChipNodeId ||
                            attrOID == chip::ASN1::kOID_AttributeType_ChipICAId ||
                            attrOID == chip::ASN1::kOID_AttributeType_ChipRootId)
                        {
                            subjectOrIssuer = chipAttr;
                        }
                        else if (attrOID == chip::ASN1::kOID_AttributeType_ChipFabricId)
                        {
                            fabric.SetValue(chipAttr);
                        }
                    }

                    //
                    else
                    {
                        err =
                            writer.PutString(ContextTag(tlvTagNum), Uint8::to_const_char(reader.GetValue()), reader.GetValueLen());
                        SuccessOrExit(err);
                    }
                }
                ASN1_EXIT_SEQUENCE;

                // Only one AttributeTypeAndValue allowed per RDN.
                err = reader.Next();
                if (err == CHIP_NO_ERROR)
                {
                    ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
                }
                if (err != ASN1_END)
                {
                    ExitNow();
                }
            }
            ASN1_EXIT_SET;
        }
    }
    ASN1_EXIT_SEQUENCE;

    err = writer.EndContainer(outerContainer);
    SuccessOrExit(err);

exit:
    return err;
}

static CHIP_ERROR ConvertValidity(ASN1Reader & reader, TLVWriter & writer)
{
    CHIP_ERROR err;
    ASN1UniversalTime asn1Time;
    uint32_t chipEpochTime;

    ASN1_PARSE_ENTER_SEQUENCE
    {
        ASN1_PARSE_TIME(asn1Time);

        err = ASN1ToChipEpochTime(asn1Time, chipEpochTime);
        SuccessOrExit(err);

        err = writer.Put(ContextTag(kTag_NotBefore), chipEpochTime);
        SuccessOrExit(err);

        ASN1_PARSE_TIME(asn1Time);

        err = ASN1ToChipEpochTime(asn1Time, chipEpochTime);
        SuccessOrExit(err);

        err = writer.Put(ContextTag(kTag_NotAfter), chipEpochTime);
        SuccessOrExit(err);
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

static CHIP_ERROR ConvertSubjectPublicKeyInfo(ASN1Reader & reader, TLVWriter & writer)
{
    CHIP_ERROR err;
    OID pubKeyAlgoOID, pubKeyCurveOID;

    // subjectPublicKeyInfo SubjectPublicKeyInfo,
    ASN1_PARSE_ENTER_SEQUENCE
    {
        // algorithm AlgorithmIdentifier,
        // AlgorithmIdentifier ::= SEQUENCE
        ASN1_PARSE_ENTER_SEQUENCE
        {
            // algorithm OBJECT IDENTIFIER,
            ASN1_PARSE_OBJECT_ID(pubKeyAlgoOID);

            // Verify that the algorithm type is supported.
            VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = ASN1_ERROR_UNSUPPORTED_ENCODING);

            err = writer.Put(ContextTag(kTag_PublicKeyAlgorithm), GetOIDEnum(pubKeyAlgoOID));
            SuccessOrExit(err);

            // EcpkParameters ::= CHOICE {
            //     ecParameters  ECParameters,
            //     namedCurve    OBJECT IDENTIFIER,
            //     implicitlyCA  NULL }
            ASN1_PARSE_ANY;

            // ecParameters and implicitlyCA not supported.
            if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Sequence)
            {
                ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
            }
            if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Null)
            {
                ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
            }

            ASN1_VERIFY_TAG(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);

            ASN1_GET_OBJECT_ID(pubKeyCurveOID);

            // Verify the curve name is recognized.
            VerifyOrExit(GetOIDCategory(pubKeyCurveOID) == kOIDCategory_EllipticCurve, err = ASN1_ERROR_UNSUPPORTED_ENCODING);

            err = writer.Put(ContextTag(kTag_EllipticCurveIdentifier), GetOIDEnum(pubKeyCurveOID));
            SuccessOrExit(err);
        }
        ASN1_EXIT_SEQUENCE;

        // subjectPublicKey BIT STRING
        ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);

        // Verify public key length.
        VerifyOrExit(reader.GetValueLen() > 0, err = ASN1_ERROR_INVALID_ENCODING);

        // The first byte is Unused Bit Count value, which should be zero.
        VerifyOrExit(reader.GetValue()[0] == 0, err = ASN1_ERROR_INVALID_ENCODING);

        // Copy the X9.62 encoded EC point into the CHIP certificate as a byte string.
        // Skip the first Unused Bit Count byte.
        err = writer.PutBytes(ContextTag(kTag_EllipticCurvePublicKey), reader.GetValue() + 1, reader.GetValueLen() - 1);
        SuccessOrExit(err);
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

static CHIP_ERROR ConvertExtension(ASN1Reader & reader, TLVWriter & writer)
{
    CHIP_ERROR err;
    TLVType outerContainer;
    OID extensionOID;
    bool critical = false;
    const uint8_t * extensionSequence;
    uint32_t extensionSequenceLen;

    err = reader.GetConstructedType(extensionSequence, extensionSequenceLen);
    SuccessOrExit(err);

    // Extension ::= SEQUENCE
    ASN1_ENTER_SEQUENCE
    {
        // extnID OBJECT IDENTIFIER,
        ASN1_PARSE_OBJECT_ID(extensionOID);

        // The kOID_Unknown will be interpreted and encoded as future-extension.
        if (extensionOID != kOID_Unknown)
        {
            VerifyOrExit(GetOIDCategory(extensionOID) == kOIDCategory_Extension, err = ASN1_ERROR_INVALID_ENCODING);
        }

        // critical BOOLEAN DEFAULT FALSE,
        ASN1_PARSE_ANY;
        if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Boolean)
        {
            ASN1_GET_BOOLEAN(critical);

            VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);

            ASN1_PARSE_ANY;
        }

        // extnValue OCTET STRING
        //           -- contains the DER encoding of an ASN.1 value
        //           -- corresponding to the extension type identified
        //           -- by extnID
        ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_OctetString)
        {
            if (extensionOID == kOID_Extension_AuthorityKeyIdentifier)
            {
                // This extension MUST be marked as non-critical.
                VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);

                // AuthorityKeyIdentifier ::= SEQUENCE
                ASN1_PARSE_ENTER_SEQUENCE
                {
                    err = reader.Next();
                    SuccessOrExit(err);

                    // keyIdentifier [0] IMPLICIT KeyIdentifier,
                    // KeyIdentifier ::= OCTET STRING
                    VerifyOrExit(reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 0,
                                 err = ASN1_ERROR_INVALID_ENCODING);

                    VerifyOrExit(reader.IsConstructed() == false, err = ASN1_ERROR_INVALID_ENCODING);
                    VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);

                    err = writer.PutBytes(ContextTag(kTag_AuthorityKeyIdentifier), reader.GetValue(), reader.GetValueLen());
                    SuccessOrExit(err);

                    err = reader.Next();
                    VerifyOrExit(err == ASN1_END, err = ASN1_ERROR_INVALID_ENCODING);
                }
                ASN1_EXIT_SEQUENCE;
            }
            else if (extensionOID == kOID_Extension_SubjectKeyIdentifier)
            {
                // This extension MUST be marked as non-critical.
                VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);

                // SubjectKeyIdentifier ::= KeyIdentifier
                // KeyIdentifier ::= OCTET STRING
                ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString);

                VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);

                err = writer.PutBytes(ContextTag(kTag_SubjectKeyIdentifier), reader.GetValue(), reader.GetValueLen());
                SuccessOrExit(err);
            }
            else if (extensionOID == kOID_Extension_KeyUsage)
            {
                // This extension MUST be marked as critical.
                VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);

                // KeyUsage ::= BIT STRING
                ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);

                uint32_t keyUsageBits;
                err = reader.GetBitString(keyUsageBits);
                SuccessOrExit(err);
                VerifyOrExit(CanCastTo<uint16_t>(keyUsageBits), err = ASN1_ERROR_INVALID_ENCODING);

                // Check that only supported flags are set.
                BitFlags<KeyUsageFlags> keyUsageFlags(static_cast<uint16_t>(keyUsageBits));
                VerifyOrExit(keyUsageFlags.HasOnly(
                                 KeyUsageFlags::kDigitalSignature, KeyUsageFlags::kNonRepudiation, KeyUsageFlags::kKeyEncipherment,
                                 KeyUsageFlags::kDataEncipherment, KeyUsageFlags::kKeyAgreement, KeyUsageFlags::kKeyCertSign,
                                 KeyUsageFlags::kCRLSign, KeyUsageFlags::kEncipherOnly, KeyUsageFlags::kEncipherOnly),
                             err = ASN1_ERROR_INVALID_ENCODING);

                err = writer.Put(ContextTag(kTag_KeyUsage), keyUsageBits);
                SuccessOrExit(err);
            }
            else if (extensionOID == kOID_Extension_BasicConstraints)
            {
                // This extension MUST be marked as critical.
                VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);

                // BasicConstraints ::= SEQUENCE
                ASN1_PARSE_ENTER_SEQUENCE
                {
                    bool isCA                 = false;
                    int64_t pathLenConstraint = -1;

                    // cA BOOLEAN DEFAULT FALSE
                    err = reader.Next();
                    if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal &&
                        reader.GetTag() == kASN1UniversalTag_Boolean)
                    {
                        ASN1_GET_BOOLEAN(isCA);

                        VerifyOrExit(isCA, err = ASN1_ERROR_INVALID_ENCODING);

                        err = reader.Next();
                    }

                    // pathLenConstraint INTEGER (0..MAX) OPTIONAL
                    if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal &&
                        reader.GetTag() == kASN1UniversalTag_Integer)
                    {
                        ASN1_GET_INTEGER(pathLenConstraint);

                        VerifyOrExit(CanCastTo<uint8_t>(pathLenConstraint), err = ASN1_ERROR_INVALID_ENCODING);

                        // pathLenConstraint is present only when cA is TRUE
                        VerifyOrExit(isCA, err = ASN1_ERROR_INVALID_ENCODING);
                    }

                    err = writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, outerContainer);
                    SuccessOrExit(err);

                    // Set also when cA is FALSE
                    err = writer.PutBoolean(ContextTag(kTag_BasicConstraints_IsCA), isCA);
                    SuccessOrExit(err);

                    if (pathLenConstraint != -1)
                    {
                        err = writer.Put(ContextTag(kTag_BasicConstraints_PathLenConstraint),
                                         static_cast<uint8_t>(pathLenConstraint));
                        SuccessOrExit(err);
                    }

                    err = writer.EndContainer(outerContainer);
                    SuccessOrExit(err);
                }
                ASN1_EXIT_SEQUENCE;
            }
            else if (extensionOID == kOID_Extension_ExtendedKeyUsage)
            {
                // This extension MUST be marked as critical.
                VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);

                err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Array, outerContainer);
                SuccessOrExit(err);

                // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
                ASN1_PARSE_ENTER_SEQUENCE
                {
                    while ((err = reader.Next()) == CHIP_NO_ERROR)
                    {
                        // KeyPurposeId ::= OBJECT IDENTIFIER
                        OID keyPurposeOID;
                        ASN1_GET_OBJECT_ID(keyPurposeOID);

                        VerifyOrExit(keyPurposeOID != kOID_Unknown, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
                        VerifyOrExit(GetOIDCategory(keyPurposeOID) == kOIDCategory_KeyPurpose, err = ASN1_ERROR_INVALID_ENCODING);

                        err = writer.Put(AnonymousTag(), GetOIDEnum(keyPurposeOID));
                        SuccessOrExit(err);
                    }
                    if (err != ASN1_END)
                    {
                        SuccessOrExit(err);
                    }
                }
                ASN1_EXIT_SEQUENCE;

                err = writer.EndContainer(outerContainer);
                SuccessOrExit(err);
            }
            // Any other extension is treated as FutureExtension
            else
            {
                err = writer.PutBytes(ContextTag(kTag_FutureExtension), extensionSequence, extensionSequenceLen);
                SuccessOrExit(err);

                ASN1_PARSE_ANY;
            }
        }
        ASN1_EXIT_ENCAPSULATED;
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

static CHIP_ERROR ConvertExtensions(ASN1Reader & reader, TLVWriter & writer)
{
    CHIP_ERROR err;
    TLVType containerType;

    err = writer.StartContainer(ContextTag(kTag_Extensions), kTLVType_List, containerType);
    SuccessOrExit(err);

    // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
    ASN1_PARSE_ENTER_SEQUENCE
    {
        while ((err = reader.Next()) == CHIP_NO_ERROR)
        {
            err = ConvertExtension(reader, writer);
            SuccessOrExit(err);
        }

        if (err != ASN1_END)
        {
            SuccessOrExit(err);
        }
    }
    ASN1_EXIT_SEQUENCE;

    err = writer.EndContainer(containerType);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR ConvertECDSASignatureDERToRaw(ASN1Reader & reader, TLVWriter & writer, Tag tag)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    uint8_t rawSig[kP256_ECDSA_Signature_Length_Raw];

    // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING.
    ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_BitString)
    {
        // Ecdsa-Sig-Value ::= SEQUENCE
        ASN1_PARSE_ENTER_SEQUENCE
        {
            // r INTEGER
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
            ReturnErrorOnFailure(
                ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig, kP256_FE_Length));

            // s INTEGER
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
            ReturnErrorOnFailure(ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig + kP256_FE_Length,
                                                        kP256_FE_Length));
        }
        ASN1_EXIT_SEQUENCE;
    }
    ASN1_EXIT_ENCAPSULATED;

    ReturnErrorOnFailure(writer.PutBytes(tag, rawSig, kP256_ECDSA_Signature_Length_Raw));

exit:
    return err;
}

static CHIP_ERROR ConvertCertificate(ASN1Reader & reader, TLVWriter & writer, Tag tag, uint64_t & issuer, uint64_t & subject,
                                     Optional<uint64_t> & fabric)
{
    CHIP_ERROR err;
    int64_t version;
    OID sigAlgoOID;
    TLVType containerType;

    err = writer.StartContainer(tag, kTLVType_Structure, containerType);
    SuccessOrExit(err);

    // Certificate ::= SEQUENCE
    ASN1_PARSE_ENTER_SEQUENCE
    {
        // tbsCertificate TBSCertificate,
        // TBSCertificate ::= SEQUENCE
        ASN1_PARSE_ENTER_SEQUENCE
        {
            // version [0] EXPLICIT Version DEFAULT v1
            ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
            {
                // Version ::= INTEGER { v1(0), v2(1), v3(2) }
                ASN1_PARSE_INTEGER(version);

                // Verify that the X.509 certificate version is v3
                VerifyOrExit(version == 2, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
            }
            ASN1_EXIT_CONSTRUCTED;

            // serialNumber CertificateSerialNumber
            // CertificateSerialNumber ::= INTEGER
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
            err = writer.PutBytes(ContextTag(kTag_SerialNumber), reader.GetValue(), reader.GetValueLen());
            SuccessOrExit(err);

            // signature AlgorithmIdentifier
            // AlgorithmIdentifier ::= SEQUENCE
            ASN1_PARSE_ENTER_SEQUENCE
            {
                // algorithm OBJECT IDENTIFIER,
                ASN1_PARSE_OBJECT_ID(sigAlgoOID);

                VerifyOrExit(sigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = ASN1_ERROR_UNSUPPORTED_ENCODING);

                err = writer.Put(ContextTag(kTag_SignatureAlgorithm), GetOIDEnum(sigAlgoOID));
                SuccessOrExit(err);
            }
            ASN1_EXIT_SEQUENCE;

            // issuer Name
            err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Issuer), issuer, fabric);
            SuccessOrExit(err);

            // validity Validity,
            err = ConvertValidity(reader, writer);
            SuccessOrExit(err);

            // subject Name,
            err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Subject), subject, fabric);
            SuccessOrExit(err);

            err = ConvertSubjectPublicKeyInfo(reader, writer);
            SuccessOrExit(err);

            err = reader.Next();

            // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
            // Not supported.
            if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 1)
            {
                ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
            }

            // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
            // Not supported.
            if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 2)
            {
                ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
            }

            // extensions [3] EXPLICIT Extensions OPTIONAL
            if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 3)
            {
                ASN1_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
                {
                    err = ConvertExtensions(reader, writer);
                    SuccessOrExit(err);
                }
                ASN1_EXIT_CONSTRUCTED;

                err = reader.Next();
            }

            if (err != ASN1_END)
            {
                ExitNow();
            }
        }
        ASN1_EXIT_SEQUENCE;

        // signatureAlgorithm AlgorithmIdentifier
        // AlgorithmIdentifier ::= SEQUENCE
        ASN1_PARSE_ENTER_SEQUENCE
        {
            OID localSigAlgoOID;

            // algorithm OBJECT IDENTIFIER,
            ASN1_PARSE_OBJECT_ID(localSigAlgoOID);

            // Verify that the signatureAlgorithm is the same as the "signature" field in TBSCertificate.
            VerifyOrExit(localSigAlgoOID == sigAlgoOID, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
        }
        ASN1_EXIT_SEQUENCE;

        // signatureValue BIT STRING
        ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);

        ReturnErrorOnFailure(ConvertECDSASignatureDERToRaw(reader, writer, ContextTag(kTag_ECDSASignature)));
    }
    ASN1_EXIT_SEQUENCE;

    err = writer.EndContainer(containerType);
    SuccessOrExit(err);

exit:
    return err;
}

CHIP_ERROR ConvertX509CertToChipCert(const ByteSpan x509Cert, MutableByteSpan & chipCert)
{
    ASN1Reader reader;
    TLVWriter writer;

    uint64_t issuer, subject;
    Optional<uint64_t> fabric;

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

    reader.Init(x509Cert);

    writer.Init(chipCert);

    ReturnErrorOnFailure(ConvertCertificate(reader, writer, AnonymousTag(), issuer, subject, fabric));

    ReturnErrorOnFailure(writer.Finalize());

    chipCert.reduce_size(writer.GetLengthWritten());

    return CHIP_NO_ERROR;
}

} // namespace Credentials
} // namespace chip
