/*
 *
 *    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/TLV.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);
    VerifyOrReturnError(reader.GetTag() != TLV::ContextTag(kTag_DACOriginProductId), CHIP_ERROR_INVALID_TLV_ELEMENT);

    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);
    VerifyOrReturnError(reader.GetTag() != TLV::ContextTag(kTag_DACOriginProductId), CHIP_ERROR_INVALID_TLV_ELEMENT);

    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, signature.Span(), 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.Bytes(), 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
