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 (const 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 (const 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 catch (const InvalidArgument& e) 271 { 272 // commit the error reported in child process and exit 273 // Callback method from SDEvent Loop looks for exit status 274 exit(EXIT_FAILURE); 275 commit<InvalidArgument>(); 276 } 277 } 278 else 279 { 280 using namespace sdeventplus::source; 281 Child::Callback callback = [this](Child& eventSource, 282 const siginfo_t* si) { 283 eventSource.set_enabled(Enabled::On); 284 if (si->si_status != 0) 285 { 286 this->createCSRObject(Status::FAILURE); 287 } 288 else 289 { 290 this->createCSRObject(Status::SUCCESS); 291 } 292 }; 293 try 294 { 295 sigset_t ss; 296 if (sigemptyset(&ss) < 0) 297 { 298 log<level::ERR>("Unable to initialize signal set"); 299 elog<InternalFailure>(); 300 } 301 if (sigaddset(&ss, SIGCHLD) < 0) 302 { 303 log<level::ERR>("Unable to add signal to signal set"); 304 elog<InternalFailure>(); 305 } 306 307 // Block SIGCHLD first, so that the event loop can handle it 308 if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0) 309 { 310 log<level::ERR>("Unable to block signal"); 311 elog<InternalFailure>(); 312 } 313 if (childPtr) 314 { 315 childPtr.reset(); 316 } 317 childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 318 std::move(callback)); 319 } 320 catch (const InternalFailure& e) 321 { 322 commit<InternalFailure>(); 323 } 324 } 325 auto csrObjectPath = objectPath + '/' + "csr"; 326 return csrObjectPath; 327 } 328 329 std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates() 330 { 331 return installedCerts; 332 } 333 334 void Manager::generateCSRHelper( 335 std::vector<std::string> alternativeNames, std::string challengePassword, 336 std::string city, std::string commonName, std::string contactPerson, 337 std::string country, std::string email, std::string givenName, 338 std::string initials, int64_t keyBitLength, std::string keyCurveId, 339 std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 340 std::string organization, std::string organizationalUnit, std::string state, 341 std::string surname, std::string unstructuredName) 342 { 343 int ret = 0; 344 345 // set version of x509 req 346 int nVersion = 1; 347 // TODO: Issue#6 need to make version number configurable 348 X509_REQ_Ptr x509Req(X509_REQ_new(), ::X509_REQ_free); 349 ret = X509_REQ_set_version(x509Req.get(), nVersion); 350 if (ret == 0) 351 { 352 log<level::ERR>("Error occured during X509_REQ_set_version call"); 353 elog<InternalFailure>(); 354 } 355 356 // set subject of x509 req 357 X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 358 359 if (!alternativeNames.empty()) 360 { 361 for (auto& name : alternativeNames) 362 { 363 addEntry(x509Name, "subjectAltName", name); 364 } 365 } 366 addEntry(x509Name, "challengePassword", challengePassword); 367 addEntry(x509Name, "L", city); 368 addEntry(x509Name, "CN", commonName); 369 addEntry(x509Name, "name", contactPerson); 370 addEntry(x509Name, "C", country); 371 addEntry(x509Name, "emailAddress", email); 372 addEntry(x509Name, "GN", givenName); 373 addEntry(x509Name, "initials", initials); 374 addEntry(x509Name, "algorithm", keyPairAlgorithm); 375 if (!keyUsage.empty()) 376 { 377 for (auto& usage : keyUsage) 378 { 379 if (isExtendedKeyUsage(usage)) 380 { 381 addEntry(x509Name, "extendedKeyUsage", usage); 382 } 383 else 384 { 385 addEntry(x509Name, "keyUsage", usage); 386 } 387 } 388 } 389 addEntry(x509Name, "O", organization); 390 addEntry(x509Name, "OU", organizationalUnit); 391 addEntry(x509Name, "ST", state); 392 addEntry(x509Name, "SN", surname); 393 addEntry(x509Name, "unstructuredName", unstructuredName); 394 395 EVP_PKEY_Ptr pKey(nullptr, ::EVP_PKEY_free); 396 397 log<level::INFO>("Given Key pair algorithm", 398 entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str())); 399 400 // Used EC algorithm as default if user did not give algorithm type. 401 if (keyPairAlgorithm == "RSA") 402 pKey = getRSAKeyPair(keyBitLength); 403 else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 404 pKey = generateECKeyPair(keyCurveId); 405 else 406 { 407 log<level::ERR>("Given Key pair algorithm is not supported. Supporting " 408 "RSA and EC only"); 409 elog<InvalidArgument>( 410 Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 411 Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 412 } 413 414 ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 415 if (ret == 0) 416 { 417 log<level::ERR>("Error occured while setting Public key"); 418 elog<InternalFailure>(); 419 } 420 421 // Write private key to file 422 writePrivateKey(pKey, PRIV_KEY_FILE_NAME); 423 424 // set sign key of x509 req 425 ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 426 if (ret == 0) 427 { 428 log<level::ERR>("Error occured while signing key of x509"); 429 elog<InternalFailure>(); 430 } 431 432 log<level::INFO>("Writing CSR to file"); 433 fs::path csrFilePath = certParentInstallPath / CSR_FILE_NAME; 434 writeCSR(csrFilePath.string(), x509Req); 435 } 436 437 bool Manager::isExtendedKeyUsage(const std::string& usage) 438 { 439 const static std::array<const char*, 6> usageList = { 440 "ServerAuthentication", "ClientAuthentication", "OCSPSigning", 441 "Timestamping", "CodeSigning", "EmailProtection"}; 442 auto it = std::find_if( 443 usageList.begin(), usageList.end(), 444 [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); }); 445 return it != usageList.end(); 446 } 447 EVP_PKEY_Ptr Manager::generateRSAKeyPair(const int64_t keyBitLength) 448 { 449 int ret = 0; 450 // generate rsa key 451 BIGNUM_Ptr bne(BN_new(), ::BN_free); 452 ret = BN_set_word(bne.get(), RSA_F4); 453 if (ret == 0) 454 { 455 log<level::ERR>("Error occured during BN_set_word call"); 456 elog<InternalFailure>(); 457 } 458 459 int64_t keyBitLen = keyBitLength; 460 // set keybit length to default value if not set 461 if (keyBitLen <= 0) 462 { 463 constexpr auto DEFAULT_KEYBITLENGTH = 2048; 464 log<level::INFO>( 465 "KeyBitLength is not given.Hence, using default KeyBitLength", 466 entry("DEFAULTKEYBITLENGTH=%d", DEFAULT_KEYBITLENGTH)); 467 keyBitLen = DEFAULT_KEYBITLENGTH; 468 } 469 RSA* rsa = RSA_new(); 470 ret = RSA_generate_key_ex(rsa, keyBitLen, bne.get(), NULL); 471 if (ret != 1) 472 { 473 free(rsa); 474 log<level::ERR>("Error occured during RSA_generate_key_ex call", 475 entry("KEYBITLENGTH=%PRIu64", keyBitLen)); 476 elog<InternalFailure>(); 477 } 478 479 // set public key of x509 req 480 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 481 ret = EVP_PKEY_assign_RSA(pKey.get(), rsa); 482 if (ret == 0) 483 { 484 free(rsa); 485 log<level::ERR>("Error occured during assign rsa key into EVP"); 486 elog<InternalFailure>(); 487 } 488 489 return pKey; 490 } 491 492 EVP_PKEY_Ptr Manager::generateECKeyPair(const std::string& curveId) 493 { 494 std::string curId(curveId); 495 496 if (curId.empty()) 497 { 498 // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 499 constexpr auto DEFAULT_KEYCURVEID = "secp224r1"; 500 log<level::INFO>( 501 "KeyCurveId is not given. Hence using default curve id", 502 entry("DEFAULTKEYCURVEID=%s", DEFAULT_KEYCURVEID)); 503 curId = DEFAULT_KEYCURVEID; 504 } 505 506 int ecGrp = OBJ_txt2nid(curId.c_str()); 507 508 if (ecGrp == NID_undef) 509 { 510 log<level::ERR>( 511 "Error occured during convert the curve id string format into NID", 512 entry("KEYCURVEID=%s", curId.c_str())); 513 elog<InternalFailure>(); 514 } 515 516 EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 517 518 if (ecKey == NULL) 519 { 520 log<level::ERR>( 521 "Error occured during create the EC_Key object from NID", 522 entry("ECGROUP=%d", ecGrp)); 523 elog<InternalFailure>(); 524 } 525 526 // If you want to save a key and later load it with 527 // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 528 // flag on the key. 529 EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 530 531 int ret = EC_KEY_generate_key(ecKey); 532 533 if (ret == 0) 534 { 535 EC_KEY_free(ecKey); 536 log<level::ERR>("Error occured during generate EC key"); 537 elog<InternalFailure>(); 538 } 539 540 EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 541 ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 542 if (ret == 0) 543 { 544 EC_KEY_free(ecKey); 545 log<level::ERR>("Error occured during assign EC Key into EVP"); 546 elog<InternalFailure>(); 547 } 548 549 return pKey; 550 } 551 552 void Manager::writePrivateKey(const EVP_PKEY_Ptr& pKey, 553 const std::string& privKeyFileName) 554 { 555 log<level::INFO>("Writing private key to file"); 556 // write private key to file 557 fs::path privKeyPath = certParentInstallPath / privKeyFileName; 558 559 FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 560 if (fp == NULL) 561 { 562 log<level::ERR>("Error occured creating private key file"); 563 elog<InternalFailure>(); 564 } 565 int ret = PEM_write_PrivateKey(fp, pKey.get(), NULL, NULL, 0, 0, NULL); 566 std::fclose(fp); 567 if (ret == 0) 568 { 569 log<level::ERR>("Error occured while writing private key to file"); 570 elog<InternalFailure>(); 571 } 572 } 573 574 void Manager::addEntry(X509_NAME* x509Name, const char* field, 575 const std::string& bytes) 576 { 577 if (bytes.empty()) 578 { 579 return; 580 } 581 int ret = X509_NAME_add_entry_by_txt( 582 x509Name, field, MBSTRING_ASC, 583 reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 584 if (ret != 1) 585 { 586 log<level::ERR>("Unable to set entry", entry("FIELD=%s", field), 587 entry("VALUE=%s", bytes.c_str())); 588 elog<InternalFailure>(); 589 } 590 } 591 592 void Manager::createCSRObject(const Status& status) 593 { 594 if (csrPtr) 595 { 596 csrPtr.reset(nullptr); 597 } 598 auto csrObjectPath = objectPath + '/' + "csr"; 599 csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 600 certInstallPath.c_str(), status); 601 } 602 603 void Manager::writeCSR(const std::string& filePath, const X509_REQ_Ptr& x509Req) 604 { 605 if (fs::exists(filePath)) 606 { 607 log<level::INFO>("Removing the existing file", 608 entry("FILENAME=%s", filePath.c_str())); 609 if (!fs::remove(filePath.c_str())) 610 { 611 log<level::ERR>("Unable to remove the file", 612 entry("FILENAME=%s", filePath.c_str())); 613 elog<InternalFailure>(); 614 } 615 } 616 617 FILE* fp = NULL; 618 619 if ((fp = std::fopen(filePath.c_str(), "w")) == NULL) 620 { 621 log<level::ERR>("Error opening the file to write the CSR", 622 entry("FILENAME=%s", filePath.c_str())); 623 elog<InternalFailure>(); 624 } 625 626 int rc = PEM_write_X509_REQ(fp, x509Req.get()); 627 if (!rc) 628 { 629 log<level::ERR>("PEM write routine failed", 630 entry("FILENAME=%s", filePath.c_str())); 631 std::fclose(fp); 632 elog<InternalFailure>(); 633 } 634 std::fclose(fp); 635 } 636 637 void Manager::createCertificates() 638 { 639 auto certObjectPath = objectPath + '/'; 640 641 if (certType == phosphor::certs::AUTHORITY) 642 { 643 // Check whether install path is a directory. 644 if (!fs::is_directory(certInstallPath)) 645 { 646 log<level::ERR>("Certificate installation path exists and it is " 647 "not a directory"); 648 elog<InternalFailure>(); 649 return; 650 } 651 652 for (auto& path : fs::directory_iterator(certInstallPath)) 653 { 654 try 655 { 656 // Assume here any regular file located in certificate directory 657 // contains certificates body. Do not want to use soft links 658 // would add value. 659 if (fs::is_regular_file(path)) 660 { 661 installedCerts.emplace_back(std::make_unique<Certificate>( 662 bus, certObjectPath + std::to_string(certIdCounter++), 663 certType, certInstallPath, path.path(), certWatchPtr, 664 *this)); 665 } 666 } 667 catch (const InternalFailure& e) 668 { 669 report<InternalFailure>(); 670 } 671 catch (const InvalidCertificate& e) 672 { 673 report<InvalidCertificate>( 674 Reason("Existing certificate file is corrupted")); 675 } 676 } 677 } 678 else if (fs::exists(certInstallPath)) 679 { 680 try 681 { 682 installedCerts.emplace_back(std::make_unique<Certificate>( 683 bus, certObjectPath + '1', certType, certInstallPath, 684 certInstallPath, certWatchPtr, *this)); 685 } 686 catch (const InternalFailure& e) 687 { 688 report<InternalFailure>(); 689 } 690 catch (const InvalidCertificate& e) 691 { 692 report<InvalidCertificate>( 693 Reason("Existing certificate file is corrupted")); 694 } 695 } 696 } 697 698 void Manager::createRSAPrivateKeyFile() 699 { 700 fs::path rsaPrivateKeyFileName = 701 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME; 702 703 try 704 { 705 if (!fs::exists(rsaPrivateKeyFileName)) 706 { 707 writePrivateKey(generateRSAKeyPair(SUPPORTED_KEYBITLENGTH), 708 RSA_PRIV_KEY_FILE_NAME); 709 } 710 } 711 catch (const InternalFailure& e) 712 { 713 report<InternalFailure>(); 714 } 715 } 716 717 EVP_PKEY_Ptr Manager::getRSAKeyPair(const int64_t keyBitLength) 718 { 719 if (keyBitLength != SUPPORTED_KEYBITLENGTH) 720 { 721 log<level::ERR>( 722 "Given Key bit length is not supported", 723 entry("GIVENKEYBITLENGTH=%d", keyBitLength), 724 entry("SUPPORTEDKEYBITLENGTH=%d", SUPPORTED_KEYBITLENGTH)); 725 elog<InvalidArgument>( 726 Argument::ARGUMENT_NAME("KEYBITLENGTH"), 727 Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str())); 728 } 729 fs::path rsaPrivateKeyFileName = 730 certParentInstallPath / RSA_PRIV_KEY_FILE_NAME; 731 732 FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r"); 733 if (!privateKeyFile) 734 { 735 log<level::ERR>("Unable to open RSA private key file to read", 736 entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()), 737 entry("ERRORREASON=%s", strerror(errno))); 738 elog<InternalFailure>(); 739 } 740 741 EVP_PKEY_Ptr privateKey( 742 PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr), 743 ::EVP_PKEY_free); 744 std::fclose(privateKeyFile); 745 746 if (!privateKey) 747 { 748 log<level::ERR>("Error occured during PEM_read_PrivateKey call"); 749 elog<InternalFailure>(); 750 } 751 return privateKey; 752 } 753 754 void Manager::storageUpdate() 755 { 756 if (certType == phosphor::certs::AUTHORITY) 757 { 758 // Remove symbolic links in the certificate directory 759 for (auto& certPath : fs::directory_iterator(certInstallPath)) 760 { 761 try 762 { 763 if (fs::is_symlink(certPath)) 764 { 765 fs::remove(certPath); 766 } 767 } 768 catch (const std::exception& e) 769 { 770 log<level::ERR>( 771 "Failed to remove symlink for certificate", 772 entry("ERR=%s", e.what()), 773 entry("SYMLINK=%s", certPath.path().string().c_str())); 774 elog<InternalFailure>(); 775 } 776 } 777 } 778 779 for (const auto& cert : installedCerts) 780 { 781 cert->storageUpdate(); 782 } 783 } 784 785 void Manager::reloadOrReset(const UnitsToRestart& unit) 786 { 787 if (!unit.empty()) 788 { 789 try 790 { 791 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 792 constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; 793 constexpr auto SYSTEMD_INTERFACE = 794 "org.freedesktop.systemd1.Manager"; 795 796 auto method = 797 bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, 798 SYSTEMD_INTERFACE, "ReloadOrRestartUnit"); 799 method.append(unit, "replace"); 800 bus.call_noreply(method); 801 } 802 catch (const sdbusplus::exception::exception& e) 803 { 804 log<level::ERR>("Failed to reload or restart service", 805 entry("ERR=%s", e.what()), 806 entry("UNIT=%s", unit.c_str())); 807 elog<InternalFailure>(); 808 } 809 } 810 } 811 812 bool Manager::isCertificateUnique(const std::string& filePath, 813 const Certificate* const certToDrop) 814 { 815 if (std::any_of( 816 installedCerts.begin(), installedCerts.end(), 817 [&filePath, certToDrop](std::unique_ptr<Certificate> const& cert) { 818 return cert.get() != certToDrop && cert->isSame(filePath); 819 })) 820 { 821 return false; 822 } 823 else 824 { 825 return true; 826 } 827 } 828 829 } // namespace certs 830 } // namespace phosphor 831