blob: 4f824cd666c860e079d1050c624fe9388d30d980 [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 */
Patrick Williams15b63e12024-08-16 15:22:01 -040066 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;
John Wedig8d5a3a02022-09-29 15:25:58 -070070
John Wedigb810c922021-11-17 16:38:03 -080071 /** @brief Wrapper around crypt_keyslot_add_by_volume_key.
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] volume_key - provided volume key or NULL if used after
77 * crypt_format.
78 * @param[in] volume_key_size - size of volume_key.
79 * @param[in] passphrase - passphrase for new keyslot.
80 * @param[in] passphrase_size - size of passphrase.
81 *
82 * @returns allocated key slot number or negative errno otherwise.
83 */
Patrick Williams15b63e12024-08-16 15:22:01 -040084 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;
John Wedigb810c922021-11-17 16:38:03 -080088
89 /** @brief Wrapper around crypt_load.
90 * @details Used for mocking purposes.
91 *
92 * @param[in] cd - crypt device handle.
93 * @param[in] requested_type - 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] passphrase_size - size of passphrase.
110 * @param[in] flags - activation flags.
111 *
112 * @returns unlocked key slot number or negative errno otherwise.
113 */
Patrick Williams15b63e12024-08-16 15:22:01 -0400114 virtual int cryptActivateByPassphrase(
115 struct crypt_device* cd, const char* name, int keyslot,
116 const char* passphrase, size_t passphraseSize, uint32_t flags) = 0;
John Wedigb810c922021-11-17 16:38:03 -0800117
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;
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800127
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 */
Ed Tanous82897c32022-02-21 14:11:59 -0800136 virtual int cryptKeyslotDestroy(struct crypt_device* cd, int keyslot) = 0;
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800137
John Wedig2443a022023-03-17 13:42:32 -0700138 /** @brief Wrapper around crypt_keyslot_max
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800139 * @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
John Wedig2443a022023-03-17 13:42:32 -0700148 /** @brief Wrapper around crypt_keyslot_status
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800149 * @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
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800156 */
Patrick Williams15b63e12024-08-16 15:22:01 -0400157 virtual crypt_keyslot_info
158 cryptKeySlotStatus(struct crypt_device* cd, int keyslot) = 0;
John Wedig2443a022023-03-17 13:42:32 -0700159
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;
John Wedigb810c922021-11-17 16:38:03 -0800166};
167
168/** @class Cryptsetup
169 * @brief Implements CryptsetupInterface.
170 */
171class Cryptsetup : public CryptsetupInterface
172{
173 public:
Ed Tanous82897c32022-02-21 14:11:59 -0800174 ~Cryptsetup() override = default;
John Wedigb810c922021-11-17 16:38:03 -0800175
Ed Tanous82897c32022-02-21 14:11:59 -0800176 Cryptsetup() = default;
177 Cryptsetup(const Cryptsetup&) = delete;
178 Cryptsetup& operator=(const Cryptsetup&) = delete;
179
180 Cryptsetup(Cryptsetup&&) = delete;
181 Cryptsetup& operator=(Cryptsetup&&) = delete;
John Wedigb810c922021-11-17 16:38:03 -0800182 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 {
187 return crypt_format(cd, type, cipher, cipherMode, uuid, volumeKey,
188 volumeKeySize, params);
189 }
190
Patrick Williams15b63e12024-08-16 15:22:01 -0400191 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
John Wedig8d5a3a02022-09-29 15:25:58 -0700195 {
196 return crypt_keyslot_change_by_passphrase(
197 cd, keyslotOld, keyslotNew, passphrase, passphraseSize,
198 newPassphrase, newPassphraseSize);
199 }
200
John Wedigb810c922021-11-17 16:38:03 -0800201 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 {
206 return crypt_keyslot_add_by_volume_key(
207 cd, keyslot, volumeKey, volumeKeySize, passphrase, passphraseSize);
208 }
209
210 int cryptLoad(struct crypt_device* cd, const char* requestedType,
211 void* params) override
212 {
213 return crypt_load(cd, requestedType, params);
214 }
215
Patrick Williams15b63e12024-08-16 15:22:01 -0400216 int cryptActivateByPassphrase(
217 struct crypt_device* cd, const char* name, int keyslot,
218 const char* passphrase, size_t passphraseSize, uint32_t flags) override
John Wedigb810c922021-11-17 16:38:03 -0800219 {
220 return crypt_activate_by_passphrase(cd, name, keyslot, passphrase,
221 passphraseSize, flags);
222 }
223
224 int cryptDeactivate(struct crypt_device* cd, const char* name) override
225 {
226 return crypt_deactivate(cd, name);
227 }
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800228
229 int cryptKeyslotDestroy(struct crypt_device* cd, const int keyslot) override
230 {
231 return crypt_keyslot_destroy(cd, keyslot);
232 }
233
234 int cryptKeySlotMax(const char* type) override
235 {
236 return crypt_keyslot_max(type);
237 }
238
239 crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd,
240 int keyslot) override
241 {
242 return crypt_keyslot_status(cd, keyslot);
243 }
John Wedig2443a022023-03-17 13:42:32 -0700244
245 std::string cryptGetDir() override
246 {
247 return {crypt_get_dir()};
248 }
John Wedigb810c922021-11-17 16:38:03 -0800249};
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 */
255class CryptHandle
256{
257 public:
258 /** @brief Constructor for CryptHandle
259 *
John Wedigb810c922021-11-17 16:38:03 -0800260 * @param[in] device - path to device file
261 */
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700262 explicit CryptHandle(const std::string_view& device) : handle(init(device))
John Wedigb810c922021-11-17 16:38:03 -0800263 {}
264
John Wedig6218dc52021-12-03 09:36:35 -0800265 /** @brief Get a pointer to the crypt_device struct. */
266 struct crypt_device* get()
267 {
John Edward Broadbent2b5454d2022-04-14 19:28:12 -0700268 if (*handle == nullptr)
269 {
270 lg2::error("Failed to get crypt device handle",
271 "REDFISH_MESSAGE_ID",
272 std::string("OpenBMC.0.1.HandleGetFail"));
273 throw ResourceNotFound();
274 }
275
John Wedig6218dc52021-12-03 09:36:35 -0800276 return *handle;
277 }
278
279 private:
John Wedigb810c922021-11-17 16:38:03 -0800280 /** @brief Allocate and initialize the crypt_device struct
281 *
John Wedigb810c922021-11-17 16:38:03 -0800282 * @param[in] device - path to device file
283 */
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700284 struct crypt_device* init(const std::string_view& device)
John Wedigb810c922021-11-17 16:38:03 -0800285 {
Ed Tanous82897c32022-02-21 14:11:59 -0800286 struct crypt_device* cryptDev = nullptr;
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700287 int retval = crypt_init(&cryptDev, device.data());
John Wedigb810c922021-11-17 16:38:03 -0800288 if (retval < 0)
289 {
John Edward Broadbent28cc8342022-04-14 19:28:12 -0700290 lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID",
291 std::string("OpenBMC.0.1.InitFail"));
292 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800293 }
294
John Wedig6218dc52021-12-03 09:36:35 -0800295 return cryptDev;
John Wedigb810c922021-11-17 16:38:03 -0800296 }
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 {
304 crypt_free(cd);
305 }
306
307 /** @brief Managed handle to crypt_device struct */
308 stdplus::Managed<struct crypt_device*>::Handle<cryptFree> handle;
309};
310
311} // namespace estoraged