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 18*223e4604SPatrick Williams #include <phosphor-logging/elog-errors.hpp> 19*223e4604SPatrick Williams #include <phosphor-logging/elog.hpp> 20*223e4604SPatrick Williams #include <phosphor-logging/log.hpp> 21*223e4604SPatrick Williams #include <sdbusplus/bus.hpp> 22*223e4604SPatrick Williams #include <sdbusplus/exception.hpp> 23*223e4604SPatrick Williams #include <sdbusplus/message.hpp> 24*223e4604SPatrick Williams #include <sdeventplus/source/base.hpp> 25*223e4604SPatrick Williams #include <sdeventplus/source/child.hpp> 26*223e4604SPatrick Williams #include <xyz/openbmc_project/Certs/error.hpp> 27*223e4604SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp> 28*223e4604SPatrick 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::entry; 49cf06ccdcSNan Zhou using ::phosphor::logging::level; 50cf06ccdcSNan Zhou using ::phosphor::logging::log; 51cf06ccdcSNan Zhou using ::phosphor::logging::report; 52cfbc8dc8SJayanth Othayoth 53cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 54cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 55cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 56cf06ccdcSNan Zhou using NotAllowedReason = 57cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON; 58cf06ccdcSNan Zhou using InvalidCertificateReason = ::phosphor::logging::xyz::openbmc_project:: 59cf06ccdcSNan Zhou Certs::InvalidCertificate::REASON; 60cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 61cf06ccdcSNan Zhou using Argument = 62cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::InvalidArgument; 63c6e58c7eSRamesh Iyyar 64cf06ccdcSNan Zhou // RAII support for openSSL functions. 65cf06ccdcSNan Zhou using X509ReqPtr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>; 66cf06ccdcSNan Zhou using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>; 67cf06ccdcSNan Zhou using BignumPtr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>; 686ec13c8fSNan Zhou using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>; 69cf06ccdcSNan Zhou 70cf06ccdcSNan Zhou constexpr int supportedKeyBitLength = 2048; 71cf06ccdcSNan Zhou constexpr int defaultKeyBitLength = 2048; 72cf06ccdcSNan Zhou // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 73cf06ccdcSNan Zhou constexpr auto defaultKeyCurveID = "secp224r1"; 746ec13c8fSNan Zhou // PEM certificate block markers, defined in go/rfc/7468. 756ec13c8fSNan Zhou constexpr std::string_view beginCertificate = "-----BEGIN CERTIFICATE-----"; 766ec13c8fSNan Zhou constexpr std::string_view endCertificate = "-----END CERTIFICATE-----"; 776ec13c8fSNan Zhou 786ec13c8fSNan Zhou /** 796ec13c8fSNan Zhou * @brief Splits the given authorities list file and returns an array of 806ec13c8fSNan Zhou * individual PEM encoded x509 certificate. 816ec13c8fSNan Zhou * 826ec13c8fSNan Zhou * @param[in] sourceFilePath - Path to the authorities list file. 836ec13c8fSNan Zhou * 846ec13c8fSNan Zhou * @return An array of individual PEM encoded x509 certificate 856ec13c8fSNan Zhou */ 866ec13c8fSNan Zhou std::vector<std::string> splitCertificates(const std::string& sourceFilePath) 876ec13c8fSNan Zhou { 886ec13c8fSNan Zhou std::ifstream inputCertFileStream; 896ec13c8fSNan Zhou inputCertFileStream.exceptions( 906ec13c8fSNan Zhou std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); 916ec13c8fSNan Zhou 926ec13c8fSNan Zhou std::stringstream pemStream; 936ec13c8fSNan Zhou std::vector<std::string> certificatesList; 946ec13c8fSNan Zhou try 956ec13c8fSNan Zhou { 966ec13c8fSNan Zhou inputCertFileStream.open(sourceFilePath); 976ec13c8fSNan Zhou pemStream << inputCertFileStream.rdbuf(); 986ec13c8fSNan Zhou inputCertFileStream.close(); 996ec13c8fSNan Zhou } 1006ec13c8fSNan Zhou catch (const std::exception& e) 1016ec13c8fSNan Zhou { 1026ec13c8fSNan Zhou log<level::ERR>("Failed to read certificates list", 1036ec13c8fSNan Zhou entry("ERR=%s", e.what()), 1046ec13c8fSNan Zhou entry("SRC=%s", sourceFilePath.c_str())); 1056ec13c8fSNan Zhou elog<InternalFailure>(); 1066ec13c8fSNan Zhou } 1076ec13c8fSNan Zhou std::string pem = pemStream.str(); 1086ec13c8fSNan Zhou size_t begin = 0; 1096ec13c8fSNan Zhou // |begin| points to the current start position for searching the next 1106ec13c8fSNan Zhou // |beginCertificate| block. When we find the beginning of the certificate, 1116ec13c8fSNan Zhou // we extract the content between the beginning and the end of the current 1126ec13c8fSNan Zhou // certificate. And finally we move |begin| to the end of the current 1136ec13c8fSNan Zhou // certificate to start searching the next potential certificate. 1146ec13c8fSNan Zhou for (begin = pem.find(beginCertificate, begin); begin != std::string::npos; 1156ec13c8fSNan Zhou begin = pem.find(beginCertificate, begin)) 1166ec13c8fSNan Zhou { 1176ec13c8fSNan Zhou size_t end = pem.find(endCertificate, begin); 1186ec13c8fSNan Zhou if (end == std::string::npos) 1196ec13c8fSNan Zhou { 1206ec13c8fSNan Zhou log<level::ERR>( 1216ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END"); 1226ec13c8fSNan Zhou elog<InvalidCertificate>(InvalidCertificateReason( 1236ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END")); 1246ec13c8fSNan Zhou } 1256ec13c8fSNan Zhou end += endCertificate.size(); 1266ec13c8fSNan Zhou certificatesList.emplace_back(pem.substr(begin, end - begin)); 1276ec13c8fSNan Zhou begin = end; 1286ec13c8fSNan Zhou } 1296ec13c8fSNan Zhou return certificatesList; 1306ec13c8fSNan Zhou } 1316ec13c8fSNan Zhou 132cf06ccdcSNan Zhou } // namespace 133f4682712SMarri Devender Rao 134b3dbfb37SPatrick Williams Manager::Manager(sdbusplus::bus_t& bus, sdeventplus::Event& event, 135cf06ccdcSNan Zhou const char* path, CertificateType type, 136cf06ccdcSNan Zhou const std::string& unit, const std::string& installPath) : 137cf06ccdcSNan Zhou internal::ManagerInterface(bus, path), 138f4682712SMarri Devender Rao bus(bus), event(event), objectPath(path), certType(type), 139c6e58c7eSRamesh Iyyar unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)), 140c6e58c7eSRamesh Iyyar certParentInstallPath(fs::path(certInstallPath).parent_path()) 141cfbc8dc8SJayanth Othayoth { 142db5c6fc8SMarri Devender Rao try 143db5c6fc8SMarri Devender Rao { 144fe590c4eSZbigniew Lukwinski // Create certificate directory if not existing. 145bf3cf751SNan Zhou // Set correct certificate directory permissions. 146fe590c4eSZbigniew Lukwinski fs::path certDirectory; 147b57d75e2SMarri Devender Rao try 148b57d75e2SMarri Devender Rao { 149e3d47cd4SNan Zhou if (certType == CertificateType::authority) 150b57d75e2SMarri Devender Rao { 151fe590c4eSZbigniew Lukwinski certDirectory = certInstallPath; 152b57d75e2SMarri Devender Rao } 153fe590c4eSZbigniew Lukwinski else 154fe590c4eSZbigniew Lukwinski { 155fe590c4eSZbigniew Lukwinski certDirectory = certParentInstallPath; 156fe590c4eSZbigniew Lukwinski } 157fe590c4eSZbigniew Lukwinski 158fe590c4eSZbigniew Lukwinski if (!fs::exists(certDirectory)) 159fe590c4eSZbigniew Lukwinski { 160fe590c4eSZbigniew Lukwinski fs::create_directories(certDirectory); 161fe590c4eSZbigniew Lukwinski } 162fe590c4eSZbigniew Lukwinski 163667286e4SMarri Devender Rao auto permission = fs::perms::owner_read | fs::perms::owner_write | 164667286e4SMarri Devender Rao fs::perms::owner_exec; 165db5c6fc8SMarri Devender Rao fs::permissions(certDirectory, permission, 166db5c6fc8SMarri Devender Rao fs::perm_options::replace); 1672f3563ccSZbigniew Lukwinski storageUpdate(); 168b57d75e2SMarri Devender Rao } 16971957992SPatrick Williams catch (const fs::filesystem_error& e) 170b57d75e2SMarri Devender Rao { 171db5c6fc8SMarri Devender Rao log<level::ERR>( 172db5c6fc8SMarri Devender Rao "Failed to create directory", entry("ERR=%s", e.what()), 173b57d75e2SMarri Devender Rao entry("DIRECTORY=%s", certParentInstallPath.c_str())); 174b57d75e2SMarri Devender Rao report<InternalFailure>(); 175b57d75e2SMarri Devender Rao } 176b57d75e2SMarri Devender Rao 177c6e58c7eSRamesh Iyyar // Generating RSA private key file if certificate type is server/client 178e3d47cd4SNan Zhou if (certType != CertificateType::authority) 179c6e58c7eSRamesh Iyyar { 180c6e58c7eSRamesh Iyyar createRSAPrivateKeyFile(); 181c6e58c7eSRamesh Iyyar } 182c6e58c7eSRamesh Iyyar 183ffad1ef1SMarri Devender Rao // restore any existing certificates 184db029c95SKowalski, Kamil createCertificates(); 185ffad1ef1SMarri Devender Rao 186ffad1ef1SMarri Devender Rao // watch is not required for authority certificates 187e3d47cd4SNan Zhou if (certType != CertificateType::authority) 188ffad1ef1SMarri Devender Rao { 189ffad1ef1SMarri Devender Rao // watch for certificate file create/replace 190*223e4604SPatrick Williams certWatchPtr = std::make_unique<Watch>(event, certInstallPath, 191*223e4604SPatrick Williams [this]() { 192bf7c588cSMarri Devender Rao try 193bf7c588cSMarri Devender Rao { 194ffad1ef1SMarri Devender Rao // if certificate file existing update it 195db029c95SKowalski, Kamil if (!installedCerts.empty()) 196ffad1ef1SMarri Devender Rao { 197db5c6fc8SMarri Devender Rao log<level::INFO>("Inotify callback to update " 198db5c6fc8SMarri Devender Rao "certificate properties"); 199db029c95SKowalski, Kamil installedCerts[0]->populateProperties(); 200ffad1ef1SMarri Devender Rao } 201ffad1ef1SMarri Devender Rao else 202ffad1ef1SMarri Devender Rao { 203ffad1ef1SMarri Devender Rao log<level::INFO>( 204ffad1ef1SMarri Devender Rao "Inotify callback to create certificate object"); 205db029c95SKowalski, Kamil createCertificates(); 206ffad1ef1SMarri Devender Rao } 207bf7c588cSMarri Devender Rao } 208bf7c588cSMarri Devender Rao catch (const InternalFailure& e) 209bf7c588cSMarri Devender Rao { 210ffad1ef1SMarri Devender Rao commit<InternalFailure>(); 211bf7c588cSMarri Devender Rao } 212bf7c588cSMarri Devender Rao catch (const InvalidCertificate& e) 213bf7c588cSMarri Devender Rao { 214ffad1ef1SMarri Devender Rao commit<InvalidCertificate>(); 215bf7c588cSMarri Devender Rao } 216ffad1ef1SMarri Devender Rao }); 217bf7c588cSMarri Devender Rao } 218db029c95SKowalski, Kamil else 219db029c95SKowalski, Kamil { 220db5c6fc8SMarri Devender Rao try 221db5c6fc8SMarri Devender Rao { 222db5c6fc8SMarri Devender Rao const std::string singleCertPath = "/etc/ssl/certs/Root-CA.pem"; 223db5c6fc8SMarri Devender Rao if (fs::exists(singleCertPath) && !fs::is_empty(singleCertPath)) 224db029c95SKowalski, Kamil { 225db029c95SKowalski, Kamil log<level::NOTICE>( 226db029c95SKowalski, Kamil "Legacy certificate detected, will be installed from: ", 227db5c6fc8SMarri Devender Rao entry("SINGLE_CERTPATH=%s", singleCertPath.c_str())); 228db5c6fc8SMarri Devender Rao install(singleCertPath); 229db5c6fc8SMarri Devender Rao if (!fs::remove(singleCertPath)) 230db029c95SKowalski, Kamil { 231db029c95SKowalski, Kamil log<level::ERR>( 232db029c95SKowalski, Kamil "Unable to remove old certificate from: ", 233db5c6fc8SMarri Devender Rao entry("SINGLE_CERTPATH=%s", 234db5c6fc8SMarri Devender Rao singleCertPath.c_str())); 235db029c95SKowalski, Kamil elog<InternalFailure>(); 236db029c95SKowalski, Kamil } 237db029c95SKowalski, Kamil } 238db029c95SKowalski, Kamil } 239db5c6fc8SMarri Devender Rao catch (const std::exception& ex) 240db5c6fc8SMarri Devender Rao { 241db5c6fc8SMarri Devender Rao log<level::ERR>("Error in restoring legacy certificate", 242db5c6fc8SMarri Devender Rao entry("ERROR_STR=%s", ex.what())); 243db5c6fc8SMarri Devender Rao } 244db5c6fc8SMarri Devender Rao } 245db5c6fc8SMarri Devender Rao } 24671957992SPatrick Williams catch (const std::exception& ex) 247db5c6fc8SMarri Devender Rao { 248db5c6fc8SMarri Devender Rao log<level::ERR>("Error in certificate manager constructor", 249db5c6fc8SMarri Devender Rao entry("ERROR_STR=%s", ex.what())); 250db5c6fc8SMarri Devender Rao } 251dd74bd20SJayanth Othayoth } 252589159f2SJayanth Othayoth 25306a69d7bSZbigniew Kurzynski std::string Manager::install(const std::string filePath) 254cfbc8dc8SJayanth Othayoth { 255e3d47cd4SNan Zhou if (certType != CertificateType::authority && !installedCerts.empty()) 2561396511dSMarri Devender Rao { 257cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 2581396511dSMarri Devender Rao } 259e3d47cd4SNan Zhou else if (certType == CertificateType::authority && 260718eef37SNan Zhou installedCerts.size() >= maxNumAuthorityCertificates) 2613b07b77aSZbigniew Lukwinski { 262cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificates limit reached")); 2633b07b77aSZbigniew Lukwinski } 264ffad1ef1SMarri Devender Rao 2652f3563ccSZbigniew Lukwinski std::string certObjectPath; 2662f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath)) 2672f3563ccSZbigniew Lukwinski { 2682f3563ccSZbigniew Lukwinski certObjectPath = objectPath + '/' + std::to_string(certIdCounter); 269db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 2702f3563ccSZbigniew Lukwinski bus, certObjectPath, certType, certInstallPath, filePath, 271698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/false)); 2722f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 2732f3563ccSZbigniew Lukwinski certIdCounter++; 2742f3563ccSZbigniew Lukwinski } 2752f3563ccSZbigniew Lukwinski else 2762f3563ccSZbigniew Lukwinski { 277cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 2782f3563ccSZbigniew Lukwinski } 2792f3563ccSZbigniew Lukwinski 28006a69d7bSZbigniew Kurzynski return certObjectPath; 281589159f2SJayanth Othayoth } 282ae70b3daSDeepak Kodihalli 2836ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 2846ec13c8fSNan Zhou Manager::installAll(const std::string filePath) 2856ec13c8fSNan Zhou { 286e3d47cd4SNan Zhou if (certType != CertificateType::authority) 2876ec13c8fSNan Zhou { 2886ec13c8fSNan Zhou elog<NotAllowed>( 2896ec13c8fSNan Zhou NotAllowedReason("The InstallAll interface is only allowed for " 2906ec13c8fSNan Zhou "Authority certificates")); 2916ec13c8fSNan Zhou } 2926ec13c8fSNan Zhou 2936ec13c8fSNan Zhou if (!installedCerts.empty()) 2946ec13c8fSNan Zhou { 2956ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason( 2966ec13c8fSNan Zhou "There are already root certificates; Call DeleteAll then " 2976ec13c8fSNan Zhou "InstallAll, or use ReplaceAll")); 2986ec13c8fSNan Zhou } 2996ec13c8fSNan Zhou 3006ec13c8fSNan Zhou fs::path sourceFile(filePath); 3016ec13c8fSNan Zhou if (!fs::exists(sourceFile)) 3026ec13c8fSNan Zhou { 3036ec13c8fSNan Zhou log<level::ERR>("File is Missing", entry("FILE=%s", filePath.c_str())); 3046ec13c8fSNan Zhou elog<InternalFailure>(); 3056ec13c8fSNan Zhou } 3066ec13c8fSNan Zhou std::vector<std::string> authorities = splitCertificates(sourceFile); 3076ec13c8fSNan Zhou if (authorities.size() > maxNumAuthorityCertificates) 3086ec13c8fSNan Zhou { 3096ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificates limit reached")); 3106ec13c8fSNan Zhou } 3116ec13c8fSNan Zhou 31278357b0aSNan Zhou log<level::INFO>("Starts authority list install"); 31378357b0aSNan Zhou 3146ec13c8fSNan Zhou fs::path authorityStore(certInstallPath); 315*223e4604SPatrick Williams fs::path authoritiesListFile = authorityStore / 316*223e4604SPatrick Williams defaultAuthoritiesListFileName; 3176ec13c8fSNan Zhou 3186ec13c8fSNan Zhou // Atomically install all the certificates 3196ec13c8fSNan Zhou fs::path tempPath = Certificate::generateUniqueFilePath(authorityStore); 3206ec13c8fSNan Zhou fs::create_directory(tempPath); 3216ec13c8fSNan Zhou // Copies the authorities list 3226ec13c8fSNan Zhou Certificate::copyCertificate(sourceFile, 3236ec13c8fSNan Zhou tempPath / defaultAuthoritiesListFileName); 3246ec13c8fSNan Zhou std::vector<std::unique_ptr<Certificate>> tempCertificates; 3256ec13c8fSNan Zhou uint64_t tempCertIdCounter = certIdCounter; 3266ec13c8fSNan Zhou X509StorePtr x509Store = getX509Store(sourceFile); 3276ec13c8fSNan Zhou for (const auto& authority : authorities) 3286ec13c8fSNan Zhou { 329*223e4604SPatrick Williams std::string certObjectPath = objectPath + '/' + 330*223e4604SPatrick Williams std::to_string(tempCertIdCounter); 3316ec13c8fSNan Zhou tempCertificates.emplace_back(std::make_unique<Certificate>( 3326ec13c8fSNan Zhou bus, certObjectPath, certType, tempPath, *x509Store, authority, 333698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/false)); 3346ec13c8fSNan Zhou tempCertIdCounter++; 3356ec13c8fSNan Zhou } 3366ec13c8fSNan Zhou 3376ec13c8fSNan Zhou // We are good now, issue swap 3386ec13c8fSNan Zhou installedCerts = std::move(tempCertificates); 3396ec13c8fSNan Zhou certIdCounter = tempCertIdCounter; 3406ec13c8fSNan Zhou // Rename all the certificates including the authorities list 3416ec13c8fSNan Zhou for (const fs::path& f : fs::directory_iterator(tempPath)) 3426ec13c8fSNan Zhou { 3436ec13c8fSNan Zhou if (fs::is_symlink(f)) 3446ec13c8fSNan Zhou { 3456ec13c8fSNan Zhou continue; 3466ec13c8fSNan Zhou } 3476ec13c8fSNan Zhou fs::rename(/*from=*/f, /*to=*/certInstallPath / f.filename()); 3486ec13c8fSNan Zhou } 3496ec13c8fSNan Zhou // Update file locations and create symbol links 3506ec13c8fSNan Zhou for (const auto& cert : installedCerts) 3516ec13c8fSNan Zhou { 3526ec13c8fSNan Zhou cert->setCertInstallPath(certInstallPath); 3536ec13c8fSNan Zhou cert->setCertFilePath(certInstallPath / 3546ec13c8fSNan Zhou fs::path(cert->getCertFilePath()).filename()); 3556ec13c8fSNan Zhou cert->storageUpdate(); 3566ec13c8fSNan Zhou } 3576ec13c8fSNan Zhou // Remove the temporary folder 3586ec13c8fSNan Zhou fs::remove_all(tempPath); 3596ec13c8fSNan Zhou 3606ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> objects; 3616ec13c8fSNan Zhou for (const auto& certificate : installedCerts) 3626ec13c8fSNan Zhou { 3636ec13c8fSNan Zhou objects.emplace_back(certificate->getObjectPath()); 3646ec13c8fSNan Zhou } 3656ec13c8fSNan Zhou 36678357b0aSNan Zhou log<level::INFO>("Finishes authority list install; reload units starts"); 3676ec13c8fSNan Zhou reloadOrReset(unitToRestart); 3686ec13c8fSNan Zhou return objects; 3696ec13c8fSNan Zhou } 3706ec13c8fSNan Zhou 3716ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 3726ec13c8fSNan Zhou Manager::replaceAll(std::string filePath) 3736ec13c8fSNan Zhou { 3746ec13c8fSNan Zhou installedCerts.clear(); 3756ec13c8fSNan Zhou certIdCounter = 1; 3766ec13c8fSNan Zhou storageUpdate(); 3776ec13c8fSNan Zhou return installAll(std::move(filePath)); 3786ec13c8fSNan Zhou } 3796ec13c8fSNan Zhou 380a3bb38fbSZbigniew Kurzynski void Manager::deleteAll() 381ae70b3daSDeepak Kodihalli { 3826ceec40bSMarri Devender Rao // TODO: #Issue 4 when a certificate is deleted system auto generates 3836ceec40bSMarri Devender Rao // certificate file. At present we are not supporting creation of 3846ceec40bSMarri Devender Rao // certificate object for the auto-generated certificate file as 3856ceec40bSMarri Devender Rao // deletion if only applicable for REST server and Bmcweb does not allow 3866ceec40bSMarri Devender Rao // deletion of certificates 387db029c95SKowalski, Kamil installedCerts.clear(); 3886ec13c8fSNan Zhou // If the authorities list exists, delete it as well 389e3d47cd4SNan Zhou if (certType == CertificateType::authority) 3906ec13c8fSNan Zhou { 391*223e4604SPatrick Williams if (fs::path authoritiesList = fs::path(certInstallPath) / 392*223e4604SPatrick Williams defaultAuthoritiesListFileName; 3936ec13c8fSNan Zhou fs::exists(authoritiesList)) 3946ec13c8fSNan Zhou { 3956ec13c8fSNan Zhou fs::remove(authoritiesList); 3966ec13c8fSNan Zhou } 3976ec13c8fSNan Zhou } 3986ec13c8fSNan Zhou certIdCounter = 1; 3992f3563ccSZbigniew Lukwinski storageUpdate(); 4002f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 401ae70b3daSDeepak Kodihalli } 402f4682712SMarri Devender Rao 4032f3563ccSZbigniew Lukwinski void Manager::deleteCertificate(const Certificate* const certificate) 404a3bb38fbSZbigniew Kurzynski { 405*223e4604SPatrick Williams const std::vector<std::unique_ptr<Certificate>>::iterator& certIt = 406a3bb38fbSZbigniew Kurzynski std::find_if(installedCerts.begin(), installedCerts.end(), 407*223e4604SPatrick Williams [certificate](const std::unique_ptr<Certificate>& cert) { 4082f3563ccSZbigniew Lukwinski return (cert.get() == certificate); 409a3bb38fbSZbigniew Kurzynski }); 410a3bb38fbSZbigniew Kurzynski if (certIt != installedCerts.end()) 411a3bb38fbSZbigniew Kurzynski { 412a3bb38fbSZbigniew Kurzynski installedCerts.erase(certIt); 4132f3563ccSZbigniew Lukwinski storageUpdate(); 4142f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 415a3bb38fbSZbigniew Kurzynski } 416a3bb38fbSZbigniew Kurzynski else 417a3bb38fbSZbigniew Kurzynski { 418a3bb38fbSZbigniew Kurzynski log<level::ERR>("Certificate does not exist", 4192f3563ccSZbigniew Lukwinski entry("ID=%s", certificate->getCertId().c_str())); 4202f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 4212f3563ccSZbigniew Lukwinski } 4222f3563ccSZbigniew Lukwinski } 4232f3563ccSZbigniew Lukwinski 4242f3563ccSZbigniew Lukwinski void Manager::replaceCertificate(Certificate* const certificate, 4252f3563ccSZbigniew Lukwinski const std::string& filePath) 4262f3563ccSZbigniew Lukwinski { 4272f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath, certificate)) 4282f3563ccSZbigniew Lukwinski { 429698a5743SWilly Tu certificate->install(filePath, false); 4302f3563ccSZbigniew Lukwinski storageUpdate(); 4312f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 4322f3563ccSZbigniew Lukwinski } 4332f3563ccSZbigniew Lukwinski else 4342f3563ccSZbigniew Lukwinski { 435cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 436a3bb38fbSZbigniew Kurzynski } 437a3bb38fbSZbigniew Kurzynski } 438a3bb38fbSZbigniew Kurzynski 439f4682712SMarri Devender Rao std::string Manager::generateCSR( 440f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 441f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 442f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 443f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 444f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 445f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 446f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 447f4682712SMarri Devender Rao { 448f4682712SMarri Devender Rao // We support only one CSR. 449f4682712SMarri Devender Rao csrPtr.reset(nullptr); 450f4682712SMarri Devender Rao auto pid = fork(); 451f4682712SMarri Devender Rao if (pid == -1) 452f4682712SMarri Devender Rao { 453f4682712SMarri Devender Rao log<level::ERR>("Error occurred during forking process"); 454f4682712SMarri Devender Rao report<InternalFailure>(); 455f4682712SMarri Devender Rao } 456f4682712SMarri Devender Rao else if (pid == 0) 457f4682712SMarri Devender Rao { 458f4682712SMarri Devender Rao try 459f4682712SMarri Devender Rao { 460f4682712SMarri Devender Rao generateCSRHelper(alternativeNames, challengePassword, city, 461f4682712SMarri Devender Rao commonName, contactPerson, country, email, 462f4682712SMarri Devender Rao givenName, initials, keyBitLength, keyCurveId, 463f4682712SMarri Devender Rao keyPairAlgorithm, keyUsage, organization, 464f4682712SMarri Devender Rao organizationalUnit, state, surname, 465f4682712SMarri Devender Rao unstructuredName); 466f4682712SMarri Devender Rao exit(EXIT_SUCCESS); 467f4682712SMarri Devender Rao } 468f4682712SMarri Devender Rao catch (const InternalFailure& e) 469f4682712SMarri Devender Rao { 470f4682712SMarri Devender Rao // commit the error reported in child process and exit 471f4682712SMarri Devender Rao // Callback method from SDEvent Loop looks for exit status 472f4682712SMarri Devender Rao exit(EXIT_FAILURE); 473f4682712SMarri Devender Rao commit<InternalFailure>(); 474f4682712SMarri Devender Rao } 475d2393f23SRamesh Iyyar catch (const InvalidArgument& e) 476d2393f23SRamesh Iyyar { 477d2393f23SRamesh Iyyar // commit the error reported in child process and exit 478d2393f23SRamesh Iyyar // Callback method from SDEvent Loop looks for exit status 479d2393f23SRamesh Iyyar exit(EXIT_FAILURE); 480d2393f23SRamesh Iyyar commit<InvalidArgument>(); 481d2393f23SRamesh Iyyar } 482f4682712SMarri Devender Rao } 483f4682712SMarri Devender Rao else 484f4682712SMarri Devender Rao { 485f4682712SMarri Devender Rao using namespace sdeventplus::source; 486*223e4604SPatrick Williams Child::Callback callback = 487*223e4604SPatrick Williams [this](Child& eventSource, const siginfo_t* si) { 488f4682712SMarri Devender Rao eventSource.set_enabled(Enabled::On); 489f4682712SMarri Devender Rao if (si->si_status != 0) 490f4682712SMarri Devender Rao { 491e3d47cd4SNan Zhou this->createCSRObject(Status::failure); 492f4682712SMarri Devender Rao } 493f4682712SMarri Devender Rao else 494f4682712SMarri Devender Rao { 495e3d47cd4SNan Zhou this->createCSRObject(Status::success); 496f4682712SMarri Devender Rao } 497f4682712SMarri Devender Rao }; 498f4682712SMarri Devender Rao try 499f4682712SMarri Devender Rao { 500f4682712SMarri Devender Rao sigset_t ss; 501f4682712SMarri Devender Rao if (sigemptyset(&ss) < 0) 502f4682712SMarri Devender Rao { 503f4682712SMarri Devender Rao log<level::ERR>("Unable to initialize signal set"); 504f4682712SMarri Devender Rao elog<InternalFailure>(); 505f4682712SMarri Devender Rao } 506f4682712SMarri Devender Rao if (sigaddset(&ss, SIGCHLD) < 0) 507f4682712SMarri Devender Rao { 508f4682712SMarri Devender Rao log<level::ERR>("Unable to add signal to signal set"); 509f4682712SMarri Devender Rao elog<InternalFailure>(); 510f4682712SMarri Devender Rao } 511f4682712SMarri Devender Rao 512f4682712SMarri Devender Rao // Block SIGCHLD first, so that the event loop can handle it 513cfb5802aSNan Zhou if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0) 514f4682712SMarri Devender Rao { 515f4682712SMarri Devender Rao log<level::ERR>("Unable to block signal"); 516f4682712SMarri Devender Rao elog<InternalFailure>(); 517f4682712SMarri Devender Rao } 518f4682712SMarri Devender Rao if (childPtr) 519f4682712SMarri Devender Rao { 520f4682712SMarri Devender Rao childPtr.reset(); 521f4682712SMarri Devender Rao } 522f4682712SMarri Devender Rao childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 523f4682712SMarri Devender Rao std::move(callback)); 524f4682712SMarri Devender Rao } 525f4682712SMarri Devender Rao catch (const InternalFailure& e) 526f4682712SMarri Devender Rao { 527f4682712SMarri Devender Rao commit<InternalFailure>(); 528f4682712SMarri Devender Rao } 529f4682712SMarri Devender Rao } 530f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 531f4682712SMarri Devender Rao return csrObjectPath; 532f4682712SMarri Devender Rao } 533f4682712SMarri Devender Rao 534db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates() 535ffad1ef1SMarri Devender Rao { 536db029c95SKowalski, Kamil return installedCerts; 537ffad1ef1SMarri Devender Rao } 538ffad1ef1SMarri Devender Rao 539f4682712SMarri Devender Rao void Manager::generateCSRHelper( 540f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 541f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 542f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 543f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 544f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 545f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 546f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 547f4682712SMarri Devender Rao { 548f4682712SMarri Devender Rao int ret = 0; 549f4682712SMarri Devender Rao 550f4682712SMarri Devender Rao // set version of x509 req 551f4682712SMarri Devender Rao int nVersion = 1; 552f4682712SMarri Devender Rao // TODO: Issue#6 need to make version number configurable 553cf06ccdcSNan Zhou X509ReqPtr x509Req(X509_REQ_new(), ::X509_REQ_free); 554f4682712SMarri Devender Rao ret = X509_REQ_set_version(x509Req.get(), nVersion); 555f4682712SMarri Devender Rao if (ret == 0) 556f4682712SMarri Devender Rao { 557bf3cf751SNan Zhou log<level::ERR>("Error occurred during X509_REQ_set_version call"); 558f4682712SMarri Devender Rao elog<InternalFailure>(); 559f4682712SMarri Devender Rao } 560f4682712SMarri Devender Rao 561f4682712SMarri Devender Rao // set subject of x509 req 562f4682712SMarri Devender Rao X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 563f4682712SMarri Devender Rao 564f4682712SMarri Devender Rao if (!alternativeNames.empty()) 565f4682712SMarri Devender Rao { 566f4682712SMarri Devender Rao for (auto& name : alternativeNames) 567f4682712SMarri Devender Rao { 568f4682712SMarri Devender Rao addEntry(x509Name, "subjectAltName", name); 569f4682712SMarri Devender Rao } 570f4682712SMarri Devender Rao } 571f4682712SMarri Devender Rao addEntry(x509Name, "challengePassword", challengePassword); 572f4682712SMarri Devender Rao addEntry(x509Name, "L", city); 573f4682712SMarri Devender Rao addEntry(x509Name, "CN", commonName); 574f4682712SMarri Devender Rao addEntry(x509Name, "name", contactPerson); 575f4682712SMarri Devender Rao addEntry(x509Name, "C", country); 576f4682712SMarri Devender Rao addEntry(x509Name, "emailAddress", email); 577f4682712SMarri Devender Rao addEntry(x509Name, "GN", givenName); 578f4682712SMarri Devender Rao addEntry(x509Name, "initials", initials); 579f4682712SMarri Devender Rao addEntry(x509Name, "algorithm", keyPairAlgorithm); 580f4682712SMarri Devender Rao if (!keyUsage.empty()) 581f4682712SMarri Devender Rao { 582f4682712SMarri Devender Rao for (auto& usage : keyUsage) 583f4682712SMarri Devender Rao { 5847641105dSMarri Devender Rao if (isExtendedKeyUsage(usage)) 5857641105dSMarri Devender Rao { 5867641105dSMarri Devender Rao addEntry(x509Name, "extendedKeyUsage", usage); 5877641105dSMarri Devender Rao } 5887641105dSMarri Devender Rao else 5897641105dSMarri Devender Rao { 590f4682712SMarri Devender Rao addEntry(x509Name, "keyUsage", usage); 591f4682712SMarri Devender Rao } 592f4682712SMarri Devender Rao } 5937641105dSMarri Devender Rao } 594f4682712SMarri Devender Rao addEntry(x509Name, "O", organization); 595dc91fb61SJayanth Othayoth addEntry(x509Name, "OU", organizationalUnit); 596f4682712SMarri Devender Rao addEntry(x509Name, "ST", state); 597f4682712SMarri Devender Rao addEntry(x509Name, "SN", surname); 598f4682712SMarri Devender Rao addEntry(x509Name, "unstructuredName", unstructuredName); 599f4682712SMarri Devender Rao 600cf06ccdcSNan Zhou EVPPkeyPtr pKey(nullptr, ::EVP_PKEY_free); 6018a09b52aSRamesh Iyyar 6028a09b52aSRamesh Iyyar log<level::INFO>("Given Key pair algorithm", 6038a09b52aSRamesh Iyyar entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str())); 6048a09b52aSRamesh Iyyar 6058a09b52aSRamesh Iyyar // Used EC algorithm as default if user did not give algorithm type. 6068a09b52aSRamesh Iyyar if (keyPairAlgorithm == "RSA") 607c6e58c7eSRamesh Iyyar pKey = getRSAKeyPair(keyBitLength); 6088a09b52aSRamesh Iyyar else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 609c6e58c7eSRamesh Iyyar pKey = generateECKeyPair(keyCurveId); 6108a09b52aSRamesh Iyyar else 6118a09b52aSRamesh Iyyar { 6128a09b52aSRamesh Iyyar log<level::ERR>("Given Key pair algorithm is not supported. Supporting " 6138a09b52aSRamesh Iyyar "RSA and EC only"); 6148a09b52aSRamesh Iyyar elog<InvalidArgument>( 6158a09b52aSRamesh Iyyar Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 6168a09b52aSRamesh Iyyar Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 6178a09b52aSRamesh Iyyar } 6188a09b52aSRamesh Iyyar 6198a09b52aSRamesh Iyyar ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 6208a09b52aSRamesh Iyyar if (ret == 0) 6218a09b52aSRamesh Iyyar { 622bf3cf751SNan Zhou log<level::ERR>("Error occurred while setting Public key"); 6238a09b52aSRamesh Iyyar elog<InternalFailure>(); 6248a09b52aSRamesh Iyyar } 6258a09b52aSRamesh Iyyar 6268a09b52aSRamesh Iyyar // Write private key to file 627718eef37SNan Zhou writePrivateKey(pKey, defaultPrivateKeyFileName); 628f4682712SMarri Devender Rao 629f4682712SMarri Devender Rao // set sign key of x509 req 630f4682712SMarri Devender Rao ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 6318a09b52aSRamesh Iyyar if (ret == 0) 632f4682712SMarri Devender Rao { 633bf3cf751SNan Zhou log<level::ERR>("Error occurred while signing key of x509"); 634f4682712SMarri Devender Rao elog<InternalFailure>(); 635f4682712SMarri Devender Rao } 6368a09b52aSRamesh Iyyar 637f4682712SMarri Devender Rao log<level::INFO>("Writing CSR to file"); 638718eef37SNan Zhou fs::path csrFilePath = certParentInstallPath / defaultCSRFileName; 639c6e58c7eSRamesh Iyyar writeCSR(csrFilePath.string(), x509Req); 640f4682712SMarri Devender Rao } 641f4682712SMarri Devender Rao 6427641105dSMarri Devender Rao bool Manager::isExtendedKeyUsage(const std::string& usage) 6437641105dSMarri Devender Rao { 6447641105dSMarri Devender Rao const static std::array<const char*, 6> usageList = { 6457641105dSMarri Devender Rao "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 6467641105dSMarri Devender Rao "Timestamping", "CodeSigning", "EmailProtection"}; 647*223e4604SPatrick Williams auto it = std::find_if(usageList.begin(), usageList.end(), 648*223e4604SPatrick Williams [&usage](const char* s) { 649*223e4604SPatrick Williams return (strcmp(s, usage.c_str()) == 0); 650*223e4604SPatrick Williams }); 6517641105dSMarri Devender Rao return it != usageList.end(); 6527641105dSMarri Devender Rao } 653cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateRSAKeyPair(const int64_t keyBitLength) 654f4682712SMarri Devender Rao { 6558a09b52aSRamesh Iyyar int64_t keyBitLen = keyBitLength; 656f4682712SMarri Devender Rao // set keybit length to default value if not set 6578a09b52aSRamesh Iyyar if (keyBitLen <= 0) 658f4682712SMarri Devender Rao { 6598a09b52aSRamesh Iyyar log<level::INFO>( 6608a09b52aSRamesh Iyyar "KeyBitLength is not given.Hence, using default KeyBitLength", 661cf06ccdcSNan Zhou entry("DEFAULTKEYBITLENGTH=%d", defaultKeyBitLength)); 662cf06ccdcSNan Zhou keyBitLen = defaultKeyBitLength; 663f4682712SMarri Devender Rao } 66426fb83efSPatrick Williams 66526fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 66626fb83efSPatrick Williams 66726fb83efSPatrick Williams // generate rsa key 668cf06ccdcSNan Zhou BignumPtr bne(BN_new(), ::BN_free); 66926fb83efSPatrick Williams auto ret = BN_set_word(bne.get(), RSA_F4); 67026fb83efSPatrick Williams if (ret == 0) 67126fb83efSPatrick Williams { 672bf3cf751SNan Zhou log<level::ERR>("Error occurred during BN_set_word call"); 67326fb83efSPatrick Williams elog<InternalFailure>(); 67426fb83efSPatrick Williams } 675762da74eSNan Zhou using RSAPtr = std::unique_ptr<RSA, decltype(&::RSA_free)>; 676762da74eSNan Zhou RSAPtr rsa(RSA_new(), ::RSA_free); 677762da74eSNan Zhou ret = RSA_generate_key_ex(rsa.get(), keyBitLen, bne.get(), nullptr); 678f4682712SMarri Devender Rao if (ret != 1) 679f4682712SMarri Devender Rao { 680bf3cf751SNan Zhou log<level::ERR>("Error occurred during RSA_generate_key_ex call", 6818a09b52aSRamesh Iyyar entry("KEYBITLENGTH=%PRIu64", keyBitLen)); 682f4682712SMarri Devender Rao elog<InternalFailure>(); 683f4682712SMarri Devender Rao } 684f4682712SMarri Devender Rao 685f4682712SMarri Devender Rao // set public key of x509 req 686cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 687762da74eSNan Zhou ret = EVP_PKEY_assign_RSA(pKey.get(), rsa.get()); 688f4682712SMarri Devender Rao if (ret == 0) 689f4682712SMarri Devender Rao { 690bf3cf751SNan Zhou log<level::ERR>("Error occurred during assign rsa key into EVP"); 691f4682712SMarri Devender Rao elog<InternalFailure>(); 692f4682712SMarri Devender Rao } 693762da74eSNan Zhou // Now |rsa| is managed by |pKey| 694762da74eSNan Zhou rsa.release(); 6958a09b52aSRamesh Iyyar return pKey; 69626fb83efSPatrick Williams 69726fb83efSPatrick Williams #else 69826fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 69926fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr), &::EVP_PKEY_CTX_free); 70026fb83efSPatrick Williams if (!ctx) 70126fb83efSPatrick Williams { 702bf3cf751SNan Zhou log<level::ERR>("Error occurred creating EVP_PKEY_CTX from algorithm"); 70326fb83efSPatrick Williams elog<InternalFailure>(); 70426fb83efSPatrick Williams } 70526fb83efSPatrick Williams 70626fb83efSPatrick Williams if ((EVP_PKEY_keygen_init(ctx.get()) <= 0) || 70726fb83efSPatrick Williams (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), keyBitLen) <= 0)) 70826fb83efSPatrick Williams 70926fb83efSPatrick Williams { 710bf3cf751SNan Zhou log<level::ERR>("Error occurred initializing keygen context"); 71126fb83efSPatrick Williams elog<InternalFailure>(); 71226fb83efSPatrick Williams } 71326fb83efSPatrick Williams 71426fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 71526fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 71626fb83efSPatrick Williams { 717bf3cf751SNan Zhou log<level::ERR>("Error occurred during generate EC key"); 71826fb83efSPatrick Williams elog<InternalFailure>(); 71926fb83efSPatrick Williams } 72026fb83efSPatrick Williams 72126fb83efSPatrick Williams return {pKey, &::EVP_PKEY_free}; 72226fb83efSPatrick Williams #endif 7238a09b52aSRamesh Iyyar } 7248a09b52aSRamesh Iyyar 725cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateECKeyPair(const std::string& curveId) 7268a09b52aSRamesh Iyyar { 7278a09b52aSRamesh Iyyar std::string curId(curveId); 7288a09b52aSRamesh Iyyar 7298a09b52aSRamesh Iyyar if (curId.empty()) 7308a09b52aSRamesh Iyyar { 7318a09b52aSRamesh Iyyar log<level::INFO>( 7328a09b52aSRamesh Iyyar "KeyCurveId is not given. Hence using default curve id", 733cf06ccdcSNan Zhou entry("DEFAULTKEYCURVEID=%s", defaultKeyCurveID)); 734cf06ccdcSNan Zhou curId = defaultKeyCurveID; 7358a09b52aSRamesh Iyyar } 7368a09b52aSRamesh Iyyar 7378a09b52aSRamesh Iyyar int ecGrp = OBJ_txt2nid(curId.c_str()); 7388a09b52aSRamesh Iyyar if (ecGrp == NID_undef) 7398a09b52aSRamesh Iyyar { 7408a09b52aSRamesh Iyyar log<level::ERR>( 741bf3cf751SNan Zhou "Error occurred during convert the curve id string format into NID", 7428a09b52aSRamesh Iyyar entry("KEYCURVEID=%s", curId.c_str())); 7438a09b52aSRamesh Iyyar elog<InternalFailure>(); 7448a09b52aSRamesh Iyyar } 7458a09b52aSRamesh Iyyar 74626fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 74726fb83efSPatrick Williams 7488a09b52aSRamesh Iyyar EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 7498a09b52aSRamesh Iyyar 750cfb5802aSNan Zhou if (ecKey == nullptr) 7518a09b52aSRamesh Iyyar { 7528a09b52aSRamesh Iyyar log<level::ERR>( 753bf3cf751SNan Zhou "Error occurred during create the EC_Key object from NID", 7548a09b52aSRamesh Iyyar entry("ECGROUP=%d", ecGrp)); 7558a09b52aSRamesh Iyyar elog<InternalFailure>(); 7568a09b52aSRamesh Iyyar } 7578a09b52aSRamesh Iyyar 7588a09b52aSRamesh Iyyar // If you want to save a key and later load it with 7598a09b52aSRamesh Iyyar // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 7608a09b52aSRamesh Iyyar // flag on the key. 7618a09b52aSRamesh Iyyar EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 7628a09b52aSRamesh Iyyar 7638a09b52aSRamesh Iyyar int ret = EC_KEY_generate_key(ecKey); 7648a09b52aSRamesh Iyyar 7658a09b52aSRamesh Iyyar if (ret == 0) 7668a09b52aSRamesh Iyyar { 7678a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 768bf3cf751SNan Zhou log<level::ERR>("Error occurred during generate EC key"); 7698a09b52aSRamesh Iyyar elog<InternalFailure>(); 7708a09b52aSRamesh Iyyar } 7718a09b52aSRamesh Iyyar 772cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 7738a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 7748a09b52aSRamesh Iyyar if (ret == 0) 7758a09b52aSRamesh Iyyar { 7768a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 777bf3cf751SNan Zhou log<level::ERR>("Error occurred during assign EC Key into EVP"); 7788a09b52aSRamesh Iyyar elog<InternalFailure>(); 7798a09b52aSRamesh Iyyar } 7808a09b52aSRamesh Iyyar 7818a09b52aSRamesh Iyyar return pKey; 78226fb83efSPatrick Williams 78326fb83efSPatrick Williams #else 784e3d47cd4SNan Zhou auto holderOfKey = [](EVP_PKEY* key) { 78526fb83efSPatrick Williams return std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>{ 78626fb83efSPatrick Williams key, &::EVP_PKEY_free}; 78726fb83efSPatrick Williams }; 78826fb83efSPatrick Williams 78926fb83efSPatrick Williams // Create context to set up curve parameters. 79026fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 79126fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr), &::EVP_PKEY_CTX_free); 79226fb83efSPatrick Williams if (!ctx) 79326fb83efSPatrick Williams { 794bf3cf751SNan Zhou log<level::ERR>("Error occurred creating EVP_PKEY_CTX for params"); 79526fb83efSPatrick Williams elog<InternalFailure>(); 79626fb83efSPatrick Williams } 79726fb83efSPatrick Williams 79826fb83efSPatrick Williams // Set up curve parameters. 79926fb83efSPatrick Williams EVP_PKEY* params = nullptr; 80026fb83efSPatrick Williams 80126fb83efSPatrick Williams if ((EVP_PKEY_paramgen_init(ctx.get()) <= 0) || 80226fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_param_enc(ctx.get(), OPENSSL_EC_NAMED_CURVE) <= 80326fb83efSPatrick Williams 0) || 80426fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), ecGrp) <= 0) || 80526fb83efSPatrick Williams (EVP_PKEY_paramgen(ctx.get(), ¶ms) <= 0)) 80626fb83efSPatrick Williams { 807bf3cf751SNan Zhou log<level::ERR>("Error occurred setting curve parameters"); 80826fb83efSPatrick Williams elog<InternalFailure>(); 80926fb83efSPatrick Williams } 81026fb83efSPatrick Williams 81126fb83efSPatrick Williams // Move parameters to RAII holder. 812e3d47cd4SNan Zhou auto pparms = holderOfKey(params); 81326fb83efSPatrick Williams 81426fb83efSPatrick Williams // Create new context for key. 81526fb83efSPatrick Williams ctx.reset(EVP_PKEY_CTX_new_from_pkey(nullptr, params, nullptr)); 81626fb83efSPatrick Williams 81726fb83efSPatrick Williams if (!ctx || (EVP_PKEY_keygen_init(ctx.get()) <= 0)) 81826fb83efSPatrick Williams { 819bf3cf751SNan Zhou log<level::ERR>("Error occurred initializing keygen context"); 82026fb83efSPatrick Williams elog<InternalFailure>(); 82126fb83efSPatrick Williams } 82226fb83efSPatrick Williams 82326fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 82426fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 82526fb83efSPatrick Williams { 826bf3cf751SNan Zhou log<level::ERR>("Error occurred during generate EC key"); 82726fb83efSPatrick Williams elog<InternalFailure>(); 82826fb83efSPatrick Williams } 82926fb83efSPatrick Williams 830e3d47cd4SNan Zhou return holderOfKey(pKey); 83126fb83efSPatrick Williams #endif 8328a09b52aSRamesh Iyyar } 8338a09b52aSRamesh Iyyar 834cf06ccdcSNan Zhou void Manager::writePrivateKey(const EVPPkeyPtr& pKey, 835c6e58c7eSRamesh Iyyar const std::string& privKeyFileName) 8368a09b52aSRamesh Iyyar { 8378a09b52aSRamesh Iyyar log<level::INFO>("Writing private key to file"); 838f4682712SMarri Devender Rao // write private key to file 839c6e58c7eSRamesh Iyyar fs::path privKeyPath = certParentInstallPath / privKeyFileName; 840f4682712SMarri Devender Rao 841f4682712SMarri Devender Rao FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 842cfb5802aSNan Zhou if (fp == nullptr) 843f4682712SMarri Devender Rao { 844bf3cf751SNan Zhou log<level::ERR>("Error occurred creating private key file"); 845f4682712SMarri Devender Rao elog<InternalFailure>(); 846f4682712SMarri Devender Rao } 847*223e4604SPatrick Williams int ret = PEM_write_PrivateKey(fp, pKey.get(), nullptr, nullptr, 0, 0, 848*223e4604SPatrick Williams nullptr); 849f4682712SMarri Devender Rao std::fclose(fp); 850f4682712SMarri Devender Rao if (ret == 0) 851f4682712SMarri Devender Rao { 852bf3cf751SNan Zhou log<level::ERR>("Error occurred while writing private key to file"); 853f4682712SMarri Devender Rao elog<InternalFailure>(); 854f4682712SMarri Devender Rao } 855f4682712SMarri Devender Rao } 856f4682712SMarri Devender Rao 857f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field, 858f4682712SMarri Devender Rao const std::string& bytes) 859f4682712SMarri Devender Rao { 860f4682712SMarri Devender Rao if (bytes.empty()) 861f4682712SMarri Devender Rao { 862f4682712SMarri Devender Rao return; 863f4682712SMarri Devender Rao } 864f4682712SMarri Devender Rao int ret = X509_NAME_add_entry_by_txt( 865f4682712SMarri Devender Rao x509Name, field, MBSTRING_ASC, 866f4682712SMarri Devender Rao reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 867f4682712SMarri Devender Rao if (ret != 1) 868f4682712SMarri Devender Rao { 869f4682712SMarri Devender Rao log<level::ERR>("Unable to set entry", entry("FIELD=%s", field), 870f4682712SMarri Devender Rao entry("VALUE=%s", bytes.c_str())); 871f4682712SMarri Devender Rao elog<InternalFailure>(); 872f4682712SMarri Devender Rao } 873f4682712SMarri Devender Rao } 874f4682712SMarri Devender Rao 875f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status) 876f4682712SMarri Devender Rao { 877f4682712SMarri Devender Rao if (csrPtr) 878f4682712SMarri Devender Rao { 879f4682712SMarri Devender Rao csrPtr.reset(nullptr); 880f4682712SMarri Devender Rao } 881f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 882f4682712SMarri Devender Rao csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 883f4682712SMarri Devender Rao certInstallPath.c_str(), status); 884f4682712SMarri Devender Rao } 885f4682712SMarri Devender Rao 886cf06ccdcSNan Zhou void Manager::writeCSR(const std::string& filePath, const X509ReqPtr& x509Req) 887f4682712SMarri Devender Rao { 888f4682712SMarri Devender Rao if (fs::exists(filePath)) 889f4682712SMarri Devender Rao { 890f4682712SMarri Devender Rao log<level::INFO>("Removing the existing file", 891f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 892f4682712SMarri Devender Rao if (!fs::remove(filePath.c_str())) 893f4682712SMarri Devender Rao { 894f4682712SMarri Devender Rao log<level::ERR>("Unable to remove the file", 895f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 896f4682712SMarri Devender Rao elog<InternalFailure>(); 897f4682712SMarri Devender Rao } 898f4682712SMarri Devender Rao } 899f4682712SMarri Devender Rao 900cfb5802aSNan Zhou FILE* fp = nullptr; 901f4682712SMarri Devender Rao 902cfb5802aSNan Zhou if ((fp = std::fopen(filePath.c_str(), "w")) == nullptr) 903f4682712SMarri Devender Rao { 904f4682712SMarri Devender Rao log<level::ERR>("Error opening the file to write the CSR", 905f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 906f4682712SMarri Devender Rao elog<InternalFailure>(); 907f4682712SMarri Devender Rao } 908f4682712SMarri Devender Rao 909f4682712SMarri Devender Rao int rc = PEM_write_X509_REQ(fp, x509Req.get()); 910f4682712SMarri Devender Rao if (!rc) 911f4682712SMarri Devender Rao { 912f4682712SMarri Devender Rao log<level::ERR>("PEM write routine failed", 913f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 914f4682712SMarri Devender Rao std::fclose(fp); 915f4682712SMarri Devender Rao elog<InternalFailure>(); 916f4682712SMarri Devender Rao } 917f4682712SMarri Devender Rao std::fclose(fp); 918f4682712SMarri Devender Rao } 919f4682712SMarri Devender Rao 920db029c95SKowalski, Kamil void Manager::createCertificates() 921db029c95SKowalski, Kamil { 922db029c95SKowalski, Kamil auto certObjectPath = objectPath + '/'; 923db029c95SKowalski, Kamil 924e3d47cd4SNan Zhou if (certType == CertificateType::authority) 925db029c95SKowalski, Kamil { 926fe590c4eSZbigniew Lukwinski // Check whether install path is a directory. 927db029c95SKowalski, Kamil if (!fs::is_directory(certInstallPath)) 928db029c95SKowalski, Kamil { 929db029c95SKowalski, Kamil log<level::ERR>("Certificate installation path exists and it is " 930db029c95SKowalski, Kamil "not a directory"); 931db029c95SKowalski, Kamil elog<InternalFailure>(); 9326ec13c8fSNan Zhou } 9336ec13c8fSNan Zhou 9346ec13c8fSNan Zhou // If the authorities list exists, recover from it and return 935*223e4604SPatrick Williams if (fs::path authoritiesListFilePath = fs::path(certInstallPath) / 936*223e4604SPatrick Williams defaultAuthoritiesListFileName; 9376ec13c8fSNan Zhou fs::exists(authoritiesListFilePath)) 9386ec13c8fSNan Zhou { 9396ec13c8fSNan Zhou // remove all other files and directories 9406ec13c8fSNan Zhou for (auto& path : fs::directory_iterator(certInstallPath)) 9416ec13c8fSNan Zhou { 9426ec13c8fSNan Zhou if (path.path() != authoritiesListFilePath) 9436ec13c8fSNan Zhou { 9446ec13c8fSNan Zhou fs::remove_all(path); 9456ec13c8fSNan Zhou } 9466ec13c8fSNan Zhou } 9476ec13c8fSNan Zhou installAll(authoritiesListFilePath); 948db029c95SKowalski, Kamil return; 949db029c95SKowalski, Kamil } 950db029c95SKowalski, Kamil 951db029c95SKowalski, Kamil for (auto& path : fs::directory_iterator(certInstallPath)) 952ffad1ef1SMarri Devender Rao { 953ffad1ef1SMarri Devender Rao try 954ffad1ef1SMarri Devender Rao { 9552f3563ccSZbigniew Lukwinski // Assume here any regular file located in certificate directory 9562f3563ccSZbigniew Lukwinski // contains certificates body. Do not want to use soft links 9572f3563ccSZbigniew Lukwinski // would add value. 9582f3563ccSZbigniew Lukwinski if (fs::is_regular_file(path)) 9592f3563ccSZbigniew Lukwinski { 960db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 961db029c95SKowalski, Kamil bus, certObjectPath + std::to_string(certIdCounter++), 962cf06ccdcSNan Zhou certType, certInstallPath, path.path(), 963698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/true)); 9642f3563ccSZbigniew Lukwinski } 965ffad1ef1SMarri Devender Rao } 966ffad1ef1SMarri Devender Rao catch (const InternalFailure& e) 967ffad1ef1SMarri Devender Rao { 968ffad1ef1SMarri Devender Rao report<InternalFailure>(); 969ffad1ef1SMarri Devender Rao } 970ffad1ef1SMarri Devender Rao catch (const InvalidCertificate& e) 971ffad1ef1SMarri Devender Rao { 972cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 973cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 974ffad1ef1SMarri Devender Rao } 975ffad1ef1SMarri Devender Rao } 976db029c95SKowalski, Kamil } 977db029c95SKowalski, Kamil else if (fs::exists(certInstallPath)) 978db029c95SKowalski, Kamil { 979db029c95SKowalski, Kamil try 980db029c95SKowalski, Kamil { 981db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 9822f3563ccSZbigniew Lukwinski bus, certObjectPath + '1', certType, certInstallPath, 983698a5743SWilly Tu certInstallPath, certWatchPtr.get(), *this, /*restore=*/false)); 984db029c95SKowalski, Kamil } 985db029c95SKowalski, Kamil catch (const InternalFailure& e) 986db029c95SKowalski, Kamil { 987db029c95SKowalski, Kamil report<InternalFailure>(); 988db029c95SKowalski, Kamil } 989db029c95SKowalski, Kamil catch (const InvalidCertificate& e) 990db029c95SKowalski, Kamil { 991cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 992cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 993db029c95SKowalski, Kamil } 994db029c95SKowalski, Kamil } 995db029c95SKowalski, Kamil } 996c6e58c7eSRamesh Iyyar 997c6e58c7eSRamesh Iyyar void Manager::createRSAPrivateKeyFile() 998c6e58c7eSRamesh Iyyar { 999*223e4604SPatrick Williams fs::path rsaPrivateKeyFileName = certParentInstallPath / 1000*223e4604SPatrick Williams defaultRSAPrivateKeyFileName; 1001c6e58c7eSRamesh Iyyar 1002c6e58c7eSRamesh Iyyar try 1003c6e58c7eSRamesh Iyyar { 1004c6e58c7eSRamesh Iyyar if (!fs::exists(rsaPrivateKeyFileName)) 1005c6e58c7eSRamesh Iyyar { 1006cf06ccdcSNan Zhou writePrivateKey(generateRSAKeyPair(supportedKeyBitLength), 1007718eef37SNan Zhou defaultRSAPrivateKeyFileName); 1008c6e58c7eSRamesh Iyyar } 1009c6e58c7eSRamesh Iyyar } 1010c6e58c7eSRamesh Iyyar catch (const InternalFailure& e) 1011c6e58c7eSRamesh Iyyar { 1012c6e58c7eSRamesh Iyyar report<InternalFailure>(); 1013c6e58c7eSRamesh Iyyar } 1014c6e58c7eSRamesh Iyyar } 1015c6e58c7eSRamesh Iyyar 1016cf06ccdcSNan Zhou EVPPkeyPtr Manager::getRSAKeyPair(const int64_t keyBitLength) 1017c6e58c7eSRamesh Iyyar { 1018cf06ccdcSNan Zhou if (keyBitLength != supportedKeyBitLength) 1019c6e58c7eSRamesh Iyyar { 1020c6e58c7eSRamesh Iyyar log<level::ERR>( 1021c6e58c7eSRamesh Iyyar "Given Key bit length is not supported", 1022c6e58c7eSRamesh Iyyar entry("GIVENKEYBITLENGTH=%d", keyBitLength), 1023cf06ccdcSNan Zhou entry("SUPPORTEDKEYBITLENGTH=%d", supportedKeyBitLength)); 1024c6e58c7eSRamesh Iyyar elog<InvalidArgument>( 1025c6e58c7eSRamesh Iyyar Argument::ARGUMENT_NAME("KEYBITLENGTH"), 1026c6e58c7eSRamesh Iyyar Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 1027c6e58c7eSRamesh Iyyar } 1028*223e4604SPatrick Williams fs::path rsaPrivateKeyFileName = certParentInstallPath / 1029*223e4604SPatrick Williams defaultRSAPrivateKeyFileName; 1030c6e58c7eSRamesh Iyyar 1031c6e58c7eSRamesh Iyyar FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 1032c6e58c7eSRamesh Iyyar if (!privateKeyFile) 1033c6e58c7eSRamesh Iyyar { 1034c6e58c7eSRamesh Iyyar log<level::ERR>("Unable to open RSA private key file to read", 1035c6e58c7eSRamesh Iyyar entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()), 1036c6e58c7eSRamesh Iyyar entry("ERRORREASON=%s", strerror(errno))); 1037c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1038c6e58c7eSRamesh Iyyar } 1039c6e58c7eSRamesh Iyyar 1040cf06ccdcSNan Zhou EVPPkeyPtr privateKey( 1041c6e58c7eSRamesh Iyyar PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 1042c6e58c7eSRamesh Iyyar ::EVP_PKEY_free); 1043c6e58c7eSRamesh Iyyar std::fclose(privateKeyFile); 1044c6e58c7eSRamesh Iyyar 1045c6e58c7eSRamesh Iyyar if (!privateKey) 1046c6e58c7eSRamesh Iyyar { 1047bf3cf751SNan Zhou log<level::ERR>("Error occurred during PEM_read_PrivateKey call"); 1048c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1049c6e58c7eSRamesh Iyyar } 1050c6e58c7eSRamesh Iyyar return privateKey; 1051c6e58c7eSRamesh Iyyar } 10522f3563ccSZbigniew Lukwinski 10532f3563ccSZbigniew Lukwinski void Manager::storageUpdate() 10542f3563ccSZbigniew Lukwinski { 1055e3d47cd4SNan Zhou if (certType == CertificateType::authority) 10562f3563ccSZbigniew Lukwinski { 10572f3563ccSZbigniew Lukwinski // Remove symbolic links in the certificate directory 10582f3563ccSZbigniew Lukwinski for (auto& certPath : fs::directory_iterator(certInstallPath)) 10592f3563ccSZbigniew Lukwinski { 10602f3563ccSZbigniew Lukwinski try 10612f3563ccSZbigniew Lukwinski { 10622f3563ccSZbigniew Lukwinski if (fs::is_symlink(certPath)) 10632f3563ccSZbigniew Lukwinski { 10642f3563ccSZbigniew Lukwinski fs::remove(certPath); 10652f3563ccSZbigniew Lukwinski } 10662f3563ccSZbigniew Lukwinski } 10672f3563ccSZbigniew Lukwinski catch (const std::exception& e) 10682f3563ccSZbigniew Lukwinski { 10692f3563ccSZbigniew Lukwinski log<level::ERR>( 10702f3563ccSZbigniew Lukwinski "Failed to remove symlink for certificate", 10712f3563ccSZbigniew Lukwinski entry("ERR=%s", e.what()), 10722f3563ccSZbigniew Lukwinski entry("SYMLINK=%s", certPath.path().string().c_str())); 10732f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 10742f3563ccSZbigniew Lukwinski } 10752f3563ccSZbigniew Lukwinski } 10762f3563ccSZbigniew Lukwinski } 10772f3563ccSZbigniew Lukwinski 10782f3563ccSZbigniew Lukwinski for (const auto& cert : installedCerts) 10792f3563ccSZbigniew Lukwinski { 10802f3563ccSZbigniew Lukwinski cert->storageUpdate(); 10812f3563ccSZbigniew Lukwinski } 10822f3563ccSZbigniew Lukwinski } 10832f3563ccSZbigniew Lukwinski 1084cf06ccdcSNan Zhou void Manager::reloadOrReset(const std::string& unit) 10852f3563ccSZbigniew Lukwinski { 10862f3563ccSZbigniew Lukwinski if (!unit.empty()) 10872f3563ccSZbigniew Lukwinski { 10882f3563ccSZbigniew Lukwinski try 10892f3563ccSZbigniew Lukwinski { 1090cf06ccdcSNan Zhou constexpr auto defaultSystemdService = "org.freedesktop.systemd1"; 1091cf06ccdcSNan Zhou constexpr auto defaultSystemdObjectPath = 1092cf06ccdcSNan Zhou "/org/freedesktop/systemd1"; 1093cf06ccdcSNan Zhou constexpr auto defaultSystemdInterface = 10942f3563ccSZbigniew Lukwinski "org.freedesktop.systemd1.Manager"; 1095cf06ccdcSNan Zhou auto method = bus.new_method_call( 1096cf06ccdcSNan Zhou defaultSystemdService, defaultSystemdObjectPath, 1097cf06ccdcSNan Zhou defaultSystemdInterface, "ReloadOrRestartUnit"); 10982f3563ccSZbigniew Lukwinski method.append(unit, "replace"); 10992f3563ccSZbigniew Lukwinski bus.call_noreply(method); 11002f3563ccSZbigniew Lukwinski } 1101b3dbfb37SPatrick Williams catch (const sdbusplus::exception_t& e) 11022f3563ccSZbigniew Lukwinski { 11032f3563ccSZbigniew Lukwinski log<level::ERR>("Failed to reload or restart service", 11042f3563ccSZbigniew Lukwinski entry("ERR=%s", e.what()), 11052f3563ccSZbigniew Lukwinski entry("UNIT=%s", unit.c_str())); 11062f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 11072f3563ccSZbigniew Lukwinski } 11082f3563ccSZbigniew Lukwinski } 11092f3563ccSZbigniew Lukwinski } 11102f3563ccSZbigniew Lukwinski 11112f3563ccSZbigniew Lukwinski bool Manager::isCertificateUnique(const std::string& filePath, 11122f3563ccSZbigniew Lukwinski const Certificate* const certToDrop) 11132f3563ccSZbigniew Lukwinski { 11142f3563ccSZbigniew Lukwinski if (std::any_of( 11152f3563ccSZbigniew Lukwinski installedCerts.begin(), installedCerts.end(), 1116*223e4604SPatrick Williams [&filePath, certToDrop](const std::unique_ptr<Certificate>& cert) { 11172f3563ccSZbigniew Lukwinski return cert.get() != certToDrop && cert->isSame(filePath); 11182f3563ccSZbigniew Lukwinski })) 11192f3563ccSZbigniew Lukwinski { 11202f3563ccSZbigniew Lukwinski return false; 11212f3563ccSZbigniew Lukwinski } 11222f3563ccSZbigniew Lukwinski else 11232f3563ccSZbigniew Lukwinski { 11242f3563ccSZbigniew Lukwinski return true; 11252f3563ccSZbigniew Lukwinski } 11262f3563ccSZbigniew Lukwinski } 11272f3563ccSZbigniew Lukwinski 1128e1289adfSNan Zhou } // namespace phosphor::certs 1129