blob: 91a7f129c1475705870c5f63271271acdf23bd17 [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>
John Wedig972c3fa2021-12-29 17:30:41 -080012#include <xyz/openbmc_project/Common/error.hpp>
John Wedigb810c922021-11-17 16:38:03 -080013
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
19namespace estoraged
20{
21
John Wedig972c3fa2021-12-29 17:30:41 -080022using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
23using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
24using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest;
John Wedigb810c922021-11-17 16:38:03 -080025
John Wedig972c3fa2021-12-29 17:30:41 -080026void eStoraged::formatLuks(std::vector<uint8_t> password, FilesystemType type)
John Wedig2098dab2021-09-14 13:56:28 -070027{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080028 std::string msg = "OpenBMC.0.1.DriveFormat";
29 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080030
John Wedig972c3fa2021-12-29 17:30:41 -080031 if (type != FilesystemType::ext4)
32 {
33 lg2::error("Only ext4 filesystems are supported currently",
34 "REDFISH_MESSAGE_ID", std::string("OpenBMC.0.1.FormatFail"));
35 throw UnsupportedRequest();
36 }
37
John Wedig6218dc52021-12-03 09:36:35 -080038 CryptHandle cryptHandle(devPath.c_str());
39 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -080040 {
41 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
42 std::string("OpenBMC.0.1.FormatFail"));
John Wedig972c3fa2021-12-29 17:30:41 -080043 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -080044 }
45
John Wedig6218dc52021-12-03 09:36:35 -080046 formatLuksDev(cryptHandle.get(), password);
47 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -080048
49 createFilesystem();
50 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -070051}
52
John Wedig972c3fa2021-12-29 17:30:41 -080053void eStoraged::erase(EraseMethod inEraseMethod)
John Wedig2098dab2021-09-14 13:56:28 -070054{
55 std::cerr << "Erasing encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -070056 lg2::info("Starting erase", "REDFISH_MESSAGE_ID",
57 std::string("OpenBMC.0.1.DriveErase"));
58 switch (inEraseMethod)
59 {
60 case EraseMethod::CryptoErase:
61 {
62 break;
63 }
64 case EraseMethod::VerifyGeometry:
65 {
66 VerifyDriveGeometry myVerifyGeometry(devPath);
67 uint64_t size = myVerifyGeometry.findSizeOfBlockDevice();
68 myVerifyGeometry.geometryOkay(size);
69 break;
70 }
71 case EraseMethod::LogicalOverWrite:
72 {
73 break;
74 }
75 case EraseMethod::LogicalVerify:
76 {
77 break;
78 }
79 case EraseMethod::VendorSanitize:
80 {
81 break;
82 }
83 case EraseMethod::ZeroOverWrite:
84 {
85 break;
86 }
87 case EraseMethod::ZeroVerify:
88 {
89 break;
90 }
91 case EraseMethod::SecuredLocked:
92 {
93 break;
94 }
95 }
John Wedig2098dab2021-09-14 13:56:28 -070096}
97
John Wedig972c3fa2021-12-29 17:30:41 -080098void eStoraged::lock()
John Wedig2098dab2021-09-14 13:56:28 -070099{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800100 std::string msg = "OpenBMC.0.1.DriveLock";
101 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800102
103 unmountFilesystem();
104 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -0700105}
106
John Wedigb810c922021-11-17 16:38:03 -0800107void eStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -0700108{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -0800109 std::string msg = "OpenBMC.0.1.DriveUnlock";
110 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -0800111
John Wedig6218dc52021-12-03 09:36:35 -0800112 CryptHandle cryptHandle(devPath.c_str());
113 if (cryptHandle.get() == nullptr)
John Wedigb810c922021-11-17 16:38:03 -0800114 {
115 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
116 std::string("OpenBMC.0.1.UnlockFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800117 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800118 }
119
John Wedig6218dc52021-12-03 09:36:35 -0800120 activateLuksDev(cryptHandle.get(), password);
John Wedigb810c922021-11-17 16:38:03 -0800121 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -0700122}
123
124void eStoraged::changePassword(std::vector<uint8_t>, std::vector<uint8_t>)
125{
126 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbente6ffe702021-10-14 14:03:11 -0700127 lg2::info("Starting change password", "REDFISH_MESSAGE_ID",
128 std::string("OpenBMC.0.1.DrivePasswordChanged"));
John Wedig2098dab2021-09-14 13:56:28 -0700129}
130
John Wedigb810c922021-11-17 16:38:03 -0800131bool eStoraged::isLocked() const
132{
133 return locked();
134}
135
136std::string_view eStoraged::getMountPoint() const
137{
138 return mountPoint;
139}
140
141void eStoraged::formatLuksDev(struct crypt_device* cd,
142 std::vector<uint8_t> password)
143{
144 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
145 std::string("OpenBMC.0.1.FormatLuksDev"));
146
147 /* Generate the volume key. */
148 const std::size_t keySize = 64;
149 std::vector<uint8_t> volumeKey(keySize);
150 if (RAND_bytes(volumeKey.data(), keySize) != 1)
151 {
152 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
153 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800154 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800155 }
156 /* Format the LUKS encrypted device. */
157 int retval =
158 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
159 reinterpret_cast<const char*>(volumeKey.data()),
160 volumeKey.size(), nullptr);
161 if (retval < 0)
162 {
163 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
164 retval, "REDFISH_MESSAGE_ID",
165 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800166 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800167 }
168
169 /* Device is now encrypted. */
170 locked(true);
171
172 /* Set the password. */
173 retval = cryptIface->cryptKeyslotAddByVolumeKey(
174 cd, CRYPT_ANY_SLOT, nullptr, 0,
175 reinterpret_cast<const char*>(password.data()), password.size());
176
177 if (retval < 0)
178 {
179 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
180 std::string("OpenBMC.0.1.FormatLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800181 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800182 }
183
184 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
185 "REDFISH_MESSAGE_ID",
186 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
187}
188
189void eStoraged::activateLuksDev(struct crypt_device* cd,
190 std::vector<uint8_t> password)
191{
192 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
193 std::string("OpenBMC.0.1.ActivateLuksDev"));
194
195 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
196 if (retval < 0)
197 {
198 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
199 "REDFISH_MESSAGE_ID",
200 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800201 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800202 }
203
204 retval = cryptIface->cryptActivateByPassphrase(
205 cd, containerName.c_str(), CRYPT_ANY_SLOT,
206 reinterpret_cast<const char*>(password.data()), password.size(), 0);
207
208 if (retval < 0)
209 {
210 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
211 "REDFISH_MESSAGE_ID",
212 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800213 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800214 }
215
216 /* Device is now unlocked. */
217 locked(false);
218
219 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
220 "REDFISH_MESSAGE_ID",
221 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
222}
223
224void eStoraged::createFilesystem()
225{
226 /* Run the command to create the filesystem. */
227 int retval = fsIface->runMkfs(containerName);
228 if (retval)
229 {
230 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
231 "REDFISH_MESSAGE_ID",
232 std::string("OpenBMC.0.1.CreateFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800233 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800234 }
235 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
236 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
237 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
238}
239
240void eStoraged::mountFilesystem()
241{
242 /* Create directory for the filesystem. */
243 bool success = fsIface->createDirectory(std::filesystem::path(mountPoint));
244 if (!success)
245 {
246 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
247 "REDFISH_MESSAGE_ID",
248 std::string("OpenBMC.0.1.MountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800249 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800250 }
251
252 /* Run the command to mount the filesystem. */
253 std::string luksContainer("/dev/mapper/" + containerName);
254 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
255 "ext4", 0, nullptr);
256 if (retval)
257 {
258 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
259 "REDFISH_MESSAGE_ID",
260 std::string("OpenBMC.0.1.MountFilesystemFail"));
261 bool removeSuccess =
262 fsIface->removeDirectory(std::filesystem::path(mountPoint));
263 if (!removeSuccess)
264 {
265 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
266 "REDFISH_MESSAGE_ID",
267 std::string("OpenBMC.0.1.MountFilesystemFail"));
268 }
John Wedig972c3fa2021-12-29 17:30:41 -0800269 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800270 }
271
272 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
273 "REDFISH_MESSAGE_ID",
274 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
275}
276
277void eStoraged::unmountFilesystem()
278{
279 int retval = fsIface->doUnmount(mountPoint.c_str());
280 if (retval)
281 {
282 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
283 "REDFISH_MESSAGE_ID",
284 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800285 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800286 }
287
288 /* Remove the mount point. */
289 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
290 if (!success)
291 {
292 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
293 "REDFISH_MESSAGE_ID",
294 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800295 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800296 }
297
298 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
299 "REDFISH_MESSAGE_ID",
300 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
301}
302
303void eStoraged::deactivateLuksDev()
304{
305 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
306 "REDFISH_MESSAGE_ID",
307 std::string("OpenBMC.0.1.DeactivateLuksDev"));
308
309 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
310 if (retval < 0)
311 {
312 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
313 retval, "REDFISH_MESSAGE_ID",
314 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
John Wedig972c3fa2021-12-29 17:30:41 -0800315 throw InternalFailure();
John Wedigb810c922021-11-17 16:38:03 -0800316 }
317
318 /* Device is now locked. */
319 locked(true);
320
321 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
322 "REDFISH_MESSAGE_ID",
323 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
324}
325
John Wedig2098dab2021-09-14 13:56:28 -0700326} // namespace estoraged