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> 10*8dbcc72dSAndrew 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) : 134cf06ccdcSNan Zhou internal::ManagerInterface(bus, path), 135f4682712SMarri Devender Rao bus(bus), event(event), objectPath(path), certType(type), 136c6e58c7eSRamesh Iyyar unitToRestart(std::move(unit)), 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 187223e4604SPatrick Williams certWatchPtr = std::make_unique<Watch>(event, certInstallPath, 188223e4604SPatrick Williams [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 { 2876ec13c8fSNan Zhou elog<NotAllowed>( 2886ec13c8fSNan Zhou NotAllowedReason("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); 314223e4604SPatrick Williams fs::path authoritiesListFile = authorityStore / 315223e4604SPatrick Williams 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 { 328223e4604SPatrick Williams std::string certObjectPath = objectPath + '/' + 329223e4604SPatrick Williams 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); 3526ec13c8fSNan Zhou cert->setCertFilePath(certInstallPath / 3536ec13c8fSNan Zhou 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 { 390223e4604SPatrick Williams if (fs::path authoritiesList = fs::path(certInstallPath) / 391223e4604SPatrick Williams 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 { 459f4682712SMarri Devender Rao generateCSRHelper(alternativeNames, challengePassword, city, 460f4682712SMarri Devender Rao commonName, contactPerson, country, email, 461f4682712SMarri Devender Rao givenName, initials, keyBitLength, keyCurveId, 462f4682712SMarri Devender Rao keyPairAlgorithm, keyUsage, organization, 463f4682712SMarri Devender Rao 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; 485d96b81caSPatrick Williams Child::Callback callback = [this](Child& eventSource, 486d96b81caSPatrick Williams 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 549f4682712SMarri Devender Rao // set version of x509 req 550f4682712SMarri Devender Rao int nVersion = 1; 551cf06ccdcSNan Zhou X509ReqPtr x509Req(X509_REQ_new(), ::X509_REQ_free); 552f4682712SMarri Devender Rao ret = X509_REQ_set_version(x509Req.get(), nVersion); 553f4682712SMarri Devender Rao if (ret == 0) 554f4682712SMarri Devender Rao { 555f2646271SRavi Teja lg2::error("Error occurred during X509_REQ_set_version call"); 556*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 557f4682712SMarri Devender Rao elog<InternalFailure>(); 558f4682712SMarri Devender Rao } 559f4682712SMarri Devender Rao 560f4682712SMarri Devender Rao // set subject of x509 req 561f4682712SMarri Devender Rao X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 562f4682712SMarri Devender Rao 563f4682712SMarri Devender Rao if (!alternativeNames.empty()) 564f4682712SMarri Devender Rao { 565f4682712SMarri Devender Rao for (auto& name : alternativeNames) 566f4682712SMarri Devender Rao { 567f4682712SMarri Devender Rao addEntry(x509Name, "subjectAltName", name); 568f4682712SMarri Devender Rao } 569f4682712SMarri Devender Rao } 570f4682712SMarri Devender Rao addEntry(x509Name, "challengePassword", challengePassword); 571f4682712SMarri Devender Rao addEntry(x509Name, "L", city); 572f4682712SMarri Devender Rao addEntry(x509Name, "CN", commonName); 573f4682712SMarri Devender Rao addEntry(x509Name, "name", contactPerson); 574f4682712SMarri Devender Rao addEntry(x509Name, "C", country); 575f4682712SMarri Devender Rao addEntry(x509Name, "emailAddress", email); 576f4682712SMarri Devender Rao addEntry(x509Name, "GN", givenName); 577f4682712SMarri Devender Rao addEntry(x509Name, "initials", initials); 578f4682712SMarri Devender Rao addEntry(x509Name, "algorithm", keyPairAlgorithm); 579f4682712SMarri Devender Rao if (!keyUsage.empty()) 580f4682712SMarri Devender Rao { 581f4682712SMarri Devender Rao for (auto& usage : keyUsage) 582f4682712SMarri Devender Rao { 5837641105dSMarri Devender Rao if (isExtendedKeyUsage(usage)) 5847641105dSMarri Devender Rao { 5857641105dSMarri Devender Rao addEntry(x509Name, "extendedKeyUsage", usage); 5867641105dSMarri Devender Rao } 5877641105dSMarri Devender Rao else 5887641105dSMarri Devender Rao { 589f4682712SMarri Devender Rao addEntry(x509Name, "keyUsage", usage); 590f4682712SMarri Devender Rao } 591f4682712SMarri Devender Rao } 5927641105dSMarri Devender Rao } 593f4682712SMarri Devender Rao addEntry(x509Name, "O", organization); 594dc91fb61SJayanth Othayoth addEntry(x509Name, "OU", organizationalUnit); 595f4682712SMarri Devender Rao addEntry(x509Name, "ST", state); 596f4682712SMarri Devender Rao addEntry(x509Name, "SN", surname); 597f4682712SMarri Devender Rao addEntry(x509Name, "unstructuredName", unstructuredName); 598f4682712SMarri Devender Rao 599cf06ccdcSNan Zhou EVPPkeyPtr pKey(nullptr, ::EVP_PKEY_free); 6008a09b52aSRamesh Iyyar 601f2646271SRavi Teja lg2::info("Given Key pair algorithm, KEYPAIRALGORITHM:{KEYPAIRALGORITHM}", 602f2646271SRavi Teja "KEYPAIRALGORITHM", keyPairAlgorithm); 6038a09b52aSRamesh Iyyar 6048a09b52aSRamesh Iyyar // Used EC algorithm as default if user did not give algorithm type. 6058a09b52aSRamesh Iyyar if (keyPairAlgorithm == "RSA") 606c6e58c7eSRamesh Iyyar pKey = getRSAKeyPair(keyBitLength); 6078a09b52aSRamesh Iyyar else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 608c6e58c7eSRamesh Iyyar pKey = generateECKeyPair(keyCurveId); 6098a09b52aSRamesh Iyyar else 6108a09b52aSRamesh Iyyar { 611f2646271SRavi Teja lg2::error("Given Key pair algorithm is not supported. Supporting " 6128a09b52aSRamesh Iyyar "RSA and EC only"); 6138a09b52aSRamesh Iyyar elog<InvalidArgument>( 6148a09b52aSRamesh Iyyar Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 6158a09b52aSRamesh Iyyar Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 6168a09b52aSRamesh Iyyar } 6178a09b52aSRamesh Iyyar 6188a09b52aSRamesh Iyyar ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 6198a09b52aSRamesh Iyyar if (ret == 0) 6208a09b52aSRamesh Iyyar { 621f2646271SRavi Teja lg2::error("Error occurred while setting Public key"); 622*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 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 { 633f2646271SRavi Teja lg2::error("Error occurred while signing key of x509"); 634*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 635f4682712SMarri Devender Rao elog<InternalFailure>(); 636f4682712SMarri Devender Rao } 6378a09b52aSRamesh Iyyar 638f2646271SRavi Teja lg2::info("Writing CSR to file"); 639718eef37SNan Zhou fs::path csrFilePath = certParentInstallPath / defaultCSRFileName; 640c6e58c7eSRamesh Iyyar writeCSR(csrFilePath.string(), x509Req); 641f4682712SMarri Devender Rao } 642f4682712SMarri Devender Rao 6437641105dSMarri Devender Rao bool Manager::isExtendedKeyUsage(const std::string& usage) 6447641105dSMarri Devender Rao { 6457641105dSMarri Devender Rao const static std::array<const char*, 6> usageList = { 6467641105dSMarri Devender Rao "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 6477641105dSMarri Devender Rao "Timestamping", "CodeSigning", "EmailProtection"}; 648d96b81caSPatrick Williams auto it = std::find_if( 649d96b81caSPatrick Williams usageList.begin(), usageList.end(), 650d96b81caSPatrick Williams [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); }); 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 { 659f2646271SRavi Teja lg2::info("KeyBitLength is not given.Hence, using default KeyBitLength:" 660f2646271SRavi Teja "{DEFAULTKEYBITLENGTH}", 661f2646271SRavi Teja "DEFAULTKEYBITLENGTH", 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 { 672f2646271SRavi Teja lg2::error("Error occurred during BN_set_word call"); 673*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 67426fb83efSPatrick Williams elog<InternalFailure>(); 67526fb83efSPatrick Williams } 676762da74eSNan Zhou using RSAPtr = std::unique_ptr<RSA, decltype(&::RSA_free)>; 677762da74eSNan Zhou RSAPtr rsa(RSA_new(), ::RSA_free); 678762da74eSNan Zhou ret = RSA_generate_key_ex(rsa.get(), keyBitLen, bne.get(), nullptr); 679f4682712SMarri Devender Rao if (ret != 1) 680f4682712SMarri Devender Rao { 681f2646271SRavi Teja lg2::error( 682f2646271SRavi Teja "Error occurred during RSA_generate_key_ex call: {KEYBITLENGTH}", 683f2646271SRavi Teja "KEYBITLENGTH", keyBitLen); 684*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 685f4682712SMarri Devender Rao elog<InternalFailure>(); 686f4682712SMarri Devender Rao } 687f4682712SMarri Devender Rao 688f4682712SMarri Devender Rao // set public key of x509 req 689cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 690762da74eSNan Zhou ret = EVP_PKEY_assign_RSA(pKey.get(), rsa.get()); 691f4682712SMarri Devender Rao if (ret == 0) 692f4682712SMarri Devender Rao { 693f2646271SRavi Teja lg2::error("Error occurred during assign rsa key into EVP"); 694*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 695f4682712SMarri Devender Rao elog<InternalFailure>(); 696f4682712SMarri Devender Rao } 697762da74eSNan Zhou // Now |rsa| is managed by |pKey| 698762da74eSNan Zhou rsa.release(); 6998a09b52aSRamesh Iyyar return pKey; 70026fb83efSPatrick Williams 70126fb83efSPatrick Williams #else 70226fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 70326fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr), &::EVP_PKEY_CTX_free); 70426fb83efSPatrick Williams if (!ctx) 70526fb83efSPatrick Williams { 706f2646271SRavi Teja lg2::error("Error occurred creating EVP_PKEY_CTX from algorithm"); 707*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 70826fb83efSPatrick Williams elog<InternalFailure>(); 70926fb83efSPatrick Williams } 71026fb83efSPatrick Williams 71126fb83efSPatrick Williams if ((EVP_PKEY_keygen_init(ctx.get()) <= 0) || 71226fb83efSPatrick Williams (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), keyBitLen) <= 0)) 71326fb83efSPatrick Williams 71426fb83efSPatrick Williams { 715f2646271SRavi Teja lg2::error("Error occurred initializing keygen context"); 716*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 71726fb83efSPatrick Williams elog<InternalFailure>(); 71826fb83efSPatrick Williams } 71926fb83efSPatrick Williams 72026fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 72126fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 72226fb83efSPatrick Williams { 723f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 724*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 72526fb83efSPatrick Williams elog<InternalFailure>(); 72626fb83efSPatrick Williams } 72726fb83efSPatrick Williams 72826fb83efSPatrick Williams return {pKey, &::EVP_PKEY_free}; 72926fb83efSPatrick Williams #endif 7308a09b52aSRamesh Iyyar } 7318a09b52aSRamesh Iyyar 732cf06ccdcSNan Zhou EVPPkeyPtr Manager::generateECKeyPair(const std::string& curveId) 7338a09b52aSRamesh Iyyar { 7348a09b52aSRamesh Iyyar std::string curId(curveId); 7358a09b52aSRamesh Iyyar 7368a09b52aSRamesh Iyyar if (curId.empty()) 7378a09b52aSRamesh Iyyar { 738f2646271SRavi Teja lg2::info("KeyCurveId is not given. Hence using default curve id," 739f2646271SRavi Teja "DEFAULTKEYCURVEID:{DEFAULTKEYCURVEID}", 740f2646271SRavi Teja "DEFAULTKEYCURVEID", defaultKeyCurveID); 741cf06ccdcSNan Zhou curId = defaultKeyCurveID; 7428a09b52aSRamesh Iyyar } 7438a09b52aSRamesh Iyyar 7448a09b52aSRamesh Iyyar int ecGrp = OBJ_txt2nid(curId.c_str()); 7458a09b52aSRamesh Iyyar if (ecGrp == NID_undef) 7468a09b52aSRamesh Iyyar { 747f2646271SRavi Teja lg2::error( 748f2646271SRavi Teja "Error occurred during convert the curve id string format into NID," 749f2646271SRavi Teja "KEYCURVEID:{KEYCURVEID}", 750f2646271SRavi Teja "KEYCURVEID", curId); 7518a09b52aSRamesh Iyyar elog<InternalFailure>(); 7528a09b52aSRamesh Iyyar } 7538a09b52aSRamesh Iyyar 75426fb83efSPatrick Williams #if (OPENSSL_VERSION_NUMBER < 0x30000000L) 75526fb83efSPatrick Williams 7568a09b52aSRamesh Iyyar EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 7578a09b52aSRamesh Iyyar 758cfb5802aSNan Zhou if (ecKey == nullptr) 7598a09b52aSRamesh Iyyar { 760f2646271SRavi Teja lg2::error( 761f2646271SRavi Teja "Error occurred during create the EC_Key object from NID, ECGROUP:{ECGROUP}", 762f2646271SRavi Teja "ECGROUP", ecGrp); 763*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 7648a09b52aSRamesh Iyyar elog<InternalFailure>(); 7658a09b52aSRamesh Iyyar } 7668a09b52aSRamesh Iyyar 7678a09b52aSRamesh Iyyar // If you want to save a key and later load it with 7688a09b52aSRamesh Iyyar // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 7698a09b52aSRamesh Iyyar // flag on the key. 7708a09b52aSRamesh Iyyar EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 7718a09b52aSRamesh Iyyar 7728a09b52aSRamesh Iyyar int ret = EC_KEY_generate_key(ecKey); 7738a09b52aSRamesh Iyyar 7748a09b52aSRamesh Iyyar if (ret == 0) 7758a09b52aSRamesh Iyyar { 7768a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 777f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 778*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 7798a09b52aSRamesh Iyyar elog<InternalFailure>(); 7808a09b52aSRamesh Iyyar } 7818a09b52aSRamesh Iyyar 782cf06ccdcSNan Zhou EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 7838a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 7848a09b52aSRamesh Iyyar if (ret == 0) 7858a09b52aSRamesh Iyyar { 7868a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 787f2646271SRavi Teja lg2::error("Error occurred during assign EC Key into EVP"); 788*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 7898a09b52aSRamesh Iyyar elog<InternalFailure>(); 7908a09b52aSRamesh Iyyar } 7918a09b52aSRamesh Iyyar 7928a09b52aSRamesh Iyyar return pKey; 79326fb83efSPatrick Williams 79426fb83efSPatrick Williams #else 795e3d47cd4SNan Zhou auto holderOfKey = [](EVP_PKEY* key) { 79626fb83efSPatrick Williams return std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>{ 79726fb83efSPatrick Williams key, &::EVP_PKEY_free}; 79826fb83efSPatrick Williams }; 79926fb83efSPatrick Williams 80026fb83efSPatrick Williams // Create context to set up curve parameters. 80126fb83efSPatrick Williams auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>( 80226fb83efSPatrick Williams EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr), &::EVP_PKEY_CTX_free); 80326fb83efSPatrick Williams if (!ctx) 80426fb83efSPatrick Williams { 805f2646271SRavi Teja lg2::error("Error occurred creating EVP_PKEY_CTX for params"); 806*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 80726fb83efSPatrick Williams elog<InternalFailure>(); 80826fb83efSPatrick Williams } 80926fb83efSPatrick Williams 81026fb83efSPatrick Williams // Set up curve parameters. 81126fb83efSPatrick Williams EVP_PKEY* params = nullptr; 81226fb83efSPatrick Williams 81326fb83efSPatrick Williams if ((EVP_PKEY_paramgen_init(ctx.get()) <= 0) || 81426fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_param_enc(ctx.get(), OPENSSL_EC_NAMED_CURVE) <= 81526fb83efSPatrick Williams 0) || 81626fb83efSPatrick Williams (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), ecGrp) <= 0) || 81726fb83efSPatrick Williams (EVP_PKEY_paramgen(ctx.get(), ¶ms) <= 0)) 81826fb83efSPatrick Williams { 819f2646271SRavi Teja lg2::error("Error occurred setting curve parameters"); 820*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 82126fb83efSPatrick Williams elog<InternalFailure>(); 82226fb83efSPatrick Williams } 82326fb83efSPatrick Williams 82426fb83efSPatrick Williams // Move parameters to RAII holder. 825e3d47cd4SNan Zhou auto pparms = holderOfKey(params); 82626fb83efSPatrick Williams 82726fb83efSPatrick Williams // Create new context for key. 82826fb83efSPatrick Williams ctx.reset(EVP_PKEY_CTX_new_from_pkey(nullptr, params, nullptr)); 82926fb83efSPatrick Williams 83026fb83efSPatrick Williams if (!ctx || (EVP_PKEY_keygen_init(ctx.get()) <= 0)) 83126fb83efSPatrick Williams { 832f2646271SRavi Teja lg2::error("Error occurred initializing keygen context"); 833*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 83426fb83efSPatrick Williams elog<InternalFailure>(); 83526fb83efSPatrick Williams } 83626fb83efSPatrick Williams 83726fb83efSPatrick Williams EVP_PKEY* pKey = nullptr; 83826fb83efSPatrick Williams if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0) 83926fb83efSPatrick Williams { 840f2646271SRavi Teja lg2::error("Error occurred during generate EC key"); 841*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 84226fb83efSPatrick Williams elog<InternalFailure>(); 84326fb83efSPatrick Williams } 84426fb83efSPatrick Williams 845e3d47cd4SNan Zhou return holderOfKey(pKey); 84626fb83efSPatrick Williams #endif 8478a09b52aSRamesh Iyyar } 8488a09b52aSRamesh Iyyar 849cf06ccdcSNan Zhou void Manager::writePrivateKey(const EVPPkeyPtr& pKey, 850c6e58c7eSRamesh Iyyar const std::string& privKeyFileName) 8518a09b52aSRamesh Iyyar { 852f2646271SRavi Teja lg2::info("Writing private key to file"); 853f4682712SMarri Devender Rao // write private key to file 854c6e58c7eSRamesh Iyyar fs::path privKeyPath = certParentInstallPath / privKeyFileName; 855f4682712SMarri Devender Rao 856f4682712SMarri Devender Rao FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 857cfb5802aSNan Zhou if (fp == nullptr) 858f4682712SMarri Devender Rao { 859f2646271SRavi Teja lg2::error("Error occurred creating private key file"); 860f4682712SMarri Devender Rao elog<InternalFailure>(); 861f4682712SMarri Devender Rao } 862223e4604SPatrick Williams int ret = PEM_write_PrivateKey(fp, pKey.get(), nullptr, nullptr, 0, 0, 863223e4604SPatrick Williams nullptr); 864f4682712SMarri Devender Rao std::fclose(fp); 865f4682712SMarri Devender Rao if (ret == 0) 866f4682712SMarri Devender Rao { 867f2646271SRavi Teja lg2::error("Error occurred while writing private key to file"); 868f4682712SMarri Devender Rao elog<InternalFailure>(); 869f4682712SMarri Devender Rao } 870f4682712SMarri Devender Rao } 871f4682712SMarri Devender Rao 872f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field, 873f4682712SMarri Devender Rao const std::string& bytes) 874f4682712SMarri Devender Rao { 875f4682712SMarri Devender Rao if (bytes.empty()) 876f4682712SMarri Devender Rao { 877f4682712SMarri Devender Rao return; 878f4682712SMarri Devender Rao } 879f4682712SMarri Devender Rao int ret = X509_NAME_add_entry_by_txt( 880f4682712SMarri Devender Rao x509Name, field, MBSTRING_ASC, 881f4682712SMarri Devender Rao reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 882f4682712SMarri Devender Rao if (ret != 1) 883f4682712SMarri Devender Rao { 884f2646271SRavi Teja lg2::error("Unable to set entry, FIELD:{FIELD}, VALUE:{VALUE}", "FIELD", 885f2646271SRavi Teja field, "VALUE", bytes); 886*8dbcc72dSAndrew Geissler ERR_print_errors_fp(stderr); 887f4682712SMarri Devender Rao elog<InternalFailure>(); 888f4682712SMarri Devender Rao } 889f4682712SMarri Devender Rao } 890f4682712SMarri Devender Rao 891f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status) 892f4682712SMarri Devender Rao { 893f4682712SMarri Devender Rao if (csrPtr) 894f4682712SMarri Devender Rao { 895f4682712SMarri Devender Rao csrPtr.reset(nullptr); 896f4682712SMarri Devender Rao } 897f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 898f4682712SMarri Devender Rao csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 899f4682712SMarri Devender Rao certInstallPath.c_str(), status); 900f4682712SMarri Devender Rao } 901f4682712SMarri Devender Rao 902cf06ccdcSNan Zhou void Manager::writeCSR(const std::string& filePath, const X509ReqPtr& x509Req) 903f4682712SMarri Devender Rao { 904f4682712SMarri Devender Rao if (fs::exists(filePath)) 905f4682712SMarri Devender Rao { 906f2646271SRavi Teja lg2::info("Removing the existing file, FILENAME:{FILENAME}", "FILENAME", 907f2646271SRavi Teja filePath); 908f4682712SMarri Devender Rao if (!fs::remove(filePath.c_str())) 909f4682712SMarri Devender Rao { 910f2646271SRavi Teja lg2::error("Unable to remove the file, FILENAME:{FILENAME}", 911f2646271SRavi Teja "FILENAME", filePath); 912f4682712SMarri Devender Rao elog<InternalFailure>(); 913f4682712SMarri Devender Rao } 914f4682712SMarri Devender Rao } 915f4682712SMarri Devender Rao 916cfb5802aSNan Zhou FILE* fp = nullptr; 917f4682712SMarri Devender Rao 918cfb5802aSNan Zhou if ((fp = std::fopen(filePath.c_str(), "w")) == nullptr) 919f4682712SMarri Devender Rao { 920f2646271SRavi Teja lg2::error( 921f2646271SRavi Teja "Error opening the file to write the CSR, FILENAME:{FILENAME}", 922f2646271SRavi Teja "FILENAME", filePath); 923f4682712SMarri Devender Rao elog<InternalFailure>(); 924f4682712SMarri Devender Rao } 925f4682712SMarri Devender Rao 926f4682712SMarri Devender Rao int rc = PEM_write_X509_REQ(fp, x509Req.get()); 927f4682712SMarri Devender Rao if (!rc) 928f4682712SMarri Devender Rao { 929f2646271SRavi Teja lg2::error("PEM write routine failed, FILENAME:{FILENAME}", "FILENAME", 930f2646271SRavi Teja filePath); 931f4682712SMarri Devender Rao std::fclose(fp); 932f4682712SMarri Devender Rao elog<InternalFailure>(); 933f4682712SMarri Devender Rao } 934f4682712SMarri Devender Rao std::fclose(fp); 935f4682712SMarri Devender Rao } 936f4682712SMarri Devender Rao 937db029c95SKowalski, Kamil void Manager::createCertificates() 938db029c95SKowalski, Kamil { 939db029c95SKowalski, Kamil auto certObjectPath = objectPath + '/'; 940db029c95SKowalski, Kamil 941e3d47cd4SNan Zhou if (certType == CertificateType::authority) 942db029c95SKowalski, Kamil { 943fe590c4eSZbigniew Lukwinski // Check whether install path is a directory. 944db029c95SKowalski, Kamil if (!fs::is_directory(certInstallPath)) 945db029c95SKowalski, Kamil { 946f2646271SRavi Teja lg2::error("Certificate installation path exists and it is " 947db029c95SKowalski, Kamil "not a directory"); 948db029c95SKowalski, Kamil elog<InternalFailure>(); 9496ec13c8fSNan Zhou } 9506ec13c8fSNan Zhou 9516ec13c8fSNan Zhou // If the authorities list exists, recover from it and return 952223e4604SPatrick Williams if (fs::path authoritiesListFilePath = fs::path(certInstallPath) / 953223e4604SPatrick Williams defaultAuthoritiesListFileName; 9546ec13c8fSNan Zhou fs::exists(authoritiesListFilePath)) 9556ec13c8fSNan Zhou { 9566ec13c8fSNan Zhou // remove all other files and directories 9576ec13c8fSNan Zhou for (auto& path : fs::directory_iterator(certInstallPath)) 9586ec13c8fSNan Zhou { 9596ec13c8fSNan Zhou if (path.path() != authoritiesListFilePath) 9606ec13c8fSNan Zhou { 9616ec13c8fSNan Zhou fs::remove_all(path); 9626ec13c8fSNan Zhou } 9636ec13c8fSNan Zhou } 9646ec13c8fSNan Zhou installAll(authoritiesListFilePath); 965db029c95SKowalski, Kamil return; 966db029c95SKowalski, Kamil } 967db029c95SKowalski, Kamil 968db029c95SKowalski, Kamil for (auto& path : fs::directory_iterator(certInstallPath)) 969ffad1ef1SMarri Devender Rao { 970ffad1ef1SMarri Devender Rao try 971ffad1ef1SMarri Devender Rao { 9722f3563ccSZbigniew Lukwinski // Assume here any regular file located in certificate directory 9732f3563ccSZbigniew Lukwinski // contains certificates body. Do not want to use soft links 9742f3563ccSZbigniew Lukwinski // would add value. 9752f3563ccSZbigniew Lukwinski if (fs::is_regular_file(path)) 9762f3563ccSZbigniew Lukwinski { 977db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 978db029c95SKowalski, Kamil bus, certObjectPath + std::to_string(certIdCounter++), 979cf06ccdcSNan Zhou certType, certInstallPath, path.path(), 980698a5743SWilly Tu certWatchPtr.get(), *this, /*restore=*/true)); 9812f3563ccSZbigniew Lukwinski } 982ffad1ef1SMarri Devender Rao } 983ffad1ef1SMarri Devender Rao catch (const InternalFailure& e) 984ffad1ef1SMarri Devender Rao { 985ffad1ef1SMarri Devender Rao report<InternalFailure>(); 986ffad1ef1SMarri Devender Rao } 987ffad1ef1SMarri Devender Rao catch (const InvalidCertificate& e) 988ffad1ef1SMarri Devender Rao { 989cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 990cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 991ffad1ef1SMarri Devender Rao } 992ffad1ef1SMarri Devender Rao } 993db029c95SKowalski, Kamil } 994db029c95SKowalski, Kamil else if (fs::exists(certInstallPath)) 995db029c95SKowalski, Kamil { 996db029c95SKowalski, Kamil try 997db029c95SKowalski, Kamil { 998db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 9992f3563ccSZbigniew Lukwinski bus, certObjectPath + '1', certType, certInstallPath, 1000698a5743SWilly Tu certInstallPath, certWatchPtr.get(), *this, /*restore=*/false)); 1001db029c95SKowalski, Kamil } 1002db029c95SKowalski, Kamil catch (const InternalFailure& e) 1003db029c95SKowalski, Kamil { 1004db029c95SKowalski, Kamil report<InternalFailure>(); 1005db029c95SKowalski, Kamil } 1006db029c95SKowalski, Kamil catch (const InvalidCertificate& e) 1007db029c95SKowalski, Kamil { 1008cf06ccdcSNan Zhou report<InvalidCertificate>(InvalidCertificateReason( 1009cf06ccdcSNan Zhou "Existing certificate file is corrupted")); 1010db029c95SKowalski, Kamil } 1011db029c95SKowalski, Kamil } 1012db029c95SKowalski, Kamil } 1013c6e58c7eSRamesh Iyyar 1014c6e58c7eSRamesh Iyyar void Manager::createRSAPrivateKeyFile() 1015c6e58c7eSRamesh Iyyar { 1016223e4604SPatrick Williams fs::path rsaPrivateKeyFileName = certParentInstallPath / 1017223e4604SPatrick Williams defaultRSAPrivateKeyFileName; 1018c6e58c7eSRamesh Iyyar 1019c6e58c7eSRamesh Iyyar try 1020c6e58c7eSRamesh Iyyar { 1021c6e58c7eSRamesh Iyyar if (!fs::exists(rsaPrivateKeyFileName)) 1022c6e58c7eSRamesh Iyyar { 1023cf06ccdcSNan Zhou writePrivateKey(generateRSAKeyPair(supportedKeyBitLength), 1024718eef37SNan Zhou defaultRSAPrivateKeyFileName); 1025c6e58c7eSRamesh Iyyar } 1026c6e58c7eSRamesh Iyyar } 1027c6e58c7eSRamesh Iyyar catch (const InternalFailure& e) 1028c6e58c7eSRamesh Iyyar { 1029c6e58c7eSRamesh Iyyar report<InternalFailure>(); 1030c6e58c7eSRamesh Iyyar } 1031c6e58c7eSRamesh Iyyar } 1032c6e58c7eSRamesh Iyyar 1033cf06ccdcSNan Zhou EVPPkeyPtr Manager::getRSAKeyPair(const int64_t keyBitLength) 1034c6e58c7eSRamesh Iyyar { 1035cf06ccdcSNan Zhou if (keyBitLength != supportedKeyBitLength) 1036c6e58c7eSRamesh Iyyar { 1037f2646271SRavi Teja lg2::error( 1038f2646271SRavi Teja "Given Key bit length is not supported, GIVENKEYBITLENGTH:" 1039f2646271SRavi Teja "{GIVENKEYBITLENGTH}, SUPPORTEDKEYBITLENGTH:{SUPPORTEDKEYBITLENGTH}", 1040f2646271SRavi Teja "GIVENKEYBITLENGTH", keyBitLength, "SUPPORTEDKEYBITLENGTH", 1041f2646271SRavi Teja supportedKeyBitLength); 1042c6e58c7eSRamesh Iyyar elog<InvalidArgument>( 1043c6e58c7eSRamesh Iyyar Argument::ARGUMENT_NAME("KEYBITLENGTH"), 1044c6e58c7eSRamesh Iyyar Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 1045c6e58c7eSRamesh Iyyar } 1046223e4604SPatrick Williams fs::path rsaPrivateKeyFileName = certParentInstallPath / 1047223e4604SPatrick Williams defaultRSAPrivateKeyFileName; 1048c6e58c7eSRamesh Iyyar 1049c6e58c7eSRamesh Iyyar FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 1050c6e58c7eSRamesh Iyyar if (!privateKeyFile) 1051c6e58c7eSRamesh Iyyar { 1052f2646271SRavi Teja lg2::error( 1053f2646271SRavi Teja "Unable to open RSA private key file to read, RSAKEYFILE:{RSAKEYFILE}," 1054f2646271SRavi Teja "ERRORREASON:{ERRORREASON}", 1055f2646271SRavi Teja "RSAKEYFILE", rsaPrivateKeyFileName, "ERRORREASON", 1056f2646271SRavi Teja strerror(errno)); 1057c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1058c6e58c7eSRamesh Iyyar } 1059c6e58c7eSRamesh Iyyar 1060cf06ccdcSNan Zhou EVPPkeyPtr privateKey( 1061c6e58c7eSRamesh Iyyar PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 1062c6e58c7eSRamesh Iyyar ::EVP_PKEY_free); 1063c6e58c7eSRamesh Iyyar std::fclose(privateKeyFile); 1064c6e58c7eSRamesh Iyyar 1065c6e58c7eSRamesh Iyyar if (!privateKey) 1066c6e58c7eSRamesh Iyyar { 1067f2646271SRavi Teja lg2::error("Error occurred during PEM_read_PrivateKey call"); 1068c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 1069c6e58c7eSRamesh Iyyar } 1070c6e58c7eSRamesh Iyyar return privateKey; 1071c6e58c7eSRamesh Iyyar } 10722f3563ccSZbigniew Lukwinski 10732f3563ccSZbigniew Lukwinski void Manager::storageUpdate() 10742f3563ccSZbigniew Lukwinski { 1075e3d47cd4SNan Zhou if (certType == CertificateType::authority) 10762f3563ccSZbigniew Lukwinski { 10772f3563ccSZbigniew Lukwinski // Remove symbolic links in the certificate directory 10782f3563ccSZbigniew Lukwinski for (auto& certPath : fs::directory_iterator(certInstallPath)) 10792f3563ccSZbigniew Lukwinski { 10802f3563ccSZbigniew Lukwinski try 10812f3563ccSZbigniew Lukwinski { 10822f3563ccSZbigniew Lukwinski if (fs::is_symlink(certPath)) 10832f3563ccSZbigniew Lukwinski { 10842f3563ccSZbigniew Lukwinski fs::remove(certPath); 10852f3563ccSZbigniew Lukwinski } 10862f3563ccSZbigniew Lukwinski } 10872f3563ccSZbigniew Lukwinski catch (const std::exception& e) 10882f3563ccSZbigniew Lukwinski { 1089f2646271SRavi Teja lg2::error( 1090f2646271SRavi Teja "Failed to remove symlink for certificate, ERR:{ERR} SYMLINK:{SYMLINK}", 1091f2646271SRavi Teja "ERR", e, "SYMLINK", certPath.path().string()); 10922f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 10932f3563ccSZbigniew Lukwinski } 10942f3563ccSZbigniew Lukwinski } 10952f3563ccSZbigniew Lukwinski } 10962f3563ccSZbigniew Lukwinski 10972f3563ccSZbigniew Lukwinski for (const auto& cert : installedCerts) 10982f3563ccSZbigniew Lukwinski { 10992f3563ccSZbigniew Lukwinski cert->storageUpdate(); 11002f3563ccSZbigniew Lukwinski } 11012f3563ccSZbigniew Lukwinski } 11022f3563ccSZbigniew Lukwinski 1103cf06ccdcSNan Zhou void Manager::reloadOrReset(const std::string& unit) 11042f3563ccSZbigniew Lukwinski { 11052f3563ccSZbigniew Lukwinski if (!unit.empty()) 11062f3563ccSZbigniew Lukwinski { 11072f3563ccSZbigniew Lukwinski try 11082f3563ccSZbigniew Lukwinski { 1109cf06ccdcSNan Zhou constexpr auto defaultSystemdService = "org.freedesktop.systemd1"; 1110cf06ccdcSNan Zhou constexpr auto defaultSystemdObjectPath = 1111cf06ccdcSNan Zhou "/org/freedesktop/systemd1"; 1112cf06ccdcSNan Zhou constexpr auto defaultSystemdInterface = 11132f3563ccSZbigniew Lukwinski "org.freedesktop.systemd1.Manager"; 1114cf06ccdcSNan Zhou auto method = bus.new_method_call( 1115cf06ccdcSNan Zhou defaultSystemdService, defaultSystemdObjectPath, 1116cf06ccdcSNan Zhou defaultSystemdInterface, "ReloadOrRestartUnit"); 11172f3563ccSZbigniew Lukwinski method.append(unit, "replace"); 11182f3563ccSZbigniew Lukwinski bus.call_noreply(method); 11192f3563ccSZbigniew Lukwinski } 1120b3dbfb37SPatrick Williams catch (const sdbusplus::exception_t& e) 11212f3563ccSZbigniew Lukwinski { 1122f2646271SRavi Teja lg2::error( 1123f2646271SRavi Teja "Failed to reload or restart service, ERR:{ERR}, UNIT:{UNIT}", 1124f2646271SRavi Teja "ERR", e, "UNIT", unit); 11252f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 11262f3563ccSZbigniew Lukwinski } 11272f3563ccSZbigniew Lukwinski } 11282f3563ccSZbigniew Lukwinski } 11292f3563ccSZbigniew Lukwinski 11302f3563ccSZbigniew Lukwinski bool Manager::isCertificateUnique(const std::string& filePath, 11312f3563ccSZbigniew Lukwinski const Certificate* const certToDrop) 11322f3563ccSZbigniew Lukwinski { 11332f3563ccSZbigniew Lukwinski if (std::any_of( 11342f3563ccSZbigniew Lukwinski installedCerts.begin(), installedCerts.end(), 1135223e4604SPatrick Williams [&filePath, certToDrop](const std::unique_ptr<Certificate>& cert) { 11362f3563ccSZbigniew Lukwinski return cert.get() != certToDrop && cert->isSame(filePath); 11372f3563ccSZbigniew Lukwinski })) 11382f3563ccSZbigniew Lukwinski { 11392f3563ccSZbigniew Lukwinski return false; 11402f3563ccSZbigniew Lukwinski } 11412f3563ccSZbigniew Lukwinski else 11422f3563ccSZbigniew Lukwinski { 11432f3563ccSZbigniew Lukwinski return true; 11442f3563ccSZbigniew Lukwinski } 11452f3563ccSZbigniew Lukwinski } 11462f3563ccSZbigniew Lukwinski 1147e1289adfSNan Zhou } // namespace phosphor::certs 1148