/*
 *
 *    Copyright (c) 2021-2022 Project CHIP Authors
 *    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 data types, objects and APIs for
 *      working with Certification Declaration elements.
 */

#include <algorithm>
#include <cinttypes>
#include <cstddef>

#include <credentials/CertificationDeclaration.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/SafeInt.h>

namespace chip {
namespace Credentials {

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

static constexpr uint8_t sOID_ContentType_PKCS7Data[]       = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 };
static constexpr uint8_t sOID_ContentType_PKCS7SignedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };
static constexpr uint8_t sOID_DigestAlgo_SHA256[]           = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 };
static constexpr uint8_t sOID_SigAlgo_ECDSAWithSHA256[]     = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 };

/** Certification Declaration Element TLV Tags
 */
enum
{
    kTag_FormatVersion       = 0,  /**< [ unsigned int ] Format version. */
    kTag_VendorId            = 1,  /**< [ unsigned int ] Vedor identifier. */
    kTag_ProductIdArray      = 2,  /**< [ array ] Product identifiers (each is unsigned int). */
    kTag_DeviceTypeId        = 3,  /**< [ unsigned int ] Device Type identifier. */
    kTag_CertificateId       = 4,  /**< [ UTF-8 string, length 19 ] Certificate identifier. */
    kTag_SecurityLevel       = 5,  /**< [ unsigned int ] Security level. */
    kTag_SecurityInformation = 6,  /**< [ unsigned int ] Security information. */
    kTag_VersionNumber       = 7,  /**< [ unsigned int ] Version number. */
    kTag_CertificationType   = 8,  /**< [ unsigned int ] Certification Type. */
    kTag_DACOriginVendorId   = 9,  /**< [ unsigned int, optional ] DAC origin vendor identifier. */
    kTag_DACOriginProductId  = 10, /**< [ unsigned int, optional ] DAC origin product identifier. */
    kTag_AuthorizedPAAList   = 11, /**< [ array, optional ] Authorized PAA List. */
};

CHIP_ERROR EncodeCertificationElements(const CertificationElements & certElements, MutableByteSpan & encodedCertElements)
{
    TLVWriter writer;
    TLVType outerContainer1, outerContainer2;

    writer.Init(encodedCertElements);

    ReturnErrorOnFailure(writer.StartContainer(AnonymousTag(), kTLVType_Structure, outerContainer1));

    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_FormatVersion), certElements.FormatVersion));
    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_VendorId), certElements.VendorId));

    VerifyOrReturnError(certElements.ProductIdsCount > 0, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(certElements.ProductIdsCount <= kMaxProductIdsCount, CHIP_ERROR_INVALID_ARGUMENT);

    ReturnErrorOnFailure(writer.StartContainer(ContextTag(kTag_ProductIdArray), kTLVType_Array, outerContainer2));
    for (uint8_t i = 0; i < certElements.ProductIdsCount; i++)
    {
        ReturnErrorOnFailure(writer.Put(AnonymousTag(), certElements.ProductIds[i]));
    }
    ReturnErrorOnFailure(writer.EndContainer(outerContainer2));

    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_DeviceTypeId), certElements.DeviceTypeId));
    ReturnErrorOnFailure(writer.PutString(ContextTag(kTag_CertificateId), certElements.CertificateId));
    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_SecurityLevel), certElements.SecurityLevel));
    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_SecurityInformation), certElements.SecurityInformation));
    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_VersionNumber), certElements.VersionNumber));
    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_CertificationType), certElements.CertificationType));
    if (certElements.DACOriginVIDandPIDPresent)
    {
        ReturnErrorOnFailure(writer.Put(ContextTag(kTag_DACOriginVendorId), certElements.DACOriginVendorId));
        ReturnErrorOnFailure(writer.Put(ContextTag(kTag_DACOriginProductId), certElements.DACOriginProductId));
    }
    if (certElements.AuthorizedPAAListCount > 0)
    {
        VerifyOrReturnError(certElements.AuthorizedPAAListCount <= kMaxAuthorizedPAAListCount, CHIP_ERROR_INVALID_ARGUMENT);

        ReturnErrorOnFailure(writer.StartContainer(ContextTag(kTag_AuthorizedPAAList), kTLVType_Array, outerContainer2));
        for (uint8_t i = 0; i < certElements.AuthorizedPAAListCount; i++)
        {
            ReturnErrorOnFailure(writer.Put(AnonymousTag(), ByteSpan(certElements.AuthorizedPAAList[i])));
        }
        ReturnErrorOnFailure(writer.EndContainer(outerContainer2));
    }

    ReturnErrorOnFailure(writer.EndContainer(outerContainer1));

    ReturnErrorOnFailure(writer.Finalize());

    encodedCertElements.reduce_size(writer.GetLengthWritten());

    return CHIP_NO_ERROR;
}

