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