/*
 *
 *    Copyright (c) 2021-2023 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 utility functions for reading, writing,
 *      parsing, resigning, encoding, and decoding CHIP certificates.
 *
 */

#include "chip-cert.h"
#include <lib/core/CHIPEncoding.h>
#include <lib/support/BytesToHex.h>

#include <memory>
#include <string>
#include <utility>

using namespace chip;
using namespace chip::Credentials;
using namespace chip::ASN1;
using namespace chip::TLV;
using namespace chip::Encoding;

bool ToolChipDN::SetCertName(X509_NAME * name) const
{
    bool res         = true;
    uint8_t rdnCount = RDNCount();

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        int attrNID;
        switch (rdn[i].mAttrOID)
        {
        case kOID_AttributeType_CommonName:
            attrNID = NID_commonName;
            break;
        case kOID_AttributeType_Surname:
            attrNID = NID_surname;
            break;
        case kOID_AttributeType_SerialNumber:
            attrNID = NID_serialNumber;
            break;
        case kOID_AttributeType_CountryName:
            attrNID = NID_countryName;
            break;
        case kOID_AttributeType_LocalityName:
            attrNID = NID_localityName;
            break;
        case kOID_AttributeType_StateOrProvinceName:
            attrNID = NID_stateOrProvinceName;
            break;
        case kOID_AttributeType_OrganizationName:
            attrNID = NID_organizationName;
            break;
        case kOID_AttributeType_OrganizationalUnitName:
            attrNID = NID_organizationalUnitName;
            break;
        case kOID_AttributeType_Title:
            attrNID = NID_title;
            break;
        case kOID_AttributeType_Name:
            attrNID = NID_name;
            break;
        case kOID_AttributeType_GivenName:
            attrNID = NID_givenName;
            break;
        case kOID_AttributeType_Initials:
            attrNID = NID_initials;
            break;
        case kOID_AttributeType_GenerationQualifier:
            attrNID = NID_generationQualifier;
            break;
        case kOID_AttributeType_DNQualifier:
            attrNID = NID_dnQualifier;
            break;
        case kOID_AttributeType_Pseudonym:
            attrNID = NID_pseudonym;
            break;
        case kOID_AttributeType_DomainComponent:
            attrNID = NID_domainComponent;
            break;
        case kOID_AttributeType_MatterNodeId:
            attrNID = gNIDChipNodeId;
            break;
        case kOID_AttributeType_MatterFirmwareSigningId:
            attrNID = gNIDChipFirmwareSigningId;
            break;
        case kOID_AttributeType_MatterICACId:
            attrNID = gNIDChipICAId;
            break;
        case kOID_AttributeType_MatterVidVerificationSignerId:
            attrNID = gNIDChipVidVerificationSignerId;
            break;
        case kOID_AttributeType_MatterRCACId:
            attrNID = gNIDChipRootId;
            break;
        case kOID_AttributeType_MatterFabricId:
            attrNID = gNIDChipFabricId;
            break;
        case kOID_AttributeType_MatterCASEAuthTag:
            attrNID = gNIDChipCASEAuthenticatedTag;
            break;
        default:
            ExitNow(res = false);
        }

        char chipAttrStr[std::max(kChip64bitAttrUTF8Length, kChip32bitAttrUTF8Length)] = { 0 };
        int type                                                                       = V_ASN1_UTF8STRING;
        uint8_t * attrStr                                                              = reinterpret_cast<uint8_t *>(chipAttrStr);
        int attrLen                                                                    = 0;

        if (IsChip64bitDNAttr(rdn[i].mAttrOID))
        {
            VerifyOrReturnError(Encoding::Uint64ToHex(rdn[i].mChipVal, chipAttrStr, kChip64bitAttrUTF8Length,
                                                      Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR,
                                false);
            attrLen = kChip64bitAttrUTF8Length;
        }
        else if (IsChip32bitDNAttr(rdn[i].mAttrOID))
        {
            VerifyOrReturnError(Encoding::Uint32ToHex(static_cast<uint32_t>(rdn[i].mChipVal), chipAttrStr, kChip32bitAttrUTF8Length,
                                                      Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR,
                                false);
            attrLen = kChip32bitAttrUTF8Length;
        }
        else
        {
            if (rdn[i].mAttrOID == kOID_AttributeType_DomainComponent)
            {
                type = V_ASN1_IA5STRING;
            }
            else if (rdn[i].mAttrIsPrintableString)
            {
                type = V_ASN1_PRINTABLESTRING;
            }
            attrStr = reinterpret_cast<uint8_t *>(const_cast<char *>(rdn[i].mString.data()));
            attrLen = static_cast<int>(rdn[i].mString.size());
        }

        if (!X509_NAME_add_entry_by_NID(name, attrNID, type, attrStr, attrLen, -1, 0))
        {
            ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false);
        }
    }

exit:
    return res;
}

bool ToolChipDN::HasAttr(chip::ASN1::OID oid) const
{
    uint8_t rdnCount = RDNCount();

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        if (oid == rdn[i].mAttrOID)
        {
            return true;
        }
    }

    return false;
}

void ToolChipDN::PrintDN(FILE * file, const char * name) const
{
    uint8_t rdnCount = RDNCount();
    char valueStr[128];
    const char * certDesc = nullptr;

    fprintf(file, "%s: ", name);

    for (uint8_t i = 0; i < rdnCount; i++)
    {
        if (IsChip64bitDNAttr(rdn[i].mAttrOID))
        {
            TEMPORARY_RETURN_IGNORED Encoding::Uint64ToHex(rdn[i].mChipVal, valueStr, sizeof(valueStr),
                                                           Encoding::HexFlags::kUppercaseAndNullTerminate);
        }
        else if (IsChip32bitDNAttr(rdn[i].mAttrOID))
        {
            TEMPORARY_RETURN_IGNORED Encoding::Uint32ToHex(static_cast<uint32_t>(rdn[i].mChipVal), valueStr, sizeof(valueStr),
                                                           Encoding::HexFlags::kUppercaseAndNullTerminate);
        }
        else
        {
            size_t len = rdn[i].mString.size();
            if (len > sizeof(valueStr) - 1)
            {
                len = sizeof(valueStr) - 1;
            }
            memcpy(valueStr, rdn[i].mString.data(), len);
            valueStr[len] = 0;
        }

        fprintf(file, "%s=%s", chip::ASN1::GetOIDName(rdn[i].mAttrOID), valueStr);
        if (certDesc != nullptr)
        {
            fprintf(file, " (%s)", certDesc);
        }
    }
}

