1014be0bfSNan Zhou #include "config.h" 2014be0bfSNan Zhou 3cfbc8dc8SJayanth Othayoth #include "certs_manager.hpp" 4cfbc8dc8SJayanth Othayoth 5*6ec13c8fSNan Zhou #include "x509_utils.hpp" 6*6ec13c8fSNan 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 18a3bb38fbSZbigniew Kurzynski #include <algorithm> 19014be0bfSNan Zhou #include <array> 20014be0bfSNan Zhou #include <cerrno> 21014be0bfSNan Zhou #include <chrono> 22014be0bfSNan Zhou #include <csignal> 23014be0bfSNan Zhou #include <cstdio> 24014be0bfSNan Zhou #include <cstdlib> 25014be0bfSNan Zhou #include <cstring> 26014be0bfSNan Zhou #include <exception> 27*6ec13c8fSNan Zhou #include <fstream> 286ceec40bSMarri Devender Rao #include <phosphor-logging/elog-errors.hpp> 29014be0bfSNan Zhou #include <phosphor-logging/elog.hpp> 30014be0bfSNan Zhou #include <phosphor-logging/log.hpp> 31014be0bfSNan Zhou #include <sdbusplus/bus.hpp> 32014be0bfSNan Zhou #include <sdbusplus/exception.hpp> 33014be0bfSNan Zhou #include <sdbusplus/message.hpp> 34014be0bfSNan Zhou #include <sdeventplus/source/base.hpp> 35014be0bfSNan Zhou #include <sdeventplus/source/child.hpp> 36014be0bfSNan Zhou #include <utility> 3713bf74e4SMarri Devender Rao #include <xyz/openbmc_project/Certs/error.hpp> 38cfbc8dc8SJayanth Othayoth #include <xyz/openbmc_project/Common/error.hpp> 392f3563ccSZbigniew Lukwinski 40e1289adfSNan Zhou namespace phosphor::certs 41cfbc8dc8SJayanth Othayoth { 42cf06ccdcSNan Zhou namespace 43cf06ccdcSNan Zhou { 44cf06ccdcSNan Zhou namespace fs = std::filesystem; 45cf06ccdcSNan Zhou using ::phosphor::logging::commit; 46cf06ccdcSNan Zhou using ::phosphor::logging::elog; 47cf06ccdcSNan Zhou using ::phosphor::logging::entry; 48cf06ccdcSNan Zhou using ::phosphor::logging::level; 49cf06ccdcSNan Zhou using ::phosphor::logging::log; 50cf06ccdcSNan Zhou using ::phosphor::logging::report; 51cfbc8dc8SJayanth Othayoth 52cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 53cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 54cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 55cf06ccdcSNan Zhou using NotAllowedReason = 56cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON; 57cf06ccdcSNan Zhou using InvalidCertificateReason = ::phosphor::logging::xyz::openbmc_project:: 58cf06ccdcSNan Zhou Certs::InvalidCertificate::REASON; 59cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 60cf06ccdcSNan Zhou using Argument = 61cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::InvalidArgument; 62c6e58c7eSRamesh Iyyar 63cf06ccdcSNan Zhou // RAII support for openSSL functions. 64cf06ccdcSNan Zhou using X509ReqPtr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>; 65cf06ccdcSNan Zhou using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>; 66cf06ccdcSNan Zhou using BignumPtr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>; 67*6ec13c8fSNan Zhou using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>; 68cf06ccdcSNan Zhou 69cf06ccdcSNan Zhou constexpr int supportedKeyBitLength = 2048; 70cf06ccdcSNan Zhou constexpr int defaultKeyBitLength = 2048; 71cf06ccdcSNan Zhou // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 72cf06ccdcSNan Zhou constexpr auto defaultKeyCurveID = "secp224r1"; 73*6ec13c8fSNan Zhou // PEM certificate block markers, defined in go/rfc/7468. 74*6ec13c8fSNan Zhou constexpr std::string_view beginCertificate = "-----BEGIN CERTIFICATE-----"; 75*6ec13c8fSNan Zhou constexpr std::string_view endCertificate = "-----END CERTIFICATE-----"; 76*6ec13c8fSNan Zhou 77*6ec13c8fSNan Zhou /** 78*6ec13c8fSNan Zhou * @brief Splits the given authorities list file and returns an array of 79*6ec13c8fSNan Zhou * individual PEM encoded x509 certificate. 80*6ec13c8fSNan Zhou * 81*6ec13c8fSNan Zhou * @param[in] sourceFilePath - Path to the authorities list file. 82*6ec13c8fSNan Zhou * 83*6ec13c8fSNan Zhou * @return An array of individual PEM encoded x509 certificate 84*6ec13c8fSNan Zhou */ 85*6ec13c8fSNan Zhou std::vector<std::string> splitCertificates(const std::string& sourceFilePath) 86*6ec13c8fSNan Zhou { 87*6ec13c8fSNan Zhou std::ifstream inputCertFileStream; 88*6ec13c8fSNan Zhou inputCertFileStream.exceptions( 89*6ec13c8fSNan Zhou std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); 90*6ec13c8fSNan Zhou 91*6ec13c8fSNan Zhou std::stringstream pemStream; 92*6ec13c8fSNan Zhou std::vector<std::string> certificatesList; 93*6ec13c8fSNan Zhou try 94*6ec13c8fSNan Zhou { 95*6ec13c8fSNan Zhou inputCertFileStream.open(sourceFilePath); 96*6ec13c8fSNan Zhou pemStream << inputCertFileStream.rdbuf(); 97*6ec13c8fSNan Zhou inputCertFileStream.close(); 98*6ec13c8fSNan Zhou } 99*6ec13c8fSNan Zhou catch (const std::exception& e) 100*6ec13c8fSNan Zhou { 101*6ec13c8fSNan Zhou log<level::ERR>("Failed to read certificates list", 102*6ec13c8fSNan Zhou entry("ERR=%s", e.what()), 103*6ec13c8fSNan Zhou entry("SRC=%s", sourceFilePath.c_str())); 104*6ec13c8fSNan Zhou elog<InternalFailure>(); 105*6ec13c8fSNan Zhou } 106*6ec13c8fSNan Zhou std::string pem = pemStream.str(); 107*6ec13c8fSNan Zhou size_t begin = 0; 108*6ec13c8fSNan Zhou // |begin| points to the current start position for searching the next 109*6ec13c8fSNan Zhou // |beginCertificate| block. When we find the beginning of the certificate, 110*6ec13c8fSNan Zhou // we extract the content between the beginning and the end of the current 111*6ec13c8fSNan Zhou // certificate. And finally we move |begin| to the end of the current 112*6ec13c8fSNan Zhou // certificate to start searching the next potential certificate. 113*6ec13c8fSNan Zhou for (begin = pem.find(beginCertificate, begin); begin != std::string::npos; 114*6ec13c8fSNan Zhou begin = pem.find(beginCertificate, begin)) 115*6ec13c8fSNan Zhou { 116*6ec13c8fSNan Zhou size_t end = pem.find(endCertificate, begin); 117*6ec13c8fSNan Zhou if (end == std::string::npos) 118*6ec13c8fSNan Zhou { 119*6ec13c8fSNan Zhou log<level::ERR>( 120*6ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END"); 121*6ec13c8fSNan Zhou elog<InvalidCertificate>(InvalidCertificateReason( 122*6ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END")); 123*6ec13c8fSNan Zhou } 124*6ec13c8fSNan Zhou end += endCertificate.size(); 125*6ec13c8fSNan Zhou certificatesList.emplace_back(pem.substr(begin, end - begin)); 126*6ec13c8fSNan Zhou begin = end; 127*6ec13c8fSNan Zhou } 128*6ec13c8fSNan Zhou return certificatesList; 129*6ec13c8fSNan Zhou } 130*6ec13c8fSNan Zhou 131cf06ccdcSNan Zhou } // namespace 132f4682712SMarri Devender Rao 133f4682712SMarri Devender Rao Manager::Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event, 134cf06ccdcSNan Zhou const char* path, CertificateType type, 135cf06ccdcSNan Zhou const std::string& unit, const std::string& installPath) : 136cf06ccdcSNan Zhou internal::ManagerInterface(bus, path), 137f4682712SMarri Devender Rao bus(bus), event(event), objectPath(path), certType(type), 138c6e58c7eSRamesh Iyyar unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)), 139c6e58c7eSRamesh Iyyar certParentInstallPath(fs::path(certInstallPath).parent_path()) 140cfbc8dc8SJayanth Othayoth { 141db5c6fc8SMarri Devender Rao try 142db5c6fc8SMarri Devender Rao { 143fe590c4eSZbigniew Lukwinski // Create certificate directory if not existing. 144bf3cf751SNan Zhou // Set correct certificate directory permissions. 145fe590c4eSZbigniew Lukwinski fs::path certDirectory; 146b57d75e2SMarri Devender Rao try 147b57d75e2SMarri Devender Rao { 148cf06ccdcSNan Zhou if (certType == CertificateType::Authority) 149b57d75e2SMarri Devender Rao { 150fe590c4eSZbigniew Lukwinski certDirectory = certInstallPath; 151b57d75e2SMarri Devender Rao } 152fe590c4eSZbigniew Lukwinski else 153fe590c4eSZbigniew Lukwinski { 154fe590c4eSZbigniew Lukwinski certDirectory = certParentInstallPath; 155fe590c4eSZbigniew Lukwinski } 156fe590c4eSZbigniew Lukwinski 157fe590c4eSZbigniew Lukwinski if (!fs::exists(certDirectory)) 158fe590c4eSZbigniew Lukwinski { 159fe590c4eSZbigniew Lukwinski fs::create_directories(certDirectory); 160fe590c4eSZbigniew Lukwinski } 161fe590c4eSZbigniew Lukwinski 162667286e4SMarri Devender Rao auto permission = fs::perms::owner_read | fs::perms::owner_write | 163667286e4SMarri Devender Rao fs::perms::owner_exec; 164db5c6fc8SMarri Devender Rao fs::permissions(certDirectory, permission, 165db5c6fc8SMarri Devender Rao fs::perm_options::replace); 1662f3563ccSZbigniew Lukwinski storageUpdate(); 167b57d75e2SMarri Devender Rao } 16871957992SPatrick Williams catch (const fs::filesystem_error& e) 169b57d75e2SMarri Devender Rao { 170db5c6fc8SMarri Devender Rao log<level::ERR>( 171db5c6fc8SMarri Devender Rao "Failed to create directory", entry("ERR=%s", e.what()), 172b57d75e2SMarri Devender Rao entry("DIRECTORY=%s", certParentInstallPath.c_str())); 173b57d75e2SMarri Devender Rao report<InternalFailure>(); 174b57d75e2SMarri Devender Rao } 175b57d75e2SMarri Devender Rao 176c6e58c7eSRamesh Iyyar // Generating RSA private key file if certificate type is server/client 177cf06ccdcSNan Zhou if (certType != CertificateType::Authority) 178c6e58c7eSRamesh Iyyar { 179c6e58c7eSRamesh Iyyar createRSAPrivateKeyFile(); 180c6e58c7eSRamesh Iyyar } 181c6e58c7eSRamesh Iyyar 182ffad1ef1SMarri Devender Rao // restore any existing certificates 183db029c95SKowalski, Kamil createCertificates(); 184ffad1ef1SMarri Devender Rao 185ffad1ef1SMarri Devender Rao // watch is not required for authority certificates 186cf06ccdcSNan Zhou if (certType != CertificateType::Authority) 187ffad1ef1SMarri Devender Rao { 188ffad1ef1SMarri Devender Rao // watch for certificate file create/replace 189ffad1ef1SMarri Devender Rao certWatchPtr = std::make_unique< 190ffad1ef1SMarri Devender Rao Watch>(event, certInstallPath, [this]() { 191bf7c588cSMarri Devender Rao try 192bf7c588cSMarri Devender Rao { 193ffad1ef1SMarri Devender Rao // if certificate file existing update it 194db029c95SKowalski, Kamil if (!installedCerts.empty()) 195ffad1ef1SMarri Devender Rao { 196db5c6fc8SMarri Devender Rao log<level::INFO>("Inotify callback to update " 197db5c6fc8SMarri Devender Rao "certificate properties"); 198db029c95SKowalski, Kamil installedCerts[0]->populateProperties(); 199ffad1ef1SMarri Devender Rao } 200ffad1ef1SMarri Devender Rao else 201ffad1ef1SMarri Devender Rao { 202ffad1ef1SMarri Devender Rao log<level::INFO>( 203ffad1ef1SMarri Devender Rao "Inotify callback to create certificate object"); 204db029c95SKowalski, Kamil createCertificates(); 205ffad1ef1SMarri Devender Rao } 206bf7c588cSMarri Devender Rao } 207bf7c588cSMarri Devender Rao catch (const InternalFailure& e) 208bf7c588cSMarri Devender Rao { 209ffad1ef1SMarri Devender Rao commit<InternalFailure>(); 210bf7c588cSMarri Devender Rao } 211bf7c588cSMarri Devender Rao catch (const InvalidCertificate& e) 212bf7c588cSMarri Devender Rao { 213ffad1ef1SMarri Devender Rao commit<InvalidCertificate>(); 214bf7c588cSMarri Devender Rao } 215ffad1ef1SMarri Devender Rao }); 216bf7c588cSMarri Devender Rao } 217db029c95SKowalski, Kamil else 218db029c95SKowalski, Kamil { 219db5c6fc8SMarri Devender Rao try 220db5c6fc8SMarri Devender Rao { 221db5c6fc8SMarri Devender Rao const std::string singleCertPath = "/etc/ssl/certs/Root-CA.pem"; 222db5c6fc8SMarri Devender Rao if (fs::exists(singleCertPath) && !fs::is_empty(singleCertPath)) 223db029c95SKowalski, Kamil { 224db029c95SKowalski, Kamil log<level::NOTICE>( 225db029c95SKowalski, Kamil "Legacy certificate detected, will be installed from: ", 226db5c6fc8SMarri Devender Rao entry("SINGLE_CERTPATH=%s", singleCertPath.c_str())); 227db5c6fc8SMarri Devender Rao install(singleCertPath); 228db5c6fc8SMarri Devender Rao if (!fs::remove(singleCertPath)) 229db029c95SKowalski, Kamil { 230db029c95SKowalski, Kamil log<level::ERR>( 231db029c95SKowalski, Kamil "Unable to remove old certificate from: ", 232db5c6fc8SMarri Devender Rao entry("SINGLE_CERTPATH=%s", 233db5c6fc8SMarri Devender Rao singleCertPath.c_str())); 234db029c95SKowalski, Kamil elog<InternalFailure>(); 235db029c95SKowalski, Kamil } 236db029c95SKowalski, Kamil } 237db029c95SKowalski, Kamil } 238db5c6fc8SMarri Devender Rao catch (const std::exception& ex) 239db5c6fc8SMarri Devender Rao { 240db5c6fc8SMarri Devender Rao log<level::ERR>("Error in restoring legacy certificate", 241db5c6fc8SMarri Devender Rao entry("ERROR_STR=%s", ex.what())); 242db5c6fc8SMarri Devender Rao } 243db5c6fc8SMarri Devender Rao } 244db5c6fc8SMarri Devender Rao } 24571957992SPatrick Williams catch (const std::exception& ex) 246db5c6fc8SMarri Devender Rao { 247db5c6fc8SMarri Devender Rao log<level::ERR>("Error in certificate manager constructor", 248db5c6fc8SMarri Devender Rao entry("ERROR_STR=%s", ex.what())); 249db5c6fc8SMarri Devender Rao } 250dd74bd20SJayanth Othayoth } 251589159f2SJayanth Othayoth 25206a69d7bSZbigniew Kurzynski std::string Manager::install(const std::string filePath) 253cfbc8dc8SJayanth Othayoth { 254cf06ccdcSNan Zhou if (certType != CertificateType::Authority && !installedCerts.empty()) 2551396511dSMarri Devender Rao { 256cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 2571396511dSMarri Devender Rao } 258cf06ccdcSNan Zhou else if (certType == CertificateType::Authority && 259718eef37SNan Zhou installedCerts.size() >= maxNumAuthorityCertificates) 2603b07b77aSZbigniew Lukwinski { 261cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificates limit reached")); 2623b07b77aSZbigniew Lukwinski } 263ffad1ef1SMarri Devender Rao 2642f3563ccSZbigniew Lukwinski std::string certObjectPath; 2652f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath)) 2662f3563ccSZbigniew Lukwinski { 2672f3563ccSZbigniew Lukwinski certObjectPath = objectPath + '/' + std::to_string(certIdCounter); 268db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 2692f3563ccSZbigniew Lukwinski bus, certObjectPath, certType, certInstallPath, filePath, 270cf06ccdcSNan Zhou certWatchPtr.get(), *this)); 2712f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 2722f3563ccSZbigniew Lukwinski certIdCounter++; 2732f3563ccSZbigniew Lukwinski } 2742f3563ccSZbigniew Lukwinski else 2752f3563ccSZbigniew Lukwinski { 276cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 2772f3563ccSZbigniew Lukwinski } 2782f3563ccSZbigniew Lukwinski 27906a69d7bSZbigniew Kurzynski return certObjectPath; 280589159f2SJayanth Othayoth } 281ae70b3daSDeepak Kodihalli 282*6ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 283*6ec13c8fSNan Zhou Manager::installAll(const std::string filePath) 284*6ec13c8fSNan Zhou { 285*6ec13c8fSNan Zhou if (certType != CertificateType::Authority) 286*6ec13c8fSNan Zhou { 287*6ec13c8fSNan Zhou elog<NotAllowed>( 288*6ec13c8fSNan Zhou NotAllowedReason("The InstallAll interface is only allowed for " 289*6ec13c8fSNan Zhou "Authority certificates")); 290*6ec13c8fSNan Zhou } 291*6ec13c8fSNan Zhou 292*6ec13c8fSNan Zhou if (!installedCerts.empty()) 293*6ec13c8fSNan Zhou { 294*6ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason( 295*6ec13c8fSNan Zhou "There are already root certificates; Call DeleteAll then " 296*6ec13c8fSNan Zhou "InstallAll, or use ReplaceAll")); 297*6ec13c8fSNan Zhou } 298*6ec13c8fSNan Zhou 299*6ec13c8fSNan Zhou fs::path sourceFile(filePath); 300*6ec13c8fSNan Zhou if (!fs::exists(sourceFile)) 301*6ec13c8fSNan Zhou { 302*6ec13c8fSNan Zhou log<level::ERR>("File is Missing", entry("FILE=%s", filePath.c_str())); 303*6ec13c8fSNan Zhou elog<InternalFailure>(); 304*6ec13c8fSNan Zhou } 305*6ec13c8fSNan Zhou std::vector<std::string> authorities = splitCertificates(sourceFile); 306*6ec13c8fSNan Zhou if (authorities.size() > maxNumAuthorityCertificates) 307*6ec13c8fSNan Zhou { 308*6ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificates limit reached")); 309*6ec13c8fSNan Zhou } 310*6ec13c8fSNan Zhou 311*6ec13c8fSNan Zhou fs::path authorityStore(certInstallPath); 312*6ec13c8fSNan Zhou fs::path authoritiesListFile = 313*6ec13c8fSNan Zhou authorityStore / defaultAuthoritiesListFileName; 314*6ec13c8fSNan Zhou 315*6ec13c8fSNan Zhou // Atomically install all the certificates 316*6ec13c8fSNan Zhou fs::path tempPath = Certificate::generateUniqueFilePath(authorityStore); 317*6ec13c8fSNan Zhou fs::create_directory(tempPath); 318*6ec13c8fSNan Zhou // Copies the authorities list 319*6ec13c8fSNan Zhou Certificate::copyCertificate(sourceFile, 320*6ec13c8fSNan Zhou tempPath / defaultAuthoritiesListFileName); 321*6ec13c8fSNan Zhou std::vector<std::unique_ptr<Certificate>> tempCertificates; 322*6ec13c8fSNan Zhou uint64_t tempCertIdCounter = certIdCounter; 323*6ec13c8fSNan Zhou X509StorePtr x509Store = getX509Store(sourceFile); 324*6ec13c8fSNan Zhou for (const auto& authority : authorities) 325*6ec13c8fSNan Zhou { 326*6ec13c8fSNan Zhou std::string certObjectPath = 327*6ec13c8fSNan Zhou objectPath + '/' + std::to_string(tempCertIdCounter); 328*6ec13c8fSNan Zhou tempCertificates.emplace_back(std::make_unique<Certificate>( 329*6ec13c8fSNan Zhou bus, certObjectPath, certType, tempPath, *x509Store, authority, 330*6ec13c8fSNan Zhou certWatchPtr.get(), *this)); 331*6ec13c8fSNan Zhou tempCertIdCounter++; 332*6ec13c8fSNan Zhou } 333*6ec13c8fSNan Zhou 334*6ec13c8fSNan Zhou // We are good now, issue swap 335*6ec13c8fSNan Zhou installedCerts = std::move(tempCertificates); 336*6ec13c8fSNan Zhou certIdCounter = tempCertIdCounter; 337*6ec13c8fSNan Zhou // Rename all the certificates including the authorities list 338*6ec13c8fSNan Zhou for (const fs::path& f : fs::directory_iterator(tempPath)) 339*6ec13c8fSNan Zhou { 340*6ec13c8fSNan Zhou if (fs::is_symlink(f)) 341*6ec13c8fSNan Zhou { 342*6ec13c8fSNan Zhou continue; 343*6ec13c8fSNan Zhou } 344*6ec13c8fSNan Zhou fs::rename(/*from=*/f, /*to=*/certInstallPath / f.filename()); 345*6ec13c8fSNan Zhou } 346*6ec13c8fSNan Zhou // Update file locations and create symbol links 347*6ec13c8fSNan Zhou for (const auto& cert : installedCerts) 348*6ec13c8fSNan Zhou { 349*6ec13c8fSNan Zhou cert->setCertInstallPath(certInstallPath); 350*6ec13c8fSNan Zhou cert->setCertFilePath(certInstallPath / 351*6ec13c8fSNan Zhou fs::path(cert->getCertFilePath()).filename()); 352*6ec13c8fSNan Zhou cert->storageUpdate(); 353*6ec13c8fSNan Zhou } 354*6ec13c8fSNan Zhou // Remove the temporary folder 355*6ec13c8fSNan Zhou fs::remove_all(tempPath); 356*6ec13c8fSNan Zhou 357*6ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> objects; 358*6ec13c8fSNan Zhou for (const auto& certificate : installedCerts) 359*6ec13c8fSNan Zhou { 360*6ec13c8fSNan Zhou objects.emplace_back(certificate->getObjectPath()); 361*6ec13c8fSNan Zhou } 362*6ec13c8fSNan Zhou 363*6ec13c8fSNan Zhou reloadOrReset(unitToRestart); 364*6ec13c8fSNan Zhou return objects; 365*6ec13c8fSNan Zhou } 366*6ec13c8fSNan Zhou 367*6ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 368*6ec13c8fSNan Zhou Manager::replaceAll(std::string filePath) 369*6ec13c8fSNan Zhou { 370*6ec13c8fSNan Zhou installedCerts.clear(); 371*6ec13c8fSNan Zhou certIdCounter = 1; 372*6ec13c8fSNan Zhou storageUpdate(); 373*6ec13c8fSNan Zhou return installAll(std::move(filePath)); 374*6ec13c8fSNan Zhou } 375*6ec13c8fSNan Zhou 376a3bb38fbSZbigniew Kurzynski void Manager::deleteAll() 377ae70b3daSDeepak Kodihalli { 3786ceec40bSMarri Devender Rao // TODO: #Issue 4 when a certificate is deleted system auto generates 3796ceec40bSMarri Devender Rao // certificate file. At present we are not supporting creation of 3806ceec40bSMarri Devender Rao // certificate object for the auto-generated certificate file as 3816ceec40bSMarri Devender Rao // deletion if only applicable for REST server and Bmcweb does not allow 3826ceec40bSMarri Devender Rao // deletion of certificates 383db029c95SKowalski, Kamil installedCerts.clear(); 384*6ec13c8fSNan Zhou // If the authorities list exists, delete it as well 385*6ec13c8fSNan Zhou if (certType == CertificateType::Authority) 386*6ec13c8fSNan Zhou { 387*6ec13c8fSNan Zhou if (fs::path authoritiesList = 388*6ec13c8fSNan Zhou fs::path(certInstallPath) / defaultAuthoritiesListFileName; 389*6ec13c8fSNan Zhou fs::exists(authoritiesList)) 390*6ec13c8fSNan Zhou { 391*6ec13c8fSNan Zhou fs::remove(authoritiesList); 392*6ec13c8fSNan Zhou } 393*6ec13c8fSNan Zhou } 394*6ec13c8fSNan Zhou certIdCounter = 1; 3952f3563ccSZbigniew Lukwinski storageUpdate(); 3962f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 397ae70b3daSDeepak Kodihalli } 398f4682712SMarri Devender Rao 3992f3563ccSZbigniew Lukwinski void Manager::deleteCertificate(const Certificate* const certificate) 400a3bb38fbSZbigniew Kurzynski { 401a3bb38fbSZbigniew Kurzynski std::vector<std::unique_ptr<Certificate>>::iterator const& certIt = 402a3bb38fbSZbigniew Kurzynski std::find_if(installedCerts.begin(), installedCerts.end(), 4032f3563ccSZbigniew Lukwinski [certificate](std::unique_ptr<Certificate> const& cert) { 4042f3563ccSZbigniew Lukwinski return (cert.get() == certificate); 405a3bb38fbSZbigniew Kurzynski }); 406a3bb38fbSZbigniew Kurzynski if (certIt != installedCerts.end()) 407a3bb38fbSZbigniew Kurzynski { 408a3bb38fbSZbigniew Kurzynski installedCerts.erase(certIt); 4092f3563ccSZbigniew Lukwinski storageUpdate(); 4102f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 411a3bb38fbSZbigniew Kurzynski } 412a3bb38fbSZbigniew Kurzynski else 413a3bb38fbSZbigniew Kurzynski { 414a3bb38fbSZbigniew Kurzynski log<level::ERR>("Certificate does not exist", 4152f3563ccSZbigniew Lukwinski entry("ID=%s", certificate->getCertId().c_str())); 4162f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 4172f3563ccSZbigniew Lukwinski } 4182f3563ccSZbigniew Lukwinski } 4192f3563ccSZbigniew Lukwinski 4202f3563ccSZbigniew Lukwinski void Manager::replaceCertificate(Certificate* const certificate, 4212f3563ccSZbigniew Lukwinski const std::string& filePath) 4222f3563ccSZbigniew Lukwinski { 4232f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath, certificate)) 4242f3563ccSZbigniew Lukwinski { 4252f3563ccSZbigniew Lukwinski certificate->install(filePath); 4262f3563ccSZbigniew Lukwinski storageUpdate(); 4272f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 4282f3563ccSZbigniew Lukwinski } 4292f3563ccSZbigniew Lukwinski else 4302f3563ccSZbigniew Lukwinski { 431cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 432a3bb38fbSZbigniew Kurzynski } 433a3bb38fbSZbigniew Kurzynski } 434a3bb38fbSZbigniew Kurzynski 435f4682712SMarri Devender Rao std::string Manager::generateCSR( 436f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 437f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 438f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 439f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 440f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 441f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 442f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 443f4682712SMarri Devender Rao { 444f4682712SMarri Devender Rao // We support only one CSR. 445f4682712SMarri Devender Rao csrPtr.reset(nullptr); 446f4682712SMarri Devender Rao auto pid = fork(); 447f4682712SMarri Devender Rao if (pid == -1) 448f4682712SMarri Devender Rao { 449f4682712SMarri Devender Rao log<level::ERR>("Error occurred during forking process"); 450f4682712SMarri Devender Rao report<InternalFailure>(); 451f4682712SMarri Devender Rao } 452f4682712SMarri Devender Rao else if (pid == 0) 453f4682712SMarri Devender Rao { 454f4682712SMarri Devender Rao try 455f4682712SMarri Devender Rao { 456f4682712SMarri Devender Rao generateCSRHelper(alternativeNames, challengePassword, city, 457f4682712SMarri Devender Rao commonName, contactPerson, country, email, 458f4682712SMarri Devender Rao givenName, initials, keyBitLength, keyCurveId, 459f4682712SMarri Devender Rao keyPairAlgorithm, keyUsage, organization, 460f4682712SMarri Devender Rao organizationalUnit, state, surname, 461f4682712SMarri Devender Rao unstructuredName); 462f4682712SMarri Devender Rao exit(EXIT_SUCCESS); 463f4682712SMarri Devender Rao } 464f4682712SMarri Devender Rao catch (const InternalFailure& e) 465f4682712SMarri Devender Rao { 466f4682712SMarri Devender Rao // commit the error reported in child process and exit 467f4682712SMarri Devender Rao // Callback method from SDEvent Loop looks for exit status 468f4682712SMarri Devender Rao exit(EXIT_FAILURE); 469f4682712SMarri Devender Rao commit<InternalFailure>(); 470f4682712SMarri Devender Rao } 471d2393f23SRamesh Iyyar catch (const InvalidArgument& e) 472d2393f23SRamesh Iyyar { 473d2393f23SRamesh Iyyar // commit the error reported in child process and exit 474d2393f23SRamesh Iyyar // Callback method from SDEvent Loop looks for exit status 475d2393f23SRamesh Iyyar exit(EXIT_FAILURE); 476d2393f23SRamesh Iyyar commit<InvalidArgument>(); 477d2393f23SRamesh Iyyar } 478f4682712SMarri Devender Rao } 479f4682712SMarri Devender Rao else 480f4682712SMarri Devender Rao { 481f4682712SMarri Devender Rao using namespace sdeventplus::source; 482f4682712SMarri Devender Rao Child::Callback callback = [this](Child& eventSource, 483f4682712SMarri Devender Rao const siginfo_t* si) { 484f4682712SMarri Devender Rao eventSource.set_enabled(Enabled::On); 485f4682712SMarri Devender Rao if (si->si_status != 0) 486f4682712SMarri Devender Rao { 487f4682712SMarri Devender Rao this->createCSRObject(Status::FAILURE); 488f4682712SMarri Devender Rao } 489f4682712SMarri Devender Rao else 490f4682712SMarri Devender Rao { 491f4682712SMarri Devender Rao this->createCSRObject(Status::SUCCESS); 492f4682712SMarri Devender Rao } 493f4682712SMarri Devender Rao }; 494f4682712SMarri Devender Rao try 495f4682712SMarri Devender Rao { 496f4682712SMarri Devender Rao sigset_t ss; 497f4682712SMarri Devender Rao if (sigemptyset(&ss) < 0) 498f4682712SMarri Devender Rao { 499f4682712SMarri Devender Rao log<level::ERR>("Unable to initialize signal set"); 500f4682712SMarri Devender Rao elog<InternalFailure>(); 501f4682712SMarri Devender Rao } 502f4682712SMarri Devender Rao if (sigaddset(&ss, SIGCHLD) < 0) 503f4682712SMarri Devender Rao { 504f4682712SMarri Devender Rao log<level::ERR>("Unable to add signal to signal set"); 505f4682712SMarri Devender Rao elog<InternalFailure>(); 506f4682712SMarri Devender Rao } 507f4682712SMarri Devender Rao 508f4682712SMarri Devender Rao // Block SIGCHLD first, so that the event loop can handle it 509cfb5802aSNan Zhou if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0) 510f4682712SMarri Devender Rao { 511f4682712SMarri Devender Rao log<level::ERR>("Unable to block signal"); 512f4682712SMarri Devender Rao elog<InternalFailure>(); 513f4682712SMarri Devender Rao } 514f4682712SMarri Devender Rao if (childPtr) 515f4682712SMarri Devender Rao { 516f4682712SMarri Devender Rao childPtr.reset(); 517f4682712SMarri Devender Rao } 518f4682712SMarri Devender Rao childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 519f4682712SMarri Devender Rao std::move(callback)); 520f4682712SMarri Devender Rao } 521f4682712SMarri Devender Rao catch (const InternalFailure& e) 522f4682712SMarri Devender Rao { 523f4682712SMarri Devender Rao commit<InternalFailure>(); 524f4682712SMarri Devender Rao } 525f4682712SMarri Devender Rao } 526f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 527f4682712SMarri Devender Rao return csrObjectPath; 528f4682712SMarri Devender Rao } 529f4682712SMarri Devender Rao 530db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates() 531ffad1ef1SMarri Devender Rao { 532db029c95SKowalski, Kamil return installedCerts; 533ffad1ef1SMarri Devender Rao } 534ffad1ef1SMarri Devender Rao 535f4682712SMarri Devender Rao void Manager::generateCSRHelper( 536f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 537f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 538f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 539f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 540f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 541f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 542f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 543f4682712SMarri Devender Rao { 544f4682712SMarri Devender Rao int ret = 0; 545f4682712SMarri Devender Rao 546f4682712SMarri Devender Rao // set version of x509 req 547f4682712SMarri Devender Rao int nVersion = 1; 548f4682712SMarri Devender Rao // TODO: Issue#6 need to make version number configurable 549cf06ccdcSNan Zhou X509ReqPtr x509Req(X509_REQ_new(), ::X509_REQ_free); 550f4682712SMarri Devender Rao ret = X509_REQ_set_version(x509Req.get(), nVersion); 551f4682712SMarri Devender Rao if (ret == 0) 552f4682712SMarri Devender Rao { 553bf3cf751SNan Zhou log<level::ERR>("Error occurred during X509_REQ_set_version call"); 554f4682712SMarri Devender Rao elog<InternalFailure>(); 555f4682712SMarri Devender Rao } 556f4682712SMarri Devender Rao 557f4682712SMarri Devender Rao // set subject of x509 req 558f4682712SMarri Devender Rao X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 559f4682712SMarri Devender Rao 560f4682712SMarri Devender Rao if (!alternativeNames.empty()) 561f4682712SMarri Devender Rao { 562f4682712SMarri Devender Rao for (auto& name : alternativeNames) 563f4682712SMarri Devender Rao { 564f4682712SMarri Devender Rao addEntry(x509Name, "subjectAltName", name); 565f4682712SMarri Devender Rao } 566f4682712SMarri Devender Rao } 567f4682712SMarri Devender Rao addEntry(x509Name, "challengePassword", challengePassword); 568f4682712SMarri Devender Rao addEntry(x509Name, "L", city); 569f4682712SMarri Devender Rao addEntry(x509Name, "CN", commonName); 570f4682712SMarri Devender Rao addEntry(x509Name, "name", contactPerson); 571f4682712SMarri Devender Rao addEntry(x509Name, "C", country); 572f4682712SMarri Devender Rao addEntry(x509Name, "emailAddress", email); 573f4682712SMarri Devender Rao addEntry(x509Name, "GN", givenName); 574f4682712SMarri Devender Rao addEntry(x509Name, "initials", initials); 575f4682712SMarri Devender Rao addEntry(x509Name, "algorithm", keyPairAlgorithm); 576f4682712SMarri Devender Rao if (!keyUsage.empty()) 577f4682712SMarri Devender Rao { 578f4682712SMarri Devender Rao for (auto& usage : keyUsage) 579f4682712SMarri Devender Rao { 5807641105dSMarri Devender Rao if (isExtendedKeyUsage(usage)) 5817641105dSMarri Devender Rao { 5827641105dSMarri Devender Rao addEntry(x509Name, "extendedKeyUsage", usage); 5837641105dSMarri Devender Rao } 5847641105dSMarri Devender Rao else 5857641105dSMarri Devender Rao { 586f4682712SMarri Devender Rao addEntry(x509Name, "keyUsage", usage); 587f4682712SMarri Devender Rao } 588f4682712SMarri Devender Rao } 5897641105dSMarri Devender Rao } 590f4682712SMarri Devender Rao addEntry(x509Name, "O", organization); 591dc91fb61SJayanth Othayoth addEntry(x509Name, "OU", organizationalUnit); 592f4682712SMarri Devender Rao addEntry(x509Name, "ST", state); 593f4682712SMarri Devender Rao addEntry(x509Name, "SN", surname); 594f4682712SMarri Devender Rao addEntry(x509Name, "unstructuredName", unstructuredName); 595f4682712SMarri Devender Rao 596cf06ccdcSNan Zhou EVPPkeyPtr pKey(nullptr, ::EVP_PKEY_free); 5978a09b52aSRamesh Iyyar 5988a09b52aSRamesh Iyyar log<level::INFO>("Given Key pair algorithm", 5998a09b52aSRamesh Iyyar entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str())); 6008a09b52aSRamesh Iyyar 6018a09b52aSRamesh Iyyar // Used EC algorithm as default if user did not give algorithm type. 6028a09b52aSRamesh Iyyar if (keyPairAlgorithm == "RSA") 603c6e58c7eSRamesh Iyyar pKey = getRSAKeyPair(keyBitLength); 6048a09b52aSRamesh Iyyar else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 605c6e58c7eSRamesh Iyyar pKey = generateECKeyPair(keyCurveId); 6068a09b52aSRamesh Iyyar else 6078a09b52aSRamesh Iyyar { 6088a09b52aSRamesh Iyyar log<level::ERR>("Given Key pair algorithm is not supported. Supporting " 6098a09b52aSRamesh Iyyar "RSA and EC only"); 6108a09b52aSRamesh Iyyar elog<InvalidArgument>( 6118a09b52aSRamesh Iyyar Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 6128a09b52aSRamesh Iyyar Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 6138a09b52aSRamesh Iyyar } 6148a09b52aSRamesh Iyyar 6158a09b52aSRamesh Iyyar ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 6168a09b52aSRamesh Iyyar if (ret == 0) 6178a09b52aSRamesh Iyyar { 618bf3cf751SNan Zhou log<level::ERR>("Error occurred while setting Public key"); 6198a09b52aSRamesh Iyyar elog<InternalFailure>(); 6208a09b52aSRamesh Iyyar } 6218a09b52aSRamesh Iyyar 6228a09b52aSRamesh Iyyar // Write private key to file 623718eef37SNan Zhou writePrivateKey(pKey, defaultPrivateKeyFileName); 624f4682712SMarri Devender Rao 625f4682712SMarri Devender Rao // set sign key of x509 req 626f4682712SMarri Devender Rao ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 6278a09b52aSRamesh Iyyar if (ret == 0) 628f4682712SMarri Devender Rao { 629bf3cf751SNan Zhou log<level::ERR>("Error occurred while signing key of x509"); 630f4682712SMarri Devender Rao elog<InternalFailure>(); 631f4682712SMarri Devender Rao } 6328a09b52aSRamesh Iyyar 633f4682712SMarri Devender Rao log<level::INFO>("Writing CSR to file"); 634718eef37SNan Zhou fs::path csrFilePath = certParentInstallPath / defaultCSRFileName; 635c6e58c7eSRamesh Iyyar writeCSR(csrFilePath.string(), x509Req); 636f4682712SMarri Devender Rao } 637f4682712SMarri Devender Rao 6387641105dSMarri Devender Rao bool Manager::isExtendedKeyUsage(const std::string& usage) 6397641105dSMarri Devender Rao { 6407641105dSMarri Devender Rao const static std::array<const char*, 6> usageList = { 6417641105dSMarri Devender Rao "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 6427641105dSMarri Devender Rao "Timestamping", "CodeSigning", "EmailProtection"}; 6437641105dSMarri Devender Rao auto it = std::find_if( 6447641105dSMarri Devender Rao usageList.begin(), usageList.end(), 6457641105dSMarri Devender Rao [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); }); 6467641105dSMarri Devender Rao return it != usageList.end(); 6477641105dSMarri Devender Rao } 648cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateRSAKeyPair(const int64_t keyBitLength) 649f4682712SMarri Devender Rao { 6508a09b52aSRamesh Iyyar int64_t keyBitLen = keyBitLength; 651f4682712SMarri Devender Rao // set keybit length to default value if not set 6528a09b52aSRamesh Iyyar if (keyBitLen <= 0) 653f4682712SMarri Devender Rao { 6548a09b52aSRamesh Iyyar log<level::INFO>( 6558a09b52aSRamesh Iyyar "KeyBitLength is not given.Hence, using default KeyBitLength", 656cf06ccdcSNan Zhou entry("DEFAULTKEYBITLENGTH=%d", defaultKeyBitLength)); 657cf06ccdcSNan Zhou keyBitLen = defaultKeyBitLength; 658f4682712SMarri Devender Rao } 65926fb83efSPatrick Williams 66026fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 66126fb83efSPatrick Williams 66226fb83efSPatrick Williams // generate rsa key 663cf06ccdcSNan Zhou BignumPtr bne(BN_new(), ::BN_free); 66426fb83efSPatrick Williams auto ret = BN_set_word(bne.get(), RSA_F4); 66526fb83efSPatrick Williams if (ret == 0) 66626fb83efSPatrick Williams { 667bf3cf751SNan Zhou log<level::ERR>("Error occurred during BN_set_word call"); 66826fb83efSPatrick Williams elog<InternalFailure>(); 66926fb83efSPatrick Williams } 670762da74eSNan Zhou using RSAPtr = std::unique_ptr<RSA, decltype(&::RSA_free)>; 671762da74eSNan Zhou RSAPtr rsa(RSA_new(), ::RSA_free); 672762da74eSNan Zhou ret = RSA_generate_key_ex(rsa.get(), keyBitLen, bne.get(), nullptr); 673f4682712SMarri Devender Rao if (ret != 1) 674f4682712SMarri Devender Rao { 675bf3cf751SNan Zhou log<level::ERR>("Error occurred during RSA_generate_key_ex call", 6768a09b52aSRamesh Iyyar entry("KEYBITLENGTH=%PRIu64", keyBitLen)); 677f4682712SMarri Devender Rao elog<InternalFailure>(); 678f4682712SMarri Devender Rao } 679f4682712SMarri Devender Rao 680f4682712SMarri Devender Rao // set public key of x509 req 681cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 682762da74eSNan Zhou ret = EVP_PKEY_assign_RSA(pKey.get(), rsa.get()); 683f4682712SMarri Devender Rao if (ret == 0) 684f4682712SMarri Devender Rao { 685bf3cf751SNan Zhou log<level::ERR>("Error occurred during assign rsa key into EVP"); 686f4682712SMarri Devender Rao elog<InternalFailure>(); 687f4682712SMarri Devender Rao } 688762da74eSNan Zhou // Now |rsa| is managed by |pKey| 689762da74eSNan Zhou rsa.release(); 6908a09b52aSRamesh Iyyar return pKey; 69126fb83efSPatrick Williams 69226fb83efSPatrick Williams #else 69326fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 69426fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr), &::EVP_PKEY_CTX_free); 69526fb83efSPatrick Williams if (!ctx) 69626fb83efSPatrick Williams { 697bf3cf751SNan Zhou log<level::ERR>("Error occurred creating EVP_PKEY_CTX from algorithm"); 69826fb83efSPatrick Williams elog<InternalFailure>(); 69926fb83efSPatrick Williams } 70026fb83efSPatrick Williams 70126fb83efSPatrick Williams if ((EVP_PKEY_keygen_init(ctx.get()) <= 0) || 70226fb83efSPatrick Williams (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), keyBitLen) <= 0)) 70326fb83efSPatrick Williams 70426fb83efSPatrick Williams { 705bf3cf751SNan Zhou log<level::ERR>("Error occurred initializing keygen context"); 70626fb83efSPatrick Williams elog<InternalFailure>(); 70726fb83efSPatrick Williams } 70826fb83efSPatrick Williams 70926fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 71026fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 71126fb83efSPatrick Williams { 712bf3cf751SNan Zhou log<level::ERR>("Error occurred during generate EC key"); 71326fb83efSPatrick Williams elog<InternalFailure>(); 71426fb83efSPatrick Williams } 71526fb83efSPatrick Williams 71626fb83efSPatrick Williams return {pKey, &::EVP_PKEY_free}; 71726fb83efSPatrick Williams #endif 7188a09b52aSRamesh Iyyar } 7198a09b52aSRamesh Iyyar 720cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateECKeyPair(const std::string& curveId) 7218a09b52aSRamesh Iyyar { 7228a09b52aSRamesh Iyyar std::string curId(curveId); 7238a09b52aSRamesh Iyyar 7248a09b52aSRamesh Iyyar if (curId.empty()) 7258a09b52aSRamesh Iyyar { 7268a09b52aSRamesh Iyyar log<level::INFO>( 7278a09b52aSRamesh Iyyar "KeyCurveId is not given. Hence using default curve id", 728cf06ccdcSNan Zhou entry("DEFAULTKEYCURVEID=%s", defaultKeyCurveID)); 729cf06ccdcSNan Zhou curId = defaultKeyCurveID; 7308a09b52aSRamesh Iyyar } 7318a09b52aSRamesh Iyyar 7328a09b52aSRamesh Iyyar int ecGrp = OBJ_txt2nid(curId.c_str()); 7338a09b52aSRamesh Iyyar if (ecGrp == NID_undef) 7348a09b52aSRamesh Iyyar { 7358a09b52aSRamesh Iyyar log<level::ERR>( 736bf3cf751SNan Zhou "Error occurred during convert the curve id string format into NID", 7378a09b52aSRamesh Iyyar entry("KEYCURVEID=%s", curId.c_str())); 7388a09b52aSRamesh Iyyar elog<InternalFailure>(); 7398a09b52aSRamesh Iyyar } 7408a09b52aSRamesh Iyyar 74126fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 74226fb83efSPatrick Williams 7438a09b52aSRamesh Iyyar EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 7448a09b52aSRamesh Iyyar 745cfb5802aSNan Zhou if (ecKey == nullptr) 7468a09b52aSRamesh Iyyar { 7478a09b52aSRamesh Iyyar log<level::ERR>( 748bf3cf751SNan Zhou "Error occurred during create the EC_Key object from NID", 7498a09b52aSRamesh Iyyar entry("ECGROUP=%d", ecGrp)); 7508a09b52aSRamesh Iyyar elog<InternalFailure>(); 7518a09b52aSRamesh Iyyar } 7528a09b52aSRamesh Iyyar 7538a09b52aSRamesh Iyyar // If you want to save a key and later load it with 7548a09b52aSRamesh Iyyar // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 7558a09b52aSRamesh Iyyar // flag on the key. 7568a09b52aSRamesh Iyyar EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 7578a09b52aSRamesh Iyyar 7588a09b52aSRamesh Iyyar int ret = EC_KEY_generate_key(ecKey); 7598a09b52aSRamesh Iyyar 7608a09b52aSRamesh Iyyar if (ret == 0) 7618a09b52aSRamesh Iyyar { 7628a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 763bf3cf751SNan Zhou log<level::ERR>("Error occurred during generate EC key"); 7648a09b52aSRamesh Iyyar elog<InternalFailure>(); 7658a09b52aSRamesh Iyyar } 7668a09b52aSRamesh Iyyar 767cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 7688a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 7698a09b52aSRamesh Iyyar if (ret == 0) 7708a09b52aSRamesh Iyyar { 7718a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 772bf3cf751SNan Zhou log<level::ERR>("Error occurred during assign EC Key into EVP"); 7738a09b52aSRamesh Iyyar elog<InternalFailure>(); 7748a09b52aSRamesh Iyyar } 7758a09b52aSRamesh Iyyar 7768a09b52aSRamesh Iyyar return pKey; 77726fb83efSPatrick Williams 77826fb83efSPatrick Williams #else 77926fb83efSPatrick Williams auto holder_of_key = [](EVP_PKEY* key) { 78026fb83efSPatrick Williams return std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>{ 78126fb83efSPatrick Williams key, &::EVP_PKEY_free}; 78226fb83efSPatrick Williams }; 78326fb83efSPatrick Williams 78426fb83efSPatrick Williams // Create context to set up curve parameters. 78526fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 78626fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr), &::EVP_PKEY_CTX_free); 78726fb83efSPatrick Williams if (!ctx) 78826fb83efSPatrick Williams { 789bf3cf751SNan Zhou log<level::ERR>("Error occurred creating EVP_PKEY_CTX for params"); 79026fb83efSPatrick Williams elog<InternalFailure>(); 79126fb83efSPatrick Williams } 79226fb83efSPatrick Williams 79326fb83efSPatrick Williams // Set up curve parameters. 79426fb83efSPatrick Williams EVP_PKEY* params = nullptr; 79526fb83efSPatrick Williams 79626fb83efSPatrick Williams if ((EVP_PKEY_paramgen_init(ctx.get()) <= 0) || 79726fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_param_enc(ctx.get(), OPENSSL_EC_NAMED_CURVE) <= 79826fb83efSPatrick Williams 0) || 79926fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), ecGrp) <= 0) || 80026fb83efSPatrick Williams (EVP_PKEY_paramgen(ctx.get(), ¶ms) <= 0)) 80126fb83efSPatrick Williams { 802bf3cf751SNan Zhou log<level::ERR>("Error occurred setting curve parameters"); 80326fb83efSPatrick Williams elog<InternalFailure>(); 80426fb83efSPatrick Williams } 80526fb83efSPatrick Williams 80626fb83efSPatrick Williams // Move parameters to RAII holder. 80726fb83efSPatrick Williams auto pparms = holder_of_key(params); 80826fb83efSPatrick Williams 80926fb83efSPatrick Williams // Create new context for key. 81026fb83efSPatrick Williams ctx.reset(EVP_PKEY_CTX_new_from_pkey(nullptr, params, nullptr)); 81126fb83efSPatrick Williams 81226fb83efSPatrick Williams if (!ctx || (EVP_PKEY_keygen_init(ctx.get()) <= 0)) 81326fb83efSPatrick Williams { 814bf3cf751SNan Zhou log<level::ERR>("Error occurred initializing keygen context"); 81526fb83efSPatrick Williams elog<InternalFailure>(); 81626fb83efSPatrick Williams } 81726fb83efSPatrick Williams 81826fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 81926fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 82026fb83efSPatrick Williams { 821bf3cf751SNan Zhou log<level::ERR>("Error occurred during generate EC key"); 82226fb83efSPatrick Williams elog<InternalFailure>(); 82326fb83efSPatrick Williams } 82426fb83efSPatrick Williams 82526fb83efSPatrick Williams return holder_of_key(pKey); 82626fb83efSPatrick Williams #endif 8278a09b52aSRamesh Iyyar } 8288a09b52aSRamesh Iyyar 829cf06ccdcSNan Zhou void Manager::writePrivateKey(const EVPPkeyPtr& pKey, 830c6e58c7eSRamesh Iyyar const std::string& privKeyFileName) 8318a09b52aSRamesh Iyyar { 8328a09b52aSRamesh Iyyar log<level::INFO>("Writing private key to file"); 833f4682712SMarri Devender Rao // write private key to file 834c6e58c7eSRamesh Iyyar fs::path privKeyPath = certParentInstallPath / privKeyFileName; 835f4682712SMarri Devender Rao 836f4682712SMarri Devender Rao FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 837cfb5802aSNan Zhou if (fp == nullptr) 838f4682712SMarri Devender Rao { 839bf3cf751SNan Zhou log<level::ERR>("Error occurred creating private key file"); 840f4682712SMarri Devender Rao elog<InternalFailure>(); 841f4682712SMarri Devender Rao } 842cfb5802aSNan Zhou int ret = 843cfb5802aSNan Zhou PEM_write_PrivateKey(fp, pKey.get(), nullptr, nullptr, 0, 0, nullptr); 844f4682712SMarri Devender Rao std::fclose(fp); 845f4682712SMarri Devender Rao if (ret == 0) 846f4682712SMarri Devender Rao { 847bf3cf751SNan Zhou log<level::ERR>("Error occurred while writing private key to file"); 848f4682712SMarri Devender Rao elog<InternalFailure>(); 849f4682712SMarri Devender Rao } 850f4682712SMarri Devender Rao } 851f4682712SMarri Devender Rao 852f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field, 853f4682712SMarri Devender Rao const std::string& bytes) 854f4682712SMarri Devender Rao { 855f4682712SMarri Devender Rao if (bytes.empty()) 856f4682712SMarri Devender Rao { 857f4682712SMarri Devender Rao return; 858f4682712SMarri Devender Rao } 859f4682712SMarri Devender Rao int ret = X509_NAME_add_entry_by_txt( 860f4682712SMarri Devender Rao x509Name, field, MBSTRING_ASC, 861f4682712SMarri Devender Rao reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 862f4682712SMarri Devender Rao if (ret != 1) 863f4682712SMarri Devender Rao { 864f4682712SMarri Devender Rao log<level::ERR>("Unable to set entry", entry("FIELD=%s", field), 865f4682712SMarri Devender Rao entry("VALUE=%s", bytes.c_str())); 866f4682712SMarri Devender Rao elog<InternalFailure>(); 867f4682712SMarri Devender Rao } 868f4682712SMarri Devender Rao } 869f4682712SMarri Devender Rao 870f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status) 871f4682712SMarri Devender Rao { 872f4682712SMarri Devender Rao if (csrPtr) 873f4682712SMarri Devender Rao { 874f4682712SMarri Devender Rao csrPtr.reset(nullptr); 875f4682712SMarri Devender Rao } 876f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 877f4682712SMarri Devender Rao csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 878f4682712SMarri Devender Rao certInstallPath.c_str(), status); 879f4682712SMarri Devender Rao } 880f4682712SMarri Devender Rao 881cf06ccdcSNan Zhou void Manager::writeCSR(const std::string& filePath, const X509ReqPtr& x509Req) 882f4682712SMarri Devender Rao { 883f4682712SMarri Devender Rao if (fs::exists(filePath)) 884f4682712SMarri Devender Rao { 885f4682712SMarri Devender Rao log<level::INFO>("Removing the existing file", 886f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 887f4682712SMarri Devender Rao if (!fs::remove(filePath.c_str())) 888f4682712SMarri Devender Rao { 889f4682712SMarri Devender Rao log<level::ERR>("Unable to remove the file", 890f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 891f4682712SMarri Devender Rao elog<InternalFailure>(); 892f4682712SMarri Devender Rao } 893f4682712SMarri Devender Rao } 894f4682712SMarri Devender Rao 895cfb5802aSNan Zhou FILE* fp = nullptr; 896f4682712SMarri Devender Rao 897cfb5802aSNan Zhou if ((fp = std::fopen(filePath.c_str(), "w")) == nullptr) 898f4682712SMarri Devender Rao { 899f4682712SMarri Devender Rao log<level::ERR>("Error opening the file to write the CSR", 900f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 901f4682712SMarri Devender Rao elog<InternalFailure>(); 902f4682712SMarri Devender Rao } 903f4682712SMarri Devender Rao 904f4682712SMarri Devender Rao int rc = PEM_write_X509_REQ(fp, x509Req.get()); 905f4682712SMarri Devender Rao if (!rc) 906f4682712SMarri Devender Rao { 907f4682712SMarri Devender Rao log<level::ERR>("PEM write routine failed", 908f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 909f4682712SMarri Devender Rao std::fclose(fp); 910f4682712SMarri Devender Rao elog<InternalFailure>(); 911f4682712SMarri Devender Rao } 912f4682712SMarri Devender Rao std::fclose(fp); 913f4682712SMarri Devender Rao } 914f4682712SMarri Devender Rao 915db029c95SKowalski, Kamil void Manager::createCertificates() 916db029c95SKowalski, Kamil { 917db029c95SKowalski, Kamil auto certObjectPath = objectPath + '/'; 918db029c95SKowalski, Kamil 919cf06ccdcSNan Zhou if (certType == CertificateType::Authority) 920db029c95SKowalski, Kamil { 921fe590c4eSZbigniew Lukwinski // Check whether install path is a directory. 922db029c95SKowalski, Kamil if (!fs::is_directory(certInstallPath)) 923db029c95SKowalski, Kamil { 924db029c95SKowalski, Kamil log<level::ERR>("Certificate installation path exists and it is " 925db029c95SKowalski, Kamil "not a directory"); 926db029c95SKowalski, Kamil elog<InternalFailure>(); 927*6ec13c8fSNan Zhou } 928*6ec13c8fSNan Zhou 929*6ec13c8fSNan Zhou // If the authorities list exists, recover from it and return 930*6ec13c8fSNan Zhou if (fs::path authoritiesListFilePath = 931*6ec13c8fSNan Zhou fs::path(certInstallPath) / defaultAuthoritiesListFileName; 932*6ec13c8fSNan Zhou fs::exists(authoritiesListFilePath)) 933*6ec13c8fSNan Zhou { 934*6ec13c8fSNan Zhou // remove all other files and directories 935*6ec13c8fSNan Zhou for (auto& path : fs::directory_iterator(certInstallPath)) 936*6ec13c8fSNan Zhou { 937*6ec13c8fSNan Zhou if (path.path() != authoritiesListFilePath) 938*6ec13c8fSNan Zhou { 939*6ec13c8fSNan Zhou fs::remove_all(path); 940*6ec13c8fSNan Zhou } 941*6ec13c8fSNan Zhou } 942*6ec13c8fSNan Zhou installAll(authoritiesListFilePath); 943db029c95SKowalski, Kamil return; 944db029c95SKowalski, Kamil } 945db029c95SKowalski, Kamil 946db029c95SKowalski, Kamil for (auto& path : fs::directory_iterator(certInstallPath)) 947ffad1ef1SMarri Devender Rao { 948ffad1ef1SMarri Devender Rao try 949ffad1ef1SMarri Devender Rao { 9502f3563ccSZbigniew Lukwinski // Assume here any regular file located in certificate directory 9512f3563ccSZbigniew Lukwinski // contains certificates body. Do not want to use soft links 9522f3563ccSZbigniew Lukwinski // would add value. 9532f3563ccSZbigniew Lukwinski if (fs::is_regular_file(path)) 9542f3563ccSZbigniew Lukwinski { 955db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 956db029c95SKowalski, Kamil bus, certObjectPath + std::to_string(certIdCounter++), 957cf06ccdcSNan Zhou certType, certInstallPath, path.path(), 958cf06ccdcSNan Zhou certWatchPtr.get(), *this)); 9592f3563ccSZbigniew Lukwinski } 960ffad1ef1SMarri Devender Rao } 961ffad1ef1SMarri Devender Rao catch (const InternalFailure& e) 962ffad1ef1SMarri Devender Rao { 963ffad1ef1SMarri Devender Rao report<InternalFailure>(); 964ffad1ef1SMarri Devender Rao } 965ffad1ef1SMarri Devender Rao catch (const InvalidCertificate& e) 966ffad1ef1SMarri Devender Rao { 967cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 968cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 969ffad1ef1SMarri Devender Rao } 970ffad1ef1SMarri Devender Rao } 971db029c95SKowalski, Kamil } 972db029c95SKowalski, Kamil else if (fs::exists(certInstallPath)) 973db029c95SKowalski, Kamil { 974db029c95SKowalski, Kamil try 975db029c95SKowalski, Kamil { 976db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 9772f3563ccSZbigniew Lukwinski bus, certObjectPath + '1', certType, certInstallPath, 978cf06ccdcSNan Zhou certInstallPath, certWatchPtr.get(), *this)); 979db029c95SKowalski, Kamil } 980db029c95SKowalski, Kamil catch (const InternalFailure& e) 981db029c95SKowalski, Kamil { 982db029c95SKowalski, Kamil report<InternalFailure>(); 983db029c95SKowalski, Kamil } 984db029c95SKowalski, Kamil catch (const InvalidCertificate& e) 985db029c95SKowalski, Kamil { 986cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 987cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 988db029c95SKowalski, Kamil } 989db029c95SKowalski, Kamil } 990db029c95SKowalski, Kamil } 991c6e58c7eSRamesh Iyyar 992c6e58c7eSRamesh Iyyar void Manager::createRSAPrivateKeyFile() 993c6e58c7eSRamesh Iyyar { 994c6e58c7eSRamesh Iyyar fs::path rsaPrivateKeyFileName = 995718eef37SNan Zhou certParentInstallPath / defaultRSAPrivateKeyFileName; 996c6e58c7eSRamesh Iyyar 997c6e58c7eSRamesh Iyyar try 998c6e58c7eSRamesh Iyyar { 999c6e58c7eSRamesh Iyyar if (!fs::exists(rsaPrivateKeyFileName)) 1000c6e58c7eSRamesh Iyyar { 1001cf06ccdcSNan Zhou writePrivateKey(generateRSAKeyPair(supportedKeyBitLength), 1002718eef37SNan Zhou defaultRSAPrivateKeyFileName); 1003c6e58c7eSRamesh Iyyar } 1004c6e58c7eSRamesh Iyyar } 1005c6e58c7eSRamesh Iyyar catch (const InternalFailure& e) 1006c6e58c7eSRamesh Iyyar { 1007c6e58c7eSRamesh Iyyar report<InternalFailure>(); 1008c6e58c7eSRamesh Iyyar } 1009c6e58c7eSRamesh Iyyar } 1010c6e58c7eSRamesh Iyyar 1011cf06ccdcSNan Zhou EVPPkeyPtr Manager::getRSAKeyPair(const int64_t keyBitLength) 1012c6e58c7eSRamesh Iyyar { 1013cf06ccdcSNan Zhou if (keyBitLength != supportedKeyBitLength) 1014c6e58c7eSRamesh Iyyar { 1015c6e58c7eSRamesh Iyyar log<level::ERR>( 1016c6e58c7eSRamesh Iyyar "Given Key bit length is not supported", 1017c6e58c7eSRamesh Iyyar entry("GIVENKEYBITLENGTH=%d", keyBitLength), 1018cf06ccdcSNan Zhou entry("SUPPORTEDKEYBITLENGTH=%d", supportedKeyBitLength)); 1019c6e58c7eSRamesh Iyyar elog<InvalidArgument>( 1020c6e58c7eSRamesh Iyyar Argument::ARGUMENT_NAME("KEYBITLENGTH"), 1021c6e58c7eSRamesh Iyyar Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 1022c6e58c7eSRamesh Iyyar } 1023c6e58c7eSRamesh Iyyar fs::path rsaPrivateKeyFileName = 1024718eef37SNan Zhou certParentInstallPath / defaultRSAPrivateKeyFileName; 1025c6e58c7eSRamesh Iyyar 1026c6e58c7eSRamesh Iyyar FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 1027c6e58c7eSRamesh Iyyar if (!privateKeyFile) 1028c6e58c7eSRamesh Iyyar { 1029c6e58c7eSRamesh Iyyar log<level::ERR>("Unable to open RSA private key file to read", 1030c6e58c7eSRamesh Iyyar entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()), 1031c6e58c7eSRamesh Iyyar entry("ERRORREASON=%s", strerror(errno))); 1032c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1033c6e58c7eSRamesh Iyyar } 1034c6e58c7eSRamesh Iyyar 1035cf06ccdcSNan Zhou EVPPkeyPtr privateKey( 1036c6e58c7eSRamesh Iyyar PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 1037c6e58c7eSRamesh Iyyar ::EVP_PKEY_free); 1038c6e58c7eSRamesh Iyyar std::fclose(privateKeyFile); 1039c6e58c7eSRamesh Iyyar 1040c6e58c7eSRamesh Iyyar if (!privateKey) 1041c6e58c7eSRamesh Iyyar { 1042bf3cf751SNan Zhou log<level::ERR>("Error occurred during PEM_read_PrivateKey call"); 1043c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1044c6e58c7eSRamesh Iyyar } 1045c6e58c7eSRamesh Iyyar return privateKey; 1046c6e58c7eSRamesh Iyyar } 10472f3563ccSZbigniew Lukwinski 10482f3563ccSZbigniew Lukwinski void Manager::storageUpdate() 10492f3563ccSZbigniew Lukwinski { 1050cf06ccdcSNan Zhou if (certType == CertificateType::Authority) 10512f3563ccSZbigniew Lukwinski { 10522f3563ccSZbigniew Lukwinski // Remove symbolic links in the certificate directory 10532f3563ccSZbigniew Lukwinski for (auto& certPath : fs::directory_iterator(certInstallPath)) 10542f3563ccSZbigniew Lukwinski { 10552f3563ccSZbigniew Lukwinski try 10562f3563ccSZbigniew Lukwinski { 10572f3563ccSZbigniew Lukwinski if (fs::is_symlink(certPath)) 10582f3563ccSZbigniew Lukwinski { 10592f3563ccSZbigniew Lukwinski fs::remove(certPath); 10602f3563ccSZbigniew Lukwinski } 10612f3563ccSZbigniew Lukwinski } 10622f3563ccSZbigniew Lukwinski catch (const std::exception& e) 10632f3563ccSZbigniew Lukwinski { 10642f3563ccSZbigniew Lukwinski log<level::ERR>( 10652f3563ccSZbigniew Lukwinski "Failed to remove symlink for certificate", 10662f3563ccSZbigniew Lukwinski entry("ERR=%s", e.what()), 10672f3563ccSZbigniew Lukwinski entry("SYMLINK=%s", certPath.path().string().c_str())); 10682f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 10692f3563ccSZbigniew Lukwinski } 10702f3563ccSZbigniew Lukwinski } 10712f3563ccSZbigniew Lukwinski } 10722f3563ccSZbigniew Lukwinski 10732f3563ccSZbigniew Lukwinski for (const auto& cert : installedCerts) 10742f3563ccSZbigniew Lukwinski { 10752f3563ccSZbigniew Lukwinski cert->storageUpdate(); 10762f3563ccSZbigniew Lukwinski } 10772f3563ccSZbigniew Lukwinski } 10782f3563ccSZbigniew Lukwinski 1079cf06ccdcSNan Zhou void Manager::reloadOrReset(const std::string& unit) 10802f3563ccSZbigniew Lukwinski { 10812f3563ccSZbigniew Lukwinski if (!unit.empty()) 10822f3563ccSZbigniew Lukwinski { 10832f3563ccSZbigniew Lukwinski try 10842f3563ccSZbigniew Lukwinski { 1085cf06ccdcSNan Zhou constexpr auto defaultSystemdService = "org.freedesktop.systemd1"; 1086cf06ccdcSNan Zhou constexpr auto defaultSystemdObjectPath = 1087cf06ccdcSNan Zhou "/org/freedesktop/systemd1"; 1088cf06ccdcSNan Zhou constexpr auto defaultSystemdInterface = 10892f3563ccSZbigniew Lukwinski "org.freedesktop.systemd1.Manager"; 1090cf06ccdcSNan Zhou auto method = bus.new_method_call( 1091cf06ccdcSNan Zhou defaultSystemdService, defaultSystemdObjectPath, 1092cf06ccdcSNan Zhou defaultSystemdInterface, "ReloadOrRestartUnit"); 10932f3563ccSZbigniew Lukwinski method.append(unit, "replace"); 10942f3563ccSZbigniew Lukwinski bus.call_noreply(method); 10952f3563ccSZbigniew Lukwinski } 1096ca128117SPatrick Williams catch (const sdbusplus::exception::exception& e) 10972f3563ccSZbigniew Lukwinski { 10982f3563ccSZbigniew Lukwinski log<level::ERR>("Failed to reload or restart service", 10992f3563ccSZbigniew Lukwinski entry("ERR=%s", e.what()), 11002f3563ccSZbigniew Lukwinski entry("UNIT=%s", unit.c_str())); 11012f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 11022f3563ccSZbigniew Lukwinski } 11032f3563ccSZbigniew Lukwinski } 11042f3563ccSZbigniew Lukwinski } 11052f3563ccSZbigniew Lukwinski 11062f3563ccSZbigniew Lukwinski bool Manager::isCertificateUnique(const std::string& filePath, 11072f3563ccSZbigniew Lukwinski const Certificate* const certToDrop) 11082f3563ccSZbigniew Lukwinski { 11092f3563ccSZbigniew Lukwinski if (std::any_of( 11102f3563ccSZbigniew Lukwinski installedCerts.begin(), installedCerts.end(), 11112f3563ccSZbigniew Lukwinski [&filePath, certToDrop](std::unique_ptr<Certificate> const& cert) { 11122f3563ccSZbigniew Lukwinski return cert.get() != certToDrop && cert->isSame(filePath); 11132f3563ccSZbigniew Lukwinski })) 11142f3563ccSZbigniew Lukwinski { 11152f3563ccSZbigniew Lukwinski return false; 11162f3563ccSZbigniew Lukwinski } 11172f3563ccSZbigniew Lukwinski else 11182f3563ccSZbigniew Lukwinski { 11192f3563ccSZbigniew Lukwinski return true; 11202f3563ccSZbigniew Lukwinski } 11212f3563ccSZbigniew Lukwinski } 11222f3563ccSZbigniew Lukwinski 1123e1289adfSNan Zhou } // namespace phosphor::certs 1124