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