vold: Support Storage keys for FBE

To prevent keys from being compromised if an attacker
acquires read access to kernel memory, some inline
encryption hardware supports protecting the keys in
hardware without software having access to or the
ability to set the plaintext keys.  Instead, software
only sees "wrapped keys", which may differ on every boot.

'wrappedkey_v0' fileencryption flag is used to denote
that the device supports inline encryption hardware that
supports this feature. On such devices keymaster is used
to generate keys with STORAGE_KEY tag and export a
per-boot ephemerally wrapped storage key to install it in
the kernel.

The wrapped key framework in the linux kernel ensures the
wrapped key is provided to the inline encryption hardware
where it is unwrapped and the file contents key is derived
to encrypt contents without revealing the plaintext key in
the clear.

Test: FBE validation with Fscrypt v2 + inline crypt + wrapped
key changes kernel.

Bug: 147733587

Change-Id: I1f0de61b56534ec1df9baef075acb74bacd00758
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 1f7faac..21495be 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -208,6 +208,19 @@
     return true;
 }
 
+static bool install_storage_key(const std::string& mountpoint, const EncryptionOptions& options,
+                                const KeyBuffer& key, EncryptionPolicy* policy) {
+    KeyBuffer ephemeral_wrapped_key;
+    if (options.use_hw_wrapped_key) {
+        if (!exportWrappedStorageKey(key, &ephemeral_wrapped_key)) {
+            LOG(ERROR) << "Failed to get ephemeral wrapped key";
+            return false;
+        }
+    }
+    return installKey(mountpoint, options, options.use_hw_wrapped_key ? ephemeral_wrapped_key : key,
+                      policy);
+}
+
 // Retrieve the options to use for encryption policies on adoptable storage.
 static bool get_volume_file_encryption_options(EncryptionOptions* options) {
     auto contents_mode =
@@ -231,7 +244,7 @@
     KeyBuffer ce_key;
     if (!read_and_fixate_user_ce_key(user_id, auth, &ce_key)) return false;
     EncryptionPolicy ce_policy;
-    if (!installKey(DATA_MNT_POINT, options, ce_key, &ce_policy)) return false;
+    if (!install_storage_key(DATA_MNT_POINT, options, ce_key, &ce_policy)) return false;
     s_ce_policies[user_id] = ce_policy;
     LOG(DEBUG) << "Installed ce key for user " << user_id;
     return true;
@@ -261,8 +274,8 @@
     EncryptionOptions options;
     if (!get_data_file_encryption_options(&options)) return false;
     KeyBuffer de_key, ce_key;
-    if (!android::vold::randomKey(&de_key)) return false;
-    if (!android::vold::randomKey(&ce_key)) return false;
+    if (!generateStorageKey(options, &de_key)) return false;
+    if (!generateStorageKey(options, &ce_key)) return false;
     if (create_ephemeral) {
         // If the key should be created as ephemeral, don't store it.
         s_ephemeral_users.insert(user_id);
@@ -282,10 +295,10 @@
             return false;
     }
     EncryptionPolicy de_policy;
-    if (!installKey(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
+    if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
     s_de_policies[user_id] = de_policy;
     EncryptionPolicy ce_policy;
-    if (!installKey(DATA_MNT_POINT, options, ce_key, &ce_policy)) return false;
+    if (!install_storage_key(DATA_MNT_POINT, options, ce_key, &ce_policy)) return false;
     s_ce_policies[user_id] = ce_policy;
     LOG(DEBUG) << "Created keys for user " << user_id;
     return true;
@@ -338,7 +351,7 @@
             KeyBuffer de_key;
             if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &de_key)) return false;
             EncryptionPolicy de_policy;
-            if (!installKey(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
+            if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
             s_de_policies[user_id] = de_policy;
             LOG(DEBUG) << "Installed de key for user " << user_id;
         }
@@ -360,12 +373,11 @@
 
     KeyBuffer device_key;
     if (!android::vold::retrieveKey(true, kEmptyAuthentication, device_key_path, device_key_temp,
-                                    &device_key))
+                                    options, &device_key))
         return false;
 
     EncryptionPolicy device_policy;
-    if (!android::vold::installKey(DATA_MNT_POINT, options, device_key, &device_policy))
-        return false;
+    if (!install_storage_key(DATA_MNT_POINT, options, device_key, &device_policy)) return false;
 
     std::string options_string;
     if (!OptionsToString(device_policy.options, &options_string)) {
@@ -380,10 +392,9 @@
     LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
 
     KeyBuffer per_boot_key;
-    if (!android::vold::randomKey(&per_boot_key)) return false;
+    if (!generateStorageKey(options, &per_boot_key)) return false;
     EncryptionPolicy per_boot_policy;
-    if (!android::vold::installKey(DATA_MNT_POINT, options, per_boot_key, &per_boot_policy))
-        return false;
+    if (!install_storage_key(DATA_MNT_POINT, options, per_boot_key, &per_boot_policy)) return false;
     std::string per_boot_ref_filename = std::string("/data") + fscrypt_key_per_boot_ref;
     if (!android::vold::writeStringToFile(per_boot_policy.key_raw_ref, per_boot_ref_filename))
         return false;
@@ -590,8 +601,9 @@
     EncryptionOptions options;
     if (!get_volume_file_encryption_options(&options)) return false;
     KeyBuffer key;
-    if (!android::vold::retrieveKey(true, auth, key_path, key_path + "_tmp", &key)) return false;
-    if (!android::vold::installKey(BuildDataPath(volume_uuid), options, key, policy)) return false;
+    if (!android::vold::retrieveKey(true, auth, key_path, key_path + "_tmp", options, &key))
+        return false;
+    if (!install_storage_key(BuildDataPath(volume_uuid), options, key, policy)) return false;
     return true;
 }