blob: 3e3d0bb1b75a6dbca04762323d8c5adfa5af480d [file] [log] [blame]
John Wedig2098dab2021-09-14 13:56:28 -07001
2#include "estoraged.hpp"
3
John Wedigb810c922021-11-17 16:38:03 -08004#include "cryptsetupInterface.hpp"
John Edward Broadbent7f2ab642021-11-11 21:00:38 -08005#include "pattern.hpp"
John Edward Broadbente6ffe702021-10-14 14:03:11 -07006#include "verifyDriveGeometry.hpp"
John Edward Broadbent4bc8a102021-12-30 16:11:49 -08007#include "zero.hpp"
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -08008
John Wedigb810c922021-11-17 16:38:03 -08009#include <libcryptsetup.h>
10#include <openssl/rand.h>
11#include <stdlib.h>
12
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
16#include <filesystem>
John Wedig2098dab2021-09-14 13:56:28 -070017#include <iostream>
John Wedigb810c922021-11-17 16:38:03 -080018#include <string_view>
John Wedig2098dab2021-09-14 13:56:28 -070019#include <vector>
20
21namespace estoraged
22{
23
John Wedig972c3fa2021-12-29 17:30:41 -080024using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
25using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
26using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest;
John Wedigb810c922021-11-17 16:38:03 -080027
John Wedig972c3fa2021-12-29 17:30:41 -080028void eStoraged::formatLuks(std::vector<uint8_t> password, FilesystemType type)
John Wedig2098dab2021-09-14 13:56:28 -070029{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080030 std::string msg = "OpenBMC.0.1.DriveFormat";
31 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080032
John Wedig972c3fa2021-12-29 17:30:41 -080033 if (type != FilesystemType::ext4)
34 {
35 lg2::error("Only ext4 filesystems are supported currently",
36 "REDFISH_MESSAGE_ID", std::string("OpenBMC.0.1.FormatFail"));
37 throw UnsupportedRequest();
38 }
39
John Wedig6218dc52021-12-03 09:36:35 -080040 CryptHandle cryptHandle(devPath.c_str());
41 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -080042 {
43 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
44 std::string("OpenBMC.0.1.FormatFail"));
John Wedig972c3fa2021-12-29 17:30:41 -080045 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -080046 }
47
John Wedig6218dc52021-12-03 09:36:35 -080048 formatLuksDev(cryptHandle.get(), password);
49 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -080050
51 createFilesystem();
52 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -070053}
54
John Wedig972c3fa2021-12-29 17:30:41 -080055void eStoraged::erase(EraseMethod inEraseMethod)
John Wedig2098dab2021-09-14 13:56:28 -070056{
57 std::cerr << "Erasing encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -070058 lg2::info("Starting erase", "REDFISH_MESSAGE_ID",
59 std::string("OpenBMC.0.1.DriveErase"));
60 switch (inEraseMethod)
61 {
62 case EraseMethod::CryptoErase:
63 {
64 break;
65 }
66 case EraseMethod::VerifyGeometry:
67 {
68 VerifyDriveGeometry myVerifyGeometry(devPath);
69 uint64_t size = myVerifyGeometry.findSizeOfBlockDevice();
70 myVerifyGeometry.geometryOkay(size);
71 break;
72 }
73 case EraseMethod::LogicalOverWrite:
74 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080075 Pattern myErasePattern(devPath);
John Edward Broadbent69786762022-01-21 14:16:23 -080076 myErasePattern.writePattern(myErasePattern.findSizeOfBlockDevice());
John Edward Broadbente6ffe702021-10-14 14:03:11 -070077 break;
78 }
79 case EraseMethod::LogicalVerify:
80 {
John Edward Broadbent7f2ab642021-11-11 21:00:38 -080081 Pattern myErasePattern(devPath);
John Edward Broadbent69786762022-01-21 14:16:23 -080082 myErasePattern.verifyPattern(
83 myErasePattern.findSizeOfBlockDevice());
John Edward Broadbente6ffe702021-10-14 14:03:11 -070084 break;
85 }
86 case EraseMethod::VendorSanitize:
87 {
88 break;
89 }
90 case EraseMethod::ZeroOverWrite:
91 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -080092 Zero myZero(devPath);
John Edward Broadbent69786762022-01-21 14:16:23 -080093 myZero.writeZero(myZero.findSizeOfBlockDevice());
John Edward Broadbente6ffe702021-10-14 14:03:11 -070094 break;
95 }
96 case EraseMethod::ZeroVerify:
97 {
John Edward Broadbent4bc8a102021-12-30 16:11:49 -080098 Zero myZero(devPath);
John Edward Broadbent69786762022-01-21 14:16:23 -080099 myZero.verifyZero(myZero.findSizeOfBlockDevice());
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700100 break;
101 }
102 case EraseMethod::SecuredLocked:
103 {
104 break;
105 }
106 }
John Wedig2098dab2021-09-14 13:56:28 -0700107}
108
John Wedig972c3fa2021-12-29 17:30:41 -0800109void eStoraged::lock()
John Wedig2098dab2021-09-14 13:56:28 -0700110{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800111 std::string msg = "OpenBMC.0.1.DriveLock";
112 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800113
114 unmountFilesystem();
115 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700116}
117
John Wedigb810c922021-11-17 16:38:03 -0800118void eStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700119{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800120 std::string msg = "OpenBMC.0.1.DriveUnlock";
121 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800122
John Wedig6218dc52021-12-03 09:36:35 -0800123 CryptHandle cryptHandle(devPath.c_str());
124 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800125 {
126 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
127 std::string("OpenBMC.0.1.UnlockFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800128 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800129 }
130
John Wedig6218dc52021-12-03 09:36:35 -0800131 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -0800132 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700133}
134
135void eStoraged::changePassword(std::vector<uint8_t>, std::vector<uint8_t>)
136{
137 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700138 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
139 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700140}
141
John Wedigb810c922021-11-17 16:38:03 -0800142bool eStoraged::isLocked() const
143{
144 return locked();
145}
146
147std::string_view eStoraged::getMountPoint() const
148{
149 return mountPoint;
150}
151
152void eStoraged::formatLuksDev(struct crypt_device* cd,
153 std::vector<uint8_t> password)
154{
155 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
156 std::string("OpenBMC.0.1.FormatLuksDev"));
157
158 /* Generate the volume key. */
159 const std::size_t keySize = 64;
160 std::vector<uint8_t> volumeKey(keySize);
161 if (RAND_bytes(volumeKey.data(), keySize) != 1)
162 {
163 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
164 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800165 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800166 }
167 /* Format the LUKS encrypted device. */
168 int retval =
169 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
170 reinterpret_cast<const char*>(volumeKey.data()),
171 volumeKey.size(), nullptr);
172 if (retval < 0)
173 {
174 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
175 retval, "REDFISH_MESSAGE_ID",
176 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800177 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800178 }
179
180 /* Device is now encrypted. */
181 locked(true);
182
183 /* Set the password. */
184 retval = cryptIface->cryptKeyslotAddByVolumeKey(
185 cd, CRYPT_ANY_SLOT, nullptr, 0,
186 reinterpret_cast<const char*>(password.data()), password.size());
187
188 if (retval < 0)
189 {
190 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
191 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800192 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800193 }
194
195 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
196 "REDFISH_MESSAGE_ID",
197 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
198}
199
200void eStoraged::activateLuksDev(struct crypt_device* cd,
201 std::vector<uint8_t> password)
202{
203 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
204 std::string("OpenBMC.0.1.ActivateLuksDev"));
205
206 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
207 if (retval < 0)
208 {
209 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
210 "REDFISH_MESSAGE_ID",
211 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800212 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800213 }
214
215 retval = cryptIface->cryptActivateByPassphrase(
216 cd, containerName.c_str(), CRYPT_ANY_SLOT,
217 reinterpret_cast<const char*>(password.data()), password.size(), 0);
218
219 if (retval < 0)
220 {
221 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
222 "REDFISH_MESSAGE_ID",
223 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800224 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800225 }
226
227 /* Device is now unlocked. */
228 locked(false);
229
230 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
231 "REDFISH_MESSAGE_ID",
232 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
233}
234
235void eStoraged::createFilesystem()
236{
237 /* Run the command to create the filesystem. */
238 int retval = fsIface->runMkfs(containerName);
239 if (retval)
240 {
241 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
242 "REDFISH_MESSAGE_ID",
243 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800244 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800245 }
246 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
247 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
248 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
249}
250
251void eStoraged::mountFilesystem()
252{
John Wedigb17f8252022-01-12 14:24:26 -0800253 /*
254 * Create directory for the filesystem, if it's not already present. It
255 * might already exist if, for example, the BMC reboots after creating the
256 * directory.
257 */
258 if (!fsIface->directoryExists(std::filesystem::path(mountPoint)))
John Wedigb810c922021-11-17 16:38:03 -0800259 {
John Wedigb17f8252022-01-12 14:24:26 -0800260 bool success =
261 fsIface->createDirectory(std::filesystem::path(mountPoint));
262 if (!success)
263 {
264 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
265 "REDFISH_MESSAGE_ID",
266 std::string("OpenBMC.0.1.MountFilesystemFail"));
267 throw InternalFailure();
268 }
John Wedigb810c922021-11-17 16:38:03 -0800269 }
270
271 /* Run the command to mount the filesystem. */
272 std::string luksContainer("/dev/mapper/" + containerName);
273 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
274 "ext4", 0, nullptr);
275 if (retval)
276 {
277 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
278 "REDFISH_MESSAGE_ID",
279 std::string("OpenBMC.0.1.MountFilesystemFail"));
280 bool removeSuccess =
281 fsIface->removeDirectory(std::filesystem::path(mountPoint));
282 if (!removeSuccess)
283 {
284 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
285 "REDFISH_MESSAGE_ID",
286 std::string("OpenBMC.0.1.MountFilesystemFail"));
287 }
John Wedig972c3fa2021-12-29 17:30:41 -0800288 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800289 }
290
291 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
292 "REDFISH_MESSAGE_ID",
293 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
294}
295
296void eStoraged::unmountFilesystem()
297{
298 int retval = fsIface->doUnmount(mountPoint.c_str());
299 if (retval)
300 {
301 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
302 "REDFISH_MESSAGE_ID",
303 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800304 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800305 }
306
307 /* Remove the mount point. */
308 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
309 if (!success)
310 {
311 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
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 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
318 "REDFISH_MESSAGE_ID",
319 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
320}
321
322void eStoraged::deactivateLuksDev()
323{
324 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
325 "REDFISH_MESSAGE_ID",
326 std::string("OpenBMC.0.1.DeactivateLuksDev"));
327
328 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
329 if (retval < 0)
330 {
331 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
332 retval, "REDFISH_MESSAGE_ID",
333 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800334 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800335 }
336
337 /* Device is now locked. */
338 locked(true);
339
340 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
341 "REDFISH_MESSAGE_ID",
342 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
343}
344
John Wedig2098dab2021-09-14 13:56:28 -0700345} // namespace estoraged