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