blob: d2d9342d7de5383d8170098d9ee3386a9b7db545 [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{
Marri Devender Raob57d75e2019-07-25 04:56:21 -050035 // create parent certificate path if not existing
36 try
37 {
38 if (!fs::exists(certParentInstallPath))
39 {
40 fs::create_directories(certParentInstallPath);
41 }
42 }
43 catch (fs::filesystem_error& e)
44 {
45 log<level::ERR>("Failed to create directory", entry("ERR=%s", e.what()),
46 entry("DIRECTORY=%s", certParentInstallPath.c_str()));
47 report<InternalFailure>();
48 }
49
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -050050 // Generating RSA private key file if certificate type is server/client
51 if (certType != AUTHORITY)
52 {
53 createRSAPrivateKeyFile();
54 }
55
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050056 // restore any existing certificates
Marri Devender Raobf7c5882019-02-27 08:41:07 -060057 if (fs::exists(certInstallPath))
58 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -050059 createCertificate();
60 }
61
62 // watch is not required for authority certificates
63 if (certType != AUTHORITY)
64 {
65 // watch for certificate file create/replace
66 certWatchPtr = std::make_unique<
67 Watch>(event, certInstallPath, [this]() {
68 try
69 {
70 // if certificate file existing update it
71 if (certificatePtr != nullptr)
72 {
73 log<level::INFO>(
74 "Inotify callback to update certificate properties");
75 certificatePtr->populateProperties();
76 }
77 else
78 {
79 log<level::INFO>(
80 "Inotify callback to create certificate object");
81 createCertificate();
82 }
83 }
84 catch (const InternalFailure& e)
85 {
86 commit<InternalFailure>();
87 }
88 catch (const InvalidCertificate& e)
89 {
90 commit<InvalidCertificate>();
91 }
92 });
Marri Devender Raobf7c5882019-02-27 08:41:07 -060093 }
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050094}
95
Zbigniew Kurzynski06a69d72019-09-27 10:57:38 +020096std::string Manager::install(const std::string filePath)
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050097{
Marri Devender Rao13965112019-02-27 08:47:12 -060098 using NotAllowed =
99 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
100 using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
101 // TODO: Issue#3 At present supporting only one certificate to be
102 // uploaded this need to be revisited to support multiple
103 // certificates
104 if (certificatePtr != nullptr)
105 {
106 elog<NotAllowed>(Reason("Certificate already exist"));
107 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500108
Marri Devender Rao13965112019-02-27 08:47:12 -0600109 auto certObjectPath = objectPath + '/' + '1';
Marri Devender Rao8f80c352019-05-13 00:53:01 -0500110 certificatePtr = std::make_unique<Certificate>(
111 bus, certObjectPath, certType, unitToRestart, certInstallPath, filePath,
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500112 false, certWatchPtr);
Zbigniew Kurzynski06a69d72019-09-27 10:57:38 +0200113 return certObjectPath;
Jayanth Othayoth589159f2018-09-28 08:32:39 -0500114}
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500115
116void Manager::delete_()
117{
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600118 // TODO: #Issue 4 when a certificate is deleted system auto generates
119 // certificate file. At present we are not supporting creation of
120 // certificate object for the auto-generated certificate file as
121 // deletion if only applicable for REST server and Bmcweb does not allow
122 // deletion of certificates
123 if (certificatePtr != nullptr)
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500124 {
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600125 certificatePtr.reset(nullptr);
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500126 }
127}
Marri Devender Raof4682712019-03-19 05:00:28 -0500128
129std::string Manager::generateCSR(
130 std::vector<std::string> alternativeNames, std::string challengePassword,
131 std::string city, std::string commonName, std::string contactPerson,
132 std::string country, std::string email, std::string givenName,
133 std::string initials, int64_t keyBitLength, std::string keyCurveId,
134 std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
135 std::string organization, std::string organizationalUnit, std::string state,
136 std::string surname, std::string unstructuredName)
137{
138 // We support only one CSR.
139 csrPtr.reset(nullptr);
140 auto pid = fork();
141 if (pid == -1)
142 {
143 log<level::ERR>("Error occurred during forking process");
144 report<InternalFailure>();
145 }
146 else if (pid == 0)
147 {
148 try
149 {
150 generateCSRHelper(alternativeNames, challengePassword, city,
151 commonName, contactPerson, country, email,
152 givenName, initials, keyBitLength, keyCurveId,
153 keyPairAlgorithm, keyUsage, organization,
154 organizationalUnit, state, surname,
155 unstructuredName);
156 exit(EXIT_SUCCESS);
157 }
158 catch (const InternalFailure& e)
159 {
160 // commit the error reported in child process and exit
161 // Callback method from SDEvent Loop looks for exit status
162 exit(EXIT_FAILURE);
163 commit<InternalFailure>();
164 }
165 }
166 else
167 {
168 using namespace sdeventplus::source;
169 Child::Callback callback = [this](Child& eventSource,
170 const siginfo_t* si) {
171 eventSource.set_enabled(Enabled::On);
172 if (si->si_status != 0)
173 {
174 this->createCSRObject(Status::FAILURE);
175 }
176 else
177 {
178 this->createCSRObject(Status::SUCCESS);
179 }
180 };
181 try
182 {
183 sigset_t ss;
184 if (sigemptyset(&ss) < 0)
185 {
186 log<level::ERR>("Unable to initialize signal set");
187 elog<InternalFailure>();
188 }
189 if (sigaddset(&ss, SIGCHLD) < 0)
190 {
191 log<level::ERR>("Unable to add signal to signal set");
192 elog<InternalFailure>();
193 }
194
195 // Block SIGCHLD first, so that the event loop can handle it
196 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0)
197 {
198 log<level::ERR>("Unable to block signal");
199 elog<InternalFailure>();
200 }
201 if (childPtr)
202 {
203 childPtr.reset();
204 }
205 childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED,
206 std::move(callback));
207 }
208 catch (const InternalFailure& e)
209 {
210 commit<InternalFailure>();
211 }
212 }
213 auto csrObjectPath = objectPath + '/' + "csr";
214 return csrObjectPath;
215}
216
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500217CertificatePtr& Manager::getCertificate()
218{
219 return certificatePtr;
220}
221
Marri Devender Raof4682712019-03-19 05:00:28 -0500222void Manager::generateCSRHelper(
223 std::vector<std::string> alternativeNames, std::string challengePassword,
224 std::string city, std::string commonName, std::string contactPerson,
225 std::string country, std::string email, std::string givenName,
226 std::string initials, int64_t keyBitLength, std::string keyCurveId,
227 std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
228 std::string organization, std::string organizationalUnit, std::string state,
229 std::string surname, std::string unstructuredName)
230{
231 int ret = 0;
232
233 // set version of x509 req
234 int nVersion = 1;
235 // TODO: Issue#6 need to make version number configurable
236 X509_REQ_Ptr x509Req(X509_REQ_new(), ::X509_REQ_free);
237 ret = X509_REQ_set_version(x509Req.get(), nVersion);
238 if (ret == 0)
239 {
240 log<level::ERR>("Error occured during X509_REQ_set_version call");
241 elog<InternalFailure>();
242 }
243
244 // set subject of x509 req
245 X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get());
246
247 if (!alternativeNames.empty())
248 {
249 for (auto& name : alternativeNames)
250 {
251 addEntry(x509Name, "subjectAltName", name);
252 }
253 }
254 addEntry(x509Name, "challengePassword", challengePassword);
255 addEntry(x509Name, "L", city);
256 addEntry(x509Name, "CN", commonName);
257 addEntry(x509Name, "name", contactPerson);
258 addEntry(x509Name, "C", country);
259 addEntry(x509Name, "emailAddress", email);
260 addEntry(x509Name, "GN", givenName);
261 addEntry(x509Name, "initials", initials);
262 addEntry(x509Name, "algorithm", keyPairAlgorithm);
263 if (!keyUsage.empty())
264 {
265 for (auto& usage : keyUsage)
266 {
Marri Devender Rao76411052019-08-07 01:25:07 -0500267 if (isExtendedKeyUsage(usage))
268 {
269 addEntry(x509Name, "extendedKeyUsage", usage);
270 }
271 else
272 {
273 addEntry(x509Name, "keyUsage", usage);
274 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500275 }
276 }
277 addEntry(x509Name, "O", organization);
278 addEntry(x509Name, "ST", state);
279 addEntry(x509Name, "SN", surname);
280 addEntry(x509Name, "unstructuredName", unstructuredName);
281
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500282 EVP_PKEY_Ptr pKey(nullptr, ::EVP_PKEY_free);
283
284 log<level::INFO>("Given Key pair algorithm",
285 entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str()));
286
287 // Used EC algorithm as default if user did not give algorithm type.
288 if (keyPairAlgorithm == "RSA")
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500289 pKey = getRSAKeyPair(keyBitLength);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500290 else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty()))
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500291 pKey = generateECKeyPair(keyCurveId);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500292 else
293 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500294 log<level::ERR>("Given Key pair algorithm is not supported. Supporting "
295 "RSA and EC only");
296 elog<InvalidArgument>(
297 Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"),
298 Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str()));
299 }
300
301 ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get());
302 if (ret == 0)
303 {
304 log<level::ERR>("Error occured while setting Public key");
305 elog<InternalFailure>();
306 }
307
308 // Write private key to file
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500309 writePrivateKey(pKey, PRIV_KEY_FILE_NAME);
Marri Devender Raof4682712019-03-19 05:00:28 -0500310
311 // set sign key of x509 req
312 ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256());
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500313 if (ret == 0)
Marri Devender Raof4682712019-03-19 05:00:28 -0500314 {
315 log<level::ERR>("Error occured while signing key of x509");
316 elog<InternalFailure>();
317 }
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500318
Marri Devender Raof4682712019-03-19 05:00:28 -0500319 log<level::INFO>("Writing CSR to file");
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500320 fs::path csrFilePath = certParentInstallPath / CSR_FILE_NAME;
321 writeCSR(csrFilePath.string(), x509Req);
Marri Devender Raof4682712019-03-19 05:00:28 -0500322}
323
Marri Devender Rao76411052019-08-07 01:25:07 -0500324bool Manager::isExtendedKeyUsage(const std::string& usage)
325{
326 const static std::array<const char*, 6> usageList = {
327 "ServerAuthentication", "ClientAuthentication", "OCSPSigning",
328 "Timestamping", "CodeSigning", "EmailProtection"};
329 auto it = std::find_if(
330 usageList.begin(), usageList.end(),
331 [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); });
332 return it != usageList.end();
333}
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500334EVP_PKEY_Ptr Manager::generateRSAKeyPair(const int64_t keyBitLength)
Marri Devender Raof4682712019-03-19 05:00:28 -0500335{
336 int ret = 0;
337 // generate rsa key
338 BIGNUM_Ptr bne(BN_new(), ::BN_free);
339 ret = BN_set_word(bne.get(), RSA_F4);
340 if (ret == 0)
341 {
342 log<level::ERR>("Error occured during BN_set_word call");
343 elog<InternalFailure>();
344 }
345
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500346 int64_t keyBitLen = keyBitLength;
Marri Devender Raof4682712019-03-19 05:00:28 -0500347 // set keybit length to default value if not set
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500348 if (keyBitLen <= 0)
Marri Devender Raof4682712019-03-19 05:00:28 -0500349 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500350 constexpr auto DEFAULT_KEYBITLENGTH = 2048;
351 log<level::INFO>(
352 "KeyBitLength is not given.Hence, using default KeyBitLength",
353 entry("DEFAULTKEYBITLENGTH=%d", DEFAULT_KEYBITLENGTH));
354 keyBitLen = DEFAULT_KEYBITLENGTH;
Marri Devender Raof4682712019-03-19 05:00:28 -0500355 }
356 RSA* rsa = RSA_new();
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500357 ret = RSA_generate_key_ex(rsa, keyBitLen, bne.get(), NULL);
Marri Devender Raof4682712019-03-19 05:00:28 -0500358 if (ret != 1)
359 {
360 free(rsa);
361 log<level::ERR>("Error occured during RSA_generate_key_ex call",
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500362 entry("KEYBITLENGTH=%PRIu64", keyBitLen));
Marri Devender Raof4682712019-03-19 05:00:28 -0500363 elog<InternalFailure>();
364 }
365
366 // set public key of x509 req
367 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500368 ret = EVP_PKEY_assign_RSA(pKey.get(), rsa);
Marri Devender Raof4682712019-03-19 05:00:28 -0500369 if (ret == 0)
370 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500371 free(rsa);
372 log<level::ERR>("Error occured during assign rsa key into EVP");
Marri Devender Raof4682712019-03-19 05:00:28 -0500373 elog<InternalFailure>();
374 }
375
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500376 return pKey;
377}
378
379EVP_PKEY_Ptr Manager::generateECKeyPair(const std::string& curveId)
380{
381 std::string curId(curveId);
382
383 if (curId.empty())
384 {
385 // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349
386 constexpr auto DEFAULT_KEYCURVEID = "secp224r1";
387 log<level::INFO>(
388 "KeyCurveId is not given. Hence using default curve id",
389 entry("DEFAULTKEYCURVEID=%s", DEFAULT_KEYCURVEID));
390 curId = DEFAULT_KEYCURVEID;
391 }
392
393 int ecGrp = OBJ_txt2nid(curId.c_str());
394
395 if (ecGrp == NID_undef)
396 {
397 log<level::ERR>(
398 "Error occured during convert the curve id string format into NID",
399 entry("KEYCURVEID=%s", curId.c_str()));
400 elog<InternalFailure>();
401 }
402
403 EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp);
404
405 if (ecKey == NULL)
406 {
407 log<level::ERR>(
408 "Error occured during create the EC_Key object from NID",
409 entry("ECGROUP=%d", ecGrp));
410 elog<InternalFailure>();
411 }
412
413 // If you want to save a key and later load it with
414 // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE
415 // flag on the key.
416 EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE);
417
418 int ret = EC_KEY_generate_key(ecKey);
419
420 if (ret == 0)
421 {
422 EC_KEY_free(ecKey);
423 log<level::ERR>("Error occured during generate EC key");
424 elog<InternalFailure>();
425 }
426
427 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free);
428 ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey);
429 if (ret == 0)
430 {
431 EC_KEY_free(ecKey);
432 log<level::ERR>("Error occured during assign EC Key into EVP");
433 elog<InternalFailure>();
434 }
435
436 return pKey;
437}
438
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500439void Manager::writePrivateKey(const EVP_PKEY_Ptr& pKey,
440 const std::string& privKeyFileName)
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500441{
442 log<level::INFO>("Writing private key to file");
Marri Devender Raof4682712019-03-19 05:00:28 -0500443 // write private key to file
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500444 fs::path privKeyPath = certParentInstallPath / privKeyFileName;
Marri Devender Raof4682712019-03-19 05:00:28 -0500445
446 FILE* fp = std::fopen(privKeyPath.c_str(), "w");
447 if (fp == NULL)
448 {
Marri Devender Raof4682712019-03-19 05:00:28 -0500449 log<level::ERR>("Error occured creating private key file");
450 elog<InternalFailure>();
451 }
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500452 int ret = PEM_write_PrivateKey(fp, pKey.get(), NULL, NULL, 0, 0, NULL);
Marri Devender Raof4682712019-03-19 05:00:28 -0500453 std::fclose(fp);
454 if (ret == 0)
455 {
456 log<level::ERR>("Error occured while writing private key to file");
457 elog<InternalFailure>();
458 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500459}
460
461void Manager::addEntry(X509_NAME* x509Name, const char* field,
462 const std::string& bytes)
463{
464 if (bytes.empty())
465 {
466 return;
467 }
468 int ret = X509_NAME_add_entry_by_txt(
469 x509Name, field, MBSTRING_ASC,
470 reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0);
471 if (ret != 1)
472 {
473 log<level::ERR>("Unable to set entry", entry("FIELD=%s", field),
474 entry("VALUE=%s", bytes.c_str()));
475 elog<InternalFailure>();
476 }
477}
478
479void Manager::createCSRObject(const Status& status)
480{
481 if (csrPtr)
482 {
483 csrPtr.reset(nullptr);
484 }
485 auto csrObjectPath = objectPath + '/' + "csr";
486 csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(),
487 certInstallPath.c_str(), status);
488}
489
490void Manager::writeCSR(const std::string& filePath, const X509_REQ_Ptr& x509Req)
491{
492 if (fs::exists(filePath))
493 {
494 log<level::INFO>("Removing the existing file",
495 entry("FILENAME=%s", filePath.c_str()));
496 if (!fs::remove(filePath.c_str()))
497 {
498 log<level::ERR>("Unable to remove the file",
499 entry("FILENAME=%s", filePath.c_str()));
500 elog<InternalFailure>();
501 }
502 }
503
504 FILE* fp = NULL;
505
506 if ((fp = std::fopen(filePath.c_str(), "w")) == NULL)
507 {
508 log<level::ERR>("Error opening the file to write the CSR",
509 entry("FILENAME=%s", filePath.c_str()));
510 elog<InternalFailure>();
511 }
512
513 int rc = PEM_write_X509_REQ(fp, x509Req.get());
514 if (!rc)
515 {
516 log<level::ERR>("PEM write routine failed",
517 entry("FILENAME=%s", filePath.c_str()));
518 std::fclose(fp);
519 elog<InternalFailure>();
520 }
521 std::fclose(fp);
522}
523
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500524void Manager::createCertificate()
525{
526 try
527 {
528 // TODO: Issue#3 At present supporting only one certificate to be
529 // uploaded this need to be revisited to support multiple
530 // certificates
531 auto certObjectPath = objectPath + '/' + '1';
532 certificatePtr = std::make_unique<Certificate>(
533 bus, certObjectPath, certType, unitToRestart, certInstallPath,
534 certInstallPath, true, certWatchPtr);
535 }
536 catch (const InternalFailure& e)
537 {
538 report<InternalFailure>();
539 }
540 catch (const InvalidCertificate& e)
541 {
542 report<InvalidCertificate>(
543 Reason("Existing certificate file is corrupted"));
544 }
545}
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500546
547void Manager::createRSAPrivateKeyFile()
548{
549 fs::path rsaPrivateKeyFileName =
550 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME;
551
552 try
553 {
554 if (!fs::exists(rsaPrivateKeyFileName))
555 {
556 writePrivateKey(generateRSAKeyPair(SUPPORTED_KEYBITLENGTH),
557 RSA_PRIV_KEY_FILE_NAME);
558 }
559 }
560 catch (const InternalFailure& e)
561 {
562 report<InternalFailure>();
563 }
564}
565
566EVP_PKEY_Ptr Manager::getRSAKeyPair(const int64_t keyBitLength)
567{
568 if (keyBitLength != SUPPORTED_KEYBITLENGTH)
569 {
570 log<level::ERR>(
571 "Given Key bit length is not supported",
572 entry("GIVENKEYBITLENGTH=%d", keyBitLength),
573 entry("SUPPORTEDKEYBITLENGTH=%d", SUPPORTED_KEYBITLENGTH));
574 elog<InvalidArgument>(
575 Argument::ARGUMENT_NAME("KEYBITLENGTH"),
576 Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str()));
577 }
578 fs::path rsaPrivateKeyFileName =
579 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME;
580
581 FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r");
582 if (!privateKeyFile)
583 {
584 log<level::ERR>("Unable to open RSA private key file to read",
585 entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()),
586 entry("ERRORREASON=%s", strerror(errno)));
587 elog<InternalFailure>();
588 }
589
590 EVP_PKEY_Ptr privateKey(
591 PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr),
592 ::EVP_PKEY_free);
593 std::fclose(privateKeyFile);
594
595 if (!privateKey)
596 {
597 log<level::ERR>("Error occured during PEM_read_PrivateKey call");
598 elog<InternalFailure>();
599 }
600 return privateKey;
601}
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500602} // namespace certs
603} // namespace phosphor