/*
 *
 *    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.
 *
 */

#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 {

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::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(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;
}
