1014be0bfSNan Zhou #include "config.h" 2014be0bfSNan Zhou 3cfbc8dc8SJayanth Othayoth #include "certs_manager.hpp" 4cfbc8dc8SJayanth Othayoth 56ec13c8fSNan Zhou #include "x509_utils.hpp" 66ec13c8fSNan Zhou 7014be0bfSNan Zhou #include <openssl/asn1.h> 8014be0bfSNan Zhou #include <openssl/bn.h> 9014be0bfSNan Zhou #include <openssl/ec.h> 1026fb83efSPatrick Williams #include <openssl/evp.h> 11014be0bfSNan Zhou #include <openssl/obj_mac.h> 12014be0bfSNan Zhou #include <openssl/objects.h> 13014be0bfSNan Zhou #include <openssl/opensslv.h> 14f4682712SMarri Devender Rao #include <openssl/pem.h> 15014be0bfSNan Zhou #include <openssl/rsa.h> 16f4682712SMarri Devender Rao #include <unistd.h> 17f4682712SMarri Devender Rao 18223e4604SPatrick Williams #include <phosphor-logging/elog-errors.hpp> 19223e4604SPatrick Williams #include <phosphor-logging/elog.hpp> 20f2646271SRavi Teja #include <phosphor-logging/lg2.hpp> 21223e4604SPatrick Williams #include <sdbusplus/bus.hpp> 22223e4604SPatrick Williams #include <sdbusplus/exception.hpp> 23223e4604SPatrick Williams #include <sdbusplus/message.hpp> 24223e4604SPatrick Williams #include <sdeventplus/source/base.hpp> 25223e4604SPatrick Williams #include <sdeventplus/source/child.hpp> 26223e4604SPatrick Williams #include <xyz/openbmc_project/Certs/error.hpp> 27223e4604SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp> 28223e4604SPatrick Williams 29a3bb38fbSZbigniew Kurzynski #include <algorithm> 30014be0bfSNan Zhou #include <array> 31014be0bfSNan Zhou #include <cerrno> 32014be0bfSNan Zhou #include <chrono> 33014be0bfSNan Zhou #include <csignal> 34014be0bfSNan Zhou #include <cstdio> 35014be0bfSNan Zhou #include <cstdlib> 36014be0bfSNan Zhou #include <cstring> 37014be0bfSNan Zhou #include <exception> 386ec13c8fSNan Zhou #include <fstream> 39014be0bfSNan Zhou #include <utility> 402f3563ccSZbigniew Lukwinski 41e1289adfSNan Zhou namespace phosphor::certs 42cfbc8dc8SJayanth Othayoth { 43cf06ccdcSNan Zhou namespace 44cf06ccdcSNan Zhou { 45cf06ccdcSNan Zhou namespace fs = std::filesystem; 46cf06ccdcSNan Zhou using ::phosphor::logging::commit; 47cf06ccdcSNan Zhou using ::phosphor::logging::elog; 48cf06ccdcSNan Zhou using ::phosphor::logging::report; 49cfbc8dc8SJayanth Othayoth 50cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 51cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 52cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 53cf06ccdcSNan Zhou using NotAllowedReason = 54cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON; 55cf06ccdcSNan Zhou using InvalidCertificateReason = ::phosphor::logging::xyz::openbmc_project:: 56cf06ccdcSNan Zhou Certs::InvalidCertificate::REASON; 57cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 58cf06ccdcSNan Zhou using Argument = 59cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::InvalidArgument; 60c6e58c7eSRamesh Iyyar 61cf06ccdcSNan Zhou // RAII support for openSSL functions. 62cf06ccdcSNan Zhou using X509ReqPtr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>; 63cf06ccdcSNan Zhou using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>; 64cf06ccdcSNan Zhou using BignumPtr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>; 656ec13c8fSNan Zhou using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>; 66cf06ccdcSNan Zhou 67cf06ccdcSNan Zhou constexpr int supportedKeyBitLength = 2048; 68cf06ccdcSNan Zhou constexpr int defaultKeyBitLength = 2048; 69cf06ccdcSNan Zhou // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 70cf06ccdcSNan Zhou constexpr auto defaultKeyCurveID = "secp224r1"; 716ec13c8fSNan Zhou // PEM certificate block markers, defined in go/rfc/7468. 726ec13c8fSNan Zhou constexpr std::string_view beginCertificate = "-----BEGIN CERTIFICATE-----"; 736ec13c8fSNan Zhou constexpr std::string_view endCertificate = "-----END CERTIFICATE-----"; 746ec13c8fSNan Zhou 756ec13c8fSNan Zhou /** 766ec13c8fSNan Zhou * @brief Splits the given authorities list file and returns an array of 776ec13c8fSNan Zhou * individual PEM encoded x509 certificate. 786ec13c8fSNan Zhou * 796ec13c8fSNan Zhou * @param[in] sourceFilePath - Path to the authorities list file. 806ec13c8fSNan Zhou * 816ec13c8fSNan Zhou * @return An array of individual PEM encoded x509 certificate 826ec13c8fSNan Zhou */ 836ec13c8fSNan Zhou std::vector<std::string> splitCertificates(const std::string& sourceFilePath) 846ec13c8fSNan Zhou { 856ec13c8fSNan Zhou std::ifstream inputCertFileStream; 866ec13c8fSNan Zhou inputCertFileStream.exceptions( 876ec13c8fSNan Zhou std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); 886ec13c8fSNan Zhou 896ec13c8fSNan Zhou std::stringstream pemStream; 906ec13c8fSNan Zhou std::vector<std::string> certificatesList; 916ec13c8fSNan Zhou try 926ec13c8fSNan Zhou { 936ec13c8fSNan Zhou inputCertFileStream.open(sourceFilePath); 946ec13c8fSNan Zhou pemStream << inputCertFileStream.rdbuf(); 956ec13c8fSNan Zhou inputCertFileStream.close(); 966ec13c8fSNan Zhou } 976ec13c8fSNan Zhou catch (const std::exception& e) 986ec13c8fSNan Zhou { 99f2646271SRavi Teja lg2::error("Failed to read certificates list, ERR:{ERR}, SRC:{SRC}", 100f2646271SRavi Teja "ERR", e, "SRC", sourceFilePath); 1016ec13c8fSNan Zhou elog<InternalFailure>(); 1026ec13c8fSNan Zhou } 1036ec13c8fSNan Zhou std::string pem = pemStream.str(); 1046ec13c8fSNan Zhou size_t begin = 0; 1056ec13c8fSNan Zhou // |begin| points to the current start position for searching the next 1066ec13c8fSNan Zhou // |beginCertificate| block. When we find the beginning of the certificate, 1076ec13c8fSNan Zhou // we extract the content between the beginning and the end of the current 1086ec13c8fSNan Zhou // certificate. And finally we move |begin| to the end of the current 1096ec13c8fSNan Zhou // certificate to start searching the next potential certificate. 1106ec13c8fSNan Zhou for (begin = pem.find(beginCertificate, begin); begin != std::string::npos; 1116ec13c8fSNan Zhou begin = pem.find(beginCertificate, begin)) 1126ec13c8fSNan Zhou { 1136ec13c8fSNan Zhou size_t end = pem.find(endCertificate, begin); 1146ec13c8fSNan Zhou if (end == std::string::npos) 1156ec13c8fSNan Zhou { 116f2646271SRavi Teja lg2::error( 1176ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END"); 1186ec13c8fSNan Zhou elog<InvalidCertificate>(InvalidCertificateReason( 1196ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END")); 1206ec13c8fSNan Zhou } 1216ec13c8fSNan Zhou end += endCertificate.size(); 1226ec13c8fSNan Zhou certificatesList.emplace_back(pem.substr(begin, end - begin)); 1236ec13c8fSNan Zhou begin = end; 1246ec13c8fSNan Zhou } 1256ec13c8fSNan Zhou return certificatesList; 1266ec13c8fSNan Zhou } 1276ec13c8fSNan Zhou 128cf06ccdcSNan Zhou } // namespace 129f4682712SMarri Devender Rao 130b3dbfb37SPatrick Williams Manager::Manager(sdbusplus::bus_t& bus, sdeventplus::Event& event, 131cf06ccdcSNan Zhou const char* path, CertificateType type, 132cf06ccdcSNan Zhou const std::string& unit, const std::string& installPath) : 133cf06ccdcSNan Zhou internal::ManagerInterface(bus, path), 134f4682712SMarri Devender Rao bus(bus), event(event), objectPath(path), certType(type), 135c6e58c7eSRamesh Iyyar unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)), 136c6e58c7eSRamesh Iyyar certParentInstallPath(fs::path(certInstallPath).parent_path()) 137cfbc8dc8SJayanth Othayoth { 138db5c6fc8SMarri Devender Rao try 139db5c6fc8SMarri Devender Rao { 140fe590c4eSZbigniew Lukwinski // Create certificate directory if not existing. 141bf3cf751SNan Zhou // Set correct certificate directory permissions. 142fe590c4eSZbigniew Lukwinski fs::path certDirectory; 143b57d75e2SMarri Devender Rao try 144b57d75e2SMarri Devender Rao { 145e3d47cd4SNan Zhou if (certType == CertificateType::authority) 146b57d75e2SMarri Devender Rao { 147fe590c4eSZbigniew Lukwinski certDirectory = certInstallPath; 148b57d75e2SMarri Devender Rao } 149fe590c4eSZbigniew Lukwinski else 150fe590c4eSZbigniew Lukwinski { 151fe590c4eSZbigniew Lukwinski certDirectory = certParentInstallPath; 152fe590c4eSZbigniew Lukwinski } 153fe590c4eSZbigniew Lukwinski 154fe590c4eSZbigniew Lukwinski if (!fs::exists(certDirectory)) 155fe590c4eSZbigniew Lukwinski { 156fe590c4eSZbigniew Lukwinski fs::create_directories(certDirectory); 157fe590c4eSZbigniew Lukwinski } 158fe590c4eSZbigniew Lukwinski 159667286e4SMarri Devender Rao auto permission = fs::perms::owner_read | fs::perms::owner_write | 160667286e4SMarri Devender Rao fs::perms::owner_exec; 161db5c6fc8SMarri Devender Rao fs::permissions(certDirectory, permission, 162db5c6fc8SMarri Devender Rao fs::perm_options::replace); 1632f3563ccSZbigniew Lukwinski storageUpdate(); 164b57d75e2SMarri Devender Rao } 16571957992SPatrick Williams catch (const fs::filesystem_error& e) 166b57d75e2SMarri Devender Rao { 167f2646271SRavi Teja lg2::error( 168f2646271SRavi Teja "Failed to create directory, ERR:{ERR}, DIRECTORY:{DIRECTORY}", 169f2646271SRavi Teja "ERR", e, "DIRECTORY", certParentInstallPath); 170b57d75e2SMarri Devender Rao report<InternalFailure>(); 171b57d75e2SMarri Devender Rao } 172b57d75e2SMarri Devender Rao 173c6e58c7eSRamesh Iyyar // Generating RSA private key file if certificate type is server/client 174e3d47cd4SNan Zhou if (certType != CertificateType::authority) 175c6e58c7eSRamesh Iyyar { 176c6e58c7eSRamesh Iyyar createRSAPrivateKeyFile(); 177c6e58c7eSRamesh Iyyar } 178c6e58c7eSRamesh Iyyar 179ffad1ef1SMarri Devender Rao // restore any existing certificates 180db029c95SKowalski, Kamil createCertificates(); 181ffad1ef1SMarri Devender Rao 182ffad1ef1SMarri Devender Rao // watch is not required for authority certificates 183e3d47cd4SNan Zhou if (certType != CertificateType::authority) 184ffad1ef1SMarri Devender Rao { 185ffad1ef1SMarri Devender Rao // watch for certificate file create/replace 186223e4604SPatrick Williams certWatchPtr = std::make_unique<Watch>(event, certInstallPath, 187223e4604SPatrick Williams [this]() { 188bf7c588cSMarri Devender Rao try 189bf7c588cSMarri Devender Rao { 190ffad1ef1SMarri Devender Rao // if certificate file existing update it 191db029c95SKowalski, Kamil if (!installedCerts.empty()) 192ffad1ef1SMarri Devender Rao { 193f2646271SRavi Teja lg2::info("Inotify callback to update " 194db5c6fc8SMarri Devender Rao "certificate properties"); 195db029c95SKowalski, Kamil installedCerts[0]->populateProperties(); 196ffad1ef1SMarri Devender Rao } 197ffad1ef1SMarri Devender Rao else 198ffad1ef1SMarri Devender Rao { 199f2646271SRavi Teja lg2::info( 200ffad1ef1SMarri Devender Rao "Inotify callback to create certificate object"); 201db029c95SKowalski, Kamil createCertificates(); 202ffad1ef1SMarri Devender Rao } 203bf7c588cSMarri Devender Rao } 204bf7c588cSMarri Devender Rao catch (const InternalFailure& e) 205bf7c588cSMarri Devender Rao { 206ffad1ef1SMarri Devender Rao commit<InternalFailure>(); 207bf7c588cSMarri Devender Rao } 208bf7c588cSMarri Devender Rao catch (const InvalidCertificate& e) 209bf7c588cSMarri Devender Rao { 210ffad1ef1SMarri Devender Rao commit<InvalidCertificate>(); 211bf7c588cSMarri Devender Rao } 212ffad1ef1SMarri Devender Rao }); 213bf7c588cSMarri Devender Rao } 214db029c95SKowalski, Kamil else 215db029c95SKowalski, Kamil { 216db5c6fc8SMarri Devender Rao try 217db5c6fc8SMarri Devender Rao { 218db5c6fc8SMarri Devender Rao const std::string singleCertPath = "/etc/ssl/certs/Root-CA.pem"; 219db5c6fc8SMarri Devender Rao if (fs::exists(singleCertPath) && !fs::is_empty(singleCertPath)) 220db029c95SKowalski, Kamil { 221f2646271SRavi Teja lg2::notice( 222f2646271SRavi Teja "Legacy certificate detected, will be installed from," 223f2646271SRavi Teja "SINGLE_CERTPATH:{SINGLE_CERTPATH}", 224f2646271SRavi Teja "SINGLE_CERTPATH", singleCertPath); 225db5c6fc8SMarri Devender Rao install(singleCertPath); 226db5c6fc8SMarri Devender Rao if (!fs::remove(singleCertPath)) 227db029c95SKowalski, Kamil { 228f2646271SRavi Teja lg2::error("Unable to remove old certificate from," 229f2646271SRavi Teja "SINGLE_CERTPATH:{SINGLE_CERTPATH}", 230f2646271SRavi Teja "SINGLE_CERTPATH", singleCertPath); 231db029c95SKowalski, Kamil elog<InternalFailure>(); 232db029c95SKowalski, Kamil } 233db029c95SKowalski, Kamil } 234db029c95SKowalski, Kamil } 235db5c6fc8SMarri Devender Rao catch (const std::exception& ex) 236db5c6fc8SMarri Devender Rao { 237f2646271SRavi Teja lg2::error( 238f2646271SRavi Teja "Error in restoring legacy certificate, ERROR_STR:{ERROR_STR}", 239f2646271SRavi Teja "ERROR_STR", ex); 240db5c6fc8SMarri Devender Rao } 241db5c6fc8SMarri Devender Rao } 242db5c6fc8SMarri Devender Rao } 24371957992SPatrick Williams catch (const std::exception& ex) 244db5c6fc8SMarri Devender Rao { 245f2646271SRavi Teja lg2::error( 246f2646271SRavi Teja "Error in certificate manager constructor, ERROR_STR:{ERROR_STR}", 247f2646271SRavi Teja "ERROR_STR", ex); 248db5c6fc8SMarri Devender Rao } 249dd74bd20SJayanth Othayoth } 250589159f2SJayanth Othayoth 25106a69d7bSZbigniew Kurzynski std::string Manager::install(const std::string filePath) 252cfbc8dc8SJayanth Othayoth { 253e3d47cd4SNan Zhou if (certType != CertificateType::authority && !installedCerts.empty()) 2541396511dSMarri Devender Rao { 255cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 2561396511dSMarri Devender Rao } 257e3d47cd4SNan Zhou else if (certType == CertificateType::authority && 258718eef37SNan Zhou installedCerts.size() >= maxNumAuthorityCertificates) 2593b07b77aSZbigniew Lukwinski { 260cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificates limit reached")); 2613b07b77aSZbigniew Lukwinski } 262ffad1ef1SMarri Devender Rao 2632f3563ccSZbigniew Lukwinski std::string certObjectPath; 2642f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath)) 2652f3563ccSZbigniew Lukwinski { 2662f3563ccSZbigniew Lukwinski certObjectPath = objectPath + '/' + std::to_string(certIdCounter); 267db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 2682f3563ccSZbigniew Lukwinski bus, certObjectPath, certType, certInstallPath, filePath, 269698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/false)); 2702f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 2712f3563ccSZbigniew Lukwinski certIdCounter++; 2722f3563ccSZbigniew Lukwinski } 2732f3563ccSZbigniew Lukwinski else 2742f3563ccSZbigniew Lukwinski { 275cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 2762f3563ccSZbigniew Lukwinski } 2772f3563ccSZbigniew Lukwinski 27806a69d7bSZbigniew Kurzynski return certObjectPath; 279589159f2SJayanth Othayoth } 280ae70b3daSDeepak Kodihalli 2816ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 2826ec13c8fSNan Zhou Manager::installAll(const std::string filePath) 2836ec13c8fSNan Zhou { 284e3d47cd4SNan Zhou if (certType != CertificateType::authority) 2856ec13c8fSNan Zhou { 2866ec13c8fSNan Zhou elog<NotAllowed>( 2876ec13c8fSNan Zhou NotAllowedReason("The InstallAll interface is only allowed for " 2886ec13c8fSNan Zhou "Authority certificates")); 2896ec13c8fSNan Zhou } 2906ec13c8fSNan Zhou 2916ec13c8fSNan Zhou if (!installedCerts.empty()) 2926ec13c8fSNan Zhou { 2936ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason( 2946ec13c8fSNan Zhou "There are already root certificates; Call DeleteAll then " 2956ec13c8fSNan Zhou "InstallAll, or use ReplaceAll")); 2966ec13c8fSNan Zhou } 2976ec13c8fSNan Zhou 2986ec13c8fSNan Zhou fs::path sourceFile(filePath); 2996ec13c8fSNan Zhou if (!fs::exists(sourceFile)) 3006ec13c8fSNan Zhou { 301f2646271SRavi Teja lg2::error("File is Missing, FILE:{FILE}", "FILE", filePath); 3026ec13c8fSNan Zhou elog<InternalFailure>(); 3036ec13c8fSNan Zhou } 3046ec13c8fSNan Zhou std::vector<std::string> authorities = splitCertificates(sourceFile); 3056ec13c8fSNan Zhou if (authorities.size() > maxNumAuthorityCertificates) 3066ec13c8fSNan Zhou { 3076ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificates limit reached")); 3086ec13c8fSNan Zhou } 3096ec13c8fSNan Zhou 310f2646271SRavi Teja lg2::info("Starts authority list install"); 31178357b0aSNan Zhou 3126ec13c8fSNan Zhou fs::path authorityStore(certInstallPath); 313223e4604SPatrick Williams fs::path authoritiesListFile = authorityStore / 314223e4604SPatrick Williams defaultAuthoritiesListFileName; 3156ec13c8fSNan Zhou 3166ec13c8fSNan Zhou // Atomically install all the certificates 3176ec13c8fSNan Zhou fs::path tempPath = Certificate::generateUniqueFilePath(authorityStore); 3186ec13c8fSNan Zhou fs::create_directory(tempPath); 3196ec13c8fSNan Zhou // Copies the authorities list 3206ec13c8fSNan Zhou Certificate::copyCertificate(sourceFile, 3216ec13c8fSNan Zhou tempPath / defaultAuthoritiesListFileName); 3226ec13c8fSNan Zhou std::vector<std::unique_ptr<Certificate>> tempCertificates; 3236ec13c8fSNan Zhou uint64_t tempCertIdCounter = certIdCounter; 3246ec13c8fSNan Zhou X509StorePtr x509Store = getX509Store(sourceFile); 3256ec13c8fSNan Zhou for (const auto& authority : authorities) 3266ec13c8fSNan Zhou { 327223e4604SPatrick Williams std::string certObjectPath = objectPath + '/' + 328223e4604SPatrick Williams std::to_string(tempCertIdCounter); 3296ec13c8fSNan Zhou tempCertificates.emplace_back(std::make_unique<Certificate>( 3306ec13c8fSNan Zhou bus, certObjectPath, certType, tempPath, *x509Store, authority, 331698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/false)); 3326ec13c8fSNan Zhou tempCertIdCounter++; 3336ec13c8fSNan Zhou } 3346ec13c8fSNan Zhou 3356ec13c8fSNan Zhou // We are good now, issue swap 3366ec13c8fSNan Zhou installedCerts = std::move(tempCertificates); 3376ec13c8fSNan Zhou certIdCounter = tempCertIdCounter; 3386ec13c8fSNan Zhou // Rename all the certificates including the authorities list 3396ec13c8fSNan Zhou for (const fs::path& f : fs::directory_iterator(tempPath)) 3406ec13c8fSNan Zhou { 3416ec13c8fSNan Zhou if (fs::is_symlink(f)) 3426ec13c8fSNan Zhou { 3436ec13c8fSNan Zhou continue; 3446ec13c8fSNan Zhou } 3456ec13c8fSNan Zhou fs::rename(/*from=*/f, /*to=*/certInstallPath / f.filename()); 3466ec13c8fSNan Zhou } 3476ec13c8fSNan Zhou // Update file locations and create symbol links 3486ec13c8fSNan Zhou for (const auto& cert : installedCerts) 3496ec13c8fSNan Zhou { 3506ec13c8fSNan Zhou cert->setCertInstallPath(certInstallPath); 3516ec13c8fSNan Zhou cert->setCertFilePath(certInstallPath / 3526ec13c8fSNan Zhou fs::path(cert->getCertFilePath()).filename()); 3536ec13c8fSNan Zhou cert->storageUpdate(); 3546ec13c8fSNan Zhou } 3556ec13c8fSNan Zhou // Remove the temporary folder 3566ec13c8fSNan Zhou fs::remove_all(tempPath); 3576ec13c8fSNan Zhou 3586ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> objects; 3596ec13c8fSNan Zhou for (const auto& certificate : installedCerts) 3606ec13c8fSNan Zhou { 3616ec13c8fSNan Zhou objects.emplace_back(certificate->getObjectPath()); 3626ec13c8fSNan Zhou } 3636ec13c8fSNan Zhou 364f2646271SRavi Teja lg2::info("Finishes authority list install; reload units starts"); 3656ec13c8fSNan Zhou reloadOrReset(unitToRestart); 3666ec13c8fSNan Zhou return objects; 3676ec13c8fSNan Zhou } 3686ec13c8fSNan Zhou 3696ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 3706ec13c8fSNan Zhou Manager::replaceAll(std::string filePath) 3716ec13c8fSNan Zhou { 3726ec13c8fSNan Zhou installedCerts.clear(); 3736ec13c8fSNan Zhou certIdCounter = 1; 3746ec13c8fSNan Zhou storageUpdate(); 3756ec13c8fSNan Zhou return installAll(std::move(filePath)); 3766ec13c8fSNan Zhou } 3776ec13c8fSNan Zhou 378a3bb38fbSZbigniew Kurzynski void Manager::deleteAll() 379ae70b3daSDeepak Kodihalli { 3806ceec40bSMarri Devender Rao // TODO: #Issue 4 when a certificate is deleted system auto generates 3816ceec40bSMarri Devender Rao // certificate file. At present we are not supporting creation of 3826ceec40bSMarri Devender Rao // certificate object for the auto-generated certificate file as 3836ceec40bSMarri Devender Rao // deletion if only applicable for REST server and Bmcweb does not allow 3846ceec40bSMarri Devender Rao // deletion of certificates 385db029c95SKowalski, Kamil installedCerts.clear(); 3866ec13c8fSNan Zhou // If the authorities list exists, delete it as well 387e3d47cd4SNan Zhou if (certType == CertificateType::authority) 3886ec13c8fSNan Zhou { 389223e4604SPatrick Williams if (fs::path authoritiesList = fs::path(certInstallPath) / 390223e4604SPatrick Williams defaultAuthoritiesListFileName; 3916ec13c8fSNan Zhou fs::exists(authoritiesList)) 3926ec13c8fSNan Zhou { 3936ec13c8fSNan Zhou fs::remove(authoritiesList); 3946ec13c8fSNan Zhou } 3956ec13c8fSNan Zhou } 3966ec13c8fSNan Zhou certIdCounter = 1; 3972f3563ccSZbigniew Lukwinski storageUpdate(); 3982f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 399ae70b3daSDeepak Kodihalli } 400f4682712SMarri Devender Rao 4012f3563ccSZbigniew Lukwinski void Manager::deleteCertificate(const Certificate* const certificate) 402a3bb38fbSZbigniew Kurzynski { 403223e4604SPatrick Williams const std::vector<std::unique_ptr<Certificate>>::iterator& certIt = 404a3bb38fbSZbigniew Kurzynski std::find_if(installedCerts.begin(), installedCerts.end(), 405223e4604SPatrick Williams [certificate](const std::unique_ptr<Certificate>& cert) { 4062f3563ccSZbigniew Lukwinski return (cert.get() == certificate); 407a3bb38fbSZbigniew Kurzynski }); 408a3bb38fbSZbigniew Kurzynski if (certIt != installedCerts.end()) 409a3bb38fbSZbigniew Kurzynski { 410a3bb38fbSZbigniew Kurzynski installedCerts.erase(certIt); 4112f3563ccSZbigniew Lukwinski storageUpdate(); 4122f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 413a3bb38fbSZbigniew Kurzynski } 414a3bb38fbSZbigniew Kurzynski else 415a3bb38fbSZbigniew Kurzynski { 416f2646271SRavi Teja lg2::error("Certificate does not exist, ID:{ID}", "ID", 417f2646271SRavi Teja certificate->getCertId()); 4182f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 4192f3563ccSZbigniew Lukwinski } 4202f3563ccSZbigniew Lukwinski } 4212f3563ccSZbigniew Lukwinski 4222f3563ccSZbigniew Lukwinski void Manager::replaceCertificate(Certificate* const certificate, 4232f3563ccSZbigniew Lukwinski const std::string& filePath) 4242f3563ccSZbigniew Lukwinski { 4252f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath, certificate)) 4262f3563ccSZbigniew Lukwinski { 427698a5743SWilly Tu certificate->install(filePath, false); 4282f3563ccSZbigniew Lukwinski storageUpdate(); 4292f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 4302f3563ccSZbigniew Lukwinski } 4312f3563ccSZbigniew Lukwinski else 4322f3563ccSZbigniew Lukwinski { 433cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 434a3bb38fbSZbigniew Kurzynski } 435a3bb38fbSZbigniew Kurzynski } 436a3bb38fbSZbigniew Kurzynski 437f4682712SMarri Devender Rao std::string Manager::generateCSR( 438f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 439f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 440f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 441f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 442f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 443f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 444f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 445f4682712SMarri Devender Rao { 446f4682712SMarri Devender Rao // We support only one CSR. 447f4682712SMarri Devender Rao csrPtr.reset(nullptr); 448f4682712SMarri Devender Rao auto pid = fork(); 449f4682712SMarri Devender Rao if (pid == -1) 450f4682712SMarri Devender Rao { 451f2646271SRavi Teja lg2::error("Error occurred during forking process"); 452f4682712SMarri Devender Rao report<InternalFailure>(); 453f4682712SMarri Devender Rao } 454f4682712SMarri Devender Rao else if (pid == 0) 455f4682712SMarri Devender Rao { 456f4682712SMarri Devender Rao try 457f4682712SMarri Devender Rao { 458f4682712SMarri Devender Rao generateCSRHelper(alternativeNames, challengePassword, city, 459f4682712SMarri Devender Rao commonName, contactPerson, country, email, 460f4682712SMarri Devender Rao givenName, initials, keyBitLength, keyCurveId, 461f4682712SMarri Devender Rao keyPairAlgorithm, keyUsage, organization, 462f4682712SMarri Devender Rao organizationalUnit, state, surname, 463f4682712SMarri Devender Rao unstructuredName); 464f4682712SMarri Devender Rao exit(EXIT_SUCCESS); 465f4682712SMarri Devender Rao } 466f4682712SMarri Devender Rao catch (const InternalFailure& e) 467f4682712SMarri Devender Rao { 468f4682712SMarri Devender Rao // commit the error reported in child process and exit 469f4682712SMarri Devender Rao // Callback method from SDEvent Loop looks for exit status 470f4682712SMarri Devender Rao exit(EXIT_FAILURE); 471f4682712SMarri Devender Rao commit<InternalFailure>(); 472f4682712SMarri Devender Rao } 473d2393f23SRamesh Iyyar catch (const InvalidArgument& e) 474d2393f23SRamesh Iyyar { 475d2393f23SRamesh Iyyar // commit the error reported in child process and exit 476d2393f23SRamesh Iyyar // Callback method from SDEvent Loop looks for exit status 477d2393f23SRamesh Iyyar exit(EXIT_FAILURE); 478d2393f23SRamesh Iyyar commit<InvalidArgument>(); 479d2393f23SRamesh Iyyar } 480f4682712SMarri Devender Rao } 481f4682712SMarri Devender Rao else 482f4682712SMarri Devender Rao { 483f4682712SMarri Devender Rao using namespace sdeventplus::source; 484*d96b81caSPatrick Williams Child::Callback callback = [this](Child& eventSource, 485*d96b81caSPatrick Williams const siginfo_t* si) { 486f4682712SMarri Devender Rao eventSource.set_enabled(Enabled::On); 487f4682712SMarri Devender Rao if (si->si_status != 0) 488f4682712SMarri Devender Rao { 489e3d47cd4SNan Zhou this->createCSRObject(Status::failure); 490f4682712SMarri Devender Rao } 491f4682712SMarri Devender Rao else 492f4682712SMarri Devender Rao { 493e3d47cd4SNan Zhou this->createCSRObject(Status::success); 494f4682712SMarri Devender Rao } 495f4682712SMarri Devender Rao }; 496f4682712SMarri Devender Rao try 497f4682712SMarri Devender Rao { 498f4682712SMarri Devender Rao sigset_t ss; 499f4682712SMarri Devender Rao if (sigemptyset(&ss) < 0) 500f4682712SMarri Devender Rao { 501f2646271SRavi Teja lg2::error("Unable to initialize signal set"); 502f4682712SMarri Devender Rao elog<InternalFailure>(); 503f4682712SMarri Devender Rao } 504f4682712SMarri Devender Rao if (sigaddset(&ss, SIGCHLD) < 0) 505f4682712SMarri Devender Rao { 506f2646271SRavi Teja lg2::error("Unable to add signal to signal set"); 507f4682712SMarri Devender Rao elog<InternalFailure>(); 508f4682712SMarri Devender Rao } 509f4682712SMarri Devender Rao 510f4682712SMarri Devender Rao // Block SIGCHLD first, so that the event loop can handle it 511cfb5802aSNan Zhou if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0) 512f4682712SMarri Devender Rao { 513f2646271SRavi Teja lg2::error("Unable to block signal"); 514f4682712SMarri Devender Rao elog<InternalFailure>(); 515f4682712SMarri Devender Rao } 516f4682712SMarri Devender Rao if (childPtr) 517f4682712SMarri Devender Rao { 518f4682712SMarri Devender Rao childPtr.reset(); 519f4682712SMarri Devender Rao } 520f4682712SMarri Devender Rao childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 521f4682712SMarri Devender Rao std::move(callback)); 522f4682712SMarri Devender Rao } 523f4682712SMarri Devender Rao catch (const InternalFailure& e) 524f4682712SMarri Devender Rao { 525f4682712SMarri Devender Rao commit<InternalFailure>(); 526f4682712SMarri Devender Rao } 527f4682712SMarri Devender Rao } 528f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 529f4682712SMarri Devender Rao return csrObjectPath; 530f4682712SMarri Devender Rao } 531f4682712SMarri Devender Rao 532db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates() 533ffad1ef1SMarri Devender Rao { 534db029c95SKowalski, Kamil return installedCerts; 535ffad1ef1SMarri Devender Rao } 536ffad1ef1SMarri Devender Rao 537f4682712SMarri Devender Rao void Manager::generateCSRHelper( 538f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 539f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 540f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 541f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 542f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 543f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 544f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 545f4682712SMarri Devender Rao { 546f4682712SMarri Devender Rao int ret = 0; 547f4682712SMarri Devender Rao 548f4682712SMarri Devender Rao // set version of x509 req 549f4682712SMarri Devender Rao int nVersion = 1; 550cf06ccdcSNan Zhou X509ReqPtr x509Req(X509_REQ_new(), ::X509_REQ_free); 551f4682712SMarri Devender Rao ret = X509_REQ_set_version(x509Req.get(), nVersion); 552f4682712SMarri Devender Rao if (ret == 0) 553f4682712SMarri Devender Rao { 554f2646271SRavi Teja lg2::error("Error occurred during X509_REQ_set_version call"); 555f4682712SMarri Devender Rao elog<InternalFailure>(); 556f4682712SMarri Devender Rao } 557f4682712SMarri Devender Rao 558f4682712SMarri Devender Rao // set subject of x509 req 559f4682712SMarri Devender Rao X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 560f4682712SMarri Devender Rao 561f4682712SMarri Devender Rao if (!alternativeNames.empty()) 562f4682712SMarri Devender Rao { 563f4682712SMarri Devender Rao for (auto& name : alternativeNames) 564f4682712SMarri Devender Rao { 565f4682712SMarri Devender Rao addEntry(x509Name, "subjectAltName", name); 566f4682712SMarri Devender Rao } 567f4682712SMarri Devender Rao } 568f4682712SMarri Devender Rao addEntry(x509Name, "challengePassword", challengePassword); 569f4682712SMarri Devender Rao addEntry(x509Name, "L", city); 570f4682712SMarri Devender Rao addEntry(x509Name, "CN", commonName); 571f4682712SMarri Devender Rao addEntry(x509Name, "name", contactPerson); 572f4682712SMarri Devender Rao addEntry(x509Name, "C", country); 573f4682712SMarri Devender Rao addEntry(x509Name, "emailAddress", email); 574f4682712SMarri Devender Rao addEntry(x509Name, "GN", givenName); 575f4682712SMarri Devender Rao addEntry(x509Name, "initials", initials); 576f4682712SMarri Devender Rao addEntry(x509Name, "algorithm", keyPairAlgorithm); 577f4682712SMarri Devender Rao if (!keyUsage.empty()) 578f4682712SMarri Devender Rao { 579f4682712SMarri Devender Rao for (auto& usage : keyUsage) 580f4682712SMarri Devender Rao { 5817641105dSMarri Devender Rao if (isExtendedKeyUsage(usage)) 5827641105dSMarri Devender Rao { 5837641105dSMarri Devender Rao addEntry(x509Name, "extendedKeyUsage", usage); 5847641105dSMarri Devender Rao } 5857641105dSMarri Devender Rao else 5867641105dSMarri Devender Rao { 587f4682712SMarri Devender Rao addEntry(x509Name, "keyUsage", usage); 588f4682712SMarri Devender Rao } 589f4682712SMarri Devender Rao } 5907641105dSMarri Devender Rao } 591f4682712SMarri Devender Rao addEntry(x509Name, "O", organization); 592dc91fb61SJayanth Othayoth addEntry(x509Name, "OU", organizationalUnit); 593f4682712SMarri Devender Rao addEntry(x509Name, "ST", state); 594f4682712SMarri Devender Rao addEntry(x509Name, "SN", surname); 595f4682712SMarri Devender Rao addEntry(x509Name, "unstructuredName", unstructuredName); 596f4682712SMarri Devender Rao 597cf06ccdcSNan Zhou EVPPkeyPtr pKey(nullptr, ::EVP_PKEY_free); 5988a09b52aSRamesh Iyyar 599f2646271SRavi Teja lg2::info("Given Key pair algorithm, KEYPAIRALGORITHM:{KEYPAIRALGORITHM}", 600f2646271SRavi Teja "KEYPAIRALGORITHM", keyPairAlgorithm); 6018a09b52aSRamesh Iyyar 6028a09b52aSRamesh Iyyar // Used EC algorithm as default if user did not give algorithm type. 6038a09b52aSRamesh Iyyar if (keyPairAlgorithm == "RSA") 604c6e58c7eSRamesh Iyyar pKey = getRSAKeyPair(keyBitLength); 6058a09b52aSRamesh Iyyar else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 606c6e58c7eSRamesh Iyyar pKey = generateECKeyPair(keyCurveId); 6078a09b52aSRamesh Iyyar else 6088a09b52aSRamesh Iyyar { 609f2646271SRavi Teja lg2::error("Given Key pair algorithm is not supported. Supporting " 6108a09b52aSRamesh Iyyar "RSA and EC only"); 6118a09b52aSRamesh Iyyar elog<InvalidArgument>( 6128a09b52aSRamesh Iyyar Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 6138a09b52aSRamesh Iyyar Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 6148a09b52aSRamesh Iyyar } 6158a09b52aSRamesh Iyyar 6168a09b52aSRamesh Iyyar ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 6178a09b52aSRamesh Iyyar if (ret == 0) 6188a09b52aSRamesh Iyyar { 619f2646271SRavi Teja lg2::error("Error occurred while setting Public key"); 6208a09b52aSRamesh Iyyar elog<InternalFailure>(); 6218a09b52aSRamesh Iyyar } 6228a09b52aSRamesh Iyyar 6238a09b52aSRamesh Iyyar // Write private key to file 624718eef37SNan Zhou writePrivateKey(pKey, defaultPrivateKeyFileName); 625f4682712SMarri Devender Rao 626f4682712SMarri Devender Rao // set sign key of x509 req 627f4682712SMarri Devender Rao ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 6288a09b52aSRamesh Iyyar if (ret == 0) 629f4682712SMarri Devender Rao { 630f2646271SRavi Teja lg2::error("Error occurred while signing key of x509"); 631f4682712SMarri Devender Rao elog<InternalFailure>(); 632f4682712SMarri Devender Rao } 6338a09b52aSRamesh Iyyar 634f2646271SRavi Teja lg2::info("Writing CSR to file"); 635718eef37SNan Zhou fs::path csrFilePath = certParentInstallPath / defaultCSRFileName; 636c6e58c7eSRamesh Iyyar writeCSR(csrFilePath.string(), x509Req); 637f4682712SMarri Devender Rao } 638f4682712SMarri Devender Rao 6397641105dSMarri Devender Rao bool Manager::isExtendedKeyUsage(const std::string& usage) 6407641105dSMarri Devender Rao { 6417641105dSMarri Devender Rao const static std::array<const char*, 6> usageList = { 6427641105dSMarri Devender Rao "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 6437641105dSMarri Devender Rao "Timestamping", "CodeSigning", "EmailProtection"}; 644*d96b81caSPatrick Williams auto it = std::find_if( 645*d96b81caSPatrick Williams usageList.begin(), usageList.end(), 646*d96b81caSPatrick Williams [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); }); 6477641105dSMarri Devender Rao return it != usageList.end(); 6487641105dSMarri Devender Rao } 649cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateRSAKeyPair(const int64_t keyBitLength) 650f4682712SMarri Devender Rao { 6518a09b52aSRamesh Iyyar int64_t keyBitLen = keyBitLength; 652f4682712SMarri Devender Rao // set keybit length to default value if not set 6538a09b52aSRamesh Iyyar if (keyBitLen <= 0) 654f4682712SMarri Devender Rao { 655f2646271SRavi Teja lg2::info("KeyBitLength is not given.Hence, using default KeyBitLength:" 656f2646271SRavi Teja "{DEFAULTKEYBITLENGTH}", 657f2646271SRavi Teja "DEFAULTKEYBITLENGTH", defaultKeyBitLength); 658cf06ccdcSNan Zhou keyBitLen = defaultKeyBitLength; 659f4682712SMarri Devender Rao } 66026fb83efSPatrick Williams 66126fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 66226fb83efSPatrick Williams 66326fb83efSPatrick Williams // generate rsa key 664cf06ccdcSNan Zhou BignumPtr bne(BN_new(), ::BN_free); 66526fb83efSPatrick Williams auto ret = BN_set_word(bne.get(), RSA_F4); 66626fb83efSPatrick Williams if (ret == 0) 66726fb83efSPatrick Williams { 668f2646271SRavi Teja lg2::error("Error occurred during BN_set_word call"); 66926fb83efSPatrick Williams elog<InternalFailure>(); 67026fb83efSPatrick Williams } 671762da74eSNan Zhou using RSAPtr = std::unique_ptr<RSA, decltype(&::RSA_free)>; 672762da74eSNan Zhou RSAPtr rsa(RSA_new(), ::RSA_free); 673762da74eSNan Zhou ret = RSA_generate_key_ex(rsa.get(), keyBitLen, bne.get(), nullptr); 674f4682712SMarri Devender Rao if (ret != 1) 675f4682712SMarri Devender Rao { 676f2646271SRavi Teja lg2::error( 677f2646271SRavi Teja "Error occurred during RSA_generate_key_ex call: {KEYBITLENGTH}", 678f2646271SRavi Teja "KEYBITLENGTH", keyBitLen); 679f4682712SMarri Devender Rao elog<InternalFailure>(); 680f4682712SMarri Devender Rao } 681f4682712SMarri Devender Rao 682f4682712SMarri Devender Rao // set public key of x509 req 683cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 684762da74eSNan Zhou ret = EVP_PKEY_assign_RSA(pKey.get(), rsa.get()); 685f4682712SMarri Devender Rao if (ret == 0) 686f4682712SMarri Devender Rao { 687f2646271SRavi Teja lg2::error("Error occurred during assign rsa key into EVP"); 688f4682712SMarri Devender Rao elog<InternalFailure>(); 689f4682712SMarri Devender Rao } 690762da74eSNan Zhou // Now |rsa| is managed by |pKey| 691762da74eSNan Zhou rsa.release(); 6928a09b52aSRamesh Iyyar return pKey; 69326fb83efSPatrick Williams 69426fb83efSPatrick Williams #else 69526fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 69626fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr), &::EVP_PKEY_CTX_free); 69726fb83efSPatrick Williams if (!ctx) 69826fb83efSPatrick Williams { 699f2646271SRavi Teja lg2::error("Error occurred creating EVP_PKEY_CTX from algorithm"); 70026fb83efSPatrick Williams elog<InternalFailure>(); 70126fb83efSPatrick Williams } 70226fb83efSPatrick Williams 70326fb83efSPatrick Williams if ((EVP_PKEY_keygen_init(ctx.get()) <= 0) || 70426fb83efSPatrick Williams (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), keyBitLen) <= 0)) 70526fb83efSPatrick Williams 70626fb83efSPatrick Williams { 707f2646271SRavi Teja lg2::error("Error occurred initializing keygen context"); 70826fb83efSPatrick Williams elog<InternalFailure>(); 70926fb83efSPatrick Williams } 71026fb83efSPatrick Williams 71126fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 71226fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 71326fb83efSPatrick Williams { 714f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 71526fb83efSPatrick Williams elog<InternalFailure>(); 71626fb83efSPatrick Williams } 71726fb83efSPatrick Williams 71826fb83efSPatrick Williams return {pKey, &::EVP_PKEY_free}; 71926fb83efSPatrick Williams #endif 7208a09b52aSRamesh Iyyar } 7218a09b52aSRamesh Iyyar 722cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateECKeyPair(const std::string& curveId) 7238a09b52aSRamesh Iyyar { 7248a09b52aSRamesh Iyyar std::string curId(curveId); 7258a09b52aSRamesh Iyyar 7268a09b52aSRamesh Iyyar if (curId.empty()) 7278a09b52aSRamesh Iyyar { 728f2646271SRavi Teja lg2::info("KeyCurveId is not given. Hence using default curve id," 729f2646271SRavi Teja "DEFAULTKEYCURVEID:{DEFAULTKEYCURVEID}", 730f2646271SRavi Teja "DEFAULTKEYCURVEID", defaultKeyCurveID); 731cf06ccdcSNan Zhou curId = defaultKeyCurveID; 7328a09b52aSRamesh Iyyar } 7338a09b52aSRamesh Iyyar 7348a09b52aSRamesh Iyyar int ecGrp = OBJ_txt2nid(curId.c_str()); 7358a09b52aSRamesh Iyyar if (ecGrp == NID_undef) 7368a09b52aSRamesh Iyyar { 737f2646271SRavi Teja lg2::error( 738f2646271SRavi Teja "Error occurred during convert the curve id string format into NID," 739f2646271SRavi Teja "KEYCURVEID:{KEYCURVEID}", 740f2646271SRavi Teja "KEYCURVEID", curId); 7418a09b52aSRamesh Iyyar elog<InternalFailure>(); 7428a09b52aSRamesh Iyyar } 7438a09b52aSRamesh Iyyar 74426fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 74526fb83efSPatrick Williams 7468a09b52aSRamesh Iyyar EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 7478a09b52aSRamesh Iyyar 748cfb5802aSNan Zhou if (ecKey == nullptr) 7498a09b52aSRamesh Iyyar { 750f2646271SRavi Teja lg2::error( 751f2646271SRavi Teja "Error occurred during create the EC_Key object from NID, ECGROUP:{ECGROUP}", 752f2646271SRavi Teja "ECGROUP", ecGrp); 7538a09b52aSRamesh Iyyar elog<InternalFailure>(); 7548a09b52aSRamesh Iyyar } 7558a09b52aSRamesh Iyyar 7568a09b52aSRamesh Iyyar // If you want to save a key and later load it with 7578a09b52aSRamesh Iyyar // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 7588a09b52aSRamesh Iyyar // flag on the key. 7598a09b52aSRamesh Iyyar EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 7608a09b52aSRamesh Iyyar 7618a09b52aSRamesh Iyyar int ret = EC_KEY_generate_key(ecKey); 7628a09b52aSRamesh Iyyar 7638a09b52aSRamesh Iyyar if (ret == 0) 7648a09b52aSRamesh Iyyar { 7658a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 766f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 7678a09b52aSRamesh Iyyar elog<InternalFailure>(); 7688a09b52aSRamesh Iyyar } 7698a09b52aSRamesh Iyyar 770cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 7718a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 7728a09b52aSRamesh Iyyar if (ret == 0) 7738a09b52aSRamesh Iyyar { 7748a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 775f2646271SRavi Teja lg2::error("Error occurred during assign EC Key into EVP"); 7768a09b52aSRamesh Iyyar elog<InternalFailure>(); 7778a09b52aSRamesh Iyyar } 7788a09b52aSRamesh Iyyar 7798a09b52aSRamesh Iyyar return pKey; 78026fb83efSPatrick Williams 78126fb83efSPatrick Williams #else 782e3d47cd4SNan Zhou auto holderOfKey = [](EVP_PKEY* key) { 78326fb83efSPatrick Williams return std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>{ 78426fb83efSPatrick Williams key, &::EVP_PKEY_free}; 78526fb83efSPatrick Williams }; 78626fb83efSPatrick Williams 78726fb83efSPatrick Williams // Create context to set up curve parameters. 78826fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 78926fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr), &::EVP_PKEY_CTX_free); 79026fb83efSPatrick Williams if (!ctx) 79126fb83efSPatrick Williams { 792f2646271SRavi Teja lg2::error("Error occurred creating EVP_PKEY_CTX for params"); 79326fb83efSPatrick Williams elog<InternalFailure>(); 79426fb83efSPatrick Williams } 79526fb83efSPatrick Williams 79626fb83efSPatrick Williams // Set up curve parameters. 79726fb83efSPatrick Williams EVP_PKEY* params = nullptr; 79826fb83efSPatrick Williams 79926fb83efSPatrick Williams if ((EVP_PKEY_paramgen_init(ctx.get()) <= 0) || 80026fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_param_enc(ctx.get(), OPENSSL_EC_NAMED_CURVE) <= 80126fb83efSPatrick Williams 0) || 80226fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), ecGrp) <= 0) || 80326fb83efSPatrick Williams (EVP_PKEY_paramgen(ctx.get(), ¶ms) <= 0)) 80426fb83efSPatrick Williams { 805f2646271SRavi Teja lg2::error("Error occurred setting curve parameters"); 80626fb83efSPatrick Williams elog<InternalFailure>(); 80726fb83efSPatrick Williams } 80826fb83efSPatrick Williams 80926fb83efSPatrick Williams // Move parameters to RAII holder. 810e3d47cd4SNan Zhou auto pparms = holderOfKey(params); 81126fb83efSPatrick Williams 81226fb83efSPatrick Williams // Create new context for key. 81326fb83efSPatrick Williams ctx.reset(EVP_PKEY_CTX_new_from_pkey(nullptr, params, nullptr)); 81426fb83efSPatrick Williams 81526fb83efSPatrick Williams if (!ctx || (EVP_PKEY_keygen_init(ctx.get()) <= 0)) 81626fb83efSPatrick Williams { 817f2646271SRavi Teja lg2::error("Error occurred initializing keygen context"); 81826fb83efSPatrick Williams elog<InternalFailure>(); 81926fb83efSPatrick Williams } 82026fb83efSPatrick Williams 82126fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 82226fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 82326fb83efSPatrick Williams { 824f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 82526fb83efSPatrick Williams elog<InternalFailure>(); 82626fb83efSPatrick Williams } 82726fb83efSPatrick Williams 828e3d47cd4SNan Zhou return holderOfKey(pKey); 82926fb83efSPatrick Williams #endif 8308a09b52aSRamesh Iyyar } 8318a09b52aSRamesh Iyyar 832cf06ccdcSNan Zhou void Manager::writePrivateKey(const EVPPkeyPtr& pKey, 833c6e58c7eSRamesh Iyyar const std::string& privKeyFileName) 8348a09b52aSRamesh Iyyar { 835f2646271SRavi Teja lg2::info("Writing private key to file"); 836f4682712SMarri Devender Rao // write private key to file 837c6e58c7eSRamesh Iyyar fs::path privKeyPath = certParentInstallPath / privKeyFileName; 838f4682712SMarri Devender Rao 839f4682712SMarri Devender Rao FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 840cfb5802aSNan Zhou if (fp == nullptr) 841f4682712SMarri Devender Rao { 842f2646271SRavi Teja lg2::error("Error occurred creating private key file"); 843f4682712SMarri Devender Rao elog<InternalFailure>(); 844f4682712SMarri Devender Rao } 845223e4604SPatrick Williams int ret = PEM_write_PrivateKey(fp, pKey.get(), nullptr, nullptr, 0, 0, 846223e4604SPatrick Williams nullptr); 847f4682712SMarri Devender Rao std::fclose(fp); 848f4682712SMarri Devender Rao if (ret == 0) 849f4682712SMarri Devender Rao { 850f2646271SRavi Teja lg2::error("Error occurred while writing private key to file"); 851f4682712SMarri Devender Rao elog<InternalFailure>(); 852f4682712SMarri Devender Rao } 853f4682712SMarri Devender Rao } 854f4682712SMarri Devender Rao 855f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field, 856f4682712SMarri Devender Rao const std::string& bytes) 857f4682712SMarri Devender Rao { 858f4682712SMarri Devender Rao if (bytes.empty()) 859f4682712SMarri Devender Rao { 860f4682712SMarri Devender Rao return; 861f4682712SMarri Devender Rao } 862f4682712SMarri Devender Rao int ret = X509_NAME_add_entry_by_txt( 863f4682712SMarri Devender Rao x509Name, field, MBSTRING_ASC, 864f4682712SMarri Devender Rao reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 865f4682712SMarri Devender Rao if (ret != 1) 866f4682712SMarri Devender Rao { 867f2646271SRavi Teja lg2::error("Unable to set entry, FIELD:{FIELD}, VALUE:{VALUE}", "FIELD", 868f2646271SRavi Teja field, "VALUE", bytes); 869f4682712SMarri Devender Rao elog<InternalFailure>(); 870f4682712SMarri Devender Rao } 871f4682712SMarri Devender Rao } 872f4682712SMarri Devender Rao 873f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status) 874f4682712SMarri Devender Rao { 875f4682712SMarri Devender Rao if (csrPtr) 876f4682712SMarri Devender Rao { 877f4682712SMarri Devender Rao csrPtr.reset(nullptr); 878f4682712SMarri Devender Rao } 879f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 880f4682712SMarri Devender Rao csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 881f4682712SMarri Devender Rao certInstallPath.c_str(), status); 882f4682712SMarri Devender Rao } 883f4682712SMarri Devender Rao 884cf06ccdcSNan Zhou void Manager::writeCSR(const std::string& filePath, const X509ReqPtr& x509Req) 885f4682712SMarri Devender Rao { 886f4682712SMarri Devender Rao if (fs::exists(filePath)) 887f4682712SMarri Devender Rao { 888f2646271SRavi Teja lg2::info("Removing the existing file, FILENAME:{FILENAME}", "FILENAME", 889f2646271SRavi Teja filePath); 890f4682712SMarri Devender Rao if (!fs::remove(filePath.c_str())) 891f4682712SMarri Devender Rao { 892f2646271SRavi Teja lg2::error("Unable to remove the file, FILENAME:{FILENAME}", 893f2646271SRavi Teja "FILENAME", filePath); 894f4682712SMarri Devender Rao elog<InternalFailure>(); 895f4682712SMarri Devender Rao } 896f4682712SMarri Devender Rao } 897f4682712SMarri Devender Rao 898cfb5802aSNan Zhou FILE* fp = nullptr; 899f4682712SMarri Devender Rao 900cfb5802aSNan Zhou if ((fp = std::fopen(filePath.c_str(), "w")) == nullptr) 901f4682712SMarri Devender Rao { 902f2646271SRavi Teja lg2::error( 903f2646271SRavi Teja "Error opening the file to write the CSR, FILENAME:{FILENAME}", 904f2646271SRavi Teja "FILENAME", filePath); 905f4682712SMarri Devender Rao elog<InternalFailure>(); 906f4682712SMarri Devender Rao } 907f4682712SMarri Devender Rao 908f4682712SMarri Devender Rao int rc = PEM_write_X509_REQ(fp, x509Req.get()); 909f4682712SMarri Devender Rao if (!rc) 910f4682712SMarri Devender Rao { 911f2646271SRavi Teja lg2::error("PEM write routine failed, FILENAME:{FILENAME}", "FILENAME", 912f2646271SRavi Teja filePath); 913f4682712SMarri Devender Rao std::fclose(fp); 914f4682712SMarri Devender Rao elog<InternalFailure>(); 915f4682712SMarri Devender Rao } 916f4682712SMarri Devender Rao std::fclose(fp); 917f4682712SMarri Devender Rao } 918f4682712SMarri Devender Rao 919db029c95SKowalski, Kamil void Manager::createCertificates() 920db029c95SKowalski, Kamil { 921db029c95SKowalski, Kamil auto certObjectPath = objectPath + '/'; 922db029c95SKowalski, Kamil 923e3d47cd4SNan Zhou if (certType == CertificateType::authority) 924db029c95SKowalski, Kamil { 925fe590c4eSZbigniew Lukwinski // Check whether install path is a directory. 926db029c95SKowalski, Kamil if (!fs::is_directory(certInstallPath)) 927db029c95SKowalski, Kamil { 928f2646271SRavi Teja lg2::error("Certificate installation path exists and it is " 929db029c95SKowalski, Kamil "not a directory"); 930db029c95SKowalski, Kamil elog<InternalFailure>(); 9316ec13c8fSNan Zhou } 9326ec13c8fSNan Zhou 9336ec13c8fSNan Zhou // If the authorities list exists, recover from it and return 934223e4604SPatrick Williams if (fs::path authoritiesListFilePath = fs::path(certInstallPath) / 935223e4604SPatrick Williams defaultAuthoritiesListFileName; 9366ec13c8fSNan Zhou fs::exists(authoritiesListFilePath)) 9376ec13c8fSNan Zhou { 9386ec13c8fSNan Zhou // remove all other files and directories 9396ec13c8fSNan Zhou for (auto& path : fs::directory_iterator(certInstallPath)) 9406ec13c8fSNan Zhou { 9416ec13c8fSNan Zhou if (path.path() != authoritiesListFilePath) 9426ec13c8fSNan Zhou { 9436ec13c8fSNan Zhou fs::remove_all(path); 9446ec13c8fSNan Zhou } 9456ec13c8fSNan Zhou } 9466ec13c8fSNan Zhou installAll(authoritiesListFilePath); 947db029c95SKowalski, Kamil return; 948db029c95SKowalski, Kamil } 949db029c95SKowalski, Kamil 950db029c95SKowalski, Kamil for (auto& path : fs::directory_iterator(certInstallPath)) 951ffad1ef1SMarri Devender Rao { 952ffad1ef1SMarri Devender Rao try 953ffad1ef1SMarri Devender Rao { 9542f3563ccSZbigniew Lukwinski // Assume here any regular file located in certificate directory 9552f3563ccSZbigniew Lukwinski // contains certificates body. Do not want to use soft links 9562f3563ccSZbigniew Lukwinski // would add value. 9572f3563ccSZbigniew Lukwinski if (fs::is_regular_file(path)) 9582f3563ccSZbigniew Lukwinski { 959db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 960db029c95SKowalski, Kamil bus, certObjectPath + std::to_string(certIdCounter++), 961cf06ccdcSNan Zhou certType, certInstallPath, path.path(), 962698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/true)); 9632f3563ccSZbigniew Lukwinski } 964ffad1ef1SMarri Devender Rao } 965ffad1ef1SMarri Devender Rao catch (const InternalFailure& e) 966ffad1ef1SMarri Devender Rao { 967ffad1ef1SMarri Devender Rao report<InternalFailure>(); 968ffad1ef1SMarri Devender Rao } 969ffad1ef1SMarri Devender Rao catch (const InvalidCertificate& e) 970ffad1ef1SMarri Devender Rao { 971cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 972cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 973ffad1ef1SMarri Devender Rao } 974ffad1ef1SMarri Devender Rao } 975db029c95SKowalski, Kamil } 976db029c95SKowalski, Kamil else if (fs::exists(certInstallPath)) 977db029c95SKowalski, Kamil { 978db029c95SKowalski, Kamil try 979db029c95SKowalski, Kamil { 980db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 9812f3563ccSZbigniew Lukwinski bus, certObjectPath + '1', certType, certInstallPath, 982698a5743SWilly Tu certInstallPath, certWatchPtr.get(), *this, /*restore=*/false)); 983db029c95SKowalski, Kamil } 984db029c95SKowalski, Kamil catch (const InternalFailure& e) 985db029c95SKowalski, Kamil { 986db029c95SKowalski, Kamil report<InternalFailure>(); 987db029c95SKowalski, Kamil } 988db029c95SKowalski, Kamil catch (const InvalidCertificate& e) 989db029c95SKowalski, Kamil { 990cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 991cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 992db029c95SKowalski, Kamil } 993db029c95SKowalski, Kamil } 994db029c95SKowalski, Kamil } 995c6e58c7eSRamesh Iyyar 996c6e58c7eSRamesh Iyyar void Manager::createRSAPrivateKeyFile() 997c6e58c7eSRamesh Iyyar { 998223e4604SPatrick Williams fs::path rsaPrivateKeyFileName = certParentInstallPath / 999223e4604SPatrick Williams defaultRSAPrivateKeyFileName; 1000c6e58c7eSRamesh Iyyar 1001c6e58c7eSRamesh Iyyar try 1002c6e58c7eSRamesh Iyyar { 1003c6e58c7eSRamesh Iyyar if (!fs::exists(rsaPrivateKeyFileName)) 1004c6e58c7eSRamesh Iyyar { 1005cf06ccdcSNan Zhou writePrivateKey(generateRSAKeyPair(supportedKeyBitLength), 1006718eef37SNan Zhou defaultRSAPrivateKeyFileName); 1007c6e58c7eSRamesh Iyyar } 1008c6e58c7eSRamesh Iyyar } 1009c6e58c7eSRamesh Iyyar catch (const InternalFailure& e) 1010c6e58c7eSRamesh Iyyar { 1011c6e58c7eSRamesh Iyyar report<InternalFailure>(); 1012c6e58c7eSRamesh Iyyar } 1013c6e58c7eSRamesh Iyyar } 1014c6e58c7eSRamesh Iyyar 1015cf06ccdcSNan Zhou EVPPkeyPtr Manager::getRSAKeyPair(const int64_t keyBitLength) 1016c6e58c7eSRamesh Iyyar { 1017cf06ccdcSNan Zhou if (keyBitLength != supportedKeyBitLength) 1018c6e58c7eSRamesh Iyyar { 1019f2646271SRavi Teja lg2::error( 1020f2646271SRavi Teja "Given Key bit length is not supported, GIVENKEYBITLENGTH:" 1021f2646271SRavi Teja "{GIVENKEYBITLENGTH}, SUPPORTEDKEYBITLENGTH:{SUPPORTEDKEYBITLENGTH}", 1022f2646271SRavi Teja "GIVENKEYBITLENGTH", keyBitLength, "SUPPORTEDKEYBITLENGTH", 1023f2646271SRavi Teja supportedKeyBitLength); 1024c6e58c7eSRamesh Iyyar elog<InvalidArgument>( 1025c6e58c7eSRamesh Iyyar Argument::ARGUMENT_NAME("KEYBITLENGTH"), 1026c6e58c7eSRamesh Iyyar Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 1027c6e58c7eSRamesh Iyyar } 1028223e4604SPatrick Williams fs::path rsaPrivateKeyFileName = certParentInstallPath / 1029223e4604SPatrick Williams defaultRSAPrivateKeyFileName; 1030c6e58c7eSRamesh Iyyar 1031c6e58c7eSRamesh Iyyar FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 1032c6e58c7eSRamesh Iyyar if (!privateKeyFile) 1033c6e58c7eSRamesh Iyyar { 1034f2646271SRavi Teja lg2::error( 1035f2646271SRavi Teja "Unable to open RSA private key file to read, RSAKEYFILE:{RSAKEYFILE}," 1036f2646271SRavi Teja "ERRORREASON:{ERRORREASON}", 1037f2646271SRavi Teja "RSAKEYFILE", rsaPrivateKeyFileName, "ERRORREASON", 1038f2646271SRavi Teja strerror(errno)); 1039c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1040c6e58c7eSRamesh Iyyar } 1041c6e58c7eSRamesh Iyyar 1042cf06ccdcSNan Zhou EVPPkeyPtr privateKey( 1043c6e58c7eSRamesh Iyyar PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 1044c6e58c7eSRamesh Iyyar ::EVP_PKEY_free); 1045c6e58c7eSRamesh Iyyar std::fclose(privateKeyFile); 1046c6e58c7eSRamesh Iyyar 1047c6e58c7eSRamesh Iyyar if (!privateKey) 1048c6e58c7eSRamesh Iyyar { 1049f2646271SRavi Teja lg2::error("Error occurred during PEM_read_PrivateKey call"); 1050c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1051c6e58c7eSRamesh Iyyar } 1052c6e58c7eSRamesh Iyyar return privateKey; 1053c6e58c7eSRamesh Iyyar } 10542f3563ccSZbigniew Lukwinski 10552f3563ccSZbigniew Lukwinski void Manager::storageUpdate() 10562f3563ccSZbigniew Lukwinski { 1057e3d47cd4SNan Zhou if (certType == CertificateType::authority) 10582f3563ccSZbigniew Lukwinski { 10592f3563ccSZbigniew Lukwinski // Remove symbolic links in the certificate directory 10602f3563ccSZbigniew Lukwinski for (auto& certPath : fs::directory_iterator(certInstallPath)) 10612f3563ccSZbigniew Lukwinski { 10622f3563ccSZbigniew Lukwinski try 10632f3563ccSZbigniew Lukwinski { 10642f3563ccSZbigniew Lukwinski if (fs::is_symlink(certPath)) 10652f3563ccSZbigniew Lukwinski { 10662f3563ccSZbigniew Lukwinski fs::remove(certPath); 10672f3563ccSZbigniew Lukwinski } 10682f3563ccSZbigniew Lukwinski } 10692f3563ccSZbigniew Lukwinski catch (const std::exception& e) 10702f3563ccSZbigniew Lukwinski { 1071f2646271SRavi Teja lg2::error( 1072f2646271SRavi Teja "Failed to remove symlink for certificate, ERR:{ERR} SYMLINK:{SYMLINK}", 1073f2646271SRavi Teja "ERR", e, "SYMLINK", certPath.path().string()); 10742f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 10752f3563ccSZbigniew Lukwinski } 10762f3563ccSZbigniew Lukwinski } 10772f3563ccSZbigniew Lukwinski } 10782f3563ccSZbigniew Lukwinski 10792f3563ccSZbigniew Lukwinski for (const auto& cert : installedCerts) 10802f3563ccSZbigniew Lukwinski { 10812f3563ccSZbigniew Lukwinski cert->storageUpdate(); 10822f3563ccSZbigniew Lukwinski } 10832f3563ccSZbigniew Lukwinski } 10842f3563ccSZbigniew Lukwinski 1085cf06ccdcSNan Zhou void Manager::reloadOrReset(const std::string& unit) 10862f3563ccSZbigniew Lukwinski { 10872f3563ccSZbigniew Lukwinski if (!unit.empty()) 10882f3563ccSZbigniew Lukwinski { 10892f3563ccSZbigniew Lukwinski try 10902f3563ccSZbigniew Lukwinski { 1091cf06ccdcSNan Zhou constexpr auto defaultSystemdService = "org.freedesktop.systemd1"; 1092cf06ccdcSNan Zhou constexpr auto defaultSystemdObjectPath = 1093cf06ccdcSNan Zhou "/org/freedesktop/systemd1"; 1094cf06ccdcSNan Zhou constexpr auto defaultSystemdInterface = 10952f3563ccSZbigniew Lukwinski "org.freedesktop.systemd1.Manager"; 1096cf06ccdcSNan Zhou auto method = bus.new_method_call( 1097cf06ccdcSNan Zhou defaultSystemdService, defaultSystemdObjectPath, 1098cf06ccdcSNan Zhou defaultSystemdInterface, "ReloadOrRestartUnit"); 10992f3563ccSZbigniew Lukwinski method.append(unit, "replace"); 11002f3563ccSZbigniew Lukwinski bus.call_noreply(method); 11012f3563ccSZbigniew Lukwinski } 1102b3dbfb37SPatrick Williams catch (const sdbusplus::exception_t& e) 11032f3563ccSZbigniew Lukwinski { 1104f2646271SRavi Teja lg2::error( 1105f2646271SRavi Teja "Failed to reload or restart service, ERR:{ERR}, UNIT:{UNIT}", 1106f2646271SRavi Teja "ERR", e, "UNIT", unit); 11072f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 11082f3563ccSZbigniew Lukwinski } 11092f3563ccSZbigniew Lukwinski } 11102f3563ccSZbigniew Lukwinski } 11112f3563ccSZbigniew Lukwinski 11122f3563ccSZbigniew Lukwinski bool Manager::isCertificateUnique(const std::string& filePath, 11132f3563ccSZbigniew Lukwinski const Certificate* const certToDrop) 11142f3563ccSZbigniew Lukwinski { 11152f3563ccSZbigniew Lukwinski if (std::any_of( 11162f3563ccSZbigniew Lukwinski installedCerts.begin(), installedCerts.end(), 1117223e4604SPatrick Williams [&filePath, certToDrop](const std::unique_ptr<Certificate>& cert) { 11182f3563ccSZbigniew Lukwinski return cert.get() != certToDrop && cert->isSame(filePath); 11192f3563ccSZbigniew Lukwinski })) 11202f3563ccSZbigniew Lukwinski { 11212f3563ccSZbigniew Lukwinski return false; 11222f3563ccSZbigniew Lukwinski } 11232f3563ccSZbigniew Lukwinski else 11242f3563ccSZbigniew Lukwinski { 11252f3563ccSZbigniew Lukwinski return true; 11262f3563ccSZbigniew Lukwinski } 11272f3563ccSZbigniew Lukwinski } 11282f3563ccSZbigniew Lukwinski 1129e1289adfSNan Zhou } // namespace phosphor::certs 1130