/*
 *
 *    Copyright (c) 2021 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. */
};

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 <= kMaxProductIdsCountPerCD, 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));
    }
    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);

    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;

    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)));

    // skip PID Array

    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);

    ReturnErrorOnFailure(reader.ExitContainer(outerContainer));

    ReturnErrorOnFailure(reader.VerifyEndOfContainer());

    return CHIP_NO_ERROR;
}

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

    uint16_t cdProductId = 0;
    CHIP_ERROR error     = CHIP_NO_ERROR;

    while ((error = GetNextProductId(cdProductId)) == CHIP_NO_ERROR)
    {
        if (productId == cdProductId)
        {
            return true;
        }
    }

    return false;
}

CHIP_ERROR CertificationElementsDecoder::PrepareToReadProductIdList(const ByteSpan & encodedCertElements)
{
    mIsInitialized                = false;
    mCertificationDeclarationData = encodedCertElements;

    mReader.Init(mCertificationDeclarationData);
    ReturnErrorOnFailure(mReader.Next(kTLVType_Structure, AnonymousTag()));
    ReturnErrorOnFailure(mReader.EnterContainer(mOuterContainerType1));

    // position to ProductId Array
    CHIP_ERROR error = CHIP_NO_ERROR;
    do
    {
        error = mReader.Next(kTLVType_Array, ContextTag(kTag_ProductIdArray));
        // return error code if Next method returned different than CHIP_NO_ERROR.
        // also return if different error code than CHIP_ERROR_WRONG_TLV_TYPE/CHIP_ERROR_UNEXPECTED_TLV_ELEMENT, which means that
        // the expected type and tags do not match.
        VerifyOrReturnError(
            error == CHIP_NO_ERROR || error == CHIP_ERROR_WRONG_TLV_TYPE || error == CHIP_ERROR_UNEXPECTED_TLV_ELEMENT, error);
    } while (error != CHIP_NO_ERROR);

    ReturnErrorOnFailure(mReader.EnterContainer(mOuterContainerType2));

    mIsInitialized = true;
    return CHIP_NO_ERROR;
}

CHIP_ERROR CertificationElementsDecoder::GetNextProductId(uint16_t & productId)
{
    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_INCORRECT_STATE);
    ReturnErrorOnFailure(mReader.Next(AnonymousTag()));
    ReturnErrorOnFailure(mReader.Get(productId));
    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
