blob: 4f7fc401d508f805d934898f459f700fe5a55db2 [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 {
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
John Wedig972c3fa2021-12-29 17:30:41 -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
John Wedigb810c922021-11-17 16:38:03 -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
144void eStoraged::changePassword(std::vector<uint8_t>, std::vector<uint8_t>)
145{
146 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700147 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
148 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700149}
150
John Wedigb810c922021-11-17 16:38:03 -0800151bool eStoraged::isLocked() const
152{
153 return locked();
154}
155
156std::string_view eStoraged::getMountPoint() const
157{
158 return mountPoint;
159}
160
161void eStoraged::formatLuksDev(struct crypt_device* cd,
162 std::vector<uint8_t> password)
163{
164 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
165 std::string("OpenBMC.0.1.FormatLuksDev"));
166
167 /* Generate the volume key. */
168 const std::size_t keySize = 64;
169 std::vector<uint8_t> volumeKey(keySize);
170 if (RAND_bytes(volumeKey.data(), keySize) != 1)
171 {
172 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
173 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800174 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800175 }
176 /* Format the LUKS encrypted device. */
177 int retval =
178 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
179 reinterpret_cast<const char*>(volumeKey.data()),
180 volumeKey.size(), nullptr);
181 if (retval < 0)
182 {
183 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
184 retval, "REDFISH_MESSAGE_ID",
185 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800186 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800187 }
188
189 /* Device is now encrypted. */
190 locked(true);
191
192 /* Set the password. */
193 retval = cryptIface->cryptKeyslotAddByVolumeKey(
194 cd, CRYPT_ANY_SLOT, nullptr, 0,
195 reinterpret_cast<const char*>(password.data()), password.size());
196
197 if (retval < 0)
198 {
199 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
200 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800201 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800202 }
203
204 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
205 "REDFISH_MESSAGE_ID",
206 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
207}
208
209void eStoraged::activateLuksDev(struct crypt_device* cd,
210 std::vector<uint8_t> password)
211{
212 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
213 std::string("OpenBMC.0.1.ActivateLuksDev"));
214
215 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
216 if (retval < 0)
217 {
218 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
219 "REDFISH_MESSAGE_ID",
220 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800221 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800222 }
223
224 retval = cryptIface->cryptActivateByPassphrase(
225 cd, containerName.c_str(), CRYPT_ANY_SLOT,
226 reinterpret_cast<const char*>(password.data()), password.size(), 0);
227
228 if (retval < 0)
229 {
230 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
231 "REDFISH_MESSAGE_ID",
232 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800233 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800234 }
235
236 /* Device is now unlocked. */
237 locked(false);
238
239 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
240 "REDFISH_MESSAGE_ID",
241 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
242}
243
244void eStoraged::createFilesystem()
245{
246 /* Run the command to create the filesystem. */
247 int retval = fsIface->runMkfs(containerName);
248 if (retval)
249 {
250 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
251 "REDFISH_MESSAGE_ID",
252 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800253 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800254 }
255 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
256 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
257 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
258}
259
260void eStoraged::mountFilesystem()
261{
John Wedigb17f8252022-01-12 14:24:26 -0800262 /*
263 * Create directory for the filesystem, if it's not already present. It
264 * might already exist if, for example, the BMC reboots after creating the
265 * directory.
266 */
267 if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
John Wedigb810c922021-11-17 16:38:03 -0800268 {
John Wedigb17f8252022-01-12 14:24:26 -0800269 bool success =
270 fsIface->createDirectory(std::filesystem::path(mountPoint));
271 if (!success)
272 {
273 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
274 "REDFISH_MESSAGE_ID",
275 std::string("OpenBMC.0.1.MountFilesystemFail"));
276 throw InternalFailure();
277 }
John Wedigb810c922021-11-17 16:38:03 -0800278 }
279
280 /* Run the command to mount the filesystem. */
281 std::string luksContainer("/dev/mapper/" + containerName);
282 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
283 "ext4", 0, nullptr);
284 if (retval)
285 {
286 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
287 "REDFISH_MESSAGE_ID",
288 std::string("OpenBMC.0.1.MountFilesystemFail"));
289 bool removeSuccess =
290 fsIface->removeDirectory(std::filesystem::path(mountPoint));
291 if (!removeSuccess)
292 {
293 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
294 "REDFISH_MESSAGE_ID",
295 std::string("OpenBMC.0.1.MountFilesystemFail"));
296 }
John Wedig972c3fa2021-12-29 17:30:41 -0800297 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800298 }
299
300 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
301 "REDFISH_MESSAGE_ID",
302 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
303}
304
305void eStoraged::unmountFilesystem()
306{
307 int retval = fsIface->doUnmount(mountPoint.c_str());
308 if (retval)
309 {
310 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
311 "REDFISH_MESSAGE_ID",
312 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800313 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800314 }
315
316 /* Remove the mount point. */
317 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
318 if (!success)
319 {
320 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
321 "REDFISH_MESSAGE_ID",
322 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800323 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800324 }
325
326 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
327 "REDFISH_MESSAGE_ID",
328 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
329}
330
331void eStoraged::deactivateLuksDev()
332{
333 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
334 "REDFISH_MESSAGE_ID",
335 std::string("OpenBMC.0.1.DeactivateLuksDev"));
336
337 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
338 if (retval < 0)
339 {
340 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
341 retval, "REDFISH_MESSAGE_ID",
342 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800343 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800344 }
345
346 /* Device is now locked. */
347 locked(true);
348
349 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
350 "REDFISH_MESSAGE_ID",
351 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
352}
353
John Wedig2098dab2021-09-14 13:56:28 -0700354} // namespace estoraged