blob: 4e64ca6902d472282634ecd4b3b0a5cd7d6a7559 [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 Broadbente6ffe702021-10-14 14:03:11 -07005#include "verifyDriveGeometry.hpp"
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -08006
John Wedigb810c922021-11-17 16:38:03 -08007#include <libcryptsetup.h>
8#include <openssl/rand.h>
9#include <stdlib.h>
10
11#include <phosphor-logging/lg2.hpp>
12#include <xyz/openbmc_project/eStoraged/error.hpp>
13
14#include <filesystem>
John Wedig2098dab2021-09-14 13:56:28 -070015#include <iostream>
John Wedigb810c922021-11-17 16:38:03 -080016#include <string_view>
John Wedig2098dab2021-09-14 13:56:28 -070017#include <vector>
18
John Edward Broadbente6ffe702021-10-14 14:03:11 -070019using sdbusplus::xyz::openbmc_project::eStoraged::Error::EraseError;
20
John Wedig2098dab2021-09-14 13:56:28 -070021namespace estoraged
22{
23
John Wedigb810c922021-11-17 16:38:03 -080024using sdbusplus::xyz::openbmc_project::eStoraged::Error::EncryptionError;
25using sdbusplus::xyz::openbmc_project::eStoraged::Error::FilesystemError;
26
27void eStoraged::format(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -070028{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080029 std::string msg = "OpenBMC.0.1.DriveFormat";
30 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080031
32 struct crypt_device* cryptDev;
33 CryptHandle cryptHandle(&cryptDev, devPath.c_str());
34 if (*cryptHandle.handle == nullptr)
35 {
36 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
37 std::string("OpenBMC.0.1.FormatFail"));
38 throw EncryptionError();
39 }
40
41 formatLuksDev(cryptDev, password);
42 activateLuksDev(cryptDev, password);
43
44 createFilesystem();
45 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -070046}
47
John Edward Broadbente6ffe702021-10-14 14:03:11 -070048void eStoraged::erase(std::vector<uint8_t>, EraseMethod inEraseMethod)
John Wedig2098dab2021-09-14 13:56:28 -070049{
50 std::cerr << "Erasing encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -070051 lg2::info("Starting erase", "REDFISH_MESSAGE_ID",
52 std::string("OpenBMC.0.1.DriveErase"));
53 switch (inEraseMethod)
54 {
55 case EraseMethod::CryptoErase:
56 {
57 break;
58 }
59 case EraseMethod::VerifyGeometry:
60 {
61 VerifyDriveGeometry myVerifyGeometry(devPath);
62 uint64_t size = myVerifyGeometry.findSizeOfBlockDevice();
63 myVerifyGeometry.geometryOkay(size);
64 break;
65 }
66 case EraseMethod::LogicalOverWrite:
67 {
68 break;
69 }
70 case EraseMethod::LogicalVerify:
71 {
72 break;
73 }
74 case EraseMethod::VendorSanitize:
75 {
76 break;
77 }
78 case EraseMethod::ZeroOverWrite:
79 {
80 break;
81 }
82 case EraseMethod::ZeroVerify:
83 {
84 break;
85 }
86 case EraseMethod::SecuredLocked:
87 {
88 break;
89 }
90 }
John Wedig2098dab2021-09-14 13:56:28 -070091}
92
93void eStoraged::lock(std::vector<uint8_t>)
94{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080095 std::string msg = "OpenBMC.0.1.DriveLock";
96 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080097
98 unmountFilesystem();
99 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700100}
101
John Wedigb810c922021-11-17 16:38:03 -0800102void eStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700103{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800104 std::string msg = "OpenBMC.0.1.DriveUnlock";
105 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800106
107 struct crypt_device* cryptDev;
108 CryptHandle cryptHandle(&cryptDev, devPath.c_str());
109 if (*cryptHandle.handle == nullptr)
110 {
111 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
112 std::string("OpenBMC.0.1.UnlockFail"));
113 throw EncryptionError();
114 }
115
116 activateLuksDev(cryptDev, password);
117 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700118}
119
120void eStoraged::changePassword(std::vector<uint8_t>, std::vector<uint8_t>)
121{
122 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700123 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
124 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700125}
126
John Wedigb810c922021-11-17 16:38:03 -0800127bool eStoraged::isLocked() const
128{
129 return locked();
130}
131
132std::string_view eStoraged::getMountPoint() const
133{
134 return mountPoint;
135}
136
137void eStoraged::formatLuksDev(struct crypt_device* cd,
138 std::vector<uint8_t> password)
139{
140 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
141 std::string("OpenBMC.0.1.FormatLuksDev"));
142
143 /* Generate the volume key. */
144 const std::size_t keySize = 64;
145 std::vector<uint8_t> volumeKey(keySize);
146 if (RAND_bytes(volumeKey.data(), keySize) != 1)
147 {
148 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
149 std::string("OpenBMC.0.1.FormatLuksDevFail"));
150 throw EncryptionError();
151 }
152 /* Format the LUKS encrypted device. */
153 int retval =
154 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
155 reinterpret_cast<const char*>(volumeKey.data()),
156 volumeKey.size(), nullptr);
157 if (retval < 0)
158 {
159 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
160 retval, "REDFISH_MESSAGE_ID",
161 std::string("OpenBMC.0.1.FormatLuksDevFail"));
162 throw EncryptionError();
163 }
164
165 /* Device is now encrypted. */
166 locked(true);
167
168 /* Set the password. */
169 retval = cryptIface->cryptKeyslotAddByVolumeKey(
170 cd, CRYPT_ANY_SLOT, nullptr, 0,
171 reinterpret_cast<const char*>(password.data()), password.size());
172
173 if (retval < 0)
174 {
175 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
176 std::string("OpenBMC.0.1.FormatLuksDevFail"));
177 throw EncryptionError();
178 }
179
180 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
181 "REDFISH_MESSAGE_ID",
182 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
183}
184
185void eStoraged::activateLuksDev(struct crypt_device* cd,
186 std::vector<uint8_t> password)
187{
188 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
189 std::string("OpenBMC.0.1.ActivateLuksDev"));
190
191 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
192 if (retval < 0)
193 {
194 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
195 "REDFISH_MESSAGE_ID",
196 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
197 throw EncryptionError();
198 }
199
200 retval = cryptIface->cryptActivateByPassphrase(
201 cd, containerName.c_str(), CRYPT_ANY_SLOT,
202 reinterpret_cast<const char*>(password.data()), password.size(), 0);
203
204 if (retval < 0)
205 {
206 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
207 "REDFISH_MESSAGE_ID",
208 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
209 throw EncryptionError();
210 }
211
212 /* Device is now unlocked. */
213 locked(false);
214
215 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
216 "REDFISH_MESSAGE_ID",
217 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
218}
219
220void eStoraged::createFilesystem()
221{
222 /* Run the command to create the filesystem. */
223 int retval = fsIface->runMkfs(containerName);
224 if (retval)
225 {
226 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
227 "REDFISH_MESSAGE_ID",
228 std::string("OpenBMC.0.1.CreateFilesystemFail"));
229 throw FilesystemError();
230 }
231 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
232 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
233 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
234}
235
236void eStoraged::mountFilesystem()
237{
238 /* Create directory for the filesystem. */
239 bool success = fsIface->createDirectory(std::filesystem::path(mountPoint));
240 if (!success)
241 {
242 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
243 "REDFISH_MESSAGE_ID",
244 std::string("OpenBMC.0.1.MountFilesystemFail"));
245 throw FilesystemError();
246 }
247
248 /* Run the command to mount the filesystem. */
249 std::string luksContainer("/dev/mapper/" + containerName);
250 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
251 "ext4", 0, nullptr);
252 if (retval)
253 {
254 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
255 "REDFISH_MESSAGE_ID",
256 std::string("OpenBMC.0.1.MountFilesystemFail"));
257 bool removeSuccess =
258 fsIface->removeDirectory(std::filesystem::path(mountPoint));
259 if (!removeSuccess)
260 {
261 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
262 "REDFISH_MESSAGE_ID",
263 std::string("OpenBMC.0.1.MountFilesystemFail"));
264 }
265 throw FilesystemError();
266 }
267
268 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
269 "REDFISH_MESSAGE_ID",
270 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
271}
272
273void eStoraged::unmountFilesystem()
274{
275 int retval = fsIface->doUnmount(mountPoint.c_str());
276 if (retval)
277 {
278 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
279 "REDFISH_MESSAGE_ID",
280 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
281 throw FilesystemError();
282 }
283
284 /* Remove the mount point. */
285 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
286 if (!success)
287 {
288 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
289 "REDFISH_MESSAGE_ID",
290 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
291 throw FilesystemError();
292 }
293
294 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
295 "REDFISH_MESSAGE_ID",
296 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
297}
298
299void eStoraged::deactivateLuksDev()
300{
301 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
302 "REDFISH_MESSAGE_ID",
303 std::string("OpenBMC.0.1.DeactivateLuksDev"));
304
305 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
306 if (retval < 0)
307 {
308 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
309 retval, "REDFISH_MESSAGE_ID",
310 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
311 throw EncryptionError();
312 }
313
314 /* Device is now locked. */
315 locked(true);
316
317 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
318 "REDFISH_MESSAGE_ID",
319 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
320}
321
John Wedig2098dab2021-09-14 13:56:28 -0700322} // namespace estoraged