system: vold: Use wrapped key for metadata encryption

Wrapped key feature is needed for better security of encryption keys and to
ensure data integrity when crypto key cache is cleared during reset operation
of storage/crypto hardware.

CRs-Fixed: 2367150
Change-Id: I83d14861bf81e102151fa3417d84008c214a9ac0
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 6d510a0..5468c10 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -210,6 +210,10 @@
     return false;
 }
 
+bool is_metadata_wrapped_key_supported() {
+    return GetEntryForMountPoint(&fstab_default, METADATA_MNT_POINT)->fs_mgr_flags.wrapped_key;
+}
+
 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/FsCrypt.h b/FsCrypt.h
index d81271c..3040669 100644
--- a/FsCrypt.h
+++ b/FsCrypt.h
@@ -40,3 +40,4 @@
 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();
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index 36a7777..160c38b 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -143,7 +143,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/KeyStorage.h b/KeyStorage.h
index 72ddfc4..1980acb 100644
--- a/KeyStorage.h
+++ b/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/KeyUtil.cpp b/KeyUtil.cpp
index b1f4c3d..fd6e662 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -198,14 +198,35 @@
     if (pathExists(key_path)) {
         LOG(DEBUG) << "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(INFO) << "Creating new key in " << key_path;
-        if (!randomKey(key)) return false;
-        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;
+        }
+        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/cryptfs.h b/cryptfs.h
index 3f21d50..8574d90 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -208,6 +208,7 @@
 };
 
 #define DATA_MNT_POINT "/data"
+#define METADATA_MNT_POINT "/metadata"
 
 /* Return values for cryptfs_crypto_complete */
 #define CRYPTO_COMPLETE_NOT_ENCRYPTED 1