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