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 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 cipher_mode - including IV specification (e.g. "xts-plain"). 40 * @params[in] uuid - requested UUID or NULL if it should be generated. 41 * @params[in] volume_key - pre-generated volume key or NULL if it should 42 * be generated (only for LUKS). 43 * @params[in] volume_key_size - 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(struct crypt_device* cd, 67 int keyslotOld, int keyslotNew, 68 const char* passphrase, 69 size_t passphraseSize, 70 const char* newPassphrase, 71 size_t newPassphraseSize) = 0; 72 73 /** @brief Wrapper around crypt_keyslot_add_by_volume_key. 74 * @details Used for mocking purposes. 75 * 76 * @param[in] cd - crypt device handle. 77 * @param[in] keyslot - requested keyslot or CRYPT_ANY_SLOT. 78 * @param[in] volume_key - provided volume key or NULL if used after 79 * crypt_format. 80 * @param[in] volume_key_size - size of volume_key. 81 * @param[in] passphrase - passphrase for new keyslot. 82 * @param[in] passphrase_size - size of passphrase. 83 * 84 * @returns allocated key slot number or negative errno otherwise. 85 */ 86 virtual int cryptKeyslotAddByVolumeKey(struct crypt_device* cd, int keyslot, 87 const char* volumeKey, 88 size_t volumeKeySize, 89 const char* passphrase, 90 size_t passphraseSize) = 0; 91 92 /** @brief Wrapper around crypt_load. 93 * @details Used for mocking purposes. 94 * 95 * @param[in] cd - crypt device handle. 96 * @param[in] requested_type - crypt-type or NULL for all known. 97 * @param[in] params - crypt type specific parameters (see crypt-type). 98 * 99 * @returns 0 on success or negative errno value otherwise. 100 */ 101 virtual int cryptLoad(struct crypt_device* cd, const char* requestedType, 102 void* params) = 0; 103 104 /** @brief Wrapper around crypt_activate_by_passphrase. 105 * @details Used for mocking purposes. 106 * 107 * @param[in] cd - crypt device handle. 108 * @param[in] name - name of device to create, if NULL only check 109 * passphrase. 110 * @param[in] keyslot - requested keyslot to check or CRYPT_ANY_SLOT. 111 * @param[in] passphrase - passphrase used to unlock volume key. 112 * @param[in] passphrase_size - size of passphrase. 113 * @param[in] flags - activation flags. 114 * 115 * @returns unlocked key slot number or negative errno otherwise. 116 */ 117 virtual int cryptActivateByPassphrase(struct crypt_device* cd, 118 const char* name, int keyslot, 119 const char* passphrase, 120 size_t passphraseSize, 121 uint32_t flags) = 0; 122 123 /** @brief Wrapper around crypt_deactivate. 124 * @details Used for mocking purposes. 125 * 126 * @param[in] cd - crypt device handle, can be NULL. 127 * @param[in] name - name of device to deactivate. 128 * 129 * @returns 0 on success or negative errno value otherwise. 130 */ 131 virtual int cryptDeactivate(struct crypt_device* cd, const char* name) = 0; 132 133 /** @brief Wrapper around crypt_keyslot_destory. 134 * @details Used for mocking purposes. 135 * 136 * @param[in] cd - crypt device handle, can not be NULL. 137 * @param[in] keyslot requested key slot to destroy 138 * 139 * @returns 0 on success or negative errno value otherwise. 140 */ 141 virtual int cryptKeyslotDestroy(struct crypt_device* cd, int keyslot) = 0; 142 143 /** @brief Wrapper around crypt_keyslot_max 144 * @details Used for mocking purposes. 145 * 146 * @param type crypt device type 147 * 148 * @return slot count or negative errno otherwise if device 149 * does not support keyslots. 150 */ 151 virtual int cryptKeySlotMax(const char* type) = 0; 152 153 /** @brief Wrapper around crypt_keyslot_status 154 * @details Used for mocking purposes. 155 * Get information about particular key slot. 156 * 157 * @param cd crypt device handle 158 * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT 159 * 160 * @return value defined by crypt_keyslot_info 161 */ 162 virtual crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd, 163 int keyslot) = 0; 164 165 /** @brief Wrapper around crypt_get_dir. 166 * @details Used for mocking purposes. 167 * 168 * @returns the directory where mapped crypt devices are created. 169 */ 170 virtual std::string cryptGetDir() = 0; 171 }; 172 173 /** @class Cryptsetup 174 * @brief Implements CryptsetupInterface. 175 */ 176 class Cryptsetup : public CryptsetupInterface 177 { 178 public: 179 ~Cryptsetup() override = default; 180 181 Cryptsetup() = default; 182 Cryptsetup(const Cryptsetup&) = delete; 183 Cryptsetup& operator=(const Cryptsetup&) = delete; 184 185 Cryptsetup(Cryptsetup&&) = delete; 186 Cryptsetup& operator=(Cryptsetup&&) = delete; 187 int cryptFormat(struct crypt_device* cd, const char* type, 188 const char* cipher, const char* cipherMode, 189 const char* uuid, const char* volumeKey, 190 size_t volumeKeySize, void* params) override 191 { 192 return crypt_format(cd, type, cipher, cipherMode, uuid, volumeKey, 193 volumeKeySize, params); 194 } 195 196 int cryptKeyslotChangeByPassphrase(struct crypt_device* cd, int keyslotOld, 197 int keyslotNew, const char* passphrase, 198 size_t passphraseSize, 199 const char* newPassphrase, 200 size_t newPassphraseSize) override 201 { 202 return crypt_keyslot_change_by_passphrase( 203 cd, keyslotOld, keyslotNew, passphrase, passphraseSize, 204 newPassphrase, newPassphraseSize); 205 } 206 207 int cryptKeyslotAddByVolumeKey(struct crypt_device* cd, int keyslot, 208 const char* volumeKey, size_t volumeKeySize, 209 const char* passphrase, 210 size_t passphraseSize) override 211 { 212 return crypt_keyslot_add_by_volume_key( 213 cd, keyslot, volumeKey, volumeKeySize, passphrase, passphraseSize); 214 } 215 216 int cryptLoad(struct crypt_device* cd, const char* requestedType, 217 void* params) override 218 { 219 return crypt_load(cd, requestedType, params); 220 } 221 222 int cryptActivateByPassphrase(struct crypt_device* cd, const char* name, 223 int keyslot, const char* passphrase, 224 size_t passphraseSize, 225 uint32_t flags) override 226 { 227 return crypt_activate_by_passphrase(cd, name, keyslot, passphrase, 228 passphraseSize, flags); 229 } 230 231 int cryptDeactivate(struct crypt_device* cd, const char* name) override 232 { 233 return crypt_deactivate(cd, name); 234 } 235 236 int cryptKeyslotDestroy(struct crypt_device* cd, const int keyslot) override 237 { 238 return crypt_keyslot_destroy(cd, keyslot); 239 } 240 241 int cryptKeySlotMax(const char* type) override 242 { 243 return crypt_keyslot_max(type); 244 } 245 246 crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd, 247 int keyslot) override 248 { 249 return crypt_keyslot_status(cd, keyslot); 250 } 251 252 std::string cryptGetDir() override 253 { 254 return {crypt_get_dir()}; 255 } 256 }; 257 258 /** @class CryptHandle 259 * @brief This manages a crypt_device struct and automatically frees it when 260 * this handle exits the current scope. 261 */ 262 class CryptHandle 263 { 264 public: 265 /** @brief Constructor for CryptHandle 266 * 267 * @param[in] device - path to device file 268 */ 269 explicit CryptHandle(const std::string_view& device) : handle(init(device)) 270 {} 271 272 /** @brief Get a pointer to the crypt_device struct. */ 273 struct crypt_device* get() 274 { 275 if (*handle == nullptr) 276 { 277 lg2::error("Failed to get crypt device handle", 278 "REDFISH_MESSAGE_ID", 279 std::string("OpenBMC.0.1.HandleGetFail")); 280 throw ResourceNotFound(); 281 } 282 283 return *handle; 284 } 285 286 private: 287 /** @brief Allocate and initialize the crypt_device struct 288 * 289 * @param[in] device - path to device file 290 */ 291 struct crypt_device* init(const std::string_view& device) 292 { 293 struct crypt_device* cryptDev = nullptr; 294 int retval = crypt_init(&cryptDev, device.data()); 295 if (retval < 0) 296 { 297 lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID", 298 std::string("OpenBMC.0.1.InitFail")); 299 throw ResourceNotFound(); 300 } 301 302 return cryptDev; 303 } 304 305 /** @brief Free the crypt_device struct 306 * 307 * @param[in] cd - pointer to crypt_device*, to be freed 308 */ 309 static void cryptFree(struct crypt_device*&& cd) 310 { 311 crypt_free(cd); 312 } 313 314 /** @brief Managed handle to crypt_device struct */ 315 stdplus::Managed<struct crypt_device*>::Handle<cryptFree> handle; 316 }; 317 318 } // namespace estoraged 319