xref: /openbmc/estoraged/src/estoraged.cpp (revision 15b63e12bdc3f3116fb841349dd4f1cd17a8398b)
12098dabeSJohn Wedig 
22098dabeSJohn Wedig #include "estoraged.hpp"
32098dabeSJohn Wedig 
459dffa63SJohn Edward Broadbent #include "cryptErase.hpp"
5b810c926SJohn Wedig #include "cryptsetupInterface.hpp"
67f2ab643SJohn Edward Broadbent #include "pattern.hpp"
7605085a6SJohn Edward Broadbent #include "sanitize.hpp"
8e6ffe704SJohn Edward Broadbent #include "verifyDriveGeometry.hpp"
94bc8a10cSJohn Edward Broadbent #include "zero.hpp"
104e13b0a1SJohn Edward Broadbent 
11b810c926SJohn Wedig #include <libcryptsetup.h>
12b810c926SJohn Wedig #include <openssl/rand.h>
13b810c926SJohn Wedig 
14b810c926SJohn Wedig #include <phosphor-logging/lg2.hpp>
1567a47446SJohn Wedig #include <sdbusplus/asio/object_server.hpp>
16972c3faaSJohn Wedig #include <xyz/openbmc_project/Common/error.hpp>
17b810c926SJohn Wedig 
1882897c35SEd Tanous #include <cstdlib>
19b810c926SJohn Wedig #include <filesystem>
202098dabeSJohn Wedig #include <iostream>
2167a47446SJohn Wedig #include <string>
22b810c926SJohn Wedig #include <string_view>
2367a47446SJohn Wedig #include <utility>
242098dabeSJohn Wedig #include <vector>
252098dabeSJohn Wedig 
262098dabeSJohn Wedig namespace estoraged
272098dabeSJohn Wedig {
282098dabeSJohn Wedig 
296c0d8ce1SJohn Wedig using Association = std::tuple<std::string, std::string, std::string>;
30972c3faaSJohn Wedig using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
31972c3faaSJohn Wedig using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest;
3291c1ec1bSJohn Edward Broadbent using sdbusplus::xyz::openbmc_project::Inventory::Item::server::Drive;
3367a47446SJohn Wedig using sdbusplus::xyz::openbmc_project::Inventory::Item::server::Volume;
34b810c926SJohn Wedig 
EStoraged(sdbusplus::asio::object_server & server,const std::string & configPath,const std::string & devPath,const std::string & luksName,uint64_t size,uint8_t lifeTime,const std::string & partNumber,const std::string & serialNumber,const std::string & locationCode,uint64_t eraseMaxGeometry,uint64_t eraseMinGeometry,const std::string & driveType,const std::string & driveProtocol,std::unique_ptr<CryptsetupInterface> cryptInterface,std::unique_ptr<FilesystemInterface> fsInterface)35*15b63e12SPatrick Williams EStoraged::EStoraged(
36*15b63e12SPatrick Williams     sdbusplus::asio::object_server& server, const std::string& configPath,
37*15b63e12SPatrick Williams     const std::string& devPath, const std::string& luksName, uint64_t size,
38b4838308SJohn Wedig     uint8_t lifeTime, const std::string& partNumber,
39*15b63e12SPatrick Williams     const std::string& serialNumber, const std::string& locationCode,
40*15b63e12SPatrick Williams     uint64_t eraseMaxGeometry, uint64_t eraseMinGeometry,
41*15b63e12SPatrick Williams     const std::string& driveType, const std::string& driveProtocol,
4267a47446SJohn Wedig     std::unique_ptr<CryptsetupInterface> cryptInterface,
4367a47446SJohn Wedig     std::unique_ptr<FilesystemInterface> fsInterface) :
44*15b63e12SPatrick Williams     devPath(devPath), containerName(luksName),
45*15b63e12SPatrick Williams     mountPoint("/mnt/" + luksName + "_fs"), eraseMaxGeometry(eraseMaxGeometry),
46*15b63e12SPatrick Williams     eraseMinGeometry(eraseMinGeometry), cryptIface(std::move(cryptInterface)),
47*15b63e12SPatrick Williams     fsIface(std::move(fsInterface)),
482443a021SJohn Wedig     cryptDevicePath(cryptIface->cryptGetDir() + "/" + luksName),
496771c691SJohn Edward Broadbent     objectServer(server)
5067a47446SJohn Wedig {
5167a47446SJohn Wedig     /* Get the filename of the device (without "/dev/"). */
5267a47446SJohn Wedig     std::string deviceName = std::filesystem::path(devPath).filename().string();
5367a47446SJohn Wedig     /* DBus object path */
54*15b63e12SPatrick Williams     std::string objectPath =
55*15b63e12SPatrick Williams         "/xyz/openbmc_project/inventory/storage/" + deviceName;
5667a47446SJohn Wedig 
5767a47446SJohn Wedig     /* Add Volume interface. */
5867a47446SJohn Wedig     volumeInterface = objectServer.add_interface(
596c0d8ce1SJohn Wedig         objectPath, "xyz.openbmc_project.Inventory.Item.Volume");
6067a47446SJohn Wedig     volumeInterface->register_method(
6167a47446SJohn Wedig         "FormatLuks", [this](const std::vector<uint8_t>& password,
6267a47446SJohn Wedig                              Volume::FilesystemType type) {
6367a47446SJohn Wedig             this->formatLuks(password, type);
6467a47446SJohn Wedig         });
65ff1b64f0SPatrick Williams     volumeInterface->register_method(
66ff1b64f0SPatrick Williams         "Erase",
67ff1b64f0SPatrick Williams         [this](Volume::EraseMethod eraseType) { this->erase(eraseType); });
6867a47446SJohn Wedig     volumeInterface->register_method("Lock", [this]() { this->lock(); });
69ff1b64f0SPatrick Williams     volumeInterface->register_method(
70ff1b64f0SPatrick Williams         "Unlock",
71ff1b64f0SPatrick Williams         [this](std::vector<uint8_t>& password) { this->unlock(password); });
7267a47446SJohn Wedig     volumeInterface->register_method(
7367a47446SJohn Wedig         "ChangePassword", [this](const std::vector<uint8_t>& oldPassword,
7467a47446SJohn Wedig                                  const std::vector<uint8_t>& newPassword) {
7567a47446SJohn Wedig             this->changePassword(oldPassword, newPassword);
7667a47446SJohn Wedig         });
7767a47446SJohn Wedig     volumeInterface->register_property_r(
7867a47446SJohn Wedig         "Locked", lockedProperty, sdbusplus::vtable::property_::emits_change,
7967a47446SJohn Wedig         [this](bool& value) {
8067a47446SJohn Wedig             value = this->isLocked();
8167a47446SJohn Wedig             return value;
8267a47446SJohn Wedig         });
8367a47446SJohn Wedig 
8467a47446SJohn Wedig     /* Add Drive interface. */
8567a47446SJohn Wedig     driveInterface = objectServer.add_interface(
866c0d8ce1SJohn Wedig         objectPath, "xyz.openbmc_project.Inventory.Item.Drive");
8767a47446SJohn Wedig     driveInterface->register_property("Capacity", size);
885d799bb9SJohn Edward Broadbent     driveInterface->register_property("PredictedMediaLifeLeftPercent",
895d799bb9SJohn Edward Broadbent                                       lifeTime);
90d7be42bdSJohn Wedig     driveInterface->register_property(
91d7be42bdSJohn Wedig         "Type",
92d7be42bdSJohn Wedig         "xyz.openbmc_project.Inventory.Item.Drive.DriveType." + driveType);
93c0d66eb7SJohn Wedig     driveInterface->register_property(
94c0d66eb7SJohn Wedig         "Protocol", "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol." +
95c0d66eb7SJohn Wedig                         driveProtocol);
9614aee774SJohn Edward Broadbent     /* This registers the Locked property for the Drives interface.
9714aee774SJohn Edward Broadbent      * Now it is the same as the volume Locked property */
9814aee774SJohn Edward Broadbent     driveInterface->register_property_r(
9914aee774SJohn Edward Broadbent         "Locked", lockedProperty, sdbusplus::vtable::property_::emits_change,
10014aee774SJohn Edward Broadbent         [this](bool& value) {
10114aee774SJohn Edward Broadbent             value = this->isLocked();
10214aee774SJohn Edward Broadbent             return value;
10314aee774SJohn Edward Broadbent         });
10467a47446SJohn Wedig 
10591c1ec1bSJohn Edward Broadbent     driveInterface->register_property_r(
10691c1ec1bSJohn Edward Broadbent         "EncryptionStatus", encryptionStatus,
10791c1ec1bSJohn Edward Broadbent         sdbusplus::vtable::property_::emits_change,
10891c1ec1bSJohn Edward Broadbent         [this](Drive::DriveEncryptionState& value) {
10991c1ec1bSJohn Edward Broadbent             value = this->findEncryptionStatus();
11091c1ec1bSJohn Edward Broadbent             return value;
11191c1ec1bSJohn Edward Broadbent         });
11291c1ec1bSJohn Edward Broadbent 
11349796415SJohn Edward Broadbent     embeddedLocationInterface = objectServer.add_interface(
11449796415SJohn Edward Broadbent         objectPath, "xyz.openbmc_project.Inventory.Connector.Embedded");
115740e94bdSJohn Edward Broadbent 
11619825057SRahul Kapoor     if (!locationCode.empty())
11719825057SRahul Kapoor     {
11819825057SRahul Kapoor         locationCodeInterface = objectServer.add_interface(
11919825057SRahul Kapoor             objectPath, "xyz.openbmc_project.Inventory.Decorator.LocationCode");
12019825057SRahul Kapoor         locationCodeInterface->register_property("LocationCode", locationCode);
12119825057SRahul Kapoor         locationCodeInterface->initialize();
12219825057SRahul Kapoor     }
12319825057SRahul Kapoor 
124b4838308SJohn Wedig     /* Add Asset interface. */
125b4838308SJohn Wedig     assetInterface = objectServer.add_interface(
126b4838308SJohn Wedig         objectPath, "xyz.openbmc_project.Inventory.Decorator.Asset");
127b4838308SJohn Wedig     assetInterface->register_property("PartNumber", partNumber);
128b4838308SJohn Wedig     assetInterface->register_property("SerialNumber", serialNumber);
129b4838308SJohn Wedig 
13067a47446SJohn Wedig     volumeInterface->initialize();
13167a47446SJohn Wedig     driveInterface->initialize();
13249796415SJohn Edward Broadbent     embeddedLocationInterface->initialize();
133b4838308SJohn Wedig     assetInterface->initialize();
1346c0d8ce1SJohn Wedig 
1356c0d8ce1SJohn Wedig     /* Set up the association between chassis and drive. */
1366c0d8ce1SJohn Wedig     association = objectServer.add_interface(
1376c0d8ce1SJohn Wedig         objectPath, "xyz.openbmc_project.Association.Definitions");
1386c0d8ce1SJohn Wedig 
1396c0d8ce1SJohn Wedig     std::vector<Association> associations;
1406c0d8ce1SJohn Wedig     associations.emplace_back("chassis", "drive",
1416c0d8ce1SJohn Wedig                               std::filesystem::path(configPath).parent_path());
1426c0d8ce1SJohn Wedig     association->register_property("Associations", associations);
1436c0d8ce1SJohn Wedig     association->initialize();
14467a47446SJohn Wedig }
14567a47446SJohn Wedig 
~EStoraged()14667a47446SJohn Wedig EStoraged::~EStoraged()
14767a47446SJohn Wedig {
14867a47446SJohn Wedig     objectServer.remove_interface(volumeInterface);
14967a47446SJohn Wedig     objectServer.remove_interface(driveInterface);
15049796415SJohn Edward Broadbent     objectServer.remove_interface(embeddedLocationInterface);
151b4838308SJohn Wedig     objectServer.remove_interface(assetInterface);
1526c0d8ce1SJohn Wedig     objectServer.remove_interface(association);
15319825057SRahul Kapoor 
15419825057SRahul Kapoor     if (locationCodeInterface != nullptr)
15519825057SRahul Kapoor     {
15619825057SRahul Kapoor         objectServer.remove_interface(locationCodeInterface);
15719825057SRahul Kapoor     }
15867a47446SJohn Wedig }
15967a47446SJohn Wedig 
formatLuks(const std::vector<uint8_t> & password,Volume::FilesystemType type)16067a47446SJohn Wedig void EStoraged::formatLuks(const std::vector<uint8_t>& password,
16167a47446SJohn Wedig                            Volume::FilesystemType type)
1622098dabeSJohn Wedig {
1634e13b0a1SJohn Edward Broadbent     std::string msg = "OpenBMC.0.1.DriveFormat";
1644e13b0a1SJohn Edward Broadbent     lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
165b810c926SJohn Wedig 
16667a47446SJohn Wedig     if (type != Volume::FilesystemType::ext4)
167972c3faaSJohn Wedig     {
168972c3faaSJohn Wedig         lg2::error("Only ext4 filesystems are supported currently",
169972c3faaSJohn Wedig                    "REDFISH_MESSAGE_ID", std::string("OpenBMC.0.1.FormatFail"));
170972c3faaSJohn Wedig         throw UnsupportedRequest();
171972c3faaSJohn Wedig     }
172972c3faaSJohn Wedig 
173b2c86be3SJohn Edward Broadbent     formatLuksDev(password);
174b2c86be3SJohn Edward Broadbent     activateLuksDev(password);
175b810c926SJohn Wedig 
176b810c926SJohn Wedig     createFilesystem();
177b810c926SJohn Wedig     mountFilesystem();
1782098dabeSJohn Wedig }
1792098dabeSJohn Wedig 
erase(Volume::EraseMethod inEraseMethod)18067a47446SJohn Wedig void EStoraged::erase(Volume::EraseMethod inEraseMethod)
1812098dabeSJohn Wedig {
1822098dabeSJohn Wedig     std::cerr << "Erasing encrypted eMMC" << std::endl;
183e6ffe704SJohn Edward Broadbent     lg2::info("Starting erase", "REDFISH_MESSAGE_ID",
184e6ffe704SJohn Edward Broadbent               std::string("OpenBMC.0.1.DriveErase"));
185e6ffe704SJohn Edward Broadbent     switch (inEraseMethod)
186e6ffe704SJohn Edward Broadbent     {
18767a47446SJohn Wedig         case Volume::EraseMethod::CryptoErase:
188e6ffe704SJohn Edward Broadbent         {
18959dffa63SJohn Edward Broadbent             CryptErase myCryptErase(devPath);
19059dffa63SJohn Edward Broadbent             myCryptErase.doErase();
191e6ffe704SJohn Edward Broadbent             break;
192e6ffe704SJohn Edward Broadbent         }
19367a47446SJohn Wedig         case Volume::EraseMethod::VerifyGeometry:
194e6ffe704SJohn Edward Broadbent         {
195e6ffe704SJohn Edward Broadbent             VerifyDriveGeometry myVerifyGeometry(devPath);
196043af59fSTom Tung             myVerifyGeometry.geometryOkay(eraseMaxGeometry, eraseMinGeometry);
197e6ffe704SJohn Edward Broadbent             break;
198e6ffe704SJohn Edward Broadbent         }
19967a47446SJohn Wedig         case Volume::EraseMethod::LogicalOverWrite:
200e6ffe704SJohn Edward Broadbent         {
2017f2ab643SJohn Edward Broadbent             Pattern myErasePattern(devPath);
202a6e3b99dSJohn Edward Broadbent             myErasePattern.writePattern();
203e6ffe704SJohn Edward Broadbent             break;
204e6ffe704SJohn Edward Broadbent         }
20567a47446SJohn Wedig         case Volume::EraseMethod::LogicalVerify:
206e6ffe704SJohn Edward Broadbent         {
2077f2ab643SJohn Edward Broadbent             Pattern myErasePattern(devPath);
208a6e3b99dSJohn Edward Broadbent             myErasePattern.verifyPattern();
209e6ffe704SJohn Edward Broadbent             break;
210e6ffe704SJohn Edward Broadbent         }
21167a47446SJohn Wedig         case Volume::EraseMethod::VendorSanitize:
212e6ffe704SJohn Edward Broadbent         {
213605085a6SJohn Edward Broadbent             Sanitize mySanitize(devPath);
214605085a6SJohn Edward Broadbent             mySanitize.doSanitize();
215e6ffe704SJohn Edward Broadbent             break;
216e6ffe704SJohn Edward Broadbent         }
21767a47446SJohn Wedig         case Volume::EraseMethod::ZeroOverWrite:
218e6ffe704SJohn Edward Broadbent         {
2194bc8a10cSJohn Edward Broadbent             Zero myZero(devPath);
220a6e3b99dSJohn Edward Broadbent             myZero.writeZero();
221e6ffe704SJohn Edward Broadbent             break;
222e6ffe704SJohn Edward Broadbent         }
22367a47446SJohn Wedig         case Volume::EraseMethod::ZeroVerify:
224e6ffe704SJohn Edward Broadbent         {
2254bc8a10cSJohn Edward Broadbent             Zero myZero(devPath);
226a6e3b99dSJohn Edward Broadbent             myZero.verifyZero();
227e6ffe704SJohn Edward Broadbent             break;
228e6ffe704SJohn Edward Broadbent         }
22967a47446SJohn Wedig         case Volume::EraseMethod::SecuredLocked:
230e6ffe704SJohn Edward Broadbent         {
23147cd7996SJohn Wedig             if (!isLocked())
232f59b7291SJohn Edward Broadbent             {
233f59b7291SJohn Edward Broadbent                 lock();
234f59b7291SJohn Edward Broadbent             }
235f59b7291SJohn Edward Broadbent             // TODO: implement hardware locking
236f59b7291SJohn Edward Broadbent             // Until that is done, we can lock using eStoraged::lock()
237e6ffe704SJohn Edward Broadbent             break;
238e6ffe704SJohn Edward Broadbent         }
239e6ffe704SJohn Edward Broadbent     }
2402098dabeSJohn Wedig }
2412098dabeSJohn Wedig 
lock()24282897c35SEd Tanous void EStoraged::lock()
2432098dabeSJohn Wedig {
2444e13b0a1SJohn Edward Broadbent     std::string msg = "OpenBMC.0.1.DriveLock";
2454e13b0a1SJohn Edward Broadbent     lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
246b810c926SJohn Wedig 
247b810c926SJohn Wedig     unmountFilesystem();
248b810c926SJohn Wedig     deactivateLuksDev();
2492098dabeSJohn Wedig }
2502098dabeSJohn Wedig 
unlock(std::vector<uint8_t> password)25182897c35SEd Tanous void EStoraged::unlock(std::vector<uint8_t> password)
2522098dabeSJohn Wedig {
2534e13b0a1SJohn Edward Broadbent     std::string msg = "OpenBMC.0.1.DriveUnlock";
2544e13b0a1SJohn Edward Broadbent     lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
255b810c926SJohn Wedig 
256b2c86be3SJohn Edward Broadbent     activateLuksDev(std::move(password));
257b810c926SJohn Wedig     mountFilesystem();
2582098dabeSJohn Wedig }
2592098dabeSJohn Wedig 
changePassword(const std::vector<uint8_t> & oldPassword,const std::vector<uint8_t> & newPassword)2608d5a3a07SJohn Wedig void EStoraged::changePassword(const std::vector<uint8_t>& oldPassword,
2618d5a3a07SJohn Wedig                                const std::vector<uint8_t>& newPassword)
2622098dabeSJohn Wedig {
263e6ffe704SJohn Edward Broadbent     lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
264e6ffe704SJohn Edward Broadbent               std::string("OpenBMC.0.1.DrivePasswordChanged"));
2658d5a3a07SJohn Wedig 
2668d5a3a07SJohn Wedig     CryptHandle cryptHandle = loadLuksHeader();
2678d5a3a07SJohn Wedig 
2688d5a3a07SJohn Wedig     int retval = cryptIface->cryptKeyslotChangeByPassphrase(
2698d5a3a07SJohn Wedig         cryptHandle.get(), CRYPT_ANY_SLOT, CRYPT_ANY_SLOT,
2708d5a3a07SJohn Wedig         reinterpret_cast<const char*>(oldPassword.data()), oldPassword.size(),
2718d5a3a07SJohn Wedig         reinterpret_cast<const char*>(newPassword.data()), newPassword.size());
2728d5a3a07SJohn Wedig     if (retval < 0)
2738d5a3a07SJohn Wedig     {
2748d5a3a07SJohn Wedig         lg2::error("Failed to change password", "REDFISH_MESSAGE_ID",
2758d5a3a07SJohn Wedig                    std::string("OpenBMC.0.1.DrivePasswordChangeFail"));
2768d5a3a07SJohn Wedig         throw InternalFailure();
2778d5a3a07SJohn Wedig     }
2788d5a3a07SJohn Wedig 
2798d5a3a07SJohn Wedig     lg2::info("Successfully changed password for {DEV}", "DEV", devPath,
2808d5a3a07SJohn Wedig               "REDFISH_MESSAGE_ID",
2818d5a3a07SJohn Wedig               std::string("OpenBMC.0.1.DrivePasswordChangeSuccess"));
2822098dabeSJohn Wedig }
2832098dabeSJohn Wedig 
isLocked() const28482897c35SEd Tanous bool EStoraged::isLocked() const
285b810c926SJohn Wedig {
2862443a021SJohn Wedig     /*
2872443a021SJohn Wedig      * Check if the mapped virtual device exists. If it exists, the LUKS volume
2882443a021SJohn Wedig      * is unlocked.
2892443a021SJohn Wedig      */
2902443a021SJohn Wedig     try
2912443a021SJohn Wedig     {
2922443a021SJohn Wedig         std::filesystem::path mappedDevicePath(cryptDevicePath);
2932443a021SJohn Wedig         return (std::filesystem::exists(mappedDevicePath) == false);
2942443a021SJohn Wedig     }
2952443a021SJohn Wedig     catch (const std::exception& e)
2962443a021SJohn Wedig     {
2972443a021SJohn Wedig         lg2::error("Failed to query locked status: {EXCEPT}", "EXCEPT",
2982443a021SJohn Wedig                    e.what(), "REDFISH_MESSAGE_ID",
2992443a021SJohn Wedig                    std::string("OpenBMC.0.1.IsLockedFail"));
3002443a021SJohn Wedig         /* If we couldn't query the filesystem path, assume unlocked. */
3012443a021SJohn Wedig         return false;
3022443a021SJohn Wedig     }
303b810c926SJohn Wedig }
304b810c926SJohn Wedig 
getMountPoint() const30582897c35SEd Tanous std::string_view EStoraged::getMountPoint() const
306b810c926SJohn Wedig {
307b810c926SJohn Wedig     return mountPoint;
308b810c926SJohn Wedig }
309b810c926SJohn Wedig 
formatLuksDev(std::vector<uint8_t> password)310b2c86be3SJohn Edward Broadbent void EStoraged::formatLuksDev(std::vector<uint8_t> password)
311b810c926SJohn Wedig {
312b810c926SJohn Wedig     lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
313b810c926SJohn Wedig               std::string("OpenBMC.0.1.FormatLuksDev"));
314b810c926SJohn Wedig 
315b810c926SJohn Wedig     /* Generate the volume key. */
316b810c926SJohn Wedig     const std::size_t keySize = 64;
317b810c926SJohn Wedig     std::vector<uint8_t> volumeKey(keySize);
318b810c926SJohn Wedig     if (RAND_bytes(volumeKey.data(), keySize) != 1)
319b810c926SJohn Wedig     {
320b810c926SJohn Wedig         lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
321b810c926SJohn Wedig                    std::string("OpenBMC.0.1.FormatLuksDevFail"));
322972c3faaSJohn Wedig         throw InternalFailure();
323b810c926SJohn Wedig     }
324b2c86be3SJohn Edward Broadbent 
325b2c86be3SJohn Edward Broadbent     /* Create the handle. */
326b2c86be3SJohn Edward Broadbent     CryptHandle cryptHandle(devPath);
327b2c86be3SJohn Edward Broadbent 
328b810c926SJohn Wedig     /* Format the LUKS encrypted device. */
329b2c86be3SJohn Edward Broadbent     int retval = cryptIface->cryptFormat(
330b2c86be3SJohn Edward Broadbent         cryptHandle.get(), CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
331b2c86be3SJohn Edward Broadbent         reinterpret_cast<const char*>(volumeKey.data()), volumeKey.size(),
332b2c86be3SJohn Edward Broadbent         nullptr);
333b810c926SJohn Wedig     if (retval < 0)
334b810c926SJohn Wedig     {
335b810c926SJohn Wedig         lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
336b810c926SJohn Wedig                    retval, "REDFISH_MESSAGE_ID",
337b810c926SJohn Wedig                    std::string("OpenBMC.0.1.FormatLuksDevFail"));
338972c3faaSJohn Wedig         throw InternalFailure();
339b810c926SJohn Wedig     }
340b810c926SJohn Wedig 
341b810c926SJohn Wedig     /* Set the password. */
342b810c926SJohn Wedig     retval = cryptIface->cryptKeyslotAddByVolumeKey(
343b2c86be3SJohn Edward Broadbent         cryptHandle.get(), CRYPT_ANY_SLOT, nullptr, 0,
344b810c926SJohn Wedig         reinterpret_cast<const char*>(password.data()), password.size());
345b810c926SJohn Wedig 
346b810c926SJohn Wedig     if (retval < 0)
347b810c926SJohn Wedig     {
348b810c926SJohn Wedig         lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
349b810c926SJohn Wedig                    std::string("OpenBMC.0.1.FormatLuksDevFail"));
350972c3faaSJohn Wedig         throw InternalFailure();
351b810c926SJohn Wedig     }
352b810c926SJohn Wedig 
353b810c926SJohn Wedig     lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
354b810c926SJohn Wedig               "REDFISH_MESSAGE_ID",
355b810c926SJohn Wedig               std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
356b810c926SJohn Wedig }
357b810c926SJohn Wedig 
loadLuksHeader()35891c1ec1bSJohn Edward Broadbent CryptHandle EStoraged::loadLuksHeader()
359b810c926SJohn Wedig {
360b2c86be3SJohn Edward Broadbent     CryptHandle cryptHandle(devPath);
361b2c86be3SJohn Edward Broadbent 
362b2c86be3SJohn Edward Broadbent     int retval = cryptIface->cryptLoad(cryptHandle.get(), CRYPT_LUKS2, nullptr);
363b810c926SJohn Wedig     if (retval < 0)
364b810c926SJohn Wedig     {
365b810c926SJohn Wedig         lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
366b810c926SJohn Wedig                    "REDFISH_MESSAGE_ID",
367b810c926SJohn Wedig                    std::string("OpenBMC.0.1.ActivateLuksDevFail"));
368972c3faaSJohn Wedig         throw InternalFailure();
369b810c926SJohn Wedig     }
37091c1ec1bSJohn Edward Broadbent     return cryptHandle;
37191c1ec1bSJohn Edward Broadbent }
372b810c926SJohn Wedig 
findEncryptionStatus()37391c1ec1bSJohn Edward Broadbent Drive::DriveEncryptionState EStoraged::findEncryptionStatus()
37491c1ec1bSJohn Edward Broadbent {
37591c1ec1bSJohn Edward Broadbent     try
37691c1ec1bSJohn Edward Broadbent     {
37791c1ec1bSJohn Edward Broadbent         loadLuksHeader();
37891c1ec1bSJohn Edward Broadbent         return Drive::DriveEncryptionState::Encrypted;
37991c1ec1bSJohn Edward Broadbent     }
38091c1ec1bSJohn Edward Broadbent     catch (...)
38191c1ec1bSJohn Edward Broadbent     {
3820cec4286SHao Zhou         return Drive::DriveEncryptionState::Unencrypted;
38391c1ec1bSJohn Edward Broadbent     }
38491c1ec1bSJohn Edward Broadbent }
38591c1ec1bSJohn Edward Broadbent 
activateLuksDev(std::vector<uint8_t> password)38691c1ec1bSJohn Edward Broadbent void EStoraged::activateLuksDev(std::vector<uint8_t> password)
38791c1ec1bSJohn Edward Broadbent {
38891c1ec1bSJohn Edward Broadbent     lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
38991c1ec1bSJohn Edward Broadbent               std::string("OpenBMC.0.1.ActivateLuksDev"));
39091c1ec1bSJohn Edward Broadbent 
39191c1ec1bSJohn Edward Broadbent     /* Create the handle. */
39291c1ec1bSJohn Edward Broadbent     CryptHandle cryptHandle = loadLuksHeader();
39391c1ec1bSJohn Edward Broadbent 
39491c1ec1bSJohn Edward Broadbent     int retval = cryptIface->cryptActivateByPassphrase(
395b2c86be3SJohn Edward Broadbent         cryptHandle.get(), containerName.c_str(), CRYPT_ANY_SLOT,
396b810c926SJohn Wedig         reinterpret_cast<const char*>(password.data()), password.size(), 0);
397b810c926SJohn Wedig 
398b810c926SJohn Wedig     if (retval < 0)
399b810c926SJohn Wedig     {
400b810c926SJohn Wedig         lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
401b810c926SJohn Wedig                    "REDFISH_MESSAGE_ID",
402b810c926SJohn Wedig                    std::string("OpenBMC.0.1.ActivateLuksDevFail"));
403972c3faaSJohn Wedig         throw InternalFailure();
404b810c926SJohn Wedig     }
405b810c926SJohn Wedig 
406b810c926SJohn Wedig     lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
407b810c926SJohn Wedig               "REDFISH_MESSAGE_ID",
408b810c926SJohn Wedig               std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
409b810c926SJohn Wedig }
410b810c926SJohn Wedig 
createFilesystem()41182897c35SEd Tanous void EStoraged::createFilesystem()
412b810c926SJohn Wedig {
413b810c926SJohn Wedig     /* Run the command to create the filesystem. */
4142443a021SJohn Wedig     int retval = fsIface->runMkfs(cryptDevicePath);
41582897c35SEd Tanous     if (retval != 0)
416b810c926SJohn Wedig     {
417b810c926SJohn Wedig         lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
418b810c926SJohn Wedig                    "REDFISH_MESSAGE_ID",
419b810c926SJohn Wedig                    std::string("OpenBMC.0.1.CreateFilesystemFail"));
420972c3faaSJohn Wedig         throw InternalFailure();
421b810c926SJohn Wedig     }
4222443a021SJohn Wedig     lg2::info("Successfully created filesystem for {CONTAINER}", "CONTAINER",
4232443a021SJohn Wedig               cryptDevicePath, "REDFISH_MESSAGE_ID",
424b810c926SJohn Wedig               std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
425b810c926SJohn Wedig }
426b810c926SJohn Wedig 
mountFilesystem()42782897c35SEd Tanous void EStoraged::mountFilesystem()
428b810c926SJohn Wedig {
429b17f8251SJohn Wedig     /*
430b17f8251SJohn Wedig      * Create directory for the filesystem, if it's not already present. It
431b17f8251SJohn Wedig      * might already exist if, for example, the BMC reboots after creating the
432b17f8251SJohn Wedig      * directory.
433b17f8251SJohn Wedig      */
434b17f8251SJohn Wedig     if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
435b17f8251SJohn Wedig     {
436b17f8251SJohn Wedig         bool success =
437b17f8251SJohn Wedig             fsIface->createDirectory(std::filesystem::path(mountPoint));
438b810c926SJohn Wedig         if (!success)
439b810c926SJohn Wedig         {
440b810c926SJohn Wedig             lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
441b810c926SJohn Wedig                        "REDFISH_MESSAGE_ID",
442b810c926SJohn Wedig                        std::string("OpenBMC.0.1.MountFilesystemFail"));
443972c3faaSJohn Wedig             throw InternalFailure();
444b810c926SJohn Wedig         }
445b17f8251SJohn Wedig     }
446b810c926SJohn Wedig 
447b810c926SJohn Wedig     /* Run the command to mount the filesystem. */
4482443a021SJohn Wedig     int retval = fsIface->doMount(cryptDevicePath.c_str(), mountPoint.c_str(),
449b810c926SJohn Wedig                                   "ext4", 0, nullptr);
45082897c35SEd Tanous     if (retval != 0)
451b810c926SJohn Wedig     {
452b810c926SJohn Wedig         lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
453b810c926SJohn Wedig                    "REDFISH_MESSAGE_ID",
454b810c926SJohn Wedig                    std::string("OpenBMC.0.1.MountFilesystemFail"));
455b810c926SJohn Wedig         bool removeSuccess =
456b810c926SJohn Wedig             fsIface->removeDirectory(std::filesystem::path(mountPoint));
457b810c926SJohn Wedig         if (!removeSuccess)
458b810c926SJohn Wedig         {
459b810c926SJohn Wedig             lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
460b810c926SJohn Wedig                        "REDFISH_MESSAGE_ID",
461b810c926SJohn Wedig                        std::string("OpenBMC.0.1.MountFilesystemFail"));
462b810c926SJohn Wedig         }
463972c3faaSJohn Wedig         throw InternalFailure();
464b810c926SJohn Wedig     }
465b810c926SJohn Wedig 
466b810c926SJohn Wedig     lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
467b810c926SJohn Wedig               "REDFISH_MESSAGE_ID",
468b810c926SJohn Wedig               std::string("OpenBMC.0.1.MountFilesystemSuccess"));
469b810c926SJohn Wedig }
470b810c926SJohn Wedig 
unmountFilesystem()47182897c35SEd Tanous void EStoraged::unmountFilesystem()
472b810c926SJohn Wedig {
473b810c926SJohn Wedig     int retval = fsIface->doUnmount(mountPoint.c_str());
47482897c35SEd Tanous     if (retval != 0)
475b810c926SJohn Wedig     {
476b810c926SJohn Wedig         lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
477b810c926SJohn Wedig                    "REDFISH_MESSAGE_ID",
478b810c926SJohn Wedig                    std::string("OpenBMC.0.1.UnmountFilesystemFail"));
479972c3faaSJohn Wedig         throw InternalFailure();
480b810c926SJohn Wedig     }
481b810c926SJohn Wedig 
482b810c926SJohn Wedig     /* Remove the mount point. */
483b810c926SJohn Wedig     bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
484b810c926SJohn Wedig     if (!success)
485b810c926SJohn Wedig     {
486b810c926SJohn Wedig         lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
487b810c926SJohn Wedig                    "REDFISH_MESSAGE_ID",
488b810c926SJohn Wedig                    std::string("OpenBMC.0.1.UnmountFilesystemFail"));
489972c3faaSJohn Wedig         throw InternalFailure();
490b810c926SJohn Wedig     }
491b810c926SJohn Wedig 
492b810c926SJohn Wedig     lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
493b810c926SJohn Wedig               "REDFISH_MESSAGE_ID",
494b810c926SJohn Wedig               std::string("OpenBMC.0.1.MountFilesystemSuccess"));
495b810c926SJohn Wedig }
496b810c926SJohn Wedig 
deactivateLuksDev()49782897c35SEd Tanous void EStoraged::deactivateLuksDev()
498b810c926SJohn Wedig {
499b810c926SJohn Wedig     lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
500b810c926SJohn Wedig               "REDFISH_MESSAGE_ID",
501b810c926SJohn Wedig               std::string("OpenBMC.0.1.DeactivateLuksDev"));
502b810c926SJohn Wedig 
503b810c926SJohn Wedig     int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
504b810c926SJohn Wedig     if (retval < 0)
505b810c926SJohn Wedig     {
506b810c926SJohn Wedig         lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
507b810c926SJohn Wedig                    retval, "REDFISH_MESSAGE_ID",
508b810c926SJohn Wedig                    std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
509972c3faaSJohn Wedig         throw InternalFailure();
510b810c926SJohn Wedig     }
511b810c926SJohn Wedig 
512b810c926SJohn Wedig     lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
513b810c926SJohn Wedig               "REDFISH_MESSAGE_ID",
514b810c926SJohn Wedig               std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
515b810c926SJohn Wedig }
516b810c926SJohn Wedig 
getCryptDevicePath() const5172443a021SJohn Wedig std::string_view EStoraged::getCryptDevicePath() const
51867a47446SJohn Wedig {
5192443a021SJohn Wedig     return cryptDevicePath;
52067a47446SJohn Wedig }
52167a47446SJohn Wedig 
5222098dabeSJohn Wedig } // namespace estoraged
523