blob: 5942b6074f517456b92e4b0e39ce078502eb614d [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 Wedigb810c922021-11-17 16:38:03 -080031 /** @brief Wrapper around crypt_format.
32 * @details Used for mocking purposes.
33 *
34 * @param[in] cd - crypt device handle.
35 * @param[in] type - type of device (optional params struct must be of
36 * this type).
37 * @param[in] cipher - (e.g. "aes").
38 * @params[in cipher_mode - including IV specification (e.g. "xts-plain").
39 * @params[in] uuid - requested UUID or NULL if it should be generated.
40 * @params[in] volume_key - pre-generated volume key or NULL if it should
41 * be generated (only for LUKS).
42 * @params[in] volume_key_size - size of volume key in bytes.
43 * @params[in] params - crypt type specific parameters.
44 *
45 * @returns 0 on success or negative errno value otherwise.
46 */
47 virtual int cryptFormat(struct crypt_device* cd, const char* type,
48 const char* cipher, const char* cipherMode,
49 const char* uuid, const char* volumeKey,
50 size_t volumeKeySize, void* params) = 0;
51
52 /** @brief Wrapper around crypt_keyslot_add_by_volume_key.
53 * @details Used for mocking purposes.
54 *
55 * @param[in] cd - crypt device handle.
56 * @param[in] keyslot - requested keyslot or CRYPT_ANY_SLOT.
57 * @param[in] volume_key - provided volume key or NULL if used after
58 * crypt_format.
59 * @param[in] volume_key_size - size of volume_key.
60 * @param[in] passphrase - passphrase for new keyslot.
61 * @param[in] passphrase_size - size of passphrase.
62 *
63 * @returns allocated key slot number or negative errno otherwise.
64 */
65 virtual int cryptKeyslotAddByVolumeKey(struct crypt_device* cd, int keyslot,
66 const char* volumeKey,
67 size_t volumeKeySize,
68 const char* passphrase,
69 size_t passphraseSize) = 0;
70
71 /** @brief Wrapper around crypt_load.
72 * @details Used for mocking purposes.
73 *
74 * @param[in] cd - crypt device handle.
75 * @param[in] requested_type - crypt-type or NULL for all known.
76 * @param[in] params - crypt type specific parameters (see crypt-type).
77 *
78 * @returns 0 on success or negative errno value otherwise.
79 */
80 virtual int cryptLoad(struct crypt_device* cd, const char* requestedType,
81 void* params) = 0;
82
83 /** @brief Wrapper around crypt_activate_by_passphrase.
84 * @details Used for mocking purposes.
85 *
86 * @param[in] cd - crypt device handle.
87 * @param[in] name - name of device to create, if NULL only check
88 * passphrase.
89 * @param[in] keyslot - requested keyslot to check or CRYPT_ANY_SLOT.
90 * @param[in] passphrase - passphrase used to unlock volume key.
91 * @param[in] passphrase_size - size of passphrase.
92 * @param[in] flags - activation flags.
93 *
94 * @returns unlocked key slot number or negative errno otherwise.
95 */
96 virtual int cryptActivateByPassphrase(struct crypt_device* cd,
97 const char* name, int keyslot,
98 const char* passphrase,
99 size_t passphraseSize,
100 uint32_t flags) = 0;
101
102 /** @brief Wrapper around crypt_deactivate.
103 * @details Used for mocking purposes.
104 *
105 * @param[in] cd - crypt device handle, can be NULL.
106 * @param[in] name - name of device to deactivate.
107 *
108 * @returns 0 on success or negative errno value otherwise.
109 */
110 virtual int cryptDeactivate(struct crypt_device* cd, const char* name) = 0;
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800111
112 /** @brief Wrapper around crypt_keyslot_destory.
113 * @details Used for mocking purposes.
114 *
115 * @param[in] cd - crypt device handle, can not be NULL.
116 * @param[in] keyslot requested key slot to destroy
117 *
118 * @returns 0 on success or negative errno value otherwise.
119 */
Ed Tanous82897c32022-02-21 14:11:59 -0800120 virtual int cryptKeyslotDestroy(struct crypt_device* cd, int keyslot) = 0;
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800121
122 /** @breif Wapper around crypt_keyslot_max
123 * @details Used for mocking purposes.
124 *
125 * @param type crypt device type
126 *
127 * @return slot count or negative errno otherwise if device
128 * does not support keyslots.
129 */
130 virtual int cryptKeySlotMax(const char* type) = 0;
131
132 /** @breif Wapper around crypt_keyslot_status
133 * @details Used for mocking purposes.
134 * Get information about particular key slot.
135 *
136 * @param cd crypt device handle
137 * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT
138 *
139 * @return value defined by crypt_keyslot_info
140 *
141 */
142 virtual crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd,
143 int keyslot) = 0;
John Wedigb810c922021-11-17 16:38:03 -0800144};
145
146/** @class Cryptsetup
147 * @brief Implements CryptsetupInterface.
148 */
149class Cryptsetup : public CryptsetupInterface
150{
151 public:
Ed Tanous82897c32022-02-21 14:11:59 -0800152 ~Cryptsetup() override = default;
John Wedigb810c922021-11-17 16:38:03 -0800153
Ed Tanous82897c32022-02-21 14:11:59 -0800154 Cryptsetup() = default;
155 Cryptsetup(const Cryptsetup&) = delete;
156 Cryptsetup& operator=(const Cryptsetup&) = delete;
157
158 Cryptsetup(Cryptsetup&&) = delete;
159 Cryptsetup& operator=(Cryptsetup&&) = delete;
John Wedigb810c922021-11-17 16:38:03 -0800160 int cryptFormat(struct crypt_device* cd, const char* type,
161 const char* cipher, const char* cipherMode,
162 const char* uuid, const char* volumeKey,
163 size_t volumeKeySize, void* params) override
164 {
165 return crypt_format(cd, type, cipher, cipherMode, uuid, volumeKey,
166 volumeKeySize, params);
167 }
168
169 int cryptKeyslotAddByVolumeKey(struct crypt_device* cd, int keyslot,
170 const char* volumeKey, size_t volumeKeySize,
171 const char* passphrase,
172 size_t passphraseSize) override
173 {
174 return crypt_keyslot_add_by_volume_key(
175 cd, keyslot, volumeKey, volumeKeySize, passphrase, passphraseSize);
176 }
177
178 int cryptLoad(struct crypt_device* cd, const char* requestedType,
179 void* params) override
180 {
181 return crypt_load(cd, requestedType, params);
182 }
183
184 int cryptActivateByPassphrase(struct crypt_device* cd, const char* name,
185 int keyslot, const char* passphrase,
186 size_t passphraseSize,
187 uint32_t flags) override
188 {
189 return crypt_activate_by_passphrase(cd, name, keyslot, passphrase,
190 passphraseSize, flags);
191 }
192
193 int cryptDeactivate(struct crypt_device* cd, const char* name) override
194 {
195 return crypt_deactivate(cd, name);
196 }
John Edward Broadbent59dffa62022-01-13 17:41:32 -0800197
198 int cryptKeyslotDestroy(struct crypt_device* cd, const int keyslot) override
199 {
200 return crypt_keyslot_destroy(cd, keyslot);
201 }
202
203 int cryptKeySlotMax(const char* type) override
204 {
205 return crypt_keyslot_max(type);
206 }
207
208 crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd,
209 int keyslot) override
210 {
211 return crypt_keyslot_status(cd, keyslot);
212 }
John Wedigb810c922021-11-17 16:38:03 -0800213};
214
215/** @class CryptHandle
216 * @brief This manages a crypt_device struct and automatically frees it when
217 * this handle exits the current scope.
218 */
219class CryptHandle
220{
221 public:
222 /** @brief Constructor for CryptHandle
223 *
John Wedigb810c922021-11-17 16:38:03 -0800224 * @param[in] device - path to device file
225 */
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700226 explicit CryptHandle(const std::string_view& device) : handle(init(device))
John Wedigb810c922021-11-17 16:38:03 -0800227 {}
228
John Wedig6218dc52021-12-03 09:36:35 -0800229 /** @brief Get a pointer to the crypt_device struct. */
230 struct crypt_device* get()
231 {
John Edward Broadbent2b5454d2022-04-14 19:28:12 -0700232 if (*handle == nullptr)
233 {
234 lg2::error("Failed to get crypt device handle",
235 "REDFISH_MESSAGE_ID",
236 std::string("OpenBMC.0.1.HandleGetFail"));
237 throw ResourceNotFound();
238 }
239
John Wedig6218dc52021-12-03 09:36:35 -0800240 return *handle;
241 }
242
243 private:
John Wedigb810c922021-11-17 16:38:03 -0800244 /** @brief Allocate and initialize the crypt_device struct
245 *
John Wedigb810c922021-11-17 16:38:03 -0800246 * @param[in] device - path to device file
247 */
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700248 struct crypt_device* init(const std::string_view& device)
John Wedigb810c922021-11-17 16:38:03 -0800249 {
Ed Tanous82897c32022-02-21 14:11:59 -0800250 struct crypt_device* cryptDev = nullptr;
John Edward Broadbentb2c86be2022-04-15 11:45:53 -0700251 int retval = crypt_init(&cryptDev, device.data());
John Wedigb810c922021-11-17 16:38:03 -0800252 if (retval < 0)
253 {
John Edward Broadbent28cc8342022-04-14 19:28:12 -0700254 lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID",
255 std::string("OpenBMC.0.1.InitFail"));
256 throw ResourceNotFound();
John Wedigb810c922021-11-17 16:38:03 -0800257 }
258
John Wedig6218dc52021-12-03 09:36:35 -0800259 return cryptDev;
John Wedigb810c922021-11-17 16:38:03 -0800260 }
261
262 /** @brief Free the crypt_device struct
263 *
264 * @param[in] cd - pointer to crypt_device*, to be freed
265 */
266 static void cryptFree(struct crypt_device*&& cd)
267 {
268 crypt_free(cd);
269 }
270
271 /** @brief Managed handle to crypt_device struct */
272 stdplus::Managed<struct crypt_device*>::Handle<cryptFree> handle;
273};
274
275} // namespace estoraged