blob: dcbb524ec1022454d34dc48492cc0380e8476ab8 [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 Broadbent4e13b0a2021-11-15 15:21:59 -08005
John Wedigb810c922021-11-17 16:38:03 -08006#include <libcryptsetup.h>
7#include <openssl/rand.h>
8#include <stdlib.h>
9
10#include <phosphor-logging/lg2.hpp>
11#include <xyz/openbmc_project/eStoraged/error.hpp>
12
13#include <filesystem>
John Wedig2098dab2021-09-14 13:56:28 -070014#include <iostream>
John Wedigb810c922021-11-17 16:38:03 -080015#include <string_view>
John Wedig2098dab2021-09-14 13:56:28 -070016#include <vector>
17
18namespace estoraged
19{
20
John Wedigb810c922021-11-17 16:38:03 -080021using sdbusplus::xyz::openbmc_project::eStoraged::Error::EncryptionError;
22using sdbusplus::xyz::openbmc_project::eStoraged::Error::FilesystemError;
23
24void eStoraged::format(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -070025{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080026 std::string msg = "OpenBMC.0.1.DriveFormat";
27 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080028
29 struct crypt_device* cryptDev;
30 CryptHandle cryptHandle(&cryptDev, devPath.c_str());
31 if (*cryptHandle.handle == nullptr)
32 {
33 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
34 std::string("OpenBMC.0.1.FormatFail"));
35 throw EncryptionError();
36 }
37
38 formatLuksDev(cryptDev, password);
39 activateLuksDev(cryptDev, password);
40
41 createFilesystem();
42 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -070043}
44
45void eStoraged::erase(std::vector<uint8_t>, EraseMethod)
46{
47 std::cerr << "Erasing encrypted eMMC" << std::endl;
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080048 std::string msg = "OpenBMC.0.1.DriveErase";
49 lg2::info("Starting erase", "REDFISH_MESSAGE_ID", msg);
John Wedig2098dab2021-09-14 13:56:28 -070050}
51
52void eStoraged::lock(std::vector<uint8_t>)
53{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080054 std::string msg = "OpenBMC.0.1.DriveLock";
55 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080056
57 unmountFilesystem();
58 deactivateLuksDev();
John Wedig2098dab2021-09-14 13:56:28 -070059}
60
John Wedigb810c922021-11-17 16:38:03 -080061void eStoraged::unlock(std::vector<uint8_t> password)
John Wedig2098dab2021-09-14 13:56:28 -070062{
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080063 std::string msg = "OpenBMC.0.1.DriveUnlock";
64 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg);
John Wedigb810c922021-11-17 16:38:03 -080065
66 struct crypt_device* cryptDev;
67 CryptHandle cryptHandle(&cryptDev, devPath.c_str());
68 if (*cryptHandle.handle == nullptr)
69 {
70 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID",
71 std::string("OpenBMC.0.1.UnlockFail"));
72 throw EncryptionError();
73 }
74
75 activateLuksDev(cryptDev, password);
76 mountFilesystem();
John Wedig2098dab2021-09-14 13:56:28 -070077}
78
79void eStoraged::changePassword(std::vector<uint8_t>, std::vector<uint8_t>)
80{
81 std::cerr << "Changing password for encrypted eMMC" << std::endl;
John Edward Broadbent4e13b0a2021-11-15 15:21:59 -080082 std::string msg = "OpenBMC.0.1.DrivePasswordChanged";
83 lg2::info("Starting change password", "REDFISH_MESSAGE_ID", msg);
John Wedig2098dab2021-09-14 13:56:28 -070084}
85
John Wedigb810c922021-11-17 16:38:03 -080086bool eStoraged::isLocked() const
87{
88 return locked();
89}
90
91std::string_view eStoraged::getMountPoint() const
92{
93 return mountPoint;
94}
95
96void eStoraged::formatLuksDev(struct crypt_device* cd,
97 std::vector<uint8_t> password)
98{
99 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
100 std::string("OpenBMC.0.1.FormatLuksDev"));
101
102 /* Generate the volume key. */
103 const std::size_t keySize = 64;
104 std::vector<uint8_t> volumeKey(keySize);
105 if (RAND_bytes(volumeKey.data(), keySize) != 1)
106 {
107 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID",
108 std::string("OpenBMC.0.1.FormatLuksDevFail"));
109 throw EncryptionError();
110 }
111 /* Format the LUKS encrypted device. */
112 int retval =
113 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr,
114 reinterpret_cast<const char*>(volumeKey.data()),
115 volumeKey.size(), nullptr);
116 if (retval < 0)
117 {
118 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL",
119 retval, "REDFISH_MESSAGE_ID",
120 std::string("OpenBMC.0.1.FormatLuksDevFail"));
121 throw EncryptionError();
122 }
123
124 /* Device is now encrypted. */
125 locked(true);
126
127 /* Set the password. */
128 retval = cryptIface->cryptKeyslotAddByVolumeKey(
129 cd, CRYPT_ANY_SLOT, nullptr, 0,
130 reinterpret_cast<const char*>(password.data()), password.size());
131
132 if (retval < 0)
133 {
134 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID",
135 std::string("OpenBMC.0.1.FormatLuksDevFail"));
136 throw EncryptionError();
137 }
138
139 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath,
140 "REDFISH_MESSAGE_ID",
141 std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
142}
143
144void eStoraged::activateLuksDev(struct crypt_device* cd,
145 std::vector<uint8_t> password)
146{
147 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
148 std::string("OpenBMC.0.1.ActivateLuksDev"));
149
150 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr);
151 if (retval < 0)
152 {
153 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval,
154 "REDFISH_MESSAGE_ID",
155 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
156 throw EncryptionError();
157 }
158
159 retval = cryptIface->cryptActivateByPassphrase(
160 cd, containerName.c_str(), CRYPT_ANY_SLOT,
161 reinterpret_cast<const char*>(password.data()), password.size(), 0);
162
163 if (retval < 0)
164 {
165 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval,
166 "REDFISH_MESSAGE_ID",
167 std::string("OpenBMC.0.1.ActivateLuksDevFail"));
168 throw EncryptionError();
169 }
170
171 /* Device is now unlocked. */
172 locked(false);
173
174 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath,
175 "REDFISH_MESSAGE_ID",
176 std::string("OpenBMC.0.1.ActivateLuksDevSuccess"));
177}
178
179void eStoraged::createFilesystem()
180{
181 /* Run the command to create the filesystem. */
182 int retval = fsIface->runMkfs(containerName);
183 if (retval)
184 {
185 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval,
186 "REDFISH_MESSAGE_ID",
187 std::string("OpenBMC.0.1.CreateFilesystemFail"));
188 throw FilesystemError();
189 }
190 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}",
191 "CONTAINER", containerName, "REDFISH_MESSAGE_ID",
192 std::string("OpenBMC.0.1.CreateFilesystemSuccess"));
193}
194
195void eStoraged::mountFilesystem()
196{
197 /* Create directory for the filesystem. */
198 bool success = fsIface->createDirectory(std::filesystem::path(mountPoint));
199 if (!success)
200 {
201 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint,
202 "REDFISH_MESSAGE_ID",
203 std::string("OpenBMC.0.1.MountFilesystemFail"));
204 throw FilesystemError();
205 }
206
207 /* Run the command to mount the filesystem. */
208 std::string luksContainer("/dev/mapper/" + containerName);
209 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(),
210 "ext4", 0, nullptr);
211 if (retval)
212 {
213 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval,
214 "REDFISH_MESSAGE_ID",
215 std::string("OpenBMC.0.1.MountFilesystemFail"));
216 bool removeSuccess =
217 fsIface->removeDirectory(std::filesystem::path(mountPoint));
218 if (!removeSuccess)
219 {
220 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint,
221 "REDFISH_MESSAGE_ID",
222 std::string("OpenBMC.0.1.MountFilesystemFail"));
223 }
224 throw FilesystemError();
225 }
226
227 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint,
228 "REDFISH_MESSAGE_ID",
229 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
230}
231
232void eStoraged::unmountFilesystem()
233{
234 int retval = fsIface->doUnmount(mountPoint.c_str());
235 if (retval)
236 {
237 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval,
238 "REDFISH_MESSAGE_ID",
239 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
240 throw FilesystemError();
241 }
242
243 /* Remove the mount point. */
244 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint));
245 if (!success)
246 {
247 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint,
248 "REDFISH_MESSAGE_ID",
249 std::string("OpenBMC.0.1.UnmountFilesystemFail"));
250 throw FilesystemError();
251 }
252
253 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint,
254 "REDFISH_MESSAGE_ID",
255 std::string("OpenBMC.0.1.MountFilesystemSuccess"));
256}
257
258void eStoraged::deactivateLuksDev()
259{
260 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath,
261 "REDFISH_MESSAGE_ID",
262 std::string("OpenBMC.0.1.DeactivateLuksDev"));
263
264 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str());
265 if (retval < 0)
266 {
267 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL",
268 retval, "REDFISH_MESSAGE_ID",
269 std::string("OpenBMC.0.1.DeactivateLuksDevFail"));
270 throw EncryptionError();
271 }
272
273 /* Device is now locked. */
274 locked(true);
275
276 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath,
277 "REDFISH_MESSAGE_ID",
278 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess"));
279}
280
John Wedig2098dab2021-09-14 13:56:28 -0700281} // namespace estoraged