namespace {

template <size_t N>
bool HasRawPrefix(const uint8_t * buffer, size_t len, const uint8_t (&prefix)[N])
{
    return len >= N && memcmp(buffer, prefix, N) == 0;
}

bool HasStringPrefix(const uint8_t * buffer, size_t len, const char * prefix)
{
    size_t prefixLen = strlen(prefix);
    return len >= prefixLen && memcmp(buffer, prefix, prefixLen) == 0;
}

CertFormat DetectCertFormat(const uint8_t * cert, uint32_t certLen)
{
    static const uint8_t chipRawPrefix[]           = { 0x15, 0x30, 0x01 };
    static const char chipHexPrefix[]              = "153001";
    static const char chipB64Prefix[]              = "FTAB";
    static const uint8_t chipCompactPdcRawPrefix[] = { 0x15, 0x30, 0x09 };
    static const char chipCompactPdcHexPrefix[]    = "153009";
    static const char chipCompactPdcB64Prefix[]    = "FTAJ";
    static const uint8_t derRawPrefix[]            = { 0x30, 0x82 };
    static const char derHexPrefix[]               = "30820";
    static const char pemMarker[]                  = "-----BEGIN CERTIFICATE-----";

    VerifyOrReturnError(cert != nullptr, kCertFormat_Unknown);

    if (HasRawPrefix(cert, certLen, chipRawPrefix) || HasRawPrefix(cert, certLen, chipCompactPdcRawPrefix))
    {
        return kCertFormat_Chip_Raw;
    }

    if (HasStringPrefix(cert, certLen, chipHexPrefix) || HasStringPrefix(cert, certLen, chipCompactPdcHexPrefix))
    {
        return kCertFormat_Chip_Hex;
    }

    if (HasStringPrefix(cert, certLen, chipB64Prefix) || HasStringPrefix(cert, certLen, chipCompactPdcB64Prefix))
    {
        return kCertFormat_Chip_Base64;
    }

    if (HasRawPrefix(cert, certLen, derRawPrefix))
    {
        return kCertFormat_X509_DER;
    }

    if (HasStringPrefix(cert, certLen, derHexPrefix))
    {
        return kCertFormat_X509_Hex;
    }

    if (ContainsPEMMarker(pemMarker, cert, certLen))
    {
        return kCertFormat_X509_PEM;
    }

    return kCertFormat_Unknown;
}

bool SetCertSerialNumber(X509 * cert, uint64_t value = kUseRandomSerialNumber)
{
    bool res = true;
    uint64_t rnd;
    ASN1_INTEGER * snInt = X509_get_serialNumber(cert);

    if (value == kUseRandomSerialNumber)
    {
        // Generate a random value to be used as the serial number.
        if (!RAND_bytes(reinterpret_cast<uint8_t *>(&rnd), sizeof(rnd)))
        {
            ReportOpenSSLErrorAndExit("RAND_bytes", res = false);
        }

        // Avoid negative numbers.
        value = rnd & 0x7FFFFFFFFFFFFFFFULL;
    }

    // Store the serial number as an ASN1 integer value within the certificate.
    if (ASN1_INTEGER_set_uint64(snInt, value) == 0)
    {
        ReportOpenSSLErrorAndExit("ASN1_INTEGER_set_uint64", res = false);
    }

exit:
    return res;
}

bool SetCertTimeField(ASN1_TIME * asn1Time, const struct tm & value)
{
    char timeStr[ASN1UniversalTime::kASN1TimeStringMaxLength + 1];
    MutableCharSpan timeSpan(timeStr);
    ASN1UniversalTime val = { .Year   = static_cast<uint16_t>((value.tm_year == kX509NoWellDefinedExpirationDateYear)
                                                                  ? kX509NoWellDefinedExpirationDateYear
                                                                  : (value.tm_year + 1900)),
                              .Month  = static_cast<uint8_t>(value.tm_mon + 1),
                              .Day    = static_cast<uint8_t>(value.tm_mday),
                              .Hour   = static_cast<uint8_t>(value.tm_hour),
                              .Minute = static_cast<uint8_t>(value.tm_min),
                              .Second = static_cast<uint8_t>(value.tm_sec) };

    if (val.ExportTo_ASN1_TIME_string(timeSpan) != CHIP_NO_ERROR)
    {
        fprintf(stderr, "ExportTo_ASN1_TIME_string() failed\n");
        return false;
    }

    timeSpan.data()[timeSpan.size()] = '\0';

    if (!ASN1_TIME_set_string(asn1Time, timeStr))
    {
        fprintf(stderr, "OpenSSL ASN1_TIME_set_string() failed\n");
        return false;
    }

    return true;
}

bool SetValidityTime(X509 * cert, const struct tm & validFrom, uint32_t validDays, CertStructConfig & certConfig)
{
    bool res = true;
    struct tm validFromLocal;
    struct tm validTo;
    time_t validToTime;

    // Compute the validity end date.
    // Note that this computation is done in local time, despite the fact that the certificate validity times are
    // UTC.  This is because the standard posix time functions do not make it easy to convert a struct tm containing
    // UTC to a time_t value without manipulating the TZ environment variable.
    if (validDays == kCertValidDays_NoWellDefinedExpiration)
    {
        validTo.tm_year  = kX509NoWellDefinedExpirationDateYear;
        validTo.tm_mon   = kMonthsPerYear - 1;
        validTo.tm_mday  = kMaxDaysPerMonth;
        validTo.tm_hour  = kHoursPerDay - 1;
        validTo.tm_min   = kMinutesPerHour - 1;
        validTo.tm_sec   = kSecondsPerMinute - 1;
        validTo.tm_isdst = -1;
    }
    else
    {
        validTo = validFrom;
        validTo.tm_mday += validDays;
        validTo.tm_sec -= 1; // Ensure validity period is exactly a multiple of a day.
        validTo.tm_isdst = -1;
        validToTime      = mktime(&validTo);

        if (validToTime == static_cast<time_t>(-1))
        {
            fprintf(stderr, "mktime() failed\n");
            ExitNow(res = false);
        }
        localtime_r(&validToTime, &validTo);
    }

    if (certConfig.IsValidityCorrect())
    {
        validFromLocal = validFrom;
    }
    else
    {
        // Switch values if error flag is set.
        validFromLocal = validTo;
        validTo        = validFrom;
    }

    // Set the certificate's notBefore date.
    if (certConfig.IsValidityNotBeforePresent())
    {
        res = SetCertTimeField(X509_get_notBefore(cert), validFromLocal);
        VerifyTrueOrExit(res);
    }

    // Set the certificate's notAfter date.
    if (certConfig.IsValidityNotAfterPresent())
    {
        res = SetCertTimeField(X509_get_notAfter(cert), validTo);
        VerifyTrueOrExit(res);
    }

exit:
    return true;
}

bool AddExtension(X509 * cert, int extNID, const char * extStr)
{
    bool res = true;
    std::unique_ptr<X509_EXTENSION, void (*)(X509_EXTENSION *)> ex(
        X509V3_EXT_nconf_nid(nullptr, nullptr, extNID, const_cast<char *>(extStr)), &X509_EXTENSION_free);

    if (!X509_add_ext(cert, ex.get(), -1))
    {
        ReportOpenSSLErrorAndExit("X509_add_ext", res = false);
    }

exit:
    return res;
}

bool SetBasicConstraintsExtension(X509 * cert, bool isCA, int pathLen, CertStructConfig & certConfig)
{
    if (!certConfig.IsExtensionBasicPresent())
    {
        return true;
    }

    std::string basicConstraintsExt;

    if (certConfig.IsExtensionBasicCriticalPresent() && certConfig.IsExtensionBasicCritical())
    {
        basicConstraintsExt += "critical";
    }

    if (certConfig.IsExtensionBasicCAPresent())
    {
        if (!basicConstraintsExt.empty())
        {
            basicConstraintsExt += ",";
        }
        if ((certConfig.IsExtensionBasicCACorrect() && !isCA) || (!certConfig.IsExtensionBasicCACorrect() && isCA))
        {
            basicConstraintsExt += "CA:FALSE";
        }
        else
        {
            basicConstraintsExt += "CA:TRUE";
        }
    }

    if (pathLen != kPathLength_NotSpecified)
    {
        if (!basicConstraintsExt.empty())
        {
            basicConstraintsExt += ",";
        }
        basicConstraintsExt.append("pathlen:" + std::to_string(pathLen));
    }

    return AddExtension(cert, NID_basic_constraints, basicConstraintsExt.c_str());
}

bool SetKeyUsageExtension(X509 * cert, bool isCA, CertStructConfig & certConfig)
{
    if (!certConfig.IsExtensionKeyUsagePresent())
    {
        return true;
    }

    std::string keyUsageExt;

    if (certConfig.IsExtensionKeyUsageCriticalPresent() && certConfig.IsExtensionKeyUsageCritical())
    {
        keyUsageExt += "critical";
    }

    if ((certConfig.IsExtensionKeyUsageDigitalSigCorrect() && !isCA) ||
        (!certConfig.IsExtensionKeyUsageDigitalSigCorrect() && isCA))
    {
        if (!keyUsageExt.empty())
        {
            keyUsageExt += ",";
        }
        keyUsageExt += "digitalSignature";
    }

    if ((certConfig.IsExtensionKeyUsageKeyCertSignCorrect() && isCA) ||
        (!certConfig.IsExtensionKeyUsageKeyCertSignCorrect() && !isCA))
    {
        if (!keyUsageExt.empty())
        {
            keyUsageExt += ",";
        }
        keyUsageExt += "keyCertSign";
    }

    if ((certConfig.IsExtensionKeyUsageCRLSignCorrect() && isCA) || (!certConfig.IsExtensionKeyUsageCRLSignCorrect() && !isCA))
    {
        if (!keyUsageExt.empty())
        {
            keyUsageExt += ",";
        }
        keyUsageExt += "cRLSign";
    }

    // In test mode only: just add an extra extension flag to prevent empty extantion.
    if (certConfig.IsErrorTestCaseEnabled() && (keyUsageExt.empty() || (keyUsageExt.compare("critical") == 0)))
    {
        if (!keyUsageExt.empty())
        {
            keyUsageExt += ",";
        }
        keyUsageExt += "keyEncipherment";
    }

    return AddExtension(cert, NID_key_usage, keyUsageExt.c_str());
}

/** The key identifier field is derived from the public key using method (1) per RFC5280 (section 4.2.1.2):
 *
 *      (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
 *           value of the BIT STRING subjectPublicKey (excluding the tag,
 *           length, and number of unused bits).
 */
bool AddSubjectKeyId(X509 * cert, bool isSKIDLengthValid)
{
    bool res             = true;
    ASN1_BIT_STRING * pk = X509_get0_pubkey_bitstr(cert);
    unsigned char pkHash[EVP_MAX_MD_SIZE];
    unsigned int pkHashLen;
    std::unique_ptr<ASN1_STRING, void (*)(ASN1_STRING *)> pkHashOS(ASN1_STRING_type_new(V_ASN1_OCTET_STRING), &ASN1_STRING_free);

    if (!EVP_Digest(pk->data, static_cast<size_t>(pk->length), pkHash, &pkHashLen, EVP_sha1(), nullptr))
    {
        ReportOpenSSLErrorAndExit("EVP_Digest", res = false);
    }

    if (pkHashLen != kKeyIdentifierLength)
    {
        fprintf(stderr, "Unexpected hash length returned from EVP_Digest()\n");
        ExitNow(res = false);
    }

    if (!isSKIDLengthValid)
    {
        pkHashLen--;
    }

    if (!ASN1_STRING_set(pkHashOS.get(), pkHash, static_cast<int>(pkHashLen)))
    {
        ReportOpenSSLErrorAndExit("ASN1_STRING_set", res = false);
    }

    if (!X509_add1_ext_i2d(cert, NID_subject_key_identifier, pkHashOS.get(), 0, X509V3_ADD_APPEND))
    {
        ReportOpenSSLErrorAndExit("X509_add1_ext_i2d", res = false);
    }

exit:
    return res;
}

bool AddAuthorityKeyId(X509 * cert, X509 * caCert, bool isAKIDLengthValid)
{
    bool res = true;
    int isCritical;
    int index = 0;
    std::unique_ptr<AUTHORITY_KEYID, void (*)(AUTHORITY_KEYID *)> akid(AUTHORITY_KEYID_new(), &AUTHORITY_KEYID_free);

    akid->keyid = reinterpret_cast<ASN1_OCTET_STRING *>(X509_get_ext_d2i(caCert, NID_subject_key_identifier, &isCritical, &index));
    if (akid->keyid == nullptr)
    {
        ReportOpenSSLErrorAndExit("X509_get_ext_d2i", res = false);
    }

    if (!isAKIDLengthValid)
    {
        akid->keyid->length = 19;
    }

    if (!X509_add1_ext_i2d(cert, NID_authority_key_identifier, akid.get(), 0, X509V3_ADD_APPEND))
    {
        ReportOpenSSLErrorAndExit("X509_add1_ext_i2d", res = false);
    }

exit:
    return res;
}

} // namespace

