blob: fb03a8b5ed49cd4d4bccd0a5cd6b3af5310b1942 [file] [log] [blame]
John Wedigb810c922021-11-17 16:38:03 -08001#pragma once
2
3#include <libcryptsetup.h>
4
John Edward Broadbent2b5454d2022-04-14 19:28:12 -07005#include <phosphor-logging/lg2.hpp>
John Wedigb810c922021-11-17 16:38:03 -08006#include <stdplus/handle/managed.hpp>
John Edward Broadbent2b5454d2022-04-14 19:28:12 -07007#include <xyz/openbmc_project/Common/error.hpp>
8
9#include <string>
John Edward Broadbentb2c86be2022-04-15 11:45:53 -070010#include <string_view>
John Wedigb810c922021-11-17 16:38:03 -080011
12namespace estoraged
13{
14
John Edward Broadbent2b5454d2022-04-14 19:28:12 -070015using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound;
16
John Wedigb810c922021-11-17 16:38:03 -080017/** @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 */
21class CryptsetupInterface
22{
23 public:
24 virtual ~CryptsetupInterface() = default;
Ed Tanous82897c32022-02-21 14:11:59 -080025 CryptsetupInterface() = default;
26 CryptsetupInterface(const CryptsetupInterface&) = delete;
27 CryptsetupInterface& operator=(const CryptsetupInterface&) = delete;
John Wedigb810c922021-11-17 16:38:03 -080028
Ed Tanous82897c32022-02-21 14:11:59 -080029 CryptsetupInterface(CryptsetupInterface&&) = delete;
30 CryptsetupInterface& operator=(CryptsetupInterface&&) = delete;
John Wedig8d5a3a02022-09-29 15:25:58 -070031
John Wedigb810c922021-11-17 16:38:03 -080032 /** @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 cipher_mode - including IV specification (e.g. "xts-plain").
40 * @params[in] uuid - requested UUID or NULL if it should be generated.
41 * @params[in] volume_key - pre-generated volume key or NULL if it should
42 * be generated (only for LUKS).
43 * @params[in] volume_key_size - 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
John Wedig8d5a3a02022-09-29 15:25:58 -070053 /** @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(struct crypt_device* cd,
67 int keyslotOld, int keyslotNew,
68 const char* passphrase,
69 size_t passphraseSize,
70 const char* newPassphrase,
71 size_t newPassphraseSize) = 0;
72
John Wedigb810c922021-11-17 16:38:03 -080073 /** @brief Wrapper around crypt_keyslot_add_by_volume_key.
74 * @details Used for mocking purposes.
75 *
76 * @param[in] cd - crypt device handle.
77 * @param[in] keyslot - requested keyslot or CRYPT_ANY_SLOT.
78 * @param[in] volume_key - provided volume key or NULL if used after
79 * crypt_format.
80 * @param[in] volume_key_size - size of volume_key.
81 * @param[in] passphrase - passphrase for new keyslot.
82 * @param[in] passphrase_size - size of passphrase.
83 *
84 * @returns allocated key slot number or negative errno otherwise.
85 */
86 virtual int cryptKeyslotAddByVolumeKey(struct crypt_device* cd, int keyslot,
87 const char* volumeKey,
88 size_t volumeKeySize,
89 const char* passphrase,
90 size_t passphraseSize) = 0;
91
92 /** @brief Wrapper around crypt_load.
93 * @details Used for mocking purposes.
94 *
95 * @param[in] cd - crypt device handle.
96 * @param[in] requested_type - crypt-type or NULL for all known.
97 * @param[in] params - crypt type specific parameters (see crypt-type).
98 *
99 * @returns 0 on success or negative errno value otherwise.
100 */
101 virtual int cryptLoad(struct crypt_device* cd, const char* requestedType,
102 void* params) = 0;
103
104 /** @brief Wrapper around crypt_activate_by_passphrase.
105 * @details Used for mocking purposes.
106 *
107 * @param[in] cd - crypt device handle.
108 * @param[in] name - name of device to create, if NULL only check
109 * passphrase.
110 * @param[in] keyslot - requested keyslot to check or CRYPT_ANY_SLOT.
111 * @param[in] passphrase - passphrase used to unlock volume key.
112 * @param[in] passphrase_size - size of passphrase.
113 * @param[in] flags - activation flags.
114 *
115 * @returns unlocked key slot number or negative errno otherwise.
116 */
117 virtual int cryptActivateByPassphrase(struct crypt_device* cd,
118 const char* name, int keyslot,
119 const char* passphrase,
120 size_t passphraseSize,
121 uint32_t flags) = 0;
122
123 /** @brief Wrapper around crypt_deactivate.
124 * @details Used for mocking purposes.
125 *
126 * @param[in] cd - crypt device handle, can be NULL.
127 * @param[in] name - name of device to deactivate.
128 *
129 * @returns 0 on success or negative errno value otherwise.
130 */
131 virtual int cryptDeactivate(struct crypt_device* cd, const char* name) = 0;
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800132
133 /** @brief Wrapper around crypt_keyslot_destory.
134 * @details Used for mocking purposes.
135 *
136 * @param[in] cd - crypt device handle, can not be NULL.
137 * @param[in] keyslot requested key slot to destroy
138 *
139 * @returns 0 on success or negative errno value otherwise.
140 */
Ed Tanous82897c32022-02-21 14:11:59 -0800141 virtual int cryptKeyslotDestroy(struct crypt_device* cd, int keyslot) = 0;
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800142
John Wedig2443a022023-03-17 13:42:32 -0700143 /** @brief Wrapper around crypt_keyslot_max
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800144 * @details Used for mocking purposes.
145 *
146 * @param type crypt device type
147 *
148 * @return slot count or negative errno otherwise if device
149 * does not support keyslots.
150 */
151 virtual int cryptKeySlotMax(const char* type) = 0;
152
John Wedig2443a022023-03-17 13:42:32 -0700153 /** @brief Wrapper around crypt_keyslot_status
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800154 * @details Used for mocking purposes.
155 * Get information about particular key slot.
156 *
157 * @param cd crypt device handle
158 * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT
159 *
160 * @return value defined by crypt_keyslot_info
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800161 */
162 virtual crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd,
163 int keyslot) = 0;
John Wedig2443a022023-03-17 13:42:32 -0700164
165 /** @brief Wrapper around crypt_get_dir.
166 * @details Used for mocking purposes.
167 *
168 * @returns the directory where mapped crypt devices are created.
169 */
170 virtual std::string cryptGetDir() = 0;
John Wedigb810c922021-11-17 16:38:03 -0800171};
172
173/** @class Cryptsetup
174 * @brief Implements CryptsetupInterface.
175 */
176class Cryptsetup : public CryptsetupInterface
177{
178 public:
Ed Tanous82897c32022-02-21 14:11:59 -0800179 ~Cryptsetup() override = default;
John Wedigb810c922021-11-17 16:38:03 -0800180
Ed Tanous82897c32022-02-21 14:11:59 -0800181 Cryptsetup() = default;
182 Cryptsetup(const Cryptsetup&) = delete;
183 Cryptsetup& operator=(const Cryptsetup&) = delete;
184
185 Cryptsetup(Cryptsetup&&) = delete;
186 Cryptsetup& operator=(Cryptsetup&&) = delete;
John Wedigb810c922021-11-17 16:38:03 -0800187 int cryptFormat(struct crypt_device* cd, const char* type,
188 const char* cipher, const char* cipherMode,
189 const char* uuid, const char* volumeKey,
190 size_t volumeKeySize, void* params) override
191 {
192 return crypt_format(cd, type, cipher, cipherMode, uuid, volumeKey,
193 volumeKeySize, params);
194 }
195
John Wedig8d5a3a02022-09-29 15:25:58 -0700196 int cryptKeyslotChangeByPassphrase(struct crypt_device* cd, int keyslotOld,
197 int keyslotNew, const char* passphrase,
198 size_t passphraseSize,
199 const char* newPassphrase,
200 size_t newPassphraseSize) override
201 {
202 return crypt_keyslot_change_by_passphrase(
203 cd, keyslotOld, keyslotNew, passphrase, passphraseSize,
204 newPassphrase, newPassphraseSize);
205 }
206
John Wedigb810c922021-11-17 16:38:03 -0800207 int cryptKeyslotAddByVolumeKey(struct crypt_device* cd, int keyslot,
208 const char* volumeKey, size_t volumeKeySize,
209 const char* passphrase,
210 size_t passphraseSize) override
211 {
212 return crypt_keyslot_add_by_volume_key(
213 cd, keyslot, volumeKey, volumeKeySize, passphrase, passphraseSize);
214 }
215
216 int cryptLoad(struct crypt_device* cd, const char* requestedType,
217 void* params) override
218 {
219 return crypt_load(cd, requestedType, params);
220 }
221
222 int cryptActivateByPassphrase(struct crypt_device* cd, const char* name,
223 int keyslot, const char* passphrase,
224 size_t passphraseSize,
225 uint32_t flags) override
226 {
227 return crypt_activate_by_passphrase(cd, name, keyslot, passphrase,
228 passphraseSize, flags);
229 }
230
231 int cryptDeactivate(struct crypt_device* cd, const char* name) override
232 {
233 return crypt_deactivate(cd, name);
234 }
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800235
236 int cryptKeyslotDestroy(struct crypt_device* cd, const int keyslot) override
237 {
238 return crypt_keyslot_destroy(cd, keyslot);
239 }
240
241 int cryptKeySlotMax(const char* type) override
242 {
243 return crypt_keyslot_max(type);
244 }
245
246 crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd,
247 int keyslot) override
248 {
249 return crypt_keyslot_status(cd, keyslot);
250 }
John Wedig2443a022023-03-17 13:42:32 -0700251
252 std::string cryptGetDir() override
253 {
254 return {crypt_get_dir()};
255 }
John Wedigb810c922021-11-17 16:38:03 -0800256};
257
258/** @class CryptHandle
259 * @brief This manages a crypt_device struct and automatically frees it when
260 * this handle exits the current scope.
261 */
262class CryptHandle
263{
264 public:
265 /** @brief Constructor for CryptHandle
266 *
John Wedigb810c922021-11-17 16:38:03 -0800267 * @param[in] device - path to device file
268 */
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700269 explicit CryptHandle(const std::string_view& device) : handle(init(device))
John Wedigb810c922021-11-17 16:38:03 -0800270 {}
271
John Wedig6218dc52021-12-03 09:36:35 -0800272 /** @brief Get a pointer to the crypt_device struct. */
273 struct crypt_device* get()
274 {
John Edward Broadbent2b5454d2022-04-14 19:28:12 -0700275 if (*handle == nullptr)
276 {
277 lg2::error("Failed to get crypt device handle",
278 "REDFISH_MESSAGE_ID",
279 std::string("OpenBMC.0.1.HandleGetFail"));
280 throw ResourceNotFound();
281 }
282
John Wedig6218dc52021-12-03 09:36:35 -0800283 return *handle;
284 }
285
286 private:
John Wedigb810c922021-11-17 16:38:03 -0800287 /** @brief Allocate and initialize the crypt_device struct
288 *
John Wedigb810c922021-11-17 16:38:03 -0800289 * @param[in] device - path to device file
290 */
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700291 struct crypt_device* init(const std::string_view& device)
John Wedigb810c922021-11-17 16:38:03 -0800292 {
Ed Tanous82897c32022-02-21 14:11:59 -0800293 struct crypt_device* cryptDev = nullptr;
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700294 int retval = crypt_init(&cryptDev, device.data());
John Wedigb810c922021-11-17 16:38:03 -0800295 if (retval < 0)
296 {
John Edward Broadbent28cc8342022-04-14 19:28:12 -0700297 lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID",
298 std::string("OpenBMC.0.1.InitFail"));
299 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800300 }
301
John Wedig6218dc52021-12-03 09:36:35 -0800302 return cryptDev;
John Wedigb810c922021-11-17 16:38:03 -0800303 }
304
305 /** @brief Free the crypt_device struct
306 *
307 * @param[in] cd - pointer to crypt_device*, to be freed
308 */
309 static void cryptFree(struct crypt_device*&& cd)
310 {
311 crypt_free(cd);
312 }
313
314 /** @brief Managed handle to crypt_device struct */
315 stdplus::Managed<struct crypt_device*>::Handle<cryptFree> handle;
316};
317
318} // namespace estoraged