1 #include "config.h"
2 
3 #include "csr.hpp"
4 
5 #include <openssl/pem.h>
6 
7 #include <filesystem>
8 #include <phosphor-logging/elog-errors.hpp>
9 #include <phosphor-logging/elog.hpp>
10 #include <xyz/openbmc_project/Certs/error.hpp>
11 #include <xyz/openbmc_project/Common/error.hpp>
12 
13 namespace phosphor::certs
14 {
15 
16 using ::phosphor::logging::elog;
17 using ::phosphor::logging::entry;
18 using ::phosphor::logging::level;
19 using ::phosphor::logging::log;
20 using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
21 namespace fs = std::filesystem;
22 
23 using X509ReqPtr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>;
24 using BIOPtr = std::unique_ptr<BIO, decltype(&::BIO_free_all)>;
25 
26 CSR::CSR(sdbusplus::bus::bus& bus, const char* path, std::string&& installPath,
27          const Status& status) :
28     internal::CSRInterface(bus, path, true),
29     objectPath(path), certInstallPath(std::move(installPath)), csrStatus(status)
30 {
31     // Emit deferred signal.
32     this->emit_object_added();
33 }
34 
35 std::string CSR::csr()
36 {
37     if (csrStatus == Status::FAILURE)
38     {
39         log<level::ERR>("Failure in Generating CSR");
40         elog<InternalFailure>();
41     }
42     fs::path csrFilePath = certInstallPath;
43     csrFilePath = csrFilePath.parent_path() / defaultCSRFileName;
44     if (!fs::exists(csrFilePath))
45     {
46         log<level::ERR>("CSR file doesn't exists",
47                         entry("FILENAME=%s", csrFilePath.c_str()));
48         elog<InternalFailure>();
49     }
50 
51     FILE* fp = std::fopen(csrFilePath.c_str(), "r");
52     X509ReqPtr x509Req(PEM_read_X509_REQ(fp, nullptr, nullptr, nullptr),
53                        ::X509_REQ_free);
54     if (x509Req == nullptr || fp == nullptr)
55     {
56         if (fp != nullptr)
57         {
58             std::fclose(fp);
59         }
60         log<level::ERR>("ERROR occurred while reading CSR file",
61                         entry("FILENAME=%s", csrFilePath.c_str()));
62         elog<InternalFailure>();
63     }
64     std::fclose(fp);
65 
66     BIOPtr bio(BIO_new(BIO_s_mem()), ::BIO_free_all);
67     int ret = PEM_write_bio_X509_REQ(bio.get(), x509Req.get());
68     if (ret <= 0)
69     {
70         log<level::ERR>("Error occurred while calling PEM_write_bio_X509_REQ");
71         elog<InternalFailure>();
72     }
73 
74     BUF_MEM* mem = nullptr;
75     BIO_get_mem_ptr(bio.get(), &mem);
76     std::string pem(mem->data, mem->length);
77     return pem;
78 }
79 
80 } // namespace phosphor::certs
81