CHIP_ERROR DecodeCertificationElements(const ByteSpan & encodedCertElements, CertificationElements & certElements)
{
    CHIP_ERROR err;
    TLVReader reader;
    TLVType outerContainer1, outerContainer2;

    VerifyOrReturnError(encodedCertElements.size() <= kMaxCMSSignedCDMessage, CHIP_ERROR_INVALID_ARGUMENT);

    reader.Init(encodedCertElements);

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

    ReturnErrorOnFailure(reader.EnterContainer(outerContainer1));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_FormatVersion)));
    ReturnErrorOnFailure(reader.Get(certElements.FormatVersion));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_VendorId)));
    ReturnErrorOnFailure(reader.Get(certElements.VendorId));

    ReturnErrorOnFailure(reader.Next(kTLVType_Array, ContextTag(kTag_ProductIdArray)));
    ReturnErrorOnFailure(reader.EnterContainer(outerContainer2));

    certElements.ProductIdsCount = 0;
    while ((err = reader.Next(AnonymousTag())) == CHIP_NO_ERROR)
    {
        ReturnErrorOnFailure(reader.Get(certElements.ProductIds[certElements.ProductIdsCount++]));
    }
    VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
    ReturnErrorOnFailure(reader.ExitContainer(outerContainer2));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_DeviceTypeId)));
    ReturnErrorOnFailure(reader.Get(certElements.DeviceTypeId));

    ReturnErrorOnFailure(reader.Next(kTLVType_UTF8String, ContextTag(kTag_CertificateId)));
    ReturnErrorOnFailure(reader.GetString(certElements.CertificateId, sizeof(certElements.CertificateId)));
    VerifyOrReturnError(strlen(certElements.CertificateId) == kCertificateIdLength, CHIP_ERROR_INVALID_TLV_ELEMENT);

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_SecurityLevel)));
    ReturnErrorOnFailure(reader.Get(certElements.SecurityLevel));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_SecurityInformation)));
    ReturnErrorOnFailure(reader.Get(certElements.SecurityInformation));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_VersionNumber)));
    ReturnErrorOnFailure(reader.Get(certElements.VersionNumber));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_CertificationType)));
    ReturnErrorOnFailure(reader.Get(certElements.CertificationType));

    certElements.DACOriginVIDandPIDPresent = false;

    // If kTag_DACOriginVendorId present then kTag_DACOriginProductId must be present.
    if ((err = reader.Next(ContextTag(kTag_DACOriginVendorId))) == CHIP_NO_ERROR)
    {
        ReturnErrorOnFailure(reader.Get(certElements.DACOriginVendorId));

        ReturnErrorOnFailure(reader.Next(ContextTag(kTag_DACOriginProductId)));
        ReturnErrorOnFailure(reader.Get(certElements.DACOriginProductId));

        certElements.DACOriginVIDandPIDPresent = true;

        err = reader.Next();
    }
    VerifyOrReturnError(err == CHIP_END_OF_TLV || err == CHIP_ERROR_UNEXPECTED_TLV_ELEMENT || err == CHIP_NO_ERROR, err);

    if (err != CHIP_END_OF_TLV && reader.GetTag() == ContextTag(kTag_AuthorizedPAAList))
    {
        VerifyOrReturnError(reader.GetType() == kTLVType_Array, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);

        ReturnErrorOnFailure(reader.EnterContainer(outerContainer2));

        certElements.AuthorizedPAAListCount = 0;
        while ((err = reader.Next(kTLVType_ByteString, AnonymousTag())) == CHIP_NO_ERROR)
        {
            VerifyOrReturnError(reader.GetLength() == kKeyIdentifierLength, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);

            ReturnErrorOnFailure(
                reader.GetBytes(certElements.AuthorizedPAAList[certElements.AuthorizedPAAListCount++], kKeyIdentifierLength));
        }
        VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
        ReturnErrorOnFailure(reader.ExitContainer(outerContainer2));

        err = reader.Next();
    }
    VerifyOrReturnError(err == CHIP_END_OF_TLV || err == CHIP_ERROR_UNEXPECTED_TLV_ELEMENT || err == CHIP_NO_ERROR, err);

    ReturnErrorOnFailure(reader.ExitContainer(outerContainer1));

    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    return CHIP_NO_ERROR;
}

