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