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