xref: /openbmc/phosphor-certificate-manager/certs_manager.cpp (revision f46827128c0b53aac50e08db772ffe48c9987c65)
1cfbc8dc8SJayanth Othayoth #include "certs_manager.hpp"
2cfbc8dc8SJayanth Othayoth 
3*f4682712SMarri Devender Rao #include <openssl/pem.h>
4*f4682712SMarri Devender Rao #include <unistd.h>
5*f4682712SMarri Devender Rao 
66ceec40bSMarri Devender Rao #include <phosphor-logging/elog-errors.hpp>
713bf74e4SMarri Devender Rao #include <xyz/openbmc_project/Certs/error.hpp>
8cfbc8dc8SJayanth Othayoth #include <xyz/openbmc_project/Common/error.hpp>
9cfbc8dc8SJayanth Othayoth namespace phosphor
10cfbc8dc8SJayanth Othayoth {
11cfbc8dc8SJayanth Othayoth namespace certs
12cfbc8dc8SJayanth Othayoth {
131396511dSMarri Devender Rao using InternalFailure =
141396511dSMarri Devender Rao     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
15cfbc8dc8SJayanth Othayoth 
16*f4682712SMarri Devender Rao using X509_REQ_Ptr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>;
17*f4682712SMarri Devender Rao using BIGNUM_Ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
18*f4682712SMarri Devender Rao 
19*f4682712SMarri Devender Rao Manager::Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event,
20*f4682712SMarri Devender Rao                  const char* path, const CertificateType& type,
21*f4682712SMarri Devender Rao                  UnitsToRestart&& unit, CertInstallPath&& installPath) :
226ceec40bSMarri Devender Rao     Ifaces(bus, path),
23*f4682712SMarri Devender Rao     bus(bus), event(event), objectPath(path), certType(type),
24*f4682712SMarri Devender Rao     unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)),
25*f4682712SMarri Devender Rao     childPtr(nullptr)
26cfbc8dc8SJayanth Othayoth {
2713bf74e4SMarri Devender Rao     using InvalidCertificate =
2813bf74e4SMarri Devender Rao         sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
2913bf74e4SMarri Devender Rao     using Reason = xyz::openbmc_project::Certs::InvalidCertificate::REASON;
30bf7c588cSMarri Devender Rao     if (fs::exists(certInstallPath))
31bf7c588cSMarri Devender Rao     {
32bf7c588cSMarri Devender Rao         try
33bf7c588cSMarri Devender Rao         {
34bf7c588cSMarri Devender Rao             // TODO: Issue#3 At present supporting only one certificate to be
35bf7c588cSMarri Devender Rao             // uploaded this need to be revisited to support multiple
36bf7c588cSMarri Devender Rao             // certificates
37bf7c588cSMarri Devender Rao             auto certObjectPath = objectPath + '/' + '1';
38bf7c588cSMarri Devender Rao             certificatePtr = std::make_unique<Certificate>(
39bf7c588cSMarri Devender Rao                 bus, certObjectPath, certType, unitToRestart, certInstallPath,
408f80c35bSMarri Devender Rao                 certInstallPath, true);
41bf7c588cSMarri Devender Rao         }
42bf7c588cSMarri Devender Rao         catch (const InternalFailure& e)
43bf7c588cSMarri Devender Rao         {
44bf7c588cSMarri Devender Rao             report<InternalFailure>();
45bf7c588cSMarri Devender Rao         }
46bf7c588cSMarri Devender Rao         catch (const InvalidCertificate& e)
47bf7c588cSMarri Devender Rao         {
48bf7c588cSMarri Devender Rao             report<InvalidCertificate>(
49bf7c588cSMarri Devender Rao                 Reason("Existing certificate file is corrupted"));
50bf7c588cSMarri Devender Rao         }
51bf7c588cSMarri Devender Rao     }
52dd74bd20SJayanth Othayoth }
53589159f2SJayanth Othayoth 
546ceec40bSMarri Devender Rao void Manager::install(const std::string filePath)
55cfbc8dc8SJayanth Othayoth {
561396511dSMarri Devender Rao     using NotAllowed =
571396511dSMarri Devender Rao         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
581396511dSMarri Devender Rao     using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
591396511dSMarri Devender Rao     // TODO: Issue#3 At present supporting only one certificate to be
601396511dSMarri Devender Rao     // uploaded this need to be revisited to support multiple
611396511dSMarri Devender Rao     // certificates
621396511dSMarri Devender Rao     if (certificatePtr != nullptr)
631396511dSMarri Devender Rao     {
641396511dSMarri Devender Rao         elog<NotAllowed>(Reason("Certificate already exist"));
651396511dSMarri Devender Rao     }
661396511dSMarri Devender Rao     auto certObjectPath = objectPath + '/' + '1';
678f80c35bSMarri Devender Rao     certificatePtr = std::make_unique<Certificate>(
688f80c35bSMarri Devender Rao         bus, certObjectPath, certType, unitToRestart, certInstallPath, filePath,
698f80c35bSMarri Devender Rao         false);
70589159f2SJayanth Othayoth }
71ae70b3daSDeepak Kodihalli 
72ae70b3daSDeepak Kodihalli void Manager::delete_()
73ae70b3daSDeepak Kodihalli {
746ceec40bSMarri Devender Rao     // TODO: #Issue 4 when a certificate is deleted system auto generates
756ceec40bSMarri Devender Rao     // certificate file. At present we are not supporting creation of
766ceec40bSMarri Devender Rao     // certificate object for the auto-generated certificate file as
776ceec40bSMarri Devender Rao     // deletion if only applicable for REST server and Bmcweb does not allow
786ceec40bSMarri Devender Rao     // deletion of certificates
796ceec40bSMarri Devender Rao     if (certificatePtr != nullptr)
80ae70b3daSDeepak Kodihalli     {
816ceec40bSMarri Devender Rao         certificatePtr.reset(nullptr);
82ae70b3daSDeepak Kodihalli     }
83ae70b3daSDeepak Kodihalli }
84*f4682712SMarri Devender Rao 
85*f4682712SMarri Devender Rao std::string Manager::generateCSR(
86*f4682712SMarri Devender Rao     std::vector<std::string> alternativeNames, std::string challengePassword,
87*f4682712SMarri Devender Rao     std::string city, std::string commonName, std::string contactPerson,
88*f4682712SMarri Devender Rao     std::string country, std::string email, std::string givenName,
89*f4682712SMarri Devender Rao     std::string initials, int64_t keyBitLength, std::string keyCurveId,
90*f4682712SMarri Devender Rao     std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
91*f4682712SMarri Devender Rao     std::string organization, std::string organizationalUnit, std::string state,
92*f4682712SMarri Devender Rao     std::string surname, std::string unstructuredName)
93*f4682712SMarri Devender Rao {
94*f4682712SMarri Devender Rao     // We support only one CSR.
95*f4682712SMarri Devender Rao     csrPtr.reset(nullptr);
96*f4682712SMarri Devender Rao     auto pid = fork();
97*f4682712SMarri Devender Rao     if (pid == -1)
98*f4682712SMarri Devender Rao     {
99*f4682712SMarri Devender Rao         log<level::ERR>("Error occurred during forking process");
100*f4682712SMarri Devender Rao         report<InternalFailure>();
101*f4682712SMarri Devender Rao     }
102*f4682712SMarri Devender Rao     else if (pid == 0)
103*f4682712SMarri Devender Rao     {
104*f4682712SMarri Devender Rao         try
105*f4682712SMarri Devender Rao         {
106*f4682712SMarri Devender Rao             generateCSRHelper(alternativeNames, challengePassword, city,
107*f4682712SMarri Devender Rao                               commonName, contactPerson, country, email,
108*f4682712SMarri Devender Rao                               givenName, initials, keyBitLength, keyCurveId,
109*f4682712SMarri Devender Rao                               keyPairAlgorithm, keyUsage, organization,
110*f4682712SMarri Devender Rao                               organizationalUnit, state, surname,
111*f4682712SMarri Devender Rao                               unstructuredName);
112*f4682712SMarri Devender Rao             exit(EXIT_SUCCESS);
113*f4682712SMarri Devender Rao         }
114*f4682712SMarri Devender Rao         catch (const InternalFailure& e)
115*f4682712SMarri Devender Rao         {
116*f4682712SMarri Devender Rao             // commit the error reported in child process and exit
117*f4682712SMarri Devender Rao             // Callback method from SDEvent Loop looks for exit status
118*f4682712SMarri Devender Rao             exit(EXIT_FAILURE);
119*f4682712SMarri Devender Rao             commit<InternalFailure>();
120*f4682712SMarri Devender Rao         }
121*f4682712SMarri Devender Rao     }
122*f4682712SMarri Devender Rao     else
123*f4682712SMarri Devender Rao     {
124*f4682712SMarri Devender Rao         using namespace sdeventplus::source;
125*f4682712SMarri Devender Rao         Child::Callback callback = [this](Child& eventSource,
126*f4682712SMarri Devender Rao                                           const siginfo_t* si) {
127*f4682712SMarri Devender Rao             eventSource.set_enabled(Enabled::On);
128*f4682712SMarri Devender Rao             if (si->si_status != 0)
129*f4682712SMarri Devender Rao             {
130*f4682712SMarri Devender Rao                 this->createCSRObject(Status::FAILURE);
131*f4682712SMarri Devender Rao             }
132*f4682712SMarri Devender Rao             else
133*f4682712SMarri Devender Rao             {
134*f4682712SMarri Devender Rao                 this->createCSRObject(Status::SUCCESS);
135*f4682712SMarri Devender Rao             }
136*f4682712SMarri Devender Rao         };
137*f4682712SMarri Devender Rao         try
138*f4682712SMarri Devender Rao         {
139*f4682712SMarri Devender Rao             sigset_t ss;
140*f4682712SMarri Devender Rao             if (sigemptyset(&ss) < 0)
141*f4682712SMarri Devender Rao             {
142*f4682712SMarri Devender Rao                 log<level::ERR>("Unable to initialize signal set");
143*f4682712SMarri Devender Rao                 elog<InternalFailure>();
144*f4682712SMarri Devender Rao             }
145*f4682712SMarri Devender Rao             if (sigaddset(&ss, SIGCHLD) < 0)
146*f4682712SMarri Devender Rao             {
147*f4682712SMarri Devender Rao                 log<level::ERR>("Unable to add signal to signal set");
148*f4682712SMarri Devender Rao                 elog<InternalFailure>();
149*f4682712SMarri Devender Rao             }
150*f4682712SMarri Devender Rao 
151*f4682712SMarri Devender Rao             // Block SIGCHLD first, so that the event loop can handle it
152*f4682712SMarri Devender Rao             if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
153*f4682712SMarri Devender Rao             {
154*f4682712SMarri Devender Rao                 log<level::ERR>("Unable to block signal");
155*f4682712SMarri Devender Rao                 elog<InternalFailure>();
156*f4682712SMarri Devender Rao             }
157*f4682712SMarri Devender Rao             if (childPtr)
158*f4682712SMarri Devender Rao             {
159*f4682712SMarri Devender Rao                 childPtr.reset();
160*f4682712SMarri Devender Rao             }
161*f4682712SMarri Devender Rao             childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED,
162*f4682712SMarri Devender Rao                                                std::move(callback));
163*f4682712SMarri Devender Rao         }
164*f4682712SMarri Devender Rao         catch (const InternalFailure& e)
165*f4682712SMarri Devender Rao         {
166*f4682712SMarri Devender Rao             commit<InternalFailure>();
167*f4682712SMarri Devender Rao         }
168*f4682712SMarri Devender Rao     }
169*f4682712SMarri Devender Rao     auto csrObjectPath = objectPath + '/' + "csr";
170*f4682712SMarri Devender Rao     return csrObjectPath;
171*f4682712SMarri Devender Rao }
172*f4682712SMarri Devender Rao 
173*f4682712SMarri Devender Rao void Manager::generateCSRHelper(
174*f4682712SMarri Devender Rao     std::vector<std::string> alternativeNames, std::string challengePassword,
175*f4682712SMarri Devender Rao     std::string city, std::string commonName, std::string contactPerson,
176*f4682712SMarri Devender Rao     std::string country, std::string email, std::string givenName,
177*f4682712SMarri Devender Rao     std::string initials, int64_t keyBitLength, std::string keyCurveId,
178*f4682712SMarri Devender Rao     std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
179*f4682712SMarri Devender Rao     std::string organization, std::string organizationalUnit, std::string state,
180*f4682712SMarri Devender Rao     std::string surname, std::string unstructuredName)
181*f4682712SMarri Devender Rao {
182*f4682712SMarri Devender Rao     int ret = 0;
183*f4682712SMarri Devender Rao 
184*f4682712SMarri Devender Rao     // set version of x509 req
185*f4682712SMarri Devender Rao     int nVersion = 1;
186*f4682712SMarri Devender Rao     // TODO: Issue#6 need to make version number configurable
187*f4682712SMarri Devender Rao     X509_REQ_Ptr x509Req(X509_REQ_new(), ::X509_REQ_free);
188*f4682712SMarri Devender Rao     ret = X509_REQ_set_version(x509Req.get(), nVersion);
189*f4682712SMarri Devender Rao     if (ret == 0)
190*f4682712SMarri Devender Rao     {
191*f4682712SMarri Devender Rao         log<level::ERR>("Error occured during X509_REQ_set_version call");
192*f4682712SMarri Devender Rao         elog<InternalFailure>();
193*f4682712SMarri Devender Rao     }
194*f4682712SMarri Devender Rao 
195*f4682712SMarri Devender Rao     // set subject of x509 req
196*f4682712SMarri Devender Rao     X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get());
197*f4682712SMarri Devender Rao 
198*f4682712SMarri Devender Rao     if (!alternativeNames.empty())
199*f4682712SMarri Devender Rao     {
200*f4682712SMarri Devender Rao         for (auto& name : alternativeNames)
201*f4682712SMarri Devender Rao         {
202*f4682712SMarri Devender Rao             addEntry(x509Name, "subjectAltName", name);
203*f4682712SMarri Devender Rao         }
204*f4682712SMarri Devender Rao     }
205*f4682712SMarri Devender Rao     addEntry(x509Name, "challengePassword", challengePassword);
206*f4682712SMarri Devender Rao     addEntry(x509Name, "L", city);
207*f4682712SMarri Devender Rao     addEntry(x509Name, "CN", commonName);
208*f4682712SMarri Devender Rao     addEntry(x509Name, "name", contactPerson);
209*f4682712SMarri Devender Rao     addEntry(x509Name, "C", country);
210*f4682712SMarri Devender Rao     addEntry(x509Name, "emailAddress", email);
211*f4682712SMarri Devender Rao     addEntry(x509Name, "GN", givenName);
212*f4682712SMarri Devender Rao     addEntry(x509Name, "initials", initials);
213*f4682712SMarri Devender Rao     addEntry(x509Name, "algorithm", keyPairAlgorithm);
214*f4682712SMarri Devender Rao     if (!keyUsage.empty())
215*f4682712SMarri Devender Rao     {
216*f4682712SMarri Devender Rao         for (auto& usage : keyUsage)
217*f4682712SMarri Devender Rao         {
218*f4682712SMarri Devender Rao             addEntry(x509Name, "keyUsage", usage);
219*f4682712SMarri Devender Rao         }
220*f4682712SMarri Devender Rao     }
221*f4682712SMarri Devender Rao     addEntry(x509Name, "O", organization);
222*f4682712SMarri Devender Rao     addEntry(x509Name, "ST", state);
223*f4682712SMarri Devender Rao     addEntry(x509Name, "SN", surname);
224*f4682712SMarri Devender Rao     addEntry(x509Name, "unstructuredName", unstructuredName);
225*f4682712SMarri Devender Rao 
226*f4682712SMarri Devender Rao     // Generate private key and write to file
227*f4682712SMarri Devender Rao     EVP_PKEY_Ptr pKey = writePrivateKey(keyBitLength, x509Req);
228*f4682712SMarri Devender Rao 
229*f4682712SMarri Devender Rao     // set sign key of x509 req
230*f4682712SMarri Devender Rao     ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256());
231*f4682712SMarri Devender Rao     if (ret <= 0)
232*f4682712SMarri Devender Rao     {
233*f4682712SMarri Devender Rao         log<level::ERR>("Error occured while signing key of x509");
234*f4682712SMarri Devender Rao         elog<InternalFailure>();
235*f4682712SMarri Devender Rao     }
236*f4682712SMarri Devender Rao     log<level::INFO>("Writing CSR to file");
237*f4682712SMarri Devender Rao     std::string path = fs::path(certInstallPath).parent_path();
238*f4682712SMarri Devender Rao     std::string csrFilePath = path + '/' + CSR_FILE_NAME;
239*f4682712SMarri Devender Rao     writeCSR(csrFilePath, x509Req);
240*f4682712SMarri Devender Rao }
241*f4682712SMarri Devender Rao 
242*f4682712SMarri Devender Rao EVP_PKEY_Ptr Manager::writePrivateKey(int64_t keyBitLength,
243*f4682712SMarri Devender Rao                                       X509_REQ_Ptr& x509Req)
244*f4682712SMarri Devender Rao {
245*f4682712SMarri Devender Rao     int ret = 0;
246*f4682712SMarri Devender Rao     // generate rsa key
247*f4682712SMarri Devender Rao     BIGNUM_Ptr bne(BN_new(), ::BN_free);
248*f4682712SMarri Devender Rao     ret = BN_set_word(bne.get(), RSA_F4);
249*f4682712SMarri Devender Rao     if (ret == 0)
250*f4682712SMarri Devender Rao     {
251*f4682712SMarri Devender Rao         log<level::ERR>("Error occured during BN_set_word call");
252*f4682712SMarri Devender Rao         elog<InternalFailure>();
253*f4682712SMarri Devender Rao     }
254*f4682712SMarri Devender Rao 
255*f4682712SMarri Devender Rao     // set keybit length to default value if not set
256*f4682712SMarri Devender Rao     if (keyBitLength <= 0)
257*f4682712SMarri Devender Rao     {
258*f4682712SMarri Devender Rao         keyBitLength = 2048;
259*f4682712SMarri Devender Rao     }
260*f4682712SMarri Devender Rao     RSA* rsa = RSA_new();
261*f4682712SMarri Devender Rao     ret = RSA_generate_key_ex(rsa, keyBitLength, bne.get(), NULL);
262*f4682712SMarri Devender Rao     if (ret != 1)
263*f4682712SMarri Devender Rao     {
264*f4682712SMarri Devender Rao         free(rsa);
265*f4682712SMarri Devender Rao         log<level::ERR>("Error occured during RSA_generate_key_ex call",
266*f4682712SMarri Devender Rao                         entry("KEYBITLENGTH=%PRIu64", keyBitLength));
267*f4682712SMarri Devender Rao         elog<InternalFailure>();
268*f4682712SMarri Devender Rao     }
269*f4682712SMarri Devender Rao 
270*f4682712SMarri Devender Rao     // set public key of x509 req
271*f4682712SMarri Devender Rao     EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free);
272*f4682712SMarri Devender Rao     EVP_PKEY_assign_RSA(pKey.get(), rsa);
273*f4682712SMarri Devender Rao     ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get());
274*f4682712SMarri Devender Rao     if (ret == 0)
275*f4682712SMarri Devender Rao     {
276*f4682712SMarri Devender Rao         log<level::ERR>("Error occured while setting Public key");
277*f4682712SMarri Devender Rao         elog<InternalFailure>();
278*f4682712SMarri Devender Rao     }
279*f4682712SMarri Devender Rao 
280*f4682712SMarri Devender Rao     log<level::ERR>("Writing private key to file");
281*f4682712SMarri Devender Rao     // write private key to file
282*f4682712SMarri Devender Rao     std::string path = fs::path(certInstallPath).parent_path();
283*f4682712SMarri Devender Rao     std::string privKeyPath = path + '/' + PRIV_KEY_FILE_NAME;
284*f4682712SMarri Devender Rao 
285*f4682712SMarri Devender Rao     FILE* fp = std::fopen(privKeyPath.c_str(), "w");
286*f4682712SMarri Devender Rao     if (fp == NULL)
287*f4682712SMarri Devender Rao     {
288*f4682712SMarri Devender Rao         ret = -1;
289*f4682712SMarri Devender Rao         log<level::ERR>("Error occured creating private key file");
290*f4682712SMarri Devender Rao         elog<InternalFailure>();
291*f4682712SMarri Devender Rao     }
292*f4682712SMarri Devender Rao     ret = PEM_write_PrivateKey(fp, pKey.get(), NULL, NULL, 0, 0, NULL);
293*f4682712SMarri Devender Rao     std::fclose(fp);
294*f4682712SMarri Devender Rao     if (ret == 0)
295*f4682712SMarri Devender Rao     {
296*f4682712SMarri Devender Rao         log<level::ERR>("Error occured while writing private key to file");
297*f4682712SMarri Devender Rao         elog<InternalFailure>();
298*f4682712SMarri Devender Rao     }
299*f4682712SMarri Devender Rao     return pKey;
300*f4682712SMarri Devender Rao }
301*f4682712SMarri Devender Rao 
302*f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field,
303*f4682712SMarri Devender Rao                        const std::string& bytes)
304*f4682712SMarri Devender Rao {
305*f4682712SMarri Devender Rao     if (bytes.empty())
306*f4682712SMarri Devender Rao     {
307*f4682712SMarri Devender Rao         return;
308*f4682712SMarri Devender Rao     }
309*f4682712SMarri Devender Rao     int ret = X509_NAME_add_entry_by_txt(
310*f4682712SMarri Devender Rao         x509Name, field, MBSTRING_ASC,
311*f4682712SMarri Devender Rao         reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0);
312*f4682712SMarri Devender Rao     if (ret != 1)
313*f4682712SMarri Devender Rao     {
314*f4682712SMarri Devender Rao         log<level::ERR>("Unable to set entry", entry("FIELD=%s", field),
315*f4682712SMarri Devender Rao                         entry("VALUE=%s", bytes.c_str()));
316*f4682712SMarri Devender Rao         elog<InternalFailure>();
317*f4682712SMarri Devender Rao     }
318*f4682712SMarri Devender Rao }
319*f4682712SMarri Devender Rao 
320*f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status)
321*f4682712SMarri Devender Rao {
322*f4682712SMarri Devender Rao     if (csrPtr)
323*f4682712SMarri Devender Rao     {
324*f4682712SMarri Devender Rao         csrPtr.reset(nullptr);
325*f4682712SMarri Devender Rao     }
326*f4682712SMarri Devender Rao     auto csrObjectPath = objectPath + '/' + "csr";
327*f4682712SMarri Devender Rao     csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(),
328*f4682712SMarri Devender Rao                                    certInstallPath.c_str(), status);
329*f4682712SMarri Devender Rao }
330*f4682712SMarri Devender Rao 
331*f4682712SMarri Devender Rao void Manager::writeCSR(const std::string& filePath, const X509_REQ_Ptr& x509Req)
332*f4682712SMarri Devender Rao {
333*f4682712SMarri Devender Rao     if (fs::exists(filePath))
334*f4682712SMarri Devender Rao     {
335*f4682712SMarri Devender Rao         log<level::INFO>("Removing the existing file",
336*f4682712SMarri Devender Rao                          entry("FILENAME=%s", filePath.c_str()));
337*f4682712SMarri Devender Rao         if (!fs::remove(filePath.c_str()))
338*f4682712SMarri Devender Rao         {
339*f4682712SMarri Devender Rao             log<level::ERR>("Unable to remove the file",
340*f4682712SMarri Devender Rao                             entry("FILENAME=%s", filePath.c_str()));
341*f4682712SMarri Devender Rao             elog<InternalFailure>();
342*f4682712SMarri Devender Rao         }
343*f4682712SMarri Devender Rao     }
344*f4682712SMarri Devender Rao 
345*f4682712SMarri Devender Rao     FILE* fp = NULL;
346*f4682712SMarri Devender Rao 
347*f4682712SMarri Devender Rao     if ((fp = std::fopen(filePath.c_str(), "w")) == NULL)
348*f4682712SMarri Devender Rao     {
349*f4682712SMarri Devender Rao         log<level::ERR>("Error opening the file to write the CSR",
350*f4682712SMarri Devender Rao                         entry("FILENAME=%s", filePath.c_str()));
351*f4682712SMarri Devender Rao         elog<InternalFailure>();
352*f4682712SMarri Devender Rao     }
353*f4682712SMarri Devender Rao 
354*f4682712SMarri Devender Rao     int rc = PEM_write_X509_REQ(fp, x509Req.get());
355*f4682712SMarri Devender Rao     if (!rc)
356*f4682712SMarri Devender Rao     {
357*f4682712SMarri Devender Rao         log<level::ERR>("PEM write routine failed",
358*f4682712SMarri Devender Rao                         entry("FILENAME=%s", filePath.c_str()));
359*f4682712SMarri Devender Rao         std::fclose(fp);
360*f4682712SMarri Devender Rao         elog<InternalFailure>();
361*f4682712SMarri Devender Rao     }
362*f4682712SMarri Devender Rao     std::fclose(fp);
363*f4682712SMarri Devender Rao }
364*f4682712SMarri Devender Rao 
365cfbc8dc8SJayanth Othayoth } // namespace certs
366cfbc8dc8SJayanth Othayoth } // namespace phosphor
367