bool ReadCert(const char * fileNameOrStr, std::unique_ptr<X509, void (*)(X509 *)> & cert)
{
    CertFormat origCertFmt;
    return ReadCert(fileNameOrStr, cert, origCertFmt);
}

bool ReadCert(const char * fileNameOrStr, std::unique_ptr<X509, void (*)(X509 *)> & cert, CertFormat & certFmt)
{
    bool res         = true;
    uint32_t certLen = 0;
    std::unique_ptr<uint8_t[]> certBuf;

    // If fileNameOrStr is a file name
    if (access(fileNameOrStr, R_OK) == 0)
    {
        res = ReadFileIntoMem(fileNameOrStr, nullptr, certLen);
        VerifyTrueOrExit(res);

        certBuf = std::make_unique<uint8_t[]>(certLen);

        res = ReadFileIntoMem(fileNameOrStr, certBuf.get(), certLen);
        VerifyTrueOrExit(res);

        certFmt = DetectCertFormat(certBuf.get(), certLen);
        if (certFmt == kCertFormat_Unknown)
        {
            fprintf(stderr, "Unrecognized Cert Format in File: %s\n", fileNameOrStr);
            return false;
        }
    }
    // Otherwise, treat fileNameOrStr as a pointer to the certificate string
    else
    {
        certLen = static_cast<uint32_t>(strlen(fileNameOrStr));

        certFmt = DetectCertFormat(reinterpret_cast<const uint8_t *>(fileNameOrStr), certLen);
        if (certFmt == kCertFormat_Unknown)
        {
            fprintf(stderr, "Unrecognized Cert Format in the Input Argument: %s\n", fileNameOrStr);
            return false;
        }

        certBuf = std::make_unique<uint8_t[]>(certLen);
        memcpy(certBuf.get(), fileNameOrStr, certLen);
    }

    if ((certFmt == kCertFormat_X509_Hex) || (certFmt == kCertFormat_Chip_Hex))
    {
        size_t len = chip::Encoding::HexToBytes(Uint8::to_char(certBuf.get()), certLen, certBuf.get(), certLen);
        VerifyOrReturnError(CanCastTo<uint32_t>(2 * len), false);
        VerifyOrReturnError(2 * len == certLen, false);
        certLen = static_cast<uint32_t>(len);
    }

    if (certFmt == kCertFormat_X509_PEM)
    {
        VerifyOrReturnError(chip::CanCastTo<int>(certLen), false);

        std::unique_ptr<BIO, void (*)(BIO *)> certBIO(
            BIO_new_mem_buf(static_cast<const void *>(certBuf.get()), static_cast<int>(certLen)), &BIO_free_all);

        cert.reset(PEM_read_bio_X509(certBIO.get(), nullptr, nullptr, nullptr));
        if (cert.get() == nullptr)
        {
            ReportOpenSSLErrorAndExit("PEM_read_bio_X509", res = false);
        }
    }
    else if ((certFmt == kCertFormat_X509_DER) || (certFmt == kCertFormat_X509_Hex))
    {
        VerifyOrReturnError(chip::CanCastTo<int>(certLen), false);

        const uint8_t * outCert = certBuf.get();

        cert.reset(d2i_X509(nullptr, &outCert, static_cast<int>(certLen)));
        if (cert.get() == nullptr)
        {
            ReportOpenSSLErrorAndExit("d2i_X509", res = false);
        }
    }
    // Otherwise, it is either CHIP TLV in raw, Base64, or hex encoded format.
    else
    {
        if (certFmt == kCertFormat_Chip_Base64)
        {
            res = Base64Decode(certBuf.get(), certLen, certBuf.get(), certLen, certLen);
            VerifyTrueOrExit(res);
        }

        auto x509CertBuf = std::make_unique<uint8_t[]>(kMaxDERCertLength);
        MutableByteSpan x509Cert(x509CertBuf.get(), kMaxDERCertLength);

        CHIP_ERROR err = ConvertChipCertToX509Cert(ByteSpan(certBuf.get(), certLen), x509Cert);
        if (err != CHIP_NO_ERROR)
        {
            fprintf(stderr, "Error converting certificate: %s\n", chip::ErrorStr(err));
            ExitNow(res = false);
        }

        const uint8_t * outCert = x509Cert.data();

        VerifyOrReturnError(chip::CanCastTo<int>(x509Cert.size()), false);

        cert.reset(d2i_X509(nullptr, &outCert, static_cast<int>(x509Cert.size())));
        if (cert.get() == nullptr)
        {
            ReportOpenSSLErrorAndExit("d2i_X509", res = false);
        }
    }

exit:
    return res;
}

