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