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