blob: 09a92229c71298c9f3f3d27ac8c163779bc764f1 [file] [log] [blame]
Marri Devender Raocd30c492019-06-12 01:40:17 -05001#include "config.h"
2
Marri Devender Rao6ceec402019-02-01 03:15:19 -06003#include "certificate.hpp"
4
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +02005#include "certs_manager.hpp"
6
Nan Zhou014be0b2021-12-28 18:00:14 -08007#include <openssl/asn1.h>
Marri Devender Rao6ceec402019-02-01 03:15:19 -06008#include <openssl/bio.h>
Nan Zhou014be0b2021-12-28 18:00:14 -08009#include <openssl/buffer.h>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060010#include <openssl/err.h>
11#include <openssl/evp.h>
Nan Zhou014be0b2021-12-28 18:00:14 -080012#include <openssl/obj_mac.h>
13#include <openssl/objects.h>
14#include <openssl/opensslv.h>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060015#include <openssl/pem.h>
Nan Zhou014be0b2021-12-28 18:00:14 -080016#include <openssl/ssl3.h>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060017#include <openssl/x509v3.h>
18
Nan Zhou014be0b2021-12-28 18:00:14 -080019#include <cstdint>
20#include <cstdio>
21#include <cstdlib>
22#include <ctime>
23#include <exception>
24#include <filesystem>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060025#include <fstream>
Nan Zhou014be0b2021-12-28 18:00:14 -080026#include <map>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060027#include <phosphor-logging/elog-errors.hpp>
Nan Zhou014be0b2021-12-28 18:00:14 -080028#include <phosphor-logging/elog.hpp>
29#include <phosphor-logging/log.hpp>
30#include <utility>
31#include <vector>
32#include <watch.hpp>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050033#include <xyz/openbmc_project/Certs/error.hpp>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060034#include <xyz/openbmc_project/Common/error.hpp>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050035
Nan Zhoue1289ad2021-12-28 11:02:56 -080036namespace phosphor::certs
Marri Devender Rao6ceec402019-02-01 03:15:19 -060037{
Nan Zhoucf06ccd2021-12-28 16:25:45 -080038
39namespace
40{
41namespace fs = std::filesystem;
42using ::phosphor::logging::elog;
43using ::phosphor::logging::entry;
44using ::phosphor::logging::level;
45using ::phosphor::logging::log;
46using ::phosphor::logging::report;
47using InvalidCertificateError =
48 ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
49using ::phosphor::logging::xyz::openbmc_project::Certs::InvalidCertificate;
50using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
51
Marri Devender Rao6ceec402019-02-01 03:15:19 -060052// RAII support for openSSL functions.
Nan Zhoucf06ccd2021-12-28 16:25:45 -080053using BIOMemPtr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
54using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>;
55using X509StoreCtxPtr =
Marri Devender Rao6ceec402019-02-01 03:15:19 -060056 std::unique_ptr<X509_STORE_CTX, decltype(&::X509_STORE_CTX_free)>;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080057using ASN1TimePtr = std::unique_ptr<ASN1_TIME, decltype(&ASN1_STRING_free)>;
58using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
59using BufMemPtr = std::unique_ptr<BUF_MEM, decltype(&::BUF_MEM_free)>;
Marri Devender Rao6ceec402019-02-01 03:15:19 -060060
61// Trust chain related errors.`
62#define TRUST_CHAIN_ERR(errnum) \
63 ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) || \
64 (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) || \
65 (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) || \
Nan Zhou63540132021-11-25 15:47:52 -080066 (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) || \
Marri Devender Rao6ceec402019-02-01 03:15:19 -060067 (errnum == X509_V_ERR_CERT_UNTRUSTED) || \
68 (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE))
69
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -060070// Refer to schema 2018.3
71// http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for
72// supported KeyUsage types in redfish
73// Refer to
74// https://github.com/openssl/openssl/blob/master/include/openssl/x509v3.h for
75// key usage bit fields
76std::map<uint8_t, std::string> keyUsageToRfStr = {
77 {KU_DIGITAL_SIGNATURE, "DigitalSignature"},
78 {KU_NON_REPUDIATION, "NonRepudiation"},
79 {KU_KEY_ENCIPHERMENT, "KeyEncipherment"},
80 {KU_DATA_ENCIPHERMENT, "DataEncipherment"},
81 {KU_KEY_AGREEMENT, "KeyAgreement"},
82 {KU_KEY_CERT_SIGN, "KeyCertSign"},
83 {KU_CRL_SIGN, "CRLSigning"},
84 {KU_ENCIPHER_ONLY, "EncipherOnly"},
85 {KU_DECIPHER_ONLY, "DecipherOnly"}};
86
87// Refer to schema 2018.3
88// http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for
89// supported Extended KeyUsage types in redfish
90std::map<uint8_t, std::string> extendedKeyUsageToRfStr = {
91 {NID_server_auth, "ServerAuthentication"},
92 {NID_client_auth, "ClientAuthentication"},
93 {NID_email_protect, "EmailProtection"},
94 {NID_OCSP_sign, "OCSPSigning"},
95 {NID_ad_timeStamping, "Timestamping"},
96 {NID_code_sign, "CodeSigning"}};
Nan Zhoucf06ccd2021-12-28 16:25:45 -080097} // namespace
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -060098
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010099std::string Certificate::generateCertId(const std::string& certPath)
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200100{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800101 const internal::X509Ptr cert = loadCert(certPath);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100102 unsigned long subjectNameHash = X509_subject_name_hash(cert.get());
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100103 unsigned long issuerSerialHash = X509_issuer_and_serial_hash(cert.get());
104 static constexpr auto CERT_ID_LENGTH = 17;
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100105 char idBuff[CERT_ID_LENGTH];
106
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100107 snprintf(idBuff, CERT_ID_LENGTH, "%08lx%08lx", subjectNameHash,
108 issuerSerialHash);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100109
110 return std::string(idBuff);
111}
112
113std::string
114 Certificate::generateUniqueFilePath(const std::string& directoryPath)
115{
Nan Zhoucfb58022021-12-28 11:02:26 -0800116 char* filePath = tempnam(directoryPath.c_str(), nullptr);
117 if (filePath == nullptr)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100118 {
119 log<level::ERR>(
Nan Zhoubf3cf752021-12-28 11:02:07 -0800120 "Error occurred while creating random certificate file path",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100121 entry("DIR=%s", directoryPath.c_str()));
122 elog<InternalFailure>();
123 }
124 std::string filePathStr(filePath);
125 free(filePath);
126 return filePathStr;
127}
128
129std::string Certificate::generateAuthCertFileX509Path(
130 const std::string& certSrcFilePath, const std::string& certDstDirPath)
131{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800132 const internal::X509Ptr cert = loadCert(certSrcFilePath);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200133 unsigned long hash = X509_subject_name_hash(cert.get());
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100134 static constexpr auto CERT_HASH_LENGTH = 9;
135 char hashBuf[CERT_HASH_LENGTH];
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200136
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100137 snprintf(hashBuf, CERT_HASH_LENGTH, "%08lx", hash);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200138
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100139 const std::string certHash(hashBuf);
Nan Zhou718eef32021-12-28 11:03:30 -0800140 for (size_t i = 0; i < maxNumAuthorityCertificates; ++i)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100141 {
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100142 const std::string certDstFileX509Path =
143 certDstDirPath + "/" + certHash + "." + std::to_string(i);
144 if (!fs::exists(certDstFileX509Path))
145 {
146 return certDstFileX509Path;
147 }
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100148 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200149
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100150 log<level::ERR>("Authority certificate x509 file path already used",
151 entry("DIR=%s", certDstDirPath.c_str()));
152 elog<InternalFailure>();
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100153}
154
155std::string
156 Certificate::generateAuthCertFilePath(const std::string& certSrcFilePath)
157{
158 // If there is a certificate file path (which means certificate replacement
159 // is doing) use it (do not create new one)
160 if (!certFilePath.empty())
161 {
162 return certFilePath;
163 }
164 // If source certificate file is located in the certificates directory use
165 // it (do not create new one)
166 else if (fs::path(certSrcFilePath).parent_path().string() ==
167 certInstallPath)
168 {
169 return certSrcFilePath;
170 }
171 // Otherwise generate new file name/path
172 else
173 {
174 return generateUniqueFilePath(certInstallPath);
175 }
176}
177
178std::string
179 Certificate::generateCertFilePath(const std::string& certSrcFilePath)
180{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800181 if (certType == CertificateType::Authority)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100182 {
183 return generateAuthCertFilePath(certSrcFilePath);
184 }
185 else
186 {
187 return certInstallPath;
188 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200189}
190
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600191Certificate::Certificate(sdbusplus::bus::bus& bus, const std::string& objPath,
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800192 CertificateType type, const std::string& installPath,
193 const std::string& uploadPath, Watch* watch,
194 Manager& parent) :
195 internal::CertificateInterface(bus, objPath.c_str(), true),
196 objectPath(objPath), certType(type), certInstallPath(installPath),
197 certWatch(watch), manager(parent)
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600198{
199 auto installHelper = [this](const auto& filePath) {
200 if (!compareKeys(filePath))
201 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800202 elog<InvalidCertificateError>(InvalidCertificate::REASON(
203 "Private key does not match the Certificate"));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600204 };
205 };
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800206 typeFuncMap[CertificateType::Server] = installHelper;
207 typeFuncMap[CertificateType::Client] = installHelper;
208 typeFuncMap[CertificateType::Authority] = [](const std::string&) {};
Marri Devender Raocd30c492019-06-12 01:40:17 -0500209
210 auto appendPrivateKey = [this](const std::string& filePath) {
211 checkAndAppendPrivateKey(filePath);
212 };
213
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800214 appendKeyMap[CertificateType::Server] = appendPrivateKey;
215 appendKeyMap[CertificateType::Client] = appendPrivateKey;
216 appendKeyMap[CertificateType::Authority] = [](const std::string&) {};
Marri Devender Raocd30c492019-06-12 01:40:17 -0500217
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100218 // Generate certificate file path
219 certFilePath = generateCertFilePath(uploadPath);
220
Marri Devender Raocd30c492019-06-12 01:40:17 -0500221 // install the certificate
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100222 install(uploadPath);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500223
Marri Devender Raoedd11312019-02-27 08:45:10 -0600224 this->emit_object_added();
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600225}
226
227Certificate::~Certificate()
228{
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100229 if (!fs::remove(certFilePath))
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600230 {
231 log<level::INFO>("Certificate file not found!",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100232 entry("PATH=%s", certFilePath.c_str()));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600233 }
234}
235
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500236void Certificate::replace(const std::string filePath)
237{
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100238 manager.replaceCertificate(this, filePath);
Marri Devender Rao13bf74e2019-03-26 01:52:17 -0500239}
240
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100241void Certificate::install(const std::string& certSrcFilePath)
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600242{
243 log<level::INFO>("Certificate install ",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100244 entry("FILEPATH=%s", certSrcFilePath.c_str()));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600245 auto errCode = X509_V_OK;
246
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500247 // stop watch for user initiated certificate install
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800248 if (certWatch != nullptr)
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500249 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800250 certWatch->stopWatch();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500251 }
252
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600253 // Verify the certificate file
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100254 fs::path file(certSrcFilePath);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600255 if (!fs::exists(file))
256 {
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100257 log<level::ERR>("File is Missing",
258 entry("FILE=%s", certSrcFilePath.c_str()));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600259 elog<InternalFailure>();
260 }
261
262 try
263 {
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100264 if (fs::file_size(certSrcFilePath) == 0)
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600265 {
266 // file is empty
267 log<level::ERR>("File is empty",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100268 entry("FILE=%s", certSrcFilePath.c_str()));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800269 elog<InvalidCertificateError>(
270 InvalidCertificate::REASON("File is empty"));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600271 }
272 }
273 catch (const fs::filesystem_error& e)
274 {
275 // Log Error message
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100276 log<level::ERR>(e.what(), entry("FILE=%s", certSrcFilePath.c_str()));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600277 elog<InternalFailure>();
278 }
279
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600280 // Create an empty X509_STORE structure for certificate validation.
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800281 X509StorePtr x509Store(X509_STORE_new(), &X509_STORE_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600282 if (!x509Store)
283 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800284 log<level::ERR>("Error occurred during X509_STORE_new call");
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600285 elog<InternalFailure>();
286 }
287
288 OpenSSL_add_all_algorithms();
289
290 // ADD Certificate Lookup method.
Patrick Williams83e6eab2021-12-05 06:32:24 -0600291 // lookup will be cleaned up automatically when the holding Store goes away.
292 auto lookup = X509_STORE_add_lookup(x509Store.get(), X509_LOOKUP_file());
293
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600294 if (!lookup)
295 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800296 log<level::ERR>("Error occurred during X509_STORE_add_lookup call");
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600297 elog<InternalFailure>();
298 }
299 // Load Certificate file.
Patrick Williams83e6eab2021-12-05 06:32:24 -0600300 errCode = X509_LOOKUP_load_file(lookup, certSrcFilePath.c_str(),
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600301 X509_FILETYPE_PEM);
302 if (errCode != 1)
303 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800304 log<level::ERR>("Error occurred during X509_LOOKUP_load_file call",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100305 entry("FILE=%s", certSrcFilePath.c_str()));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800306 elog<InvalidCertificateError>(
307 InvalidCertificate::REASON("Invalid certificate file format"));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600308 }
309
Nan Zhoubf3cf752021-12-28 11:02:07 -0800310 // Load Certificate file into the X509 structure.
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800311 internal::X509Ptr cert = loadCert(certSrcFilePath);
312 X509StoreCtxPtr storeCtx(X509_STORE_CTX_new(), ::X509_STORE_CTX_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600313 if (!storeCtx)
314 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800315 log<level::ERR>("Error occurred during X509_STORE_CTX_new call",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100316 entry("FILE=%s", certSrcFilePath.c_str()));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600317 elog<InternalFailure>();
318 }
319
Nan Zhoucfb58022021-12-28 11:02:26 -0800320 errCode = X509_STORE_CTX_init(storeCtx.get(), x509Store.get(), cert.get(),
321 nullptr);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600322 if (errCode != 1)
323 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800324 log<level::ERR>("Error occurred during X509_STORE_CTX_init call",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100325 entry("FILE=%s", certSrcFilePath.c_str()));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600326 elog<InternalFailure>();
327 }
328
329 // Set time to current time.
330 auto locTime = time(nullptr);
331
332 X509_STORE_CTX_set_time(storeCtx.get(), X509_V_FLAG_USE_CHECK_TIME,
333 locTime);
334
335 errCode = X509_verify_cert(storeCtx.get());
336 if (errCode == 1)
337 {
338 errCode = X509_V_OK;
339 }
340 else if (errCode == 0)
341 {
342 errCode = X509_STORE_CTX_get_error(storeCtx.get());
Marri Devender Rao2e8c3a52019-08-09 01:26:35 -0500343 log<level::INFO>(
Nan Zhoubf3cf752021-12-28 11:02:07 -0800344 "Error occurred during X509_verify_cert call, checking for known "
Marri Devender Rao2e8c3a52019-08-09 01:26:35 -0500345 "error",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100346 entry("FILE=%s", certSrcFilePath.c_str()),
347 entry("ERRCODE=%d", errCode),
Marri Devender Rao2e8c3a52019-08-09 01:26:35 -0500348 entry("ERROR_STR=%s", X509_verify_cert_error_string(errCode)));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600349 }
350 else
351 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800352 log<level::ERR>("Error occurred during X509_verify_cert call",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100353 entry("FILE=%s", certSrcFilePath.c_str()));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600354 elog<InternalFailure>();
355 }
356
357 // Allow certificate upload, for "certificate is not yet valid" and
358 // trust chain related errors.
359 if (!((errCode == X509_V_OK) ||
360 (errCode == X509_V_ERR_CERT_NOT_YET_VALID) ||
361 TRUST_CHAIN_ERR(errCode)))
362 {
363 if (errCode == X509_V_ERR_CERT_HAS_EXPIRED)
364 {
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500365 log<level::ERR>("Expired certificate ");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800366 elog<InvalidCertificateError>(
367 InvalidCertificate::REASON("Expired Certificate"));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600368 }
Nan Zhoubf3cf752021-12-28 11:02:07 -0800369 // Logging general error here.
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500370 log<level::ERR>(
371 "Certificate validation failed", entry("ERRCODE=%d", errCode),
372 entry("ERROR_STR=%s", X509_verify_cert_error_string(errCode)));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800373 elog<InvalidCertificateError>(
374 InvalidCertificate::REASON("Certificate validation failed"));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600375 }
376
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800377 validateCertificateStartDate(*cert);
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500378
Nidhin MS811a29e2021-05-13 12:54:32 +0530379 // Verify that the certificate can be used in a TLS context
380 const SSL_METHOD* method = TLS_method();
381 std::unique_ptr<SSL_CTX, decltype(&::SSL_CTX_free)> ctx(SSL_CTX_new(method),
382 SSL_CTX_free);
383 if (SSL_CTX_use_certificate(ctx.get(), cert.get()) != 1)
384 {
385 log<level::ERR>("Certificate is not usable",
386 entry("ERRCODE=%x", ERR_get_error()));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800387 elog<InvalidCertificateError>(
388 InvalidCertificate::REASON("Certificate is not usable"));
Nidhin MS811a29e2021-05-13 12:54:32 +0530389 }
390
Marri Devender Raocd30c492019-06-12 01:40:17 -0500391 // Invoke type specific append private key function.
392 auto appendIter = appendKeyMap.find(certType);
393 if (appendIter == appendKeyMap.end())
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600394 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800395 log<level::ERR>("Unsupported Type",
396 entry("TYPE=%s", certificateTypeToString(certType)));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600397 elog<InternalFailure>();
398 }
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100399 appendIter->second(certSrcFilePath);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500400
401 // Invoke type specific compare keys function.
402 auto compIter = typeFuncMap.find(certType);
403 if (compIter == typeFuncMap.end())
404 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800405 log<level::ERR>("Unsupported Type",
406 entry("TYPE=%s", certificateTypeToString(certType)));
Marri Devender Raocd30c492019-06-12 01:40:17 -0500407 elog<InternalFailure>();
408 }
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100409 compIter->second(certSrcFilePath);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200410
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500411 // Copy the certificate to the installation path
412 // During bootup will be parsing existing file so no need to
413 // copy it.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100414 if (certSrcFilePath != certFilePath)
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600415 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500416 std::ifstream inputCertFileStream;
417 std::ofstream outputCertFileStream;
418 inputCertFileStream.exceptions(std::ifstream::failbit |
419 std::ifstream::badbit |
420 std::ifstream::eofbit);
421 outputCertFileStream.exceptions(std::ofstream::failbit |
422 std::ofstream::badbit |
423 std::ofstream::eofbit);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200424
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500425 try
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600426 {
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100427 inputCertFileStream.open(certSrcFilePath);
428 outputCertFileStream.open(certFilePath, std::ios::out);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500429 outputCertFileStream << inputCertFileStream.rdbuf() << std::flush;
430 inputCertFileStream.close();
431 outputCertFileStream.close();
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600432 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500433 catch (const std::exception& e)
434 {
435 log<level::ERR>("Failed to copy certificate",
436 entry("ERR=%s", e.what()),
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100437 entry("SRC=%s", certSrcFilePath.c_str()),
438 entry("DST=%s", certFilePath.c_str()));
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500439 elog<InternalFailure>();
440 }
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600441 }
Marri Devender Rao8f80c352019-05-13 00:53:01 -0500442
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100443 storageUpdate();
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600444
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100445 // Keep certificate ID
446 certId = generateCertId(certFilePath);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200447
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600448 // Parse the certificate file and populate properties
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100449 populateProperties(certFilePath);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500450
451 // restart watch
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800452 if (certWatch != nullptr)
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500453 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800454 certWatch->startWatch();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500455 }
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600456}
457
Nan Zhoucf811c42021-12-02 14:56:17 -0800458// Checks that notBefore is not earlier than the unix epoch given that
459// the corresponding DBus interface is uint64_t.
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800460void Certificate::validateCertificateStartDate(X509& cert)
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500461{
462 int days = 0;
463 int secs = 0;
464
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800465 ASN1TimePtr epoch(ASN1_TIME_new(), ASN1_STRING_free);
Nan Zhoucf811c42021-12-02 14:56:17 -0800466 // Set time to 00:00am GMT, Jan 1 1970; format: YYYYMMDDHHMMSSZ
467 ASN1_TIME_set_string(epoch.get(), "19700101000000Z");
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500468
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800469 ASN1_TIME* notBefore = X509_get_notBefore(&cert);
Nan Zhoucf811c42021-12-02 14:56:17 -0800470 ASN1_TIME_diff(&days, &secs, epoch.get(), notBefore);
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500471
Nan Zhoucf811c42021-12-02 14:56:17 -0800472 if (days < 0 || secs < 0)
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500473 {
Nan Zhoucf811c42021-12-02 14:56:17 -0800474 log<level::ERR>("Certificate valid date starts before the Unix Epoch");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800475 elog<InvalidCertificateError>(InvalidCertificate::REASON(
476 "NotBefore should after 19700101000000Z"));
Marri Devender Raoc4522d22020-03-12 06:50:17 -0500477 }
478}
479
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600480void Certificate::populateProperties()
481{
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200482 populateProperties(certInstallPath);
483}
484
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100485std::string Certificate::getCertId() const
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200486{
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100487 return certId;
488}
489
490bool Certificate::isSame(const std::string& certPath)
491{
492 return getCertId() == generateCertId(certPath);
493}
494
495void Certificate::storageUpdate()
496{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800497 if (certType == CertificateType::Authority)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100498 {
499 // Create symbolic link in the certificate directory
500 std::string certFileX509Path;
501 try
502 {
503 if (!certFilePath.empty() &&
504 fs::is_regular_file(fs::path(certFilePath)))
505 {
506 certFileX509Path =
507 generateAuthCertFileX509Path(certFilePath, certInstallPath);
508 fs::create_symlink(fs::path(certFilePath),
509 fs::path(certFileX509Path));
510 }
511 }
512 catch (const std::exception& e)
513 {
514 log<level::ERR>("Failed to create symlink for certificate",
515 entry("ERR=%s", e.what()),
516 entry("FILE=%s", certFilePath.c_str()),
517 entry("SYMLINK=%s", certFileX509Path.c_str()));
518 elog<InternalFailure>();
519 }
520 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200521}
522
523void Certificate::populateProperties(const std::string& certPath)
524{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800525 internal::X509Ptr cert = loadCert(certPath);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600526 // Update properties if no error thrown
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800527 BIOMemPtr certBio(BIO_new(BIO_s_mem()), BIO_free);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600528 PEM_write_bio_X509(certBio.get(), cert.get());
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800529 BufMemPtr certBuf(BUF_MEM_new(), BUF_MEM_free);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600530 BUF_MEM* buf = certBuf.get();
531 BIO_get_mem_ptr(certBio.get(), &buf);
532 std::string certStr(buf->data, buf->length);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800533 certificateString(certStr);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600534
535 static const int maxKeySize = 4096;
536 char subBuffer[maxKeySize] = {0};
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800537 BIOMemPtr subBio(BIO_new(BIO_s_mem()), BIO_free);
Nan Zhoubf3cf752021-12-28 11:02:07 -0800538 // This pointer cannot be freed independently.
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600539 X509_NAME* sub = X509_get_subject_name(cert.get());
Marri Devender Raodec58772019-06-11 03:10:00 -0500540 X509_NAME_print_ex(subBio.get(), sub, 0, XN_FLAG_SEP_COMMA_PLUS);
541 BIO_read(subBio.get(), subBuffer, maxKeySize);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800542 subject(subBuffer);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600543
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600544 char issuerBuffer[maxKeySize] = {0};
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800545 BIOMemPtr issuerBio(BIO_new(BIO_s_mem()), BIO_free);
Nan Zhoubf3cf752021-12-28 11:02:07 -0800546 // This pointer cannot be freed independently.
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600547 X509_NAME* issuer_name = X509_get_issuer_name(cert.get());
Marri Devender Raodec58772019-06-11 03:10:00 -0500548 X509_NAME_print_ex(issuerBio.get(), issuer_name, 0, XN_FLAG_SEP_COMMA_PLUS);
549 BIO_read(issuerBio.get(), issuerBuffer, maxKeySize);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800550 issuer(issuerBuffer);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600551
552 std::vector<std::string> keyUsageList;
553 ASN1_BIT_STRING* usage;
554
555 // Go through each usage in the bit string and convert to
556 // corresponding string value
557 if ((usage = static_cast<ASN1_BIT_STRING*>(
Nan Zhoucfb58022021-12-28 11:02:26 -0800558 X509_get_ext_d2i(cert.get(), NID_key_usage, nullptr, nullptr))))
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600559 {
560 for (auto i = 0; i < usage->length; ++i)
561 {
562 for (auto& x : keyUsageToRfStr)
563 {
564 if (x.first & usage->data[i])
565 {
566 keyUsageList.push_back(x.second);
567 break;
568 }
569 }
570 }
571 }
572
573 EXTENDED_KEY_USAGE* extUsage;
Nan Zhoucfb58022021-12-28 11:02:26 -0800574 if ((extUsage = static_cast<EXTENDED_KEY_USAGE*>(X509_get_ext_d2i(
575 cert.get(), NID_ext_key_usage, nullptr, nullptr))))
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600576 {
577 for (int i = 0; i < sk_ASN1_OBJECT_num(extUsage); i++)
578 {
579 keyUsageList.push_back(extendedKeyUsageToRfStr[OBJ_obj2nid(
580 sk_ASN1_OBJECT_value(extUsage, i))]);
581 }
582 }
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800583 keyUsage(keyUsageList);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600584
585 int days = 0;
586 int secs = 0;
587
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800588 ASN1TimePtr epoch(ASN1_TIME_new(), ASN1_STRING_free);
Nan Zhoucf811c42021-12-02 14:56:17 -0800589 // Set time to 00:00am GMT, Jan 1 1970; format: YYYYMMDDHHMMSSZ
590 ASN1_TIME_set_string(epoch.get(), "19700101000000Z");
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600591
Nan Zhoucf811c42021-12-02 14:56:17 -0800592 static const uint64_t dayToSeconds = 24 * 60 * 60;
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600593 ASN1_TIME* notAfter = X509_get_notAfter(cert.get());
594 ASN1_TIME_diff(&days, &secs, epoch.get(), notAfter);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800595 validNotAfter((days * dayToSeconds) + secs);
Dhruvaraj Subhashchandran36f25142019-02-14 05:06:26 -0600596
597 ASN1_TIME* notBefore = X509_get_notBefore(cert.get());
598 ASN1_TIME_diff(&days, &secs, epoch.get(), notBefore);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800599 validNotBefore((days * dayToSeconds) + secs);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600600}
601
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800602internal::X509Ptr Certificate::loadCert(const std::string& filePath)
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600603{
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600604 // Read Certificate file
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800605 internal::X509Ptr cert(X509_new(), ::X509_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600606 if (!cert)
607 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800608 log<level::ERR>("Error occurred during X509_new call",
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600609 entry("FILE=%s", filePath.c_str()),
610 entry("ERRCODE=%lu", ERR_get_error()));
611 elog<InternalFailure>();
612 }
613
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800614 BIOMemPtr bioCert(BIO_new_file(filePath.c_str(), "rb"), ::BIO_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600615 if (!bioCert)
616 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800617 log<level::ERR>("Error occurred during BIO_new_file call",
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600618 entry("FILE=%s", filePath.c_str()));
619 elog<InternalFailure>();
620 }
621
622 X509* x509 = cert.get();
623 if (!PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr))
624 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800625 log<level::ERR>("Error occurred during PEM_read_bio_X509 call",
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600626 entry("FILE=%s", filePath.c_str()));
627 elog<InternalFailure>();
628 }
629 return cert;
630}
Marri Devender Raocd30c492019-06-12 01:40:17 -0500631
632void Certificate::checkAndAppendPrivateKey(const std::string& filePath)
633{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800634 BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free);
Marri Devender Raocd30c492019-06-12 01:40:17 -0500635 if (!keyBio)
636 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800637 log<level::ERR>("Error occurred during BIO_s_file call",
Marri Devender Raocd30c492019-06-12 01:40:17 -0500638 entry("FILE=%s", filePath.c_str()));
639 elog<InternalFailure>();
640 }
641 BIO_read_filename(keyBio.get(), filePath.c_str());
642
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800643 EVPPkeyPtr priKey(
Marri Devender Raocd30c492019-06-12 01:40:17 -0500644 PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr),
645 ::EVP_PKEY_free);
646 if (!priKey)
647 {
648 log<level::INFO>("Private key not present in file",
649 entry("FILE=%s", filePath.c_str()));
650 fs::path privateKeyFile = fs::path(certInstallPath).parent_path();
Nan Zhou718eef32021-12-28 11:03:30 -0800651 privateKeyFile = privateKeyFile / defaultPrivateKeyFileName;
Marri Devender Raocd30c492019-06-12 01:40:17 -0500652 if (!fs::exists(privateKeyFile))
653 {
654 log<level::ERR>("Private key file is not found",
655 entry("FILE=%s", privateKeyFile.c_str()));
656 elog<InternalFailure>();
657 }
658
659 std::ifstream privKeyFileStream;
660 std::ofstream certFileStream;
661 privKeyFileStream.exceptions(std::ifstream::failbit |
662 std::ifstream::badbit |
663 std::ifstream::eofbit);
664 certFileStream.exceptions(std::ofstream::failbit |
665 std::ofstream::badbit |
666 std::ofstream::eofbit);
667 try
668 {
669 privKeyFileStream.open(privateKeyFile);
670 certFileStream.open(filePath, std::ios::app);
Marri Devender Rao18e51c92019-07-15 04:59:01 -0500671 certFileStream << std::endl; // insert line break
Marri Devender Raocd30c492019-06-12 01:40:17 -0500672 certFileStream << privKeyFileStream.rdbuf() << std::flush;
673 privKeyFileStream.close();
674 certFileStream.close();
675 }
676 catch (const std::exception& e)
677 {
678 log<level::ERR>("Failed to append private key",
679 entry("ERR=%s", e.what()),
680 entry("SRC=%s", privateKeyFile.c_str()),
681 entry("DST=%s", filePath.c_str()));
682 elog<InternalFailure>();
683 }
684 }
685}
686
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600687bool Certificate::compareKeys(const std::string& filePath)
688{
689 log<level::INFO>("Certificate compareKeys",
690 entry("FILEPATH=%s", filePath.c_str()));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800691 internal::X509Ptr cert(X509_new(), ::X509_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600692 if (!cert)
693 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800694 log<level::ERR>("Error occurred during X509_new call",
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600695 entry("FILE=%s", filePath.c_str()),
696 entry("ERRCODE=%lu", ERR_get_error()));
697 elog<InternalFailure>();
698 }
699
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800700 BIOMemPtr bioCert(BIO_new_file(filePath.c_str(), "rb"), ::BIO_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600701 if (!bioCert)
702 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800703 log<level::ERR>("Error occurred during BIO_new_file call",
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600704 entry("FILE=%s", filePath.c_str()));
705 elog<InternalFailure>();
706 }
707
708 X509* x509 = cert.get();
709 PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr);
710
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800711 EVPPkeyPtr pubKey(X509_get_pubkey(cert.get()), ::EVP_PKEY_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600712 if (!pubKey)
713 {
714 log<level::ERR>("Error occurred during X509_get_pubkey",
715 entry("FILE=%s", filePath.c_str()),
716 entry("ERRCODE=%lu", ERR_get_error()));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800717 elog<InvalidCertificateError>(
718 InvalidCertificate::REASON("Failed to get public key info"));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600719 }
720
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800721 BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free);
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600722 if (!keyBio)
723 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800724 log<level::ERR>("Error occurred during BIO_s_file call",
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600725 entry("FILE=%s", filePath.c_str()));
726 elog<InternalFailure>();
727 }
728 BIO_read_filename(keyBio.get(), filePath.c_str());
729
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800730 EVPPkeyPtr priKey(
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600731 PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr),
732 ::EVP_PKEY_free);
733 if (!priKey)
734 {
735 log<level::ERR>("Error occurred during PEM_read_bio_PrivateKey",
736 entry("FILE=%s", filePath.c_str()),
737 entry("ERRCODE=%lu", ERR_get_error()));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800738 elog<InvalidCertificateError>(
739 InvalidCertificate::REASON("Failed to get private key info"));
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600740 }
741
Patrick Williams55ceaa22021-12-14 06:52:26 -0600742#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600743 int32_t rc = EVP_PKEY_cmp(priKey.get(), pubKey.get());
Patrick Williams55ceaa22021-12-14 06:52:26 -0600744#else
745 int32_t rc = EVP_PKEY_eq(priKey.get(), pubKey.get());
746#endif
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600747 if (rc != 1)
748 {
749 log<level::ERR>("Private key is not matching with Certificate",
750 entry("FILE=%s", filePath.c_str()),
751 entry("ERRCODE=%d", rc));
752 return false;
753 }
754 return true;
755}
756
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200757void Certificate::delete_()
758{
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100759 manager.deleteCertificate(this);
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200760}
Nan Zhoue1289ad2021-12-28 11:02:56 -0800761} // namespace phosphor::certs