Emulate media encryption, always chmod to unlock.

When FBE emulation is enabled, lock/unlock the media directories that
store emulated SD card contents.

Change unlocking logic to always chmod directories back to known
state so that we can recover devices that have disabled FBE
emulation.

Bug: 26010607, 26027473
Change-Id: I6d4bff25d8ad7b948679290106f585f777f7a249
diff --git a/Ext4Crypt.cpp b/Ext4Crypt.cpp
index 1f92e57..f90ba56 100644
--- a/Ext4Crypt.cpp
+++ b/Ext4Crypt.cpp
@@ -52,7 +52,15 @@
 
 using android::base::StringPrintf;
 
-static const char* kPropEmulateFbe = "persist.sys.emulate_fbe";
+static bool e4crypt_is_native() {
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.crypto.type", value, "none");
+    return !strcmp(value, "file");
+}
+
+static bool e4crypt_is_emulated() {
+    return property_get_bool("persist.sys.emulate_fbe", false);
+}
 
 namespace {
     // Key length in bits
@@ -685,14 +693,7 @@
 }
 
 int e4crypt_unlock_user_key(userid_t user_id, const char* token) {
-    if (property_get_bool(kPropEmulateFbe, false)) {
-        // When in emulation mode, we just use chmod
-        if (chmod(android::vold::BuildDataSystemCePath(user_id).c_str(), 0771) ||
-                chmod(android::vold::BuildDataUserPath(nullptr, user_id).c_str(), 0771)) {
-            PLOG(ERROR) << "Failed to unlock user " << user_id;
-            return -1;
-        }
-    } else {
+    if (e4crypt_is_native()) {
         auto user_key = e4crypt_get_key(get_key_path(DATA_MNT_POINT, user_id), false);
         if (user_key.empty()) {
             return -1;
@@ -701,21 +702,34 @@
         if (raw_ref.empty()) {
             return -1;
         }
+    } else {
+        // When in emulation mode, we just use chmod. However, we also
+        // unlock directories when not in emulation mode, to bring devices
+        // back into a known-good state.
+        if (chmod(android::vold::BuildDataSystemCePath(user_id).c_str(), 0771) ||
+                chmod(android::vold::BuildDataMediaPath(nullptr, user_id).c_str(), 0770) ||
+                chmod(android::vold::BuildDataUserPath(nullptr, user_id).c_str(), 0771)) {
+            PLOG(ERROR) << "Failed to unlock user " << user_id;
+            return -1;
+        }
     }
+
     return 0;
 }
 
 int e4crypt_lock_user_key(userid_t user_id) {
-    if (property_get_bool(kPropEmulateFbe, false)) {
+    if (e4crypt_is_native()) {
+        // TODO: remove from kernel keyring
+    } else if (e4crypt_is_emulated()) {
         // When in emulation mode, we just use chmod
         if (chmod(android::vold::BuildDataSystemCePath(user_id).c_str(), 0000) ||
+                chmod(android::vold::BuildDataMediaPath(nullptr, user_id).c_str(), 0000) ||
                 chmod(android::vold::BuildDataUserPath(nullptr, user_id).c_str(), 0000)) {
             PLOG(ERROR) << "Failed to lock user " << user_id;
             return -1;
         }
-    } else {
-        // TODO: remove from kernel keyring
     }
+
     return 0;
 }
 
diff --git a/Utils.cpp b/Utils.cpp
index 5276bba..aba3a53 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -576,6 +576,12 @@
     }
 }
 
+std::string BuildDataMediaPath(const char* volumeUuid, userid_t userId) {
+    // TODO: unify with installd path generation logic
+    std::string data(BuildDataPath(volumeUuid));
+    return StringPrintf("%s/media/%u", data.c_str(), userId);
+}
+
 std::string BuildDataUserPath(const char* volumeUuid, userid_t userId) {
     // TODO: unify with installd path generation logic
     std::string data(BuildDataPath(volumeUuid));
diff --git a/Utils.h b/Utils.h
index c88325a..0a74af7 100644
--- a/Utils.h
+++ b/Utils.h
@@ -97,6 +97,7 @@
 std::string BuildDataSystemCePath(userid_t userid);
 
 std::string BuildDataPath(const char* volumeUuid);
+std::string BuildDataMediaPath(const char* volumeUuid, userid_t userid);
 std::string BuildDataUserPath(const char* volumeUuid, userid_t userid);
 std::string BuildDataUserDePath(const char* volumeUuid, userid_t userid);