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> 108dbcc72dSAndrew Geissler #include <openssl/err.h> 1126fb83efSPatrick Williams #include <openssl/evp.h> 12014be0bfSNan Zhou #include <openssl/obj_mac.h> 13014be0bfSNan Zhou #include <openssl/objects.h> 14014be0bfSNan Zhou #include <openssl/opensslv.h> 15f4682712SMarri Devender Rao #include <openssl/pem.h> 16014be0bfSNan Zhou #include <openssl/rsa.h> 17f4682712SMarri Devender Rao #include <unistd.h> 18f4682712SMarri Devender Rao 19223e4604SPatrick Williams #include <phosphor-logging/elog-errors.hpp> 20223e4604SPatrick Williams #include <phosphor-logging/elog.hpp> 21f2646271SRavi Teja #include <phosphor-logging/lg2.hpp> 22223e4604SPatrick Williams #include <sdbusplus/bus.hpp> 23223e4604SPatrick Williams #include <sdbusplus/exception.hpp> 24223e4604SPatrick Williams #include <sdbusplus/message.hpp> 25223e4604SPatrick Williams #include <sdeventplus/source/base.hpp> 26223e4604SPatrick Williams #include <sdeventplus/source/child.hpp> 27223e4604SPatrick Williams #include <xyz/openbmc_project/Certs/error.hpp> 28223e4604SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp> 29223e4604SPatrick Williams 30a3bb38fbSZbigniew Kurzynski #include <algorithm> 31014be0bfSNan Zhou #include <array> 32014be0bfSNan Zhou #include <cerrno> 33014be0bfSNan Zhou #include <chrono> 34014be0bfSNan Zhou #include <csignal> 35014be0bfSNan Zhou #include <cstdio> 36014be0bfSNan Zhou #include <cstdlib> 37014be0bfSNan Zhou #include <cstring> 38014be0bfSNan Zhou #include <exception> 396ec13c8fSNan Zhou #include <fstream> 40014be0bfSNan Zhou #include <utility> 412f3563ccSZbigniew Lukwinski 42e1289adfSNan Zhou namespace phosphor::certs 43cfbc8dc8SJayanth Othayoth { 44cf06ccdcSNan Zhou namespace 45cf06ccdcSNan Zhou { 46cf06ccdcSNan Zhou namespace fs = std::filesystem; 47cf06ccdcSNan Zhou using ::phosphor::logging::commit; 48cf06ccdcSNan Zhou using ::phosphor::logging::elog; 49cf06ccdcSNan Zhou using ::phosphor::logging::report; 50cfbc8dc8SJayanth Othayoth 51cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 52cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 53cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 54cf06ccdcSNan Zhou using NotAllowedReason = 55cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON; 56cf06ccdcSNan Zhou using InvalidCertificateReason = ::phosphor::logging::xyz::openbmc_project:: 57cf06ccdcSNan Zhou Certs::InvalidCertificate::REASON; 58cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 59cf06ccdcSNan Zhou using Argument = 60cf06ccdcSNan Zhou ::phosphor::logging::xyz::openbmc_project::Common::InvalidArgument; 61c6e58c7eSRamesh Iyyar 62cf06ccdcSNan Zhou // RAII support for openSSL functions. 63cf06ccdcSNan Zhou using X509ReqPtr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>; 64cf06ccdcSNan Zhou using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>; 65cf06ccdcSNan Zhou using BignumPtr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>; 666ec13c8fSNan Zhou using X509StorePtr = std::unique_ptr<X509_STORE, decltype(&::X509_STORE_free)>; 67cf06ccdcSNan Zhou 68cf06ccdcSNan Zhou constexpr int supportedKeyBitLength = 2048; 69cf06ccdcSNan Zhou constexpr int defaultKeyBitLength = 2048; 70cf06ccdcSNan Zhou // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 71cf06ccdcSNan Zhou constexpr auto defaultKeyCurveID = "secp224r1"; 726ec13c8fSNan Zhou // PEM certificate block markers, defined in go/rfc/7468. 736ec13c8fSNan Zhou constexpr std::string_view beginCertificate = "-----BEGIN CERTIFICATE-----"; 746ec13c8fSNan Zhou constexpr std::string_view endCertificate = "-----END CERTIFICATE-----"; 756ec13c8fSNan Zhou 766ec13c8fSNan Zhou /** 776ec13c8fSNan Zhou * @brief Splits the given authorities list file and returns an array of 786ec13c8fSNan Zhou * individual PEM encoded x509 certificate. 796ec13c8fSNan Zhou * 806ec13c8fSNan Zhou * @param[in] sourceFilePath - Path to the authorities list file. 816ec13c8fSNan Zhou * 826ec13c8fSNan Zhou * @return An array of individual PEM encoded x509 certificate 836ec13c8fSNan Zhou */ 846ec13c8fSNan Zhou std::vector<std::string> splitCertificates(const std::string& sourceFilePath) 856ec13c8fSNan Zhou { 866ec13c8fSNan Zhou std::ifstream inputCertFileStream; 876ec13c8fSNan Zhou inputCertFileStream.exceptions( 886ec13c8fSNan Zhou std::ifstream::failbit | std::ifstream::badbit | std::ifstream::eofbit); 896ec13c8fSNan Zhou 906ec13c8fSNan Zhou std::stringstream pemStream; 916ec13c8fSNan Zhou std::vector<std::string> certificatesList; 926ec13c8fSNan Zhou try 936ec13c8fSNan Zhou { 946ec13c8fSNan Zhou inputCertFileStream.open(sourceFilePath); 956ec13c8fSNan Zhou pemStream << inputCertFileStream.rdbuf(); 966ec13c8fSNan Zhou inputCertFileStream.close(); 976ec13c8fSNan Zhou } 986ec13c8fSNan Zhou catch (const std::exception& e) 996ec13c8fSNan Zhou { 100f2646271SRavi Teja lg2::error("Failed to read certificates list, ERR:{ERR}, SRC:{SRC}", 101f2646271SRavi Teja "ERR", e, "SRC", sourceFilePath); 1026ec13c8fSNan Zhou elog<InternalFailure>(); 1036ec13c8fSNan Zhou } 1046ec13c8fSNan Zhou std::string pem = pemStream.str(); 1056ec13c8fSNan Zhou size_t begin = 0; 1066ec13c8fSNan Zhou // |begin| points to the current start position for searching the next 1076ec13c8fSNan Zhou // |beginCertificate| block. When we find the beginning of the certificate, 1086ec13c8fSNan Zhou // we extract the content between the beginning and the end of the current 1096ec13c8fSNan Zhou // certificate. And finally we move |begin| to the end of the current 1106ec13c8fSNan Zhou // certificate to start searching the next potential certificate. 1116ec13c8fSNan Zhou for (begin = pem.find(beginCertificate, begin); begin != std::string::npos; 1126ec13c8fSNan Zhou begin = pem.find(beginCertificate, begin)) 1136ec13c8fSNan Zhou { 1146ec13c8fSNan Zhou size_t end = pem.find(endCertificate, begin); 1156ec13c8fSNan Zhou if (end == std::string::npos) 1166ec13c8fSNan Zhou { 117f2646271SRavi Teja lg2::error( 1186ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END"); 1196ec13c8fSNan Zhou elog<InvalidCertificate>(InvalidCertificateReason( 1206ec13c8fSNan Zhou "invalid PEM contains a BEGIN identifier without an END")); 1216ec13c8fSNan Zhou } 1226ec13c8fSNan Zhou end += endCertificate.size(); 1236ec13c8fSNan Zhou certificatesList.emplace_back(pem.substr(begin, end - begin)); 1246ec13c8fSNan Zhou begin = end; 1256ec13c8fSNan Zhou } 1266ec13c8fSNan Zhou return certificatesList; 1276ec13c8fSNan Zhou } 1286ec13c8fSNan Zhou 129cf06ccdcSNan Zhou } // namespace 130f4682712SMarri Devender Rao 131b3dbfb37SPatrick Williams Manager::Manager(sdbusplus::bus_t& bus, sdeventplus::Event& event, 132cf06ccdcSNan Zhou const char* path, CertificateType type, 133cf06ccdcSNan Zhou const std::string& unit, const std::string& installPath) : 134*a2f68d8bSPatrick Williams internal::ManagerInterface(bus, path), bus(bus), event(event), 135*a2f68d8bSPatrick Williams objectPath(path), certType(type), unitToRestart(std::move(unit)), 136*a2f68d8bSPatrick Williams certInstallPath(std::move(installPath)), 137c6e58c7eSRamesh Iyyar certParentInstallPath(fs::path(certInstallPath).parent_path()) 138cfbc8dc8SJayanth Othayoth { 139db5c6fc8SMarri Devender Rao try 140db5c6fc8SMarri Devender Rao { 141fe590c4eSZbigniew Lukwinski // Create certificate directory if not existing. 142bf3cf751SNan Zhou // Set correct certificate directory permissions. 143fe590c4eSZbigniew Lukwinski fs::path certDirectory; 144b57d75e2SMarri Devender Rao try 145b57d75e2SMarri Devender Rao { 146e3d47cd4SNan Zhou if (certType == CertificateType::authority) 147b57d75e2SMarri Devender Rao { 148fe590c4eSZbigniew Lukwinski certDirectory = certInstallPath; 149b57d75e2SMarri Devender Rao } 150fe590c4eSZbigniew Lukwinski else 151fe590c4eSZbigniew Lukwinski { 152fe590c4eSZbigniew Lukwinski certDirectory = certParentInstallPath; 153fe590c4eSZbigniew Lukwinski } 154fe590c4eSZbigniew Lukwinski 155fe590c4eSZbigniew Lukwinski if (!fs::exists(certDirectory)) 156fe590c4eSZbigniew Lukwinski { 157fe590c4eSZbigniew Lukwinski fs::create_directories(certDirectory); 158fe590c4eSZbigniew Lukwinski } 159fe590c4eSZbigniew Lukwinski 160667286e4SMarri Devender Rao auto permission = fs::perms::owner_read | fs::perms::owner_write | 161667286e4SMarri Devender Rao fs::perms::owner_exec; 162db5c6fc8SMarri Devender Rao fs::permissions(certDirectory, permission, 163db5c6fc8SMarri Devender Rao fs::perm_options::replace); 1642f3563ccSZbigniew Lukwinski storageUpdate(); 165b57d75e2SMarri Devender Rao } 16671957992SPatrick Williams catch (const fs::filesystem_error& e) 167b57d75e2SMarri Devender Rao { 168f2646271SRavi Teja lg2::error( 169f2646271SRavi Teja "Failed to create directory, ERR:{ERR}, DIRECTORY:{DIRECTORY}", 170f2646271SRavi Teja "ERR", e, "DIRECTORY", certParentInstallPath); 171b57d75e2SMarri Devender Rao report<InternalFailure>(); 172b57d75e2SMarri Devender Rao } 173b57d75e2SMarri Devender Rao 174c6e58c7eSRamesh Iyyar // Generating RSA private key file if certificate type is server/client 175e3d47cd4SNan Zhou if (certType != CertificateType::authority) 176c6e58c7eSRamesh Iyyar { 177c6e58c7eSRamesh Iyyar createRSAPrivateKeyFile(); 178c6e58c7eSRamesh Iyyar } 179c6e58c7eSRamesh Iyyar 180ffad1ef1SMarri Devender Rao // restore any existing certificates 181db029c95SKowalski, Kamil createCertificates(); 182ffad1ef1SMarri Devender Rao 183ffad1ef1SMarri Devender Rao // watch is not required for authority certificates 184e3d47cd4SNan Zhou if (certType != CertificateType::authority) 185ffad1ef1SMarri Devender Rao { 186ffad1ef1SMarri Devender Rao // watch for certificate file create/replace 187*a2f68d8bSPatrick Williams certWatchPtr = std::make_unique< 188*a2f68d8bSPatrick Williams Watch>(event, certInstallPath, [this]() { 189bf7c588cSMarri Devender Rao try 190bf7c588cSMarri Devender Rao { 191ffad1ef1SMarri Devender Rao // if certificate file existing update it 192db029c95SKowalski, Kamil if (!installedCerts.empty()) 193ffad1ef1SMarri Devender Rao { 194f2646271SRavi Teja lg2::info("Inotify callback to update " 195db5c6fc8SMarri Devender Rao "certificate properties"); 196db029c95SKowalski, Kamil installedCerts[0]->populateProperties(); 197ffad1ef1SMarri Devender Rao } 198ffad1ef1SMarri Devender Rao else 199ffad1ef1SMarri Devender Rao { 200f2646271SRavi Teja lg2::info( 201ffad1ef1SMarri Devender Rao "Inotify callback to create certificate object"); 202db029c95SKowalski, Kamil createCertificates(); 203ffad1ef1SMarri Devender Rao } 204bf7c588cSMarri Devender Rao } 205bf7c588cSMarri Devender Rao catch (const InternalFailure& e) 206bf7c588cSMarri Devender Rao { 207ffad1ef1SMarri Devender Rao commit<InternalFailure>(); 208bf7c588cSMarri Devender Rao } 209bf7c588cSMarri Devender Rao catch (const InvalidCertificate& e) 210bf7c588cSMarri Devender Rao { 211ffad1ef1SMarri Devender Rao commit<InvalidCertificate>(); 212bf7c588cSMarri Devender Rao } 213ffad1ef1SMarri Devender Rao }); 214bf7c588cSMarri Devender Rao } 215db029c95SKowalski, Kamil else 216db029c95SKowalski, Kamil { 217db5c6fc8SMarri Devender Rao try 218db5c6fc8SMarri Devender Rao { 219db5c6fc8SMarri Devender Rao const std::string singleCertPath = "/etc/ssl/certs/Root-CA.pem"; 220db5c6fc8SMarri Devender Rao if (fs::exists(singleCertPath) && !fs::is_empty(singleCertPath)) 221db029c95SKowalski, Kamil { 222f2646271SRavi Teja lg2::notice( 223f2646271SRavi Teja "Legacy certificate detected, will be installed from," 224f2646271SRavi Teja "SINGLE_CERTPATH:{SINGLE_CERTPATH}", 225f2646271SRavi Teja "SINGLE_CERTPATH", singleCertPath); 226db5c6fc8SMarri Devender Rao install(singleCertPath); 227db5c6fc8SMarri Devender Rao if (!fs::remove(singleCertPath)) 228db029c95SKowalski, Kamil { 229f2646271SRavi Teja lg2::error("Unable to remove old certificate from," 230f2646271SRavi Teja "SINGLE_CERTPATH:{SINGLE_CERTPATH}", 231f2646271SRavi Teja "SINGLE_CERTPATH", singleCertPath); 232db029c95SKowalski, Kamil elog<InternalFailure>(); 233db029c95SKowalski, Kamil } 234db029c95SKowalski, Kamil } 235db029c95SKowalski, Kamil } 236db5c6fc8SMarri Devender Rao catch (const std::exception& ex) 237db5c6fc8SMarri Devender Rao { 238f2646271SRavi Teja lg2::error( 239f2646271SRavi Teja "Error in restoring legacy certificate, ERROR_STR:{ERROR_STR}", 240f2646271SRavi Teja "ERROR_STR", ex); 241db5c6fc8SMarri Devender Rao } 242db5c6fc8SMarri Devender Rao } 243db5c6fc8SMarri Devender Rao } 24471957992SPatrick Williams catch (const std::exception& ex) 245db5c6fc8SMarri Devender Rao { 246f2646271SRavi Teja lg2::error( 247f2646271SRavi Teja "Error in certificate manager constructor, ERROR_STR:{ERROR_STR}", 248f2646271SRavi Teja "ERROR_STR", ex); 249db5c6fc8SMarri Devender Rao } 250dd74bd20SJayanth Othayoth } 251589159f2SJayanth Othayoth 25206a69d7bSZbigniew Kurzynski std::string Manager::install(const std::string filePath) 253cfbc8dc8SJayanth Othayoth { 254e3d47cd4SNan Zhou if (certType != CertificateType::authority && !installedCerts.empty()) 2551396511dSMarri Devender Rao { 256cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 2571396511dSMarri Devender Rao } 258e3d47cd4SNan 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, 270698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/false)); 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 2826ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 2836ec13c8fSNan Zhou Manager::installAll(const std::string filePath) 2846ec13c8fSNan Zhou { 285e3d47cd4SNan Zhou if (certType != CertificateType::authority) 2866ec13c8fSNan Zhou { 287*a2f68d8bSPatrick Williams elog<NotAllowed>(NotAllowedReason( 288*a2f68d8bSPatrick Williams "The InstallAll interface is only allowed for " 2896ec13c8fSNan Zhou "Authority certificates")); 2906ec13c8fSNan Zhou } 2916ec13c8fSNan Zhou 2926ec13c8fSNan Zhou if (!installedCerts.empty()) 2936ec13c8fSNan Zhou { 2946ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason( 2956ec13c8fSNan Zhou "There are already root certificates; Call DeleteAll then " 2966ec13c8fSNan Zhou "InstallAll, or use ReplaceAll")); 2976ec13c8fSNan Zhou } 2986ec13c8fSNan Zhou 2996ec13c8fSNan Zhou fs::path sourceFile(filePath); 3006ec13c8fSNan Zhou if (!fs::exists(sourceFile)) 3016ec13c8fSNan Zhou { 302f2646271SRavi Teja lg2::error("File is Missing, FILE:{FILE}", "FILE", filePath); 3036ec13c8fSNan Zhou elog<InternalFailure>(); 3046ec13c8fSNan Zhou } 3056ec13c8fSNan Zhou std::vector<std::string> authorities = splitCertificates(sourceFile); 3066ec13c8fSNan Zhou if (authorities.size() > maxNumAuthorityCertificates) 3076ec13c8fSNan Zhou { 3086ec13c8fSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificates limit reached")); 3096ec13c8fSNan Zhou } 3106ec13c8fSNan Zhou 311f2646271SRavi Teja lg2::info("Starts authority list install"); 31278357b0aSNan Zhou 3136ec13c8fSNan Zhou fs::path authorityStore(certInstallPath); 314*a2f68d8bSPatrick Williams fs::path authoritiesListFile = 315*a2f68d8bSPatrick Williams authorityStore / defaultAuthoritiesListFileName; 3166ec13c8fSNan Zhou 3176ec13c8fSNan Zhou // Atomically install all the certificates 3186ec13c8fSNan Zhou fs::path tempPath = Certificate::generateUniqueFilePath(authorityStore); 3196ec13c8fSNan Zhou fs::create_directory(tempPath); 3206ec13c8fSNan Zhou // Copies the authorities list 3216ec13c8fSNan Zhou Certificate::copyCertificate(sourceFile, 3226ec13c8fSNan Zhou tempPath / defaultAuthoritiesListFileName); 3236ec13c8fSNan Zhou std::vector<std::unique_ptr<Certificate>> tempCertificates; 3246ec13c8fSNan Zhou uint64_t tempCertIdCounter = certIdCounter; 3256ec13c8fSNan Zhou X509StorePtr x509Store = getX509Store(sourceFile); 3266ec13c8fSNan Zhou for (const auto& authority : authorities) 3276ec13c8fSNan Zhou { 328*a2f68d8bSPatrick Williams std::string certObjectPath = 329*a2f68d8bSPatrick Williams objectPath + '/' + std::to_string(tempCertIdCounter); 3306ec13c8fSNan Zhou tempCertificates.emplace_back(std::make_unique<Certificate>( 3316ec13c8fSNan Zhou bus, certObjectPath, certType, tempPath, *x509Store, authority, 332698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/false)); 3336ec13c8fSNan Zhou tempCertIdCounter++; 3346ec13c8fSNan Zhou } 3356ec13c8fSNan Zhou 3366ec13c8fSNan Zhou // We are good now, issue swap 3376ec13c8fSNan Zhou installedCerts = std::move(tempCertificates); 3386ec13c8fSNan Zhou certIdCounter = tempCertIdCounter; 3396ec13c8fSNan Zhou // Rename all the certificates including the authorities list 3406ec13c8fSNan Zhou for (const fs::path& f : fs::directory_iterator(tempPath)) 3416ec13c8fSNan Zhou { 3426ec13c8fSNan Zhou if (fs::is_symlink(f)) 3436ec13c8fSNan Zhou { 3446ec13c8fSNan Zhou continue; 3456ec13c8fSNan Zhou } 3466ec13c8fSNan Zhou fs::rename(/*from=*/f, /*to=*/certInstallPath / f.filename()); 3476ec13c8fSNan Zhou } 3486ec13c8fSNan Zhou // Update file locations and create symbol links 3496ec13c8fSNan Zhou for (const auto& cert : installedCerts) 3506ec13c8fSNan Zhou { 3516ec13c8fSNan Zhou cert->setCertInstallPath(certInstallPath); 352*a2f68d8bSPatrick Williams cert->setCertFilePath( 353*a2f68d8bSPatrick Williams certInstallPath / fs::path(cert->getCertFilePath()).filename()); 3546ec13c8fSNan Zhou cert->storageUpdate(); 3556ec13c8fSNan Zhou } 3566ec13c8fSNan Zhou // Remove the temporary folder 3576ec13c8fSNan Zhou fs::remove_all(tempPath); 3586ec13c8fSNan Zhou 3596ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> objects; 3606ec13c8fSNan Zhou for (const auto& certificate : installedCerts) 3616ec13c8fSNan Zhou { 3626ec13c8fSNan Zhou objects.emplace_back(certificate->getObjectPath()); 3636ec13c8fSNan Zhou } 3646ec13c8fSNan Zhou 365f2646271SRavi Teja lg2::info("Finishes authority list install; reload units starts"); 3666ec13c8fSNan Zhou reloadOrReset(unitToRestart); 3676ec13c8fSNan Zhou return objects; 3686ec13c8fSNan Zhou } 3696ec13c8fSNan Zhou 3706ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> 3716ec13c8fSNan Zhou Manager::replaceAll(std::string filePath) 3726ec13c8fSNan Zhou { 3736ec13c8fSNan Zhou installedCerts.clear(); 3746ec13c8fSNan Zhou certIdCounter = 1; 3756ec13c8fSNan Zhou storageUpdate(); 3766ec13c8fSNan Zhou return installAll(std::move(filePath)); 3776ec13c8fSNan Zhou } 3786ec13c8fSNan Zhou 379a3bb38fbSZbigniew Kurzynski void Manager::deleteAll() 380ae70b3daSDeepak Kodihalli { 3816ceec40bSMarri Devender Rao // TODO: #Issue 4 when a certificate is deleted system auto generates 3826ceec40bSMarri Devender Rao // certificate file. At present we are not supporting creation of 3836ceec40bSMarri Devender Rao // certificate object for the auto-generated certificate file as 3846ceec40bSMarri Devender Rao // deletion if only applicable for REST server and Bmcweb does not allow 3856ceec40bSMarri Devender Rao // deletion of certificates 386db029c95SKowalski, Kamil installedCerts.clear(); 3876ec13c8fSNan Zhou // If the authorities list exists, delete it as well 388e3d47cd4SNan Zhou if (certType == CertificateType::authority) 3896ec13c8fSNan Zhou { 390*a2f68d8bSPatrick Williams if (fs::path authoritiesList = 391*a2f68d8bSPatrick Williams fs::path(certInstallPath) / defaultAuthoritiesListFileName; 3926ec13c8fSNan Zhou fs::exists(authoritiesList)) 3936ec13c8fSNan Zhou { 3946ec13c8fSNan Zhou fs::remove(authoritiesList); 3956ec13c8fSNan Zhou } 3966ec13c8fSNan Zhou } 3976ec13c8fSNan Zhou certIdCounter = 1; 3982f3563ccSZbigniew Lukwinski storageUpdate(); 3992f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 400ae70b3daSDeepak Kodihalli } 401f4682712SMarri Devender Rao 4022f3563ccSZbigniew Lukwinski void Manager::deleteCertificate(const Certificate* const certificate) 403a3bb38fbSZbigniew Kurzynski { 404223e4604SPatrick Williams const std::vector<std::unique_ptr<Certificate>>::iterator& certIt = 405a3bb38fbSZbigniew Kurzynski std::find_if(installedCerts.begin(), installedCerts.end(), 406223e4604SPatrick Williams [certificate](const std::unique_ptr<Certificate>& cert) { 4072f3563ccSZbigniew Lukwinski return (cert.get() == certificate); 408a3bb38fbSZbigniew Kurzynski }); 409a3bb38fbSZbigniew Kurzynski if (certIt != installedCerts.end()) 410a3bb38fbSZbigniew Kurzynski { 411a3bb38fbSZbigniew Kurzynski installedCerts.erase(certIt); 4122f3563ccSZbigniew Lukwinski storageUpdate(); 4132f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 414a3bb38fbSZbigniew Kurzynski } 415a3bb38fbSZbigniew Kurzynski else 416a3bb38fbSZbigniew Kurzynski { 417f2646271SRavi Teja lg2::error("Certificate does not exist, ID:{ID}", "ID", 418f2646271SRavi Teja certificate->getCertId()); 4192f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 4202f3563ccSZbigniew Lukwinski } 4212f3563ccSZbigniew Lukwinski } 4222f3563ccSZbigniew Lukwinski 4232f3563ccSZbigniew Lukwinski void Manager::replaceCertificate(Certificate* const certificate, 4242f3563ccSZbigniew Lukwinski const std::string& filePath) 4252f3563ccSZbigniew Lukwinski { 4262f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath, certificate)) 4272f3563ccSZbigniew Lukwinski { 428698a5743SWilly Tu certificate->install(filePath, false); 4292f3563ccSZbigniew Lukwinski storageUpdate(); 4302f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 4312f3563ccSZbigniew Lukwinski } 4322f3563ccSZbigniew Lukwinski else 4332f3563ccSZbigniew Lukwinski { 434cf06ccdcSNan Zhou elog<NotAllowed>(NotAllowedReason("Certificate already exist")); 435a3bb38fbSZbigniew Kurzynski } 436a3bb38fbSZbigniew Kurzynski } 437a3bb38fbSZbigniew Kurzynski 438f4682712SMarri Devender Rao std::string Manager::generateCSR( 439f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 440f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 441f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 442f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 443f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 444f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 445f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 446f4682712SMarri Devender Rao { 447f4682712SMarri Devender Rao // We support only one CSR. 448f4682712SMarri Devender Rao csrPtr.reset(nullptr); 449f4682712SMarri Devender Rao auto pid = fork(); 450f4682712SMarri Devender Rao if (pid == -1) 451f4682712SMarri Devender Rao { 452f2646271SRavi Teja lg2::error("Error occurred during forking process"); 453f4682712SMarri Devender Rao report<InternalFailure>(); 454f4682712SMarri Devender Rao } 455f4682712SMarri Devender Rao else if (pid == 0) 456f4682712SMarri Devender Rao { 457f4682712SMarri Devender Rao try 458f4682712SMarri Devender Rao { 459*a2f68d8bSPatrick Williams generateCSRHelper( 460*a2f68d8bSPatrick Williams alternativeNames, challengePassword, city, commonName, 461*a2f68d8bSPatrick Williams contactPerson, country, email, givenName, initials, 462*a2f68d8bSPatrick Williams keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 463*a2f68d8bSPatrick Williams organization, organizationalUnit, state, surname, 464f4682712SMarri Devender Rao unstructuredName); 465f4682712SMarri Devender Rao exit(EXIT_SUCCESS); 466f4682712SMarri Devender Rao } 467f4682712SMarri Devender Rao catch (const InternalFailure& e) 468f4682712SMarri Devender Rao { 469f4682712SMarri Devender Rao // commit the error reported in child process and exit 470f4682712SMarri Devender Rao // Callback method from SDEvent Loop looks for exit status 471f4682712SMarri Devender Rao exit(EXIT_FAILURE); 472f4682712SMarri Devender Rao commit<InternalFailure>(); 473f4682712SMarri Devender Rao } 474d2393f23SRamesh Iyyar catch (const InvalidArgument& e) 475d2393f23SRamesh Iyyar { 476d2393f23SRamesh Iyyar // commit the error reported in child process and exit 477d2393f23SRamesh Iyyar // Callback method from SDEvent Loop looks for exit status 478d2393f23SRamesh Iyyar exit(EXIT_FAILURE); 479d2393f23SRamesh Iyyar commit<InvalidArgument>(); 480d2393f23SRamesh Iyyar } 481f4682712SMarri Devender Rao } 482f4682712SMarri Devender Rao else 483f4682712SMarri Devender Rao { 484f4682712SMarri Devender Rao using namespace sdeventplus::source; 485*a2f68d8bSPatrick Williams Child::Callback callback = 486*a2f68d8bSPatrick Williams [this](Child& eventSource, const siginfo_t* si) { 487f4682712SMarri Devender Rao eventSource.set_enabled(Enabled::On); 488f4682712SMarri Devender Rao if (si->si_status != 0) 489f4682712SMarri Devender Rao { 490e3d47cd4SNan Zhou this->createCSRObject(Status::failure); 491f4682712SMarri Devender Rao } 492f4682712SMarri Devender Rao else 493f4682712SMarri Devender Rao { 494e3d47cd4SNan Zhou this->createCSRObject(Status::success); 495f4682712SMarri Devender Rao } 496f4682712SMarri Devender Rao }; 497f4682712SMarri Devender Rao try 498f4682712SMarri Devender Rao { 499f4682712SMarri Devender Rao sigset_t ss; 500f4682712SMarri Devender Rao if (sigemptyset(&ss) < 0) 501f4682712SMarri Devender Rao { 502f2646271SRavi Teja lg2::error("Unable to initialize signal set"); 503f4682712SMarri Devender Rao elog<InternalFailure>(); 504f4682712SMarri Devender Rao } 505f4682712SMarri Devender Rao if (sigaddset(&ss, SIGCHLD) < 0) 506f4682712SMarri Devender Rao { 507f2646271SRavi Teja lg2::error("Unable to add signal to signal set"); 508f4682712SMarri Devender Rao elog<InternalFailure>(); 509f4682712SMarri Devender Rao } 510f4682712SMarri Devender Rao 511f4682712SMarri Devender Rao // Block SIGCHLD first, so that the event loop can handle it 512cfb5802aSNan Zhou if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0) 513f4682712SMarri Devender Rao { 514f2646271SRavi Teja lg2::error("Unable to block signal"); 515f4682712SMarri Devender Rao elog<InternalFailure>(); 516f4682712SMarri Devender Rao } 517f4682712SMarri Devender Rao if (childPtr) 518f4682712SMarri Devender Rao { 519f4682712SMarri Devender Rao childPtr.reset(); 520f4682712SMarri Devender Rao } 521f4682712SMarri Devender Rao childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 522f4682712SMarri Devender Rao std::move(callback)); 523f4682712SMarri Devender Rao } 524f4682712SMarri Devender Rao catch (const InternalFailure& e) 525f4682712SMarri Devender Rao { 526f4682712SMarri Devender Rao commit<InternalFailure>(); 527f4682712SMarri Devender Rao } 528f4682712SMarri Devender Rao } 529f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 530f4682712SMarri Devender Rao return csrObjectPath; 531f4682712SMarri Devender Rao } 532f4682712SMarri Devender Rao 533db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates() 534ffad1ef1SMarri Devender Rao { 535db029c95SKowalski, Kamil return installedCerts; 536ffad1ef1SMarri Devender Rao } 537ffad1ef1SMarri Devender Rao 538f4682712SMarri Devender Rao void Manager::generateCSRHelper( 539f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 540f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 541f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 542f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 543f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 544f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 545f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 546f4682712SMarri Devender Rao { 547f4682712SMarri Devender Rao int ret = 0; 548f4682712SMarri Devender Rao 549cf06ccdcSNan Zhou X509ReqPtr x509Req(X509_REQ_new(), ::X509_REQ_free); 550f4682712SMarri Devender Rao 551f4682712SMarri Devender Rao // set subject of x509 req 552f4682712SMarri Devender Rao X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 553f4682712SMarri Devender Rao 554f4682712SMarri Devender Rao if (!alternativeNames.empty()) 555f4682712SMarri Devender Rao { 556f4682712SMarri Devender Rao for (auto& name : alternativeNames) 557f4682712SMarri Devender Rao { 558f4682712SMarri Devender Rao addEntry(x509Name, "subjectAltName", name); 559f4682712SMarri Devender Rao } 560f4682712SMarri Devender Rao } 561f4682712SMarri Devender Rao addEntry(x509Name, "challengePassword", challengePassword); 562f4682712SMarri Devender Rao addEntry(x509Name, "L", city); 563f4682712SMarri Devender Rao addEntry(x509Name, "CN", commonName); 564f4682712SMarri Devender Rao addEntry(x509Name, "name", contactPerson); 565f4682712SMarri Devender Rao addEntry(x509Name, "C", country); 566f4682712SMarri Devender Rao addEntry(x509Name, "emailAddress", email); 567f4682712SMarri Devender Rao addEntry(x509Name, "GN", givenName); 568f4682712SMarri Devender Rao addEntry(x509Name, "initials", initials); 569f4682712SMarri Devender Rao addEntry(x509Name, "algorithm", keyPairAlgorithm); 570f4682712SMarri Devender Rao if (!keyUsage.empty()) 571f4682712SMarri Devender Rao { 572f4682712SMarri Devender Rao for (auto& usage : keyUsage) 573f4682712SMarri Devender Rao { 5747641105dSMarri Devender Rao if (isExtendedKeyUsage(usage)) 5757641105dSMarri Devender Rao { 5767641105dSMarri Devender Rao addEntry(x509Name, "extendedKeyUsage", usage); 5777641105dSMarri Devender Rao } 5787641105dSMarri Devender Rao else 5797641105dSMarri Devender Rao { 580f4682712SMarri Devender Rao addEntry(x509Name, "keyUsage", usage); 581f4682712SMarri Devender Rao } 582f4682712SMarri Devender Rao } 5837641105dSMarri Devender Rao } 584f4682712SMarri Devender Rao addEntry(x509Name, "O", organization); 585dc91fb61SJayanth Othayoth addEntry(x509Name, "OU", organizationalUnit); 586f4682712SMarri Devender Rao addEntry(x509Name, "ST", state); 587f4682712SMarri Devender Rao addEntry(x509Name, "SN", surname); 588f4682712SMarri Devender Rao addEntry(x509Name, "unstructuredName", unstructuredName); 589f4682712SMarri Devender Rao 590cf06ccdcSNan Zhou EVPPkeyPtr pKey(nullptr, ::EVP_PKEY_free); 5918a09b52aSRamesh Iyyar 592f2646271SRavi Teja lg2::info("Given Key pair algorithm, KEYPAIRALGORITHM:{KEYPAIRALGORITHM}", 593f2646271SRavi Teja "KEYPAIRALGORITHM", keyPairAlgorithm); 5948a09b52aSRamesh Iyyar 5958a09b52aSRamesh Iyyar // Used EC algorithm as default if user did not give algorithm type. 5968a09b52aSRamesh Iyyar if (keyPairAlgorithm == "RSA") 597c6e58c7eSRamesh Iyyar pKey = getRSAKeyPair(keyBitLength); 5988a09b52aSRamesh Iyyar else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 599c6e58c7eSRamesh Iyyar pKey = generateECKeyPair(keyCurveId); 6008a09b52aSRamesh Iyyar else 6018a09b52aSRamesh Iyyar { 602f2646271SRavi Teja lg2::error("Given Key pair algorithm is not supported. Supporting " 6038a09b52aSRamesh Iyyar "RSA and EC only"); 6048a09b52aSRamesh Iyyar elog<InvalidArgument>( 6058a09b52aSRamesh Iyyar Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 6068a09b52aSRamesh Iyyar Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 6078a09b52aSRamesh Iyyar } 6088a09b52aSRamesh Iyyar 6098a09b52aSRamesh Iyyar ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 6108a09b52aSRamesh Iyyar if (ret == 0) 6118a09b52aSRamesh Iyyar { 612f2646271SRavi Teja lg2::error("Error occurred while setting Public key"); 6138dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 6148a09b52aSRamesh Iyyar elog<InternalFailure>(); 6158a09b52aSRamesh Iyyar } 6168a09b52aSRamesh Iyyar 6178a09b52aSRamesh Iyyar // Write private key to file 618718eef37SNan Zhou writePrivateKey(pKey, defaultPrivateKeyFileName); 619f4682712SMarri Devender Rao 620f4682712SMarri Devender Rao // set sign key of x509 req 621f4682712SMarri Devender Rao ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 6228a09b52aSRamesh Iyyar if (ret == 0) 623f4682712SMarri Devender Rao { 624f2646271SRavi Teja lg2::error("Error occurred while signing key of x509"); 6258dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 626f4682712SMarri Devender Rao elog<InternalFailure>(); 627f4682712SMarri Devender Rao } 6288a09b52aSRamesh Iyyar 629f2646271SRavi Teja lg2::info("Writing CSR to file"); 630718eef37SNan Zhou fs::path csrFilePath = certParentInstallPath / defaultCSRFileName; 631c6e58c7eSRamesh Iyyar writeCSR(csrFilePath.string(), x509Req); 632f4682712SMarri Devender Rao } 633f4682712SMarri Devender Rao 6347641105dSMarri Devender Rao bool Manager::isExtendedKeyUsage(const std::string& usage) 6357641105dSMarri Devender Rao { 6367641105dSMarri Devender Rao const static std::array<const char*, 6> usageList = { 6377641105dSMarri Devender Rao "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 6387641105dSMarri Devender Rao "Timestamping", "CodeSigning", "EmailProtection"}; 639d96b81caSPatrick Williams auto it = std::find_if( 640d96b81caSPatrick Williams usageList.begin(), usageList.end(), 641d96b81caSPatrick Williams [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); }); 6427641105dSMarri Devender Rao return it != usageList.end(); 6437641105dSMarri Devender Rao } 644cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateRSAKeyPair(const int64_t keyBitLength) 645f4682712SMarri Devender Rao { 6468a09b52aSRamesh Iyyar int64_t keyBitLen = keyBitLength; 647f4682712SMarri Devender Rao // set keybit length to default value if not set 6488a09b52aSRamesh Iyyar if (keyBitLen <= 0) 649f4682712SMarri Devender Rao { 650f2646271SRavi Teja lg2::info("KeyBitLength is not given.Hence, using default KeyBitLength:" 651f2646271SRavi Teja "{DEFAULTKEYBITLENGTH}", 652f2646271SRavi Teja "DEFAULTKEYBITLENGTH", defaultKeyBitLength); 653cf06ccdcSNan Zhou keyBitLen = defaultKeyBitLength; 654f4682712SMarri Devender Rao } 65526fb83efSPatrick Williams 65626fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 65726fb83efSPatrick Williams 65826fb83efSPatrick Williams // generate rsa key 659cf06ccdcSNan Zhou BignumPtr bne(BN_new(), ::BN_free); 66026fb83efSPatrick Williams auto ret = BN_set_word(bne.get(), RSA_F4); 66126fb83efSPatrick Williams if (ret == 0) 66226fb83efSPatrick Williams { 663f2646271SRavi Teja lg2::error("Error occurred during BN_set_word call"); 6648dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 66526fb83efSPatrick Williams elog<InternalFailure>(); 66626fb83efSPatrick Williams } 667762da74eSNan Zhou using RSAPtr = std::unique_ptr<RSA, decltype(&::RSA_free)>; 668762da74eSNan Zhou RSAPtr rsa(RSA_new(), ::RSA_free); 669762da74eSNan Zhou ret = RSA_generate_key_ex(rsa.get(), keyBitLen, bne.get(), nullptr); 670f4682712SMarri Devender Rao if (ret != 1) 671f4682712SMarri Devender Rao { 672f2646271SRavi Teja lg2::error( 673f2646271SRavi Teja "Error occurred during RSA_generate_key_ex call: {KEYBITLENGTH}", 674f2646271SRavi Teja "KEYBITLENGTH", keyBitLen); 6758dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 676f4682712SMarri Devender Rao elog<InternalFailure>(); 677f4682712SMarri Devender Rao } 678f4682712SMarri Devender Rao 679f4682712SMarri Devender Rao // set public key of x509 req 680cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 681762da74eSNan Zhou ret = EVP_PKEY_assign_RSA(pKey.get(), rsa.get()); 682f4682712SMarri Devender Rao if (ret == 0) 683f4682712SMarri Devender Rao { 684f2646271SRavi Teja lg2::error("Error occurred during assign rsa key into EVP"); 6858dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 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 { 697f2646271SRavi Teja lg2::error("Error occurred creating EVP_PKEY_CTX from algorithm"); 6988dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 69926fb83efSPatrick Williams elog<InternalFailure>(); 70026fb83efSPatrick Williams } 70126fb83efSPatrick Williams 70226fb83efSPatrick Williams if ((EVP_PKEY_keygen_init(ctx.get()) <= 0) || 70326fb83efSPatrick Williams (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), keyBitLen) <= 0)) 70426fb83efSPatrick Williams 70526fb83efSPatrick Williams { 706f2646271SRavi Teja lg2::error("Error occurred initializing keygen context"); 7078dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 70826fb83efSPatrick Williams elog<InternalFailure>(); 70926fb83efSPatrick Williams } 71026fb83efSPatrick Williams 71126fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 71226fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 71326fb83efSPatrick Williams { 714f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 7158dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 71626fb83efSPatrick Williams elog<InternalFailure>(); 71726fb83efSPatrick Williams } 71826fb83efSPatrick Williams 71926fb83efSPatrick Williams return {pKey, &::EVP_PKEY_free}; 72026fb83efSPatrick Williams #endif 7218a09b52aSRamesh Iyyar } 7228a09b52aSRamesh Iyyar 723cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateECKeyPair(const std::string& curveId) 7248a09b52aSRamesh Iyyar { 7258a09b52aSRamesh Iyyar std::string curId(curveId); 7268a09b52aSRamesh Iyyar 7278a09b52aSRamesh Iyyar if (curId.empty()) 7288a09b52aSRamesh Iyyar { 729f2646271SRavi Teja lg2::info("KeyCurveId is not given. Hence using default curve id," 730f2646271SRavi Teja "DEFAULTKEYCURVEID:{DEFAULTKEYCURVEID}", 731f2646271SRavi Teja "DEFAULTKEYCURVEID", defaultKeyCurveID); 732cf06ccdcSNan Zhou curId = defaultKeyCurveID; 7338a09b52aSRamesh Iyyar } 7348a09b52aSRamesh Iyyar 7358a09b52aSRamesh Iyyar int ecGrp = OBJ_txt2nid(curId.c_str()); 7368a09b52aSRamesh Iyyar if (ecGrp == NID_undef) 7378a09b52aSRamesh Iyyar { 738f2646271SRavi Teja lg2::error( 739f2646271SRavi Teja "Error occurred during convert the curve id string format into NID," 740f2646271SRavi Teja "KEYCURVEID:{KEYCURVEID}", 741f2646271SRavi Teja "KEYCURVEID", curId); 7428a09b52aSRamesh Iyyar elog<InternalFailure>(); 7438a09b52aSRamesh Iyyar } 7448a09b52aSRamesh Iyyar 74526fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 74626fb83efSPatrick Williams 7478a09b52aSRamesh Iyyar EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 7488a09b52aSRamesh Iyyar 749cfb5802aSNan Zhou if (ecKey == nullptr) 7508a09b52aSRamesh Iyyar { 751f2646271SRavi Teja lg2::error( 752f2646271SRavi Teja "Error occurred during create the EC_Key object from NID, ECGROUP:{ECGROUP}", 753f2646271SRavi Teja "ECGROUP", ecGrp); 7548dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 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); 768f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 7698dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 7708a09b52aSRamesh Iyyar elog<InternalFailure>(); 7718a09b52aSRamesh Iyyar } 7728a09b52aSRamesh Iyyar 773cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 7748a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 7758a09b52aSRamesh Iyyar if (ret == 0) 7768a09b52aSRamesh Iyyar { 7778a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 778f2646271SRavi Teja lg2::error("Error occurred during assign EC Key into EVP"); 7798dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 7808a09b52aSRamesh Iyyar elog<InternalFailure>(); 7818a09b52aSRamesh Iyyar } 7828a09b52aSRamesh Iyyar 7838a09b52aSRamesh Iyyar return pKey; 78426fb83efSPatrick Williams 78526fb83efSPatrick Williams #else 786e3d47cd4SNan Zhou auto holderOfKey = [](EVP_PKEY* key) { 78726fb83efSPatrick Williams return std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>{ 78826fb83efSPatrick Williams key, &::EVP_PKEY_free}; 78926fb83efSPatrick Williams }; 79026fb83efSPatrick Williams 79126fb83efSPatrick Williams // Create context to set up curve parameters. 79226fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 79326fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr), &::EVP_PKEY_CTX_free); 79426fb83efSPatrick Williams if (!ctx) 79526fb83efSPatrick Williams { 796f2646271SRavi Teja lg2::error("Error occurred creating EVP_PKEY_CTX for params"); 7978dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 79826fb83efSPatrick Williams elog<InternalFailure>(); 79926fb83efSPatrick Williams } 80026fb83efSPatrick Williams 80126fb83efSPatrick Williams // Set up curve parameters. 80226fb83efSPatrick Williams EVP_PKEY* params = nullptr; 80326fb83efSPatrick Williams 80426fb83efSPatrick Williams if ((EVP_PKEY_paramgen_init(ctx.get()) <= 0) || 80526fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_param_enc(ctx.get(), OPENSSL_EC_NAMED_CURVE) <= 80626fb83efSPatrick Williams 0) || 80726fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), ecGrp) <= 0) || 80826fb83efSPatrick Williams (EVP_PKEY_paramgen(ctx.get(), ¶ms) <= 0)) 80926fb83efSPatrick Williams { 810f2646271SRavi Teja lg2::error("Error occurred setting curve parameters"); 8118dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 81226fb83efSPatrick Williams elog<InternalFailure>(); 81326fb83efSPatrick Williams } 81426fb83efSPatrick Williams 81526fb83efSPatrick Williams // Move parameters to RAII holder. 816e3d47cd4SNan Zhou auto pparms = holderOfKey(params); 81726fb83efSPatrick Williams 81826fb83efSPatrick Williams // Create new context for key. 81926fb83efSPatrick Williams ctx.reset(EVP_PKEY_CTX_new_from_pkey(nullptr, params, nullptr)); 82026fb83efSPatrick Williams 82126fb83efSPatrick Williams if (!ctx || (EVP_PKEY_keygen_init(ctx.get()) <= 0)) 82226fb83efSPatrick Williams { 823f2646271SRavi Teja lg2::error("Error occurred initializing keygen context"); 8248dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 82526fb83efSPatrick Williams elog<InternalFailure>(); 82626fb83efSPatrick Williams } 82726fb83efSPatrick Williams 82826fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 82926fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 83026fb83efSPatrick Williams { 831f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 8328dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 83326fb83efSPatrick Williams elog<InternalFailure>(); 83426fb83efSPatrick Williams } 83526fb83efSPatrick Williams 836e3d47cd4SNan Zhou return holderOfKey(pKey); 83726fb83efSPatrick Williams #endif 8388a09b52aSRamesh Iyyar } 8398a09b52aSRamesh Iyyar 840cf06ccdcSNan Zhou void Manager::writePrivateKey(const EVPPkeyPtr& pKey, 841c6e58c7eSRamesh Iyyar const std::string& privKeyFileName) 8428a09b52aSRamesh Iyyar { 843f2646271SRavi Teja lg2::info("Writing private key to file"); 844f4682712SMarri Devender Rao // write private key to file 845c6e58c7eSRamesh Iyyar fs::path privKeyPath = certParentInstallPath / privKeyFileName; 846f4682712SMarri Devender Rao 847f4682712SMarri Devender Rao FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 848cfb5802aSNan Zhou if (fp == nullptr) 849f4682712SMarri Devender Rao { 850f2646271SRavi Teja lg2::error("Error occurred creating private key file"); 851f4682712SMarri Devender Rao elog<InternalFailure>(); 852f4682712SMarri Devender Rao } 853*a2f68d8bSPatrick Williams int ret = 854*a2f68d8bSPatrick Williams PEM_write_PrivateKey(fp, pKey.get(), nullptr, nullptr, 0, 0, nullptr); 855f4682712SMarri Devender Rao std::fclose(fp); 856f4682712SMarri Devender Rao if (ret == 0) 857f4682712SMarri Devender Rao { 858f2646271SRavi Teja lg2::error("Error occurred while writing private key to file"); 859f4682712SMarri Devender Rao elog<InternalFailure>(); 860f4682712SMarri Devender Rao } 861f4682712SMarri Devender Rao } 862f4682712SMarri Devender Rao 863f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field, 864f4682712SMarri Devender Rao const std::string& bytes) 865f4682712SMarri Devender Rao { 866f4682712SMarri Devender Rao if (bytes.empty()) 867f4682712SMarri Devender Rao { 868f4682712SMarri Devender Rao return; 869f4682712SMarri Devender Rao } 870f4682712SMarri Devender Rao int ret = X509_NAME_add_entry_by_txt( 871f4682712SMarri Devender Rao x509Name, field, MBSTRING_ASC, 872f4682712SMarri Devender Rao reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 873f4682712SMarri Devender Rao if (ret != 1) 874f4682712SMarri Devender Rao { 875f2646271SRavi Teja lg2::error("Unable to set entry, FIELD:{FIELD}, VALUE:{VALUE}", "FIELD", 876f2646271SRavi Teja field, "VALUE", bytes); 8778dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 878f4682712SMarri Devender Rao elog<InternalFailure>(); 879f4682712SMarri Devender Rao } 880f4682712SMarri Devender Rao } 881f4682712SMarri Devender Rao 882f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status) 883f4682712SMarri Devender Rao { 884f4682712SMarri Devender Rao if (csrPtr) 885f4682712SMarri Devender Rao { 886f4682712SMarri Devender Rao csrPtr.reset(nullptr); 887f4682712SMarri Devender Rao } 888f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 889f4682712SMarri Devender Rao csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 890f4682712SMarri Devender Rao certInstallPath.c_str(), status); 891f4682712SMarri Devender Rao } 892f4682712SMarri Devender Rao 893cf06ccdcSNan Zhou void Manager::writeCSR(const std::string& filePath, const X509ReqPtr& x509Req) 894f4682712SMarri Devender Rao { 895f4682712SMarri Devender Rao if (fs::exists(filePath)) 896f4682712SMarri Devender Rao { 897f2646271SRavi Teja lg2::info("Removing the existing file, FILENAME:{FILENAME}", "FILENAME", 898f2646271SRavi Teja filePath); 899f4682712SMarri Devender Rao if (!fs::remove(filePath.c_str())) 900f4682712SMarri Devender Rao { 901f2646271SRavi Teja lg2::error("Unable to remove the file, FILENAME:{FILENAME}", 902f2646271SRavi Teja "FILENAME", filePath); 903f4682712SMarri Devender Rao elog<InternalFailure>(); 904f4682712SMarri Devender Rao } 905f4682712SMarri Devender Rao } 906f4682712SMarri Devender Rao 907cfb5802aSNan Zhou FILE* fp = nullptr; 908f4682712SMarri Devender Rao 909cfb5802aSNan Zhou if ((fp = std::fopen(filePath.c_str(), "w")) == nullptr) 910f4682712SMarri Devender Rao { 911f2646271SRavi Teja lg2::error( 912f2646271SRavi Teja "Error opening the file to write the CSR, FILENAME:{FILENAME}", 913f2646271SRavi Teja "FILENAME", filePath); 914f4682712SMarri Devender Rao elog<InternalFailure>(); 915f4682712SMarri Devender Rao } 916f4682712SMarri Devender Rao 917f4682712SMarri Devender Rao int rc = PEM_write_X509_REQ(fp, x509Req.get()); 918f4682712SMarri Devender Rao if (!rc) 919f4682712SMarri Devender Rao { 920f2646271SRavi Teja lg2::error("PEM write routine failed, FILENAME:{FILENAME}", "FILENAME", 921f2646271SRavi Teja filePath); 922f4682712SMarri Devender Rao std::fclose(fp); 923f4682712SMarri Devender Rao elog<InternalFailure>(); 924f4682712SMarri Devender Rao } 925f4682712SMarri Devender Rao std::fclose(fp); 926f4682712SMarri Devender Rao } 927f4682712SMarri Devender Rao 928db029c95SKowalski, Kamil void Manager::createCertificates() 929db029c95SKowalski, Kamil { 930db029c95SKowalski, Kamil auto certObjectPath = objectPath + '/'; 931db029c95SKowalski, Kamil 932e3d47cd4SNan Zhou if (certType == CertificateType::authority) 933db029c95SKowalski, Kamil { 934fe590c4eSZbigniew Lukwinski // Check whether install path is a directory. 935db029c95SKowalski, Kamil if (!fs::is_directory(certInstallPath)) 936db029c95SKowalski, Kamil { 937f2646271SRavi Teja lg2::error("Certificate installation path exists and it is " 938db029c95SKowalski, Kamil "not a directory"); 939db029c95SKowalski, Kamil elog<InternalFailure>(); 9406ec13c8fSNan Zhou } 9416ec13c8fSNan Zhou 9426ec13c8fSNan Zhou // If the authorities list exists, recover from it and return 943*a2f68d8bSPatrick Williams if (fs::path authoritiesListFilePath = 944*a2f68d8bSPatrick Williams fs::path(certInstallPath) / defaultAuthoritiesListFileName; 9456ec13c8fSNan Zhou fs::exists(authoritiesListFilePath)) 9466ec13c8fSNan Zhou { 9476ec13c8fSNan Zhou // remove all other files and directories 9486ec13c8fSNan Zhou for (auto& path : fs::directory_iterator(certInstallPath)) 9496ec13c8fSNan Zhou { 9506ec13c8fSNan Zhou if (path.path() != authoritiesListFilePath) 9516ec13c8fSNan Zhou { 9526ec13c8fSNan Zhou fs::remove_all(path); 9536ec13c8fSNan Zhou } 9546ec13c8fSNan Zhou } 9556ec13c8fSNan Zhou installAll(authoritiesListFilePath); 956db029c95SKowalski, Kamil return; 957db029c95SKowalski, Kamil } 958db029c95SKowalski, Kamil 959db029c95SKowalski, Kamil for (auto& path : fs::directory_iterator(certInstallPath)) 960ffad1ef1SMarri Devender Rao { 961ffad1ef1SMarri Devender Rao try 962ffad1ef1SMarri Devender Rao { 9632f3563ccSZbigniew Lukwinski // Assume here any regular file located in certificate directory 9642f3563ccSZbigniew Lukwinski // contains certificates body. Do not want to use soft links 9652f3563ccSZbigniew Lukwinski // would add value. 9662f3563ccSZbigniew Lukwinski if (fs::is_regular_file(path)) 9672f3563ccSZbigniew Lukwinski { 968db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 969db029c95SKowalski, Kamil bus, certObjectPath + std::to_string(certIdCounter++), 970cf06ccdcSNan Zhou certType, certInstallPath, path.path(), 971698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/true)); 9722f3563ccSZbigniew Lukwinski } 973ffad1ef1SMarri Devender Rao } 974ffad1ef1SMarri Devender Rao catch (const InternalFailure& e) 975ffad1ef1SMarri Devender Rao { 976ffad1ef1SMarri Devender Rao report<InternalFailure>(); 977ffad1ef1SMarri Devender Rao } 978ffad1ef1SMarri Devender Rao catch (const InvalidCertificate& e) 979ffad1ef1SMarri Devender Rao { 980cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 981cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 982ffad1ef1SMarri Devender Rao } 983ffad1ef1SMarri Devender Rao } 984db029c95SKowalski, Kamil } 985db029c95SKowalski, Kamil else if (fs::exists(certInstallPath)) 986db029c95SKowalski, Kamil { 987db029c95SKowalski, Kamil try 988db029c95SKowalski, Kamil { 989db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 9902f3563ccSZbigniew Lukwinski bus, certObjectPath + '1', certType, certInstallPath, 991698a5743SWilly Tu certInstallPath, certWatchPtr.get(), *this, /*restore=*/false)); 992db029c95SKowalski, Kamil } 993db029c95SKowalski, Kamil catch (const InternalFailure& e) 994db029c95SKowalski, Kamil { 995db029c95SKowalski, Kamil report<InternalFailure>(); 996db029c95SKowalski, Kamil } 997db029c95SKowalski, Kamil catch (const InvalidCertificate& e) 998db029c95SKowalski, Kamil { 999cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 1000cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 1001db029c95SKowalski, Kamil } 1002db029c95SKowalski, Kamil } 1003db029c95SKowalski, Kamil } 1004c6e58c7eSRamesh Iyyar 1005c6e58c7eSRamesh Iyyar void Manager::createRSAPrivateKeyFile() 1006c6e58c7eSRamesh Iyyar { 1007*a2f68d8bSPatrick Williams fs::path rsaPrivateKeyFileName = 1008*a2f68d8bSPatrick Williams certParentInstallPath / defaultRSAPrivateKeyFileName; 1009c6e58c7eSRamesh Iyyar 1010c6e58c7eSRamesh Iyyar try 1011c6e58c7eSRamesh Iyyar { 1012c6e58c7eSRamesh Iyyar if (!fs::exists(rsaPrivateKeyFileName)) 1013c6e58c7eSRamesh Iyyar { 1014cf06ccdcSNan Zhou writePrivateKey(generateRSAKeyPair(supportedKeyBitLength), 1015718eef37SNan Zhou defaultRSAPrivateKeyFileName); 1016c6e58c7eSRamesh Iyyar } 1017c6e58c7eSRamesh Iyyar } 1018c6e58c7eSRamesh Iyyar catch (const InternalFailure& e) 1019c6e58c7eSRamesh Iyyar { 1020c6e58c7eSRamesh Iyyar report<InternalFailure>(); 1021c6e58c7eSRamesh Iyyar } 1022c6e58c7eSRamesh Iyyar } 1023c6e58c7eSRamesh Iyyar 1024cf06ccdcSNan Zhou EVPPkeyPtr Manager::getRSAKeyPair(const int64_t keyBitLength) 1025c6e58c7eSRamesh Iyyar { 1026cf06ccdcSNan Zhou if (keyBitLength != supportedKeyBitLength) 1027c6e58c7eSRamesh Iyyar { 1028f2646271SRavi Teja lg2::error( 1029f2646271SRavi Teja "Given Key bit length is not supported, GIVENKEYBITLENGTH:" 1030f2646271SRavi Teja "{GIVENKEYBITLENGTH}, SUPPORTEDKEYBITLENGTH:{SUPPORTEDKEYBITLENGTH}", 1031f2646271SRavi Teja "GIVENKEYBITLENGTH", keyBitLength, "SUPPORTEDKEYBITLENGTH", 1032f2646271SRavi Teja supportedKeyBitLength); 1033c6e58c7eSRamesh Iyyar elog<InvalidArgument>( 1034c6e58c7eSRamesh Iyyar Argument::ARGUMENT_NAME("KEYBITLENGTH"), 1035c6e58c7eSRamesh Iyyar Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 1036c6e58c7eSRamesh Iyyar } 1037*a2f68d8bSPatrick Williams fs::path rsaPrivateKeyFileName = 1038*a2f68d8bSPatrick Williams certParentInstallPath / defaultRSAPrivateKeyFileName; 1039c6e58c7eSRamesh Iyyar 1040c6e58c7eSRamesh Iyyar FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 1041c6e58c7eSRamesh Iyyar if (!privateKeyFile) 1042c6e58c7eSRamesh Iyyar { 1043f2646271SRavi Teja lg2::error( 1044f2646271SRavi Teja "Unable to open RSA private key file to read, RSAKEYFILE:{RSAKEYFILE}," 1045f2646271SRavi Teja "ERRORREASON:{ERRORREASON}", 1046f2646271SRavi Teja "RSAKEYFILE", rsaPrivateKeyFileName, "ERRORREASON", 1047f2646271SRavi Teja strerror(errno)); 1048c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1049c6e58c7eSRamesh Iyyar } 1050c6e58c7eSRamesh Iyyar 1051cf06ccdcSNan Zhou EVPPkeyPtr privateKey( 1052c6e58c7eSRamesh Iyyar PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 1053c6e58c7eSRamesh Iyyar ::EVP_PKEY_free); 1054c6e58c7eSRamesh Iyyar std::fclose(privateKeyFile); 1055c6e58c7eSRamesh Iyyar 1056c6e58c7eSRamesh Iyyar if (!privateKey) 1057c6e58c7eSRamesh Iyyar { 1058f2646271SRavi Teja lg2::error("Error occurred during PEM_read_PrivateKey call"); 1059c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1060c6e58c7eSRamesh Iyyar } 1061c6e58c7eSRamesh Iyyar return privateKey; 1062c6e58c7eSRamesh Iyyar } 10632f3563ccSZbigniew Lukwinski 10642f3563ccSZbigniew Lukwinski void Manager::storageUpdate() 10652f3563ccSZbigniew Lukwinski { 1066e3d47cd4SNan Zhou if (certType == CertificateType::authority) 10672f3563ccSZbigniew Lukwinski { 10682f3563ccSZbigniew Lukwinski // Remove symbolic links in the certificate directory 10692f3563ccSZbigniew Lukwinski for (auto& certPath : fs::directory_iterator(certInstallPath)) 10702f3563ccSZbigniew Lukwinski { 10712f3563ccSZbigniew Lukwinski try 10722f3563ccSZbigniew Lukwinski { 10732f3563ccSZbigniew Lukwinski if (fs::is_symlink(certPath)) 10742f3563ccSZbigniew Lukwinski { 10752f3563ccSZbigniew Lukwinski fs::remove(certPath); 10762f3563ccSZbigniew Lukwinski } 10772f3563ccSZbigniew Lukwinski } 10782f3563ccSZbigniew Lukwinski catch (const std::exception& e) 10792f3563ccSZbigniew Lukwinski { 1080f2646271SRavi Teja lg2::error( 1081f2646271SRavi Teja "Failed to remove symlink for certificate, ERR:{ERR} SYMLINK:{SYMLINK}", 1082f2646271SRavi Teja "ERR", e, "SYMLINK", certPath.path().string()); 10832f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 10842f3563ccSZbigniew Lukwinski } 10852f3563ccSZbigniew Lukwinski } 10862f3563ccSZbigniew Lukwinski } 10872f3563ccSZbigniew Lukwinski 10882f3563ccSZbigniew Lukwinski for (const auto& cert : installedCerts) 10892f3563ccSZbigniew Lukwinski { 10902f3563ccSZbigniew Lukwinski cert->storageUpdate(); 10912f3563ccSZbigniew Lukwinski } 10922f3563ccSZbigniew Lukwinski } 10932f3563ccSZbigniew Lukwinski 1094cf06ccdcSNan Zhou void Manager::reloadOrReset(const std::string& unit) 10952f3563ccSZbigniew Lukwinski { 10962f3563ccSZbigniew Lukwinski if (!unit.empty()) 10972f3563ccSZbigniew Lukwinski { 10982f3563ccSZbigniew Lukwinski try 10992f3563ccSZbigniew Lukwinski { 1100cf06ccdcSNan Zhou constexpr auto defaultSystemdService = "org.freedesktop.systemd1"; 1101cf06ccdcSNan Zhou constexpr auto defaultSystemdObjectPath = 1102cf06ccdcSNan Zhou "/org/freedesktop/systemd1"; 1103cf06ccdcSNan Zhou constexpr auto defaultSystemdInterface = 11042f3563ccSZbigniew Lukwinski "org.freedesktop.systemd1.Manager"; 1105cf06ccdcSNan Zhou auto method = bus.new_method_call( 1106cf06ccdcSNan Zhou defaultSystemdService, defaultSystemdObjectPath, 1107cf06ccdcSNan Zhou defaultSystemdInterface, "ReloadOrRestartUnit"); 11082f3563ccSZbigniew Lukwinski method.append(unit, "replace"); 11092f3563ccSZbigniew Lukwinski bus.call_noreply(method); 11102f3563ccSZbigniew Lukwinski } 1111b3dbfb37SPatrick Williams catch (const sdbusplus::exception_t& e) 11122f3563ccSZbigniew Lukwinski { 1113f2646271SRavi Teja lg2::error( 1114f2646271SRavi Teja "Failed to reload or restart service, ERR:{ERR}, UNIT:{UNIT}", 1115f2646271SRavi Teja "ERR", e, "UNIT", unit); 11162f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 11172f3563ccSZbigniew Lukwinski } 11182f3563ccSZbigniew Lukwinski } 11192f3563ccSZbigniew Lukwinski } 11202f3563ccSZbigniew Lukwinski 11212f3563ccSZbigniew Lukwinski bool Manager::isCertificateUnique(const std::string& filePath, 11222f3563ccSZbigniew Lukwinski const Certificate* const certToDrop) 11232f3563ccSZbigniew Lukwinski { 11242f3563ccSZbigniew Lukwinski if (std::any_of( 11252f3563ccSZbigniew Lukwinski installedCerts.begin(), installedCerts.end(), 1126223e4604SPatrick Williams [&filePath, certToDrop](const std::unique_ptr<Certificate>& cert) { 11272f3563ccSZbigniew Lukwinski return cert.get() != certToDrop && cert->isSame(filePath); 11282f3563ccSZbigniew Lukwinski })) 11292f3563ccSZbigniew Lukwinski { 11302f3563ccSZbigniew Lukwinski return false; 11312f3563ccSZbigniew Lukwinski } 11322f3563ccSZbigniew Lukwinski else 11332f3563ccSZbigniew Lukwinski { 11342f3563ccSZbigniew Lukwinski return true; 11352f3563ccSZbigniew Lukwinski } 11362f3563ccSZbigniew Lukwinski } 11372f3563ccSZbigniew Lukwinski 1138e1289adfSNan Zhou } // namespace phosphor::certs 1139