xref: /openbmc/estoraged/include/cryptsetupInterface.hpp (revision 4906f4ef7e04ddbbf18a401a5b9963748270cce2)
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     virtual ~CryptsetupInterface() = default;
25     CryptsetupInterface() = default;
26     CryptsetupInterface(const CryptsetupInterface&) = delete;
27     CryptsetupInterface& operator=(const CryptsetupInterface&) = delete;
28 
29     CryptsetupInterface(CryptsetupInterface&&) = delete;
30     CryptsetupInterface& operator=(CryptsetupInterface&&) = delete;
31     /** @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;
111 
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      */
120     virtual int cryptKeyslotDestroy(struct crypt_device* cd, int keyslot) = 0;
121 
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;
144 };
145 
146 /** @class Cryptsetup
147  *  @brief Implements CryptsetupInterface.
148  */
149 class Cryptsetup : public CryptsetupInterface
150 {
151   public:
152     ~Cryptsetup() override = default;
153 
154     Cryptsetup() = default;
155     Cryptsetup(const Cryptsetup&) = delete;
156     Cryptsetup& operator=(const Cryptsetup&) = delete;
157 
158     Cryptsetup(Cryptsetup&&) = delete;
159     Cryptsetup& operator=(Cryptsetup&&) = delete;
160     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     }
197 
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     }
213 };
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  */
219 class CryptHandle
220 {
221   public:
222     /** @brief Constructor for CryptHandle
223      *
224      *  @param[in] device - path to device file
225      */
226     explicit CryptHandle(const std::string_view& device) : handle(init(device))
227     {}
228 
229     /** @brief Get a pointer to the crypt_device struct. */
230     struct crypt_device* get()
231     {
232         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 
240         return *handle;
241     }
242 
243   private:
244     /** @brief Allocate and initialize the crypt_device struct
245      *
246      *  @param[in] device - path to device file
247      */
248     struct crypt_device* init(const std::string_view& device)
249     {
250         struct crypt_device* cryptDev = nullptr;
251         int retval = crypt_init(&cryptDev, device.data());
252         if (retval < 0)
253         {
254             lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID",
255                        std::string("OpenBMC.0.1.InitFail"));
256             throw ResourceNotFound();
257         }
258 
259         return cryptDev;
260     }
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
276