CHIP_ERROR DecodeCertificationElements(const ByteSpan & encodedCertElements, CertificationElementsWithoutPIDs & certDeclContent)
{
    CHIP_ERROR err;
    TLVReader reader;
    TLVType outerContainer;
    TLVType outerContainer2;

    VerifyOrReturnError(encodedCertElements.size() <= kMaxCMSSignedCDMessage, CHIP_ERROR_INVALID_ARGUMENT);

    reader.Init(encodedCertElements);

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

    ReturnErrorOnFailure(reader.EnterContainer(outerContainer));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_FormatVersion)));
    ReturnErrorOnFailure(reader.Get(certDeclContent.formatVersion));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_VendorId)));
    ReturnErrorOnFailure(reader.Get(certDeclContent.vendorId));

    ReturnErrorOnFailure(reader.Next(kTLVType_Array, ContextTag(kTag_ProductIdArray)));
    ReturnErrorOnFailure(reader.EnterContainer(outerContainer2));

    while ((err = reader.Next(kTLVType_UnsignedInteger, AnonymousTag())) == CHIP_NO_ERROR)
    {
        // Verifies that the TLV structure of PID Array is correct
        // but skip the values
    }
    VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
    ReturnErrorOnFailure(reader.ExitContainer(outerContainer2));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_DeviceTypeId)));
    ReturnErrorOnFailure(reader.Get(certDeclContent.deviceTypeId));

    ReturnErrorOnFailure(reader.Next(kTLVType_UTF8String, ContextTag(kTag_CertificateId)));
    ReturnErrorOnFailure(reader.GetString(certDeclContent.certificateId, sizeof(certDeclContent.certificateId)));
    VerifyOrReturnError(strlen(certDeclContent.certificateId) == kCertificateIdLength, CHIP_ERROR_INVALID_TLV_ELEMENT);

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_SecurityLevel)));
    ReturnErrorOnFailure(reader.Get(certDeclContent.securityLevel));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_SecurityInformation)));
    ReturnErrorOnFailure(reader.Get(certDeclContent.securityInformation));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_VersionNumber)));
    ReturnErrorOnFailure(reader.Get(certDeclContent.versionNumber));

    ReturnErrorOnFailure(reader.Next(ContextTag(kTag_CertificationType)));
    ReturnErrorOnFailure(reader.Get(certDeclContent.certificationType));

    certDeclContent.dacOriginVIDandPIDPresent = false;

    // If kTag_DACOriginVendorId present then kTag_DACOriginProductId must be present.
    if ((err = reader.Next(ContextTag(kTag_DACOriginVendorId))) == CHIP_NO_ERROR)
    {
        ReturnErrorOnFailure(reader.Get(certDeclContent.dacOriginVendorId));

        ReturnErrorOnFailure(reader.Next(ContextTag(kTag_DACOriginProductId)));
        ReturnErrorOnFailure(reader.Get(certDeclContent.dacOriginProductId));

        certDeclContent.dacOriginVIDandPIDPresent = true;

        err = reader.Next();
    }
    VerifyOrReturnError(err == CHIP_END_OF_TLV || err == CHIP_ERROR_UNEXPECTED_TLV_ELEMENT || err == CHIP_NO_ERROR, err);

    if (err != CHIP_END_OF_TLV && reader.GetTag() == ContextTag(kTag_AuthorizedPAAList))
    {
        VerifyOrReturnError(reader.GetType() == kTLVType_Array, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);

        ReturnErrorOnFailure(reader.EnterContainer(outerContainer2));

        while ((err = reader.Next(kTLVType_ByteString, AnonymousTag())) == CHIP_NO_ERROR)
        {
            VerifyOrReturnError(reader.GetLength() == kKeyIdentifierLength, CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
            // Verifies that the TLV structure of the Authorized PAA List is correct
            // but skip the values
        }
        VerifyOrReturnError(err == CHIP_END_OF_TLV, err);

        ReturnErrorOnFailure(reader.ExitContainer(outerContainer2));

        certDeclContent.authorizedPAAListPresent = true;

        err = reader.Next();
    }
    VerifyOrReturnError(err == CHIP_END_OF_TLV || err == CHIP_ERROR_UNEXPECTED_TLV_ELEMENT || err == CHIP_NO_ERROR, err);

    ReturnErrorOnFailure(reader.ExitContainer(outerContainer));

    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    return CHIP_NO_ERROR;
}

