blob: b52a5f470072544e9b18aabae3af04d29bd8504b [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 Broadbente6ffe702021-10-14 14:03:11 -07007#include "verifyDriveGeometry.hpp"
John Edward Broadbent4bc8a102021-12-30 16:11:49 -08008#include "zero.hpp"
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -08009
John Wedigb810c922021-11-17 16:38:03 -080010#include <libcryptsetup.h>
11#include <openssl/rand.h>
John Wedigb810c922021-11-17 16:38:03 -080012
13#include <phosphor-logging/lg2.hpp>
John Wedig972c3fa2021-12-29 17:30:41 -080014#include <xyz/openbmc_project/Common/error.hpp>
John Wedigb810c922021-11-17 16:38:03 -080015
Ed Tanous82897c32022-02-21 14:11:59 -080016#include <cstdlib>
John Wedigb810c922021-11-17 16:38:03 -080017#include <filesystem>
John Wedig2098dab2021-09-14 13:56:28 -070018#include <iostream>
John Wedigb810c922021-11-17 16:38:03 -080019#include <string_view>
John Wedig2098dab2021-09-14 13:56:28 -070020#include <vector>
21
22namespace estoraged
23{
24
John Wedig972c3fa2021-12-29 17:30:41 -080025using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
26using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
27using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest;
John Wedigb810c922021-11-17 16:38:03 -080028
Ed Tanous82897c32022-02-21 14:11:59 -080029void EStoraged::formatLuks(std::vector<uint8_t> password, FilesystemType type)
John Wedig2098dab2021-09-14 13:56:28 -070030{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080031 std::string msg = "OpenBMC.0.1.DriveFormat";
32 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080033
John Wedig972c3fa2021-12-29 17:30:41 -080034 if (type != FilesystemType::ext4)
35 {
36 lg2::error("Only ext4 filesystems are supported currently",
37 "REDFISH_MESSAGE_ID", std::string("OpenBMC.0.1.FormatFail"));
38 throw UnsupportedRequest();
39 }
40
John Wedig6218dc52021-12-03 09:36:35 -080041 CryptHandle cryptHandle(devPath.c_str());
42 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -080043 {
44 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
45 std::string("OpenBMC.0.1.FormatFail"));
John Wedig972c3fa2021-12-29 17:30:41 -080046 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -080047 }
48
John Wedig6218dc52021-12-03 09:36:35 -080049 formatLuksDev(cryptHandle.get(), password);
50 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -080051
52 createFilesystem();
53 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -070054}
55
Ed Tanous82897c32022-02-21 14:11:59 -080056void EStoraged::erase(EraseMethod inEraseMethod)
John Wedig2098dab2021-09-14 13:56:28 -070057{
58 std::cerr << "Erasing encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -070059 lg2::info("Starting erase", "REDFISH_MESSAGE_ID",
60 std::string("OpenBMC.0.1.DriveErase"));
61 switch (inEraseMethod)
62 {
63 case EraseMethod::CryptoErase:
64 {
John Edward Broadbent59dffa62022-01-13 17:41:32 -080065 CryptErase myCryptErase(devPath);
66 myCryptErase.doErase();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070067 break;
68 }
69 case EraseMethod::VerifyGeometry:
70 {
71 VerifyDriveGeometry myVerifyGeometry(devPath);
72 uint64_t size = myVerifyGeometry.findSizeOfBlockDevice();
73 myVerifyGeometry.geometryOkay(size);
74 break;
75 }
76 case EraseMethod::LogicalOverWrite:
77 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080078 Pattern myErasePattern(devPath);
John Edward Broadbent69786762022-01-21 14:16:23 -080079 myErasePattern.writePattern(myErasePattern.findSizeOfBlockDevice());
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 Broadbent69786762022-01-21 14:16:23 -080085 myErasePattern.verifyPattern(
86 myErasePattern.findSizeOfBlockDevice());
John Edward Broadbente6ffe702021-10-14 14:03:11 -070087 break;
88 }
89 case EraseMethod::VendorSanitize:
90 {
91 break;
92 }
93 case EraseMethod::ZeroOverWrite:
94 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -080095 Zero myZero(devPath);
John Edward Broadbent69786762022-01-21 14:16:23 -080096 myZero.writeZero(myZero.findSizeOfBlockDevice());
John Edward Broadbente6ffe702021-10-14 14:03:11 -070097 break;
98 }
99 case EraseMethod::ZeroVerify:
100 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -0800101 Zero myZero(devPath);
John Edward Broadbent69786762022-01-21 14:16:23 -0800102 myZero.verifyZero(myZero.findSizeOfBlockDevice());
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700103 break;
104 }
105 case EraseMethod::SecuredLocked:
106 {
John Edward Broadbentf59b7292022-02-15 15:07:15 -0800107 if (isLocked())
108 {
109 lock();
110 }
111 // TODO: implement hardware locking
112 // Until that is done, we can lock using eStoraged::lock()
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700113 break;
114 }
115 }
John Wedig2098dab2021-09-14 13:56:28 -0700116}
117
Ed Tanous82897c32022-02-21 14:11:59 -0800118void EStoraged::lock()
John Wedig2098dab2021-09-14 13:56:28 -0700119{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800120 std::string msg = "OpenBMC.0.1.DriveLock";
121 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800122
123 unmountFilesystem();
124 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700125}
126
Ed Tanous82897c32022-02-21 14:11:59 -0800127void EStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700128{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800129 std::string msg = "OpenBMC.0.1.DriveUnlock";
130 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800131
John Wedig6218dc52021-12-03 09:36:35 -0800132 CryptHandle cryptHandle(devPath.c_str());
133 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800134 {
135 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
136 std::string("OpenBMC.0.1.UnlockFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800137 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800138 }
139
John Wedig6218dc52021-12-03 09:36:35 -0800140 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -0800141 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700142}
143
Ed Tanous82897c32022-02-21 14:11:59 -0800144void EStoraged::changePassword(std::vector<uint8_t> /*oldPassword*/,
145 std::vector<uint8_t> /*newPassword*/)
John Wedig2098dab2021-09-14 13:56:28 -0700146{
147 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700148 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
149 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700150}
151
Ed Tanous82897c32022-02-21 14:11:59 -0800152bool EStoraged::isLocked() const
John Wedigb810c922021-11-17 16:38:03 -0800153{
154 return locked();
155}
156
Ed Tanous82897c32022-02-21 14:11:59 -0800157std::string_view EStoraged::getMountPoint() const
John Wedigb810c922021-11-17 16:38:03 -0800158{
159 return mountPoint;
160}
161
Ed Tanous82897c32022-02-21 14:11:59 -0800162void EStoraged::formatLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800163 std::vector<uint8_t> password)
164{
165 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
166 std::string("OpenBMC.0.1.FormatLuksDev"));
167
168 /* Generate the volume key. */
169 const std::size_t keySize = 64;
170 std::vector<uint8_t> volumeKey(keySize);
171 if (RAND_bytes(volumeKey.data(), keySize) != 1)
172 {
173 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
174 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800175 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800176 }
177 /* Format the LUKS encrypted device. */
178 int retval =
179 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
180 reinterpret_cast<const char*>(volumeKey.data()),
181 volumeKey.size(), nullptr);
182 if (retval < 0)
183 {
184 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
185 retval, "REDFISH_MESSAGE_ID",
186 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800187 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800188 }
189
190 /* Device is now encrypted. */
191 locked(true);
192
193 /* Set the password. */
194 retval = cryptIface->cryptKeyslotAddByVolumeKey(
195 cd, CRYPT_ANY_SLOT, nullptr, 0,
196 reinterpret_cast<const char*>(password.data()), password.size());
197
198 if (retval < 0)
199 {
200 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
201 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800202 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800203 }
204
205 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
206 "REDFISH_MESSAGE_ID",
207 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
208}
209
Ed Tanous82897c32022-02-21 14:11:59 -0800210void EStoraged::activateLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800211 std::vector<uint8_t> password)
212{
213 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
214 std::string("OpenBMC.0.1.ActivateLuksDev"));
215
216 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
217 if (retval < 0)
218 {
219 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
220 "REDFISH_MESSAGE_ID",
221 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800222 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800223 }
224
225 retval = cryptIface->cryptActivateByPassphrase(
226 cd, containerName.c_str(), CRYPT_ANY_SLOT,
227 reinterpret_cast<const char*>(password.data()), password.size(), 0);
228
229 if (retval < 0)
230 {
231 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
232 "REDFISH_MESSAGE_ID",
233 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800234 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800235 }
236
237 /* Device is now unlocked. */
238 locked(false);
239
240 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
241 "REDFISH_MESSAGE_ID",
242 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
243}
244
Ed Tanous82897c32022-02-21 14:11:59 -0800245void EStoraged::createFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800246{
247 /* Run the command to create the filesystem. */
248 int retval = fsIface->runMkfs(containerName);
Ed Tanous82897c32022-02-21 14:11:59 -0800249 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800250 {
251 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
252 "REDFISH_MESSAGE_ID",
253 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800254 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800255 }
256 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
257 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
258 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
259}
260
Ed Tanous82897c32022-02-21 14:11:59 -0800261void EStoraged::mountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800262{
John Wedigb17f8252022-01-12 14:24:26 -0800263 /*
264 * Create directory for the filesystem, if it's not already present. It
265 * might already exist if, for example, the BMC reboots after creating the
266 * directory.
267 */
268 if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
John Wedigb810c922021-11-17 16:38:03 -0800269 {
John Wedigb17f8252022-01-12 14:24:26 -0800270 bool success =
271 fsIface->createDirectory(std::filesystem::path(mountPoint));
272 if (!success)
273 {
274 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
275 "REDFISH_MESSAGE_ID",
276 std::string("OpenBMC.0.1.MountFilesystemFail"));
277 throw InternalFailure();
278 }
John Wedigb810c922021-11-17 16:38:03 -0800279 }
280
281 /* Run the command to mount the filesystem. */
282 std::string luksContainer("/dev/mapper/" + containerName);
283 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
284 "ext4", 0, nullptr);
Ed Tanous82897c32022-02-21 14:11:59 -0800285 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800286 {
287 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
288 "REDFISH_MESSAGE_ID",
289 std::string("OpenBMC.0.1.MountFilesystemFail"));
290 bool removeSuccess =
291 fsIface->removeDirectory(std::filesystem::path(mountPoint));
292 if (!removeSuccess)
293 {
294 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
295 "REDFISH_MESSAGE_ID",
296 std::string("OpenBMC.0.1.MountFilesystemFail"));
297 }
John Wedig972c3fa2021-12-29 17:30:41 -0800298 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800299 }
300
301 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
302 "REDFISH_MESSAGE_ID",
303 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
304}
305
Ed Tanous82897c32022-02-21 14:11:59 -0800306void EStoraged::unmountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800307{
308 int retval = fsIface->doUnmount(mountPoint.c_str());
Ed Tanous82897c32022-02-21 14:11:59 -0800309 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800310 {
311 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
312 "REDFISH_MESSAGE_ID",
313 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800314 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800315 }
316
317 /* Remove the mount point. */
318 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
319 if (!success)
320 {
321 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
322 "REDFISH_MESSAGE_ID",
323 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800324 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800325 }
326
327 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
328 "REDFISH_MESSAGE_ID",
329 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
330}
331
Ed Tanous82897c32022-02-21 14:11:59 -0800332void EStoraged::deactivateLuksDev()
John Wedigb810c922021-11-17 16:38:03 -0800333{
334 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
335 "REDFISH_MESSAGE_ID",
336 std::string("OpenBMC.0.1.DeactivateLuksDev"));
337
338 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
339 if (retval < 0)
340 {
341 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
342 retval, "REDFISH_MESSAGE_ID",
343 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800344 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800345 }
346
347 /* Device is now locked. */
348 locked(true);
349
350 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
351 "REDFISH_MESSAGE_ID",
352 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
353}
354
John Wedig2098dab2021-09-14 13:56:28 -0700355} // namespace estoraged