blob: 6285079dc46e9dc7174b93db0a5b8a8c33b0b467 [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);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070072 myVerifyGeometry.geometryOkay();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070073 break;
74 }
75 case EraseMethod::LogicalOverWrite:
76 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080077 Pattern myErasePattern(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070078 myErasePattern.writePattern();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070079 break;
80 }
81 case EraseMethod::LogicalVerify:
82 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080083 Pattern myErasePattern(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070084 myErasePattern.verifyPattern();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070085 break;
86 }
87 case EraseMethod::VendorSanitize:
88 {
89 break;
90 }
91 case EraseMethod::ZeroOverWrite:
92 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -080093 Zero myZero(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -070094 myZero.writeZero();
John Edward Broadbente6ffe702021-10-14 14:03:11 -070095 break;
96 }
97 case EraseMethod::ZeroVerify:
98 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -080099 Zero myZero(devPath);
John Edward Broadbenta6e3b992022-03-17 14:33:15 -0700100 myZero.verifyZero();
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700101 break;
102 }
103 case EraseMethod::SecuredLocked:
104 {
John Edward Broadbentf59b7292022-02-15 15:07:15 -0800105 if (isLocked())
106 {
107 lock();
108 }
109 // TODO: implement hardware locking
110 // Until that is done, we can lock using eStoraged::lock()
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700111 break;
112 }
113 }
John Wedig2098dab2021-09-14 13:56:28 -0700114}
115
Ed Tanous82897c32022-02-21 14:11:59 -0800116void EStoraged::lock()
John Wedig2098dab2021-09-14 13:56:28 -0700117{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800118 std::string msg = "OpenBMC.0.1.DriveLock";
119 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800120
121 unmountFilesystem();
122 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700123}
124
Ed Tanous82897c32022-02-21 14:11:59 -0800125void EStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700126{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800127 std::string msg = "OpenBMC.0.1.DriveUnlock";
128 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800129
John Wedig6218dc52021-12-03 09:36:35 -0800130 CryptHandle cryptHandle(devPath.c_str());
131 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800132 {
133 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
134 std::string("OpenBMC.0.1.UnlockFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800135 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800136 }
137
John Wedig6218dc52021-12-03 09:36:35 -0800138 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -0800139 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700140}
141
Ed Tanous82897c32022-02-21 14:11:59 -0800142void EStoraged::changePassword(std::vector<uint8_t> /*oldPassword*/,
143 std::vector<uint8_t> /*newPassword*/)
John Wedig2098dab2021-09-14 13:56:28 -0700144{
145 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700146 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
147 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700148}
149
Ed Tanous82897c32022-02-21 14:11:59 -0800150bool EStoraged::isLocked() const
John Wedigb810c922021-11-17 16:38:03 -0800151{
152 return locked();
153}
154
Ed Tanous82897c32022-02-21 14:11:59 -0800155std::string_view EStoraged::getMountPoint() const
John Wedigb810c922021-11-17 16:38:03 -0800156{
157 return mountPoint;
158}
159
Ed Tanous82897c32022-02-21 14:11:59 -0800160void EStoraged::formatLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800161 std::vector<uint8_t> password)
162{
163 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
164 std::string("OpenBMC.0.1.FormatLuksDev"));
165
166 /* Generate the volume key. */
167 const std::size_t keySize = 64;
168 std::vector<uint8_t> volumeKey(keySize);
169 if (RAND_bytes(volumeKey.data(), keySize) != 1)
170 {
171 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
172 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800173 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800174 }
175 /* Format the LUKS encrypted device. */
176 int retval =
177 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
178 reinterpret_cast<const char*>(volumeKey.data()),
179 volumeKey.size(), nullptr);
180 if (retval < 0)
181 {
182 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
183 retval, "REDFISH_MESSAGE_ID",
184 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800185 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800186 }
187
188 /* Device is now encrypted. */
189 locked(true);
190
191 /* Set the password. */
192 retval = cryptIface->cryptKeyslotAddByVolumeKey(
193 cd, CRYPT_ANY_SLOT, nullptr, 0,
194 reinterpret_cast<const char*>(password.data()), password.size());
195
196 if (retval < 0)
197 {
198 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
199 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800200 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800201 }
202
203 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
204 "REDFISH_MESSAGE_ID",
205 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
206}
207
Ed Tanous82897c32022-02-21 14:11:59 -0800208void EStoraged::activateLuksDev(struct crypt_device* cd,
John Wedigb810c922021-11-17 16:38:03 -0800209 std::vector<uint8_t> password)
210{
211 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
212 std::string("OpenBMC.0.1.ActivateLuksDev"));
213
214 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
215 if (retval < 0)
216 {
217 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
218 "REDFISH_MESSAGE_ID",
219 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800220 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800221 }
222
223 retval = cryptIface->cryptActivateByPassphrase(
224 cd, containerName.c_str(), CRYPT_ANY_SLOT,
225 reinterpret_cast<const char*>(password.data()), password.size(), 0);
226
227 if (retval < 0)
228 {
229 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
230 "REDFISH_MESSAGE_ID",
231 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800232 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800233 }
234
235 /* Device is now unlocked. */
236 locked(false);
237
238 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
239 "REDFISH_MESSAGE_ID",
240 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
241}
242
Ed Tanous82897c32022-02-21 14:11:59 -0800243void EStoraged::createFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800244{
245 /* Run the command to create the filesystem. */
246 int retval = fsIface->runMkfs(containerName);
Ed Tanous82897c32022-02-21 14:11:59 -0800247 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800248 {
249 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
250 "REDFISH_MESSAGE_ID",
251 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800252 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800253 }
254 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
255 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
256 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
257}
258
Ed Tanous82897c32022-02-21 14:11:59 -0800259void EStoraged::mountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800260{
John Wedigb17f8252022-01-12 14:24:26 -0800261 /*
262 * Create directory for the filesystem, if it's not already present. It
263 * might already exist if, for example, the BMC reboots after creating the
264 * directory.
265 */
266 if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
John Wedigb810c922021-11-17 16:38:03 -0800267 {
John Wedigb17f8252022-01-12 14:24:26 -0800268 bool success =
269 fsIface->createDirectory(std::filesystem::path(mountPoint));
270 if (!success)
271 {
272 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
273 "REDFISH_MESSAGE_ID",
274 std::string("OpenBMC.0.1.MountFilesystemFail"));
275 throw InternalFailure();
276 }
John Wedigb810c922021-11-17 16:38:03 -0800277 }
278
279 /* Run the command to mount the filesystem. */
280 std::string luksContainer("/dev/mapper/" + containerName);
281 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
282 "ext4", 0, nullptr);
Ed Tanous82897c32022-02-21 14:11:59 -0800283 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800284 {
285 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
286 "REDFISH_MESSAGE_ID",
287 std::string("OpenBMC.0.1.MountFilesystemFail"));
288 bool removeSuccess =
289 fsIface->removeDirectory(std::filesystem::path(mountPoint));
290 if (!removeSuccess)
291 {
292 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
293 "REDFISH_MESSAGE_ID",
294 std::string("OpenBMC.0.1.MountFilesystemFail"));
295 }
John Wedig972c3fa2021-12-29 17:30:41 -0800296 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800297 }
298
299 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
300 "REDFISH_MESSAGE_ID",
301 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
302}
303
Ed Tanous82897c32022-02-21 14:11:59 -0800304void EStoraged::unmountFilesystem()
John Wedigb810c922021-11-17 16:38:03 -0800305{
306 int retval = fsIface->doUnmount(mountPoint.c_str());
Ed Tanous82897c32022-02-21 14:11:59 -0800307 if (retval != 0)
John Wedigb810c922021-11-17 16:38:03 -0800308 {
309 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
310 "REDFISH_MESSAGE_ID",
311 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800312 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800313 }
314
315 /* Remove the mount point. */
316 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
317 if (!success)
318 {
319 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
320 "REDFISH_MESSAGE_ID",
321 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800322 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800323 }
324
325 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
326 "REDFISH_MESSAGE_ID",
327 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
328}
329
Ed Tanous82897c32022-02-21 14:11:59 -0800330void EStoraged::deactivateLuksDev()
John Wedigb810c922021-11-17 16:38:03 -0800331{
332 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
333 "REDFISH_MESSAGE_ID",
334 std::string("OpenBMC.0.1.DeactivateLuksDev"));
335
336 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
337 if (retval < 0)
338 {
339 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
340 retval, "REDFISH_MESSAGE_ID",
341 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800342 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800343 }
344
345 /* Device is now locked. */
346 locked(true);
347
348 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
349 "REDFISH_MESSAGE_ID",
350 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
351}
352
John Wedig2098dab2021-09-14 13:56:28 -0700353} // namespace estoraged