bool CertificationElementsDecoder::IsProductIdIn(const ByteSpan & encodedCertElements, uint16_t productId)
{
    VerifyOrReturnError(FindAndEnterArray(encodedCertElements, ContextTag(kTag_ProductIdArray)) == CHIP_NO_ERROR, false);

    uint16_t cdProductId = 0;
    while (GetNextProductId(cdProductId) == CHIP_NO_ERROR)
    {
        if (productId == cdProductId)
        {
            return true;
        }
    }
    return false;
}

CHIP_ERROR CertificationElementsDecoder::FindAndEnterArray(const ByteSpan & encodedCertElements, Tag arrayTag)
{
    TLVType outerContainerType1;
    TLVType outerContainerType2;

    mReader.Init(encodedCertElements);
    ReturnErrorOnFailure(mReader.Next(kTLVType_Structure, AnonymousTag()));
    ReturnErrorOnFailure(mReader.EnterContainer(outerContainerType1));

    // position to arrayTag Array
    CHIP_ERROR error = CHIP_NO_ERROR;
    do
    {
        error = mReader.Next(kTLVType_Array, arrayTag);
        // Return error code unless one of three things happened:
        // 1. We found the right thing (CHIP_NO_ERROR returned).
        // 2. The next tag is not the one we are looking for (CHIP_ERROR_UNEXPECTED_TLV_ELEMENT).
        VerifyOrReturnError(error == CHIP_NO_ERROR || error == CHIP_ERROR_UNEXPECTED_TLV_ELEMENT, error);
    } while (error != CHIP_NO_ERROR);

    ReturnErrorOnFailure(mReader.EnterContainer(outerContainerType2));

    return CHIP_NO_ERROR;
}

CHIP_ERROR CertificationElementsDecoder::GetNextProductId(uint16_t & productId)
{
    ReturnErrorOnFailure(mReader.Next(AnonymousTag()));
    ReturnErrorOnFailure(mReader.Get(productId));
    return CHIP_NO_ERROR;
}