bool ReadCertDER(const char * fileNameOrStr, MutableByteSpan & cert)
{
    bool res = true;
    std::unique_ptr<X509, void (*)(X509 *)> certX509(nullptr, &X509_free);

    VerifyOrReturnError(ReadCert(fileNameOrStr, certX509), false);

    uint8_t * certPtr = cert.data();
    int certLen       = i2d_X509(certX509.get(), &certPtr);
    if (certLen < 0)
    {
        ReportOpenSSLErrorAndExit("i2d_X509", res = false);
    }

    VerifyOrReturnError(chip::CanCastTo<size_t>(certLen), false);
    cert.reduce_size(static_cast<size_t>(certLen));

exit:
    return res;
}

bool X509ToChipCert(X509 * cert, MutableByteSpan & chipCert)
{
    bool res = true;
    CHIP_ERROR err;
    uint8_t * derCert = nullptr;
    int derCertLen;

    derCertLen = i2d_X509(cert, &derCert);
    if (derCertLen < 0)
    {
        ReportOpenSSLErrorAndExit("i2d_X509", res = false);
    }

    VerifyOrExit(chip::CanCastTo<size_t>(derCertLen), res = false);

    err = ConvertX509CertToChipCert(ByteSpan(derCert, static_cast<size_t>(derCertLen)), chipCert);
    if (err != CHIP_NO_ERROR)
    {
        fprintf(stderr, "ConvertX509CertToChipCert() failed\n%s\n", chip::ErrorStr(err));
        ExitNow(res = false);
    }

exit:
    OPENSSL_free(derCert);
    return res;
}

bool LoadChipCert(const char * fileNameOrStr, bool isTrused, ChipCertificateSet & certSet, MutableByteSpan & chipCert)
{
    bool res = true;
    CHIP_ERROR err;
    BitFlags<CertDecodeFlags> decodeFlags;
    std::unique_ptr<X509, void (*)(X509 *)> cert(nullptr, &X509_free);

    res = ReadCert(fileNameOrStr, cert);
    VerifyTrueOrExit(res);

    res = X509ToChipCert(cert.get(), chipCert);
    VerifyTrueOrExit(res);

    if (isTrused)
    {
        decodeFlags.Set(CertDecodeFlags::kIsTrustAnchor);
    }
    else
    {
        decodeFlags.Set(CertDecodeFlags::kGenerateTBSHash);
    }

    err = certSet.LoadCert(chipCert, decodeFlags);
    if (err != CHIP_NO_ERROR)
    {
        fprintf(stderr, "Error reading %s\n%s\n", fileNameOrStr, chip::ErrorStr(err));
        ExitNow(res = false);
    }

exit:
    return res;
}

bool WriteCert(const char * fileName, X509 * cert, CertFormat certFmt)
{
    bool res          = true;
    FILE * file       = nullptr;
    uint8_t * derCert = nullptr;

    VerifyOrReturnError(cert != nullptr, false);
    VerifyOrReturnError(certFmt != kCertFormat_Unknown, false);

    if (IsChipCertFormat(certFmt))
    {
        uint8_t chipCertBuf[kMaxCHIPCertLength];
        MutableByteSpan chipCert(chipCertBuf);

        VerifyOrReturnError(X509ToChipCert(cert, chipCert), false);

        return WriteChipCert(fileName, chipCert, certFmt);
    }

    if (certFmt == kCertFormat_X509_Hex)
    {
        int derCertLen = i2d_X509(cert, &derCert);
        if (derCertLen < 0)
        {
            ReportOpenSSLErrorAndExit("i2d_X509", res = false);
        }

        VerifyOrExit(CanCastTo<uint32_t>(derCertLen), res = false);
        VerifyOrExit(WriteDataIntoFile(fileName, derCert, static_cast<uint32_t>(derCertLen), kDataFormat_Hex), res = false);
        ExitNow(res = true);
    }

    VerifyOrExit(OpenFile(fileName, file, true), res = false);

    if (certFmt == kCertFormat_X509_PEM)
    {
        if (PEM_write_X509(file, cert) == 0)
        {
            ReportOpenSSLErrorAndExit("PEM_write_X509", res = false);
        }
    }
    else if (certFmt == kCertFormat_X509_DER)
    {
        if (i2d_X509_fp(file, cert) == 0)
        {
            ReportOpenSSLErrorAndExit("i2d_X509_fp", res = false);
        }
    }
    else
    {
        fprintf(stderr, "Unsupported certificate format\n");
        ExitNow(res = false);
    }

exit:
    OPENSSL_free(derCert);
    CloseFile(file);
    return res;
}

bool WriteChipCert(const char * fileName, const ByteSpan & chipCert, CertFormat certFmt)
{
    DataFormat dataFormat = kDataFormat_Unknown;

    VerifyOrReturnError(IsChipCertFormat(certFmt), false);

    if (certFmt == kCertFormat_Chip_Raw)
        dataFormat = kDataFormat_Raw;
    else if (certFmt == kCertFormat_Chip_Base64)
        dataFormat = kDataFormat_Base64;
    else
        dataFormat = kDataFormat_Hex;

    return WriteDataIntoFile(fileName, chipCert.data(), static_cast<uint32_t>(chipCert.size()), dataFormat);
}

