/src/estoraged/include/cryptsetupInterface.hpp
Line | Count | Source |
1 | | #pragma once |
2 | | |
3 | | #include <libcryptsetup.h> |
4 | | |
5 | | #include <phosphor-logging/lg2.hpp> |
6 | | #include <stdplus/handle/managed.hpp> |
7 | | #include <xyz/openbmc_project/Common/error.hpp> |
8 | | |
9 | | #include <string> |
10 | | #include <string_view> |
11 | | |
12 | | namespace estoraged |
13 | | { |
14 | | |
15 | | using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound; |
16 | | |
17 | | /** @class CryptsetupInterface |
18 | | * @brief Interface to the cryptsetup functions used to manage a LUKS device. |
19 | | * @details This class is used to mock out the cryptsetup functions. |
20 | | */ |
21 | | class CryptsetupInterface |
22 | | { |
23 | | public: |
24 | 42 | virtual ~CryptsetupInterface() = default; |
25 | 42 | CryptsetupInterface() = default; |
26 | | CryptsetupInterface(const CryptsetupInterface&) = delete; |
27 | | CryptsetupInterface& operator=(const CryptsetupInterface&) = delete; |
28 | | |
29 | | CryptsetupInterface(CryptsetupInterface&&) = delete; |
30 | | CryptsetupInterface& operator=(CryptsetupInterface&&) = delete; |
31 | | |
32 | | /** @brief Wrapper around crypt_format. |
33 | | * @details Used for mocking purposes. |
34 | | * |
35 | | * @param[in] cd - crypt device handle. |
36 | | * @param[in] type - type of device (optional params struct must be of |
37 | | * this type). |
38 | | * @param[in] cipher - (e.g. "aes"). |
39 | | * @params[in cipherMode - including IV specification (e.g. "xts-plain"). |
40 | | * @params[in] uuid - requested UUID or NULL if it should be generated. |
41 | | * @params[in] volumeKey - pre-generated volume key or NULL if it should |
42 | | * be generated (only for LUKS). |
43 | | * @params[in] volumeKeySize - size of volume key in bytes. |
44 | | * @params[in] params - crypt type specific parameters. |
45 | | * |
46 | | * @returns 0 on success or negative errno value otherwise. |
47 | | */ |
48 | | virtual int cryptFormat(struct crypt_device* cd, const char* type, |
49 | | const char* cipher, const char* cipherMode, |
50 | | const char* uuid, const char* volumeKey, |
51 | | size_t volumeKeySize, void* params) = 0; |
52 | | |
53 | | /** @brief Wrapper around crypt_keyslot_change_by_passphrase. |
54 | | * @details Used for mocking purposes. |
55 | | * |
56 | | * @param[in] cd - crypt device handle. |
57 | | * @param[in] keyslotOld - old keyslot or CRYPT_ANY_SLOT. |
58 | | * @param[in] keyslotNew - new keyslot or CRYPT_ANY_SLOT. |
59 | | * @param[in] passphrase - passphrase for new keyslot. |
60 | | * @param[in] passphraseSize - size of passphrase. |
61 | | * @param[in] newPassphrase - new passphrase for the specified keyslot |
62 | | * @param[in] newPassphraseSize - size of newPassphrase (in bytes). |
63 | | * |
64 | | * @returns allocated key slot number or negative errno otherwise. |
65 | | */ |
66 | | virtual int cryptKeyslotChangeByPassphrase( |
67 | | struct crypt_device* cd, int keyslotOld, int keyslotNew, |
68 | | const char* passphrase, size_t passphraseSize, |
69 | | const char* newPassphrase, size_t newPassphraseSize) = 0; |
70 | | |
71 | | /** @brief Wrapper around crypt_keyslot_add_by_volumeKey. |
72 | | * @details Used for mocking purposes. |
73 | | * |
74 | | * @param[in] cd - crypt device handle. |
75 | | * @param[in] keyslot - requested keyslot or CRYPT_ANY_SLOT. |
76 | | * @param[in] volumeKey - provided volume key or NULL if used after |
77 | | * crypt_format. |
78 | | * @param[in] volumeKeySize - size of volumeKey. |
79 | | * @param[in] passphrase - passphrase for new keyslot. |
80 | | * @param[in] passphraseSize - size of passphrase. |
81 | | * |
82 | | * @returns allocated key slot number or negative errno otherwise. |
83 | | */ |
84 | | virtual int cryptKeyslotAddByVolumeKey( |
85 | | struct crypt_device* cd, int keyslot, const char* volumeKey, |
86 | | size_t volumeKeySize, const char* passphrase, |
87 | | size_t passphraseSize) = 0; |
88 | | |
89 | | /** @brief Wrapper around crypt_load. |
90 | | * @details Used for mocking purposes. |
91 | | * |
92 | | * @param[in] cd - crypt device handle. |
93 | | * @param[in] requestedType - crypt-type or NULL for all known. |
94 | | * @param[in] params - crypt type specific parameters (see crypt-type). |
95 | | * |
96 | | * @returns 0 on success or negative errno value otherwise. |
97 | | */ |
98 | | virtual int cryptLoad(struct crypt_device* cd, const char* requestedType, |
99 | | void* params) = 0; |
100 | | |
101 | | /** @brief Wrapper around crypt_activate_by_passphrase. |
102 | | * @details Used for mocking purposes. |
103 | | * |
104 | | * @param[in] cd - crypt device handle. |
105 | | * @param[in] name - name of device to create, if NULL only check |
106 | | * passphrase. |
107 | | * @param[in] keyslot - requested keyslot to check or CRYPT_ANY_SLOT. |
108 | | * @param[in] passphrase - passphrase used to unlock volume key. |
109 | | * @param[in] passphraseSize - size of passphrase. |
110 | | * @param[in] flags - activation flags. |
111 | | * |
112 | | * @returns unlocked key slot number or negative errno otherwise. |
113 | | */ |
114 | | virtual int cryptActivateByPassphrase( |
115 | | struct crypt_device* cd, const char* name, int keyslot, |
116 | | const char* passphrase, size_t passphraseSize, uint32_t flags) = 0; |
117 | | |
118 | | /** @brief Wrapper around crypt_deactivate. |
119 | | * @details Used for mocking purposes. |
120 | | * |
121 | | * @param[in] cd - crypt device handle, can be NULL. |
122 | | * @param[in] name - name of device to deactivate. |
123 | | * |
124 | | * @returns 0 on success or negative errno value otherwise. |
125 | | */ |
126 | | virtual int cryptDeactivate(struct crypt_device* cd, const char* name) = 0; |
127 | | |
128 | | /** @brief Wrapper around crypt_keyslot_destory. |
129 | | * @details Used for mocking purposes. |
130 | | * |
131 | | * @param[in] cd - crypt device handle, can not be NULL. |
132 | | * @param[in] keyslot requested key slot to destroy |
133 | | * |
134 | | * @returns 0 on success or negative errno value otherwise. |
135 | | */ |
136 | | virtual int cryptKeyslotDestroy(struct crypt_device* cd, int keyslot) = 0; |
137 | | |
138 | | /** @brief Wrapper around crypt_keyslot_max |
139 | | * @details Used for mocking purposes. |
140 | | * |
141 | | * @param type crypt device type |
142 | | * |
143 | | * @return slot count or negative errno otherwise if device |
144 | | * does not support keyslots. |
145 | | */ |
146 | | virtual int cryptKeySlotMax(const char* type) = 0; |
147 | | |
148 | | /** @brief Wrapper around crypt_keyslot_status |
149 | | * @details Used for mocking purposes. |
150 | | * Get information about particular key slot. |
151 | | * |
152 | | * @param cd crypt device handle |
153 | | * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT |
154 | | * |
155 | | * @return value defined by crypt_keyslot_info |
156 | | */ |
157 | | virtual crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd, |
158 | | int keyslot) = 0; |
159 | | |
160 | | /** @brief Wrapper around crypt_get_dir. |
161 | | * @details Used for mocking purposes. |
162 | | * |
163 | | * @returns the directory where mapped crypt devices are created. |
164 | | */ |
165 | | virtual std::string cryptGetDir() = 0; |
166 | | }; |
167 | | |
168 | | /** @class Cryptsetup |
169 | | * @brief Implements CryptsetupInterface. |
170 | | */ |
171 | | class Cryptsetup : public CryptsetupInterface |
172 | | { |
173 | | public: |
174 | | ~Cryptsetup() override = default; |
175 | | |
176 | | Cryptsetup() = default; |
177 | | Cryptsetup(const Cryptsetup&) = delete; |
178 | | Cryptsetup& operator=(const Cryptsetup&) = delete; |
179 | | |
180 | | Cryptsetup(Cryptsetup&&) = delete; |
181 | | Cryptsetup& operator=(Cryptsetup&&) = delete; |
182 | | int cryptFormat(struct crypt_device* cd, const char* type, |
183 | | const char* cipher, const char* cipherMode, |
184 | | const char* uuid, const char* volumeKey, |
185 | | size_t volumeKeySize, void* params) override |
186 | 0 | { |
187 | 0 | return crypt_format(cd, type, cipher, cipherMode, uuid, volumeKey, |
188 | 0 | volumeKeySize, params); |
189 | 0 | } |
190 | | |
191 | | int cryptKeyslotChangeByPassphrase( |
192 | | struct crypt_device* cd, int keyslotOld, int keyslotNew, |
193 | | const char* passphrase, size_t passphraseSize, |
194 | | const char* newPassphrase, size_t newPassphraseSize) override |
195 | 0 | { |
196 | 0 | return crypt_keyslot_change_by_passphrase( |
197 | 0 | cd, keyslotOld, keyslotNew, passphrase, passphraseSize, |
198 | 0 | newPassphrase, newPassphraseSize); |
199 | 0 | } |
200 | | |
201 | | int cryptKeyslotAddByVolumeKey(struct crypt_device* cd, int keyslot, |
202 | | const char* volumeKey, size_t volumeKeySize, |
203 | | const char* passphrase, |
204 | | size_t passphraseSize) override |
205 | 0 | { |
206 | 0 | return crypt_keyslot_add_by_volume_key( |
207 | 0 | cd, keyslot, volumeKey, volumeKeySize, passphrase, passphraseSize); |
208 | 0 | } |
209 | | |
210 | | int cryptLoad(struct crypt_device* cd, const char* requestedType, |
211 | | void* params) override |
212 | 0 | { |
213 | 0 | return crypt_load(cd, requestedType, params); |
214 | 0 | } |
215 | | |
216 | | int cryptActivateByPassphrase( |
217 | | struct crypt_device* cd, const char* name, int keyslot, |
218 | | const char* passphrase, size_t passphraseSize, uint32_t flags) override |
219 | 0 | { |
220 | 0 | return crypt_activate_by_passphrase(cd, name, keyslot, passphrase, |
221 | 0 | passphraseSize, flags); |
222 | 0 | } |
223 | | |
224 | | int cryptDeactivate(struct crypt_device* cd, const char* name) override |
225 | 0 | { |
226 | 0 | return crypt_deactivate(cd, name); |
227 | 0 | } |
228 | | |
229 | | int cryptKeyslotDestroy(struct crypt_device* cd, const int keyslot) override |
230 | 0 | { |
231 | 0 | return crypt_keyslot_destroy(cd, keyslot); |
232 | 0 | } |
233 | | |
234 | | int cryptKeySlotMax(const char* type) override |
235 | 0 | { |
236 | 0 | return crypt_keyslot_max(type); |
237 | 0 | } |
238 | | |
239 | | crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd, |
240 | | int keyslot) override |
241 | 0 | { |
242 | 0 | return crypt_keyslot_status(cd, keyslot); |
243 | 0 | } |
244 | | |
245 | | std::string cryptGetDir() override |
246 | 0 | { |
247 | 0 | return {crypt_get_dir()}; |
248 | 0 | } |
249 | | }; |
250 | | |
251 | | /** @class CryptHandle |
252 | | * @brief This manages a crypt_device struct and automatically frees it when |
253 | | * this handle exits the current scope. |
254 | | */ |
255 | | class CryptHandle |
256 | | { |
257 | | public: |
258 | | /** @brief Constructor for CryptHandle |
259 | | * |
260 | | * @param[in] device - path to device file |
261 | | */ |
262 | 42 | explicit CryptHandle(const std::string_view& device) : handle(init(device)) |
263 | 42 | {} |
264 | | |
265 | | /** @brief Get a pointer to the crypt_device struct. */ |
266 | | struct crypt_device* get() |
267 | 189 | { |
268 | 189 | if (*handle == nullptr) |
269 | 0 | { |
270 | 0 | lg2::error("Failed to get crypt device handle", |
271 | 0 | "REDFISH_MESSAGE_ID", |
272 | 0 | std::string("OpenBMC.0.1.HandleGetFail")); |
273 | 0 | throw ResourceNotFound(); |
274 | 0 | } |
275 | | |
276 | 189 | return *handle; |
277 | 189 | } |
278 | | |
279 | | private: |
280 | | /** @brief Allocate and initialize the crypt_device struct |
281 | | * |
282 | | * @param[in] device - path to device file |
283 | | */ |
284 | | struct crypt_device* init(const std::string_view& device) |
285 | 42 | { |
286 | 42 | struct crypt_device* cryptDev = nullptr; |
287 | 42 | int retval = crypt_init(&cryptDev, device.data()); |
288 | 42 | if (retval < 0) |
289 | 0 | { |
290 | 0 | lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID", |
291 | 0 | std::string("OpenBMC.0.1.InitFail")); |
292 | 0 | throw ResourceNotFound(); |
293 | 0 | } |
294 | | |
295 | 42 | return cryptDev; |
296 | 42 | } |
297 | | |
298 | | /** @brief Free the crypt_device struct |
299 | | * |
300 | | * @param[in] cd - pointer to crypt_device*, to be freed |
301 | | */ |
302 | | static void cryptFree(struct crypt_device*&& cd) |
303 | 42 | { |
304 | 42 | crypt_free(cd); |
305 | 42 | } |
306 | | |
307 | | /** @brief Managed handle to crypt_device struct */ |
308 | | stdplus::Managed<struct crypt_device*>::Handle<cryptFree> handle; |
309 | | }; |
310 | | |
311 | | } // namespace estoraged |