blob: f6176e4cbfcfd455f74c2a23c0805d537dd60c7e [file] [log] [blame]
John Wedig2098dab2021-09-14 13:56:28 -07001
2#include "estoraged.hpp"
3
John Edward Broadbent59dffa62022-01-13 17:41:32 -08004#include "cryptErase.hpp"
John Wedigb810c922021-11-17 16:38:03 -08005#include "cryptsetupInterface.hpp"
John Edward Broadbent7f2ab642021-11-11 21:00:38 -08006#include "pattern.hpp"
John Edward Broadbent605085a2021-11-05 13:45:45 -07007#include "sanitize.hpp"
John Edward Broadbente6ffe702021-10-14 14:03:11 -07008#include "verifyDriveGeometry.hpp"
John Edward Broadbent4bc8a102021-12-30 16:11:49 -08009#include "zero.hpp"
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080010
John Wedigb810c922021-11-17 16:38:03 -080011#include <libcryptsetup.h>
12#include <openssl/rand.h>
John Wedigb810c922021-11-17 16:38:03 -080013
14#include <phosphor-logging/lg2.hpp>
John Wedig972c3fa2021-12-29 17:30:41 -080015#include <xyz/openbmc_project/Common/error.hpp>
John Wedigb810c922021-11-17 16:38:03 -080016
Ed Tanous82897c32022-02-21 14:11:59 -080017#include <cstdlib>
John Wedigb810c922021-11-17 16:38:03 -080018#include <filesystem>
John Wedig2098dab2021-09-14 13:56:28 -070019#include <iostream>
John Wedigb810c922021-11-17 16:38:03 -080020#include <string_view>
John Wedig2098dab2021-09-14 13:56:28 -070021#include <vector>
22
23namespace estoraged
24{
25
John Wedig972c3fa2021-12-29 17:30:41 -080026using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
27using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
28using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest;
John Wedigb810c922021-11-17 16:38:03 -080029
Ed Tanous82897c32022-02-21 14:11:59 -080030void EStoraged::formatLuks(std::vector<uint8_t> password, FilesystemType type)
John Wedig2098dab2021-09-14 13:56:28 -070031{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080032 std::string msg = "OpenBMC.0.1.DriveFormat";
33 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080034
John Wedig972c3fa2021-12-29 17:30:41 -080035 if (type != FilesystemType::ext4)
36 {
37 lg2::error("Only ext4 filesystems are supported currently",
38 "REDFISH_MESSAGE_ID", std::string("OpenBMC.0.1.FormatFail"));
39 throw UnsupportedRequest();
40 }
41
John Wedig6218dc52021-12-03 09:36:35 -080042 CryptHandle cryptHandle(devPath.c_str());
43 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -080044 {
45 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
46 std::string("OpenBMC.0.1.FormatFail"));
John Wedig972c3fa2021-12-29 17:30:41 -080047 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -080048 }
49
John Wedig6218dc52021-12-03 09:36:35 -080050 formatLuksDev(cryptHandle.get(), password);
51 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -080052
53 createFilesystem();
54 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -070055}
56
Ed Tanous82897c32022-02-21 14:11:59 -080057void EStoraged::erase(EraseMethod inEraseMethod)
John Wedig2098dab2021-09-14 13:56:28 -070058{
59 std::cerr << "Erasing encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -070060 lg2::info("Starting erase", "REDFISH_MESSAGE_ID",
61 std::string("OpenBMC.0.1.DriveErase"));
62 switch (inEraseMethod)
63 {
64 case EraseMethod::CryptoErase:
65 {
John Edward Broadbent59dffa62022-01-13 17:41:32 -080066 CryptErase myCryptErase(devPath);
67 myCryptErase.doErase();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070068 break;
69 }
70 case EraseMethod::VerifyGeometry:
71 {
72 VerifyDriveGeometry myVerifyGeometry(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070073 myVerifyGeometry.geometryOkay();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070074 break;
75 }
76 case EraseMethod::LogicalOverWrite:
77 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080078 Pattern myErasePattern(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070079 myErasePattern.writePattern();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070080 break;
81 }
82 case EraseMethod::LogicalVerify:
83 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080084 Pattern myErasePattern(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070085 myErasePattern.verifyPattern();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070086 break;
87 }
88 case EraseMethod::VendorSanitize:
89 {
John Edward Broadbent605085a2021-11-05 13:45:45 -070090 Sanitize mySanitize(devPath);
91 mySanitize.doSanitize();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070092 break;
93 }
94 case EraseMethod::ZeroOverWrite:
95 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -080096 Zero myZero(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070097 myZero.writeZero();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070098 break;
99 }
100 case EraseMethod::ZeroVerify:
101 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -0800102 Zero myZero(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700103 myZero.verifyZero();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700104 break;
105 }
106 case EraseMethod::SecuredLocked:
107 {
John Edward Broadbentf59b7292022-02-15 15:07:15 -0800108 if (isLocked())
109 {
110 lock();
111 }
112 // TODO: implement hardware locking
113 // Until that is done, we can lock using eStoraged::lock()
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700114 break;
115 }
116 }
John Wedig2098dab2021-09-14 13:56:28 -0700117}
118
Ed Tanous82897c32022-02-21 14:11:59 -0800119void EStoraged::lock()
John Wedig2098dab2021-09-14 13:56:28 -0700120{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800121 std::string msg = "OpenBMC.0.1.DriveLock";
122 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800123
124 unmountFilesystem();
125 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700126}
127
Ed Tanous82897c32022-02-21 14:11:59 -0800128void EStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700129{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800130 std::string msg = "OpenBMC.0.1.DriveUnlock";
131 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800132
John Wedig6218dc52021-12-03 09:36:35 -0800133 CryptHandle cryptHandle(devPath.c_str());
134 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800135 {
136 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
137 std::string("OpenBMC.0.1.UnlockFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800138 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800139 }
140
John Wedig6218dc52021-12-03 09:36:35 -0800141 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -0800142 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700143}
144
Ed Tanous82897c32022-02-21 14:11:59 -0800145void EStoraged::changePassword(std::vector<uint8_t> /*oldPassword*/,
146 std::vector<uint8_t> /*newPassword*/)
John Wedig2098dab2021-09-14 13:56:28 -0700147{
148 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700149 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
150 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700151}
152
Ed Tanous82897c32022-02-21 14:11:59 -0800153bool EStoraged::isLocked() const
John Wedigb810c922021-11-17 16:38:03 -0800154{
155 return locked();
156}
157
Ed Tanous82897c32022-02-21 14:11:59 -0800158std::string_view EStoraged::getMountPoint() const
John Wedigb810c922021-11-17 16:38:03 -0800159{
160 return mountPoint;
161}
162
Ed Tanous82897c32022-02-21 14:11:59 -0800163void EStoraged::formatLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800164 std::vector<uint8_t> password)
165{
166 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
167 std::string("OpenBMC.0.1.FormatLuksDev"));
168
169 /* Generate the volume key. */
170 const std::size_t keySize = 64;
171 std::vector<uint8_t> volumeKey(keySize);
172 if (RAND_bytes(volumeKey.data(), keySize) != 1)
173 {
174 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
175 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800176 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800177 }
178 /* Format the LUKS encrypted device. */
179 int retval =
180 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
181 reinterpret_cast<const char*>(volumeKey.data()),
182 volumeKey.size(), nullptr);
183 if (retval < 0)
184 {
185 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
186 retval, "REDFISH_MESSAGE_ID",
187 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800188 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800189 }
190
191 /* Device is now encrypted. */
192 locked(true);
193
194 /* Set the password. */
195 retval = cryptIface->cryptKeyslotAddByVolumeKey(
196 cd, CRYPT_ANY_SLOT, nullptr, 0,
197 reinterpret_cast<const char*>(password.data()), password.size());
198
199 if (retval < 0)
200 {
201 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
202 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800203 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800204 }
205
206 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
207 "REDFISH_MESSAGE_ID",
208 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
209}
210
Ed Tanous82897c32022-02-21 14:11:59 -0800211void EStoraged::activateLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800212 std::vector<uint8_t> password)
213{
214 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
215 std::string("OpenBMC.0.1.ActivateLuksDev"));
216
217 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
218 if (retval < 0)
219 {
220 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
221 "REDFISH_MESSAGE_ID",
222 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800223 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800224 }
225
226 retval = cryptIface->cryptActivateByPassphrase(
227 cd, containerName.c_str(), CRYPT_ANY_SLOT,
228 reinterpret_cast<const char*>(password.data()), password.size(), 0);
229
230 if (retval < 0)
231 {
232 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
233 "REDFISH_MESSAGE_ID",
234 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800235 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800236 }
237
238 /* Device is now unlocked. */
239 locked(false);
240
241 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
242 "REDFISH_MESSAGE_ID",
243 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
244}
245
Ed Tanous82897c32022-02-21 14:11:59 -0800246void EStoraged::createFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800247{
248 /* Run the command to create the filesystem. */
249 int retval = fsIface->runMkfs(containerName);
Ed Tanous82897c32022-02-21 14:11:59 -0800250 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800251 {
252 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
253 "REDFISH_MESSAGE_ID",
254 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800255 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800256 }
257 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
258 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
259 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
260}
261
Ed Tanous82897c32022-02-21 14:11:59 -0800262void EStoraged::mountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800263{
John Wedigb17f8252022-01-12 14:24:26 -0800264 /*
265 * Create directory for the filesystem, if it's not already present. It
266 * might already exist if, for example, the BMC reboots after creating the
267 * directory.
268 */
269 if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
John Wedigb810c922021-11-17 16:38:03 -0800270 {
John Wedigb17f8252022-01-12 14:24:26 -0800271 bool success =
272 fsIface->createDirectory(std::filesystem::path(mountPoint));
273 if (!success)
274 {
275 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
276 "REDFISH_MESSAGE_ID",
277 std::string("OpenBMC.0.1.MountFilesystemFail"));
278 throw InternalFailure();
279 }
John Wedigb810c922021-11-17 16:38:03 -0800280 }
281
282 /* Run the command to mount the filesystem. */
283 std::string luksContainer("/dev/mapper/" + containerName);
284 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
285 "ext4", 0, nullptr);
Ed Tanous82897c32022-02-21 14:11:59 -0800286 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800287 {
288 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
289 "REDFISH_MESSAGE_ID",
290 std::string("OpenBMC.0.1.MountFilesystemFail"));
291 bool removeSuccess =
292 fsIface->removeDirectory(std::filesystem::path(mountPoint));
293 if (!removeSuccess)
294 {
295 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
296 "REDFISH_MESSAGE_ID",
297 std::string("OpenBMC.0.1.MountFilesystemFail"));
298 }
John Wedig972c3fa2021-12-29 17:30:41 -0800299 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800300 }
301
302 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
303 "REDFISH_MESSAGE_ID",
304 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
305}
306
Ed Tanous82897c32022-02-21 14:11:59 -0800307void EStoraged::unmountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800308{
309 int retval = fsIface->doUnmount(mountPoint.c_str());
Ed Tanous82897c32022-02-21 14:11:59 -0800310 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800311 {
312 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
313 "REDFISH_MESSAGE_ID",
314 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800315 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800316 }
317
318 /* Remove the mount point. */
319 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
320 if (!success)
321 {
322 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
323 "REDFISH_MESSAGE_ID",
324 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800325 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800326 }
327
328 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
329 "REDFISH_MESSAGE_ID",
330 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
331}
332
Ed Tanous82897c32022-02-21 14:11:59 -0800333void EStoraged::deactivateLuksDev()
John Wedigb810c922021-11-17 16:38:03 -0800334{
335 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
336 "REDFISH_MESSAGE_ID",
337 std::string("OpenBMC.0.1.DeactivateLuksDev"));
338
339 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
340 if (retval < 0)
341 {
342 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
343 retval, "REDFISH_MESSAGE_ID",
344 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800345 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800346 }
347
348 /* Device is now locked. */
349 locked(true);
350
351 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
352 "REDFISH_MESSAGE_ID",
353 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
354}
355
John Wedig2098dab2021-09-14 13:56:28 -0700356} // namespace estoraged