bool MakeCert(CertType certType, const ToolChipDN * subjectDN, X509 * caCert, EVP_PKEY * caKey, const struct tm & validFrom,
              uint32_t validDays, int pathLen, const FutureExtensionWithNID * futureExts, uint8_t futureExtsCount, X509 * newCert,
              EVP_PKEY * newKey, CertStructConfig & certConfig)
{
    bool res  = true;
    bool isCA = (certType == CertType::kRoot || certType == CertType::kICA);

    VerifyOrExit(subjectDN != nullptr, res = false);
    VerifyOrExit(caCert != nullptr, res = false);
    VerifyOrExit(caKey != nullptr, res = false);
    VerifyOrExit(newCert != nullptr, res = false);
    VerifyOrExit(newKey != nullptr, res = false);

    // Set the certificate version (must be 2, a.k.a. v3).
    if (!X509_set_version(newCert, certConfig.GetCertVersion()))
    {
        ReportOpenSSLErrorAndExit("X509_set_version", res = false);
    }

    // Generate a serial number for the cert.
    if (certConfig.IsSerialNumberPresent())
    {
        res = SetCertSerialNumber(newCert, (certType == CertType::kNetworkIdentity ? 1 : kUseRandomSerialNumber));
        VerifyTrueOrExit(res);
    }

    // Set the issuer name for the certificate. In the case of a self-signed cert, this will be
    // the new cert's subject name.
    if (certConfig.IsIssuerPresent())
    {
        if (certType == CertType::kRoot)
        {
            res = subjectDN->SetCertIssuerDN(newCert);
            VerifyTrueOrExit(res);
        }
        else
        {
            if (!X509_set_issuer_name(newCert, X509_get_subject_name(caCert)))
            {
                ReportOpenSSLErrorAndExit("X509_set_issuer_name", res = false);
            }
        }
    }

    // Set the certificate validity time.
    res = SetValidityTime(newCert, validFrom, validDays, certConfig);
    VerifyTrueOrExit(res);

    // Set the certificate's public key.
    if (!X509_set_pubkey(newCert, newKey))
    {
        ReportOpenSSLErrorAndExit("X509_set_pubkey", res = false);
    }

    // Injuct error into public key value.
    if (certConfig.IsPublicKeyError())
    {
        ASN1_BIT_STRING * pk = X509_get0_pubkey_bitstr(newCert);
        pk->data[CertStructConfig::kPublicKeyErrorByte] ^= 0xFF;
    }

    // Set certificate subject DN.
    if (certConfig.IsSubjectPresent())
    {
        res = subjectDN->SetCertSubjectDN(newCert);
        VerifyTrueOrExit(res);
    }

    // Add basic constraints certificate extensions.
    if (certConfig.IsExtensionBasicPathLenPresent() || !certConfig.IsExtensionBasicCAPresent())
    {
        pathLen = certConfig.GetExtensionBasicPathLenValue(certType);
    }
    res = SetBasicConstraintsExtension(newCert, isCA, pathLen, certConfig);
    VerifyTrueOrExit(res);

    // Add key usage certificate extensions.
    res = SetKeyUsageExtension(newCert, isCA, certConfig);
    VerifyTrueOrExit(res);

    // Add extended key usage certificate extensions.
    if (!certConfig.IsExtensionExtendedKeyUsageMissing())
    {
        if (certType == CertType::kNode)
        {
            res = AddExtension(newCert, NID_ext_key_usage, "critical,clientAuth,serverAuth");
            VerifyTrueOrExit(res);
        }
        else if (certType == CertType::kFirmwareSigning)
        {
            res = AddExtension(newCert, NID_ext_key_usage, "critical,codeSigning");
            VerifyTrueOrExit(res);
        }
        else if (certType == CertType::kNetworkIdentity)
        {
            res = AddExtension(newCert, NID_ext_key_usage, "critical,clientAuth,serverAuth");
            VerifyTrueOrExit(res);
        }
    }

    // Add a subject key id extension for the certificate.
    if (certType != CertType::kNetworkIdentity && certConfig.IsExtensionSKIDPresent())
    {
        res = AddSubjectKeyId(newCert, certConfig.IsExtensionSKIDLengthValid());
        VerifyTrueOrExit(res);
    }

    // Add the authority key id extension from the signing certificate. For self-signed cert's this will
    // be the same as new cert's subject key id extension.
    if (certType != CertType::kNetworkIdentity && certConfig.IsExtensionAKIDPresent())
    {
        if ((certType == CertType::kRoot) && !certConfig.IsExtensionSKIDPresent())
        {
            res = AddSubjectKeyId(newCert, certConfig.IsExtensionSKIDLengthValid());
            VerifyTrueOrExit(res);
            res = AddAuthorityKeyId(newCert, newCert, certConfig.IsExtensionAKIDLengthValid());
            VerifyTrueOrExit(res);

            // Remove that temporary added subject key id
            int authKeyIdExtLoc = X509_get_ext_by_NID(newCert, NID_subject_key_identifier, -1);
            if (authKeyIdExtLoc != -1)
            {
                if (X509_delete_ext(newCert, authKeyIdExtLoc) == nullptr)
                {
                    ReportOpenSSLErrorAndExit("X509_delete_ext", res = false);
                }
            }
        }
        else
        {
            res = AddAuthorityKeyId(newCert, caCert, certConfig.IsExtensionAKIDLengthValid());
            VerifyTrueOrExit(res);
        }
    }
    for (uint8_t i = 0; i < futureExtsCount; i++)
    {
        res = AddExtension(newCert, futureExts[i].nid, futureExts[i].info);
        VerifyTrueOrExit(res);
    }

    // Sign the new certificate.
    if (!X509_sign(newCert, caKey, certConfig.GetSignatureAlgorithmDER()))
    {
        ReportOpenSSLErrorAndExit("X509_sign", res = false);
    }

    // Injuct error into signature value.
    if (certConfig.IsSignatureError())
    {
        const ASN1_BIT_STRING * sig = nullptr;
        X509_get0_signature(&sig, nullptr, newCert);
        sig->data[20] ^= 0xFF;
    }

exit:
    return res;
}

