1 #include "file_io_type_cert.hpp" 2 3 #include "libpldm/base.h" 4 #include "oem/ibm/libpldm/file_io.h" 5 6 #include "common/utils.hpp" 7 8 #include <stdint.h> 9 10 #include <iostream> 11 12 namespace pldm 13 { 14 using namespace utils; 15 16 namespace responder 17 { 18 19 static constexpr auto certFilePath = "/var/lib/ibm/bmcweb/"; 20 21 CertMap CertHandler::certMap; 22 23 int CertHandler::writeFromMemory(uint32_t offset, uint32_t length, 24 uint64_t address, 25 oem_platform::Handler* /*oemPlatformHandler*/) 26 { 27 auto it = certMap.find(certType); 28 if (it == certMap.end()) 29 { 30 std::cerr << "file for type " << certType << " doesn't exist\n"; 31 return PLDM_ERROR; 32 } 33 34 auto fd = std::get<0>(it->second); 35 auto& remSize = std::get<1>(it->second); 36 auto rc = transferFileData(fd, false, offset, length, address); 37 if (rc == PLDM_SUCCESS) 38 { 39 remSize -= length; 40 if (!remSize) 41 { 42 close(fd); 43 certMap.erase(it); 44 } 45 } 46 return rc; 47 } 48 49 int CertHandler::readIntoMemory(uint32_t offset, uint32_t& length, 50 uint64_t address, 51 oem_platform::Handler* /*oemPlatformHandler*/) 52 { 53 std::string filePath = certFilePath; 54 filePath += "CSR_" + std::to_string(fileHandle); 55 if (certType != PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 56 { 57 return PLDM_ERROR_INVALID_DATA; 58 } 59 auto rc = transferFileData(filePath.c_str(), true, offset, length, address); 60 fs::remove(filePath); 61 if (rc) 62 { 63 return PLDM_ERROR; 64 } 65 return PLDM_SUCCESS; 66 } 67 68 int CertHandler::read(uint32_t offset, uint32_t& length, Response& response, 69 oem_platform::Handler* /*oemPlatformHandler*/) 70 { 71 std::string filePath = certFilePath; 72 filePath += "CSR_" + std::to_string(fileHandle); 73 if (certType != PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 74 { 75 return PLDM_ERROR_INVALID_DATA; 76 } 77 auto rc = readFile(filePath.c_str(), offset, length, response); 78 fs::remove(filePath); 79 if (rc) 80 { 81 return PLDM_ERROR; 82 } 83 return PLDM_SUCCESS; 84 } 85 86 int CertHandler::write(const char* buffer, uint32_t offset, uint32_t& length, 87 oem_platform::Handler* /*oemPlatformHandler*/) 88 { 89 auto it = certMap.find(certType); 90 if (it == certMap.end()) 91 { 92 std::cerr << "file for type " << certType << " doesn't exist\n"; 93 return PLDM_ERROR; 94 } 95 96 auto fd = std::get<0>(it->second); 97 int rc = lseek(fd, offset, SEEK_SET); 98 if (rc == -1) 99 { 100 std::cerr << "lseek failed, ERROR=" << errno << ", OFFSET=" << offset 101 << "\n"; 102 return PLDM_ERROR; 103 } 104 rc = ::write(fd, buffer, length); 105 if (rc == -1) 106 { 107 std::cerr << "file write failed, ERROR=" << errno 108 << ", LENGTH=" << length << ", OFFSET=" << offset << "\n"; 109 return PLDM_ERROR; 110 } 111 length = rc; 112 auto& remSize = std::get<1>(it->second); 113 remSize -= length; 114 if (!remSize) 115 { 116 close(fd); 117 certMap.erase(it); 118 } 119 120 if (certType == PLDM_FILE_TYPE_SIGNED_CERT) 121 { 122 constexpr auto certObjPath = "/xyz/openbmc_project/certs/ca/entry/"; 123 constexpr auto certEntryIntf = "xyz.openbmc_project.Certs.Entry"; 124 125 std::string filePath = certFilePath; 126 filePath += "ClientCert_" + std::to_string(fileHandle); 127 128 std::ifstream inFile; 129 inFile.open(filePath); 130 std::stringstream strStream; 131 strStream << inFile.rdbuf(); 132 std::string str = strStream.str(); 133 inFile.close(); 134 135 if (!str.empty()) 136 { 137 PropertyValue value{str}; 138 139 DBusMapping dbusMapping{certObjPath + std::to_string(fileHandle), 140 certEntryIntf, "ClientCertificate", 141 "string"}; 142 try 143 { 144 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 145 } 146 catch (const std::exception& e) 147 { 148 std::cerr << "failed to set Client certificate, " 149 "ERROR=" 150 << e.what() << "\n"; 151 return PLDM_ERROR; 152 } 153 PropertyValue valueStatus{ 154 "xyz.openbmc_project.Certs.Entry.State.Complete"}; 155 DBusMapping dbusMappingStatus{certObjPath + 156 std::to_string(fileHandle), 157 certEntryIntf, "Status", "string"}; 158 try 159 { 160 pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, 161 valueStatus); 162 } 163 catch (const std::exception& e) 164 { 165 std::cerr 166 << "failed to set status property of certicate entry, " 167 "ERROR=" 168 << e.what() << "\n"; 169 return PLDM_ERROR; 170 } 171 fs::remove(filePath); 172 } 173 else 174 { 175 PropertyValue value{"xyz.openbmc_project.Certs.Entry.State.BadCSR"}; 176 DBusMapping dbusMapping{certObjPath + std::to_string(fileHandle), 177 certEntryIntf, "Status", "string"}; 178 try 179 { 180 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 181 } 182 catch (const std::exception& e) 183 { 184 std::cerr 185 << "failed to set status property of certicate entry, " 186 "ERROR=" 187 << e.what() << "\n"; 188 return PLDM_ERROR; 189 } 190 } 191 } 192 return PLDM_SUCCESS; 193 } 194 195 int CertHandler::newFileAvailable(uint64_t length) 196 { 197 fs::create_directories(certFilePath); 198 fs::permissions(certFilePath, 199 fs::perms::others_read | fs::perms::owner_write); 200 int fileFd = -1; 201 int flags = O_WRONLY | O_CREAT | O_TRUNC; 202 std::string filePath = certFilePath; 203 204 if (certType == PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 205 { 206 return PLDM_ERROR_INVALID_DATA; 207 } 208 if (certType == PLDM_FILE_TYPE_SIGNED_CERT) 209 { 210 fileFd = open( 211 (filePath + "ClientCert_" + std::to_string(fileHandle)).c_str(), 212 flags, S_IRUSR | S_IWUSR); 213 } 214 else if (certType == PLDM_FILE_TYPE_ROOT_CERT) 215 { 216 fileFd = 217 open((filePath + "RootCert").c_str(), flags, S_IRUSR | S_IWUSR); 218 } 219 if (fileFd == -1) 220 { 221 std::cerr << "failed to open file for type " << certType 222 << " ERROR=" << errno << "\n"; 223 return PLDM_ERROR; 224 } 225 certMap.emplace(certType, std::tuple(fileFd, length)); 226 return PLDM_SUCCESS; 227 } 228 229 } // namespace responder 230 } // namespace pldm 231