1cfbc8dc8SJayanth Othayoth #include "certs_manager.hpp" 2cfbc8dc8SJayanth Othayoth 3f4682712SMarri Devender Rao #include <openssl/pem.h> 4f4682712SMarri Devender Rao #include <unistd.h> 5f4682712SMarri 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 16f4682712SMarri Devender Rao using X509_REQ_Ptr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>; 17f4682712SMarri Devender Rao using BIGNUM_Ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>; 18f4682712SMarri Devender Rao 19f4682712SMarri Devender Rao Manager::Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event, 20f4682712SMarri Devender Rao const char* path, const CertificateType& type, 21f4682712SMarri Devender Rao UnitsToRestart&& unit, CertInstallPath&& installPath) : 226ceec40bSMarri Devender Rao Ifaces(bus, path), 23f4682712SMarri Devender Rao bus(bus), event(event), objectPath(path), certType(type), 24f4682712SMarri Devender Rao unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)), 25f4682712SMarri 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 } 84f4682712SMarri Devender Rao 85f4682712SMarri Devender Rao std::string Manager::generateCSR( 86f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 87f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 88f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 89f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 90f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 91f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 92f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 93f4682712SMarri Devender Rao { 94f4682712SMarri Devender Rao // We support only one CSR. 95f4682712SMarri Devender Rao csrPtr.reset(nullptr); 96f4682712SMarri Devender Rao auto pid = fork(); 97f4682712SMarri Devender Rao if (pid == -1) 98f4682712SMarri Devender Rao { 99f4682712SMarri Devender Rao log<level::ERR>("Error occurred during forking process"); 100f4682712SMarri Devender Rao report<InternalFailure>(); 101f4682712SMarri Devender Rao } 102f4682712SMarri Devender Rao else if (pid == 0) 103f4682712SMarri Devender Rao { 104f4682712SMarri Devender Rao try 105f4682712SMarri Devender Rao { 106f4682712SMarri Devender Rao generateCSRHelper(alternativeNames, challengePassword, city, 107f4682712SMarri Devender Rao commonName, contactPerson, country, email, 108f4682712SMarri Devender Rao givenName, initials, keyBitLength, keyCurveId, 109f4682712SMarri Devender Rao keyPairAlgorithm, keyUsage, organization, 110f4682712SMarri Devender Rao organizationalUnit, state, surname, 111f4682712SMarri Devender Rao unstructuredName); 112f4682712SMarri Devender Rao exit(EXIT_SUCCESS); 113f4682712SMarri Devender Rao } 114f4682712SMarri Devender Rao catch (const InternalFailure& e) 115f4682712SMarri Devender Rao { 116f4682712SMarri Devender Rao // commit the error reported in child process and exit 117f4682712SMarri Devender Rao // Callback method from SDEvent Loop looks for exit status 118f4682712SMarri Devender Rao exit(EXIT_FAILURE); 119f4682712SMarri Devender Rao commit<InternalFailure>(); 120f4682712SMarri Devender Rao } 121f4682712SMarri Devender Rao } 122f4682712SMarri Devender Rao else 123f4682712SMarri Devender Rao { 124f4682712SMarri Devender Rao using namespace sdeventplus::source; 125f4682712SMarri Devender Rao Child::Callback callback = [this](Child& eventSource, 126f4682712SMarri Devender Rao const siginfo_t* si) { 127f4682712SMarri Devender Rao eventSource.set_enabled(Enabled::On); 128f4682712SMarri Devender Rao if (si->si_status != 0) 129f4682712SMarri Devender Rao { 130f4682712SMarri Devender Rao this->createCSRObject(Status::FAILURE); 131f4682712SMarri Devender Rao } 132f4682712SMarri Devender Rao else 133f4682712SMarri Devender Rao { 134f4682712SMarri Devender Rao this->createCSRObject(Status::SUCCESS); 135f4682712SMarri Devender Rao } 136f4682712SMarri Devender Rao }; 137f4682712SMarri Devender Rao try 138f4682712SMarri Devender Rao { 139f4682712SMarri Devender Rao sigset_t ss; 140f4682712SMarri Devender Rao if (sigemptyset(&ss) < 0) 141f4682712SMarri Devender Rao { 142f4682712SMarri Devender Rao log<level::ERR>("Unable to initialize signal set"); 143f4682712SMarri Devender Rao elog<InternalFailure>(); 144f4682712SMarri Devender Rao } 145f4682712SMarri Devender Rao if (sigaddset(&ss, SIGCHLD) < 0) 146f4682712SMarri Devender Rao { 147f4682712SMarri Devender Rao log<level::ERR>("Unable to add signal to signal set"); 148f4682712SMarri Devender Rao elog<InternalFailure>(); 149f4682712SMarri Devender Rao } 150f4682712SMarri Devender Rao 151f4682712SMarri Devender Rao // Block SIGCHLD first, so that the event loop can handle it 152f4682712SMarri Devender Rao if (sigprocmask(SIG_BLOCK, &ss, NULL) < 0) 153f4682712SMarri Devender Rao { 154f4682712SMarri Devender Rao log<level::ERR>("Unable to block signal"); 155f4682712SMarri Devender Rao elog<InternalFailure>(); 156f4682712SMarri Devender Rao } 157f4682712SMarri Devender Rao if (childPtr) 158f4682712SMarri Devender Rao { 159f4682712SMarri Devender Rao childPtr.reset(); 160f4682712SMarri Devender Rao } 161f4682712SMarri Devender Rao childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED, 162f4682712SMarri Devender Rao std::move(callback)); 163f4682712SMarri Devender Rao } 164f4682712SMarri Devender Rao catch (const InternalFailure& e) 165f4682712SMarri Devender Rao { 166f4682712SMarri Devender Rao commit<InternalFailure>(); 167f4682712SMarri Devender Rao } 168f4682712SMarri Devender Rao } 169f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 170f4682712SMarri Devender Rao return csrObjectPath; 171f4682712SMarri Devender Rao } 172f4682712SMarri Devender Rao 173f4682712SMarri Devender Rao void Manager::generateCSRHelper( 174f4682712SMarri Devender Rao std::vector<std::string> alternativeNames, std::string challengePassword, 175f4682712SMarri Devender Rao std::string city, std::string commonName, std::string contactPerson, 176f4682712SMarri Devender Rao std::string country, std::string email, std::string givenName, 177f4682712SMarri Devender Rao std::string initials, int64_t keyBitLength, std::string keyCurveId, 178f4682712SMarri Devender Rao std::string keyPairAlgorithm, std::vector<std::string> keyUsage, 179f4682712SMarri Devender Rao std::string organization, std::string organizationalUnit, std::string state, 180f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 181f4682712SMarri Devender Rao { 182f4682712SMarri Devender Rao int ret = 0; 183f4682712SMarri Devender Rao 184f4682712SMarri Devender Rao // set version of x509 req 185f4682712SMarri Devender Rao int nVersion = 1; 186f4682712SMarri Devender Rao // TODO: Issue#6 need to make version number configurable 187f4682712SMarri Devender Rao X509_REQ_Ptr x509Req(X509_REQ_new(), ::X509_REQ_free); 188f4682712SMarri Devender Rao ret = X509_REQ_set_version(x509Req.get(), nVersion); 189f4682712SMarri Devender Rao if (ret == 0) 190f4682712SMarri Devender Rao { 191f4682712SMarri Devender Rao log<level::ERR>("Error occured during X509_REQ_set_version call"); 192f4682712SMarri Devender Rao elog<InternalFailure>(); 193f4682712SMarri Devender Rao } 194f4682712SMarri Devender Rao 195f4682712SMarri Devender Rao // set subject of x509 req 196f4682712SMarri Devender Rao X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get()); 197f4682712SMarri Devender Rao 198f4682712SMarri Devender Rao if (!alternativeNames.empty()) 199f4682712SMarri Devender Rao { 200f4682712SMarri Devender Rao for (auto& name : alternativeNames) 201f4682712SMarri Devender Rao { 202f4682712SMarri Devender Rao addEntry(x509Name, "subjectAltName", name); 203f4682712SMarri Devender Rao } 204f4682712SMarri Devender Rao } 205f4682712SMarri Devender Rao addEntry(x509Name, "challengePassword", challengePassword); 206f4682712SMarri Devender Rao addEntry(x509Name, "L", city); 207f4682712SMarri Devender Rao addEntry(x509Name, "CN", commonName); 208f4682712SMarri Devender Rao addEntry(x509Name, "name", contactPerson); 209f4682712SMarri Devender Rao addEntry(x509Name, "C", country); 210f4682712SMarri Devender Rao addEntry(x509Name, "emailAddress", email); 211f4682712SMarri Devender Rao addEntry(x509Name, "GN", givenName); 212f4682712SMarri Devender Rao addEntry(x509Name, "initials", initials); 213f4682712SMarri Devender Rao addEntry(x509Name, "algorithm", keyPairAlgorithm); 214f4682712SMarri Devender Rao if (!keyUsage.empty()) 215f4682712SMarri Devender Rao { 216f4682712SMarri Devender Rao for (auto& usage : keyUsage) 217f4682712SMarri Devender Rao { 218f4682712SMarri Devender Rao addEntry(x509Name, "keyUsage", usage); 219f4682712SMarri Devender Rao } 220f4682712SMarri Devender Rao } 221f4682712SMarri Devender Rao addEntry(x509Name, "O", organization); 222f4682712SMarri Devender Rao addEntry(x509Name, "ST", state); 223f4682712SMarri Devender Rao addEntry(x509Name, "SN", surname); 224f4682712SMarri Devender Rao addEntry(x509Name, "unstructuredName", unstructuredName); 225f4682712SMarri Devender Rao 226*8a09b52aSRamesh Iyyar EVP_PKEY_Ptr pKey(nullptr, ::EVP_PKEY_free); 227*8a09b52aSRamesh Iyyar 228*8a09b52aSRamesh Iyyar log<level::INFO>("Given Key pair algorithm", 229*8a09b52aSRamesh Iyyar entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str())); 230*8a09b52aSRamesh Iyyar 231*8a09b52aSRamesh Iyyar // Used EC algorithm as default if user did not give algorithm type. 232*8a09b52aSRamesh Iyyar if (keyPairAlgorithm == "RSA") 233*8a09b52aSRamesh Iyyar pKey = std::move(generateRSAKeyPair(keyBitLength)); 234*8a09b52aSRamesh Iyyar else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty())) 235*8a09b52aSRamesh Iyyar pKey = std::move(generateECKeyPair(keyCurveId)); 236*8a09b52aSRamesh Iyyar else 237*8a09b52aSRamesh Iyyar { 238*8a09b52aSRamesh Iyyar using InvalidArgument = 239*8a09b52aSRamesh Iyyar sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument; 240*8a09b52aSRamesh Iyyar using Argument = xyz::openbmc_project::Common::InvalidArgument; 241*8a09b52aSRamesh Iyyar 242*8a09b52aSRamesh Iyyar log<level::ERR>("Given Key pair algorithm is not supported. Supporting " 243*8a09b52aSRamesh Iyyar "RSA and EC only"); 244*8a09b52aSRamesh Iyyar elog<InvalidArgument>( 245*8a09b52aSRamesh Iyyar Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"), 246*8a09b52aSRamesh Iyyar Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str())); 247*8a09b52aSRamesh Iyyar } 248*8a09b52aSRamesh Iyyar 249*8a09b52aSRamesh Iyyar ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get()); 250*8a09b52aSRamesh Iyyar if (ret == 0) 251*8a09b52aSRamesh Iyyar { 252*8a09b52aSRamesh Iyyar log<level::ERR>("Error occured while setting Public key"); 253*8a09b52aSRamesh Iyyar elog<InternalFailure>(); 254*8a09b52aSRamesh Iyyar } 255*8a09b52aSRamesh Iyyar 256*8a09b52aSRamesh Iyyar // Write private key to file 257*8a09b52aSRamesh Iyyar writePrivateKey(pKey); 258f4682712SMarri Devender Rao 259f4682712SMarri Devender Rao // set sign key of x509 req 260f4682712SMarri Devender Rao ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256()); 261*8a09b52aSRamesh Iyyar if (ret == 0) 262f4682712SMarri Devender Rao { 263f4682712SMarri Devender Rao log<level::ERR>("Error occured while signing key of x509"); 264f4682712SMarri Devender Rao elog<InternalFailure>(); 265f4682712SMarri Devender Rao } 266*8a09b52aSRamesh Iyyar 267f4682712SMarri Devender Rao log<level::INFO>("Writing CSR to file"); 268f4682712SMarri Devender Rao std::string path = fs::path(certInstallPath).parent_path(); 269f4682712SMarri Devender Rao std::string csrFilePath = path + '/' + CSR_FILE_NAME; 270f4682712SMarri Devender Rao writeCSR(csrFilePath, x509Req); 271f4682712SMarri Devender Rao } 272f4682712SMarri Devender Rao 273*8a09b52aSRamesh Iyyar EVP_PKEY_Ptr Manager::generateRSAKeyPair(const int64_t keyBitLength) 274f4682712SMarri Devender Rao { 275f4682712SMarri Devender Rao int ret = 0; 276f4682712SMarri Devender Rao // generate rsa key 277f4682712SMarri Devender Rao BIGNUM_Ptr bne(BN_new(), ::BN_free); 278f4682712SMarri Devender Rao ret = BN_set_word(bne.get(), RSA_F4); 279f4682712SMarri Devender Rao if (ret == 0) 280f4682712SMarri Devender Rao { 281f4682712SMarri Devender Rao log<level::ERR>("Error occured during BN_set_word call"); 282f4682712SMarri Devender Rao elog<InternalFailure>(); 283f4682712SMarri Devender Rao } 284f4682712SMarri Devender Rao 285*8a09b52aSRamesh Iyyar int64_t keyBitLen = keyBitLength; 286f4682712SMarri Devender Rao // set keybit length to default value if not set 287*8a09b52aSRamesh Iyyar if (keyBitLen <= 0) 288f4682712SMarri Devender Rao { 289*8a09b52aSRamesh Iyyar constexpr auto DEFAULT_KEYBITLENGTH = 2048; 290*8a09b52aSRamesh Iyyar log<level::INFO>( 291*8a09b52aSRamesh Iyyar "KeyBitLength is not given.Hence, using default KeyBitLength", 292*8a09b52aSRamesh Iyyar entry("DEFAULTKEYBITLENGTH=%d", DEFAULT_KEYBITLENGTH)); 293*8a09b52aSRamesh Iyyar keyBitLen = DEFAULT_KEYBITLENGTH; 294f4682712SMarri Devender Rao } 295f4682712SMarri Devender Rao RSA* rsa = RSA_new(); 296*8a09b52aSRamesh Iyyar ret = RSA_generate_key_ex(rsa, keyBitLen, bne.get(), NULL); 297f4682712SMarri Devender Rao if (ret != 1) 298f4682712SMarri Devender Rao { 299f4682712SMarri Devender Rao free(rsa); 300f4682712SMarri Devender Rao log<level::ERR>("Error occured during RSA_generate_key_ex call", 301*8a09b52aSRamesh Iyyar entry("KEYBITLENGTH=%PRIu64", keyBitLen)); 302f4682712SMarri Devender Rao elog<InternalFailure>(); 303f4682712SMarri Devender Rao } 304f4682712SMarri Devender Rao 305f4682712SMarri Devender Rao // set public key of x509 req 306f4682712SMarri Devender Rao EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 307*8a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_RSA(pKey.get(), rsa); 308f4682712SMarri Devender Rao if (ret == 0) 309f4682712SMarri Devender Rao { 310*8a09b52aSRamesh Iyyar free(rsa); 311*8a09b52aSRamesh Iyyar log<level::ERR>("Error occured during assign rsa key into EVP"); 312f4682712SMarri Devender Rao elog<InternalFailure>(); 313f4682712SMarri Devender Rao } 314f4682712SMarri Devender Rao 315*8a09b52aSRamesh Iyyar return pKey; 316*8a09b52aSRamesh Iyyar } 317*8a09b52aSRamesh Iyyar 318*8a09b52aSRamesh Iyyar EVP_PKEY_Ptr Manager::generateECKeyPair(const std::string& curveId) 319*8a09b52aSRamesh Iyyar { 320*8a09b52aSRamesh Iyyar std::string curId(curveId); 321*8a09b52aSRamesh Iyyar 322*8a09b52aSRamesh Iyyar if (curId.empty()) 323*8a09b52aSRamesh Iyyar { 324*8a09b52aSRamesh Iyyar // secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349 325*8a09b52aSRamesh Iyyar constexpr auto DEFAULT_KEYCURVEID = "secp224r1"; 326*8a09b52aSRamesh Iyyar log<level::INFO>( 327*8a09b52aSRamesh Iyyar "KeyCurveId is not given. Hence using default curve id", 328*8a09b52aSRamesh Iyyar entry("DEFAULTKEYCURVEID=%s", DEFAULT_KEYCURVEID)); 329*8a09b52aSRamesh Iyyar curId = DEFAULT_KEYCURVEID; 330*8a09b52aSRamesh Iyyar } 331*8a09b52aSRamesh Iyyar 332*8a09b52aSRamesh Iyyar int ecGrp = OBJ_txt2nid(curId.c_str()); 333*8a09b52aSRamesh Iyyar 334*8a09b52aSRamesh Iyyar if (ecGrp == NID_undef) 335*8a09b52aSRamesh Iyyar { 336*8a09b52aSRamesh Iyyar log<level::ERR>( 337*8a09b52aSRamesh Iyyar "Error occured during convert the curve id string format into NID", 338*8a09b52aSRamesh Iyyar entry("KEYCURVEID=%s", curId.c_str())); 339*8a09b52aSRamesh Iyyar elog<InternalFailure>(); 340*8a09b52aSRamesh Iyyar } 341*8a09b52aSRamesh Iyyar 342*8a09b52aSRamesh Iyyar EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp); 343*8a09b52aSRamesh Iyyar 344*8a09b52aSRamesh Iyyar if (ecKey == NULL) 345*8a09b52aSRamesh Iyyar { 346*8a09b52aSRamesh Iyyar log<level::ERR>( 347*8a09b52aSRamesh Iyyar "Error occured during create the EC_Key object from NID", 348*8a09b52aSRamesh Iyyar entry("ECGROUP=%d", ecGrp)); 349*8a09b52aSRamesh Iyyar elog<InternalFailure>(); 350*8a09b52aSRamesh Iyyar } 351*8a09b52aSRamesh Iyyar 352*8a09b52aSRamesh Iyyar // If you want to save a key and later load it with 353*8a09b52aSRamesh Iyyar // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE 354*8a09b52aSRamesh Iyyar // flag on the key. 355*8a09b52aSRamesh Iyyar EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE); 356*8a09b52aSRamesh Iyyar 357*8a09b52aSRamesh Iyyar int ret = EC_KEY_generate_key(ecKey); 358*8a09b52aSRamesh Iyyar 359*8a09b52aSRamesh Iyyar if (ret == 0) 360*8a09b52aSRamesh Iyyar { 361*8a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 362*8a09b52aSRamesh Iyyar log<level::ERR>("Error occured during generate EC key"); 363*8a09b52aSRamesh Iyyar elog<InternalFailure>(); 364*8a09b52aSRamesh Iyyar } 365*8a09b52aSRamesh Iyyar 366*8a09b52aSRamesh Iyyar EVP_PKEY_Ptr pKey(EVP_PKEY_new(), ::EVP_PKEY_free); 367*8a09b52aSRamesh Iyyar ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey); 368*8a09b52aSRamesh Iyyar if (ret == 0) 369*8a09b52aSRamesh Iyyar { 370*8a09b52aSRamesh Iyyar EC_KEY_free(ecKey); 371*8a09b52aSRamesh Iyyar log<level::ERR>("Error occured during assign EC Key into EVP"); 372*8a09b52aSRamesh Iyyar elog<InternalFailure>(); 373*8a09b52aSRamesh Iyyar } 374*8a09b52aSRamesh Iyyar 375*8a09b52aSRamesh Iyyar return pKey; 376*8a09b52aSRamesh Iyyar } 377*8a09b52aSRamesh Iyyar 378*8a09b52aSRamesh Iyyar void Manager::writePrivateKey(const EVP_PKEY_Ptr& pKey) 379*8a09b52aSRamesh Iyyar { 380*8a09b52aSRamesh Iyyar log<level::INFO>("Writing private key to file"); 381f4682712SMarri Devender Rao // write private key to file 382f4682712SMarri Devender Rao std::string path = fs::path(certInstallPath).parent_path(); 383f4682712SMarri Devender Rao std::string privKeyPath = path + '/' + PRIV_KEY_FILE_NAME; 384f4682712SMarri Devender Rao 385f4682712SMarri Devender Rao FILE* fp = std::fopen(privKeyPath.c_str(), "w"); 386f4682712SMarri Devender Rao if (fp == NULL) 387f4682712SMarri Devender Rao { 388f4682712SMarri Devender Rao log<level::ERR>("Error occured creating private key file"); 389f4682712SMarri Devender Rao elog<InternalFailure>(); 390f4682712SMarri Devender Rao } 391*8a09b52aSRamesh Iyyar int ret = PEM_write_PrivateKey(fp, pKey.get(), NULL, NULL, 0, 0, NULL); 392f4682712SMarri Devender Rao std::fclose(fp); 393f4682712SMarri Devender Rao if (ret == 0) 394f4682712SMarri Devender Rao { 395f4682712SMarri Devender Rao log<level::ERR>("Error occured while writing private key to file"); 396f4682712SMarri Devender Rao elog<InternalFailure>(); 397f4682712SMarri Devender Rao } 398f4682712SMarri Devender Rao } 399f4682712SMarri Devender Rao 400f4682712SMarri Devender Rao void Manager::addEntry(X509_NAME* x509Name, const char* field, 401f4682712SMarri Devender Rao const std::string& bytes) 402f4682712SMarri Devender Rao { 403f4682712SMarri Devender Rao if (bytes.empty()) 404f4682712SMarri Devender Rao { 405f4682712SMarri Devender Rao return; 406f4682712SMarri Devender Rao } 407f4682712SMarri Devender Rao int ret = X509_NAME_add_entry_by_txt( 408f4682712SMarri Devender Rao x509Name, field, MBSTRING_ASC, 409f4682712SMarri Devender Rao reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0); 410f4682712SMarri Devender Rao if (ret != 1) 411f4682712SMarri Devender Rao { 412f4682712SMarri Devender Rao log<level::ERR>("Unable to set entry", entry("FIELD=%s", field), 413f4682712SMarri Devender Rao entry("VALUE=%s", bytes.c_str())); 414f4682712SMarri Devender Rao elog<InternalFailure>(); 415f4682712SMarri Devender Rao } 416f4682712SMarri Devender Rao } 417f4682712SMarri Devender Rao 418f4682712SMarri Devender Rao void Manager::createCSRObject(const Status& status) 419f4682712SMarri Devender Rao { 420f4682712SMarri Devender Rao if (csrPtr) 421f4682712SMarri Devender Rao { 422f4682712SMarri Devender Rao csrPtr.reset(nullptr); 423f4682712SMarri Devender Rao } 424f4682712SMarri Devender Rao auto csrObjectPath = objectPath + '/' + "csr"; 425f4682712SMarri Devender Rao csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(), 426f4682712SMarri Devender Rao certInstallPath.c_str(), status); 427f4682712SMarri Devender Rao } 428f4682712SMarri Devender Rao 429f4682712SMarri Devender Rao void Manager::writeCSR(const std::string& filePath, const X509_REQ_Ptr& x509Req) 430f4682712SMarri Devender Rao { 431f4682712SMarri Devender Rao if (fs::exists(filePath)) 432f4682712SMarri Devender Rao { 433f4682712SMarri Devender Rao log<level::INFO>("Removing the existing file", 434f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 435f4682712SMarri Devender Rao if (!fs::remove(filePath.c_str())) 436f4682712SMarri Devender Rao { 437f4682712SMarri Devender Rao log<level::ERR>("Unable to remove the file", 438f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 439f4682712SMarri Devender Rao elog<InternalFailure>(); 440f4682712SMarri Devender Rao } 441f4682712SMarri Devender Rao } 442f4682712SMarri Devender Rao 443f4682712SMarri Devender Rao FILE* fp = NULL; 444f4682712SMarri Devender Rao 445f4682712SMarri Devender Rao if ((fp = std::fopen(filePath.c_str(), "w")) == NULL) 446f4682712SMarri Devender Rao { 447f4682712SMarri Devender Rao log<level::ERR>("Error opening the file to write the CSR", 448f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 449f4682712SMarri Devender Rao elog<InternalFailure>(); 450f4682712SMarri Devender Rao } 451f4682712SMarri Devender Rao 452f4682712SMarri Devender Rao int rc = PEM_write_X509_REQ(fp, x509Req.get()); 453f4682712SMarri Devender Rao if (!rc) 454f4682712SMarri Devender Rao { 455f4682712SMarri Devender Rao log<level::ERR>("PEM write routine failed", 456f4682712SMarri Devender Rao entry("FILENAME=%s", filePath.c_str())); 457f4682712SMarri Devender Rao std::fclose(fp); 458f4682712SMarri Devender Rao elog<InternalFailure>(); 459f4682712SMarri Devender Rao } 460f4682712SMarri Devender Rao std::fclose(fp); 461f4682712SMarri Devender Rao } 462f4682712SMarri Devender Rao 463cfbc8dc8SJayanth Othayoth } // namespace certs 464cfbc8dc8SJayanth Othayoth } // namespace phosphor 465