blob: 826d44b8308945fb76f546943a796afac6ca9233 [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>
12#include <stdlib.h>
13
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
17#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
John Wedig972c3fa2021-12-29 17:30:41 -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
John Wedig972c3fa2021-12-29 17:30:41 -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 {
107 break;
108 }
109 }
John Wedig2098dab2021-09-14 13:56:28 -0700110}
111
John Wedig972c3fa2021-12-29 17:30:41 -0800112void eStoraged::lock()
John Wedig2098dab2021-09-14 13:56:28 -0700113{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800114 std::string msg = "OpenBMC.0.1.DriveLock";
115 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800116
117 unmountFilesystem();
118 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700119}
120
John Wedigb810c922021-11-17 16:38:03 -0800121void eStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700122{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800123 std::string msg = "OpenBMC.0.1.DriveUnlock";
124 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800125
John Wedig6218dc52021-12-03 09:36:35 -0800126 CryptHandle cryptHandle(devPath.c_str());
127 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800128 {
129 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
130 std::string("OpenBMC.0.1.UnlockFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800131 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800132 }
133
John Wedig6218dc52021-12-03 09:36:35 -0800134 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -0800135 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700136}
137
138void eStoraged::changePassword(std::vector<uint8_t>, std::vector<uint8_t>)
139{
140 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700141 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
142 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700143}
144
John Wedigb810c922021-11-17 16:38:03 -0800145bool eStoraged::isLocked() const
146{
147 return locked();
148}
149
150std::string_view eStoraged::getMountPoint() const
151{
152 return mountPoint;
153}
154
155void eStoraged::formatLuksDev(struct crypt_device* cd,
156 std::vector<uint8_t> password)
157{
158 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
159 std::string("OpenBMC.0.1.FormatLuksDev"));
160
161 /* Generate the volume key. */
162 const std::size_t keySize = 64;
163 std::vector<uint8_t> volumeKey(keySize);
164 if (RAND_bytes(volumeKey.data(), keySize) != 1)
165 {
166 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
167 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800168 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800169 }
170 /* Format the LUKS encrypted device. */
171 int retval =
172 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
173 reinterpret_cast<const char*>(volumeKey.data()),
174 volumeKey.size(), nullptr);
175 if (retval < 0)
176 {
177 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
178 retval, "REDFISH_MESSAGE_ID",
179 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800180 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800181 }
182
183 /* Device is now encrypted. */
184 locked(true);
185
186 /* Set the password. */
187 retval = cryptIface->cryptKeyslotAddByVolumeKey(
188 cd, CRYPT_ANY_SLOT, nullptr, 0,
189 reinterpret_cast<const char*>(password.data()), password.size());
190
191 if (retval < 0)
192 {
193 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
194 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800195 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800196 }
197
198 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
199 "REDFISH_MESSAGE_ID",
200 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
201}
202
203void eStoraged::activateLuksDev(struct crypt_device* cd,
204 std::vector<uint8_t> password)
205{
206 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
207 std::string("OpenBMC.0.1.ActivateLuksDev"));
208
209 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
210 if (retval < 0)
211 {
212 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
213 "REDFISH_MESSAGE_ID",
214 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800215 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800216 }
217
218 retval = cryptIface->cryptActivateByPassphrase(
219 cd, containerName.c_str(), CRYPT_ANY_SLOT,
220 reinterpret_cast<const char*>(password.data()), password.size(), 0);
221
222 if (retval < 0)
223 {
224 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
225 "REDFISH_MESSAGE_ID",
226 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800227 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800228 }
229
230 /* Device is now unlocked. */
231 locked(false);
232
233 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
234 "REDFISH_MESSAGE_ID",
235 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
236}
237
238void eStoraged::createFilesystem()
239{
240 /* Run the command to create the filesystem. */
241 int retval = fsIface->runMkfs(containerName);
242 if (retval)
243 {
244 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
245 "REDFISH_MESSAGE_ID",
246 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800247 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800248 }
249 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
250 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
251 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
252}
253
254void eStoraged::mountFilesystem()
255{
John Wedigb17f8252022-01-12 14:24:26 -0800256 /*
257 * Create directory for the filesystem, if it's not already present. It
258 * might already exist if, for example, the BMC reboots after creating the
259 * directory.
260 */
261 if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
John Wedigb810c922021-11-17 16:38:03 -0800262 {
John Wedigb17f8252022-01-12 14:24:26 -0800263 bool success =
264 fsIface->createDirectory(std::filesystem::path(mountPoint));
265 if (!success)
266 {
267 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
268 "REDFISH_MESSAGE_ID",
269 std::string("OpenBMC.0.1.MountFilesystemFail"));
270 throw InternalFailure();
271 }
John Wedigb810c922021-11-17 16:38:03 -0800272 }
273
274 /* Run the command to mount the filesystem. */
275 std::string luksContainer("/dev/mapper/" + containerName);
276 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
277 "ext4", 0, nullptr);
278 if (retval)
279 {
280 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
281 "REDFISH_MESSAGE_ID",
282 std::string("OpenBMC.0.1.MountFilesystemFail"));
283 bool removeSuccess =
284 fsIface->removeDirectory(std::filesystem::path(mountPoint));
285 if (!removeSuccess)
286 {
287 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
288 "REDFISH_MESSAGE_ID",
289 std::string("OpenBMC.0.1.MountFilesystemFail"));
290 }
John Wedig972c3fa2021-12-29 17:30:41 -0800291 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800292 }
293
294 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
295 "REDFISH_MESSAGE_ID",
296 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
297}
298
299void eStoraged::unmountFilesystem()
300{
301 int retval = fsIface->doUnmount(mountPoint.c_str());
302 if (retval)
303 {
304 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
305 "REDFISH_MESSAGE_ID",
306 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800307 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800308 }
309
310 /* Remove the mount point. */
311 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
312 if (!success)
313 {
314 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
315 "REDFISH_MESSAGE_ID",
316 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800317 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800318 }
319
320 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
321 "REDFISH_MESSAGE_ID",
322 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
323}
324
325void eStoraged::deactivateLuksDev()
326{
327 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
328 "REDFISH_MESSAGE_ID",
329 std::string("OpenBMC.0.1.DeactivateLuksDev"));
330
331 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
332 if (retval < 0)
333 {
334 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
335 retval, "REDFISH_MESSAGE_ID",
336 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800337 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800338 }
339
340 /* Device is now locked. */
341 locked(true);
342
343 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
344 "REDFISH_MESSAGE_ID",
345 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
346}
347
John Wedig2098dab2021-09-14 13:56:28 -0700348} // namespace estoraged