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