pldm oem: implement certificate handler
This commit adds code to handle the ceritificate request and
certificate transfer between the host and bmc following pldm oem
file i/o protocol
Change-Id: I8095e0f5ad8c3c5cc796da1cfbe4bb9946af31cf
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/oem/ibm/libpldmresponder/file_io_type_cert.cpp b/oem/ibm/libpldmresponder/file_io_type_cert.cpp
new file mode 100644
index 0000000..aef3f4c
--- /dev/null
+++ b/oem/ibm/libpldmresponder/file_io_type_cert.cpp
@@ -0,0 +1,132 @@
+#include "file_io_type_cert.hpp"
+
+#include "utils.hpp"
+
+#include <stdint.h>
+
+#include <iostream>
+
+#include "libpldm/base.h"
+#include "oem/ibm/libpldm/file_io.h"
+
+namespace pldm
+{
+namespace responder
+{
+
+static constexpr auto csrFilePath = "/var/lib/bmcweb/CSR";
+static constexpr auto rootCertPath = "/var/lib/bmcweb/RootCert";
+static constexpr auto clientCertPath = "/var/lib/bmcweb/ClientCert";
+
+CertMap CertHandler::certMap;
+
+int CertHandler::writeFromMemory(uint32_t offset, uint32_t length,
+ uint64_t address)
+{
+ auto it = certMap.find(certType);
+ if (it == certMap.end())
+ {
+ std::cerr << "file for type " << certType << " doesn't exist\n";
+ return PLDM_ERROR;
+ }
+
+ auto fd = std::get<0>(it->second);
+ auto& remSize = std::get<1>(it->second);
+ auto rc = transferFileData(fd, false, offset, length, address);
+ if (rc == PLDM_SUCCESS)
+ {
+ remSize -= length;
+ if (!remSize)
+ {
+ close(fd);
+ certMap.erase(it);
+ }
+ }
+ return rc;
+}
+
+int CertHandler::readIntoMemory(uint32_t offset, uint32_t& length,
+ uint64_t address)
+{
+ if (certType != PLDM_FILE_TYPE_CERT_SIGNING_REQUEST)
+ {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+ return transferFileData(csrFilePath, true, offset, length, address);
+}
+
+int CertHandler::read(uint32_t offset, uint32_t& length, Response& response)
+{
+ if (certType != PLDM_FILE_TYPE_CERT_SIGNING_REQUEST)
+ {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+ return readFile(csrFilePath, offset, length, response);
+}
+
+int CertHandler::write(const char* buffer, uint32_t offset, uint32_t& length)
+{
+ auto it = certMap.find(certType);
+ if (it == certMap.end())
+ {
+ std::cerr << "file for type " << certType << " doesn't exist\n";
+ return PLDM_ERROR;
+ }
+
+ auto fd = std::get<0>(it->second);
+ int rc = lseek(fd, offset, SEEK_SET);
+ if (rc == -1)
+ {
+ std::cerr << "lseek failed, ERROR=" << errno << ", OFFSET=" << offset
+ << "\n";
+ return PLDM_ERROR;
+ }
+ rc = ::write(fd, buffer, length);
+ if (rc == -1)
+ {
+ std::cerr << "file write failed, ERROR=" << errno
+ << ", LENGTH=" << length << ", OFFSET=" << offset << "\n";
+ return PLDM_ERROR;
+ }
+ length = rc;
+ auto& remSize = std::get<1>(it->second);
+ remSize -= length;
+ if (!remSize)
+ {
+ close(fd);
+ certMap.erase(it);
+ }
+ return PLDM_SUCCESS;
+}
+
+int CertHandler::newFileAvailable(uint64_t length)
+{
+ static constexpr auto vmiCertPath = "/var/lib/bmcweb";
+ fs::create_directories(vmiCertPath);
+ int fileFd = -1;
+ int flags = O_WRONLY | O_CREAT | O_TRUNC;
+
+ if (certType == PLDM_FILE_TYPE_CERT_SIGNING_REQUEST)
+ {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+ if (certType == PLDM_FILE_TYPE_SIGNED_CERT)
+ {
+ fileFd = open(clientCertPath, flags);
+ }
+ else if (certType == PLDM_FILE_TYPE_ROOT_CERT)
+ {
+ fileFd = open(rootCertPath, flags);
+ }
+ if (fileFd == -1)
+ {
+ std::cerr << "failed to open file for type " << certType
+ << " ERROR=" << errno << "\n";
+ return PLDM_ERROR;
+ }
+ certMap.emplace(certType, std::tuple(fileFd, length));
+ return PLDM_SUCCESS;
+}
+
+} // namespace responder
+} // namespace pldm