CHIP_ERROR MakeCertTLV(CertType certType, const ToolChipDN * subjectDN, X509 * caCert, EVP_PKEY * caKey,
                       const struct tm & validFrom, uint32_t validDays, int pathLen, const FutureExtensionWithNID * futureExts,
                       uint8_t futureExtsCount, X509 * x509Cert, EVP_PKEY * newKey, CertStructConfig & certConfig,
                       MutableByteSpan & chipCert)
{
    TLVWriter writer;
    TLVType containerType;
    TLVType containerType2;
    TLVType containerType3;
    uint8_t subjectPubkey[chip::Crypto::CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES] = { 0 };
    uint8_t issuerPubkey[chip::Crypto::CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES]  = { 0 };
    uint8_t keyid[chip::Crypto::kSHA1_Hash_Length]                         = { 0 };
    bool isCA;

    VerifyOrReturnError(subjectDN != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(caCert != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(caKey != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(x509Cert != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(newKey != nullptr, CHIP_ERROR_INVALID_ARGUMENT);

    isCA = (certType == CertType::kICA || certType == CertType::kRoot);

    // If error testing is enabled, let field inclusion be controlled that way,
    // otherwise use compact identity format for Network (Client) Identities.
    bool useCompactIdentityFormat = (!certConfig.IsErrorTestCaseEnabled() && certType == CertType::kNetworkIdentity);

    uint8_t * p = subjectPubkey;
    VerifyOrReturnError(i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(newKey), &p) == chip::Crypto::CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES,
                        CHIP_ERROR_INVALID_ARGUMENT);

    p = issuerPubkey;
    VerifyOrReturnError(i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(caKey), &p) == chip::Crypto::CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES,
                        CHIP_ERROR_INVALID_ARGUMENT);

    writer.Init(chipCert);

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

    if (!useCompactIdentityFormat)
    {
        // serial number
        if (certConfig.IsSerialNumberPresent())
        {
            ASN1_INTEGER * asn1Integer = X509_get_serialNumber(x509Cert);
            uint64_t serialNumber;
            uint8_t serialNumberArray[sizeof(uint64_t)];
            VerifyOrReturnError(1 == ASN1_INTEGER_get_uint64(&serialNumber, asn1Integer), CHIP_ERROR_INVALID_ARGUMENT);
            Encoding::BigEndian::Put64(serialNumberArray, serialNumber);
            ReturnErrorOnFailure(writer.PutBytes(ContextTag(kTag_SerialNumber), serialNumberArray, sizeof(serialNumberArray)));
        }

        // signature algorithm
        ReturnErrorOnFailure(writer.Put(ContextTag(kTag_SignatureAlgorithm), certConfig.GetSignatureAlgorithmTLVEnum()));

        // issuer Name
        if (certConfig.IsIssuerPresent())
        {
            if (certType == CertType::kRoot)
            {
                ReturnErrorOnFailure(subjectDN->EncodeToTLV(writer, ContextTag(kTag_Issuer)));
            }
            else
            {
                uint8_t caChipCertBuf[kMaxCHIPCertLength];
                MutableByteSpan caChipCert(caChipCertBuf);
                VerifyOrReturnError(true == X509ToChipCert(caCert, caChipCert), CHIP_ERROR_INVALID_ARGUMENT);
                ChipDN issuerDN;
                ReturnErrorOnFailure(ExtractSubjectDNFromChipCert(caChipCert, issuerDN));
                ReturnErrorOnFailure(issuerDN.EncodeToTLV(writer, ContextTag(kTag_Issuer)));
            }
        }

        // validity
        uint32_t validFromChipEpoch;
        uint32_t validToChipEpoch;

        VerifyOrReturnError(
            true ==
                CalendarToChipEpochTime(static_cast<uint16_t>(validFrom.tm_year + 1900), static_cast<uint8_t>(validFrom.tm_mon + 1),
                                        static_cast<uint8_t>(validFrom.tm_mday), static_cast<uint8_t>(validFrom.tm_hour),
                                        static_cast<uint8_t>(validFrom.tm_min), static_cast<uint8_t>(validFrom.tm_sec),
                                        validFromChipEpoch),
            CHIP_ERROR_INVALID_ARGUMENT);
        if (validDays == kCertValidDays_NoWellDefinedExpiration)
        {
            validToChipEpoch = 0;
        }
        else
        {
            VerifyOrReturnError(CanCastTo<uint32_t>(validFromChipEpoch + validDays * kSecondsPerDay - 1),
                                CHIP_ERROR_INVALID_ARGUMENT);
            validToChipEpoch = validFromChipEpoch + validDays * kSecondsPerDay - 1;
        }
        if (!certConfig.IsValidityCorrect())
        {
            uint32_t validTemp = validFromChipEpoch;
            validFromChipEpoch = validToChipEpoch;
            validToChipEpoch   = validTemp;
        }
        if (certConfig.IsValidityNotBeforePresent())
        {
            ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotBefore), validFromChipEpoch));
        }
        if (certConfig.IsValidityNotAfterPresent())
        {
            ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotAfter), validToChipEpoch));
        }

        // subject Name
        if (certConfig.IsSubjectPresent())
        {
            ReturnErrorOnFailure(subjectDN->EncodeToTLV(writer, ContextTag(kTag_Subject)));
        }

        // public key algorithm
        ReturnErrorOnFailure(writer.Put(ContextTag(kTag_PublicKeyAlgorithm), GetOIDEnum(kOID_PubKeyAlgo_ECPublicKey)));

        // public key curve Id
        uint8_t ecCurveEnum = certConfig.IsSigCurveWrong() ? 0x02 : GetOIDEnum(kOID_EllipticCurve_prime256v1);
        ReturnErrorOnFailure(writer.Put(ContextTag(kTag_EllipticCurveIdentifier), ecCurveEnum));
    }

    // public key
    if (certConfig.IsPublicKeyError())
    {
        subjectPubkey[CertStructConfig::kPublicKeyErrorByte] ^= 0xFF;
    }
    ReturnErrorOnFailure(
        writer.PutBytes(ContextTag(kTag_EllipticCurvePublicKey), subjectPubkey, chip::Crypto::CHIP_CRYPTO_PUBLIC_KEY_SIZE_BYTES));

    // extensions
    if (!useCompactIdentityFormat)
    {
        ReturnErrorOnFailure(writer.StartContainer(ContextTag(kTag_Extensions), kTLVType_List, containerType2));
        {
            if (isCA)
            {
                // basic constraints
                if (certConfig.IsExtensionBasicPresent())
                {
                    ReturnErrorOnFailure(
                        writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, containerType3));
                    if (certConfig.IsExtensionBasicCAPresent())
                    {
                        ReturnErrorOnFailure(writer.PutBoolean(ContextTag(kTag_BasicConstraints_IsCA),
                                                               certConfig.IsExtensionBasicCACorrect() ? isCA : !isCA));
                    }
                    if (pathLen != kPathLength_NotSpecified)
                    {
                        ReturnErrorOnFailure(
                            writer.Put(ContextTag(kTag_BasicConstraints_PathLenConstraint), static_cast<uint8_t>(pathLen)));
                    }
                    ReturnErrorOnFailure(writer.EndContainer(containerType3));
                }

                // key usage
                if (certConfig.IsExtensionKeyUsagePresent())
                {
                    BitFlags<KeyUsageFlags> keyUsage;
                    if (!certConfig.IsExtensionKeyUsageDigitalSigCorrect())
                    {
                        keyUsage.Set(KeyUsageFlags::kDigitalSignature);
                    }
                    if (certConfig.IsExtensionKeyUsageKeyCertSignCorrect())
                    {
                        keyUsage.Set(KeyUsageFlags::kKeyCertSign);
                    }
                    if (certConfig.IsExtensionKeyUsageCRLSignCorrect())
                    {
                        keyUsage.Set(KeyUsageFlags::kCRLSign);
                    }
                    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_KeyUsage), keyUsage.Raw()));
                }
            }
            else
            {
                // basic constraints
                if (certConfig.IsExtensionBasicPresent())
                {
                    ReturnErrorOnFailure(
                        writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, containerType3));
                    if (certConfig.IsExtensionBasicCAPresent())
                    {
                        ReturnErrorOnFailure(writer.PutBoolean(ContextTag(kTag_BasicConstraints_IsCA),
                                                               certConfig.IsExtensionBasicCACorrect() ? isCA : !isCA));
                    }
                    ReturnErrorOnFailure(writer.EndContainer(containerType3));
                }

                // key usage
                if (certConfig.IsExtensionKeyUsagePresent())
                {
                    BitFlags<KeyUsageFlags> keyUsage;
                    if (certConfig.IsExtensionKeyUsageDigitalSigCorrect())
                    {
                        keyUsage.Set(KeyUsageFlags::kDigitalSignature);
                    }
                    if (!certConfig.IsExtensionKeyUsageKeyCertSignCorrect())
                    {
                        keyUsage.Set(KeyUsageFlags::kKeyCertSign);
                    }
                    if (!certConfig.IsExtensionKeyUsageCRLSignCorrect())
                    {
                        keyUsage.Set(KeyUsageFlags::kCRLSign);
                    }
                    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_KeyUsage), keyUsage));
                }

                // extended key usage
                if (!certConfig.IsExtensionExtendedKeyUsageMissing() && (certType == CertType::kNode))
                {
                    ReturnErrorOnFailure(writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Array, containerType3));
                    if (certType == CertType::kNode)
                    {
                        ReturnErrorOnFailure(writer.Put(AnonymousTag(), GetOIDEnum(kOID_KeyPurpose_ClientAuth)));
                        ReturnErrorOnFailure(writer.Put(AnonymousTag(), GetOIDEnum(kOID_KeyPurpose_ServerAuth)));
                    }
                    else if (certType == CertType::kFirmwareSigning)
                    {
                        ReturnErrorOnFailure(writer.Put(AnonymousTag(), GetOIDEnum(kOID_KeyPurpose_CodeSigning)));
                    }
                    ReturnErrorOnFailure(writer.EndContainer(containerType3));
                }
            }

            // subject key identifier
            if (certConfig.IsExtensionSKIDPresent())
            {
                ReturnErrorOnFailure(Crypto::Hash_SHA1(subjectPubkey, sizeof(subjectPubkey), keyid));
                size_t keyIdLen = certConfig.IsExtensionSKIDLengthValid() ? sizeof(keyid) : sizeof(keyid) - 1;
                ReturnErrorOnFailure(writer.Put(ContextTag(kTag_SubjectKeyIdentifier), ByteSpan(keyid, keyIdLen)));
            }

            // authority key identifier
            if (certConfig.IsExtensionAKIDPresent())
            {
                ReturnErrorOnFailure(Crypto::Hash_SHA1(issuerPubkey, sizeof(issuerPubkey), keyid));
                size_t keyIdLen = certConfig.IsExtensionAKIDLengthValid() ? sizeof(keyid) : sizeof(keyid) - 1;
                ReturnErrorOnFailure(writer.Put(ContextTag(kTag_AuthorityKeyIdentifier), ByteSpan(keyid, keyIdLen)));
            }

            for (uint8_t i = 0; i < futureExtsCount; i++)
            {
                ReturnErrorOnFailure(
                    writer.Put(ContextTag(kTag_FutureExtension),
                               ByteSpan(reinterpret_cast<const uint8_t *>(futureExts[i].info), strlen(futureExts[i].info))));
            }
        }
        ReturnErrorOnFailure(writer.EndContainer(containerType2));
    }

    // signature
    const ASN1_BIT_STRING * asn1Signature = nullptr;
    X509_get0_signature(&asn1Signature, nullptr, x509Cert);

    uint8_t signatureRawBuf[chip::Crypto::kP256_ECDSA_Signature_Length_Raw];
    MutableByteSpan signatureRaw(signatureRawBuf);
    ReturnErrorOnFailure(chip::Crypto::EcdsaAsn1SignatureToRaw(
        chip::Crypto::kP256_FE_Length, ByteSpan(asn1Signature->data, static_cast<size_t>(asn1Signature->length)), signatureRaw));

    ReturnErrorOnFailure(writer.Put(ContextTag(kTag_ECDSASignature), signatureRaw));

    ReturnErrorOnFailure(writer.EndContainer(containerType));

    ReturnErrorOnFailure(writer.Finalize());

    chipCert.reduce_size(writer.GetLengthWritten());

    return CHIP_NO_ERROR;
}

