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

#define __STDC_FORMAT_MACROS

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

#include <string>

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_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))
        {
            Encoding::Uint64ToHex(rdn[i].mChipVal, valueStr, sizeof(valueStr), Encoding::HexFlags::kUppercaseAndNullTerminate);
        }
        else if (IsChip32bitDNAttr(rdn[i].mAttrOID))
        {
            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 {

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 derRawPrefix[]  = { 0x30, 0x82 };
    static const char * derHexPrefix     = "30820";
    static const char * pemMarker        = "-----BEGIN CERTIFICATE-----";

    VerifyOrReturnError(cert != nullptr, kCertFormat_Unknown);

    if ((certLen > sizeof(chipRawPrefix)) && (memcmp(cert, chipRawPrefix, sizeof(chipRawPrefix)) == 0))
    {
        return kCertFormat_Chip_Raw;
    }

    if ((certLen > strlen(chipHexPrefix)) && (memcmp(cert, chipHexPrefix, strlen(chipHexPrefix)) == 0))
    {
        return kCertFormat_Chip_Hex;
    }

    if ((certLen > strlen(chipB64Prefix)) && (memcmp(cert, chipB64Prefix, strlen(chipB64Prefix)) == 0))
    {
        return kCertFormat_Chip_Base64;
    }

    if ((certLen > sizeof(derRawPrefix)) && (memcmp(cert, derRawPrefix, sizeof(derRawPrefix)) == 0))
    {
        return kCertFormat_X509_DER;
    }

    if ((certLen > strlen(derHexPrefix)) && (memcmp(cert, derHexPrefix, strlen(derHexPrefix)) == 0))
    {
        return kCertFormat_X509_Hex;
    }

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

    return kCertFormat_Unknown;
}

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

    // 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.
    rnd &= 0x7FFFFFFFFFFFFFFF;

    // Store the serial number as an ASN1 integer value within the certificate.
    if (ASN1_INTEGER_set_uint64(snInt, rnd) == 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::unique_ptr<uint8_t[]>(new 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::unique_ptr<uint8_t[]>(new 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);
        }

        std::unique_ptr<uint8_t[]> x509CertBuf(new 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);
    }

    VerifyOrReturnError(chip::CanCastTo<size_t>(derCertLen), 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(uint8_t 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 != kCertType_Node);

    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);
        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 == kCertType_Root)
        {
            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 == kCertType_Node)
        {
            res = AddExtension(newCert, NID_ext_key_usage, "critical,clientAuth,serverAuth");
            VerifyTrueOrExit(res);
        }
        else if (certType == kCertType_FirmwareSigning)
        {
            res = AddExtension(newCert, NID_ext_key_usage, "critical,codeSigning");
            VerifyTrueOrExit(res);
        }
    }

    // Add a subject key id extension for the certificate.
    if (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 (certConfig.IsExtensionAKIDPresent())
    {
        if ((certType == kCertType_Root) && !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(uint8_t 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 == kCertType_ICA || certType == kCertType_Root);

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

    // 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 == kCertType_Root)
        {
            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
    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));
                }
                // TODO
                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 == kCertType_Node))
            {
                ReturnErrorOnFailure(writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Array, containerType3));
                if (certType == kCertType_Node)
                {
                    ReturnErrorOnFailure(writer.Put(AnonymousTag(), GetOIDEnum(kOID_KeyPurpose_ClientAuth)));
                    ReturnErrorOnFailure(writer.Put(AnonymousTag(), GetOIDEnum(kOID_KeyPurpose_ServerAuth)));
                }
                else if (certType == kCertType_FirmwareSigning)
                {
                    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)
{
    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);
    }

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

exit:
    return res;
}
