blob: 06ccd93693880fedb7b6e7195cae3693d6b7ed67 [file] [log] [blame]
/*
*
* 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 defines the public API symbols, constants, and interfaces
* for the 'chip-cert' command line tool.
*
* The 'chip-cert' tool is a command line interface (CLI) utility
* used, primarily, for generating and manipulating CHIP
* certificate and private key material.
*
*/
#pragma once
#include <ctype.h>
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
#include <memory>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/x509v3.h>
#include <CHIPVersion.h>
#include <credentials/CHIPCert.h>
#include <credentials/CHIPCertificateSet.h>
#include <crypto/CHIPCryptoPAL.h>
#include <lib/asn1/ASN1.h>
#include <lib/core/CHIPConfig.h>
#include <lib/core/CHIPCore.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/Base64.h>
#include <lib/support/CHIPArgParser.hpp>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ErrorStr.h>
#include <lib/support/SafeInt.h>
#include <lib/support/TimeUtils.h>
using chip::ASN1::OID;
#ifndef CHIP_CONFIG_INTERNAL_FLAG_GENERATE_DA_TEST_CASES
#define CHIP_CONFIG_INTERNAL_FLAG_GENERATE_DA_TEST_CASES CHIP_CONFIG_TEST
#endif
#ifndef CHIP_CONFIG_INTERNAL_FLAG_GENERATE_OP_CERT_TEST_CASES
#define CHIP_CONFIG_INTERNAL_FLAG_GENERATE_OP_CERT_TEST_CASES CHIP_CONFIG_TEST
#endif
#define COPYRIGHT_STRING \
"Copyright (c) 2021-2022 Project CHIP Authors. " \
"Copyright (c) 2019 Google LLC. " \
"Copyright (c) 2013-2017 Nest Labs, Inc. " \
"All rights reserved.\n"
enum
{
kCertValidDays_Undefined = 0,
kCertValidDays_NoWellDefinedExpiration = UINT32_MAX,
kPathLength_NotSpecified = -1,
};
enum CertFormat
{
kCertFormat_Unknown = 0,
kCertFormat_X509_DER,
kCertFormat_X509_PEM,
kCertFormat_X509_Hex,
kCertFormat_Chip_Raw,
kCertFormat_Chip_Base64,
kCertFormat_Chip_Hex,
kCertFormat_Default = kCertFormat_Chip_Base64,
};
enum KeyFormat
{
kKeyFormat_Unknown = 0,
kKeyFormat_X509_DER,
kKeyFormat_X509_PEM,
kKeyFormat_X509_Hex,
kKeyFormat_X509_Pubkey_PEM,
kKeyFormat_Chip_Raw,
kKeyFormat_Chip_Base64,
kKeyFormat_Chip_Hex,
kKeyFormat_Chip_Pubkey_Raw,
kKeyFormat_Chip_Pubkey_Base64,
kKeyFormat_Chip_Pubkey_Hex,
kKeyFormat_Default = kKeyFormat_Chip_Base64,
};
enum DataFormat
{
kDataFormat_Unknown = 0,
kDataFormat_Raw,
kDataFormat_Hex,
kDataFormat_Base64,
};
extern bool IsChipCertFormat(CertFormat certFormat);
extern bool IsX509PrivateKeyFormat(KeyFormat keyFormat);
extern bool IsChipPrivateKeyFormat(KeyFormat keyFormat);
extern bool IsPrivateKeyFormat(KeyFormat keyFormat);
extern bool IsChipPublicKeyFormat(KeyFormat keyFormat);
extern bool IsPublicKeyFormat(KeyFormat keyFormat);
enum AttCertType
{
kAttCertType_NotSpecified = 0, /**< The attestation certificate type has not been specified. */
kAttCertType_PAA, /**< Product Attestation Authority (PAA) Certificate. */
kAttCertType_PAI, /**< Product Attestation Intermediate (PAI) Certificate. */
kAttCertType_DAC, /**< Device Attestation Certificate (DAC). */
};
struct FutureExtensionWithNID
{
int nid;
const char * info;
};
/** Certificate Error Flags
*
* By default all methods (if none of the class setters were used) return valid
* certificate configuration parameter as described in the spec.
* These parameters can be modified to inject errors into certificate structure.
*/
class CertStructConfig
{
public:
void EnableErrorTestCase() { mEnabled = true; }
void SetCertVersionWrong() { mFlags.Set(CertErrorFlags::kCertVersion); }
void SetSigAlgoWrong() { mFlags.Set(CertErrorFlags::kSigAlgo); }
void SetSubjectVIDMismatch() { mFlags.Set(CertErrorFlags::kSubjectVIDMismatch); }
void SetSubjectPIDMismatch() { mFlags.Set(CertErrorFlags::kSubjectPIDMismatch); }
void SetSigCurveWrong() { mFlags.Set(CertErrorFlags::kSigCurve); }
void SetPublicKeyError() { mFlags.Set(CertErrorFlags::kPublicKey); }
void SetExtensionBasicMissing() { mFlags.Set(CertErrorFlags::kExtBasicMissing); }
void SetExtensionBasicCriticalMissing() { mFlags.Set(CertErrorFlags::kExtBasicCriticalMissing); }
void SetExtensionBasicCriticalWrong() { mFlags.Set(CertErrorFlags::kExtBasicCriticalWrong); }
void SetExtensionBasicCAMissing() { mFlags.Set(CertErrorFlags::kExtBasicCAMissing); }
void SetExtensionBasicCAWrong() { mFlags.Set(CertErrorFlags::kExtBasicCAWrong); }
void SetExtensionBasicPathLenPresenceWrong() { mFlags.Set(CertErrorFlags::kExtBasicPathLenWrong); }
void SetExtensionBasicPathLen0() { mFlags.Set(CertErrorFlags::kExtBasicPathLen0); }
void SetExtensionBasicPathLen1() { mFlags.Set(CertErrorFlags::kExtBasicPathLen1); }
void SetExtensionBasicPathLen2() { mFlags.Set(CertErrorFlags::kExtBasicPathLen2); }
void SetExtensionKeyUsageMissing() { mFlags.Set(CertErrorFlags::kExtKeyUsageMissing); }
void SetExtensionKeyUsageCriticalMissing() { mFlags.Set(CertErrorFlags::kExtKeyUsageCriticalMissing); }
void SetExtensionKeyUsageCriticalWrong() { mFlags.Set(CertErrorFlags::kExtKeyUsageCriticalWrong); }
void SetExtensionKeyUsageDigitalSigWrong() { mFlags.Set(CertErrorFlags::kExtKeyUsageDigSig); }
void SetExtensionKeyUsageKeyCertSignWrong() { mFlags.Set(CertErrorFlags::kExtKeyUsageKeyCertSign); }
void SetExtensionKeyUsageCRLSignWrong() { mFlags.Set(CertErrorFlags::kExtKeyUsageCRLSign); }
void SetExtensionAKIDMissing() { mFlags.Set(CertErrorFlags::kExtAKIDMissing); }
void SetExtensionSKIDMissing() { mFlags.Set(CertErrorFlags::kExtSKIDMissing); }
void SetExtensionExtendedKeyUsagePresent() { mFlags.Set(CertErrorFlags::kExtExtendedKeyUsage); }
void SetExtensionAuthorityInfoAccessPresent() { mFlags.Set(CertErrorFlags::kExtAuthorityInfoAccess); }
void SetExtensionSubjectAltNamePresent() { mFlags.Set(CertErrorFlags::kExtSubjectAltName); }
void SetSignatureError() { mFlags.Set(CertErrorFlags::kSignature); }
void SetCertOversized() { mFlags.Set(CertErrorFlags::kCertOversized); }
void SetSerialNumberMissing() { mFlags.Set(CertErrorFlags::kSerialNumberMissing); }
void SetIssuerMissing() { mFlags.Set(CertErrorFlags::kIssuerMissing); }
void SetValidityNotBeforeMissing() { mFlags.Set(CertErrorFlags::kValidityNotBeforeMissing); }
void SetValidityNotAfterMissing() { mFlags.Set(CertErrorFlags::kValidityNotAfterMissing); }
void SetValidityWrong() { mFlags.Set(CertErrorFlags::kValidityWrong); }
void SetSubjectMissing() { mFlags.Set(CertErrorFlags::kSubjectMissing); }
void SetSubjectNodeIdMissing() { mFlags.Set(CertErrorFlags::kSubjectNodeIdMissing); }
void SetSubjectNodeIdInvalid() { mFlags.Set(CertErrorFlags::kSubjectNodeIdInvalid); }
void SetSubjectNodeIdTwice() { mFlags.Set(CertErrorFlags::kSubjectNodeIdTwice); }
void SetSubjectFabricIdMissing() { mFlags.Set(CertErrorFlags::kSubjectFabricIdMissing); }
void SetSubjectFabricIdInvalid() { mFlags.Set(CertErrorFlags::kSubjectFabricIdInvalid); }
void SetSubjectFabricIdTwice() { mFlags.Set(CertErrorFlags::kSubjectFabricIdTwice); }
void SetSubjectFabricIdMismatch() { mFlags.Set(CertErrorFlags::kSubjectFabricIdMismatch); }
void SetSubjectCATInvalid() { mFlags.Set(CertErrorFlags::kSubjectCATInvalid); }
void SetExtensionExtendedKeyUsageMissing() { mFlags.Set(CertErrorFlags::kExtExtendedKeyUsageMissing); }
bool IsErrorTestCaseEnabled() { return mEnabled; }
int GetCertVersion() { return (mEnabled && mFlags.Has(CertErrorFlags::kCertVersion)) ? 1 : 2; }
const EVP_MD * GetSignatureAlgorithmDER()
{
return (mEnabled && mFlags.Has(CertErrorFlags::kSigAlgo)) ? EVP_sha1() : EVP_sha256();
}
uint8_t GetSignatureAlgorithmTLVEnum()
{
return (mEnabled && mFlags.Has(CertErrorFlags::kSigAlgo)) ? 0x02
: GetOIDEnum(chip::ASN1::
kOID_SigAlgo_ECDSAWithSHA256);
}
bool IsSubjectVIDMismatch() { return (mEnabled && mFlags.Has(CertErrorFlags::kSubjectVIDMismatch)); }
bool IsSubjectPIDMismatch() { return (mEnabled && mFlags.Has(CertErrorFlags::kSubjectPIDMismatch)); }
bool IsSigCurveWrong() { return (mEnabled && mFlags.Has(CertErrorFlags::kSigCurve)); }
bool IsPublicKeyError() { return (mEnabled && mFlags.Has(CertErrorFlags::kPublicKey)); }
bool IsExtensionBasicPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtBasicMissing)); }
bool IsExtensionBasicCriticalPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtBasicCriticalMissing)); }
bool IsExtensionBasicCritical() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtBasicCriticalWrong)); }
bool IsExtensionBasicCAPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtBasicCAMissing)); }
bool IsExtensionBasicCACorrect() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtBasicCAWrong)); }
bool IsExtensionBasicPathLenPresent(AttCertType & attCertType)
{
bool normallyPresent = (attCertType != kAttCertType_DAC);
bool testCaseWrong = (mEnabled && mFlags.Has(CertErrorFlags::kExtBasicPathLenWrong));
return (normallyPresent ^ testCaseWrong);
}
int GetExtensionBasicPathLenValue(AttCertType & attCertType)
{
if (mFlags.Has(CertErrorFlags::kExtBasicPathLen0))
{
return 0;
}
if (mFlags.Has(CertErrorFlags::kExtBasicPathLen1))
{
return 1;
}
if (mFlags.Has(CertErrorFlags::kExtBasicPathLen2))
{
return 2;
}
if (attCertType == kAttCertType_PAA)
{
return 1;
}
if (attCertType == kAttCertType_PAI)
{
return 0;
}
return 0;
}
bool IsExtensionBasicPathLenPresent()
{
return (mEnabled &&
(mFlags.Has(CertErrorFlags::kExtBasicPathLenWrong) || mFlags.Has(CertErrorFlags::kExtBasicPathLen0) ||
mFlags.Has(CertErrorFlags::kExtBasicPathLen1) || mFlags.Has(CertErrorFlags::kExtBasicPathLen2)));
}
int GetExtensionBasicPathLenValue(uint8_t & certType)
{
if (mFlags.Has(CertErrorFlags::kExtBasicPathLen0))
{
return 0;
}
if (mFlags.Has(CertErrorFlags::kExtBasicPathLen1))
{
return 1;
}
if (mFlags.Has(CertErrorFlags::kExtBasicPathLen2))
{
return 2;
}
if (mFlags.Has(CertErrorFlags::kExtBasicPathLenWrong))
{
if (certType == chip::Credentials::kCertType_Node)
{
return 2;
}
if (certType == chip::Credentials::kCertType_ICA)
{
return 1;
}
if (certType == chip::Credentials::kCertType_Root)
{
return 0;
}
}
return 0;
}
bool IsExtensionKeyUsagePresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtKeyUsageMissing)); }
bool IsExtensionKeyUsageCriticalPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtKeyUsageCriticalMissing)); }
bool IsExtensionKeyUsageCritical() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtKeyUsageCriticalWrong)); }
bool IsExtensionKeyUsageDigitalSigCorrect() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtKeyUsageDigSig)); }
bool IsExtensionKeyUsageKeyCertSignCorrect() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtKeyUsageKeyCertSign)); }
bool IsExtensionKeyUsageCRLSignCorrect() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtKeyUsageCRLSign)); }
bool IsExtensionAKIDPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtAKIDMissing)); }
bool IsExtensionSKIDPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kExtSKIDMissing)); }
bool IsExtensionExtendedKeyUsagePresent() { return (mEnabled && mFlags.Has(CertErrorFlags::kExtExtendedKeyUsage)); }
bool IsExtensionAuthorityInfoAccessPresent() { return (mEnabled && mFlags.Has(CertErrorFlags::kExtAuthorityInfoAccess)); }
bool IsExtensionSubjectAltNamePresent() { return (mEnabled && mFlags.Has(CertErrorFlags::kExtSubjectAltName)); }
bool IsSignatureError() { return (mEnabled && mFlags.Has(CertErrorFlags::kSignature)); }
bool IsCertOversized() { return (mEnabled && mFlags.Has(CertErrorFlags::kCertOversized)); }
uint32_t GetExtraCertLength() { return IsCertOversized() ? kExtraBufferLengthForOvesizedCert : 0; }
bool IsSerialNumberPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kSerialNumberMissing)); }
bool IsIssuerPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kIssuerMissing)); }
bool IsValidityNotBeforePresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kValidityNotBeforeMissing)); }
bool IsValidityNotAfterPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kValidityNotAfterMissing)); }
bool IsValidityCorrect() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kValidityWrong)); }
bool IsSubjectPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kSubjectMissing)); }
bool IsSubjectNodeIdPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kSubjectNodeIdMissing)); }
bool IsSubjectNodeIdValid() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kSubjectNodeIdInvalid)); }
bool IsSubjectNodeIdRepeatsTwice() { return (mEnabled && mFlags.Has(CertErrorFlags::kSubjectNodeIdTwice)); }
bool IsSubjectFabricIdPresent() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kSubjectFabricIdMissing)); }
bool IsSubjectFabricIdValid() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kSubjectFabricIdInvalid)); }
bool IsSubjectFabricIdRepeatsTwice() { return (mEnabled && mFlags.Has(CertErrorFlags::kSubjectFabricIdTwice)); }
bool IsSubjectFabricIdMismatch() { return (mEnabled && mFlags.Has(CertErrorFlags::kSubjectFabricIdMismatch)); }
bool IsSubjectCATValid() { return (!mEnabled || !mFlags.Has(CertErrorFlags::kSubjectCATInvalid)); }
bool IsExtensionExtendedKeyUsageMissing() { return (mEnabled && mFlags.Has(CertErrorFlags::kExtExtendedKeyUsageMissing)); }
static constexpr uint8_t kPublicKeyErrorByte = 20;
private:
enum class CertErrorFlags : uint64_t
{
kCertVersion = 0x0000000000000001,
kSigAlgo = 0x0000000000000002,
kSubjectVIDMismatch = 0x0000000000000004, // DA specific
kSubjectPIDMismatch = 0x0000000000000008, // DA specific
kSigCurve = 0x0000000000000010,
kPublicKey = 0x0000000000000020,
kExtBasicMissing = 0x0000000000000040,
kExtBasicCriticalMissing = 0x0000000000000080,
kExtBasicCriticalWrong = 0x0000000000000100,
kExtBasicCAMissing = 0x0000000000000200,
kExtBasicCAWrong = 0x0000000000000400,
kExtBasicPathLenWrong = 0x0000000000000800,
kExtBasicPathLen0 = 0x0000000000001000,
kExtBasicPathLen1 = 0x0000000000002000,
kExtBasicPathLen2 = 0x0000000000004000,
kExtKeyUsageMissing = 0x0000000000008000,
kExtKeyUsageCriticalMissing = 0x0000000000010000,
kExtKeyUsageCriticalWrong = 0x0000000000020000,
kExtKeyUsageDigSig = 0x0000000000040000,
kExtKeyUsageKeyCertSign = 0x0000000000080000,
kExtKeyUsageCRLSign = 0x0000000000100000,
kExtAKIDMissing = 0x0000000000200000,
kExtSKIDMissing = 0x0000000000400000,
kExtExtendedKeyUsage = 0x0000000000800000, // DA specific
kExtAuthorityInfoAccess = 0x0000000001000000, // DA specific
kExtSubjectAltName = 0x0000000002000000, // DA specific
kSignature = 0x0000000004000000,
// Op Cert Specific Flags:
kCertOversized = 0x0000000100000000,
kSerialNumberMissing = 0x0000000200000000,
kIssuerMissing = 0x0000000400000000,
kValidityNotBeforeMissing = 0x0000000800000000,
kValidityNotAfterMissing = 0x0000001000000000,
kValidityWrong = 0x0000002000000000,
kSubjectMissing = 0x0000004000000000,
kSubjectNodeIdMissing = 0x0000008000000000,
kSubjectNodeIdInvalid = 0x0000010000000000,
kSubjectNodeIdTwice = 0x0000020000000000,
kSubjectFabricIdMissing = 0x0000040000000000,
kSubjectFabricIdInvalid = 0x0000080000000000,
kSubjectFabricIdTwice = 0x0000100000000000,
kSubjectFabricIdMismatch = 0x0000200000000000,
kSubjectCATInvalid = 0x0000400000000000,
kExtExtendedKeyUsageMissing = 0x0000800000000000,
};
static constexpr uint32_t kExtraBufferLengthForOvesizedCert = 300;
bool mEnabled = false;
chip::BitFlags<CertErrorFlags> mFlags;
};
class ToolChipDN : public chip::Credentials::ChipDN
{
public:
bool SetCertName(X509_NAME * name) const;
bool SetCertSubjectDN(X509 * cert) const { return SetCertName(X509_get_subject_name(cert)); };
bool SetCertIssuerDN(X509 * cert) const { return SetCertName(X509_get_issuer_name(cert)); };
bool HasAttr(chip::ASN1::OID oid) const;
void PrintDN(FILE * file, const char * name) const;
};
extern bool Cmd_GenCD(int argc, char * argv[]);
extern bool Cmd_GenCert(int argc, char * argv[]);
extern bool Cmd_ConvertCert(int argc, char * argv[]);
extern bool Cmd_ConvertKey(int argc, char * argv[]);
extern bool Cmd_ResignCert(int argc, char * argv[]);
extern bool Cmd_ValidateAttCert(int argc, char * argv[]);
extern bool Cmd_ValidateCert(int argc, char * argv[]);
extern bool Cmd_PrintCert(int argc, char * argv[]);
extern bool Cmd_PrintCD(int argc, char * argv[]);
extern bool Cmd_GenAttCert(int argc, char * argv[]);
extern bool ReadCert(const char * fileNameOrStr, X509 * cert);
extern bool ReadCert(const char * fileNameOrStr, X509 * cert, CertFormat & origCertFmt);
extern bool ReadCertDER(const char * fileNameOrStr, chip::MutableByteSpan & cert);
extern bool LoadChipCert(const char * fileNameOrStr, bool isTrused, chip::Credentials::ChipCertificateSet & certSet,
chip::MutableByteSpan & chipCert);
extern bool WriteCert(const char * fileName, X509 * cert, CertFormat certFmt);
extern bool WriteChipCert(const char * fileName, const chip::ByteSpan & cert, CertFormat certFmt);
extern 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);
extern CHIP_ERROR MakeCertChipTLV(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, chip::MutableByteSpan & chipCert);
extern bool ResignCert(X509 * cert, X509 * caCert, EVP_PKEY * caKey);
extern 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);
extern bool GenerateKeyPair(EVP_PKEY * key);
extern bool GenerateKeyPair_Secp256k1(EVP_PKEY * key);
extern bool ReadKey(const char * fileNameOrStr, std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY *)> & key,
bool ignorErrorIfUnsupportedCurve = false);
extern bool WriteKey(const char * fileName, EVP_PKEY * key, KeyFormat keyFmt);
extern bool SerializeKeyPair(EVP_PKEY * key, chip::Crypto::P256SerializedKeypair & serializedKeypair);
extern bool X509ToChipCert(X509 * cert, chip::MutableByteSpan & chipCert);
extern bool InitOpenSSL();
extern bool Base64Encode(const uint8_t * inData, uint32_t inDataLen, uint8_t * outBuf, uint32_t outBufSize, uint32_t & outDataLen);
extern bool Base64Decode(const uint8_t * inData, uint32_t inDataLen, uint8_t * outBuf, uint32_t outBufSize, uint32_t & outDataLen);
extern bool IsBase64String(const char * str, uint32_t strLen);
extern bool ContainsPEMMarker(const char * marker, const uint8_t * data, uint32_t dataLen);
extern bool ParseDateTime(const char * str, struct tm & date);
extern bool ReadFileIntoMem(const char * fileName, uint8_t * data, uint32_t & dataLen);
extern bool WriteDataIntoFile(const char * fileName, const uint8_t * data, size_t dataLen, DataFormat dataFmt);
extern bool OpenFile(const char * fileName, FILE *& file, bool toWrite = false);
extern void CloseFile(FILE *& file);
extern int gNIDChipNodeId;
extern int gNIDChipFirmwareSigningId;
extern int gNIDChipICAId;
extern int gNIDChipRootId;
extern int gNIDChipFabricId;
extern int gNIDChipCASEAuthenticatedTag;
extern int gNIDChipCurveP256;
extern int gNIDTestCurveSecp256k1;
extern int gNIDChipAttAttrVID;
extern int gNIDChipAttAttrPID;
/**
* @def VerifyTrueOrExit(aStatus)
*
* @brief
* Checks for the specified status, which is expected to be 'true',
* and branches to the local label 'exit' if the status is 'false'.
*
* @param[in] aStatus A boolean status to be evaluated.
*/
#define VerifyTrueOrExit(aStatus) nlEXPECT(aStatus, exit)
/**
* @def ReportOpenSSLErrorAndExit(aFunct, ACTION)
*
* @brief
* Prints error, which was result of execusion of the specified OpenSSL
* function, then performs specified actions and branches to the local label 'exit'.
*
* @param[in] aFunct Name of an OpenSSL function that reported an error.
*/
#define ReportOpenSSLErrorAndExit(aFunct, ...) \
do \
{ \
fprintf(stderr, "OpenSSL %s() failed\n", aFunct); \
ERR_print_errors_fp(stderr); \
__VA_ARGS__; \
goto exit; \
} while (0)