1cfbc8dc8SJayanth Othayoth #include "certs_manager.hpp" 2cfbc8dc8SJayanth Othayoth 3f4682712SMarri Devender Rao #include <openssl/pem.h> 4f4682712SMarri Devender Rao #include <unistd.h> 5f4682712SMarri Devender Rao 6a3bb38fbSZbigniew Kurzynski #include <algorithm> 76ceec40bSMarri Devender Rao #include <phosphor-logging/elog-errors.hpp> 813bf74e4SMarri Devender Rao #include <xyz/openbmc_project/Certs/error.hpp> 9cfbc8dc8SJayanth Othayoth #include <xyz/openbmc_project/Common/error.hpp> 102f3563ccSZbigniew Lukwinski 11cfbc8dc8SJayanth Othayoth namespace phosphor 12cfbc8dc8SJayanth Othayoth { 13cfbc8dc8SJayanth Othayoth namespace certs 14cfbc8dc8SJayanth Othayoth { 151396511dSMarri Devender Rao using InternalFailure = 161396511dSMarri Devender Rao sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 17ffad1ef1SMarri Devender Rao using InvalidCertificate = 18ffad1ef1SMarri Devender Rao sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 19ffad1ef1SMarri Devender Rao using Reason = xyz::openbmc_project::Certs::InvalidCertificate::REASON; 20cfbc8dc8SJayanth Othayoth 21f4682712SMarri Devender Rao using X509_REQ_Ptr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>; 22f4682712SMarri Devender Rao using BIGNUM_Ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>; 23c6e58c7eSRamesh Iyyar using InvalidArgument = 24c6e58c7eSRamesh Iyyar sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 25c6e58c7eSRamesh Iyyar using Argument = xyz::openbmc_project::Common::InvalidArgument; 26c6e58c7eSRamesh Iyyar 27c6e58c7eSRamesh Iyyar constexpr auto SUPPORTED_KEYBITLENGTH = 2048; 28f4682712SMarri Devender Rao 29f4682712SMarri Devender Rao Manager::Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event, 30f4682712SMarri Devender Rao const char* path, const CertificateType& type, 31f4682712SMarri Devender Rao UnitsToRestart&& unit, CertInstallPath&& installPath) : 326ceec40bSMarri Devender Rao Ifaces(bus, path), 33f4682712SMarri Devender Rao bus(bus), event(event), objectPath(path), certType(type), 34c6e58c7eSRamesh Iyyar unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)), 35c6e58c7eSRamesh Iyyar certParentInstallPath(fs::path(certInstallPath).parent_path()) 36cfbc8dc8SJayanth Othayoth { 37fe590c4eSZbigniew Lukwinski // Create certificate directory if not existing. 38fe590c4eSZbigniew Lukwinski // Set correct certificate directory permitions. 39fe590c4eSZbigniew Lukwinski fs::path certDirectory; 40b57d75e2SMarri Devender Rao try 41b57d75e2SMarri Devender Rao { 42fe590c4eSZbigniew Lukwinski if (certType == AUTHORITY) 43b57d75e2SMarri Devender Rao { 44fe590c4eSZbigniew Lukwinski certDirectory = certInstallPath; 45b57d75e2SMarri Devender Rao } 46fe590c4eSZbigniew Lukwinski else 47fe590c4eSZbigniew Lukwinski { 48fe590c4eSZbigniew Lukwinski certDirectory = certParentInstallPath; 49fe590c4eSZbigniew Lukwinski } 50fe590c4eSZbigniew Lukwinski 51fe590c4eSZbigniew Lukwinski if (!fs::exists(certDirectory)) 52fe590c4eSZbigniew Lukwinski { 53fe590c4eSZbigniew Lukwinski fs::create_directories(certDirectory); 54fe590c4eSZbigniew Lukwinski } 55fe590c4eSZbigniew Lukwinski 56667286e4SMarri Devender Rao auto permission = fs::perms::owner_read | fs::perms::owner_write | 57667286e4SMarri Devender Rao fs::perms::owner_exec; 58fe590c4eSZbigniew Lukwinski fs::permissions(certDirectory, permission, fs::perm_options::replace); 592f3563ccSZbigniew Lukwinski storageUpdate(); 60b57d75e2SMarri Devender Rao } 61b57d75e2SMarri Devender Rao catch (fs::filesystem_error& e) 62b57d75e2SMarri Devender Rao { 63b57d75e2SMarri Devender Rao log<level::ERR>("Failed to create directory", entry("ERR=%s", e.what()), 64b57d75e2SMarri Devender Rao entry("DIRECTORY=%s", certParentInstallPath.c_str())); 65b57d75e2SMarri Devender Rao report<InternalFailure>(); 66b57d75e2SMarri Devender Rao } 67b57d75e2SMarri Devender Rao 68c6e58c7eSRamesh Iyyar // Generating RSA private key file if certificate type is server/client 69c6e58c7eSRamesh Iyyar if (certType != AUTHORITY) 70c6e58c7eSRamesh Iyyar { 71c6e58c7eSRamesh Iyyar createRSAPrivateKeyFile(); 72c6e58c7eSRamesh Iyyar } 73c6e58c7eSRamesh Iyyar 74ffad1ef1SMarri Devender Rao // restore any existing certificates 75db029c95SKowalski, Kamil createCertificates(); 76ffad1ef1SMarri Devender Rao 77ffad1ef1SMarri Devender Rao // watch is not required for authority certificates 78ffad1ef1SMarri Devender Rao if (certType != AUTHORITY) 79ffad1ef1SMarri Devender Rao { 80ffad1ef1SMarri Devender Rao // watch for certificate file create/replace 81ffad1ef1SMarri Devender Rao certWatchPtr = std::make_unique< 82ffad1ef1SMarri Devender Rao Watch>(event, certInstallPath, [this]() { 83bf7c588cSMarri Devender Rao try 84bf7c588cSMarri Devender Rao { 85ffad1ef1SMarri Devender Rao // if certificate file existing update it 86db029c95SKowalski, Kamil if (!installedCerts.empty()) 87ffad1ef1SMarri Devender Rao { 88ffad1ef1SMarri Devender Rao log<level::INFO>( 89ffad1ef1SMarri Devender Rao "Inotify callback to update certificate properties"); 90db029c95SKowalski, Kamil installedCerts[0]->populateProperties(); 91ffad1ef1SMarri Devender Rao } 92ffad1ef1SMarri Devender Rao else 93ffad1ef1SMarri Devender Rao { 94ffad1ef1SMarri Devender Rao log<level::INFO>( 95ffad1ef1SMarri Devender Rao "Inotify callback to create certificate object"); 96db029c95SKowalski, Kamil createCertificates(); 97ffad1ef1SMarri Devender Rao } 98bf7c588cSMarri Devender Rao } 99bf7c588cSMarri Devender Rao catch (const InternalFailure& e) 100bf7c588cSMarri Devender Rao { 101ffad1ef1SMarri Devender Rao commit<InternalFailure>(); 102bf7c588cSMarri Devender Rao } 103bf7c588cSMarri Devender Rao catch (const InvalidCertificate& e) 104bf7c588cSMarri Devender Rao { 105ffad1ef1SMarri Devender Rao commit<InvalidCertificate>(); 106bf7c588cSMarri Devender Rao } 107ffad1ef1SMarri Devender Rao }); 108bf7c588cSMarri Devender Rao } 109db029c95SKowalski, Kamil else 110db029c95SKowalski, Kamil { 111db029c95SKowalski, Kamil const std::string signleCertPath = "/etc/ssl/certs/Root-CA.pem"; 112db029c95SKowalski, Kamil if (fs::exists(signleCertPath) && !fs::is_empty(signleCertPath)) 113db029c95SKowalski, Kamil { 114db029c95SKowalski, Kamil log<level::NOTICE>( 115db029c95SKowalski, Kamil "Legacy certificate detected, will be installed from: ", 116db029c95SKowalski, Kamil entry("SINGLE_CERTPATH=%s", signleCertPath.c_str())); 117db029c95SKowalski, Kamil install(signleCertPath); 118db029c95SKowalski, Kamil if (!fs::remove(signleCertPath)) 119db029c95SKowalski, Kamil { 120db029c95SKowalski, Kamil log<level::ERR>( 121db029c95SKowalski, Kamil "Unable to remove old certificate from: ", 122db029c95SKowalski, Kamil entry("SINGLE_CERTPATH=%s", signleCertPath.c_str())); 123db029c95SKowalski, Kamil elog<InternalFailure>(); 124db029c95SKowalski, Kamil } 125db029c95SKowalski, Kamil } 126db029c95SKowalski, Kamil } 127dd74bd20SJayanth Othayoth } 128589159f2SJayanth Othayoth 12906a69d7bSZbigniew Kurzynski std::string Manager::install(const std::string filePath) 130cfbc8dc8SJayanth Othayoth { 1311396511dSMarri Devender Rao using NotAllowed = 1321396511dSMarri Devender Rao sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 1331396511dSMarri Devender Rao using Reason = xyz::openbmc_project::Common::NotAllowed::REASON; 134db029c95SKowalski, Kamil 135db029c95SKowalski, Kamil if (certType != phosphor::certs::AUTHORITY && !installedCerts.empty()) 1361396511dSMarri Devender Rao { 1371396511dSMarri Devender Rao elog<NotAllowed>(Reason("Certificate already exist")); 1381396511dSMarri Devender Rao } 1393b07b77aSZbigniew Lukwinski else if (certType == phosphor::certs::AUTHORITY && 1403b07b77aSZbigniew Lukwinski installedCerts.size() >= AUTHORITY_CERTIFICATES_LIMIT) 1413b07b77aSZbigniew Lukwinski { 1423b07b77aSZbigniew Lukwinski elog<NotAllowed>(Reason("Certificates limit reached")); 1433b07b77aSZbigniew Lukwinski } 144ffad1ef1SMarri Devender Rao 1452f3563ccSZbigniew Lukwinski std::string certObjectPath; 1462f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath)) 1472f3563ccSZbigniew Lukwinski { 1482f3563ccSZbigniew Lukwinski certObjectPath = objectPath + '/' + std::to_string(certIdCounter); 149db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 1502f3563ccSZbigniew Lukwinski bus, certObjectPath, certType, certInstallPath, filePath, 1512f3563ccSZbigniew Lukwinski certWatchPtr, *this)); 1522f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 1532f3563ccSZbigniew Lukwinski certIdCounter++; 1542f3563ccSZbigniew Lukwinski } 1552f3563ccSZbigniew Lukwinski else 1562f3563ccSZbigniew Lukwinski { 1572f3563ccSZbigniew Lukwinski elog<NotAllowed>(Reason("Certificate already exist")); 1582f3563ccSZbigniew Lukwinski } 1592f3563ccSZbigniew Lukwinski 16006a69d7bSZbigniew Kurzynski return certObjectPath; 161589159f2SJayanth Othayoth } 162ae70b3daSDeepak Kodihalli 163a3bb38fbSZbigniew Kurzynski void Manager::deleteAll() 164ae70b3daSDeepak Kodihalli { 1656ceec40bSMarri Devender Rao // TODO: #Issue 4 when a certificate is deleted system auto generates 1666ceec40bSMarri Devender Rao // certificate file. At present we are not supporting creation of 1676ceec40bSMarri Devender Rao // certificate object for the auto-generated certificate file as 1686ceec40bSMarri Devender Rao // deletion if only applicable for REST server and Bmcweb does not allow 1696ceec40bSMarri Devender Rao // deletion of certificates 170db029c95SKowalski, Kamil installedCerts.clear(); 1712f3563ccSZbigniew Lukwinski storageUpdate(); 1722f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 173ae70b3daSDeepak Kodihalli } 174f4682712SMarri Devender Rao 1752f3563ccSZbigniew Lukwinski void Manager::deleteCertificate(const Certificate* const certificate) 176a3bb38fbSZbigniew Kurzynski { 177a3bb38fbSZbigniew Kurzynski std::vector<std::unique_ptr<Certificate>>::iterator const& certIt = 178a3bb38fbSZbigniew Kurzynski std::find_if(installedCerts.begin(), installedCerts.end(), 1792f3563ccSZbigniew Lukwinski [certificate](std::unique_ptr<Certificate> const& cert) { 1802f3563ccSZbigniew Lukwinski return (cert.get() == certificate); 181a3bb38fbSZbigniew Kurzynski }); 182a3bb38fbSZbigniew Kurzynski if (certIt != installedCerts.end()) 183a3bb38fbSZbigniew Kurzynski { 184a3bb38fbSZbigniew Kurzynski installedCerts.erase(certIt); 1852f3563ccSZbigniew Lukwinski storageUpdate(); 1862f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 187a3bb38fbSZbigniew Kurzynski } 188a3bb38fbSZbigniew Kurzynski else 189a3bb38fbSZbigniew Kurzynski { 190a3bb38fbSZbigniew Kurzynski log<level::ERR>("Certificate does not exist", 1912f3563ccSZbigniew Lukwinski entry("ID=%s", certificate->getCertId().c_str())); 1922f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 1932f3563ccSZbigniew Lukwinski } 1942f3563ccSZbigniew Lukwinski } 1952f3563ccSZbigniew Lukwinski 1962f3563ccSZbigniew Lukwinski void Manager::replaceCertificate(Certificate* const certificate, 1972f3563ccSZbigniew Lukwinski const std::string& filePath) 1982f3563ccSZbigniew Lukwinski { 1992f3563ccSZbigniew Lukwinski if (isCertificateUnique(filePath, certificate)) 2002f3563ccSZbigniew Lukwinski { 2012f3563ccSZbigniew Lukwinski certificate->install(filePath); 2022f3563ccSZbigniew Lukwinski storageUpdate(); 2032f3563ccSZbigniew Lukwinski reloadOrReset(unitToRestart); 2042f3563ccSZbigniew Lukwinski } 2052f3563ccSZbigniew Lukwinski else 2062f3563ccSZbigniew Lukwinski { 207*15cbbec2SZbigniew Lukwinski using NotAllowed = 208*15cbbec2SZbigniew Lukwinski sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 209*15cbbec2SZbigniew Lukwinski using Reason = xyz::openbmc_project::Common::NotAllowed::REASON; 210*15cbbec2SZbigniew Lukwinski 211*15cbbec2SZbigniew Lukwinski elog<NotAllowed>(Reason("Certificate already exist")); 212a3bb38fbSZbigniew Kurzynski } 213a3bb38fbSZbigniew Kurzynski } 214a3bb38fbSZbigniew Kurzynski 215f4682712SMarri Devender Rao std::string Manager::generateCSR( 216f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 217f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 218f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 219f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 220f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 221f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 222f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 223f4682712SMarri Devender Rao { 224f4682712SMarri Devender Rao // We support only one CSR. 225f4682712SMarri Devender Rao csrPtr.reset(nullptr); 226f4682712SMarri Devender Rao auto pid = fork(); 227f4682712SMarri Devender Rao if (pid == -1) 228f4682712SMarri Devender Rao { 229f4682712SMarri Devender Rao log<level::ERR>("Error occurred during forking process"); 230f4682712SMarri Devender Rao report<InternalFailure>(); 231f4682712SMarri Devender Rao } 232f4682712SMarri Devender Rao else if (pid == 0) 233f4682712SMarri Devender Rao { 234f4682712SMarri Devender Rao try 235f4682712SMarri Devender Rao { 236f4682712SMarri Devender Rao generateCSRHelper(alternativeNames, challengePassword, city, 237f4682712SMarri Devender Rao commonName, contactPerson, country, email, 238f4682712SMarri Devender Rao givenName, initials, keyBitLength, keyCurveId, 239f4682712SMarri Devender Rao keyPairAlgorithm, keyUsage, organization, 240f4682712SMarri Devender Rao organizationalUnit, state, surname, 241f4682712SMarri Devender Rao unstructuredName); 242f4682712SMarri Devender Rao exit(EXIT_SUCCESS); 243f4682712SMarri Devender Rao } 244f4682712SMarri Devender Rao catch (const InternalFailure& e) 245f4682712SMarri Devender Rao { 246f4682712SMarri Devender Rao // commit the error reported in child process and exit 247f4682712SMarri Devender Rao // Callback method from SDEvent Loop looks for exit status 248f4682712SMarri Devender Rao exit(EXIT_FAILURE); 249f4682712SMarri Devender Rao commit<InternalFailure>(); 250f4682712SMarri Devender Rao } 251f4682712SMarri Devender Rao } 252f4682712SMarri Devender Rao else 253f4682712SMarri Devender Rao { 254f4682712SMarri Devender Rao using namespace sdeventplus::source; 255f4682712SMarri Devender Rao Child::Callback callback = [this](Child& eventSource, 256f4682712SMarri Devender Rao const siginfo_t* si) { 257f4682712SMarri Devender Rao eventSource.set_enabled(Enabled::On); 258f4682712SMarri Devender Rao if (si->si_status != 0) 259f4682712SMarri Devender Rao { 260f4682712SMarri Devender Rao this->createCSRObject(Status::FAILURE); 261f4682712SMarri Devender Rao } 262f4682712SMarri Devender Rao else 263f4682712SMarri Devender Rao { 264f4682712SMarri Devender Rao this->createCSRObject(Status::SUCCESS); 265f4682712SMarri Devender Rao } 266f4682712SMarri Devender Rao }; 267f4682712SMarri Devender Rao try 268f4682712SMarri Devender Rao { 269f4682712SMarri Devender Rao sigset_t ss; 270f4682712SMarri Devender Rao if (sigemptyset(&ss) < 0) 271f4682712SMarri Devender Rao { 272f4682712SMarri Devender Rao log<level::ERR>("Unable to initialize signal set"); 273f4682712SMarri Devender Rao elog<InternalFailure>(); 274f4682712SMarri Devender Rao } 275f4682712SMarri Devender Rao if (sigaddset(&ss, SIGCHLD) < 0) 276f4682712SMarri Devender Rao { 277f4682712SMarri Devender Rao log<level::ERR>("Unable to add signal to signal set"); 278f4682712SMarri Devender Rao elog<InternalFailure>(); 279f4682712SMarri Devender Rao } 280f4682712SMarri Devender Rao 281f4682712SMarri Devender Rao // Block SIGCHLD first, so that the event loop can handle it 282f4682712SMarri Devender Rao if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0) 283f4682712SMarri Devender Rao { 284f4682712SMarri Devender Rao log<level::ERR>("Unable to block signal"); 285f4682712SMarri Devender Rao elog<InternalFailure>(); 286f4682712SMarri Devender Rao } 287f4682712SMarri Devender Rao if (childPtr) 288f4682712SMarri Devender Rao { 289f4682712SMarri Devender Rao childPtr.reset(); 290f4682712SMarri Devender Rao } 291f4682712SMarri Devender Rao childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 292f4682712SMarri Devender Rao std::move(callback)); 293f4682712SMarri Devender Rao } 294f4682712SMarri Devender Rao catch (const InternalFailure& e) 295f4682712SMarri Devender Rao { 296f4682712SMarri Devender Rao commit<InternalFailure>(); 297f4682712SMarri Devender Rao } 298f4682712SMarri Devender Rao } 299f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 300f4682712SMarri Devender Rao return csrObjectPath; 301f4682712SMarri Devender Rao } 302f4682712SMarri Devender Rao 303db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates() 304ffad1ef1SMarri Devender Rao { 305db029c95SKowalski, Kamil return installedCerts; 306ffad1ef1SMarri Devender Rao } 307ffad1ef1SMarri Devender Rao 308f4682712SMarri Devender Rao void Manager::generateCSRHelper( 309f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 310f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 311f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 312f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 313f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 314f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 315f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 316f4682712SMarri Devender Rao { 317f4682712SMarri Devender Rao int ret = 0; 318f4682712SMarri Devender Rao 319f4682712SMarri Devender Rao // set version of x509 req 320f4682712SMarri Devender Rao int nVersion = 1; 321f4682712SMarri Devender Rao // TODO: Issue#6 need to make version number configurable 322f4682712SMarri Devender Rao X509_REQ_Ptr x509Req(X509_REQ_new(), ::X509_REQ_free); 323f4682712SMarri Devender Rao ret = X509_REQ_set_version(x509Req.get(), nVersion); 324f4682712SMarri Devender Rao if (ret == 0) 325f4682712SMarri Devender Rao { 326f4682712SMarri Devender Rao log<level::ERR>("Error occured during X509_REQ_set_version call"); 327f4682712SMarri Devender Rao elog<InternalFailure>(); 328f4682712SMarri Devender Rao } 329f4682712SMarri Devender Rao 330f4682712SMarri Devender Rao // set subject of x509 req 331f4682712SMarri Devender Rao X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 332f4682712SMarri Devender Rao 333f4682712SMarri Devender Rao if (!alternativeNames.empty()) 334f4682712SMarri Devender Rao { 335f4682712SMarri Devender Rao for (auto& name : alternativeNames) 336f4682712SMarri Devender Rao { 337f4682712SMarri Devender Rao addEntry(x509Name, "subjectAltName", name); 338f4682712SMarri Devender Rao } 339f4682712SMarri Devender Rao } 340f4682712SMarri Devender Rao addEntry(x509Name, "challengePassword", challengePassword); 341f4682712SMarri Devender Rao addEntry(x509Name, "L", city); 342f4682712SMarri Devender Rao addEntry(x509Name, "CN", commonName); 343f4682712SMarri Devender Rao addEntry(x509Name, "name", contactPerson); 344f4682712SMarri Devender Rao addEntry(x509Name, "C", country); 345f4682712SMarri Devender Rao addEntry(x509Name, "emailAddress", email); 346f4682712SMarri Devender Rao addEntry(x509Name, "GN", givenName); 347f4682712SMarri Devender Rao addEntry(x509Name, "initials", initials); 348f4682712SMarri Devender Rao addEntry(x509Name, "algorithm", keyPairAlgorithm); 349f4682712SMarri Devender Rao if (!keyUsage.empty()) 350f4682712SMarri Devender Rao { 351f4682712SMarri Devender Rao for (auto& usage : keyUsage) 352f4682712SMarri Devender Rao { 3537641105dSMarri Devender Rao if (isExtendedKeyUsage(usage)) 3547641105dSMarri Devender Rao { 3557641105dSMarri Devender Rao addEntry(x509Name, "extendedKeyUsage", usage); 3567641105dSMarri Devender Rao } 3577641105dSMarri Devender Rao else 3587641105dSMarri Devender Rao { 359f4682712SMarri Devender Rao addEntry(x509Name, "keyUsage", usage); 360f4682712SMarri Devender Rao } 361f4682712SMarri Devender Rao } 3627641105dSMarri Devender Rao } 363f4682712SMarri Devender Rao addEntry(x509Name, "O", organization); 364f4682712SMarri Devender Rao addEntry(x509Name, "ST", state); 365f4682712SMarri Devender Rao addEntry(x509Name, "SN", surname); 366f4682712SMarri Devender Rao addEntry(x509Name, "unstructuredName", unstructuredName); 367f4682712SMarri Devender Rao 3688a09b52aSRamesh Iyyar EVP_PKEY_Ptr pKey(nullptr, ::EVP_PKEY_free); 3698a09b52aSRamesh Iyyar 3708a09b52aSRamesh Iyyar log<level::INFO>("Given Key pair algorithm", 3718a09b52aSRamesh Iyyar entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str())); 3728a09b52aSRamesh Iyyar 3738a09b52aSRamesh Iyyar // Used EC algorithm as default if user did not give algorithm type. 3748a09b52aSRamesh Iyyar if (keyPairAlgorithm == "RSA") 375c6e58c7eSRamesh Iyyar pKey = getRSAKeyPair(keyBitLength); 3768a09b52aSRamesh Iyyar else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 377c6e58c7eSRamesh Iyyar pKey = generateECKeyPair(keyCurveId); 3788a09b52aSRamesh Iyyar else 3798a09b52aSRamesh Iyyar { 3808a09b52aSRamesh Iyyar log<level::ERR>("Given Key pair algorithm is not supported. Supporting " 3818a09b52aSRamesh Iyyar "RSA and EC only"); 3828a09b52aSRamesh Iyyar elog<InvalidArgument>( 3838a09b52aSRamesh Iyyar Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 3848a09b52aSRamesh Iyyar Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 3858a09b52aSRamesh Iyyar } 3868a09b52aSRamesh Iyyar 3878a09b52aSRamesh Iyyar ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 3888a09b52aSRamesh Iyyar if (ret == 0) 3898a09b52aSRamesh Iyyar { 3908a09b52aSRamesh Iyyar log<level::ERR>("Error occured while setting Public key"); 3918a09b52aSRamesh Iyyar elog<InternalFailure>(); 3928a09b52aSRamesh Iyyar } 3938a09b52aSRamesh Iyyar 3948a09b52aSRamesh Iyyar // Write private key to file 395c6e58c7eSRamesh Iyyar writePrivateKey(pKey, PRIV_KEY_FILE_NAME); 396f4682712SMarri Devender Rao 397f4682712SMarri Devender Rao // set sign key of x509 req 398f4682712SMarri Devender Rao ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 3998a09b52aSRamesh Iyyar if (ret == 0) 400f4682712SMarri Devender Rao { 401f4682712SMarri Devender Rao log<level::ERR>("Error occured while signing key of x509"); 402f4682712SMarri Devender Rao elog<InternalFailure>(); 403f4682712SMarri Devender Rao } 4048a09b52aSRamesh Iyyar 405f4682712SMarri Devender Rao log<level::INFO>("Writing CSR to file"); 406c6e58c7eSRamesh Iyyar fs::path csrFilePath = certParentInstallPath / CSR_FILE_NAME; 407c6e58c7eSRamesh Iyyar writeCSR(csrFilePath.string(), x509Req); 408f4682712SMarri Devender Rao } 409f4682712SMarri Devender Rao 4107641105dSMarri Devender Rao bool Manager::isExtendedKeyUsage(const std::string& usage) 4117641105dSMarri Devender Rao { 4127641105dSMarri Devender Rao const static std::array<const char*, 6> usageList = { 4137641105dSMarri Devender Rao "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 4147641105dSMarri Devender Rao "Timestamping", "CodeSigning", "EmailProtection"}; 4157641105dSMarri Devender Rao auto it = std::find_if( 4167641105dSMarri Devender Rao usageList.begin(), usageList.end(), 4177641105dSMarri Devender Rao [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); }); 4187641105dSMarri Devender Rao return it != usageList.end(); 4197641105dSMarri Devender Rao } 4208a09b52aSRamesh Iyyar EVP_PKEY_Ptr Manager::generateRSAKeyPair(const int64_t keyBitLength) 421f4682712SMarri Devender Rao { 422f4682712SMarri Devender Rao int ret = 0; 423f4682712SMarri Devender Rao // generate rsa key 424f4682712SMarri Devender Rao BIGNUM_Ptr bne(BN_new(), ::BN_free); 425f4682712SMarri Devender Rao ret = BN_set_word(bne.get(), RSA_F4); 426f4682712SMarri Devender Rao if (ret == 0) 427f4682712SMarri Devender Rao { 428f4682712SMarri Devender Rao log<level::ERR>("Error occured during BN_set_word call"); 429f4682712SMarri Devender Rao elog<InternalFailure>(); 430f4682712SMarri Devender Rao } 431f4682712SMarri Devender Rao 4328a09b52aSRamesh Iyyar int64_t keyBitLen = keyBitLength; 433f4682712SMarri Devender Rao // set keybit length to default value if not set 4348a09b52aSRamesh Iyyar if (keyBitLen <= 0) 435f4682712SMarri Devender Rao { 4368a09b52aSRamesh Iyyar constexpr auto DEFAULT_KEYBITLENGTH = 2048; 4378a09b52aSRamesh Iyyar log<level::INFO>( 4388a09b52aSRamesh Iyyar "KeyBitLength is not given.Hence, using default KeyBitLength", 4398a09b52aSRamesh Iyyar entry("DEFAULTKEYBITLENGTH=%d", DEFAULT_KEYBITLENGTH)); 4408a09b52aSRamesh Iyyar keyBitLen = DEFAULT_KEYBITLENGTH; 441f4682712SMarri Devender Rao } 442f4682712SMarri Devender Rao RSA* rsa = RSA_new(); 4438a09b52aSRamesh Iyyar ret = RSA_generate_key_ex(rsa, keyBitLen, bne.get(), NULL); 444f4682712SMarri Devender Rao if (ret != 1) 445f4682712SMarri Devender Rao { 446f4682712SMarri Devender Rao free(rsa); 447f4682712SMarri Devender Rao log<level::ERR>("Error occured during RSA_generate_key_ex call", 4488a09b52aSRamesh Iyyar entry("KEYBITLENGTH=%PRIu64", keyBitLen)); 449f4682712SMarri Devender Rao elog<InternalFailure>(); 450f4682712SMarri Devender Rao } 451f4682712SMarri Devender Rao 452f4682712SMarri Devender Rao // set public key of x509 req 453f4682712SMarri Devender Rao EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 4548a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_RSA(pKey.get(), rsa); 455f4682712SMarri Devender Rao if (ret == 0) 456f4682712SMarri Devender Rao { 4578a09b52aSRamesh Iyyar free(rsa); 4588a09b52aSRamesh Iyyar log<level::ERR>("Error occured during assign rsa key into EVP"); 459f4682712SMarri Devender Rao elog<InternalFailure>(); 460f4682712SMarri Devender Rao } 461f4682712SMarri Devender Rao 4628a09b52aSRamesh Iyyar return pKey; 4638a09b52aSRamesh Iyyar } 4648a09b52aSRamesh Iyyar 4658a09b52aSRamesh Iyyar EVP_PKEY_Ptr Manager::generateECKeyPair(const std::string& curveId) 4668a09b52aSRamesh Iyyar { 4678a09b52aSRamesh Iyyar std::string curId(curveId); 4688a09b52aSRamesh Iyyar 4698a09b52aSRamesh Iyyar if (curId.empty()) 4708a09b52aSRamesh Iyyar { 4718a09b52aSRamesh Iyyar // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 4728a09b52aSRamesh Iyyar constexpr auto DEFAULT_KEYCURVEID = "secp224r1"; 4738a09b52aSRamesh Iyyar log<level::INFO>( 4748a09b52aSRamesh Iyyar "KeyCurveId is not given. Hence using default curve id", 4758a09b52aSRamesh Iyyar entry("DEFAULTKEYCURVEID=%s", DEFAULT_KEYCURVEID)); 4768a09b52aSRamesh Iyyar curId = DEFAULT_KEYCURVEID; 4778a09b52aSRamesh Iyyar } 4788a09b52aSRamesh Iyyar 4798a09b52aSRamesh Iyyar int ecGrp = OBJ_txt2nid(curId.c_str()); 4808a09b52aSRamesh Iyyar 4818a09b52aSRamesh Iyyar if (ecGrp == NID_undef) 4828a09b52aSRamesh Iyyar { 4838a09b52aSRamesh Iyyar log<level::ERR>( 4848a09b52aSRamesh Iyyar "Error occured during convert the curve id string format into NID", 4858a09b52aSRamesh Iyyar entry("KEYCURVEID=%s", curId.c_str())); 4868a09b52aSRamesh Iyyar elog<InternalFailure>(); 4878a09b52aSRamesh Iyyar } 4888a09b52aSRamesh Iyyar 4898a09b52aSRamesh Iyyar EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 4908a09b52aSRamesh Iyyar 4918a09b52aSRamesh Iyyar if (ecKey == NULL) 4928a09b52aSRamesh Iyyar { 4938a09b52aSRamesh Iyyar log<level::ERR>( 4948a09b52aSRamesh Iyyar "Error occured during create the EC_Key object from NID", 4958a09b52aSRamesh Iyyar entry("ECGROUP=%d", ecGrp)); 4968a09b52aSRamesh Iyyar elog<InternalFailure>(); 4978a09b52aSRamesh Iyyar } 4988a09b52aSRamesh Iyyar 4998a09b52aSRamesh Iyyar // If you want to save a key and later load it with 5008a09b52aSRamesh Iyyar // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 5018a09b52aSRamesh Iyyar // flag on the key. 5028a09b52aSRamesh Iyyar EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 5038a09b52aSRamesh Iyyar 5048a09b52aSRamesh Iyyar int ret = EC_KEY_generate_key(ecKey); 5058a09b52aSRamesh Iyyar 5068a09b52aSRamesh Iyyar if (ret == 0) 5078a09b52aSRamesh Iyyar { 5088a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 5098a09b52aSRamesh Iyyar log<level::ERR>("Error occured during generate EC key"); 5108a09b52aSRamesh Iyyar elog<InternalFailure>(); 5118a09b52aSRamesh Iyyar } 5128a09b52aSRamesh Iyyar 5138a09b52aSRamesh Iyyar EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 5148a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 5158a09b52aSRamesh Iyyar if (ret == 0) 5168a09b52aSRamesh Iyyar { 5178a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 5188a09b52aSRamesh Iyyar log<level::ERR>("Error occured during assign EC Key into EVP"); 5198a09b52aSRamesh Iyyar elog<InternalFailure>(); 5208a09b52aSRamesh Iyyar } 5218a09b52aSRamesh Iyyar 5228a09b52aSRamesh Iyyar return pKey; 5238a09b52aSRamesh Iyyar } 5248a09b52aSRamesh Iyyar 525c6e58c7eSRamesh Iyyar void Manager::writePrivateKey(const EVP_PKEY_Ptr& pKey, 526c6e58c7eSRamesh Iyyar const std::string& privKeyFileName) 5278a09b52aSRamesh Iyyar { 5288a09b52aSRamesh Iyyar log<level::INFO>("Writing private key to file"); 529f4682712SMarri Devender Rao // write private key to file 530c6e58c7eSRamesh Iyyar fs::path privKeyPath = certParentInstallPath / privKeyFileName; 531f4682712SMarri Devender Rao 532f4682712SMarri Devender Rao FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 533f4682712SMarri Devender Rao if (fp == NULL) 534f4682712SMarri Devender Rao { 535f4682712SMarri Devender Rao log<level::ERR>("Error occured creating private key file"); 536f4682712SMarri Devender Rao elog<InternalFailure>(); 537f4682712SMarri Devender Rao } 5388a09b52aSRamesh Iyyar int ret = PEM_write_PrivateKey(fp, pKey.get(), NULL, NULL, 0, 0, NULL); 539f4682712SMarri Devender Rao std::fclose(fp); 540f4682712SMarri Devender Rao if (ret == 0) 541f4682712SMarri Devender Rao { 542f4682712SMarri Devender Rao log<level::ERR>("Error occured while writing private key to file"); 543f4682712SMarri Devender Rao elog<InternalFailure>(); 544f4682712SMarri Devender Rao } 545f4682712SMarri Devender Rao } 546f4682712SMarri Devender Rao 547f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field, 548f4682712SMarri Devender Rao const std::string& bytes) 549f4682712SMarri Devender Rao { 550f4682712SMarri Devender Rao if (bytes.empty()) 551f4682712SMarri Devender Rao { 552f4682712SMarri Devender Rao return; 553f4682712SMarri Devender Rao } 554f4682712SMarri Devender Rao int ret = X509_NAME_add_entry_by_txt( 555f4682712SMarri Devender Rao x509Name, field, MBSTRING_ASC, 556f4682712SMarri Devender Rao reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 557f4682712SMarri Devender Rao if (ret != 1) 558f4682712SMarri Devender Rao { 559f4682712SMarri Devender Rao log<level::ERR>("Unable to set entry", entry("FIELD=%s", field), 560f4682712SMarri Devender Rao entry("VALUE=%s", bytes.c_str())); 561f4682712SMarri Devender Rao elog<InternalFailure>(); 562f4682712SMarri Devender Rao } 563f4682712SMarri Devender Rao } 564f4682712SMarri Devender Rao 565f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status) 566f4682712SMarri Devender Rao { 567f4682712SMarri Devender Rao if (csrPtr) 568f4682712SMarri Devender Rao { 569f4682712SMarri Devender Rao csrPtr.reset(nullptr); 570f4682712SMarri Devender Rao } 571f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 572f4682712SMarri Devender Rao csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 573f4682712SMarri Devender Rao certInstallPath.c_str(), status); 574f4682712SMarri Devender Rao } 575f4682712SMarri Devender Rao 576f4682712SMarri Devender Rao void Manager::writeCSR(const std::string& filePath, const X509_REQ_Ptr& x509Req) 577f4682712SMarri Devender Rao { 578f4682712SMarri Devender Rao if (fs::exists(filePath)) 579f4682712SMarri Devender Rao { 580f4682712SMarri Devender Rao log<level::INFO>("Removing the existing file", 581f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 582f4682712SMarri Devender Rao if (!fs::remove(filePath.c_str())) 583f4682712SMarri Devender Rao { 584f4682712SMarri Devender Rao log<level::ERR>("Unable to remove the file", 585f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 586f4682712SMarri Devender Rao elog<InternalFailure>(); 587f4682712SMarri Devender Rao } 588f4682712SMarri Devender Rao } 589f4682712SMarri Devender Rao 590f4682712SMarri Devender Rao FILE* fp = NULL; 591f4682712SMarri Devender Rao 592f4682712SMarri Devender Rao if ((fp = std::fopen(filePath.c_str(), "w")) == NULL) 593f4682712SMarri Devender Rao { 594f4682712SMarri Devender Rao log<level::ERR>("Error opening the file to write the CSR", 595f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 596f4682712SMarri Devender Rao elog<InternalFailure>(); 597f4682712SMarri Devender Rao } 598f4682712SMarri Devender Rao 599f4682712SMarri Devender Rao int rc = PEM_write_X509_REQ(fp, x509Req.get()); 600f4682712SMarri Devender Rao if (!rc) 601f4682712SMarri Devender Rao { 602f4682712SMarri Devender Rao log<level::ERR>("PEM write routine failed", 603f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 604f4682712SMarri Devender Rao std::fclose(fp); 605f4682712SMarri Devender Rao elog<InternalFailure>(); 606f4682712SMarri Devender Rao } 607f4682712SMarri Devender Rao std::fclose(fp); 608f4682712SMarri Devender Rao } 609f4682712SMarri Devender Rao 610db029c95SKowalski, Kamil void Manager::createCertificates() 611db029c95SKowalski, Kamil { 612db029c95SKowalski, Kamil auto certObjectPath = objectPath + '/'; 613db029c95SKowalski, Kamil 614db029c95SKowalski, Kamil if (certType == phosphor::certs::AUTHORITY) 615db029c95SKowalski, Kamil { 616fe590c4eSZbigniew Lukwinski // Check whether install path is a directory. 617db029c95SKowalski, Kamil if (!fs::is_directory(certInstallPath)) 618db029c95SKowalski, Kamil { 619db029c95SKowalski, Kamil log<level::ERR>("Certificate installation path exists and it is " 620db029c95SKowalski, Kamil "not a directory"); 621db029c95SKowalski, Kamil elog<InternalFailure>(); 622db029c95SKowalski, Kamil return; 623db029c95SKowalski, Kamil } 624db029c95SKowalski, Kamil 625db029c95SKowalski, Kamil for (auto& path : fs::directory_iterator(certInstallPath)) 626ffad1ef1SMarri Devender Rao { 627ffad1ef1SMarri Devender Rao try 628ffad1ef1SMarri Devender Rao { 6292f3563ccSZbigniew Lukwinski // Assume here any regular file located in certificate directory 6302f3563ccSZbigniew Lukwinski // contains certificates body. Do not want to use soft links 6312f3563ccSZbigniew Lukwinski // would add value. 6322f3563ccSZbigniew Lukwinski if (fs::is_regular_file(path)) 6332f3563ccSZbigniew Lukwinski { 634db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 635db029c95SKowalski, Kamil bus, certObjectPath + std::to_string(certIdCounter++), 6362f3563ccSZbigniew Lukwinski certType, certInstallPath, path.path(), certWatchPtr, 6372f3563ccSZbigniew Lukwinski *this)); 6382f3563ccSZbigniew Lukwinski } 639ffad1ef1SMarri Devender Rao } 640ffad1ef1SMarri Devender Rao catch (const InternalFailure& e) 641ffad1ef1SMarri Devender Rao { 642ffad1ef1SMarri Devender Rao report<InternalFailure>(); 643ffad1ef1SMarri Devender Rao } 644ffad1ef1SMarri Devender Rao catch (const InvalidCertificate& e) 645ffad1ef1SMarri Devender Rao { 646ffad1ef1SMarri Devender Rao report<InvalidCertificate>( 647ffad1ef1SMarri Devender Rao Reason("Existing certificate file is corrupted")); 648ffad1ef1SMarri Devender Rao } 649ffad1ef1SMarri Devender Rao } 650db029c95SKowalski, Kamil } 651db029c95SKowalski, Kamil else if (fs::exists(certInstallPath)) 652db029c95SKowalski, Kamil { 653db029c95SKowalski, Kamil try 654db029c95SKowalski, Kamil { 655db029c95SKowalski, Kamil installedCerts.emplace_back(std::make_unique<Certificate>( 6562f3563ccSZbigniew Lukwinski bus, certObjectPath + '1', certType, certInstallPath, 6572f3563ccSZbigniew Lukwinski certInstallPath, certWatchPtr, *this)); 658db029c95SKowalski, Kamil } 659db029c95SKowalski, Kamil catch (const InternalFailure& e) 660db029c95SKowalski, Kamil { 661db029c95SKowalski, Kamil report<InternalFailure>(); 662db029c95SKowalski, Kamil } 663db029c95SKowalski, Kamil catch (const InvalidCertificate& e) 664db029c95SKowalski, Kamil { 665db029c95SKowalski, Kamil report<InvalidCertificate>( 666db029c95SKowalski, Kamil Reason("Existing certificate file is corrupted")); 667db029c95SKowalski, Kamil } 668db029c95SKowalski, Kamil } 669db029c95SKowalski, Kamil } 670c6e58c7eSRamesh Iyyar 671c6e58c7eSRamesh Iyyar void Manager::createRSAPrivateKeyFile() 672c6e58c7eSRamesh Iyyar { 673c6e58c7eSRamesh Iyyar fs::path rsaPrivateKeyFileName = 674c6e58c7eSRamesh Iyyar certParentInstallPath / RSA_PRIV_KEY_FILE_NAME; 675c6e58c7eSRamesh Iyyar 676c6e58c7eSRamesh Iyyar try 677c6e58c7eSRamesh Iyyar { 678c6e58c7eSRamesh Iyyar if (!fs::exists(rsaPrivateKeyFileName)) 679c6e58c7eSRamesh Iyyar { 680c6e58c7eSRamesh Iyyar writePrivateKey(generateRSAKeyPair(SUPPORTED_KEYBITLENGTH), 681c6e58c7eSRamesh Iyyar RSA_PRIV_KEY_FILE_NAME); 682c6e58c7eSRamesh Iyyar } 683c6e58c7eSRamesh Iyyar } 684c6e58c7eSRamesh Iyyar catch (const InternalFailure& e) 685c6e58c7eSRamesh Iyyar { 686c6e58c7eSRamesh Iyyar report<InternalFailure>(); 687c6e58c7eSRamesh Iyyar } 688c6e58c7eSRamesh Iyyar } 689c6e58c7eSRamesh Iyyar 690c6e58c7eSRamesh Iyyar EVP_PKEY_Ptr Manager::getRSAKeyPair(const int64_t keyBitLength) 691c6e58c7eSRamesh Iyyar { 692c6e58c7eSRamesh Iyyar if (keyBitLength != SUPPORTED_KEYBITLENGTH) 693c6e58c7eSRamesh Iyyar { 694c6e58c7eSRamesh Iyyar log<level::ERR>( 695c6e58c7eSRamesh Iyyar "Given Key bit length is not supported", 696c6e58c7eSRamesh Iyyar entry("GIVENKEYBITLENGTH=%d", keyBitLength), 697c6e58c7eSRamesh Iyyar entry("SUPPORTEDKEYBITLENGTH=%d", SUPPORTED_KEYBITLENGTH)); 698c6e58c7eSRamesh Iyyar elog<InvalidArgument>( 699c6e58c7eSRamesh Iyyar Argument::ARGUMENT_NAME("KEYBITLENGTH"), 700c6e58c7eSRamesh Iyyar Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 701c6e58c7eSRamesh Iyyar } 702c6e58c7eSRamesh Iyyar fs::path rsaPrivateKeyFileName = 703c6e58c7eSRamesh Iyyar certParentInstallPath / RSA_PRIV_KEY_FILE_NAME; 704c6e58c7eSRamesh Iyyar 705c6e58c7eSRamesh Iyyar FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 706c6e58c7eSRamesh Iyyar if (!privateKeyFile) 707c6e58c7eSRamesh Iyyar { 708c6e58c7eSRamesh Iyyar log<level::ERR>("Unable to open RSA private key file to read", 709c6e58c7eSRamesh Iyyar entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()), 710c6e58c7eSRamesh Iyyar entry("ERRORREASON=%s", strerror(errno))); 711c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 712c6e58c7eSRamesh Iyyar } 713c6e58c7eSRamesh Iyyar 714c6e58c7eSRamesh Iyyar EVP_PKEY_Ptr privateKey( 715c6e58c7eSRamesh Iyyar PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 716c6e58c7eSRamesh Iyyar ::EVP_PKEY_free); 717c6e58c7eSRamesh Iyyar std::fclose(privateKeyFile); 718c6e58c7eSRamesh Iyyar 719c6e58c7eSRamesh Iyyar if (!privateKey) 720c6e58c7eSRamesh Iyyar { 721c6e58c7eSRamesh Iyyar log<level::ERR>("Error occured during PEM_read_PrivateKey call"); 722c6e58c7eSRamesh Iyyar elog<InternalFailure>(); 723c6e58c7eSRamesh Iyyar } 724c6e58c7eSRamesh Iyyar return privateKey; 725c6e58c7eSRamesh Iyyar } 7262f3563ccSZbigniew Lukwinski 7272f3563ccSZbigniew Lukwinski void Manager::storageUpdate() 7282f3563ccSZbigniew Lukwinski { 7292f3563ccSZbigniew Lukwinski if (certType == phosphor::certs::AUTHORITY) 7302f3563ccSZbigniew Lukwinski { 7312f3563ccSZbigniew Lukwinski // Remove symbolic links in the certificate directory 7322f3563ccSZbigniew Lukwinski for (auto& certPath : fs::directory_iterator(certInstallPath)) 7332f3563ccSZbigniew Lukwinski { 7342f3563ccSZbigniew Lukwinski try 7352f3563ccSZbigniew Lukwinski { 7362f3563ccSZbigniew Lukwinski if (fs::is_symlink(certPath)) 7372f3563ccSZbigniew Lukwinski { 7382f3563ccSZbigniew Lukwinski fs::remove(certPath); 7392f3563ccSZbigniew Lukwinski } 7402f3563ccSZbigniew Lukwinski } 7412f3563ccSZbigniew Lukwinski catch (const std::exception& e) 7422f3563ccSZbigniew Lukwinski { 7432f3563ccSZbigniew Lukwinski log<level::ERR>( 7442f3563ccSZbigniew Lukwinski "Failed to remove symlink for certificate", 7452f3563ccSZbigniew Lukwinski entry("ERR=%s", e.what()), 7462f3563ccSZbigniew Lukwinski entry("SYMLINK=%s", certPath.path().string().c_str())); 7472f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 7482f3563ccSZbigniew Lukwinski } 7492f3563ccSZbigniew Lukwinski } 7502f3563ccSZbigniew Lukwinski } 7512f3563ccSZbigniew Lukwinski 7522f3563ccSZbigniew Lukwinski for (const auto& cert : installedCerts) 7532f3563ccSZbigniew Lukwinski { 7542f3563ccSZbigniew Lukwinski cert->storageUpdate(); 7552f3563ccSZbigniew Lukwinski } 7562f3563ccSZbigniew Lukwinski } 7572f3563ccSZbigniew Lukwinski 7582f3563ccSZbigniew Lukwinski void Manager::reloadOrReset(const UnitsToRestart& unit) 7592f3563ccSZbigniew Lukwinski { 7602f3563ccSZbigniew Lukwinski if (!unit.empty()) 7612f3563ccSZbigniew Lukwinski { 7622f3563ccSZbigniew Lukwinski try 7632f3563ccSZbigniew Lukwinski { 7642f3563ccSZbigniew Lukwinski constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 7652f3563ccSZbigniew Lukwinski constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; 7662f3563ccSZbigniew Lukwinski constexpr auto SYSTEMD_INTERFACE = 7672f3563ccSZbigniew Lukwinski "org.freedesktop.systemd1.Manager"; 7682f3563ccSZbigniew Lukwinski 7692f3563ccSZbigniew Lukwinski auto method = 7702f3563ccSZbigniew Lukwinski bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, 7712f3563ccSZbigniew Lukwinski SYSTEMD_INTERFACE, "ReloadOrRestartUnit"); 7722f3563ccSZbigniew Lukwinski method.append(unit, "replace"); 7732f3563ccSZbigniew Lukwinski bus.call_noreply(method); 7742f3563ccSZbigniew Lukwinski } 7752f3563ccSZbigniew Lukwinski catch (const sdbusplus::exception::SdBusError& e) 7762f3563ccSZbigniew Lukwinski { 7772f3563ccSZbigniew Lukwinski log<level::ERR>("Failed to reload or restart service", 7782f3563ccSZbigniew Lukwinski entry("ERR=%s", e.what()), 7792f3563ccSZbigniew Lukwinski entry("UNIT=%s", unit.c_str())); 7802f3563ccSZbigniew Lukwinski elog<InternalFailure>(); 7812f3563ccSZbigniew Lukwinski } 7822f3563ccSZbigniew Lukwinski } 7832f3563ccSZbigniew Lukwinski } 7842f3563ccSZbigniew Lukwinski 7852f3563ccSZbigniew Lukwinski bool Manager::isCertificateUnique(const std::string& filePath, 7862f3563ccSZbigniew Lukwinski const Certificate* const certToDrop) 7872f3563ccSZbigniew Lukwinski { 7882f3563ccSZbigniew Lukwinski if (std::any_of( 7892f3563ccSZbigniew Lukwinski installedCerts.begin(), installedCerts.end(), 7902f3563ccSZbigniew Lukwinski [&filePath, certToDrop](std::unique_ptr<Certificate> const& cert) { 7912f3563ccSZbigniew Lukwinski return cert.get() != certToDrop && cert->isSame(filePath); 7922f3563ccSZbigniew Lukwinski })) 7932f3563ccSZbigniew Lukwinski { 7942f3563ccSZbigniew Lukwinski return false; 7952f3563ccSZbigniew Lukwinski } 7962f3563ccSZbigniew Lukwinski else 7972f3563ccSZbigniew Lukwinski { 7982f3563ccSZbigniew Lukwinski return true; 7992f3563ccSZbigniew Lukwinski } 8002f3563ccSZbigniew Lukwinski } 8012f3563ccSZbigniew Lukwinski 802cfbc8dc8SJayanth Othayoth } // namespace certs 803cfbc8dc8SJayanth Othayoth } // namespace phosphor 804