bool ResignCert(X509 * cert, X509 * caCert, EVP_PKEY * caKey)
{
    bool res            = true;
    int authKeyIdExtLoc = -1;

    res = SetCertSerialNumber(cert);
    VerifyTrueOrExit(res);

    if (!X509_set_issuer_name(cert, X509_get_subject_name(caCert)))
    {
        ReportOpenSSLErrorAndExit("X509_set_issuer_name", res = false);
    }

    // Remove any existing authority key id
    authKeyIdExtLoc = X509_get_ext_by_NID(cert, NID_authority_key_identifier, -1);
    if (authKeyIdExtLoc != -1)
    {
        if (X509_delete_ext(cert, authKeyIdExtLoc) == nullptr)
        {
            ReportOpenSSLErrorAndExit("X509_delete_ext", res = false);
        }
    }

    res = AddAuthorityKeyId(cert, caCert, true);
    VerifyTrueOrExit(res);

    if (!X509_sign(cert, caKey, EVP_sha256()))
    {
        ReportOpenSSLErrorAndExit("X509_sign", res = false);
    }

exit:
    return res;
}

bool MakeAttCert(AttCertType attCertType, const char * subjectCN, uint16_t subjectVID, uint16_t subjectPID,
                 bool encodeVIDandPIDasCN, X509 * caCert, EVP_PKEY * caKey, const struct tm & validFrom, uint32_t validDays,
                 X509 * newCert, EVP_PKEY * newKey, CertStructConfig & certConfig, X509_EXTENSION * cdpExt)
{
    bool res     = true;
    uint16_t vid = certConfig.IsSubjectVIDMismatch() ? static_cast<uint16_t>(subjectVID + 1) : subjectVID;
    uint16_t pid = certConfig.IsSubjectPIDMismatch() ? static_cast<uint16_t>(subjectPID + 1) : subjectPID;
    bool isCA    = (attCertType != kAttCertType_DAC);

    VerifyOrReturnError(subjectCN != nullptr, false);
    VerifyOrReturnError(caCert != nullptr, false);
    VerifyOrReturnError(caKey != nullptr, false);
    VerifyOrReturnError(newCert != nullptr, false);
    VerifyOrReturnError(newKey != nullptr, false);

    if (!X509_set_version(newCert, certConfig.GetCertVersion()))
    {
        ReportOpenSSLErrorAndExit("X509_set_version", res = false);
    }

    // Generate a serial number for the cert.
    res = SetCertSerialNumber(newCert);
    VerifyTrueOrExit(res);

    // Set the certificate validity time.
    res = SetValidityTime(newCert, validFrom, validDays, certConfig);
    VerifyTrueOrExit(res);

    // Set the certificate's public key.
    if (!X509_set_pubkey(newCert, newKey))
    {
        ReportOpenSSLErrorAndExit("X509_set_pubkey", res = false);
    }

    // Encode Common Name (CN) Attribute.
    {
        char cnAttrStr[chip::Crypto::kMax_CommonNameAttr_Length];
        size_t cnAttrStrLen = 0;
        if (subjectCN != nullptr)
        {
            VerifyOrReturnError(strlen(subjectCN) <= sizeof(cnAttrStr), false);
            memcpy(cnAttrStr, subjectCN, strlen(subjectCN));
            cnAttrStrLen += strlen(subjectCN);
        }

        if (encodeVIDandPIDasCN)
        {
            if (subjectVID != VendorId::NotSpecified)
            {
                // Add space to separate from the previous string.
                if (cnAttrStrLen > 0)
                {
                    VerifyOrReturnError((cnAttrStrLen + 1) <= sizeof(cnAttrStr), false);
                    cnAttrStr[cnAttrStrLen] = ' ';
                    cnAttrStrLen++;
                }

                VerifyOrReturnError((cnAttrStrLen + strlen(chip::Crypto::kVIDPrefixForCNEncoding) +
                                     chip::Crypto::kVIDandPIDHexLength) <= sizeof(cnAttrStr),
                                    false);

                memcpy(&cnAttrStr[cnAttrStrLen], chip::Crypto::kVIDPrefixForCNEncoding,
                       strlen(chip::Crypto::kVIDPrefixForCNEncoding));
                cnAttrStrLen += strlen(chip::Crypto::kVIDPrefixForCNEncoding);

                VerifyOrReturnError(Encoding::Uint16ToHex(vid, &cnAttrStr[cnAttrStrLen], chip::Crypto::kVIDandPIDHexLength,
                                                          Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR,
                                    false);
                cnAttrStrLen += chip::Crypto::kVIDandPIDHexLength;
            }

            if (subjectPID != 0)
            {
                // Add space to separate from the previous string.
                if (cnAttrStrLen > 0)
                {
                    VerifyOrReturnError((cnAttrStrLen + 1) <= sizeof(cnAttrStr), false);
                    cnAttrStr[cnAttrStrLen++] = ' ';
                }

                VerifyOrReturnError((cnAttrStrLen + strlen(chip::Crypto::kPIDPrefixForCNEncoding) +
                                     chip::Crypto::kVIDandPIDHexLength) <= sizeof(cnAttrStr),
                                    false);

                memcpy(&cnAttrStr[cnAttrStrLen], chip::Crypto::kPIDPrefixForCNEncoding,
                       strlen(chip::Crypto::kPIDPrefixForCNEncoding));
                cnAttrStrLen += strlen(chip::Crypto::kPIDPrefixForCNEncoding);

                VerifyOrReturnError(Encoding::Uint16ToHex(pid, &cnAttrStr[cnAttrStrLen], chip::Crypto::kVIDandPIDHexLength,
                                                          Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR,
                                    false);
                cnAttrStrLen += chip::Crypto::kVIDandPIDHexLength;
            }
        }

        // Add common name attribute to the certificate subject DN.
        if (!X509_NAME_add_entry_by_NID(X509_get_subject_name(newCert), NID_commonName, MBSTRING_UTF8,
                                        reinterpret_cast<uint8_t *>(cnAttrStr), static_cast<int>(cnAttrStrLen), -1, 0))
        {
            ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false);
        }
    }

    if (!encodeVIDandPIDasCN)
    {
        // Add VID attribute to the certificate subject DN.
        if (subjectVID != VendorId::NotSpecified)
        {
            char chipAttrStr[chip::Crypto::kVIDandPIDHexLength];
            VerifyOrReturnError(Encoding::Uint16ToHex(vid, chipAttrStr, chip::Crypto::kVIDandPIDHexLength,
                                                      Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR,
                                false);

            if (!X509_NAME_add_entry_by_NID(X509_get_subject_name(newCert), gNIDChipAttAttrVID, MBSTRING_UTF8,
                                            reinterpret_cast<unsigned char *>(chipAttrStr), sizeof(chipAttrStr), -1, 0))
            {
                ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false);
            }
        }

        // Add PID attribute to the certificate subject DN.
        if (subjectPID != 0)
        {
            char chipAttrStr[chip::Crypto::kVIDandPIDHexLength];
            VerifyOrReturnError(Encoding::Uint16ToHex(pid, chipAttrStr, chip::Crypto::kVIDandPIDHexLength,
                                                      Encoding::HexFlags::kUppercase) == CHIP_NO_ERROR,
                                false);

            if (!X509_NAME_add_entry_by_NID(X509_get_subject_name(newCert), gNIDChipAttAttrPID, MBSTRING_UTF8,
                                            reinterpret_cast<unsigned char *>(chipAttrStr), sizeof(chipAttrStr), -1, 0))
            {
                ReportOpenSSLErrorAndExit("X509_NAME_add_entry_by_NID", res = false);
            }
        }
    }

    // Set the issuer name for the certificate. In the case of a self-signed cert, this will be
    // the new cert's subject name.
    if (!X509_set_issuer_name(newCert, X509_get_subject_name(caCert)))
    {
        ReportOpenSSLErrorAndExit("X509_set_issuer_name", res = false);
    }

    // Add basic constraints certificate extensions.
    res = SetBasicConstraintsExtension(newCert, isCA, certConfig.GetExtensionBasicPathLenValue(attCertType), certConfig);
    VerifyTrueOrExit(res);

    // Add key usage certificate extensions.
    res = SetKeyUsageExtension(newCert, isCA, certConfig);
    VerifyTrueOrExit(res);

    if (certConfig.IsExtensionSKIDPresent())
    {
        // Add a subject key id extension for the certificate.
        res = AddSubjectKeyId(newCert, certConfig.IsExtensionSKIDLengthValid());
        VerifyTrueOrExit(res);
    }

    if (certConfig.IsExtensionAKIDPresent())
    {
        // Add the authority key id extension from the signing certificate.
        res = AddAuthorityKeyId(newCert, caCert, certConfig.IsExtensionAKIDLengthValid());
        VerifyTrueOrExit(res);
    }

    if (certConfig.IsExtensionExtendedKeyUsagePresent())
    {
        // Add optional Extended Key Usage extentsion.
        res = AddExtension(newCert, NID_ext_key_usage, "critical,clientAuth,serverAuth");
        VerifyTrueOrExit(res);
    }

    if (certConfig.IsExtensionAuthorityInfoAccessPresent())
    {
        // Add optional Authority Informational Access extentsion.
        res = AddExtension(newCert, NID_info_access, "OCSP;URI:http://ocsp.example.com/");
        VerifyTrueOrExit(res);
    }

    if (certConfig.IsExtensionSubjectAltNamePresent())
    {
        // Add optional Subject Alternative Name extentsion.
        res = AddExtension(newCert, NID_subject_alt_name, "DNS:test.com");
        VerifyTrueOrExit(res);
    }

    if (cdpExt != nullptr)
    {
        int result = X509_add_ext(newCert, cdpExt, -1);
        VerifyTrueOrExit(result == 1);
    }

    if (certConfig.IsExtensionCDPPresent())
    {
        // Add second CDP extension.
        res = AddExtension(newCert, NID_crl_distribution_points, "URI:http://example.com/test_crl.pem");
        VerifyTrueOrExit(res);
    }

    // Sign the new certificate.
    if (!X509_sign(newCert, caKey, certConfig.GetSignatureAlgorithmDER()))
    {
        ReportOpenSSLErrorAndExit("X509_sign", res = false);
    }

exit:
    return res;
}
