Coverage Report

Created: 2026-07-16 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/estoraged/include/cryptsetupInterface.hpp
Line
Count
Source
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
42
    virtual ~CryptsetupInterface() = default;
25
42
    CryptsetupInterface() = default;
26
    CryptsetupInterface(const CryptsetupInterface&) = delete;
27
    CryptsetupInterface& operator=(const CryptsetupInterface&) = delete;
28
29
    CryptsetupInterface(CryptsetupInterface&&) = delete;
30
    CryptsetupInterface& operator=(CryptsetupInterface&&) = delete;
31
32
    /** @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 cipherMode - including IV specification (e.g. "xts-plain").
40
     *  @params[in] uuid - requested UUID or NULL if it should be generated.
41
     *  @params[in] volumeKey - pre-generated volume key or NULL if it should
42
     *    be generated (only for LUKS).
43
     *  @params[in] volumeKeySize - 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
53
    /** @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
     */
66
    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;
70
71
    /** @brief Wrapper around crypt_keyslot_add_by_volumeKey.
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] volumeKey - provided volume key or NULL if used after
77
     *    crypt_format.
78
     *  @param[in] volumeKeySize - size of volumeKey.
79
     *  @param[in] passphrase - passphrase for new keyslot.
80
     *  @param[in] passphraseSize - size of passphrase.
81
     *
82
     *  @returns allocated key slot number or negative errno otherwise.
83
     */
84
    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;
88
89
    /** @brief Wrapper around crypt_load.
90
     *  @details Used for mocking purposes.
91
     *
92
     *  @param[in] cd - crypt device handle.
93
     *  @param[in] requestedType - 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] passphraseSize - size of passphrase.
110
     *  @param[in] flags - activation flags.
111
     *
112
     *  @returns unlocked key slot number or negative errno otherwise.
113
     */
114
    virtual int cryptActivateByPassphrase(
115
        struct crypt_device* cd, const char* name, int keyslot,
116
        const char* passphrase, size_t passphraseSize, uint32_t flags) = 0;
117
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;
127
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
     */
136
    virtual int cryptKeyslotDestroy(struct crypt_device* cd, int keyslot) = 0;
137
138
    /** @brief Wrapper around crypt_keyslot_max
139
     *  @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
148
    /** @brief Wrapper around crypt_keyslot_status
149
     *  @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
156
     */
157
    virtual crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd,
158
                                                  int keyslot) = 0;
159
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;
166
};
167
168
/** @class Cryptsetup
169
 *  @brief Implements CryptsetupInterface.
170
 */
171
class Cryptsetup : public CryptsetupInterface
172
{
173
  public:
174
    ~Cryptsetup() override = default;
175
176
    Cryptsetup() = default;
177
    Cryptsetup(const Cryptsetup&) = delete;
178
    Cryptsetup& operator=(const Cryptsetup&) = delete;
179
180
    Cryptsetup(Cryptsetup&&) = delete;
181
    Cryptsetup& operator=(Cryptsetup&&) = delete;
182
    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
0
    {
187
0
        return crypt_format(cd, type, cipher, cipherMode, uuid, volumeKey,
188
0
                            volumeKeySize, params);
189
0
    }
190
191
    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
195
0
    {
196
0
        return crypt_keyslot_change_by_passphrase(
197
0
            cd, keyslotOld, keyslotNew, passphrase, passphraseSize,
198
0
            newPassphrase, newPassphraseSize);
199
0
    }
200
201
    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
0
    {
206
0
        return crypt_keyslot_add_by_volume_key(
207
0
            cd, keyslot, volumeKey, volumeKeySize, passphrase, passphraseSize);
208
0
    }
209
210
    int cryptLoad(struct crypt_device* cd, const char* requestedType,
211
                  void* params) override
212
0
    {
213
0
        return crypt_load(cd, requestedType, params);
214
0
    }
215
216
    int cryptActivateByPassphrase(
217
        struct crypt_device* cd, const char* name, int keyslot,
218
        const char* passphrase, size_t passphraseSize, uint32_t flags) override
219
0
    {
220
0
        return crypt_activate_by_passphrase(cd, name, keyslot, passphrase,
221
0
                                            passphraseSize, flags);
222
0
    }
223
224
    int cryptDeactivate(struct crypt_device* cd, const char* name) override
225
0
    {
226
0
        return crypt_deactivate(cd, name);
227
0
    }
228
229
    int cryptKeyslotDestroy(struct crypt_device* cd, const int keyslot) override
230
0
    {
231
0
        return crypt_keyslot_destroy(cd, keyslot);
232
0
    }
233
234
    int cryptKeySlotMax(const char* type) override
235
0
    {
236
0
        return crypt_keyslot_max(type);
237
0
    }
238
239
    crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd,
240
                                          int keyslot) override
241
0
    {
242
0
        return crypt_keyslot_status(cd, keyslot);
243
0
    }
244
245
    std::string cryptGetDir() override
246
0
    {
247
0
        return {crypt_get_dir()};
248
0
    }
249
};
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
 */
255
class CryptHandle
256
{
257
  public:
258
    /** @brief Constructor for CryptHandle
259
     *
260
     *  @param[in] device - path to device file
261
     */
262
42
    explicit CryptHandle(const std::string_view& device) : handle(init(device))
263
42
    {}
264
265
    /** @brief Get a pointer to the crypt_device struct. */
266
    struct crypt_device* get()
267
189
    {
268
189
        if (*handle == nullptr)
269
0
        {
270
0
            lg2::error("Failed to get crypt device handle",
271
0
                       "REDFISH_MESSAGE_ID",
272
0
                       std::string("OpenBMC.0.1.HandleGetFail"));
273
0
            throw ResourceNotFound();
274
0
        }
275
276
189
        return *handle;
277
189
    }
278
279
  private:
280
    /** @brief Allocate and initialize the crypt_device struct
281
     *
282
     *  @param[in] device - path to device file
283
     */
284
    struct crypt_device* init(const std::string_view& device)
285
42
    {
286
42
        struct crypt_device* cryptDev = nullptr;
287
42
        int retval = crypt_init(&cryptDev, device.data());
288
42
        if (retval < 0)
289
0
        {
290
0
            lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID",
291
0
                       std::string("OpenBMC.0.1.InitFail"));
292
0
            throw ResourceNotFound();
293
0
        }
294
295
42
        return cryptDev;
296
42
    }
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
42
    {
304
42
        crypt_free(cd);
305
42
    }
306
307
    /** @brief Managed handle to crypt_device struct */
308
    stdplus::Managed<struct crypt_device*>::Handle<cryptFree> handle;
309
};
310
311
} // namespace estoraged