1 #include "certs_manager.hpp" 2 3 #include <openssl/pem.h> 4 #include <unistd.h> 5 6 #include <algorithm> 7 #include <phosphor-logging/elog-errors.hpp> 8 #include <xyz/openbmc_project/Certs/error.hpp> 9 #include <xyz/openbmc_project/Common/error.hpp> 10 11 namespace phosphor 12 { 13 namespace certs 14 { 15 using InternalFailure = 16 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 17 using InvalidCertificate = 18 sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 19 using Reason = xyz::openbmc_project::Certs::InvalidCertificate::REASON; 20 21 using X509_REQ_Ptr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>; 22 using BIGNUM_Ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>; 23 using InvalidArgument = 24 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 25 using Argument = xyz::openbmc_project::Common::InvalidArgument; 26 27 constexpr auto SUPPORTED_KEYBITLENGTH = 2048; 28 29 Manager::Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event, 30 const char* path, const CertificateType& type, 31 UnitsToRestart&& unit, CertInstallPath&& installPath) : 32 Ifaces(bus, path), 33 bus(bus), event(event), objectPath(path), certType(type), 34 unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)), 35 certParentInstallPath(fs::path(certInstallPath).parent_path()) 36 { 37 try 38 { 39 // Create certificate directory if not existing. 40 // Set correct certificate directory permitions. 41 fs::path certDirectory; 42 try 43 { 44 if (certType == AUTHORITY) 45 { 46 certDirectory = certInstallPath; 47 } 48 else 49 { 50 certDirectory = certParentInstallPath; 51 } 52 53 if (!fs::exists(certDirectory)) 54 { 55 fs::create_directories(certDirectory); 56 } 57 58 auto permission = fs::perms::owner_read | fs::perms::owner_write | 59 fs::perms::owner_exec; 60 fs::permissions(certDirectory, permission, 61 fs::perm_options::replace); 62 storageUpdate(); 63 } 64 catch (fs::filesystem_error& e) 65 { 66 log<level::ERR>( 67 "Failed to create directory", entry("ERR=%s", e.what()), 68 entry("DIRECTORY=%s", certParentInstallPath.c_str())); 69 report<InternalFailure>(); 70 } 71 72 // Generating RSA private key file if certificate type is server/client 73 if (certType != AUTHORITY) 74 { 75 createRSAPrivateKeyFile(); 76 } 77 78 // restore any existing certificates 79 createCertificates(); 80 81 // watch is not required for authority certificates 82 if (certType != AUTHORITY) 83 { 84 // watch for certificate file create/replace 85 certWatchPtr = std::make_unique< 86 Watch>(event, certInstallPath, [this]() { 87 try 88 { 89 // if certificate file existing update it 90 if (!installedCerts.empty()) 91 { 92 log<level::INFO>("Inotify callback to update " 93 "certificate properties"); 94 installedCerts[0]->populateProperties(); 95 } 96 else 97 { 98 log<level::INFO>( 99 "Inotify callback to create certificate object"); 100 createCertificates(); 101 } 102 } 103 catch (const InternalFailure& e) 104 { 105 commit<InternalFailure>(); 106 } 107 catch (const InvalidCertificate& e) 108 { 109 commit<InvalidCertificate>(); 110 } 111 }); 112 } 113 else 114 { 115 try 116 { 117 const std::string singleCertPath = "/etc/ssl/certs/Root-CA.pem"; 118 if (fs::exists(singleCertPath) && !fs::is_empty(singleCertPath)) 119 { 120 log<level::NOTICE>( 121 "Legacy certificate detected, will be installed from: ", 122 entry("SINGLE_CERTPATH=%s", singleCertPath.c_str())); 123 install(singleCertPath); 124 if (!fs::remove(singleCertPath)) 125 { 126 log<level::ERR>( 127 "Unable to remove old certificate from: ", 128 entry("SINGLE_CERTPATH=%s", 129 singleCertPath.c_str())); 130 elog<InternalFailure>(); 131 } 132 } 133 } 134 catch (const std::exception& ex) 135 { 136 log<level::ERR>("Error in restoring legacy certificate", 137 entry("ERROR_STR=%s", ex.what())); 138 } 139 } 140 } 141 catch (std::exception& ex) 142 { 143 log<level::ERR>("Error in certificate manager constructor", 144 entry("ERROR_STR=%s", ex.what())); 145 } 146 } 147 148 std::string Manager::install(const std::string filePath) 149 { 150 using NotAllowed = 151 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 152 using Reason = xyz::openbmc_project::Common::NotAllowed::REASON; 153 154 if (certType != phosphor::certs::AUTHORITY && !installedCerts.empty()) 155 { 156 elog<NotAllowed>(Reason("Certificate already exist")); 157 } 158 else if (certType == phosphor::certs::AUTHORITY && 159 installedCerts.size() >= AUTHORITY_CERTIFICATES_LIMIT) 160 { 161 elog<NotAllowed>(Reason("Certificates limit reached")); 162 } 163 164 std::string certObjectPath; 165 if (isCertificateUnique(filePath)) 166 { 167 certObjectPath = objectPath + '/' + std::to_string(certIdCounter); 168 installedCerts.emplace_back(std::make_unique<Certificate>( 169 bus, certObjectPath, certType, certInstallPath, filePath, 170 certWatchPtr, *this)); 171 reloadOrReset(unitToRestart); 172 certIdCounter++; 173 } 174 else 175 { 176 elog<NotAllowed>(Reason("Certificate already exist")); 177 } 178 179 return certObjectPath; 180 } 181 182 void Manager::deleteAll() 183 { 184 // TODO: #Issue 4 when a certificate is deleted system auto generates 185 // certificate file. At present we are not supporting creation of 186 // certificate object for the auto-generated certificate file as 187 // deletion if only applicable for REST server and Bmcweb does not allow 188 // deletion of certificates 189 installedCerts.clear(); 190 storageUpdate(); 191 reloadOrReset(unitToRestart); 192 } 193 194 void Manager::deleteCertificate(const Certificate* const certificate) 195 { 196 std::vector<std::unique_ptr<Certificate>>::iterator const& certIt = 197 std::find_if(installedCerts.begin(), installedCerts.end(), 198 [certificate](std::unique_ptr<Certificate> const& cert) { 199 return (cert.get() == certificate); 200 }); 201 if (certIt != installedCerts.end()) 202 { 203 installedCerts.erase(certIt); 204 storageUpdate(); 205 reloadOrReset(unitToRestart); 206 } 207 else 208 { 209 log<level::ERR>("Certificate does not exist", 210 entry("ID=%s", certificate->getCertId().c_str())); 211 elog<InternalFailure>(); 212 } 213 } 214 215 void Manager::replaceCertificate(Certificate* const certificate, 216 const std::string& filePath) 217 { 218 if (isCertificateUnique(filePath, certificate)) 219 { 220 certificate->install(filePath); 221 storageUpdate(); 222 reloadOrReset(unitToRestart); 223 } 224 else 225 { 226 using NotAllowed = 227 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 228 using Reason = xyz::openbmc_project::Common::NotAllowed::REASON; 229 230 elog<NotAllowed>(Reason("Certificate already exist")); 231 } 232 } 233 234 std::string Manager::generateCSR( 235 std::vector<std::string> alternativeNames, std::string challengePassword, 236 std::string city, std::string commonName, std::string contactPerson, 237 std::string country, std::string email, std::string givenName, 238 std::string initials, int64_t keyBitLength, std::string keyCurveId, 239 std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 240 std::string organization, std::string organizationalUnit, std::string state, 241 std::string surname, std::string unstructuredName) 242 { 243 // We support only one CSR. 244 csrPtr.reset(nullptr); 245 auto pid = fork(); 246 if (pid == -1) 247 { 248 log<level::ERR>("Error occurred during forking process"); 249 report<InternalFailure>(); 250 } 251 else if (pid == 0) 252 { 253 try 254 { 255 generateCSRHelper(alternativeNames, challengePassword, city, 256 commonName, contactPerson, country, email, 257 givenName, initials, keyBitLength, keyCurveId, 258 keyPairAlgorithm, keyUsage, organization, 259 organizationalUnit, state, surname, 260 unstructuredName); 261 exit(EXIT_SUCCESS); 262 } 263 catch (const InternalFailure& e) 264 { 265 // commit the error reported in child process and exit 266 // Callback method from SDEvent Loop looks for exit status 267 exit(EXIT_FAILURE); 268 commit<InternalFailure>(); 269 } 270 } 271 else 272 { 273 using namespace sdeventplus::source; 274 Child::Callback callback = [this](Child& eventSource, 275 const siginfo_t* si) { 276 eventSource.set_enabled(Enabled::On); 277 if (si->si_status != 0) 278 { 279 this->createCSRObject(Status::FAILURE); 280 } 281 else 282 { 283 this->createCSRObject(Status::SUCCESS); 284 } 285 }; 286 try 287 { 288 sigset_t ss; 289 if (sigemptyset(&ss) < 0) 290 { 291 log<level::ERR>("Unable to initialize signal set"); 292 elog<InternalFailure>(); 293 } 294 if (sigaddset(&ss, SIGCHLD) < 0) 295 { 296 log<level::ERR>("Unable to add signal to signal set"); 297 elog<InternalFailure>(); 298 } 299 300 // Block SIGCHLD first, so that the event loop can handle it 301 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0) 302 { 303 log<level::ERR>("Unable to block signal"); 304 elog<InternalFailure>(); 305 } 306 if (childPtr) 307 { 308 childPtr.reset(); 309 } 310 childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 311 std::move(callback)); 312 } 313 catch (const InternalFailure& e) 314 { 315 commit<InternalFailure>(); 316 } 317 } 318 auto csrObjectPath = objectPath + '/' + "csr"; 319 return csrObjectPath; 320 } 321 322 std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates() 323 { 324 return installedCerts; 325 } 326 327 void Manager::generateCSRHelper( 328 std::vector<std::string> alternativeNames, std::string challengePassword, 329 std::string city, std::string commonName, std::string contactPerson, 330 std::string country, std::string email, std::string givenName, 331 std::string initials, int64_t keyBitLength, std::string keyCurveId, 332 std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 333 std::string organization, std::string organizationalUnit, std::string state, 334 std::string surname, std::string unstructuredName) 335 { 336 int ret = 0; 337 338 // set version of x509 req 339 int nVersion = 1; 340 // TODO: Issue#6 need to make version number configurable 341 X509_REQ_Ptr x509Req(X509_REQ_new(), ::X509_REQ_free); 342 ret = X509_REQ_set_version(x509Req.get(), nVersion); 343 if (ret == 0) 344 { 345 log<level::ERR>("Error occured during X509_REQ_set_version call"); 346 elog<InternalFailure>(); 347 } 348 349 // set subject of x509 req 350 X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 351 352 if (!alternativeNames.empty()) 353 { 354 for (auto& name : alternativeNames) 355 { 356 addEntry(x509Name, "subjectAltName", name); 357 } 358 } 359 addEntry(x509Name, "challengePassword", challengePassword); 360 addEntry(x509Name, "L", city); 361 addEntry(x509Name, "CN", commonName); 362 addEntry(x509Name, "name", contactPerson); 363 addEntry(x509Name, "C", country); 364 addEntry(x509Name, "emailAddress", email); 365 addEntry(x509Name, "GN", givenName); 366 addEntry(x509Name, "initials", initials); 367 addEntry(x509Name, "algorithm", keyPairAlgorithm); 368 if (!keyUsage.empty()) 369 { 370 for (auto& usage : keyUsage) 371 { 372 if (isExtendedKeyUsage(usage)) 373 { 374 addEntry(x509Name, "extendedKeyUsage", usage); 375 } 376 else 377 { 378 addEntry(x509Name, "keyUsage", usage); 379 } 380 } 381 } 382 addEntry(x509Name, "O", organization); 383 addEntry(x509Name, "ST", state); 384 addEntry(x509Name, "SN", surname); 385 addEntry(x509Name, "unstructuredName", unstructuredName); 386 387 EVP_PKEY_Ptr pKey(nullptr, ::EVP_PKEY_free); 388 389 log<level::INFO>("Given Key pair algorithm", 390 entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str())); 391 392 // Used EC algorithm as default if user did not give algorithm type. 393 if (keyPairAlgorithm == "RSA") 394 pKey = getRSAKeyPair(keyBitLength); 395 else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 396 pKey = generateECKeyPair(keyCurveId); 397 else 398 { 399 log<level::ERR>("Given Key pair algorithm is not supported. Supporting " 400 "RSA and EC only"); 401 elog<InvalidArgument>( 402 Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 403 Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 404 } 405 406 ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 407 if (ret == 0) 408 { 409 log<level::ERR>("Error occured while setting Public key"); 410 elog<InternalFailure>(); 411 } 412 413 // Write private key to file 414 writePrivateKey(pKey, PRIV_KEY_FILE_NAME); 415 416 // set sign key of x509 req 417 ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 418 if (ret == 0) 419 { 420 log<level::ERR>("Error occured while signing key of x509"); 421 elog<InternalFailure>(); 422 } 423 424 log<level::INFO>("Writing CSR to file"); 425 fs::path csrFilePath = certParentInstallPath / CSR_FILE_NAME; 426 writeCSR(csrFilePath.string(), x509Req); 427 } 428 429 bool Manager::isExtendedKeyUsage(const std::string& usage) 430 { 431 const static std::array<const char*, 6> usageList = { 432 "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 433 "Timestamping", "CodeSigning", "EmailProtection"}; 434 auto it = std::find_if( 435 usageList.begin(), usageList.end(), 436 [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); }); 437 return it != usageList.end(); 438 } 439 EVP_PKEY_Ptr Manager::generateRSAKeyPair(const int64_t keyBitLength) 440 { 441 int ret = 0; 442 // generate rsa key 443 BIGNUM_Ptr bne(BN_new(), ::BN_free); 444 ret = BN_set_word(bne.get(), RSA_F4); 445 if (ret == 0) 446 { 447 log<level::ERR>("Error occured during BN_set_word call"); 448 elog<InternalFailure>(); 449 } 450 451 int64_t keyBitLen = keyBitLength; 452 // set keybit length to default value if not set 453 if (keyBitLen <= 0) 454 { 455 constexpr auto DEFAULT_KEYBITLENGTH = 2048; 456 log<level::INFO>( 457 "KeyBitLength is not given.Hence, using default KeyBitLength", 458 entry("DEFAULTKEYBITLENGTH=%d", DEFAULT_KEYBITLENGTH)); 459 keyBitLen = DEFAULT_KEYBITLENGTH; 460 } 461 RSA* rsa = RSA_new(); 462 ret = RSA_generate_key_ex(rsa, keyBitLen, bne.get(), NULL); 463 if (ret != 1) 464 { 465 free(rsa); 466 log<level::ERR>("Error occured during RSA_generate_key_ex call", 467 entry("KEYBITLENGTH=%PRIu64", keyBitLen)); 468 elog<InternalFailure>(); 469 } 470 471 // set public key of x509 req 472 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 473 ret = EVP_PKEY_assign_RSA(pKey.get(), rsa); 474 if (ret == 0) 475 { 476 free(rsa); 477 log<level::ERR>("Error occured during assign rsa key into EVP"); 478 elog<InternalFailure>(); 479 } 480 481 return pKey; 482 } 483 484 EVP_PKEY_Ptr Manager::generateECKeyPair(const std::string& curveId) 485 { 486 std::string curId(curveId); 487 488 if (curId.empty()) 489 { 490 // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 491 constexpr auto DEFAULT_KEYCURVEID = "secp224r1"; 492 log<level::INFO>( 493 "KeyCurveId is not given. Hence using default curve id", 494 entry("DEFAULTKEYCURVEID=%s", DEFAULT_KEYCURVEID)); 495 curId = DEFAULT_KEYCURVEID; 496 } 497 498 int ecGrp = OBJ_txt2nid(curId.c_str()); 499 500 if (ecGrp == NID_undef) 501 { 502 log<level::ERR>( 503 "Error occured during convert the curve id string format into NID", 504 entry("KEYCURVEID=%s", curId.c_str())); 505 elog<InternalFailure>(); 506 } 507 508 EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 509 510 if (ecKey == NULL) 511 { 512 log<level::ERR>( 513 "Error occured during create the EC_Key object from NID", 514 entry("ECGROUP=%d", ecGrp)); 515 elog<InternalFailure>(); 516 } 517 518 // If you want to save a key and later load it with 519 // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 520 // flag on the key. 521 EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 522 523 int ret = EC_KEY_generate_key(ecKey); 524 525 if (ret == 0) 526 { 527 EC_KEY_free(ecKey); 528 log<level::ERR>("Error occured during generate EC key"); 529 elog<InternalFailure>(); 530 } 531 532 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 533 ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 534 if (ret == 0) 535 { 536 EC_KEY_free(ecKey); 537 log<level::ERR>("Error occured during assign EC Key into EVP"); 538 elog<InternalFailure>(); 539 } 540 541 return pKey; 542 } 543 544 void Manager::writePrivateKey(const EVP_PKEY_Ptr& pKey, 545 const std::string& privKeyFileName) 546 { 547 log<level::INFO>("Writing private key to file"); 548 // write private key to file 549 fs::path privKeyPath = certParentInstallPath / privKeyFileName; 550 551 FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 552 if (fp == NULL) 553 { 554 log<level::ERR>("Error occured creating private key file"); 555 elog<InternalFailure>(); 556 } 557 int ret = PEM_write_PrivateKey(fp, pKey.get(), NULL, NULL, 0, 0, NULL); 558 std::fclose(fp); 559 if (ret == 0) 560 { 561 log<level::ERR>("Error occured while writing private key to file"); 562 elog<InternalFailure>(); 563 } 564 } 565 566 void Manager::addEntry(X509_NAME* x509Name, const char* field, 567 const std::string& bytes) 568 { 569 if (bytes.empty()) 570 { 571 return; 572 } 573 int ret = X509_NAME_add_entry_by_txt( 574 x509Name, field, MBSTRING_ASC, 575 reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 576 if (ret != 1) 577 { 578 log<level::ERR>("Unable to set entry", entry("FIELD=%s", field), 579 entry("VALUE=%s", bytes.c_str())); 580 elog<InternalFailure>(); 581 } 582 } 583 584 void Manager::createCSRObject(const Status& status) 585 { 586 if (csrPtr) 587 { 588 csrPtr.reset(nullptr); 589 } 590 auto csrObjectPath = objectPath + '/' + "csr"; 591 csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 592 certInstallPath.c_str(), status); 593 } 594 595 void Manager::writeCSR(const std::string& filePath, const X509_REQ_Ptr& x509Req) 596 { 597 if (fs::exists(filePath)) 598 { 599 log<level::INFO>("Removing the existing file", 600 entry("FILENAME=%s", filePath.c_str())); 601 if (!fs::remove(filePath.c_str())) 602 { 603 log<level::ERR>("Unable to remove the file", 604 entry("FILENAME=%s", filePath.c_str())); 605 elog<InternalFailure>(); 606 } 607 } 608 609 FILE* fp = NULL; 610 611 if ((fp = std::fopen(filePath.c_str(), "w")) == NULL) 612 { 613 log<level::ERR>("Error opening the file to write the CSR", 614 entry("FILENAME=%s", filePath.c_str())); 615 elog<InternalFailure>(); 616 } 617 618 int rc = PEM_write_X509_REQ(fp, x509Req.get()); 619 if (!rc) 620 { 621 log<level::ERR>("PEM write routine failed", 622 entry("FILENAME=%s", filePath.c_str())); 623 std::fclose(fp); 624 elog<InternalFailure>(); 625 } 626 std::fclose(fp); 627 } 628 629 void Manager::createCertificates() 630 { 631 auto certObjectPath = objectPath + '/'; 632 633 if (certType == phosphor::certs::AUTHORITY) 634 { 635 // Check whether install path is a directory. 636 if (!fs::is_directory(certInstallPath)) 637 { 638 log<level::ERR>("Certificate installation path exists and it is " 639 "not a directory"); 640 elog<InternalFailure>(); 641 return; 642 } 643 644 for (auto& path : fs::directory_iterator(certInstallPath)) 645 { 646 try 647 { 648 // Assume here any regular file located in certificate directory 649 // contains certificates body. Do not want to use soft links 650 // would add value. 651 if (fs::is_regular_file(path)) 652 { 653 installedCerts.emplace_back(std::make_unique<Certificate>( 654 bus, certObjectPath + std::to_string(certIdCounter++), 655 certType, certInstallPath, path.path(), certWatchPtr, 656 *this)); 657 } 658 } 659 catch (const InternalFailure& e) 660 { 661 report<InternalFailure>(); 662 } 663 catch (const InvalidCertificate& e) 664 { 665 report<InvalidCertificate>( 666 Reason("Existing certificate file is corrupted")); 667 } 668 } 669 } 670 else if (fs::exists(certInstallPath)) 671 { 672 try 673 { 674 installedCerts.emplace_back(std::make_unique<Certificate>( 675 bus, certObjectPath + '1', certType, certInstallPath, 676 certInstallPath, certWatchPtr, *this)); 677 } 678 catch (const InternalFailure& e) 679 { 680 report<InternalFailure>(); 681 } 682 catch (const InvalidCertificate& e) 683 { 684 report<InvalidCertificate>( 685 Reason("Existing certificate file is corrupted")); 686 } 687 } 688 } 689 690 void Manager::createRSAPrivateKeyFile() 691 { 692 fs::path rsaPrivateKeyFileName = 693 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME; 694 695 try 696 { 697 if (!fs::exists(rsaPrivateKeyFileName)) 698 { 699 writePrivateKey(generateRSAKeyPair(SUPPORTED_KEYBITLENGTH), 700 RSA_PRIV_KEY_FILE_NAME); 701 } 702 } 703 catch (const InternalFailure& e) 704 { 705 report<InternalFailure>(); 706 } 707 } 708 709 EVP_PKEY_Ptr Manager::getRSAKeyPair(const int64_t keyBitLength) 710 { 711 if (keyBitLength != SUPPORTED_KEYBITLENGTH) 712 { 713 log<level::ERR>( 714 "Given Key bit length is not supported", 715 entry("GIVENKEYBITLENGTH=%d", keyBitLength), 716 entry("SUPPORTEDKEYBITLENGTH=%d", SUPPORTED_KEYBITLENGTH)); 717 elog<InvalidArgument>( 718 Argument::ARGUMENT_NAME("KEYBITLENGTH"), 719 Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 720 } 721 fs::path rsaPrivateKeyFileName = 722 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME; 723 724 FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 725 if (!privateKeyFile) 726 { 727 log<level::ERR>("Unable to open RSA private key file to read", 728 entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()), 729 entry("ERRORREASON=%s", strerror(errno))); 730 elog<InternalFailure>(); 731 } 732 733 EVP_PKEY_Ptr privateKey( 734 PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 735 ::EVP_PKEY_free); 736 std::fclose(privateKeyFile); 737 738 if (!privateKey) 739 { 740 log<level::ERR>("Error occured during PEM_read_PrivateKey call"); 741 elog<InternalFailure>(); 742 } 743 return privateKey; 744 } 745 746 void Manager::storageUpdate() 747 { 748 if (certType == phosphor::certs::AUTHORITY) 749 { 750 // Remove symbolic links in the certificate directory 751 for (auto& certPath : fs::directory_iterator(certInstallPath)) 752 { 753 try 754 { 755 if (fs::is_symlink(certPath)) 756 { 757 fs::remove(certPath); 758 } 759 } 760 catch (const std::exception& e) 761 { 762 log<level::ERR>( 763 "Failed to remove symlink for certificate", 764 entry("ERR=%s", e.what()), 765 entry("SYMLINK=%s", certPath.path().string().c_str())); 766 elog<InternalFailure>(); 767 } 768 } 769 } 770 771 for (const auto& cert : installedCerts) 772 { 773 cert->storageUpdate(); 774 } 775 } 776 777 void Manager::reloadOrReset(const UnitsToRestart& unit) 778 { 779 if (!unit.empty()) 780 { 781 try 782 { 783 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 784 constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; 785 constexpr auto SYSTEMD_INTERFACE = 786 "org.freedesktop.systemd1.Manager"; 787 788 auto method = 789 bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, 790 SYSTEMD_INTERFACE, "ReloadOrRestartUnit"); 791 method.append(unit, "replace"); 792 bus.call_noreply(method); 793 } 794 catch (const sdbusplus::exception::SdBusError& e) 795 { 796 log<level::ERR>("Failed to reload or restart service", 797 entry("ERR=%s", e.what()), 798 entry("UNIT=%s", unit.c_str())); 799 elog<InternalFailure>(); 800 } 801 } 802 } 803 804 bool Manager::isCertificateUnique(const std::string& filePath, 805 const Certificate* const certToDrop) 806 { 807 if (std::any_of( 808 installedCerts.begin(), installedCerts.end(), 809 [&filePath, certToDrop](std::unique_ptr<Certificate> const& cert) { 810 return cert.get() != certToDrop && cert->isSame(filePath); 811 })) 812 { 813 return false; 814 } 815 else 816 { 817 return true; 818 } 819 } 820 821 } // namespace certs 822 } // namespace phosphor 823