Add DriveEncryptionState property

Tested:
Verify the property is as expected (Encrypted). Then wipe the disk, and
re-check the value to verify it is as expected (unknown).

$ busctl get-property xyz.openbmc_project.eStoraged \
/xyz/openbmc_project/inventory/storage/mmcblk0 \
xyz.openbmc_project.Inventory.Item.Drive EncryptionStatus s \
"xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Encrypted"

$ busctl call xyz.openbmc_project.eStoraged \
/xyz/openbmc_project/inventory/storage/mmcblk0 \
xyz.openbmc_project.Inventory.Item.Volume Erase s \
xyz.openbmc_project.Inventory.Item.Volume.EraseMethod.VendorSanitize

$ busctl get-property xyz.openbmc_project.eStoraged \
/xyz/openbmc_project/inventory/storage/mmcblk0 \
xyz.openbmc_project.Inventory.Item.Drive EncryptionStatus s \
"xyz.openbmc_project.Inventory.Item.Drive.DriveEncryptionState.Unknown"

Signed-off-by: John Edward Broadbent <jebr@google.com>
Change-Id: I4abba7a1e7f047c481aaf4938b2b1e2b7d7ec6be
diff --git a/src/estoraged.cpp b/src/estoraged.cpp
index af20d32..7c26e8a 100644
--- a/src/estoraged.cpp
+++ b/src/estoraged.cpp
@@ -29,6 +29,7 @@
 using Association = std::tuple<std::string, std::string, std::string>;
 using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 using sdbusplus::xyz::openbmc_project::Common::Error::UnsupportedRequest;
+using sdbusplus::xyz::openbmc_project::Inventory::Item::server::Drive;
 using sdbusplus::xyz::openbmc_project::Inventory::Item::server::Volume;
 
 EStoraged::EStoraged(sdbusplus::asio::object_server& server,
@@ -40,7 +41,8 @@
     devPath(devPath),
     containerName(luksName), mountPoint("/mnt/" + luksName + "_fs"),
     lockedProperty(false), cryptIface(std::move(cryptInterface)),
-    fsIface(std::move(fsInterface)), objectServer(server)
+    fsIface(std::move(fsInterface)), objectServer(server),
+    encryptionStatus(Drive::DriveEncryptionState::Unknown)
 {
     /* Get the filename of the device (without "/dev/"). */
     std::string deviceName = std::filesystem::path(devPath).filename().string();
@@ -82,6 +84,14 @@
     driveInterface->register_property("PredictedMediaLifeLeftPercent",
                                       lifeTime);
 
+    driveInterface->register_property_r(
+        "EncryptionStatus", encryptionStatus,
+        sdbusplus::vtable::property_::emits_change,
+        [this](Drive::DriveEncryptionState& value) {
+            value = this->findEncryptionStatus();
+            return value;
+        });
+
     volumeInterface->initialize();
     driveInterface->initialize();
 
@@ -272,12 +282,9 @@
               std::string("OpenBMC.0.1.FormatLuksDevSuccess"));
 }
 
-void EStoraged::activateLuksDev(std::vector<uint8_t> password)
+CryptHandle EStoraged::loadLuksHeader()
 {
-    lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
-              std::string("OpenBMC.0.1.ActivateLuksDev"));
 
-    /* Create the handle. */
     CryptHandle cryptHandle(devPath);
 
     int retval = cryptIface->cryptLoad(cryptHandle.get(), CRYPT_LUKS2, nullptr);
@@ -288,8 +295,31 @@
                    std::string("OpenBMC.0.1.ActivateLuksDevFail"));
         throw InternalFailure();
     }
+    return cryptHandle;
+}
 
-    retval = cryptIface->cryptActivateByPassphrase(
+Drive::DriveEncryptionState EStoraged::findEncryptionStatus()
+{
+    try
+    {
+        loadLuksHeader();
+        return Drive::DriveEncryptionState::Encrypted;
+    }
+    catch (...)
+    {
+        return Drive::DriveEncryptionState::Unknown;
+    }
+}
+
+void EStoraged::activateLuksDev(std::vector<uint8_t> password)
+{
+    lg2::info("Activating LUKS dev {DEV}", "DEV", devPath, "REDFISH_MESSAGE_ID",
+              std::string("OpenBMC.0.1.ActivateLuksDev"));
+
+    /* Create the handle. */
+    CryptHandle cryptHandle = loadLuksHeader();
+
+    int retval = cryptIface->cryptActivateByPassphrase(
         cryptHandle.get(), containerName.c_str(), CRYPT_ANY_SLOT,
         reinterpret_cast<const char*>(password.data()), password.size(), 0);