bool CertificationElementsDecoder::HasAuthorizedPAA(const ByteSpan & encodedCertElements, const ByteSpan & authorizedPAA)
{
    VerifyOrReturnError(FindAndEnterArray(encodedCertElements, ContextTag(kTag_AuthorizedPAAList)) == CHIP_NO_ERROR, false);

    ByteSpan cdAuthorizedPAA;
    while (GetNextAuthorizedPAA(cdAuthorizedPAA) == CHIP_NO_ERROR)
    {
        if (authorizedPAA.data_equal(cdAuthorizedPAA))
        {
            return true;
        }
    }
    return false;
}

CHIP_ERROR CertificationElementsDecoder::GetNextAuthorizedPAA(ByteSpan & authorizedPAA)
{
    ReturnErrorOnFailure(mReader.Next(AnonymousTag()));
    ReturnErrorOnFailure(mReader.Get(authorizedPAA));
    return CHIP_NO_ERROR;
}

namespace {

CHIP_ERROR EncodeEncapsulatedContent(const ByteSpan & cdContent, ASN1Writer & writer)
{
    /**
     * EncapsulatedContentInfo ::= SEQUENCE {
     *   eContentType OBJECT IDENTIFIER pkcs7-data (1.2.840.113549.1.7.1),
     *   eContent [0] EXPLICIT OCTET STRING cd_content }
     */
    CHIP_ERROR err = CHIP_NO_ERROR;

    ASN1_START_SEQUENCE
    {
        // eContentType OBJECT IDENTIFIER pkcs7-data (1.2.840.113549.1.7.1)
        ReturnErrorOnFailure(writer.PutObjectId(sOID_ContentType_PKCS7Data, sizeof(sOID_ContentType_PKCS7Data)));

        // eContent [0] EXPLICIT OCTET STRING cd_content
        ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
        {
            // OCTET STRING cd_content
            ReturnErrorOnFailure(writer.PutOctetString(cdContent.data(), static_cast<uint16_t>(cdContent.size())));
        }
        ASN1_END_CONSTRUCTED;
    }
    ASN1_END_SEQUENCE;

exit:
    return err;
}

CHIP_ERROR DecodeEncapsulatedContent(ASN1Reader & reader, ByteSpan & cdContent)
{
    /**
     * EncapsulatedContentInfo ::= SEQUENCE {
     *   eContentType OBJECT IDENTIFIER pkcs7-data (1.2.840.113549.1.7.1),
     *   eContent [0] EXPLICIT OCTET STRING cd_content }
     */
    CHIP_ERROR err = CHIP_NO_ERROR;

    ASN1_PARSE_ENTER_SEQUENCE
    {
        // eContentType OBJECT IDENTIFIER pkcs7-data (1.2.840.113549.1.7.1)
        ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);
        VerifyOrReturnError(ByteSpan(reader.GetValue(), reader.GetValueLen()).data_equal(ByteSpan(sOID_ContentType_PKCS7Data)),
                            ASN1_ERROR_UNSUPPORTED_ENCODING);

        // eContent [0] EXPLICIT OCTET STRING cd_content
        ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
        {
            // OCTET STRING cd_content
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString);
            cdContent = ByteSpan(reader.GetValue(), reader.GetValueLen());
        }
        ASN1_EXIT_CONSTRUCTED;
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

CHIP_ERROR EncodeSignerInfo(const ByteSpan & signerKeyId, const P256ECDSASignature & signature, ASN1Writer & writer)
{
    /**
     * SignerInfo ::= SEQUENCE {
     *   version INTEGER ( v3(3) ),
     *   subjectKeyIdentifier OCTET STRING,
     *   digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1),
     *   signatureAlgorithm OBJECT IDENTIFIER ecdsa-with-SHA256 (1.2.840.10045.4.3.2),
     *   signature OCTET STRING }
     */
    CHIP_ERROR err = CHIP_NO_ERROR;

    ASN1_START_SET
    {
        ASN1_START_SEQUENCE
        {
            // version INTEGER ( v3(3) )
            ASN1_ENCODE_INTEGER(3);

            // subjectKeyIdentifier OCTET STRING
            ReturnErrorOnFailure(writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, signerKeyId.data(),
                                                       static_cast<uint16_t>(signerKeyId.size())));

            // digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1)
            ASN1_START_SEQUENCE
            {
                ReturnErrorOnFailure(writer.PutObjectId(sOID_DigestAlgo_SHA256, sizeof(sOID_DigestAlgo_SHA256)));
            }
            ASN1_END_SEQUENCE;

            // signatureAlgorithm OBJECT IDENTIFIER ecdsa-with-SHA256 (1.2.840.10045.4.3.2)
            ASN1_START_SEQUENCE { ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256); }
            ASN1_END_SEQUENCE;

            uint8_t asn1SignatureBuf[kMax_ECDSA_Signature_Length_Der];
            MutableByteSpan asn1Signature(asn1SignatureBuf);
            ReturnErrorOnFailure(EcdsaRawSignatureToAsn1(kP256_FE_Length, ByteSpan(signature, signature.Length()), asn1Signature));

            // signature OCTET STRING
            ReturnErrorOnFailure(writer.PutOctetString(asn1Signature.data(), static_cast<uint16_t>(asn1Signature.size())));
        }
        ASN1_END_SEQUENCE;
    }
    ASN1_END_SET;

