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( 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_volume_key. 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] volume_key - provided volume key or NULL if used after 77 * crypt_format. 78 * @param[in] volume_key_size - size of volume_key. 79 * @param[in] passphrase - passphrase for new keyslot. 80 * @param[in] passphrase_size - 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] requested_type - 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] passphrase_size - 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 158 cryptKeySlotStatus(struct crypt_device* cd, 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; cryptFormat(struct crypt_device * cd,const char * type,const char * cipher,const char * cipherMode,const char * uuid,const char * volumeKey,size_t volumeKeySize,void * params)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 { 187 return crypt_format(cd, type, cipher, cipherMode, uuid, volumeKey, 188 volumeKeySize, params); 189 } 190 cryptKeyslotChangeByPassphrase(struct crypt_device * cd,int keyslotOld,int keyslotNew,const char * passphrase,size_t passphraseSize,const char * newPassphrase,size_t newPassphraseSize)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 { 196 return crypt_keyslot_change_by_passphrase( 197 cd, keyslotOld, keyslotNew, passphrase, passphraseSize, 198 newPassphrase, newPassphraseSize); 199 } 200 cryptKeyslotAddByVolumeKey(struct crypt_device * cd,int keyslot,const char * volumeKey,size_t volumeKeySize,const char * passphrase,size_t passphraseSize)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 { 206 return crypt_keyslot_add_by_volume_key( 207 cd, keyslot, volumeKey, volumeKeySize, passphrase, passphraseSize); 208 } 209 cryptLoad(struct crypt_device * cd,const char * requestedType,void * params)210 int cryptLoad(struct crypt_device* cd, const char* requestedType, 211 void* params) override 212 { 213 return crypt_load(cd, requestedType, params); 214 } 215 cryptActivateByPassphrase(struct crypt_device * cd,const char * name,int keyslot,const char * passphrase,size_t passphraseSize,uint32_t flags)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 { 220 return crypt_activate_by_passphrase(cd, name, keyslot, passphrase, 221 passphraseSize, flags); 222 } 223 cryptDeactivate(struct crypt_device * cd,const char * name)224 int cryptDeactivate(struct crypt_device* cd, const char* name) override 225 { 226 return crypt_deactivate(cd, name); 227 } 228 cryptKeyslotDestroy(struct crypt_device * cd,const int keyslot)229 int cryptKeyslotDestroy(struct crypt_device* cd, const int keyslot) override 230 { 231 return crypt_keyslot_destroy(cd, keyslot); 232 } 233 cryptKeySlotMax(const char * type)234 int cryptKeySlotMax(const char* type) override 235 { 236 return crypt_keyslot_max(type); 237 } 238 cryptKeySlotStatus(struct crypt_device * cd,int keyslot)239 crypt_keyslot_info cryptKeySlotStatus(struct crypt_device* cd, 240 int keyslot) override 241 { 242 return crypt_keyslot_status(cd, keyslot); 243 } 244 cryptGetDir()245 std::string cryptGetDir() override 246 { 247 return {crypt_get_dir()}; 248 } 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 */ CryptHandle(const std::string_view & device)262 explicit CryptHandle(const std::string_view& device) : handle(init(device)) 263 {} 264 265 /** @brief Get a pointer to the crypt_device struct. */ get()266 struct crypt_device* get() 267 { 268 if (*handle == nullptr) 269 { 270 lg2::error("Failed to get crypt device handle", 271 "REDFISH_MESSAGE_ID", 272 std::string("OpenBMC.0.1.HandleGetFail")); 273 throw ResourceNotFound(); 274 } 275 276 return *handle; 277 } 278 279 private: 280 /** @brief Allocate and initialize the crypt_device struct 281 * 282 * @param[in] device - path to device file 283 */ init(const std::string_view & device)284 struct crypt_device* init(const std::string_view& device) 285 { 286 struct crypt_device* cryptDev = nullptr; 287 int retval = crypt_init(&cryptDev, device.data()); 288 if (retval < 0) 289 { 290 lg2::error("Failed to crypt_init", "REDFISH_MESSAGE_ID", 291 std::string("OpenBMC.0.1.InitFail")); 292 throw ResourceNotFound(); 293 } 294 295 return cryptDev; 296 } 297 298 /** @brief Free the crypt_device struct 299 * 300 * @param[in] cd - pointer to crypt_device*, to be freed 301 */ cryptFree(struct crypt_device * && cd)302 static void cryptFree(struct crypt_device*&& cd) 303 { 304 crypt_free(cd); 305 } 306 307 /** @brief Managed handle to crypt_device struct */ 308 stdplus::Managed<struct crypt_device*>::Handle<cryptFree> handle; 309 }; 310 311 } // namespace estoraged 312