1 #include "file_io_type_cert.hpp" 2 3 #include "common/utils.hpp" 4 5 #include <libpldm/base.h> 6 #include <libpldm/file_io.h> 7 #include <stdint.h> 8 9 #include <iostream> 10 11 namespace pldm 12 { 13 using namespace utils; 14 15 namespace responder 16 { 17 constexpr auto certObjPath = "/xyz/openbmc_project/certs/ca/entry/"; 18 constexpr auto certEntryIntf = "xyz.openbmc_project.Certs.Entry"; 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 << "CertHandler::writeFromMemory:file for type " << certType 31 << " doesn't exist\n"; 32 return PLDM_ERROR; 33 } 34 35 auto fd = std::get<0>(it->second); 36 auto& remSize = std::get<1>(it->second); 37 auto rc = transferFileData(fd, false, offset, length, address); 38 if (rc == PLDM_SUCCESS) 39 { 40 remSize -= length; 41 if (!remSize) 42 { 43 close(fd); 44 certMap.erase(it); 45 } 46 } 47 return rc; 48 } 49 50 int CertHandler::readIntoMemory(uint32_t offset, uint32_t& length, 51 uint64_t address, 52 oem_platform::Handler* /*oemPlatformHandler*/) 53 { 54 std::string filePath = certFilePath; 55 filePath += "CSR_" + std::to_string(fileHandle); 56 if (certType != PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 57 { 58 return PLDM_ERROR_INVALID_DATA; 59 } 60 auto rc = transferFileData(filePath.c_str(), true, offset, length, address); 61 fs::remove(filePath); 62 if (rc) 63 { 64 return PLDM_ERROR; 65 } 66 return PLDM_SUCCESS; 67 } 68 69 int CertHandler::read(uint32_t offset, uint32_t& length, Response& response, 70 oem_platform::Handler* /*oemPlatformHandler*/) 71 { 72 std::cout 73 << "CertHandler::read:Read file response for Sign CSR, file handle: " 74 << fileHandle << std::endl; 75 std::string filePath = certFilePath; 76 filePath += "CSR_" + std::to_string(fileHandle); 77 if (certType != PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 78 { 79 return PLDM_ERROR_INVALID_DATA; 80 } 81 auto rc = readFile(filePath.c_str(), offset, length, response); 82 fs::remove(filePath); 83 if (rc) 84 { 85 return PLDM_ERROR; 86 } 87 return PLDM_SUCCESS; 88 } 89 90 int CertHandler::write(const char* buffer, uint32_t offset, uint32_t& length, 91 oem_platform::Handler* /*oemPlatformHandler*/) 92 { 93 auto it = certMap.find(certType); 94 if (it == certMap.end()) 95 { 96 std::cerr << "CertHandler::write:file for type " << certType 97 << " doesn't exist\n"; 98 return PLDM_ERROR; 99 } 100 101 auto fd = std::get<0>(it->second); 102 int rc = lseek(fd, offset, SEEK_SET); 103 if (rc == -1) 104 { 105 std::cerr << "CertHandler::write:lseek failed, ERROR=" << errno 106 << ", OFFSET=" << offset << "\n"; 107 return PLDM_ERROR; 108 } 109 rc = ::write(fd, buffer, length); 110 if (rc == -1) 111 { 112 std::cerr << "CertHandler::write:file write failed, ERROR=" << errno 113 << ", LENGTH=" << length << ", OFFSET=" << offset << "\n"; 114 return PLDM_ERROR; 115 } 116 length = rc; 117 auto& remSize = std::get<1>(it->second); 118 remSize -= length; 119 if (!remSize) 120 { 121 close(fd); 122 certMap.erase(it); 123 } 124 125 if (certType == PLDM_FILE_TYPE_SIGNED_CERT) 126 { 127 constexpr auto certObjPath = "/xyz/openbmc_project/certs/ca/entry/"; 128 constexpr auto certEntryIntf = "xyz.openbmc_project.Certs.Entry"; 129 130 std::string filePath = certFilePath; 131 filePath += "ClientCert_" + std::to_string(fileHandle); 132 133 std::ifstream inFile; 134 inFile.open(filePath); 135 std::stringstream strStream; 136 strStream << inFile.rdbuf(); 137 std::string str = strStream.str(); 138 inFile.close(); 139 140 if (!str.empty()) 141 { 142 PropertyValue value{str}; 143 144 DBusMapping dbusMapping{certObjPath + std::to_string(fileHandle), 145 certEntryIntf, "ClientCertificate", 146 "string"}; 147 try 148 { 149 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 150 } 151 catch (const std::exception& e) 152 { 153 std::cerr 154 << "CertHandler::write:failed to set Client certificate, " 155 "ERROR=" 156 << e.what() << "\n"; 157 return PLDM_ERROR; 158 } 159 PropertyValue valueStatus{ 160 "xyz.openbmc_project.Certs.Entry.State.Complete"}; 161 DBusMapping dbusMappingStatus{certObjPath + 162 std::to_string(fileHandle), 163 certEntryIntf, "Status", "string"}; 164 try 165 { 166 std::cout 167 << "CertHandler::write:Client cert write, status: complete. File handle: " 168 << fileHandle << std::endl; 169 pldm::utils::DBusHandler().setDbusProperty(dbusMappingStatus, 170 valueStatus); 171 } 172 catch (const std::exception& e) 173 { 174 std::cerr 175 << "CertHandler::write:failed to set status property of certicate entry, " 176 "ERROR=" 177 << e.what() << "\n"; 178 return PLDM_ERROR; 179 } 180 fs::remove(filePath); 181 } 182 else 183 { 184 PropertyValue value{"xyz.openbmc_project.Certs.Entry.State.BadCSR"}; 185 DBusMapping dbusMapping{certObjPath + std::to_string(fileHandle), 186 certEntryIntf, "Status", "string"}; 187 try 188 { 189 std::cout 190 << "CertHandler::write:Client cert write, status: Bad CSR. File handle: " 191 << fileHandle << std::endl; 192 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 193 } 194 catch (const std::exception& e) 195 { 196 std::cerr 197 << "CertHandler::write:failed to set status property of certicate entry, " 198 "ERROR=" 199 << e.what() << "\n"; 200 return PLDM_ERROR; 201 } 202 } 203 } 204 return PLDM_SUCCESS; 205 } 206 207 int CertHandler::newFileAvailable(uint64_t length) 208 { 209 fs::create_directories(certFilePath); 210 fs::permissions(certFilePath, 211 fs::perms::others_read | fs::perms::owner_write); 212 int fileFd = -1; 213 int flags = O_WRONLY | O_CREAT | O_TRUNC; 214 std::string filePath = certFilePath; 215 216 if (certType == PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 217 { 218 return PLDM_ERROR_INVALID_DATA; 219 } 220 if (certType == PLDM_FILE_TYPE_SIGNED_CERT) 221 { 222 std::cout 223 << "CertHandler::newFileAvailable:new file available client cert file, file handle: " 224 << fileHandle << std::endl; 225 fileFd = open( 226 (filePath + "ClientCert_" + std::to_string(fileHandle)).c_str(), 227 flags, S_IRUSR | S_IWUSR); 228 } 229 else if (certType == PLDM_FILE_TYPE_ROOT_CERT) 230 { 231 fileFd = 232 open((filePath + "RootCert").c_str(), flags, S_IRUSR | S_IWUSR); 233 } 234 if (fileFd == -1) 235 { 236 std::cerr 237 << "CertHandler::newFileAvailable:failed to open file for type " 238 << certType << " ERROR=" << errno << "\n"; 239 return PLDM_ERROR; 240 } 241 certMap.emplace(certType, std::tuple(fileFd, length)); 242 return PLDM_SUCCESS; 243 } 244 245 int CertHandler::newFileAvailableWithMetaData(uint64_t length, 246 uint32_t metaDataValue1, 247 uint32_t /*metaDataValue2*/, 248 uint32_t /*metaDataValue3*/, 249 uint32_t /*metaDataValue4*/) 250 { 251 fs::create_directories(certFilePath); 252 fs::permissions(certFilePath, 253 fs::perms::others_read | fs::perms::owner_write); 254 int fileFd = -1; 255 int flags = O_WRONLY | O_CREAT | O_TRUNC; 256 std::string filePath = certFilePath; 257 258 if (certType == PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 259 { 260 return PLDM_ERROR_INVALID_DATA; 261 } 262 if (certType == PLDM_FILE_TYPE_SIGNED_CERT) 263 { 264 if (metaDataValue1 == PLDM_SUCCESS) 265 { 266 std::cerr 267 << "CertHandler::newFileAvailableWithMetaData:new file available client cert file, file handle: " 268 << fileHandle << std::endl; 269 fileFd = open( 270 (filePath + "ClientCert_" + std::to_string(fileHandle)).c_str(), 271 flags, S_IRUSR | S_IWUSR); 272 } 273 else if (metaDataValue1 == PLDM_INVALID_CERT_DATA) 274 { 275 std::cerr 276 << "newFileAvailableWithMetaData:client cert file Invalid data, file handle: " 277 << fileHandle << std::endl; 278 DBusMapping dbusMapping{certObjPath + std::to_string(fileHandle), 279 certEntryIntf, "Status", "string"}; 280 std::string status = "xyz.openbmc_project.Certs.Entry.State.BadCSR"; 281 PropertyValue value{status}; 282 try 283 { 284 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 285 } 286 catch (const std::exception& e) 287 { 288 std::cerr 289 << "newFileAvailableWithMetaData:Failed to set status property of certicate entry, " 290 "ERROR=" 291 << e.what() << "\n"; 292 return PLDM_ERROR; 293 } 294 } 295 } 296 else if (certType == PLDM_FILE_TYPE_ROOT_CERT) 297 { 298 fileFd = 299 open((filePath + "RootCert").c_str(), flags, S_IRUSR | S_IWUSR); 300 } 301 if (fileFd == -1) 302 { 303 std::cerr 304 << "newFileAvailableWithMetaData:failed to open file for type " 305 << certType << " ERROR=" << errno << "\n"; 306 return PLDM_ERROR; 307 } 308 certMap.emplace(certType, std::tuple(fileFd, length)); 309 return PLDM_SUCCESS; 310 } 311 312 int CertHandler::fileAckWithMetaData(uint8_t fileStatus, 313 uint32_t /*metaDataValue1*/, 314 uint32_t /*metaDataValue2*/, 315 uint32_t /*metaDataValue3*/, 316 uint32_t /*metaDataValue4*/) 317 { 318 if (certType == PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) 319 { 320 DBusMapping dbusMapping{certObjPath + std::to_string(fileHandle), 321 certEntryIntf, "Status", "string"}; 322 PropertyValue value = "xyz.openbmc_project.Certs.Entry.State.Pending"; 323 if (fileStatus == PLDM_ERROR_INVALID_DATA) 324 { 325 value = "xyz.openbmc_project.Certs.Entry.State.BadCSR"; 326 } 327 else if (fileStatus == PLDM_ERROR_NOT_READY) 328 { 329 value = "xyz.openbmc_project.Certs.Entry.State.Pending"; 330 } 331 try 332 { 333 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 334 } 335 catch (const std::exception& e) 336 { 337 std::cerr 338 << "CertHandler::fileAckWithMetaData:Failed to set status property of certicate entry, " 339 "ERROR=" 340 << e.what() << "\n"; 341 return PLDM_ERROR; 342 } 343 } 344 return PLDM_SUCCESS; 345 } 346 347 } // namespace responder 348 } // namespace pldm 349