| #include "config.h" |
| |
| #include "certificate.hpp" |
| |
| #include "certs_manager.hpp" |
| #include "x509_utils.hpp" |
| |
| #include <openssl/asn1.h> |
| #include <openssl/bio.h> |
| #include <openssl/buffer.h> |
| #include <openssl/err.h> |
| #include <openssl/evp.h> |
| #include <openssl/obj_mac.h> |
| #include <openssl/objects.h> |
| #include <openssl/opensslv.h> |
| #include <openssl/pem.h> |
| #include <openssl/x509v3.h> |
| |
| #include <phosphor-logging/elog-errors.hpp> |
| #include <phosphor-logging/elog.hpp> |
| #include <phosphor-logging/lg2.hpp> |
| #include <watch.hpp> |
| #include <xyz/openbmc_project/Certs/error.hpp> |
| #include <xyz/openbmc_project/Common/error.hpp> |
| |
| #include <cstdint> |
| #include <cstdio> |
| #include <cstdlib> |
| #include <exception> |
| #include <filesystem> |
| #include <fstream> |
| #include <map> |
| #include <random> |
| #include <utility> |
| #include <vector> |
| |
| namespace phosphor::certs |
| { |
| |
| namespace |
| { |
| namespace fs = std::filesystem; |
| using ::phosphor::logging::elog; |
| using InvalidCertificateError = |
| ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; |
| using ::phosphor::logging::xyz::openbmc_project::Certs::InvalidCertificate; |
| using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; |
| |
| // RAII support for openSSL functions. |
| using BIOMemPtr = std::unique_ptr<BIO, decltype(&::BIO_free)>; |
| using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>; |
| using ASN1TimePtr = std::unique_ptr<ASN1_TIME, decltype(&ASN1_STRING_free)>; |
| using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>; |
| using BufMemPtr = std::unique_ptr<BUF_MEM, decltype(&::BUF_MEM_free)>; |
| |
| // Refer to schema 2018.3 |
| // http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for |
| // supported KeyUsage types in redfish |
| // Refer to |
| // https://github.com/openssl/openssl/blob/master/include/openssl/x509v3.h for |
| // key usage bit fields |
| std::map<uint8_t, std::string> keyUsageToRfStr = { |
| {KU_DIGITAL_SIGNATURE, "DigitalSignature"}, |
| {KU_NON_REPUDIATION, "NonRepudiation"}, |
| {KU_KEY_ENCIPHERMENT, "KeyEncipherment"}, |
| {KU_DATA_ENCIPHERMENT, "DataEncipherment"}, |
| {KU_KEY_AGREEMENT, "KeyAgreement"}, |
| {KU_KEY_CERT_SIGN, "KeyCertSign"}, |
| {KU_CRL_SIGN, "CRLSigning"}, |
| {KU_ENCIPHER_ONLY, "EncipherOnly"}, |
| {KU_DECIPHER_ONLY, "DecipherOnly"}}; |
| |
| // Refer to schema 2018.3 |
| // http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for |
| // supported Extended KeyUsage types in redfish |
| std::map<uint8_t, std::string> extendedKeyUsageToRfStr = { |
| {NID_server_auth, "ServerAuthentication"}, |
| {NID_client_auth, "ClientAuthentication"}, |
| {NID_email_protect, "EmailProtection"}, |
| {NID_OCSP_sign, "OCSPSigning"}, |
| {NID_ad_timeStamping, "Timestamping"}, |
| {NID_code_sign, "CodeSigning"}}; |
| |
| /** |
| * @brief Dumps the PEM encoded certificate to installFilePath |
| * |
| * @param[in] pem - PEM encoded X509 certificate buffer. |
| * @param[in] certFilePath - Path to the destination file. |
| * |
| * @return void |
| */ |
| |
| void dumpCertificate(const std::string& pem, const std::string& certFilePath) |
| { |
| std::ofstream outputCertFileStream; |
| |
| outputCertFileStream.exceptions( |
| std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit); |
| |
| try |
| { |
| outputCertFileStream.open(certFilePath, std::ios::out); |
| outputCertFileStream << pem << "\n" << std::flush; |
| outputCertFileStream.close(); |
| } |
| catch (const std::exception& e) |
| { |
| lg2::error( |
| "Failed to dump certificate, ERR:{ERR}, SRC_PEM:{SRC_PEM}, DST:{DST}", |
| "ERR", e, "SRC_PEM", pem, "DST", certFilePath); |
| elog<InternalFailure>(); |
| } |
| } |
| } // namespace |
| |
| void Certificate::copyCertificate(const std::string& certSrcFilePath, |
| const std::string& certFilePath) |
| { |
| // Copy the certificate to the installation path |
| // During bootup will be parsing existing file so no need to |
| // copy it. |
| if (certSrcFilePath != certFilePath) |
| { |
| // -p flag preserves the file metadata when copying |
| // -f flag forces the copy |
| const std::string command = |
| std::format("cp -fp {} {}", certSrcFilePath, certFilePath); |
| int statusCode = std::system(command.c_str()); |
| |
| // Non-zero `status_code` indicates something went wrong with issuing |
| // the copy command. |
| if (statusCode != 0) |
| { |
| lg2::error( |
| "Failed to copy certificate, ERR:{ERR}, SRC:{SRC}, DST:{DST}", |
| "ERR", statusCode, "SRC", certSrcFilePath, "DST", certFilePath); |
| elog<InternalFailure>(); |
| } |
| } |
| } |
| |
| std::string |
| Certificate::generateUniqueFilePath(const std::string& directoryPath) |
| { |
| // Create a template for the temporary file name |
| std::string filePath = directoryPath + "/" + "cert-XXXXXX"; |
| int fd = mkstemp(filePath.data()); |
| if (fd == -1) |
| { |
| lg2::error( |
| "Error occurred while creating random certificate file path, DIR:{DIR}", |
| "DIR", directoryPath); |
| elog<InternalFailure>(); |
| throw std::runtime_error("Failed to create unique file path"); |
| } |
| |
| // Close the file descriptor and file, just need the unique path |
| close(fd); |
| std::remove(filePath.data()); |
| return filePath; |
| } |
| |
| std::string Certificate::generateAuthCertFileX509Path( |
| const std::string& certSrcFilePath, const std::string& certDstDirPath) |
| { |
| const internal::X509Ptr cert = loadCert(certSrcFilePath); |
| unsigned long hash = X509_subject_name_hash(cert.get()); |
| static constexpr auto certHashLength = 9; |
| char hashBuf[certHashLength]; |
| |
| snprintf(hashBuf, certHashLength, "%08lx", hash); |
| |
| const std::string certHash(hashBuf); |
| for (size_t i = 0; i < maxNumAuthorityCertificates; ++i) |
| { |
| const std::string certDstFileX509Path = |
| certDstDirPath + "/" + certHash + "." + std::to_string(i); |
| if (!fs::exists(certDstFileX509Path)) |
| { |
| return certDstFileX509Path; |
| } |
| } |
| |
| lg2::error("Authority certificate x509 file path already used, DIR:{DIR}", |
| "DIR", certDstDirPath); |
| elog<InternalFailure>(); |
| } |
| |
| std::string |
| Certificate::generateAuthCertFilePath(const std::string& certSrcFilePath) |
| { |
| // If there is a certificate file path (which means certificate replacement |
| // is doing) use it (do not create new one) |
| if (!certFilePath.empty()) |
| { |
| return certFilePath; |
| } |
| // If source certificate file is located in the certificates directory use |
| // it (do not create new one) |
| else if (fs::path(certSrcFilePath).parent_path().string() == |
| certInstallPath) |
| { |
| return certSrcFilePath; |
| } |
| // Otherwise generate new file name/path |
| else |
| { |
| return generateUniqueFilePath(certInstallPath); |
| } |
| } |
| |
| std::string |
| Certificate::generateCertFilePath(const std::string& certSrcFilePath) |
| { |
| if (certType == CertificateType::authority) |
| { |
| return generateAuthCertFilePath(certSrcFilePath); |
| } |
| else |
| { |
| return certInstallPath; |
| } |
| } |
| |
| Certificate::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) : |
| internal::CertificateInterface( |
| bus, objPath.c_str(), |
| internal::CertificateInterface::action::defer_emit), |
| objectPath(objPath), certType(type), certInstallPath(installPath), |
| certWatch(watch), manager(parent) |
| { |
| auto installHelper = [this](const auto& filePath) { |
| if (!compareKeys(filePath)) |
| { |
| elog<InvalidCertificateError>(InvalidCertificate::REASON( |
| "Private key does not match the Certificate")); |
| }; |
| }; |
| typeFuncMap[CertificateType::server] = installHelper; |
| typeFuncMap[CertificateType::client] = installHelper; |
| typeFuncMap[CertificateType::authority] = [](const std::string&) {}; |
| |
| auto appendPrivateKey = [this](const std::string& filePath) { |
| checkAndAppendPrivateKey(filePath); |
| }; |
| |
| appendKeyMap[CertificateType::server] = appendPrivateKey; |
| appendKeyMap[CertificateType::client] = appendPrivateKey; |
| appendKeyMap[CertificateType::authority] = [](const std::string&) {}; |
| |
| // Generate certificate file path |
| certFilePath = generateCertFilePath(uploadPath); |
| |
| // install the certificate |
| install(uploadPath, restore); |
| |
| this->emit_object_added(); |
| } |
| |
| Certificate::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) : |
| internal::CertificateInterface( |
| bus, objPath.c_str(), |
| internal::CertificateInterface::action::defer_emit), |
| objectPath(objPath), certType(type), certInstallPath(installPath), |
| certWatch(watchPtr), manager(parent) |
| { |
| // Generate certificate file path |
| certFilePath = generateUniqueFilePath(installPath); |
| |
| // install the certificate |
| install(x509Store, pem, restore); |
| |
| this->emit_object_added(); |
| } |
| |
| Certificate::~Certificate() |
| { |
| if (!fs::remove(certFilePath)) |
| { |
| lg2::info("Certificate file not found! PATH:{PATH}", "PATH", |
| certFilePath); |
| } |
| } |
| |
| void Certificate::replace(const std::string filePath) |
| { |
| manager.replaceCertificate(this, filePath); |
| } |
| |
| void Certificate::install(const std::string& certSrcFilePath, bool restore) |
| { |
| if (restore) |
| { |
| lg2::debug("Certificate install, FILEPATH:{FILEPATH}", "FILEPATH", |
| certSrcFilePath); |
| } |
| else |
| { |
| lg2::info("Certificate install, FILEPATH:{FILEPATH}", "FILEPATH", |
| certSrcFilePath); |
| } |
| |
| // stop watch for user initiated certificate install |
| if (certWatch != nullptr) |
| { |
| certWatch->stopWatch(); |
| } |
| |
| // Verify the certificate file |
| fs::path file(certSrcFilePath); |
| if (!fs::exists(file)) |
| { |
| lg2::error("File is Missing, FILE:{FILE}", "FILE", certSrcFilePath); |
| elog<InternalFailure>(); |
| } |
| |
| try |
| { |
| if (fs::file_size(certSrcFilePath) == 0) |
| { |
| // file is empty |
| lg2::error("File is empty, FILE:{FILE}", "FILE", certSrcFilePath); |
| elog<InvalidCertificateError>( |
| InvalidCertificate::REASON("File is empty")); |
| } |
| } |
| catch (const fs::filesystem_error& e) |
| { |
| // Log Error message |
| lg2::error("File is empty, FILE:{FILE}, ERR:{ERR}", "FILE", |
| certSrcFilePath, "ERR", e); |
| elog<InternalFailure>(); |
| } |
| |
| X509StorePtr x509Store = getX509Store(certSrcFilePath); |
| |
| // Load Certificate file into the X509 structure. |
| internal::X509Ptr cert = loadCert(certSrcFilePath); |
| |
| // Perform validation |
| validateCertificateAgainstStore(*x509Store, *cert); |
| validateCertificateStartDate(*cert); |
| validateCertificateInSSLContext(*cert); |
| |
| // Invoke type specific append private key function. |
| if (auto it = appendKeyMap.find(certType); it == appendKeyMap.end()) |
| { |
| lg2::error("Unsupported Type, TYPE:{TYPE}", "TYPE", |
| certificateTypeToString(certType)); |
| elog<InternalFailure>(); |
| } |
| else |
| { |
| it->second(certSrcFilePath); |
| } |
| |
| // Invoke type specific compare keys function. |
| if (auto it = typeFuncMap.find(certType); it == typeFuncMap.end()) |
| { |
| lg2::error("Unsupported Type, TYPE:{TYPE}", "TYPE", |
| certificateTypeToString(certType)); |
| elog<InternalFailure>(); |
| } |
| else |
| { |
| it->second(certSrcFilePath); |
| } |
| |
| copyCertificate(certSrcFilePath, certFilePath); |
| storageUpdate(); |
| |
| // Keep certificate ID |
| certId = generateCertId(*cert); |
| |
| // Parse the certificate file and populate properties |
| populateProperties(*cert); |
| |
| // restart watch |
| if (certWatch != nullptr) |
| { |
| certWatch->startWatch(); |
| } |
| } |
| |
| void Certificate::install(X509_STORE& x509Store, const std::string& pem, |
| bool restore) |
| { |
| if (restore) |
| { |
| lg2::debug("Certificate install, PEM_STR:{PEM_STR}", "PEM_STR", pem); |
| } |
| else |
| { |
| lg2::info("Certificate install, PEM_STR:{PEM_STR} ", "PEM_STR", pem); |
| } |
| |
| if (certType != CertificateType::authority) |
| { |
| lg2::error("Bulk install error: Unsupported Type; only authority " |
| "supports bulk install, TYPE:{TYPE}", |
| "TYPE", certificateTypeToString(certType)); |
| elog<InternalFailure>(); |
| } |
| |
| // stop watch for user initiated certificate install |
| if (certWatch) |
| { |
| certWatch->stopWatch(); |
| } |
| |
| // Load Certificate file into the X509 structure. |
| internal::X509Ptr cert = parseCert(pem); |
| // Perform validation; no type specific compare keys function |
| validateCertificateAgainstStore(x509Store, *cert); |
| validateCertificateStartDate(*cert); |
| validateCertificateInSSLContext(*cert); |
| |
| // Copy the PEM to the installation path |
| dumpCertificate(pem, certFilePath); |
| storageUpdate(); |
| // Keep certificate ID |
| certId = generateCertId(*cert); |
| // Parse the certificate file and populate properties |
| populateProperties(*cert); |
| // restart watch |
| if (certWatch) |
| { |
| certWatch->startWatch(); |
| } |
| } |
| |
| void Certificate::populateProperties() |
| { |
| internal::X509Ptr cert = loadCert(certInstallPath); |
| populateProperties(*cert); |
| } |
| |
| std::string Certificate::getCertId() const |
| { |
| return certId; |
| } |
| |
| bool Certificate::isSame(const std::string& certPath) |
| { |
| internal::X509Ptr cert = loadCert(certPath); |
| return getCertId() == generateCertId(*cert); |
| } |
| |
| void Certificate::storageUpdate() |
| { |
| if (certType == CertificateType::authority) |
| { |
| // Create symbolic link in the certificate directory |
| std::string certFileX509Path; |
| try |
| { |
| if (!certFilePath.empty() && |
| fs::is_regular_file(fs::path(certFilePath))) |
| { |
| certFileX509Path = |
| generateAuthCertFileX509Path(certFilePath, certInstallPath); |
| fs::create_symlink(fs::path(certFilePath), |
| fs::path(certFileX509Path)); |
| } |
| } |
| catch (const std::exception& e) |
| { |
| lg2::error("Failed to create symlink for certificate, ERR:{ERR}," |
| "FILE:{FILE}, SYMLINK:{SYMLINK}", |
| "ERR", e, "FILE", certFilePath, "SYMLINK", |
| certFileX509Path); |
| elog<InternalFailure>(); |
| } |
| } |
| } |
| |
| void Certificate::populateProperties(X509& cert) |
| { |
| // Update properties if no error thrown |
| BIOMemPtr certBio(BIO_new(BIO_s_mem()), BIO_free); |
| PEM_write_bio_X509(certBio.get(), &cert); |
| BufMemPtr certBuf(BUF_MEM_new(), BUF_MEM_free); |
| BUF_MEM* buf = certBuf.get(); |
| BIO_get_mem_ptr(certBio.get(), &buf); |
| std::string certStr(buf->data, buf->length); |
| certificateString(certStr); |
| |
| static const int maxKeySize = 4096; |
| char subBuffer[maxKeySize] = {0}; |
| BIOMemPtr subBio(BIO_new(BIO_s_mem()), BIO_free); |
| // This pointer cannot be freed independently. |
| X509_NAME* sub = X509_get_subject_name(&cert); |
| X509_NAME_print_ex(subBio.get(), sub, 0, XN_FLAG_SEP_COMMA_PLUS); |
| BIO_read(subBio.get(), subBuffer, maxKeySize); |
| subject(subBuffer); |
| |
| char issuerBuffer[maxKeySize] = {0}; |
| BIOMemPtr issuerBio(BIO_new(BIO_s_mem()), BIO_free); |
| // This pointer cannot be freed independently. |
| X509_NAME* issuerName = X509_get_issuer_name(&cert); |
| X509_NAME_print_ex(issuerBio.get(), issuerName, 0, XN_FLAG_SEP_COMMA_PLUS); |
| BIO_read(issuerBio.get(), issuerBuffer, maxKeySize); |
| issuer(issuerBuffer); |
| |
| std::vector<std::string> keyUsageList; |
| ASN1_BIT_STRING* usage; |
| |
| // Go through each usage in the bit string and convert to |
| // corresponding string value |
| if ((usage = static_cast<ASN1_BIT_STRING*>( |
| X509_get_ext_d2i(&cert, NID_key_usage, nullptr, nullptr)))) |
| { |
| for (auto i = 0; i < usage->length; ++i) |
| { |
| for (auto& x : keyUsageToRfStr) |
| { |
| if (x.first & usage->data[i]) |
| { |
| keyUsageList.push_back(x.second); |
| break; |
| } |
| } |
| } |
| } |
| |
| EXTENDED_KEY_USAGE* extUsage; |
| if ((extUsage = static_cast<EXTENDED_KEY_USAGE*>( |
| X509_get_ext_d2i(&cert, NID_ext_key_usage, nullptr, nullptr)))) |
| { |
| for (int i = 0; i < sk_ASN1_OBJECT_num(extUsage); i++) |
| { |
| keyUsageList.push_back(extendedKeyUsageToRfStr[OBJ_obj2nid( |
| sk_ASN1_OBJECT_value(extUsage, i))]); |
| } |
| } |
| keyUsage(keyUsageList); |
| |
| int days = 0; |
| int secs = 0; |
| |
| ASN1TimePtr epoch(ASN1_TIME_new(), ASN1_STRING_free); |
| // Set time to 00:00am GMT, Jan 1 1970; format: YYYYMMDDHHMMSSZ |
| ASN1_TIME_set_string(epoch.get(), "19700101000000Z"); |
| |
| static const uint64_t dayToSeconds = 24 * 60 * 60; |
| ASN1_TIME* notAfter = X509_get_notAfter(&cert); |
| ASN1_TIME_diff(&days, &secs, epoch.get(), notAfter); |
| validNotAfter((days * dayToSeconds) + secs); |
| |
| ASN1_TIME* notBefore = X509_get_notBefore(&cert); |
| ASN1_TIME_diff(&days, &secs, epoch.get(), notBefore); |
| validNotBefore((days * dayToSeconds) + secs); |
| } |
| |
| void Certificate::checkAndAppendPrivateKey(const std::string& filePath) |
| { |
| BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free); |
| if (!keyBio) |
| { |
| lg2::error("Error occurred during BIO_s_file call, FILE:{FILE}", "FILE", |
| filePath); |
| elog<InternalFailure>(); |
| } |
| BIO_read_filename(keyBio.get(), filePath.c_str()); |
| |
| EVPPkeyPtr priKey( |
| PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr), |
| ::EVP_PKEY_free); |
| if (!priKey) |
| { |
| lg2::info("Private key not present in file, FILE:{FILE}", "FILE", |
| filePath); |
| fs::path privateKeyFile = fs::path(certInstallPath).parent_path(); |
| privateKeyFile = privateKeyFile / defaultPrivateKeyFileName; |
| if (!fs::exists(privateKeyFile)) |
| { |
| lg2::error("Private key file is not found, FILE:{FILE}", "FILE", |
| privateKeyFile); |
| elog<InternalFailure>(); |
| } |
| |
| std::ifstream privKeyFileStream; |
| std::ofstream certFileStream; |
| privKeyFileStream.exceptions( |
| std::ifstream::failbit | std::ifstream::badbit | |
| std::ifstream::eofbit); |
| certFileStream.exceptions( |
| std::ofstream::failbit | std::ofstream::badbit | |
| std::ofstream::eofbit); |
| try |
| { |
| privKeyFileStream.open(privateKeyFile); |
| certFileStream.open(filePath, std::ios::app); |
| certFileStream << std::endl; // insert line break |
| certFileStream << privKeyFileStream.rdbuf() << std::flush; |
| privKeyFileStream.close(); |
| certFileStream.close(); |
| } |
| catch (const std::exception& e) |
| { |
| lg2::error( |
| "Failed to append private key, ERR:{ERR}, SRC:{SRC}, DST:{DST}", |
| "ERR", e, "SRC", privateKeyFile, "DST", filePath); |
| elog<InternalFailure>(); |
| } |
| } |
| } |
| |
| bool Certificate::compareKeys(const std::string& filePath) |
| { |
| lg2::info("Certificate compareKeys, FILEPATH:{FILEPATH}", "FILEPATH", |
| filePath); |
| internal::X509Ptr cert(X509_new(), ::X509_free); |
| if (!cert) |
| { |
| lg2::error( |
| "Error occurred during X509_new call, FILE:{FILE}, ERRCODE:{ERRCODE}", |
| "FILE", filePath, "ERRCODE", ERR_get_error()); |
| elog<InternalFailure>(); |
| } |
| |
| BIOMemPtr bioCert(BIO_new_file(filePath.c_str(), "rb"), ::BIO_free); |
| if (!bioCert) |
| { |
| lg2::error("Error occurred during BIO_new_file call, FILE:{FILE}", |
| "FILE", filePath); |
| elog<InternalFailure>(); |
| } |
| |
| X509* x509 = cert.get(); |
| PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr); |
| |
| EVPPkeyPtr pubKey(X509_get_pubkey(cert.get()), ::EVP_PKEY_free); |
| if (!pubKey) |
| { |
| lg2::error( |
| "Error occurred during X509_get_pubkey, FILE:{FILE}, ERRCODE:{ERRCODE}", |
| "FILE", filePath, "ERRCODE", ERR_get_error()); |
| elog<InvalidCertificateError>( |
| InvalidCertificate::REASON("Failed to get public key info")); |
| } |
| |
| BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free); |
| if (!keyBio) |
| { |
| lg2::error("Error occurred during BIO_s_file call, FILE:{FILE}", "FILE", |
| filePath); |
| elog<InternalFailure>(); |
| } |
| BIO_read_filename(keyBio.get(), filePath.c_str()); |
| |
| EVPPkeyPtr priKey( |
| PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr), |
| ::EVP_PKEY_free); |
| if (!priKey) |
| { |
| lg2::error( |
| "Error occurred during PEM_read_bio_PrivateKey, FILE:{FILE}, ERRCODE:{ERRCODE}", |
| "FILE", filePath, "ERRCODE", ERR_get_error()); |
| elog<InvalidCertificateError>( |
| InvalidCertificate::REASON("Failed to get private key info")); |
| } |
| |
| #if (OPENSSL_VERSION_NUMBER < 0x30000000L) |
| int32_t rc = EVP_PKEY_cmp(priKey.get(), pubKey.get()); |
| #else |
| int32_t rc = EVP_PKEY_eq(priKey.get(), pubKey.get()); |
| #endif |
| if (rc != 1) |
| { |
| lg2::error( |
| "Private key is not matching with Certificate, FILE:{FILE}, ERRCODE:{ERRCODE}", |
| "FILE", filePath, "ERRCODE", rc); |
| return false; |
| } |
| return true; |
| } |
| |
| void Certificate::delete_() |
| { |
| manager.deleteCertificate(this); |
| } |
| |
| std::string Certificate::getObjectPath() |
| { |
| return objectPath; |
| } |
| |
| std::string Certificate::getCertFilePath() |
| { |
| return certFilePath; |
| } |
| |
| void Certificate::setCertFilePath(const std::string& path) |
| { |
| certFilePath = path; |
| } |
| |
| void Certificate::setCertInstallPath(const std::string& path) |
| { |
| certInstallPath = path; |
| } |
| |
| } // namespace phosphor::certs |