exit:
    return err;
}

CHIP_ERROR DecodeSignerInfo(ASN1Reader & reader, ByteSpan & signerKeyId, P256ECDSASignature & signature)
{
    /**
     * SignerInfo ::= SEQUENCE {
     *   version INTEGER ( v3(3) ),
     *   subjectKeyIdentifier OCTET STRING,
     *   digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1),
     *   signatureAlgorithm OBJECT IDENTIFIER ecdsa-with-SHA256 (1.2.840.10045.4.3.2),
     *   signature OCTET STRING }
     */
    CHIP_ERROR err = CHIP_NO_ERROR;

    ASN1_PARSE_ENTER_SET
    {
        ASN1_PARSE_ENTER_SEQUENCE
        {
            // version INTEGER ( v3(3) )
            {
                int64_t version;
                ASN1_PARSE_INTEGER(version);

                // Verify that the CMS version is v3
                VerifyOrExit(version == 3, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
            }

            // subjectKeyIdentifier OCTET STRING
            ASN1_PARSE_ELEMENT(kASN1TagClass_ContextSpecific, 0);
            signerKeyId = ByteSpan(reader.GetValue(), reader.GetValueLen());

            // digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1)
            ASN1_PARSE_ENTER_SEQUENCE
            {
                ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);
                VerifyOrReturnError(ByteSpan(reader.GetValue(), reader.GetValueLen()).data_equal(ByteSpan(sOID_DigestAlgo_SHA256)),
                                    ASN1_ERROR_UNSUPPORTED_ENCODING);
            }
            ASN1_EXIT_SEQUENCE;

            // signatureAlgorithm OBJECT IDENTIFIER ecdsa-with-SHA256 (1.2.840.10045.4.3.2)
            ASN1_PARSE_ENTER_SEQUENCE
            {
                ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);
                VerifyOrReturnError(
                    ByteSpan(reader.GetValue(), reader.GetValueLen()).data_equal(ByteSpan(sOID_SigAlgo_ECDSAWithSHA256)),
                    ASN1_ERROR_UNSUPPORTED_ENCODING);
            }
            ASN1_EXIT_SEQUENCE;

            // signature OCTET STRING
            ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString);

            MutableByteSpan signatureSpan(signature, signature.Capacity());
            ReturnErrorOnFailure(
                EcdsaAsn1SignatureToRaw(kP256_FE_Length, ByteSpan(reader.GetValue(), reader.GetValueLen()), signatureSpan));
            ReturnErrorOnFailure(signature.SetLength(signatureSpan.size()));
        }
        ASN1_EXIT_SEQUENCE;
    }
    ASN1_EXIT_SET;

