fscrypt: : Use wrapped key for metadata encryption

Importing of this commit:
https://github.com/LineageOS/android_system_vold/commit/944c48d5a4c6df1eb751b04f52c06adac35ebab6

Change-Id: I048a6c2aeff2591135f47223a99af5ddd215703c
diff --git a/crypto/fscrypt/FsCrypt.cpp b/crypto/fscrypt/FsCrypt.cpp
index 46df2b6..e967339 100755
--- a/crypto/fscrypt/FsCrypt.cpp
+++ b/crypto/fscrypt/FsCrypt.cpp
@@ -230,6 +230,18 @@
     return false;
 }
 
+bool is_metadata_wrapped_key_supported() {
+	LOG(DEBUG) << "Determining metadata wrapped-key support for " << mount_point;
+	std::string wrapped_key_supported = android::base::GetProperty("fbe.metadata.wrappedkey", "false");
+	LOG(DEBUG) << "fbe.metadata.wrappedkey = " << wrapped_key_supported;
+    if (mount_point == METADATA_MNT_POINT && wrapped_key_supported == "true") {
+        LOG(DEBUG) << "Wrapped key supported on " << mount_point;
+        return true;
+    } else {
+        return false;
+    }
+}
+
 static bool read_and_install_user_ce_key(userid_t user_id,
                                          const android::vold::KeyAuthentication& auth) {
     if (s_ce_key_raw_refs.count(user_id) != 0) return true;
diff --git a/crypto/fscrypt/FsCrypt.h b/crypto/fscrypt/FsCrypt.h
index 11a338f..c63e11f 100755
--- a/crypto/fscrypt/FsCrypt.h
+++ b/crypto/fscrypt/FsCrypt.h
@@ -42,5 +42,6 @@
 bool fscrypt_destroy_volume_keys(const std::string& volume_uuid);
 bool is_wrapped_key_supported();
 bool is_wrapped_key_supported_external();
+bool is_metadata_wrapped_key_supported();
 bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id,
                            std::string* raw_ref);
\ No newline at end of file
diff --git a/crypto/fscrypt/KeyStorage.cpp b/crypto/fscrypt/KeyStorage.cpp
index 9457591..068c069 100755
--- a/crypto/fscrypt/KeyStorage.cpp
+++ b/crypto/fscrypt/KeyStorage.cpp
@@ -146,7 +146,7 @@
     paramBuilder.push_back(param1);
 
     km::KeyParameter param2;
-    if ((key_type == KeyType::DE_USER) || (key_type == KeyType::DE_SYS)) {
+    if ((key_type == KeyType::DE_USER) || (key_type == KeyType::DE_SYS || (key_type == KeyType::ME))) {
         param2.tag = (km::Tag) (android::hardware::keymaster::V4_0::KM_TAG_KEY_TYPE);
         param2.f.integer = 0;
     } else if (key_type == KeyType::CE_USER) {
diff --git a/crypto/fscrypt/KeyStorage.h b/crypto/fscrypt/KeyStorage.h
index 72ddfc4..9959ce6 100755
--- a/crypto/fscrypt/KeyStorage.h
+++ b/crypto/fscrypt/KeyStorage.h
@@ -43,7 +43,8 @@
 enum class KeyType {
     DE_SYS,
     DE_USER,
-    CE_USER
+    CE_USER,
+	ME,
 };
 
 extern const KeyAuthentication kEmptyAuthentication;
diff --git a/crypto/fscrypt/KeyUtil.cpp b/crypto/fscrypt/KeyUtil.cpp
index 70a551c..fa40640 100755
--- a/crypto/fscrypt/KeyUtil.cpp
+++ b/crypto/fscrypt/KeyUtil.cpp
@@ -199,15 +199,36 @@
     if (pathExists(key_path)) {
         LOG(ERROR) << "Key exists, using: " << key_path;
         if (!retrieveKey(key_path, kEmptyAuthentication, key, keepOld)) return false;
+			if (is_metadata_wrapped_key_supported()) {
+				KeyBuffer ephemeral_wrapped_key;
+				if (!getEphemeralWrappedKey(KeyFormat::RAW, *key, &ephemeral_wrapped_key)) {
+					LOG(ERROR) << "Failed to export key for retrieved key";
+					return false;
+				}
+				*key = std::move(ephemeral_wrapped_key);
+			}
     } else {
         if (!create_if_absent) {
             LOG(ERROR) << "No key found in " << key_path;
             return false;
         }
         LOG(ERROR) << "Creating new key in " << key_path;
-        if (!randomKey(key)) return false;
-        LOG(ERROR) << "retrieveKey1";
-        if (!storeKeyAtomically(key_path, tmp_path, kEmptyAuthentication, *key)) return false;
+        if (is_metadata_wrapped_key_supported()) {
+            if(!generateWrappedKey(MAX_USER_ID, KeyType::ME, key)) return false;
+        } else {
+            if (!randomKey(key)) return false;
+        }
+		LOG(ERROR) << "retrieveKey1";
+        if (!storeKeyAtomically(key_path, tmp_path,
+                kEmptyAuthentication, *key)) return false;
+	if (is_metadata_wrapped_key_supported()) {
+            KeyBuffer ephemeral_wrapped_key;
+            if (!getEphemeralWrappedKey(KeyFormat::RAW, *key, &ephemeral_wrapped_key)) {
+                LOG(ERROR) << "Failed to export key for generated key";
+                return false;
+            }
+            *key = std::move(ephemeral_wrapped_key);
+        }
     }
     return true;
 }
diff --git a/crypto/fscrypt/cryptfs.h b/crypto/fscrypt/cryptfs.h
index 692d7ee..a4fe87b 100644
--- a/crypto/fscrypt/cryptfs.h
+++ b/crypto/fscrypt/cryptfs.h
@@ -200,6 +200,7 @@
 };
 
 #define DATA_MNT_POINT "/data"
+#define METADATA_MNT_POINT "/metadata"
 
 /* Return values for cryptfs_crypto_complete */
 #define CRYPTO_COMPLETE_NOT_ENCRYPTED 1