blob: 06ddf68b9b6a8c1aa791ca7c92bb1c3f0cef80b3 [file] [log] [blame]
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -05001#include "certs_manager.hpp"
2
Marri Devender Raof4682712019-03-19 05:00:28 -05003#include <openssl/pem.h>
4#include <unistd.h>
5
Marri Devender Rao6ceec402019-02-01 03:15:19 -06006#include <phosphor-logging/elog-errors.hpp>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -05007#include <xyz/openbmc_project/Certs/error.hpp>
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -05008#include <xyz/openbmc_project/Common/error.hpp>
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -05009namespace phosphor
10{
11namespace certs
12{
Marri Devender Rao13965112019-02-27 08:47:12 -060013using InternalFailure =
14 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050015using InvalidCertificate =
16 sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
17using Reason = xyz::openbmc_project::Certs::InvalidCertificate::REASON;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050018
Marri Devender Raof4682712019-03-19 05:00:28 -050019using X509_REQ_Ptr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>;
20using BIGNUM_Ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -050021using InvalidArgument =
22 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
23using Argument = xyz::openbmc_project::Common::InvalidArgument;
24
25constexpr auto SUPPORTED_KEYBITLENGTH = 2048;
Marri Devender Raof4682712019-03-19 05:00:28 -050026
27Manager::Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event,
28 const char* path, const CertificateType& type,
29 UnitsToRestart&& unit, CertInstallPath&& installPath) :
Marri Devender Rao6ceec402019-02-01 03:15:19 -060030 Ifaces(bus, path),
Marri Devender Raof4682712019-03-19 05:00:28 -050031 bus(bus), event(event), objectPath(path), certType(type),
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -050032 unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)),
33 certParentInstallPath(fs::path(certInstallPath).parent_path())
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050034{
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -050035 // Generating RSA private key file if certificate type is server/client
36 if (certType != AUTHORITY)
37 {
38 createRSAPrivateKeyFile();
39 }
40
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050041 // restore any existing certificates
Marri Devender Raobf7c5882019-02-27 08:41:07 -060042 if (fs::exists(certInstallPath))
43 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050044 createCertificate();
45 }
46
47 // watch is not required for authority certificates
48 if (certType != AUTHORITY)
49 {
50 // watch for certificate file create/replace
51 certWatchPtr = std::make_unique<
52 Watch>(event, certInstallPath, [this]() {
53 try
54 {
55 // if certificate file existing update it
56 if (certificatePtr != nullptr)
57 {
58 log<level::INFO>(
59 "Inotify callback to update certificate properties");
60 certificatePtr->populateProperties();
61 }
62 else
63 {
64 log<level::INFO>(
65 "Inotify callback to create certificate object");
66 createCertificate();
67 }
68 }
69 catch (const InternalFailure& e)
70 {
71 commit<InternalFailure>();
72 }
73 catch (const InvalidCertificate& e)
74 {
75 commit<InvalidCertificate>();
76 }
77 });
Marri Devender Raobf7c5882019-02-27 08:41:07 -060078 }
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050079}
80
Marri Devender Rao6ceec402019-02-01 03:15:19 -060081void Manager::install(const std::string filePath)
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050082{
Marri Devender Rao13965112019-02-27 08:47:12 -060083 using NotAllowed =
84 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
85 using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
86 // TODO: Issue#3 At present supporting only one certificate to be
87 // uploaded this need to be revisited to support multiple
88 // certificates
89 if (certificatePtr != nullptr)
90 {
91 elog<NotAllowed>(Reason("Certificate already exist"));
92 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050093
Marri Devender Rao13965112019-02-27 08:47:12 -060094 auto certObjectPath = objectPath + '/' + '1';
Marri Devender Rao8f80c352019-05-13 00:53:01 -050095 certificatePtr = std::make_unique<Certificate>(
96 bus, certObjectPath, certType, unitToRestart, certInstallPath, filePath,
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050097 false, certWatchPtr);
Jayanth Othayoth589159f2018-09-28 08:32:39 -050098}
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -050099
100void Manager::delete_()
101{
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600102 // TODO: #Issue 4 when a certificate is deleted system auto generates
103 // certificate file. At present we are not supporting creation of
104 // certificate object for the auto-generated certificate file as
105 // deletion if only applicable for REST server and Bmcweb does not allow
106 // deletion of certificates
107 if (certificatePtr != nullptr)
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500108 {
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600109 certificatePtr.reset(nullptr);
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500110 }
111}
Marri Devender Raof4682712019-03-19 05:00:28 -0500112
113std::string Manager::generateCSR(
114 std::vector<std::string> alternativeNames, std::string challengePassword,
115 std::string city, std::string commonName, std::string contactPerson,
116 std::string country, std::string email, std::string givenName,
117 std::string initials, int64_t keyBitLength, std::string keyCurveId,
118 std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
119 std::string organization, std::string organizationalUnit, std::string state,
120 std::string surname, std::string unstructuredName)
121{
122 // We support only one CSR.
123 csrPtr.reset(nullptr);
124 auto pid = fork();
125 if (pid == -1)
126 {
127 log<level::ERR>("Error occurred during forking process");
128 report<InternalFailure>();
129 }
130 else if (pid == 0)
131 {
132 try
133 {
134 generateCSRHelper(alternativeNames, challengePassword, city,
135 commonName, contactPerson, country, email,
136 givenName, initials, keyBitLength, keyCurveId,
137 keyPairAlgorithm, keyUsage, organization,
138 organizationalUnit, state, surname,
139 unstructuredName);
140 exit(EXIT_SUCCESS);
141 }
142 catch (const InternalFailure& e)
143 {
144 // commit the error reported in child process and exit
145 // Callback method from SDEvent Loop looks for exit status
146 exit(EXIT_FAILURE);
147 commit<InternalFailure>();
148 }
149 }
150 else
151 {
152 using namespace sdeventplus::source;
153 Child::Callback callback = [this](Child& eventSource,
154 const siginfo_t* si) {
155 eventSource.set_enabled(Enabled::On);
156 if (si->si_status != 0)
157 {
158 this->createCSRObject(Status::FAILURE);
159 }
160 else
161 {
162 this->createCSRObject(Status::SUCCESS);
163 }
164 };
165 try
166 {
167 sigset_t ss;
168 if (sigemptyset(&ss) < 0)
169 {
170 log<level::ERR>("Unable to initialize signal set");
171 elog<InternalFailure>();
172 }
173 if (sigaddset(&ss, SIGCHLD) < 0)
174 {
175 log<level::ERR>("Unable to add signal to signal set");
176 elog<InternalFailure>();
177 }
178
179 // Block SIGCHLD first, so that the event loop can handle it
180 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
181 {
182 log<level::ERR>("Unable to block signal");
183 elog<InternalFailure>();
184 }
185 if (childPtr)
186 {
187 childPtr.reset();
188 }
189 childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED,
190 std::move(callback));
191 }
192 catch (const InternalFailure& e)
193 {
194 commit<InternalFailure>();
195 }
196 }
197 auto csrObjectPath = objectPath + '/' + "csr";
198 return csrObjectPath;
199}
200
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500201CertificatePtr& Manager::getCertificate()
202{
203 return certificatePtr;
204}
205
Marri Devender Raof4682712019-03-19 05:00:28 -0500206void Manager::generateCSRHelper(
207 std::vector<std::string> alternativeNames, std::string challengePassword,
208 std::string city, std::string commonName, std::string contactPerson,
209 std::string country, std::string email, std::string givenName,
210 std::string initials, int64_t keyBitLength, std::string keyCurveId,
211 std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
212 std::string organization, std::string organizationalUnit, std::string state,
213 std::string surname, std::string unstructuredName)
214{
215 int ret = 0;
216
217 // set version of x509 req
218 int nVersion = 1;
219 // TODO: Issue#6 need to make version number configurable
220 X509_REQ_Ptr x509Req(X509_REQ_new(), ::X509_REQ_free);
221 ret = X509_REQ_set_version(x509Req.get(), nVersion);
222 if (ret == 0)
223 {
224 log<level::ERR>("Error occured during X509_REQ_set_version call");
225 elog<InternalFailure>();
226 }
227
228 // set subject of x509 req
229 X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get());
230
231 if (!alternativeNames.empty())
232 {
233 for (auto& name : alternativeNames)
234 {
235 addEntry(x509Name, "subjectAltName", name);
236 }
237 }
238 addEntry(x509Name, "challengePassword", challengePassword);
239 addEntry(x509Name, "L", city);
240 addEntry(x509Name, "CN", commonName);
241 addEntry(x509Name, "name", contactPerson);
242 addEntry(x509Name, "C", country);
243 addEntry(x509Name, "emailAddress", email);
244 addEntry(x509Name, "GN", givenName);
245 addEntry(x509Name, "initials", initials);
246 addEntry(x509Name, "algorithm", keyPairAlgorithm);
247 if (!keyUsage.empty())
248 {
249 for (auto& usage : keyUsage)
250 {
251 addEntry(x509Name, "keyUsage", usage);
252 }
253 }
254 addEntry(x509Name, "O", organization);
255 addEntry(x509Name, "ST", state);
256 addEntry(x509Name, "SN", surname);
257 addEntry(x509Name, "unstructuredName", unstructuredName);
258
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500259 EVP_PKEY_Ptr pKey(nullptr, ::EVP_PKEY_free);
260
261 log<level::INFO>("Given Key pair algorithm",
262 entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str()));
263
264 // Used EC algorithm as default if user did not give algorithm type.
265 if (keyPairAlgorithm == "RSA")
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500266 pKey = getRSAKeyPair(keyBitLength);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500267 else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty()))
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500268 pKey = generateECKeyPair(keyCurveId);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500269 else
270 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500271 log<level::ERR>("Given Key pair algorithm is not supported. Supporting "
272 "RSA and EC only");
273 elog<InvalidArgument>(
274 Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"),
275 Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str()));
276 }
277
278 ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get());
279 if (ret == 0)
280 {
281 log<level::ERR>("Error occured while setting Public key");
282 elog<InternalFailure>();
283 }
284
285 // Write private key to file
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500286 writePrivateKey(pKey, PRIV_KEY_FILE_NAME);
Marri Devender Raof4682712019-03-19 05:00:28 -0500287
288 // set sign key of x509 req
289 ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256());
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500290 if (ret == 0)
Marri Devender Raof4682712019-03-19 05:00:28 -0500291 {
292 log<level::ERR>("Error occured while signing key of x509");
293 elog<InternalFailure>();
294 }
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500295
Marri Devender Raof4682712019-03-19 05:00:28 -0500296 log<level::INFO>("Writing CSR to file");
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500297 fs::path csrFilePath = certParentInstallPath / CSR_FILE_NAME;
298 writeCSR(csrFilePath.string(), x509Req);
Marri Devender Raof4682712019-03-19 05:00:28 -0500299}
300
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500301EVP_PKEY_Ptr Manager::generateRSAKeyPair(const int64_t keyBitLength)
Marri Devender Raof4682712019-03-19 05:00:28 -0500302{
303 int ret = 0;
304 // generate rsa key
305 BIGNUM_Ptr bne(BN_new(), ::BN_free);
306 ret = BN_set_word(bne.get(), RSA_F4);
307 if (ret == 0)
308 {
309 log<level::ERR>("Error occured during BN_set_word call");
310 elog<InternalFailure>();
311 }
312
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500313 int64_t keyBitLen = keyBitLength;
Marri Devender Raof4682712019-03-19 05:00:28 -0500314 // set keybit length to default value if not set
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500315 if (keyBitLen <= 0)
Marri Devender Raof4682712019-03-19 05:00:28 -0500316 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500317 constexpr auto DEFAULT_KEYBITLENGTH = 2048;
318 log<level::INFO>(
319 "KeyBitLength is not given.Hence, using default KeyBitLength",
320 entry("DEFAULTKEYBITLENGTH=%d", DEFAULT_KEYBITLENGTH));
321 keyBitLen = DEFAULT_KEYBITLENGTH;
Marri Devender Raof4682712019-03-19 05:00:28 -0500322 }
323 RSA* rsa = RSA_new();
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500324 ret = RSA_generate_key_ex(rsa, keyBitLen, bne.get(), NULL);
Marri Devender Raof4682712019-03-19 05:00:28 -0500325 if (ret != 1)
326 {
327 free(rsa);
328 log<level::ERR>("Error occured during RSA_generate_key_ex call",
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500329 entry("KEYBITLENGTH=%PRIu64", keyBitLen));
Marri Devender Raof4682712019-03-19 05:00:28 -0500330 elog<InternalFailure>();
331 }
332
333 // set public key of x509 req
334 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500335 ret = EVP_PKEY_assign_RSA(pKey.get(), rsa);
Marri Devender Raof4682712019-03-19 05:00:28 -0500336 if (ret == 0)
337 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500338 free(rsa);
339 log<level::ERR>("Error occured during assign rsa key into EVP");
Marri Devender Raof4682712019-03-19 05:00:28 -0500340 elog<InternalFailure>();
341 }
342
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500343 return pKey;
344}
345
346EVP_PKEY_Ptr Manager::generateECKeyPair(const std::string& curveId)
347{
348 std::string curId(curveId);
349
350 if (curId.empty())
351 {
352 // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349
353 constexpr auto DEFAULT_KEYCURVEID = "secp224r1";
354 log<level::INFO>(
355 "KeyCurveId is not given. Hence using default curve id",
356 entry("DEFAULTKEYCURVEID=%s", DEFAULT_KEYCURVEID));
357 curId = DEFAULT_KEYCURVEID;
358 }
359
360 int ecGrp = OBJ_txt2nid(curId.c_str());
361
362 if (ecGrp == NID_undef)
363 {
364 log<level::ERR>(
365 "Error occured during convert the curve id string format into NID",
366 entry("KEYCURVEID=%s", curId.c_str()));
367 elog<InternalFailure>();
368 }
369
370 EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp);
371
372 if (ecKey == NULL)
373 {
374 log<level::ERR>(
375 "Error occured during create the EC_Key object from NID",
376 entry("ECGROUP=%d", ecGrp));
377 elog<InternalFailure>();
378 }
379
380 // If you want to save a key and later load it with
381 // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE
382 // flag on the key.
383 EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE);
384
385 int ret = EC_KEY_generate_key(ecKey);
386
387 if (ret == 0)
388 {
389 EC_KEY_free(ecKey);
390 log<level::ERR>("Error occured during generate EC key");
391 elog<InternalFailure>();
392 }
393
394 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free);
395 ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey);
396 if (ret == 0)
397 {
398 EC_KEY_free(ecKey);
399 log<level::ERR>("Error occured during assign EC Key into EVP");
400 elog<InternalFailure>();
401 }
402
403 return pKey;
404}
405
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500406void Manager::writePrivateKey(const EVP_PKEY_Ptr& pKey,
407 const std::string& privKeyFileName)
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500408{
409 log<level::INFO>("Writing private key to file");
Marri Devender Raof4682712019-03-19 05:00:28 -0500410 // write private key to file
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500411 fs::path privKeyPath = certParentInstallPath / privKeyFileName;
Marri Devender Raof4682712019-03-19 05:00:28 -0500412
413 FILE* fp = std::fopen(privKeyPath.c_str(), "w");
414 if (fp == NULL)
415 {
Marri Devender Raof4682712019-03-19 05:00:28 -0500416 log<level::ERR>("Error occured creating private key file");
417 elog<InternalFailure>();
418 }
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500419 int ret = PEM_write_PrivateKey(fp, pKey.get(), NULL, NULL, 0, 0, NULL);
Marri Devender Raof4682712019-03-19 05:00:28 -0500420 std::fclose(fp);
421 if (ret == 0)
422 {
423 log<level::ERR>("Error occured while writing private key to file");
424 elog<InternalFailure>();
425 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500426}
427
428void Manager::addEntry(X509_NAME* x509Name, const char* field,
429 const std::string& bytes)
430{
431 if (bytes.empty())
432 {
433 return;
434 }
435 int ret = X509_NAME_add_entry_by_txt(
436 x509Name, field, MBSTRING_ASC,
437 reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0);
438 if (ret != 1)
439 {
440 log<level::ERR>("Unable to set entry", entry("FIELD=%s", field),
441 entry("VALUE=%s", bytes.c_str()));
442 elog<InternalFailure>();
443 }
444}
445
446void Manager::createCSRObject(const Status& status)
447{
448 if (csrPtr)
449 {
450 csrPtr.reset(nullptr);
451 }
452 auto csrObjectPath = objectPath + '/' + "csr";
453 csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(),
454 certInstallPath.c_str(), status);
455}
456
457void Manager::writeCSR(const std::string& filePath, const X509_REQ_Ptr& x509Req)
458{
459 if (fs::exists(filePath))
460 {
461 log<level::INFO>("Removing the existing file",
462 entry("FILENAME=%s", filePath.c_str()));
463 if (!fs::remove(filePath.c_str()))
464 {
465 log<level::ERR>("Unable to remove the file",
466 entry("FILENAME=%s", filePath.c_str()));
467 elog<InternalFailure>();
468 }
469 }
470
471 FILE* fp = NULL;
472
473 if ((fp = std::fopen(filePath.c_str(), "w")) == NULL)
474 {
475 log<level::ERR>("Error opening the file to write the CSR",
476 entry("FILENAME=%s", filePath.c_str()));
477 elog<InternalFailure>();
478 }
479
480 int rc = PEM_write_X509_REQ(fp, x509Req.get());
481 if (!rc)
482 {
483 log<level::ERR>("PEM write routine failed",
484 entry("FILENAME=%s", filePath.c_str()));
485 std::fclose(fp);
486 elog<InternalFailure>();
487 }
488 std::fclose(fp);
489}
490
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500491void Manager::createCertificate()
492{
493 try
494 {
495 // TODO: Issue#3 At present supporting only one certificate to be
496 // uploaded this need to be revisited to support multiple
497 // certificates
498 auto certObjectPath = objectPath + '/' + '1';
499 certificatePtr = std::make_unique<Certificate>(
500 bus, certObjectPath, certType, unitToRestart, certInstallPath,
501 certInstallPath, true, certWatchPtr);
502 }
503 catch (const InternalFailure& e)
504 {
505 report<InternalFailure>();
506 }
507 catch (const InvalidCertificate& e)
508 {
509 report<InvalidCertificate>(
510 Reason("Existing certificate file is corrupted"));
511 }
512}
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500513
514void Manager::createRSAPrivateKeyFile()
515{
516 fs::path rsaPrivateKeyFileName =
517 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME;
518
519 try
520 {
521 if (!fs::exists(rsaPrivateKeyFileName))
522 {
523 writePrivateKey(generateRSAKeyPair(SUPPORTED_KEYBITLENGTH),
524 RSA_PRIV_KEY_FILE_NAME);
525 }
526 }
527 catch (const InternalFailure& e)
528 {
529 report<InternalFailure>();
530 }
531}
532
533EVP_PKEY_Ptr Manager::getRSAKeyPair(const int64_t keyBitLength)
534{
535 if (keyBitLength != SUPPORTED_KEYBITLENGTH)
536 {
537 log<level::ERR>(
538 "Given Key bit length is not supported",
539 entry("GIVENKEYBITLENGTH=%d", keyBitLength),
540 entry("SUPPORTEDKEYBITLENGTH=%d", SUPPORTED_KEYBITLENGTH));
541 elog<InvalidArgument>(
542 Argument::ARGUMENT_NAME("KEYBITLENGTH"),
543 Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str()));
544 }
545 fs::path rsaPrivateKeyFileName =
546 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME;
547
548 FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r");
549 if (!privateKeyFile)
550 {
551 log<level::ERR>("Unable to open RSA private key file to read",
552 entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()),
553 entry("ERRORREASON=%s", strerror(errno)));
554 elog<InternalFailure>();
555 }
556
557 EVP_PKEY_Ptr privateKey(
558 PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr),
559 ::EVP_PKEY_free);
560 std::fclose(privateKeyFile);
561
562 if (!privateKey)
563 {
564 log<level::ERR>("Error occured during PEM_read_PrivateKey call");
565 elog<InternalFailure>();
566 }
567 return privateKey;
568}
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500569} // namespace certs
570} // namespace phosphor