1 #include "config.h"
2
3 #include "certificate.hpp"
4
5 #include "certs_manager.hpp"
6 #include "x509_utils.hpp"
7
8 #include <openssl/asn1.h>
9 #include <openssl/bio.h>
10 #include <openssl/buffer.h>
11 #include <openssl/err.h>
12 #include <openssl/evp.h>
13 #include <openssl/obj_mac.h>
14 #include <openssl/objects.h>
15 #include <openssl/opensslv.h>
16 #include <openssl/pem.h>
17 #include <openssl/x509v3.h>
18
19 #include <phosphor-logging/elog-errors.hpp>
20 #include <phosphor-logging/elog.hpp>
21 #include <phosphor-logging/lg2.hpp>
22 #include <watch.hpp>
23 #include <xyz/openbmc_project/Certs/error.hpp>
24 #include <xyz/openbmc_project/Common/error.hpp>
25
26 #include <cstdint>
27 #include <cstdio>
28 #include <cstdlib>
29 #include <exception>
30 #include <filesystem>
31 #include <fstream>
32 #include <map>
33 #include <utility>
34 #include <vector>
35
36 namespace phosphor::certs
37 {
38
39 namespace
40 {
41 namespace fs = std::filesystem;
42 using ::phosphor::logging::elog;
43 using InvalidCertificateError =
44 ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
45 using ::phosphor::logging::xyz::openbmc_project::Certs::InvalidCertificate;
46 using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
47
48 // RAII support for openSSL functions.
49 using BIOMemPtr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
50 using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>;
51 using ASN1TimePtr = std::unique_ptr<ASN1_TIME, decltype(&ASN1_STRING_free)>;
52 using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
53 using BufMemPtr = std::unique_ptr<BUF_MEM, decltype(&::BUF_MEM_free)>;
54
55 // Refer to schema 2018.3
56 // http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for
57 // supported KeyUsage types in redfish
58 // Refer to
59 // https://github.com/openssl/openssl/blob/master/include/openssl/x509v3.h for
60 // key usage bit fields
61 std::map<uint8_t, std::string> keyUsageToRfStr = {
62 {KU_DIGITAL_SIGNATURE, "DigitalSignature"},
63 {KU_NON_REPUDIATION, "NonRepudiation"},
64 {KU_KEY_ENCIPHERMENT, "KeyEncipherment"},
65 {KU_DATA_ENCIPHERMENT, "DataEncipherment"},
66 {KU_KEY_AGREEMENT, "KeyAgreement"},
67 {KU_KEY_CERT_SIGN, "KeyCertSign"},
68 {KU_CRL_SIGN, "CRLSigning"},
69 {KU_ENCIPHER_ONLY, "EncipherOnly"},
70 {KU_DECIPHER_ONLY, "DecipherOnly"}};
71
72 // Refer to schema 2018.3
73 // http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for
74 // supported Extended KeyUsage types in redfish
75 std::map<uint8_t, std::string> extendedKeyUsageToRfStr = {
76 {NID_server_auth, "ServerAuthentication"},
77 {NID_client_auth, "ClientAuthentication"},
78 {NID_email_protect, "EmailProtection"},
79 {NID_OCSP_sign, "OCSPSigning"},
80 {NID_ad_timeStamping, "Timestamping"},
81 {NID_code_sign, "CodeSigning"}};
82
83 /**
84 * @brief Dumps the PEM encoded certificate to installFilePath
85 *
86 * @param[in] pem - PEM encoded X509 certificate buffer.
87 * @param[in] certFilePath - Path to the destination file.
88 *
89 * @return void
90 */
91
dumpCertificate(const std::string & pem,const std::string & certFilePath)92 void dumpCertificate(const std::string& pem, const std::string& certFilePath)
93 {
94 std::ofstream outputCertFileStream;
95
96 outputCertFileStream.exceptions(
97 std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
98
99 try
100 {
101 outputCertFileStream.open(certFilePath, std::ios::out);
102 outputCertFileStream << pem << "\n" << std::flush;
103 outputCertFileStream.close();
104 }
105 catch (const std::exception& e)
106 {
107 lg2::error(
108 "Failed to dump certificate, ERR:{ERR}, SRC_PEM:{SRC_PEM}, DST:{DST}",
109 "ERR", e, "SRC_PEM", pem, "DST", certFilePath);
110 elog<InternalFailure>();
111 }
112 }
113 } // namespace
114
copyCertificate(const std::string & certSrcFilePath,const std::string & certFilePath)115 void Certificate::copyCertificate(const std::string& certSrcFilePath,
116 const std::string& certFilePath)
117 {
118 try
119 {
120 // Copy the certificate to the installation path
121 // During bootup will be parsing existing file so no need to
122 // copy it.
123 if (certSrcFilePath != certFilePath)
124 {
125 fs::copy(certSrcFilePath, certFilePath,
126 fs::copy_options::overwrite_existing);
127 }
128 }
129 catch (const fs::filesystem_error& e)
130 {
131 lg2::error(
132 "Failed to copy certificate, ERR:{ERR}, SRC:{SRC}, DST:{DST}",
133 "ERR", e.what(), "SRC", certSrcFilePath, "DST", certFilePath);
134 elog<InternalFailure>();
135 }
136 }
137
138 std::string
generateUniqueFilePath(const std::string & directoryPath)139 Certificate::generateUniqueFilePath(const std::string& directoryPath)
140 {
141 char* filePath = tempnam(directoryPath.c_str(), nullptr);
142 if (filePath == nullptr)
143 {
144 lg2::error(
145 "Error occurred while creating random certificate file path, DIR:{DIR}",
146 "DIR", directoryPath);
147 elog<InternalFailure>();
148 }
149 std::string filePathStr(filePath);
150 free(filePath);
151 return filePathStr;
152 }
153
generateAuthCertFileX509Path(const std::string & certSrcFilePath,const std::string & certDstDirPath)154 std::string Certificate::generateAuthCertFileX509Path(
155 const std::string& certSrcFilePath, const std::string& certDstDirPath)
156 {
157 const internal::X509Ptr cert = loadCert(certSrcFilePath);
158 unsigned long hash = X509_subject_name_hash(cert.get());
159 static constexpr auto certHashLength = 9;
160 char hashBuf[certHashLength];
161
162 snprintf(hashBuf, certHashLength, "%08lx", hash);
163
164 const std::string certHash(hashBuf);
165 for (size_t i = 0; i < maxNumAuthorityCertificates; ++i)
166 {
167 const std::string certDstFileX509Path =
168 certDstDirPath + "/" + certHash + "." + std::to_string(i);
169 if (!fs::exists(certDstFileX509Path))
170 {
171 return certDstFileX509Path;
172 }
173 }
174
175 lg2::error("Authority certificate x509 file path already used, DIR:{DIR}",
176 "DIR", certDstDirPath);
177 elog<InternalFailure>();
178 }
179
180 std::string
generateAuthCertFilePath(const std::string & certSrcFilePath)181 Certificate::generateAuthCertFilePath(const std::string& certSrcFilePath)
182 {
183 // If there is a certificate file path (which means certificate replacement
184 // is doing) use it (do not create new one)
185 if (!certFilePath.empty())
186 {
187 return certFilePath;
188 }
189 // If source certificate file is located in the certificates directory use
190 // it (do not create new one)
191 else if (fs::path(certSrcFilePath).parent_path().string() ==
192 certInstallPath)
193 {
194 return certSrcFilePath;
195 }
196 // Otherwise generate new file name/path
197 else
198 {
199 return generateUniqueFilePath(certInstallPath);
200 }
201 }
202
203 std::string
generateCertFilePath(const std::string & certSrcFilePath)204 Certificate::generateCertFilePath(const std::string& certSrcFilePath)
205 {
206 if (certType == CertificateType::authority)
207 {
208 return generateAuthCertFilePath(certSrcFilePath);
209 }
210 else
211 {
212 return certInstallPath;
213 }
214 }
215
Certificate(sdbusplus::bus_t & bus,const std::string & objPath,CertificateType type,const std::string & installPath,const std::string & uploadPath,Watch * watch,Manager & parent,bool restore)216 Certificate::Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
217 CertificateType type, const std::string& installPath,
218 const std::string& uploadPath, Watch* watch,
219 Manager& parent, bool restore) :
220 internal::CertificateInterface(
221 bus, objPath.c_str(),
222 internal::CertificateInterface::action::defer_emit),
223 objectPath(objPath), certType(type), certInstallPath(installPath),
224 certWatch(watch), manager(parent)
225 {
226 auto installHelper = [this](const auto& filePath) {
227 if (!compareKeys(filePath))
228 {
229 elog<InvalidCertificateError>(InvalidCertificate::REASON(
230 "Private key does not match the Certificate"));
231 };
232 };
233 typeFuncMap[CertificateType::server] = installHelper;
234 typeFuncMap[CertificateType::client] = installHelper;
235 typeFuncMap[CertificateType::authority] = [](const std::string&) {};
236
237 auto appendPrivateKey = [this](const std::string& filePath) {
238 checkAndAppendPrivateKey(filePath);
239 };
240
241 appendKeyMap[CertificateType::server] = appendPrivateKey;
242 appendKeyMap[CertificateType::client] = appendPrivateKey;
243 appendKeyMap[CertificateType::authority] = [](const std::string&) {};
244
245 // Generate certificate file path
246 certFilePath = generateCertFilePath(uploadPath);
247
248 // install the certificate
249 install(uploadPath, restore);
250
251 this->emit_object_added();
252 }
253
Certificate(sdbusplus::bus_t & bus,const std::string & objPath,const CertificateType & type,const std::string & installPath,X509_STORE & x509Store,const std::string & pem,Watch * watchPtr,Manager & parent,bool restore)254 Certificate::Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
255 const CertificateType& type,
256 const std::string& installPath, X509_STORE& x509Store,
257 const std::string& pem, Watch* watchPtr,
258 Manager& parent, bool restore) :
259 internal::CertificateInterface(
260 bus, objPath.c_str(),
261 internal::CertificateInterface::action::defer_emit),
262 objectPath(objPath), certType(type), certInstallPath(installPath),
263 certWatch(watchPtr), manager(parent)
264 {
265 // Generate certificate file path
266 certFilePath = generateUniqueFilePath(installPath);
267
268 // install the certificate
269 install(x509Store, pem, restore);
270
271 this->emit_object_added();
272 }
273
~Certificate()274 Certificate::~Certificate()
275 {
276 if (!fs::remove(certFilePath))
277 {
278 lg2::info("Certificate file not found! PATH:{PATH}", "PATH",
279 certFilePath);
280 }
281 }
282
replace(const std::string filePath)283 void Certificate::replace(const std::string filePath)
284 {
285 manager.replaceCertificate(this, filePath);
286 }
287
install(const std::string & certSrcFilePath,bool restore)288 void Certificate::install(const std::string& certSrcFilePath, bool restore)
289 {
290 if (restore)
291 {
292 lg2::debug("Certificate install, FILEPATH:{FILEPATH}", "FILEPATH",
293 certSrcFilePath);
294 }
295 else
296 {
297 lg2::info("Certificate install, FILEPATH:{FILEPATH}", "FILEPATH",
298 certSrcFilePath);
299 }
300
301 // stop watch for user initiated certificate install
302 if (certWatch != nullptr)
303 {
304 certWatch->stopWatch();
305 }
306
307 // Verify the certificate file
308 fs::path file(certSrcFilePath);
309 if (!fs::exists(file))
310 {
311 lg2::error("File is Missing, FILE:{FILE}", "FILE", certSrcFilePath);
312 elog<InternalFailure>();
313 }
314
315 try
316 {
317 if (fs::file_size(certSrcFilePath) == 0)
318 {
319 // file is empty
320 lg2::error("File is empty, FILE:{FILE}", "FILE", certSrcFilePath);
321 elog<InvalidCertificateError>(
322 InvalidCertificate::REASON("File is empty"));
323 }
324 }
325 catch (const fs::filesystem_error& e)
326 {
327 // Log Error message
328 lg2::error("File is empty, FILE:{FILE}, ERR:{ERR}", "FILE",
329 certSrcFilePath, "ERR", e);
330 elog<InternalFailure>();
331 }
332
333 X509StorePtr x509Store = getX509Store(certSrcFilePath);
334
335 // Load Certificate file into the X509 structure.
336 internal::X509Ptr cert = loadCert(certSrcFilePath);
337
338 // Perform validation
339 validateCertificateAgainstStore(*x509Store, *cert);
340 validateCertificateStartDate(*cert);
341 validateCertificateInSSLContext(*cert);
342
343 // Invoke type specific append private key function.
344 if (auto it = appendKeyMap.find(certType); it == appendKeyMap.end())
345 {
346 lg2::error("Unsupported Type, TYPE:{TYPE}", "TYPE",
347 certificateTypeToString(certType));
348 elog<InternalFailure>();
349 }
350 else
351 {
352 it->second(certSrcFilePath);
353 }
354
355 // Invoke type specific compare keys function.
356 if (auto it = typeFuncMap.find(certType); it == typeFuncMap.end())
357 {
358 lg2::error("Unsupported Type, TYPE:{TYPE}", "TYPE",
359 certificateTypeToString(certType));
360 elog<InternalFailure>();
361 }
362 else
363 {
364 it->second(certSrcFilePath);
365 }
366
367 copyCertificate(certSrcFilePath, certFilePath);
368 storageUpdate();
369
370 // Keep certificate ID
371 certId = generateCertId(*cert);
372
373 // Parse the certificate file and populate properties
374 populateProperties(*cert);
375
376 // restart watch
377 if (certWatch != nullptr)
378 {
379 certWatch->startWatch();
380 }
381 }
382
install(X509_STORE & x509Store,const std::string & pem,bool restore)383 void Certificate::install(X509_STORE& x509Store, const std::string& pem,
384 bool restore)
385 {
386 if (restore)
387 {
388 lg2::debug("Certificate install, PEM_STR:{PEM_STR}", "PEM_STR", pem);
389 }
390 else
391 {
392 lg2::info("Certificate install, PEM_STR:{PEM_STR} ", "PEM_STR", pem);
393 }
394
395 if (certType != CertificateType::authority)
396 {
397 lg2::error("Bulk install error: Unsupported Type; only authority "
398 "supports bulk install, TYPE:{TYPE}",
399 "TYPE", certificateTypeToString(certType));
400 elog<InternalFailure>();
401 }
402
403 // stop watch for user initiated certificate install
404 if (certWatch)
405 {
406 certWatch->stopWatch();
407 }
408
409 // Load Certificate file into the X509 structure.
410 internal::X509Ptr cert = parseCert(pem);
411 // Perform validation; no type specific compare keys function
412 validateCertificateAgainstStore(x509Store, *cert);
413 validateCertificateStartDate(*cert);
414 validateCertificateInSSLContext(*cert);
415
416 // Copy the PEM to the installation path
417 dumpCertificate(pem, certFilePath);
418 storageUpdate();
419 // Keep certificate ID
420 certId = generateCertId(*cert);
421 // Parse the certificate file and populate properties
422 populateProperties(*cert);
423 // restart watch
424 if (certWatch)
425 {
426 certWatch->startWatch();
427 }
428 }
429
populateProperties()430 void Certificate::populateProperties()
431 {
432 internal::X509Ptr cert = loadCert(certInstallPath);
433 populateProperties(*cert);
434 }
435
getCertId() const436 std::string Certificate::getCertId() const
437 {
438 return certId;
439 }
440
isSame(const std::string & certPath)441 bool Certificate::isSame(const std::string& certPath)
442 {
443 internal::X509Ptr cert = loadCert(certPath);
444 return getCertId() == generateCertId(*cert);
445 }
446
storageUpdate()447 void Certificate::storageUpdate()
448 {
449 if (certType == CertificateType::authority)
450 {
451 // Create symbolic link in the certificate directory
452 std::string certFileX509Path;
453 try
454 {
455 if (!certFilePath.empty() &&
456 fs::is_regular_file(fs::path(certFilePath)))
457 {
458 certFileX509Path =
459 generateAuthCertFileX509Path(certFilePath, certInstallPath);
460 fs::create_symlink(fs::path(certFilePath),
461 fs::path(certFileX509Path));
462 }
463 }
464 catch (const std::exception& e)
465 {
466 lg2::error("Failed to create symlink for certificate, ERR:{ERR},"
467 "FILE:{FILE}, SYMLINK:{SYMLINK}",
468 "ERR", e, "FILE", certFilePath, "SYMLINK",
469 certFileX509Path);
470 elog<InternalFailure>();
471 }
472 }
473 }
474
populateProperties(X509 & cert)475 void Certificate::populateProperties(X509& cert)
476 {
477 // Update properties if no error thrown
478 BIOMemPtr certBio(BIO_new(BIO_s_mem()), BIO_free);
479 PEM_write_bio_X509(certBio.get(), &cert);
480 BufMemPtr certBuf(BUF_MEM_new(), BUF_MEM_free);
481 BUF_MEM* buf = certBuf.get();
482 BIO_get_mem_ptr(certBio.get(), &buf);
483 std::string certStr(buf->data, buf->length);
484 certificateString(certStr);
485
486 static const int maxKeySize = 4096;
487 char subBuffer[maxKeySize] = {0};
488 BIOMemPtr subBio(BIO_new(BIO_s_mem()), BIO_free);
489 // This pointer cannot be freed independently.
490 X509_NAME* sub = X509_get_subject_name(&cert);
491 X509_NAME_print_ex(subBio.get(), sub, 0, XN_FLAG_SEP_COMMA_PLUS);
492 BIO_read(subBio.get(), subBuffer, maxKeySize);
493 subject(subBuffer);
494
495 char issuerBuffer[maxKeySize] = {0};
496 BIOMemPtr issuerBio(BIO_new(BIO_s_mem()), BIO_free);
497 // This pointer cannot be freed independently.
498 X509_NAME* issuerName = X509_get_issuer_name(&cert);
499 X509_NAME_print_ex(issuerBio.get(), issuerName, 0, XN_FLAG_SEP_COMMA_PLUS);
500 BIO_read(issuerBio.get(), issuerBuffer, maxKeySize);
501 issuer(issuerBuffer);
502
503 std::vector<std::string> keyUsageList;
504
505 // Go through each usage in the bit string and convert to
506 // corresponding string value
507 ASN1_BIT_STRING* usage = static_cast<ASN1_BIT_STRING*>(
508 X509_get_ext_d2i(&cert, NID_key_usage, nullptr, nullptr));
509 if (usage != nullptr)
510 {
511 for (auto i = 0; i < usage->length; ++i)
512 {
513 for (auto& x : keyUsageToRfStr)
514 {
515 if (x.first & usage->data[i])
516 {
517 keyUsageList.push_back(x.second);
518 break;
519 }
520 }
521 }
522 }
523
524 EXTENDED_KEY_USAGE* extUsage = static_cast<EXTENDED_KEY_USAGE*>(
525 X509_get_ext_d2i(&cert, NID_ext_key_usage, nullptr, nullptr));
526 if (extUsage == nullptr)
527 {
528 for (int i = 0; i < sk_ASN1_OBJECT_num(extUsage); i++)
529 {
530 keyUsageList.push_back(extendedKeyUsageToRfStr[OBJ_obj2nid(
531 sk_ASN1_OBJECT_value(extUsage, i))]);
532 }
533 }
534 keyUsage(keyUsageList);
535
536 int days = 0;
537 int secs = 0;
538
539 ASN1TimePtr epoch(ASN1_TIME_new(), ASN1_STRING_free);
540 // Set time to 00:00am GMT, Jan 1 1970; format: YYYYMMDDHHMMSSZ
541 ASN1_TIME_set_string(epoch.get(), "19700101000000Z");
542
543 constexpr uint64_t dayToSeconds = 86400; // 24 * 60 * 60
544 ASN1_TIME* notAfter = X509_get_notAfter(&cert);
545 ASN1_TIME_diff(&days, &secs, epoch.get(), notAfter);
546 validNotAfter((days * dayToSeconds) + secs);
547
548 ASN1_TIME* notBefore = X509_get_notBefore(&cert);
549 ASN1_TIME_diff(&days, &secs, epoch.get(), notBefore);
550 validNotBefore((days * dayToSeconds) + secs);
551 }
552
checkAndAppendPrivateKey(const std::string & filePath)553 void Certificate::checkAndAppendPrivateKey(const std::string& filePath)
554 {
555 BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free);
556 if (!keyBio)
557 {
558 lg2::error("Error occurred during BIO_s_file call, FILE:{FILE}", "FILE",
559 filePath);
560 elog<InternalFailure>();
561 }
562 BIO_read_filename(keyBio.get(), filePath.c_str());
563
564 EVPPkeyPtr priKey(
565 PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr),
566 ::EVP_PKEY_free);
567 if (!priKey)
568 {
569 lg2::info("Private key not present in file, FILE:{FILE}", "FILE",
570 filePath);
571 fs::path privateKeyFile = fs::path(certInstallPath).parent_path();
572 privateKeyFile = privateKeyFile / defaultPrivateKeyFileName;
573 if (!fs::exists(privateKeyFile))
574 {
575 lg2::error("Private key file is not found, FILE:{FILE}", "FILE",
576 privateKeyFile);
577 elog<InternalFailure>();
578 }
579
580 std::ifstream privKeyFileStream;
581 std::ofstream certFileStream;
582 privKeyFileStream.exceptions(
583 std::ifstream::failbit | std::ifstream::badbit |
584 std::ifstream::eofbit);
585 certFileStream.exceptions(
586 std::ofstream::failbit | std::ofstream::badbit |
587 std::ofstream::eofbit);
588 try
589 {
590 privKeyFileStream.open(privateKeyFile);
591 certFileStream.open(filePath, std::ios::app);
592 certFileStream << std::endl; // insert line break
593 certFileStream << privKeyFileStream.rdbuf() << std::flush;
594 privKeyFileStream.close();
595 certFileStream.close();
596 }
597 catch (const std::exception& e)
598 {
599 lg2::error(
600 "Failed to append private key, ERR:{ERR}, SRC:{SRC}, DST:{DST}",
601 "ERR", e, "SRC", privateKeyFile, "DST", filePath);
602 elog<InternalFailure>();
603 }
604 }
605 }
606
compareKeys(const std::string & filePath)607 bool Certificate::compareKeys(const std::string& filePath)
608 {
609 lg2::info("Certificate compareKeys, FILEPATH:{FILEPATH}", "FILEPATH",
610 filePath);
611 internal::X509Ptr cert(X509_new(), ::X509_free);
612 if (!cert)
613 {
614 lg2::error(
615 "Error occurred during X509_new call, FILE:{FILE}, ERRCODE:{ERRCODE}",
616 "FILE", filePath, "ERRCODE", ERR_get_error());
617 elog<InternalFailure>();
618 }
619
620 BIOMemPtr bioCert(BIO_new_file(filePath.c_str(), "rb"), ::BIO_free);
621 if (!bioCert)
622 {
623 lg2::error("Error occurred during BIO_new_file call, FILE:{FILE}",
624 "FILE", filePath);
625 elog<InternalFailure>();
626 }
627
628 X509* x509 = cert.get();
629 PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr);
630
631 EVPPkeyPtr pubKey(X509_get_pubkey(cert.get()), ::EVP_PKEY_free);
632 if (!pubKey)
633 {
634 lg2::error(
635 "Error occurred during X509_get_pubkey, FILE:{FILE}, ERRCODE:{ERRCODE}",
636 "FILE", filePath, "ERRCODE", ERR_get_error());
637 elog<InvalidCertificateError>(
638 InvalidCertificate::REASON("Failed to get public key info"));
639 }
640
641 BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free);
642 if (!keyBio)
643 {
644 lg2::error("Error occurred during BIO_s_file call, FILE:{FILE}", "FILE",
645 filePath);
646 elog<InternalFailure>();
647 }
648 BIO_read_filename(keyBio.get(), filePath.c_str());
649
650 EVPPkeyPtr priKey(
651 PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr),
652 ::EVP_PKEY_free);
653 if (!priKey)
654 {
655 lg2::error(
656 "Error occurred during PEM_read_bio_PrivateKey, FILE:{FILE}, ERRCODE:{ERRCODE}",
657 "FILE", filePath, "ERRCODE", ERR_get_error());
658 elog<InvalidCertificateError>(
659 InvalidCertificate::REASON("Failed to get private key info"));
660 }
661
662 #if (OPENSSL_VERSION_NUMBER < 0x30000000L)
663 int32_t rc = EVP_PKEY_cmp(priKey.get(), pubKey.get());
664 #else
665 int32_t rc = EVP_PKEY_eq(priKey.get(), pubKey.get());
666 #endif
667 if (rc != 1)
668 {
669 lg2::error(
670 "Private key is not matching with Certificate, FILE:{FILE}, ERRCODE:{ERRCODE}",
671 "FILE", filePath, "ERRCODE", rc);
672 return false;
673 }
674 return true;
675 }
676
delete_()677 void Certificate::delete_()
678 {
679 manager.deleteCertificate(this);
680 }
681
getObjectPath()682 std::string Certificate::getObjectPath()
683 {
684 return objectPath;
685 }
686
getCertFilePath()687 std::string Certificate::getCertFilePath()
688 {
689 return certFilePath;
690 }
691
setCertFilePath(const std::string & path)692 void Certificate::setCertFilePath(const std::string& path)
693 {
694 certFilePath = path;
695 }
696
setCertInstallPath(const std::string & path)697 void Certificate::setCertInstallPath(const std::string& path)
698 {
699 certInstallPath = path;
700 }
701
702 } // namespace phosphor::certs
703