1cd30c496SMarri Devender Rao #include "config.h"
2cd30c496SMarri Devender Rao
36ceec40bSMarri Devender Rao #include "certificate.hpp"
46ceec40bSMarri Devender Rao
5a3bb38fbSZbigniew Kurzynski #include "certs_manager.hpp"
6e869bb63SNan Zhou #include "x509_utils.hpp"
7a3bb38fbSZbigniew Kurzynski
8014be0bfSNan Zhou #include <openssl/asn1.h>
96ceec40bSMarri Devender Rao #include <openssl/bio.h>
10014be0bfSNan Zhou #include <openssl/buffer.h>
116ceec40bSMarri Devender Rao #include <openssl/err.h>
126ceec40bSMarri Devender Rao #include <openssl/evp.h>
13014be0bfSNan Zhou #include <openssl/obj_mac.h>
14014be0bfSNan Zhou #include <openssl/objects.h>
15014be0bfSNan Zhou #include <openssl/opensslv.h>
166ceec40bSMarri Devender Rao #include <openssl/pem.h>
176ceec40bSMarri Devender Rao #include <openssl/x509v3.h>
186ceec40bSMarri Devender Rao
19223e4604SPatrick Williams #include <phosphor-logging/elog-errors.hpp>
20223e4604SPatrick Williams #include <phosphor-logging/elog.hpp>
21f2646271SRavi Teja #include <phosphor-logging/lg2.hpp>
22223e4604SPatrick Williams #include <watch.hpp>
23223e4604SPatrick Williams #include <xyz/openbmc_project/Certs/error.hpp>
24223e4604SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp>
25223e4604SPatrick Williams
26014be0bfSNan Zhou #include <cstdint>
27014be0bfSNan Zhou #include <cstdio>
28014be0bfSNan Zhou #include <cstdlib>
29014be0bfSNan Zhou #include <exception>
30014be0bfSNan Zhou #include <filesystem>
316ceec40bSMarri Devender Rao #include <fstream>
32014be0bfSNan Zhou #include <map>
33014be0bfSNan Zhou #include <utility>
34014be0bfSNan Zhou #include <vector>
3513bf74e4SMarri Devender Rao
36e1289adfSNan Zhou namespace phosphor::certs
376ceec40bSMarri Devender Rao {
38cf06ccdcSNan Zhou
39cf06ccdcSNan Zhou namespace
40cf06ccdcSNan Zhou {
41cf06ccdcSNan Zhou namespace fs = std::filesystem;
42cf06ccdcSNan Zhou using ::phosphor::logging::elog;
43cf06ccdcSNan Zhou using InvalidCertificateError =
44cf06ccdcSNan Zhou ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
45cf06ccdcSNan Zhou using ::phosphor::logging::xyz::openbmc_project::Certs::InvalidCertificate;
46cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
47cf06ccdcSNan Zhou
486ceec40bSMarri Devender Rao // RAII support for openSSL functions.
49cf06ccdcSNan Zhou using BIOMemPtr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
50cf06ccdcSNan Zhou using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>;
51cf06ccdcSNan Zhou using ASN1TimePtr = std::unique_ptr<ASN1_TIME, decltype(&ASN1_STRING_free)>;
52cf06ccdcSNan Zhou using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
53cf06ccdcSNan Zhou using BufMemPtr = std::unique_ptr<BUF_MEM, decltype(&::BUF_MEM_free)>;
546ceec40bSMarri Devender Rao
5536f25142SDhruvaraj Subhashchandran // Refer to schema 2018.3
5636f25142SDhruvaraj Subhashchandran // http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for
5736f25142SDhruvaraj Subhashchandran // supported KeyUsage types in redfish
5836f25142SDhruvaraj Subhashchandran // Refer to
5936f25142SDhruvaraj Subhashchandran // https://github.com/openssl/openssl/blob/master/include/openssl/x509v3.h for
6036f25142SDhruvaraj Subhashchandran // key usage bit fields
6136f25142SDhruvaraj Subhashchandran std::map<uint8_t, std::string> keyUsageToRfStr = {
6236f25142SDhruvaraj Subhashchandran {KU_DIGITAL_SIGNATURE, "DigitalSignature"},
6336f25142SDhruvaraj Subhashchandran {KU_NON_REPUDIATION, "NonRepudiation"},
6436f25142SDhruvaraj Subhashchandran {KU_KEY_ENCIPHERMENT, "KeyEncipherment"},
6536f25142SDhruvaraj Subhashchandran {KU_DATA_ENCIPHERMENT, "DataEncipherment"},
6636f25142SDhruvaraj Subhashchandran {KU_KEY_AGREEMENT, "KeyAgreement"},
6736f25142SDhruvaraj Subhashchandran {KU_KEY_CERT_SIGN, "KeyCertSign"},
6836f25142SDhruvaraj Subhashchandran {KU_CRL_SIGN, "CRLSigning"},
6936f25142SDhruvaraj Subhashchandran {KU_ENCIPHER_ONLY, "EncipherOnly"},
7036f25142SDhruvaraj Subhashchandran {KU_DECIPHER_ONLY, "DecipherOnly"}};
7136f25142SDhruvaraj Subhashchandran
7236f25142SDhruvaraj Subhashchandran // Refer to schema 2018.3
7336f25142SDhruvaraj Subhashchandran // http://redfish.dmtf.org/schemas/v1/Certificate.json#/definitions/KeyUsage for
7436f25142SDhruvaraj Subhashchandran // supported Extended KeyUsage types in redfish
7536f25142SDhruvaraj Subhashchandran std::map<uint8_t, std::string> extendedKeyUsageToRfStr = {
7636f25142SDhruvaraj Subhashchandran {NID_server_auth, "ServerAuthentication"},
7736f25142SDhruvaraj Subhashchandran {NID_client_auth, "ClientAuthentication"},
7836f25142SDhruvaraj Subhashchandran {NID_email_protect, "EmailProtection"},
7936f25142SDhruvaraj Subhashchandran {NID_OCSP_sign, "OCSPSigning"},
8036f25142SDhruvaraj Subhashchandran {NID_ad_timeStamping, "Timestamping"},
8136f25142SDhruvaraj Subhashchandran {NID_code_sign, "CodeSigning"}};
8236f25142SDhruvaraj Subhashchandran
83e869bb63SNan Zhou /**
846ec13c8fSNan Zhou * @brief Dumps the PEM encoded certificate to installFilePath
85e869bb63SNan Zhou *
866ec13c8fSNan Zhou * @param[in] pem - PEM encoded X509 certificate buffer.
876ec13c8fSNan Zhou * @param[in] certFilePath - Path to the destination file.
88e869bb63SNan Zhou *
89e869bb63SNan Zhou * @return void
90e869bb63SNan Zhou */
916ec13c8fSNan Zhou
dumpCertificate(const std::string & pem,const std::string & certFilePath)926ec13c8fSNan Zhou void dumpCertificate(const std::string& pem, const std::string& certFilePath)
936ec13c8fSNan Zhou {
946ec13c8fSNan Zhou std::ofstream outputCertFileStream;
956ec13c8fSNan Zhou
966ec13c8fSNan Zhou outputCertFileStream.exceptions(
976ec13c8fSNan Zhou std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
986ec13c8fSNan Zhou
996ec13c8fSNan Zhou try
1006ec13c8fSNan Zhou {
1016ec13c8fSNan Zhou outputCertFileStream.open(certFilePath, std::ios::out);
1026ec13c8fSNan Zhou outputCertFileStream << pem << "\n" << std::flush;
1036ec13c8fSNan Zhou outputCertFileStream.close();
1046ec13c8fSNan Zhou }
1056ec13c8fSNan Zhou catch (const std::exception& e)
1066ec13c8fSNan Zhou {
107f2646271SRavi Teja lg2::error(
108f2646271SRavi Teja "Failed to dump certificate, ERR:{ERR}, SRC_PEM:{SRC_PEM}, DST:{DST}",
109f2646271SRavi Teja "ERR", e, "SRC_PEM", pem, "DST", certFilePath);
1106ec13c8fSNan Zhou elog<InternalFailure>();
1116ec13c8fSNan Zhou }
1126ec13c8fSNan Zhou }
1136ec13c8fSNan Zhou } // namespace
1146ec13c8fSNan Zhou
copyCertificate(const std::string & certSrcFilePath,const std::string & certFilePath)1156ec13c8fSNan Zhou void Certificate::copyCertificate(const std::string& certSrcFilePath,
116e869bb63SNan Zhou const std::string& certFilePath)
117db029c95SKowalski, Kamil {
118f44a39cfSJayanth Othayoth try
119f44a39cfSJayanth Othayoth {
120e869bb63SNan Zhou // Copy the certificate to the installation path
121e869bb63SNan Zhou // During bootup will be parsing existing file so no need to
122e869bb63SNan Zhou // copy it.
123e869bb63SNan Zhou if (certSrcFilePath != certFilePath)
124e869bb63SNan Zhou {
125f44a39cfSJayanth Othayoth fs::copy(certSrcFilePath, certFilePath,
126f44a39cfSJayanth Othayoth fs::copy_options::overwrite_existing);
127f44a39cfSJayanth Othayoth }
128f44a39cfSJayanth Othayoth }
129f44a39cfSJayanth Othayoth catch (const fs::filesystem_error& e)
130e869bb63SNan Zhou {
131f2646271SRavi Teja lg2::error(
132f2646271SRavi Teja "Failed to copy certificate, ERR:{ERR}, SRC:{SRC}, DST:{DST}",
133f44a39cfSJayanth Othayoth "ERR", e.what(), "SRC", certSrcFilePath, "DST", certFilePath);
134e869bb63SNan Zhou elog<InternalFailure>();
135e869bb63SNan Zhou }
136e869bb63SNan Zhou }
1372f3563ccSZbigniew Lukwinski
1382f3563ccSZbigniew Lukwinski std::string
generateUniqueFilePath(const std::string & directoryPath)1392f3563ccSZbigniew Lukwinski Certificate::generateUniqueFilePath(const std::string& directoryPath)
1402f3563ccSZbigniew Lukwinski {
141*b6274297SMilton D. Miller II char* filePath = tempnam(directoryPath.c_str(), nullptr);
142*b6274297SMilton D. Miller II if (filePath == nullptr)
1432f3563ccSZbigniew Lukwinski {
144f2646271SRavi Teja lg2::error(
145f2646271SRavi Teja "Error occurred while creating random certificate file path, DIR:{DIR}",
146f2646271SRavi Teja "DIR", directoryPath);
1472f3563ccSZbigniew Lukwinski elog<InternalFailure>();
1482f3563ccSZbigniew Lukwinski }
149*b6274297SMilton D. Miller II std::string filePathStr(filePath);
150*b6274297SMilton D. Miller II free(filePath);
151*b6274297SMilton D. Miller II return filePathStr;
1522f3563ccSZbigniew Lukwinski }
1532f3563ccSZbigniew Lukwinski
generateAuthCertFileX509Path(const std::string & certSrcFilePath,const std::string & certDstDirPath)1542f3563ccSZbigniew Lukwinski std::string Certificate::generateAuthCertFileX509Path(
1552f3563ccSZbigniew Lukwinski const std::string& certSrcFilePath, const std::string& certDstDirPath)
1562f3563ccSZbigniew Lukwinski {
157cf06ccdcSNan Zhou const internal::X509Ptr cert = loadCert(certSrcFilePath);
158db029c95SKowalski, Kamil unsigned long hash = X509_subject_name_hash(cert.get());
159e3d47cd4SNan Zhou static constexpr auto certHashLength = 9;
160e3d47cd4SNan Zhou char hashBuf[certHashLength];
161db029c95SKowalski, Kamil
162e3d47cd4SNan Zhou snprintf(hashBuf, certHashLength, "%08lx", hash);
163db029c95SKowalski, Kamil
1642f3563ccSZbigniew Lukwinski const std::string certHash(hashBuf);
165718eef37SNan Zhou for (size_t i = 0; i < maxNumAuthorityCertificates; ++i)
1662f3563ccSZbigniew Lukwinski {
16773d1fbf3SZbigniew Lukwinski const std::string certDstFileX509Path =
16873d1fbf3SZbigniew Lukwinski certDstDirPath + "/" + certHash + "." + std::to_string(i);
16973d1fbf3SZbigniew Lukwinski if (!fs::exists(certDstFileX509Path))
17073d1fbf3SZbigniew Lukwinski {
17173d1fbf3SZbigniew Lukwinski return certDstFileX509Path;
17273d1fbf3SZbigniew Lukwinski }
1732f3563ccSZbigniew Lukwinski }
174db029c95SKowalski, Kamil
175f2646271SRavi Teja lg2::error("Authority certificate x509 file path already used, DIR:{DIR}",
176f2646271SRavi Teja "DIR", certDstDirPath);
17773d1fbf3SZbigniew Lukwinski elog<InternalFailure>();
1782f3563ccSZbigniew Lukwinski }
1792f3563ccSZbigniew Lukwinski
1802f3563ccSZbigniew Lukwinski std::string
generateAuthCertFilePath(const std::string & certSrcFilePath)1812f3563ccSZbigniew Lukwinski Certificate::generateAuthCertFilePath(const std::string& certSrcFilePath)
1822f3563ccSZbigniew Lukwinski {
1832f3563ccSZbigniew Lukwinski // If there is a certificate file path (which means certificate replacement
1842f3563ccSZbigniew Lukwinski // is doing) use it (do not create new one)
1852f3563ccSZbigniew Lukwinski if (!certFilePath.empty())
1862f3563ccSZbigniew Lukwinski {
1872f3563ccSZbigniew Lukwinski return certFilePath;
1882f3563ccSZbigniew Lukwinski }
1892f3563ccSZbigniew Lukwinski // If source certificate file is located in the certificates directory use
1902f3563ccSZbigniew Lukwinski // it (do not create new one)
1912f3563ccSZbigniew Lukwinski else if (fs::path(certSrcFilePath).parent_path().string() ==
1922f3563ccSZbigniew Lukwinski certInstallPath)
1932f3563ccSZbigniew Lukwinski {
1942f3563ccSZbigniew Lukwinski return certSrcFilePath;
1952f3563ccSZbigniew Lukwinski }
1962f3563ccSZbigniew Lukwinski // Otherwise generate new file name/path
1972f3563ccSZbigniew Lukwinski else
1982f3563ccSZbigniew Lukwinski {
1992f3563ccSZbigniew Lukwinski return generateUniqueFilePath(certInstallPath);
2002f3563ccSZbigniew Lukwinski }
2012f3563ccSZbigniew Lukwinski }
2022f3563ccSZbigniew Lukwinski
2032f3563ccSZbigniew Lukwinski std::string
generateCertFilePath(const std::string & certSrcFilePath)2042f3563ccSZbigniew Lukwinski Certificate::generateCertFilePath(const std::string& certSrcFilePath)
2052f3563ccSZbigniew Lukwinski {
206e3d47cd4SNan Zhou if (certType == CertificateType::authority)
2072f3563ccSZbigniew Lukwinski {
2082f3563ccSZbigniew Lukwinski return generateAuthCertFilePath(certSrcFilePath);
2092f3563ccSZbigniew Lukwinski }
2102f3563ccSZbigniew Lukwinski else
2112f3563ccSZbigniew Lukwinski {
2122f3563ccSZbigniew Lukwinski return certInstallPath;
2132f3563ccSZbigniew Lukwinski }
214db029c95SKowalski, Kamil }
215db029c95SKowalski, Kamil
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)216b3dbfb37SPatrick Williams Certificate::Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
217cf06ccdcSNan Zhou CertificateType type, const std::string& installPath,
218cf06ccdcSNan Zhou const std::string& uploadPath, Watch* watch,
219698a5743SWilly Tu Manager& parent, bool restore) :
220ebd21ba4SPatrick Williams internal::CertificateInterface(
221ebd21ba4SPatrick Williams bus, objPath.c_str(),
222ebd21ba4SPatrick Williams internal::CertificateInterface::action::defer_emit),
223cf06ccdcSNan Zhou objectPath(objPath), certType(type), certInstallPath(installPath),
224cf06ccdcSNan Zhou certWatch(watch), manager(parent)
2256ceec40bSMarri Devender Rao {
2266ceec40bSMarri Devender Rao auto installHelper = [this](const auto& filePath) {
2276ceec40bSMarri Devender Rao if (!compareKeys(filePath))
2286ceec40bSMarri Devender Rao {
229cf06ccdcSNan Zhou elog<InvalidCertificateError>(InvalidCertificate::REASON(
230cf06ccdcSNan Zhou "Private key does not match the Certificate"));
2316ceec40bSMarri Devender Rao };
2326ceec40bSMarri Devender Rao };
233e3d47cd4SNan Zhou typeFuncMap[CertificateType::server] = installHelper;
234e3d47cd4SNan Zhou typeFuncMap[CertificateType::client] = installHelper;
235e3d47cd4SNan Zhou typeFuncMap[CertificateType::authority] = [](const std::string&) {};
236cd30c496SMarri Devender Rao
237cd30c496SMarri Devender Rao auto appendPrivateKey = [this](const std::string& filePath) {
238cd30c496SMarri Devender Rao checkAndAppendPrivateKey(filePath);
239cd30c496SMarri Devender Rao };
240cd30c496SMarri Devender Rao
241e3d47cd4SNan Zhou appendKeyMap[CertificateType::server] = appendPrivateKey;
242e3d47cd4SNan Zhou appendKeyMap[CertificateType::client] = appendPrivateKey;
243e3d47cd4SNan Zhou appendKeyMap[CertificateType::authority] = [](const std::string&) {};
244cd30c496SMarri Devender Rao
2452f3563ccSZbigniew Lukwinski // Generate certificate file path
2462f3563ccSZbigniew Lukwinski certFilePath = generateCertFilePath(uploadPath);
2472f3563ccSZbigniew Lukwinski
248cd30c496SMarri Devender Rao // install the certificate
249698a5743SWilly Tu install(uploadPath, restore);
250cd30c496SMarri Devender Rao
251edd1131cSMarri Devender Rao this->emit_object_added();
2526ceec40bSMarri Devender Rao }
2536ceec40bSMarri Devender Rao
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)254b3dbfb37SPatrick Williams Certificate::Certificate(sdbusplus::bus_t& bus, const std::string& objPath,
2556ec13c8fSNan Zhou const CertificateType& type,
2566ec13c8fSNan Zhou const std::string& installPath, X509_STORE& x509Store,
2576ec13c8fSNan Zhou const std::string& pem, Watch* watchPtr,
258698a5743SWilly Tu Manager& parent, bool restore) :
259ebd21ba4SPatrick Williams internal::CertificateInterface(
260ebd21ba4SPatrick Williams bus, objPath.c_str(),
261ebd21ba4SPatrick Williams internal::CertificateInterface::action::defer_emit),
2626ec13c8fSNan Zhou objectPath(objPath), certType(type), certInstallPath(installPath),
2636ec13c8fSNan Zhou certWatch(watchPtr), manager(parent)
2646ec13c8fSNan Zhou {
2656ec13c8fSNan Zhou // Generate certificate file path
2666ec13c8fSNan Zhou certFilePath = generateUniqueFilePath(installPath);
2676ec13c8fSNan Zhou
2686ec13c8fSNan Zhou // install the certificate
269698a5743SWilly Tu install(x509Store, pem, restore);
2706ec13c8fSNan Zhou
2716ec13c8fSNan Zhou this->emit_object_added();
2726ec13c8fSNan Zhou }
2736ec13c8fSNan Zhou
~Certificate()2746ceec40bSMarri Devender Rao Certificate::~Certificate()
2756ceec40bSMarri Devender Rao {
2762f3563ccSZbigniew Lukwinski if (!fs::remove(certFilePath))
2776ceec40bSMarri Devender Rao {
278f2646271SRavi Teja lg2::info("Certificate file not found! PATH:{PATH}", "PATH",
279f2646271SRavi Teja certFilePath);
2806ceec40bSMarri Devender Rao }
2816ceec40bSMarri Devender Rao }
2826ceec40bSMarri Devender Rao
replace(const std::string filePath)28313bf74e4SMarri Devender Rao void Certificate::replace(const std::string filePath)
28413bf74e4SMarri Devender Rao {
2852f3563ccSZbigniew Lukwinski manager.replaceCertificate(this, filePath);
28613bf74e4SMarri Devender Rao }
28713bf74e4SMarri Devender Rao
install(const std::string & certSrcFilePath,bool restore)288698a5743SWilly Tu void Certificate::install(const std::string& certSrcFilePath, bool restore)
289698a5743SWilly Tu {
290698a5743SWilly Tu if (restore)
291698a5743SWilly Tu {
292f2646271SRavi Teja lg2::debug("Certificate install, FILEPATH:{FILEPATH}", "FILEPATH",
293f2646271SRavi Teja certSrcFilePath);
294698a5743SWilly Tu }
295698a5743SWilly Tu else
2966ceec40bSMarri Devender Rao {
297f2646271SRavi Teja lg2::info("Certificate install, FILEPATH:{FILEPATH}", "FILEPATH",
298f2646271SRavi Teja certSrcFilePath);
299698a5743SWilly Tu }
3006ceec40bSMarri Devender Rao
301ffad1ef1SMarri Devender Rao // stop watch for user initiated certificate install
302cf06ccdcSNan Zhou if (certWatch != nullptr)
303ffad1ef1SMarri Devender Rao {
304cf06ccdcSNan Zhou certWatch->stopWatch();
305ffad1ef1SMarri Devender Rao }
306ffad1ef1SMarri Devender Rao
3076ceec40bSMarri Devender Rao // Verify the certificate file
3082f3563ccSZbigniew Lukwinski fs::path file(certSrcFilePath);
3096ceec40bSMarri Devender Rao if (!fs::exists(file))
3106ceec40bSMarri Devender Rao {
311f2646271SRavi Teja lg2::error("File is Missing, FILE:{FILE}", "FILE", certSrcFilePath);
3126ceec40bSMarri Devender Rao elog<InternalFailure>();
3136ceec40bSMarri Devender Rao }
3146ceec40bSMarri Devender Rao
3156ceec40bSMarri Devender Rao try
3166ceec40bSMarri Devender Rao {
3172f3563ccSZbigniew Lukwinski if (fs::file_size(certSrcFilePath) == 0)
3186ceec40bSMarri Devender Rao {
3196ceec40bSMarri Devender Rao // file is empty
320f2646271SRavi Teja lg2::error("File is empty, FILE:{FILE}", "FILE", certSrcFilePath);
321cf06ccdcSNan Zhou elog<InvalidCertificateError>(
322cf06ccdcSNan Zhou InvalidCertificate::REASON("File is empty"));
3236ceec40bSMarri Devender Rao }
3246ceec40bSMarri Devender Rao }
3256ceec40bSMarri Devender Rao catch (const fs::filesystem_error& e)
3266ceec40bSMarri Devender Rao {
3276ceec40bSMarri Devender Rao // Log Error message
328f2646271SRavi Teja lg2::error("File is empty, FILE:{FILE}, ERR:{ERR}", "FILE",
329f2646271SRavi Teja certSrcFilePath, "ERR", e);
3306ceec40bSMarri Devender Rao elog<InternalFailure>();
3316ceec40bSMarri Devender Rao }
3326ceec40bSMarri Devender Rao
333e869bb63SNan Zhou X509StorePtr x509Store = getX509Store(certSrcFilePath);
3346ceec40bSMarri Devender Rao
335bf3cf751SNan Zhou // Load Certificate file into the X509 structure.
336cf06ccdcSNan Zhou internal::X509Ptr cert = loadCert(certSrcFilePath);
337e869bb63SNan Zhou
338e869bb63SNan Zhou // Perform validation
339e869bb63SNan Zhou validateCertificateAgainstStore(*x509Store, *cert);
340e869bb63SNan Zhou validateCertificateStartDate(*cert);
341e869bb63SNan Zhou validateCertificateInSSLContext(*cert);
342e869bb63SNan Zhou
343e869bb63SNan Zhou // Invoke type specific append private key function.
344e869bb63SNan Zhou if (auto it = appendKeyMap.find(certType); it == appendKeyMap.end())
3456ceec40bSMarri Devender Rao {
346f2646271SRavi Teja lg2::error("Unsupported Type, TYPE:{TYPE}", "TYPE",
347f2646271SRavi Teja certificateTypeToString(certType));
3486ceec40bSMarri Devender Rao elog<InternalFailure>();
3496ceec40bSMarri Devender Rao }
3506ceec40bSMarri Devender Rao else
3516ceec40bSMarri Devender Rao {
352e869bb63SNan Zhou it->second(certSrcFilePath);
3536ceec40bSMarri Devender Rao }
3546ceec40bSMarri Devender Rao
355cd30c496SMarri Devender Rao // Invoke type specific compare keys function.
356e869bb63SNan Zhou if (auto it = typeFuncMap.find(certType); it == typeFuncMap.end())
357cd30c496SMarri Devender Rao {
358f2646271SRavi Teja lg2::error("Unsupported Type, TYPE:{TYPE}", "TYPE",
359f2646271SRavi Teja certificateTypeToString(certType));
360cd30c496SMarri Devender Rao elog<InternalFailure>();
361cd30c496SMarri Devender Rao }
362e869bb63SNan Zhou else
3636ceec40bSMarri Devender Rao {
364e869bb63SNan Zhou it->second(certSrcFilePath);
365ffad1ef1SMarri Devender Rao }
3668f80c35bSMarri Devender Rao
367e869bb63SNan Zhou copyCertificate(certSrcFilePath, certFilePath);
3682f3563ccSZbigniew Lukwinski storageUpdate();
36936f25142SDhruvaraj Subhashchandran
3702f3563ccSZbigniew Lukwinski // Keep certificate ID
371e869bb63SNan Zhou certId = generateCertId(*cert);
372db029c95SKowalski, Kamil
37336f25142SDhruvaraj Subhashchandran // Parse the certificate file and populate properties
374e869bb63SNan Zhou populateProperties(*cert);
375ffad1ef1SMarri Devender Rao
376ffad1ef1SMarri Devender Rao // restart watch
377cf06ccdcSNan Zhou if (certWatch != nullptr)
378ffad1ef1SMarri Devender Rao {
379cf06ccdcSNan Zhou certWatch->startWatch();
380ffad1ef1SMarri Devender Rao }
38136f25142SDhruvaraj Subhashchandran }
38236f25142SDhruvaraj Subhashchandran
install(X509_STORE & x509Store,const std::string & pem,bool restore)383698a5743SWilly Tu void Certificate::install(X509_STORE& x509Store, const std::string& pem,
384698a5743SWilly Tu bool restore)
3856ec13c8fSNan Zhou {
386698a5743SWilly Tu if (restore)
387698a5743SWilly Tu {
388f2646271SRavi Teja lg2::debug("Certificate install, PEM_STR:{PEM_STR}", "PEM_STR", pem);
389698a5743SWilly Tu }
390698a5743SWilly Tu else
391698a5743SWilly Tu {
392f2646271SRavi Teja lg2::info("Certificate install, PEM_STR:{PEM_STR} ", "PEM_STR", pem);
393698a5743SWilly Tu }
3946ec13c8fSNan Zhou
395e3d47cd4SNan Zhou if (certType != CertificateType::authority)
3966ec13c8fSNan Zhou {
397f2646271SRavi Teja lg2::error("Bulk install error: Unsupported Type; only authority "
398f2646271SRavi Teja "supports bulk install, TYPE:{TYPE}",
399f2646271SRavi Teja "TYPE", certificateTypeToString(certType));
4006ec13c8fSNan Zhou elog<InternalFailure>();
4016ec13c8fSNan Zhou }
4026ec13c8fSNan Zhou
4036ec13c8fSNan Zhou // stop watch for user initiated certificate install
4046ec13c8fSNan Zhou if (certWatch)
4056ec13c8fSNan Zhou {
4066ec13c8fSNan Zhou certWatch->stopWatch();
4076ec13c8fSNan Zhou }
4086ec13c8fSNan Zhou
4096ec13c8fSNan Zhou // Load Certificate file into the X509 structure.
4106ec13c8fSNan Zhou internal::X509Ptr cert = parseCert(pem);
4116ec13c8fSNan Zhou // Perform validation; no type specific compare keys function
4126ec13c8fSNan Zhou validateCertificateAgainstStore(x509Store, *cert);
4136ec13c8fSNan Zhou validateCertificateStartDate(*cert);
4146ec13c8fSNan Zhou validateCertificateInSSLContext(*cert);
4156ec13c8fSNan Zhou
4166ec13c8fSNan Zhou // Copy the PEM to the installation path
4176ec13c8fSNan Zhou dumpCertificate(pem, certFilePath);
4186ec13c8fSNan Zhou storageUpdate();
4196ec13c8fSNan Zhou // Keep certificate ID
4206ec13c8fSNan Zhou certId = generateCertId(*cert);
4216ec13c8fSNan Zhou // Parse the certificate file and populate properties
4226ec13c8fSNan Zhou populateProperties(*cert);
4236ec13c8fSNan Zhou // restart watch
4246ec13c8fSNan Zhou if (certWatch)
4256ec13c8fSNan Zhou {
4266ec13c8fSNan Zhou certWatch->startWatch();
4276ec13c8fSNan Zhou }
4286ec13c8fSNan Zhou }
4296ec13c8fSNan Zhou
populateProperties()43036f25142SDhruvaraj Subhashchandran void Certificate::populateProperties()
43136f25142SDhruvaraj Subhashchandran {
432e869bb63SNan Zhou internal::X509Ptr cert = loadCert(certInstallPath);
433e869bb63SNan Zhou populateProperties(*cert);
434db029c95SKowalski, Kamil }
435db029c95SKowalski, Kamil
getCertId() const4362f3563ccSZbigniew Lukwinski std::string Certificate::getCertId() const
437db029c95SKowalski, Kamil {
4382f3563ccSZbigniew Lukwinski return certId;
4392f3563ccSZbigniew Lukwinski }
4402f3563ccSZbigniew Lukwinski
isSame(const std::string & certPath)4412f3563ccSZbigniew Lukwinski bool Certificate::isSame(const std::string& certPath)
4422f3563ccSZbigniew Lukwinski {
443e869bb63SNan Zhou internal::X509Ptr cert = loadCert(certPath);
444e869bb63SNan Zhou return getCertId() == generateCertId(*cert);
4452f3563ccSZbigniew Lukwinski }
4462f3563ccSZbigniew Lukwinski
storageUpdate()4472f3563ccSZbigniew Lukwinski void Certificate::storageUpdate()
4482f3563ccSZbigniew Lukwinski {
449e3d47cd4SNan Zhou if (certType == CertificateType::authority)
4502f3563ccSZbigniew Lukwinski {
4512f3563ccSZbigniew Lukwinski // Create symbolic link in the certificate directory
4522f3563ccSZbigniew Lukwinski std::string certFileX509Path;
4532f3563ccSZbigniew Lukwinski try
4542f3563ccSZbigniew Lukwinski {
4552f3563ccSZbigniew Lukwinski if (!certFilePath.empty() &&
4562f3563ccSZbigniew Lukwinski fs::is_regular_file(fs::path(certFilePath)))
4572f3563ccSZbigniew Lukwinski {
4582f3563ccSZbigniew Lukwinski certFileX509Path =
4592f3563ccSZbigniew Lukwinski generateAuthCertFileX509Path(certFilePath, certInstallPath);
4602f3563ccSZbigniew Lukwinski fs::create_symlink(fs::path(certFilePath),
4612f3563ccSZbigniew Lukwinski fs::path(certFileX509Path));
4622f3563ccSZbigniew Lukwinski }
4632f3563ccSZbigniew Lukwinski }
4642f3563ccSZbigniew Lukwinski catch (const std::exception& e)
4652f3563ccSZbigniew Lukwinski {
466f2646271SRavi Teja lg2::error("Failed to create symlink for certificate, ERR:{ERR},"
467f2646271SRavi Teja "FILE:{FILE}, SYMLINK:{SYMLINK}",
468f2646271SRavi Teja "ERR", e, "FILE", certFilePath, "SYMLINK",
469f2646271SRavi Teja certFileX509Path);
4702f3563ccSZbigniew Lukwinski elog<InternalFailure>();
4712f3563ccSZbigniew Lukwinski }
4722f3563ccSZbigniew Lukwinski }
473db029c95SKowalski, Kamil }
474db029c95SKowalski, Kamil
populateProperties(X509 & cert)475e869bb63SNan Zhou void Certificate::populateProperties(X509& cert)
476db029c95SKowalski, Kamil {
47736f25142SDhruvaraj Subhashchandran // Update properties if no error thrown
478cf06ccdcSNan Zhou BIOMemPtr certBio(BIO_new(BIO_s_mem()), BIO_free);
479e869bb63SNan Zhou PEM_write_bio_X509(certBio.get(), &cert);
480cf06ccdcSNan Zhou BufMemPtr certBuf(BUF_MEM_new(), BUF_MEM_free);
48136f25142SDhruvaraj Subhashchandran BUF_MEM* buf = certBuf.get();
48236f25142SDhruvaraj Subhashchandran BIO_get_mem_ptr(certBio.get(), &buf);
48336f25142SDhruvaraj Subhashchandran std::string certStr(buf->data, buf->length);
484cf06ccdcSNan Zhou certificateString(certStr);
48536f25142SDhruvaraj Subhashchandran
48636f25142SDhruvaraj Subhashchandran static const int maxKeySize = 4096;
48736f25142SDhruvaraj Subhashchandran char subBuffer[maxKeySize] = {0};
488cf06ccdcSNan Zhou BIOMemPtr subBio(BIO_new(BIO_s_mem()), BIO_free);
4895d4f7932SManojkiran Eda // This pointer cannot be freed independently.
490e869bb63SNan Zhou X509_NAME* sub = X509_get_subject_name(&cert);
491dec5877cSMarri Devender Rao X509_NAME_print_ex(subBio.get(), sub, 0, XN_FLAG_SEP_COMMA_PLUS);
492dec5877cSMarri Devender Rao BIO_read(subBio.get(), subBuffer, maxKeySize);
493cf06ccdcSNan Zhou subject(subBuffer);
49436f25142SDhruvaraj Subhashchandran
49536f25142SDhruvaraj Subhashchandran char issuerBuffer[maxKeySize] = {0};
496cf06ccdcSNan Zhou BIOMemPtr issuerBio(BIO_new(BIO_s_mem()), BIO_free);
4975d4f7932SManojkiran Eda // This pointer cannot be freed independently.
498e3d47cd4SNan Zhou X509_NAME* issuerName = X509_get_issuer_name(&cert);
499e3d47cd4SNan Zhou X509_NAME_print_ex(issuerBio.get(), issuerName, 0, XN_FLAG_SEP_COMMA_PLUS);
500dec5877cSMarri Devender Rao BIO_read(issuerBio.get(), issuerBuffer, maxKeySize);
501cf06ccdcSNan Zhou issuer(issuerBuffer);
50236f25142SDhruvaraj Subhashchandran
50336f25142SDhruvaraj Subhashchandran std::vector<std::string> keyUsageList;
50436f25142SDhruvaraj Subhashchandran
50536f25142SDhruvaraj Subhashchandran // Go through each usage in the bit string and convert to
50636f25142SDhruvaraj Subhashchandran // corresponding string value
507cb1ee9dcSJayanth Othayoth ASN1_BIT_STRING* usage = static_cast<ASN1_BIT_STRING*>(
508cb1ee9dcSJayanth Othayoth X509_get_ext_d2i(&cert, NID_key_usage, nullptr, nullptr));
509cb1ee9dcSJayanth Othayoth if (usage != nullptr)
51036f25142SDhruvaraj Subhashchandran {
51136f25142SDhruvaraj Subhashchandran for (auto i = 0; i < usage->length; ++i)
51236f25142SDhruvaraj Subhashchandran {
51336f25142SDhruvaraj Subhashchandran for (auto& x : keyUsageToRfStr)
51436f25142SDhruvaraj Subhashchandran {
51536f25142SDhruvaraj Subhashchandran if (x.first & usage->data[i])
51636f25142SDhruvaraj Subhashchandran {
51736f25142SDhruvaraj Subhashchandran keyUsageList.push_back(x.second);
51836f25142SDhruvaraj Subhashchandran break;
51936f25142SDhruvaraj Subhashchandran }
52036f25142SDhruvaraj Subhashchandran }
52136f25142SDhruvaraj Subhashchandran }
52236f25142SDhruvaraj Subhashchandran }
52336f25142SDhruvaraj Subhashchandran
524cb1ee9dcSJayanth Othayoth EXTENDED_KEY_USAGE* extUsage = static_cast<EXTENDED_KEY_USAGE*>(
525cb1ee9dcSJayanth Othayoth X509_get_ext_d2i(&cert, NID_ext_key_usage, nullptr, nullptr));
526cb1ee9dcSJayanth Othayoth if (extUsage == nullptr)
52736f25142SDhruvaraj Subhashchandran {
52836f25142SDhruvaraj Subhashchandran for (int i = 0; i < sk_ASN1_OBJECT_num(extUsage); i++)
52936f25142SDhruvaraj Subhashchandran {
53036f25142SDhruvaraj Subhashchandran keyUsageList.push_back(extendedKeyUsageToRfStr[OBJ_obj2nid(
53136f25142SDhruvaraj Subhashchandran sk_ASN1_OBJECT_value(extUsage, i))]);
53236f25142SDhruvaraj Subhashchandran }
53336f25142SDhruvaraj Subhashchandran }
534cf06ccdcSNan Zhou keyUsage(keyUsageList);
53536f25142SDhruvaraj Subhashchandran
53636f25142SDhruvaraj Subhashchandran int days = 0;
53736f25142SDhruvaraj Subhashchandran int secs = 0;
53836f25142SDhruvaraj Subhashchandran
539cf06ccdcSNan Zhou ASN1TimePtr epoch(ASN1_TIME_new(), ASN1_STRING_free);
540cf811c43SNan Zhou // Set time to 00:00am GMT, Jan 1 1970; format: YYYYMMDDHHMMSSZ
541cf811c43SNan Zhou ASN1_TIME_set_string(epoch.get(), "19700101000000Z");
54236f25142SDhruvaraj Subhashchandran
5438a59ea28SJayanth Othayoth constexpr uint64_t dayToSeconds = 86400; // 24 * 60 * 60
544e869bb63SNan Zhou ASN1_TIME* notAfter = X509_get_notAfter(&cert);
54536f25142SDhruvaraj Subhashchandran ASN1_TIME_diff(&days, &secs, epoch.get(), notAfter);
546cf06ccdcSNan Zhou validNotAfter((days * dayToSeconds) + secs);
54736f25142SDhruvaraj Subhashchandran
548e869bb63SNan Zhou ASN1_TIME* notBefore = X509_get_notBefore(&cert);
54936f25142SDhruvaraj Subhashchandran ASN1_TIME_diff(&days, &secs, epoch.get(), notBefore);
550cf06ccdcSNan Zhou validNotBefore((days * dayToSeconds) + secs);
5516ceec40bSMarri Devender Rao }
5526ceec40bSMarri Devender Rao
checkAndAppendPrivateKey(const std::string & filePath)553cd30c496SMarri Devender Rao void Certificate::checkAndAppendPrivateKey(const std::string& filePath)
554cd30c496SMarri Devender Rao {
555cf06ccdcSNan Zhou BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free);
556cd30c496SMarri Devender Rao if (!keyBio)
557cd30c496SMarri Devender Rao {
558f2646271SRavi Teja lg2::error("Error occurred during BIO_s_file call, FILE:{FILE}", "FILE",
559f2646271SRavi Teja filePath);
560cd30c496SMarri Devender Rao elog<InternalFailure>();
561cd30c496SMarri Devender Rao }
562cd30c496SMarri Devender Rao BIO_read_filename(keyBio.get(), filePath.c_str());
563cd30c496SMarri Devender Rao
564cf06ccdcSNan Zhou EVPPkeyPtr priKey(
565cd30c496SMarri Devender Rao PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr),
566cd30c496SMarri Devender Rao ::EVP_PKEY_free);
567cd30c496SMarri Devender Rao if (!priKey)
568cd30c496SMarri Devender Rao {
569f2646271SRavi Teja lg2::info("Private key not present in file, FILE:{FILE}", "FILE",
570f2646271SRavi Teja filePath);
571cd30c496SMarri Devender Rao fs::path privateKeyFile = fs::path(certInstallPath).parent_path();
572718eef37SNan Zhou privateKeyFile = privateKeyFile / defaultPrivateKeyFileName;
573cd30c496SMarri Devender Rao if (!fs::exists(privateKeyFile))
574cd30c496SMarri Devender Rao {
575f2646271SRavi Teja lg2::error("Private key file is not found, FILE:{FILE}", "FILE",
576f2646271SRavi Teja privateKeyFile);
577cd30c496SMarri Devender Rao elog<InternalFailure>();
578cd30c496SMarri Devender Rao }
579cd30c496SMarri Devender Rao
580cd30c496SMarri Devender Rao std::ifstream privKeyFileStream;
581cd30c496SMarri Devender Rao std::ofstream certFileStream;
582a2f68d8bSPatrick Williams privKeyFileStream.exceptions(
583a2f68d8bSPatrick Williams std::ifstream::failbit | std::ifstream::badbit |
584cd30c496SMarri Devender Rao std::ifstream::eofbit);
585a2f68d8bSPatrick Williams certFileStream.exceptions(
586a2f68d8bSPatrick Williams std::ofstream::failbit | std::ofstream::badbit |
587cd30c496SMarri Devender Rao std::ofstream::eofbit);
588cd30c496SMarri Devender Rao try
589cd30c496SMarri Devender Rao {
590cd30c496SMarri Devender Rao privKeyFileStream.open(privateKeyFile);
591cd30c496SMarri Devender Rao certFileStream.open(filePath, std::ios::app);
59218e51c92SMarri Devender Rao certFileStream << std::endl; // insert line break
593cd30c496SMarri Devender Rao certFileStream << privKeyFileStream.rdbuf() << std::flush;
594cd30c496SMarri Devender Rao privKeyFileStream.close();
595cd30c496SMarri Devender Rao certFileStream.close();
596cd30c496SMarri Devender Rao }
597cd30c496SMarri Devender Rao catch (const std::exception& e)
598cd30c496SMarri Devender Rao {
599f2646271SRavi Teja lg2::error(
600f2646271SRavi Teja "Failed to append private key, ERR:{ERR}, SRC:{SRC}, DST:{DST}",
601f2646271SRavi Teja "ERR", e, "SRC", privateKeyFile, "DST", filePath);
602cd30c496SMarri Devender Rao elog<InternalFailure>();
603cd30c496SMarri Devender Rao }
604cd30c496SMarri Devender Rao }
605cd30c496SMarri Devender Rao }
606cd30c496SMarri Devender Rao
compareKeys(const std::string & filePath)6076ceec40bSMarri Devender Rao bool Certificate::compareKeys(const std::string& filePath)
6086ceec40bSMarri Devender Rao {
609f2646271SRavi Teja lg2::info("Certificate compareKeys, FILEPATH:{FILEPATH}", "FILEPATH",
610f2646271SRavi Teja filePath);
611cf06ccdcSNan Zhou internal::X509Ptr cert(X509_new(), ::X509_free);
6126ceec40bSMarri Devender Rao if (!cert)
6136ceec40bSMarri Devender Rao {
614f2646271SRavi Teja lg2::error(
615f2646271SRavi Teja "Error occurred during X509_new call, FILE:{FILE}, ERRCODE:{ERRCODE}",
616f2646271SRavi Teja "FILE", filePath, "ERRCODE", ERR_get_error());
6176ceec40bSMarri Devender Rao elog<InternalFailure>();
6186ceec40bSMarri Devender Rao }
6196ceec40bSMarri Devender Rao
620cf06ccdcSNan Zhou BIOMemPtr bioCert(BIO_new_file(filePath.c_str(), "rb"), ::BIO_free);
6216ceec40bSMarri Devender Rao if (!bioCert)
6226ceec40bSMarri Devender Rao {
623f2646271SRavi Teja lg2::error("Error occurred during BIO_new_file call, FILE:{FILE}",
624f2646271SRavi Teja "FILE", filePath);
6256ceec40bSMarri Devender Rao elog<InternalFailure>();
6266ceec40bSMarri Devender Rao }
6276ceec40bSMarri Devender Rao
6286ceec40bSMarri Devender Rao X509* x509 = cert.get();
6296ceec40bSMarri Devender Rao PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr);
6306ceec40bSMarri Devender Rao
631cf06ccdcSNan Zhou EVPPkeyPtr pubKey(X509_get_pubkey(cert.get()), ::EVP_PKEY_free);
6326ceec40bSMarri Devender Rao if (!pubKey)
6336ceec40bSMarri Devender Rao {
634f2646271SRavi Teja lg2::error(
635f2646271SRavi Teja "Error occurred during X509_get_pubkey, FILE:{FILE}, ERRCODE:{ERRCODE}",
636f2646271SRavi Teja "FILE", filePath, "ERRCODE", ERR_get_error());
637cf06ccdcSNan Zhou elog<InvalidCertificateError>(
638cf06ccdcSNan Zhou InvalidCertificate::REASON("Failed to get public key info"));
6396ceec40bSMarri Devender Rao }
6406ceec40bSMarri Devender Rao
641cf06ccdcSNan Zhou BIOMemPtr keyBio(BIO_new(BIO_s_file()), ::BIO_free);
6426ceec40bSMarri Devender Rao if (!keyBio)
6436ceec40bSMarri Devender Rao {
644f2646271SRavi Teja lg2::error("Error occurred during BIO_s_file call, FILE:{FILE}", "FILE",
645f2646271SRavi Teja filePath);
6466ceec40bSMarri Devender Rao elog<InternalFailure>();
6476ceec40bSMarri Devender Rao }
6486ceec40bSMarri Devender Rao BIO_read_filename(keyBio.get(), filePath.c_str());
6496ceec40bSMarri Devender Rao
650cf06ccdcSNan Zhou EVPPkeyPtr priKey(
6516ceec40bSMarri Devender Rao PEM_read_bio_PrivateKey(keyBio.get(), nullptr, nullptr, nullptr),
6526ceec40bSMarri Devender Rao ::EVP_PKEY_free);
6536ceec40bSMarri Devender Rao if (!priKey)
6546ceec40bSMarri Devender Rao {
655f2646271SRavi Teja lg2::error(
656f2646271SRavi Teja "Error occurred during PEM_read_bio_PrivateKey, FILE:{FILE}, ERRCODE:{ERRCODE}",
657f2646271SRavi Teja "FILE", filePath, "ERRCODE", ERR_get_error());
658cf06ccdcSNan Zhou elog<InvalidCertificateError>(
659cf06ccdcSNan Zhou InvalidCertificate::REASON("Failed to get private key info"));
6606ceec40bSMarri Devender Rao }
6616ceec40bSMarri Devender Rao
66255ceaa2bSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L)
6636ceec40bSMarri Devender Rao int32_t rc = EVP_PKEY_cmp(priKey.get(), pubKey.get());
66455ceaa2bSPatrick Williams #else
66555ceaa2bSPatrick Williams int32_t rc = EVP_PKEY_eq(priKey.get(), pubKey.get());
66655ceaa2bSPatrick Williams #endif
6676ceec40bSMarri Devender Rao if (rc != 1)
6686ceec40bSMarri Devender Rao {
669f2646271SRavi Teja lg2::error(
670f2646271SRavi Teja "Private key is not matching with Certificate, FILE:{FILE}, ERRCODE:{ERRCODE}",
671f2646271SRavi Teja "FILE", filePath, "ERRCODE", rc);
6726ceec40bSMarri Devender Rao return false;
6736ceec40bSMarri Devender Rao }
6746ceec40bSMarri Devender Rao return true;
6756ceec40bSMarri Devender Rao }
6766ceec40bSMarri Devender Rao
delete_()677a3bb38fbSZbigniew Kurzynski void Certificate::delete_()
678a3bb38fbSZbigniew Kurzynski {
6792f3563ccSZbigniew Lukwinski manager.deleteCertificate(this);
680a3bb38fbSZbigniew Kurzynski }
6816ec13c8fSNan Zhou
getObjectPath()6826ec13c8fSNan Zhou std::string Certificate::getObjectPath()
6836ec13c8fSNan Zhou {
6846ec13c8fSNan Zhou return objectPath;
6856ec13c8fSNan Zhou }
6866ec13c8fSNan Zhou
getCertFilePath()6876ec13c8fSNan Zhou std::string Certificate::getCertFilePath()
6886ec13c8fSNan Zhou {
6896ec13c8fSNan Zhou return certFilePath;
6906ec13c8fSNan Zhou }
6916ec13c8fSNan Zhou
setCertFilePath(const std::string & path)6926ec13c8fSNan Zhou void Certificate::setCertFilePath(const std::string& path)
6936ec13c8fSNan Zhou {
6946ec13c8fSNan Zhou certFilePath = path;
6956ec13c8fSNan Zhou }
6966ec13c8fSNan Zhou
setCertInstallPath(const std::string & path)6976ec13c8fSNan Zhou void Certificate::setCertInstallPath(const std::string& path)
6986ec13c8fSNan Zhou {
6996ec13c8fSNan Zhou certInstallPath = path;
7006ec13c8fSNan Zhou }
7016ec13c8fSNan Zhou
702e1289adfSNan Zhou } // namespace phosphor::certs
703