exit:
    return err;
}

} // namespace

CHIP_ERROR CMS_Sign(const ByteSpan & cdContent, const ByteSpan & signerKeyId, Crypto::P256Keypair & signerKeypair,
                    MutableByteSpan & signedMessage)
{
    /**
     * CertificationDeclaration ::= SEQUENCE {
     *   version INTEGER ( v3(3) ),
     *   digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1),
     *   encapContentInfo EncapsulatedContentInfo,
     *   signerInfo SignerInfo }
     */
    CHIP_ERROR err = CHIP_NO_ERROR;
    ASN1Writer writer;
    uint32_t size = static_cast<uint32_t>(std::min(static_cast<size_t>(UINT32_MAX), signedMessage.size()));

    writer.Init(signedMessage.data(), size);

    ASN1_START_SEQUENCE
    {
        // OID identifies the CMS signed-data content type
        ReturnErrorOnFailure(writer.PutObjectId(sOID_ContentType_PKCS7SignedData, sizeof(sOID_ContentType_PKCS7SignedData)));

        ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
        {
            ASN1_START_SEQUENCE
            {
                // version INTEGER ( v3(3) )
                ASN1_ENCODE_INTEGER(3);

                // digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1)
                ASN1_START_SET
                {
                    ASN1_START_SEQUENCE
                    {
                        ReturnErrorOnFailure(writer.PutObjectId(sOID_DigestAlgo_SHA256, sizeof(sOID_DigestAlgo_SHA256)));
                    }
                    ASN1_END_SEQUENCE;
                }
                ASN1_END_SET;

                // encapContentInfo EncapsulatedContentInfo
                ReturnErrorOnFailure(EncodeEncapsulatedContent(cdContent, writer));

                Crypto::P256ECDSASignature signature;
                ReturnErrorOnFailure(signerKeypair.ECDSA_sign_msg(cdContent.data(), cdContent.size(), signature));

                // signerInfo SignerInfo
                ReturnErrorOnFailure(EncodeSignerInfo(signerKeyId, signature, writer));
            }
            ASN1_END_SEQUENCE;
        }
        ASN1_END_CONSTRUCTED;
    }
    ASN1_END_SEQUENCE;

    signedMessage.reduce_size(writer.GetLengthWritten());

exit:
    return err;
}

CHIP_ERROR CMS_Verify(const ByteSpan & signedMessage, const ByteSpan & signerX509Cert, ByteSpan & cdContent)
{
    P256PublicKey signerPubkey;

    ReturnErrorOnFailure(ExtractPubkeyFromX509Cert(signerX509Cert, signerPubkey));

    return CMS_Verify(signedMessage, signerPubkey, cdContent);
}

CHIP_ERROR CMS_Verify(const ByteSpan & signedMessage, const Crypto::P256PublicKey & signerPubkey, ByteSpan & cdContent)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    ASN1Reader reader;
    uint32_t size = signedMessage.size() > UINT32_MAX ? UINT32_MAX : static_cast<uint32_t>(signedMessage.size());

    reader.Init(signedMessage.data(), size);

    // SignedData ::= SEQUENCE
    ASN1_PARSE_ENTER_SEQUENCE
    {
        ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);

        // id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
        // OID identifies the CMS signed-data content type
        VerifyOrReturnError(
            ByteSpan(reader.GetValue(), reader.GetValueLen()).data_equal(ByteSpan(sOID_ContentType_PKCS7SignedData)),
            ASN1_ERROR_UNSUPPORTED_ENCODING);

        // version [0] EXPLICIT Version DEFAULT v3
        ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
        {
            ASN1_PARSE_ENTER_SEQUENCE
            {
                // Version ::= INTEGER { v3(3) }
                int64_t version;
                ASN1_PARSE_INTEGER(version);

                // Verify that the CMS version is v3
                VerifyOrExit(version == 3, err = ASN1_ERROR_UNSUPPORTED_ENCODING);

                // digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1)
                ASN1_PARSE_ENTER_SET
                {
                    ASN1_PARSE_ENTER_SEQUENCE
                    {
                        ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);
                        VerifyOrReturnError(
                            ByteSpan(reader.GetValue(), reader.GetValueLen()).data_equal(ByteSpan(sOID_DigestAlgo_SHA256)),
                            ASN1_ERROR_UNSUPPORTED_ENCODING);
                    }
                    ASN1_EXIT_SEQUENCE;
                }
                ASN1_EXIT_SET;

                // encapContentInfo EncapsulatedContentInfo
                ReturnErrorOnFailure(DecodeEncapsulatedContent(reader, cdContent));

                // signerInfo SignerInfo
                ByteSpan signerKeyId;
                P256ECDSASignature signature;
                ReturnErrorOnFailure(DecodeSignerInfo(reader, signerKeyId, signature));

                // Validate CD Signature
                ReturnErrorOnFailure(signerPubkey.ECDSA_validate_msg_signature(cdContent.data(), cdContent.size(), signature));
            }
            ASN1_EXIT_SEQUENCE;
        }
        ASN1_EXIT_CONSTRUCTED;
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

