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