1 2 #include "estoraged.hpp" 3 4 #include "cryptsetupInterface.hpp" 5 #include "pattern.hpp" 6 #include "verifyDriveGeometry.hpp" 7 #include "zero.hpp" 8 9 #include <libcryptsetup.h> 10 #include <openssl/rand.h> 11 #include <stdlib.h> 12 13 #include <phosphor-logging/lg2.hpp> 14 #include <xyz/openbmc_project/Common/error.hpp> 15 16 #include <filesystem> 17 #include <iostream> 18 #include <string_view> 19 #include <vector> 20 21 namespace estoraged 22 { 23 24 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 25 using sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound; 26 using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest; 27 28 void eStoraged::formatLuks(std::vector<uint8_t> password, FilesystemType type) 29 { 30 std::string msg = "OpenBMC.0.1.DriveFormat"; 31 lg2::info("Starting format", "REDFISH_MESSAGE_ID", msg); 32 33 if (type != FilesystemType::ext4) 34 { 35 lg2::error("Only ext4 filesystems are supported currently", 36 "REDFISH_MESSAGE_ID", std::string("OpenBMC.0.1.FormatFail")); 37 throw UnsupportedRequest(); 38 } 39 40 CryptHandle cryptHandle(devPath.c_str()); 41 if (cryptHandle.get() == nullptr) 42 { 43 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID", 44 std::string("OpenBMC.0.1.FormatFail")); 45 throw ResourceNotFound(); 46 } 47 48 formatLuksDev(cryptHandle.get(), password); 49 activateLuksDev(cryptHandle.get(), password); 50 51 createFilesystem(); 52 mountFilesystem(); 53 } 54 55 void eStoraged::erase(EraseMethod inEraseMethod) 56 { 57 std::cerr << "Erasing encrypted eMMC" << std::endl; 58 lg2::info("Starting erase", "REDFISH_MESSAGE_ID", 59 std::string("OpenBMC.0.1.DriveErase")); 60 switch (inEraseMethod) 61 { 62 case EraseMethod::CryptoErase: 63 { 64 break; 65 } 66 case EraseMethod::VerifyGeometry: 67 { 68 VerifyDriveGeometry myVerifyGeometry(devPath); 69 uint64_t size = myVerifyGeometry.findSizeOfBlockDevice(); 70 myVerifyGeometry.geometryOkay(size); 71 break; 72 } 73 case EraseMethod::LogicalOverWrite: 74 { 75 Pattern myErasePattern(devPath); 76 myErasePattern.writePattern(myErasePattern.findSizeOfBlockDevice()); 77 break; 78 } 79 case EraseMethod::LogicalVerify: 80 { 81 Pattern myErasePattern(devPath); 82 myErasePattern.verifyPattern( 83 myErasePattern.findSizeOfBlockDevice()); 84 break; 85 } 86 case EraseMethod::VendorSanitize: 87 { 88 break; 89 } 90 case EraseMethod::ZeroOverWrite: 91 { 92 Zero myZero(devPath); 93 myZero.writeZero(myZero.findSizeOfBlockDevice()); 94 break; 95 } 96 case EraseMethod::ZeroVerify: 97 { 98 Zero myZero(devPath); 99 myZero.verifyZero(myZero.findSizeOfBlockDevice()); 100 break; 101 } 102 case EraseMethod::SecuredLocked: 103 { 104 break; 105 } 106 } 107 } 108 109 void eStoraged::lock() 110 { 111 std::string msg = "OpenBMC.0.1.DriveLock"; 112 lg2::info("Starting lock", "REDFISH_MESSAGE_ID", msg); 113 114 unmountFilesystem(); 115 deactivateLuksDev(); 116 } 117 118 void eStoraged::unlock(std::vector<uint8_t> password) 119 { 120 std::string msg = "OpenBMC.0.1.DriveUnlock"; 121 lg2::info("Starting unlock", "REDFISH_MESSAGE_ID", msg); 122 123 CryptHandle cryptHandle(devPath.c_str()); 124 if (cryptHandle.get() == nullptr) 125 { 126 lg2::error("Failed to initialize crypt device", "REDFISH_MESSAGE_ID", 127 std::string("OpenBMC.0.1.UnlockFail")); 128 throw ResourceNotFound(); 129 } 130 131 activateLuksDev(cryptHandle.get(), password); 132 mountFilesystem(); 133 } 134 135 void eStoraged::changePassword(std::vector<uint8_t>, std::vector<uint8_t>) 136 { 137 std::cerr << "Changing password for encrypted eMMC" << std::endl; 138 lg2::info("Starting change password", "REDFISH_MESSAGE_ID", 139 std::string("OpenBMC.0.1.DrivePasswordChanged")); 140 } 141 142 bool eStoraged::isLocked() const 143 { 144 return locked(); 145 } 146 147 std::string_view eStoraged::getMountPoint() const 148 { 149 return mountPoint; 150 } 151 152 void eStoraged::formatLuksDev(struct crypt_device* cd, 153 std::vector<uint8_t> password) 154 { 155 lg2::info("Formatting device {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID", 156 std::string("OpenBMC.0.1.FormatLuksDev")); 157 158 /* Generate the volume key. */ 159 const std::size_t keySize = 64; 160 std::vector<uint8_t> volumeKey(keySize); 161 if (RAND_bytes(volumeKey.data(), keySize) != 1) 162 { 163 lg2::error("Failed to create volume key", "REDFISH_MESSAGE_ID", 164 std::string("OpenBMC.0.1.FormatLuksDevFail")); 165 throw InternalFailure(); 166 } 167 /* Format the LUKS encrypted device. */ 168 int retval = 169 cryptIface->cryptFormat(cd, CRYPT_LUKS2, "aes", "xts-plain64", nullptr, 170 reinterpret_cast<const char*>(volumeKey.data()), 171 volumeKey.size(), nullptr); 172 if (retval < 0) 173 { 174 lg2::error("Failed to format encrypted device: {RETVAL}", "RETVAL", 175 retval, "REDFISH_MESSAGE_ID", 176 std::string("OpenBMC.0.1.FormatLuksDevFail")); 177 throw InternalFailure(); 178 } 179 180 /* Device is now encrypted. */ 181 locked(true); 182 183 /* Set the password. */ 184 retval = cryptIface->cryptKeyslotAddByVolumeKey( 185 cd, CRYPT_ANY_SLOT, nullptr, 0, 186 reinterpret_cast<const char*>(password.data()), password.size()); 187 188 if (retval < 0) 189 { 190 lg2::error("Failed to set encryption password", "REDFISH_MESSAGE_ID", 191 std::string("OpenBMC.0.1.FormatLuksDevFail")); 192 throw InternalFailure(); 193 } 194 195 lg2::info("Encrypted device {DEV} successfully formatted", "DEV", devPath, 196 "REDFISH_MESSAGE_ID", 197 std::string("OpenBMC.0.1.FormatLuksDevSuccess")); 198 } 199 200 void eStoraged::activateLuksDev(struct crypt_device* cd, 201 std::vector<uint8_t> password) 202 { 203 lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID", 204 std::string("OpenBMC.0.1.ActivateLuksDev")); 205 206 int retval = cryptIface->cryptLoad(cd, CRYPT_LUKS2, nullptr); 207 if (retval < 0) 208 { 209 lg2::error("Failed to load LUKS header: {RETVAL}", "RETVAL", retval, 210 "REDFISH_MESSAGE_ID", 211 std::string("OpenBMC.0.1.ActivateLuksDevFail")); 212 throw InternalFailure(); 213 } 214 215 retval = cryptIface->cryptActivateByPassphrase( 216 cd, containerName.c_str(), CRYPT_ANY_SLOT, 217 reinterpret_cast<const char*>(password.data()), password.size(), 0); 218 219 if (retval < 0) 220 { 221 lg2::error("Failed to activate LUKS dev: {RETVAL}", "RETVAL", retval, 222 "REDFISH_MESSAGE_ID", 223 std::string("OpenBMC.0.1.ActivateLuksDevFail")); 224 throw InternalFailure(); 225 } 226 227 /* Device is now unlocked. */ 228 locked(false); 229 230 lg2::info("Successfully activated LUKS dev {DEV}", "DEV", devPath, 231 "REDFISH_MESSAGE_ID", 232 std::string("OpenBMC.0.1.ActivateLuksDevSuccess")); 233 } 234 235 void eStoraged::createFilesystem() 236 { 237 /* Run the command to create the filesystem. */ 238 int retval = fsIface->runMkfs(containerName); 239 if (retval) 240 { 241 lg2::error("Failed to create filesystem: {RETVAL}", "RETVAL", retval, 242 "REDFISH_MESSAGE_ID", 243 std::string("OpenBMC.0.1.CreateFilesystemFail")); 244 throw InternalFailure(); 245 } 246 lg2::info("Successfully created filesystem for /dev/mapper/{CONTAINER}", 247 "CONTAINER", containerName, "REDFISH_MESSAGE_ID", 248 std::string("OpenBMC.0.1.CreateFilesystemSuccess")); 249 } 250 251 void eStoraged::mountFilesystem() 252 { 253 /* 254 * Create directory for the filesystem, if it's not already present. It 255 * might already exist if, for example, the BMC reboots after creating the 256 * directory. 257 */ 258 if (!fsIface->directoryExists(std::filesystem::path(mountPoint))) 259 { 260 bool success = 261 fsIface->createDirectory(std::filesystem::path(mountPoint)); 262 if (!success) 263 { 264 lg2::error("Failed to create mount point: {DIR}", "DIR", mountPoint, 265 "REDFISH_MESSAGE_ID", 266 std::string("OpenBMC.0.1.MountFilesystemFail")); 267 throw InternalFailure(); 268 } 269 } 270 271 /* Run the command to mount the filesystem. */ 272 std::string luksContainer("/dev/mapper/" + containerName); 273 int retval = fsIface->doMount(luksContainer.c_str(), mountPoint.c_str(), 274 "ext4", 0, nullptr); 275 if (retval) 276 { 277 lg2::error("Failed to mount filesystem: {RETVAL}", "RETVAL", retval, 278 "REDFISH_MESSAGE_ID", 279 std::string("OpenBMC.0.1.MountFilesystemFail")); 280 bool removeSuccess = 281 fsIface->removeDirectory(std::filesystem::path(mountPoint)); 282 if (!removeSuccess) 283 { 284 lg2::error("Failed to remove mount point: {DIR}", "DIR", mountPoint, 285 "REDFISH_MESSAGE_ID", 286 std::string("OpenBMC.0.1.MountFilesystemFail")); 287 } 288 throw InternalFailure(); 289 } 290 291 lg2::info("Successfully mounted filesystem at {DIR}", "DIR", mountPoint, 292 "REDFISH_MESSAGE_ID", 293 std::string("OpenBMC.0.1.MountFilesystemSuccess")); 294 } 295 296 void eStoraged::unmountFilesystem() 297 { 298 int retval = fsIface->doUnmount(mountPoint.c_str()); 299 if (retval) 300 { 301 lg2::error("Failed to unmount filesystem: {RETVAL}", "RETVAL", retval, 302 "REDFISH_MESSAGE_ID", 303 std::string("OpenBMC.0.1.UnmountFilesystemFail")); 304 throw InternalFailure(); 305 } 306 307 /* Remove the mount point. */ 308 bool success = fsIface->removeDirectory(std::filesystem::path(mountPoint)); 309 if (!success) 310 { 311 lg2::error("Failed to remove mount point {DIR}", "DIR", mountPoint, 312 "REDFISH_MESSAGE_ID", 313 std::string("OpenBMC.0.1.UnmountFilesystemFail")); 314 throw InternalFailure(); 315 } 316 317 lg2::info("Successfully unmounted filesystem at {DIR}", "DIR", mountPoint, 318 "REDFISH_MESSAGE_ID", 319 std::string("OpenBMC.0.1.MountFilesystemSuccess")); 320 } 321 322 void eStoraged::deactivateLuksDev() 323 { 324 lg2::info("Deactivating LUKS device {DEV}", "DEV", devPath, 325 "REDFISH_MESSAGE_ID", 326 std::string("OpenBMC.0.1.DeactivateLuksDev")); 327 328 int retval = cryptIface->cryptDeactivate(nullptr, containerName.c_str()); 329 if (retval < 0) 330 { 331 lg2::error("Failed to deactivate crypt device: {RETVAL}", "RETVAL", 332 retval, "REDFISH_MESSAGE_ID", 333 std::string("OpenBMC.0.1.DeactivateLuksDevFail")); 334 throw InternalFailure(); 335 } 336 337 /* Device is now locked. */ 338 locked(true); 339 340 lg2::info("Successfully deactivated LUKS device {DEV}", "DEV", devPath, 341 "REDFISH_MESSAGE_ID", 342 std::string("OpenBMC.0.1.DeactivateLuksDevSuccess")); 343 } 344 345 } // namespace estoraged 346