CHIP_ERROR CMS_ExtractKeyId(const ByteSpan & signedMessage, ByteSpan & signerKeyId)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    ASN1Reader reader;
    uint32_t size = signedMessage.size() > UINT32_MAX ? UINT32_MAX : static_cast<uint32_t>(signedMessage.size());

    reader.Init(signedMessage.data(), size);

    // SignedData ::= SEQUENCE
    ASN1_PARSE_ENTER_SEQUENCE
    {
        // id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
        // OID identifies the CMS signed-data content type
        ASN1_PARSE_ANY;

        // version [0] EXPLICIT Version DEFAULT v3
        ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
        {
            ASN1_PARSE_ENTER_SEQUENCE
            {
                // Version ::= INTEGER { v3(3) }
                ASN1_PARSE_ANY;

                // digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1)
                ASN1_PARSE_ANY;

                // encapContentInfo EncapsulatedContentInfo
                ASN1_PARSE_ANY;

                // signerInfo SignerInfo
                P256ECDSASignature signature;
                ReturnErrorOnFailure(DecodeSignerInfo(reader, signerKeyId, signature));
            }
            ASN1_EXIT_SEQUENCE;
        }
        ASN1_EXIT_CONSTRUCTED;
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

CHIP_ERROR CMS_ExtractCDContent(const ByteSpan & signedMessage, ByteSpan & cdContent)
{
    CHIP_ERROR err = CHIP_NO_ERROR;
    ASN1Reader reader;
    uint32_t size = signedMessage.size() > UINT32_MAX ? UINT32_MAX : static_cast<uint32_t>(signedMessage.size());

    reader.Init(signedMessage.data(), size);

    // SignedData ::= SEQUENCE
    ASN1_PARSE_ENTER_SEQUENCE
    {
        // id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
        // OID identifies the CMS signed-data content type
        ASN1_PARSE_ANY;

        // version [0] EXPLICIT Version DEFAULT v3
        ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
        {
            ASN1_PARSE_ENTER_SEQUENCE
            {
                // Version ::= INTEGER { v3(3) }
                ASN1_PARSE_ANY;

                // digestAlgorithm OBJECT IDENTIFIER sha256 (2.16.840.1.101.3.4.2.1)
                ASN1_PARSE_ANY;

                // encapContentInfo EncapsulatedContentInfo
                ReturnErrorOnFailure(DecodeEncapsulatedContent(reader, cdContent));

                // signerInfo SignerInfo
                ASN1_PARSE_ANY;
            }
            ASN1_EXIT_SEQUENCE;
        }
        ASN1_EXIT_CONSTRUCTED;
    }
    ASN1_EXIT_SEQUENCE;

exit:
    return err;
}

} // namespace Credentials
} // namespace chip
