Merge tag 'android-15.0.0_r32' of https://android.googlesource.com/platform/system/vold into HEAD

Android 15.0.0 Release 32 (BP1A.250505.005)

Change-Id: I3f302f1544037b4bfff2a2464200de2b81941cc1

# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCaBqG7wAKCRDorT+BmrEO
# eE5LAJ9WbpwcEdFFrJfhHDXOSCERvUMUGwCdHgfqIq2OHP0eLOhNBsBrfMOSHgQ=
# =EXJ6
# -----END PGP SIGNATURE-----
# gpg: Signature faite le mar 06 mai 2025 18:02:23 EDT
# gpg:                avec la clef DSA 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Impossible de vérifier la signature : Pas de clef publique
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 563dd4f..2c90f95 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -331,6 +331,10 @@
                       "32-bit DUNs.  Remove this flag from the device's fstab";
         return false;
     }
+    if (s_data_options.version == 1) {
+        s_data_options.use_hw_wrapped_key =
+            GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT)->fs_mgr_flags.wrapped_key;
+    }
     return true;
 }
 
@@ -375,6 +379,10 @@
     return true;
 }
 
+bool is_metadata_wrapped_key_supported() {
+    return GetEntryForMountPoint(&fstab_default, METADATA_MNT_POINT)->fs_mgr_flags.wrapped_key;
+}
+
 // Prepare a directory without assigning it an encryption policy.  The directory
 // will inherit the encryption policy of its parent directory, or will be
 // unencrypted if the parent directory is unencrypted.
diff --git a/FsCrypt.h b/FsCrypt.h
index be21fba..d4a482c 100644
--- a/FsCrypt.h
+++ b/FsCrypt.h
@@ -36,3 +36,4 @@
 bool fscrypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
 
 bool fscrypt_destroy_volume_keys(const std::string& volume_uuid);
+bool is_metadata_wrapped_key_supported();
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index 5090b4e..125ee2b 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -65,6 +65,8 @@
 static const char* kFn_version = "version";
 // Note: old key directories may contain a file named "stretching".
 
+static const int32_t KM_TAG_FBE_ICE = static_cast<int32_t>(7 << 28) | 16201;
+
 namespace {
 
 // Storage binding info for ensuring key encryption keys include a
@@ -139,6 +141,12 @@
     std::string key_temp;
     auto paramBuilder = km::AuthorizationSetBuilder().AesEncryptionKey(AES_KEY_BYTES * 8);
     paramBuilder.Authorization(km::TAG_STORAGE_KEY);
+
+    km::KeyParameter param1;
+    param1.tag = (km::Tag) (KM_TAG_FBE_ICE);
+    param1.value = km::KeyParameterValue::make<km::KeyParameterValue::boolValue>(true);
+    paramBuilder.push_back(param1);
+
     if (!keystore.generateKey(paramBuilder, &key_temp)) return false;
     *key = KeyBuffer(key_temp.size());
     memcpy(reinterpret_cast<void*>(key->data()), key_temp.c_str(), key->size());
@@ -150,7 +158,24 @@
     if (!keystore) return false;
     std::string key_temp;
 
-    if (!keystore.exportKey(ksKey, &key_temp)) return false;
+    auto ret = keystore.exportKey(ksKey, &key_temp);
+    if (ret != km::ErrorCode::OK) {
+        if (ret == km::ErrorCode::KEY_REQUIRES_UPGRADE) {
+           // TODO(b/187304488): Re-land the below logic. (keystore.upgradeKey() was removed)
+           return false;
+           /*
+           std::string kmKeyStr(reinterpret_cast<const char*>(ksKey.data()), ksKey.size());
+           std::string Keystr;
+           if (!keystore.upgradeKey(kmKeyStr, km::AuthorizationSet(), &Keystr)) return false;
+           KeyBuffer upgradedKey = KeyBuffer(Keystr.size());
+           memcpy(reinterpret_cast<void*>(upgradedKey.data()), Keystr.c_str(), upgradedKey.size());
+           ret = keystore.exportKey(upgradedKey, &key_temp);
+           if (ret != km::ErrorCode::OK) return false;
+           */
+        } else {
+           return false;
+        }
+    }
     *key = KeyBuffer(key_temp.size());
     memcpy(reinterpret_cast<void*>(key->data()), key_temp.c_str(), key->size());
     return true;
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index bd2ccdd..6d96541 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -143,7 +143,14 @@
             // A key for a v1 policy is specified by an arbitrary 8-byte
             // "descriptor", which must be provided by userspace.  We use the
             // first 8 bytes from the double SHA-512 of the key itself.
-            policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size());
+            if (options.use_hw_wrapped_key) {
+                /* When wrapped key is supported, only the first 32 bytes are
+                   the same per boot. The second 32 bytes can change as the ephemeral
+                   key is different. */
+                policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size()/2);
+            } else {
+                policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size());
+            }
             if (!buildKeySpecifier(&arg->key_spec, *policy)) {
                 return false;
             }
diff --git a/Keystore.cpp b/Keystore.cpp
index fd8a887..3ed6f54 100644
--- a/Keystore.cpp
+++ b/Keystore.cpp
@@ -150,8 +150,8 @@
     return true;
 }
 
-bool Keystore::exportKey(const KeyBuffer& ksKey, std::string* key) {
-    bool ret = false;
+km::ErrorCode Keystore::exportKey(const KeyBuffer& ksKey, std::string* key) {
+    km::ErrorCode ret = km::ErrorCode::UNKNOWN_ERROR;
     ks2::KeyDescriptor storageKey = {
             .domain = ks2::Domain::BLOB,
             .nspace = VOLD_NAMESPACE,
@@ -174,7 +174,7 @@
     // using the original blobs for TAG_STORAGE_KEY keys.  If KeyMint "upgrades"
     // them anyway, then they'll just get re-upgraded before each use.
 
-    ret = true;
+    ret = km::ErrorCode::OK;
 out:
     zeroize_vector(ephemeral_key_response.ephemeralKey);
     zeroize_vector(storageKey.blob.value());
diff --git a/Keystore.h b/Keystore.h
index d8c488e..a9dd7aa 100644
--- a/Keystore.h
+++ b/Keystore.h
@@ -113,7 +113,7 @@
     // Generate a key using keystore2 from the given params.
     bool generateKey(const km::AuthorizationSet& inParams, std::string* key);
     // Exports a keystore2 key with STORAGE_KEY tag wrapped with a per-boot ephemeral key
-    bool exportKey(const KeyBuffer& ksKey, std::string* key);
+    km::ErrorCode exportKey(const KeyBuffer& ksKey, std::string* key);
     // If supported, permanently delete a key from the keymint device it belongs to.
     bool deleteKey(const std::string& key);
     // Begin a new cryptographic operation, collecting output parameters if pointer is non-null
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index 2fa0cff..b7b8e3a 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -37,6 +37,7 @@
 #include "Checkpoint.h"
 #include "CryptoType.h"
 #include "EncryptInplace.h"
+#include "FsCrypt.h"
 #include "KeyStorage.h"
 #include "KeyUtil.h"
 #include "Keystore.h"
@@ -326,6 +327,8 @@
         }
         options.cipher = legacy_aes_256_xts;
         options.use_legacy_options_format = true;
+        if (is_metadata_wrapped_key_supported())
+            options.use_hw_wrapped_key = true;
         options.set_dun = android::base::GetBoolProperty("ro.crypto.set_dun", false);
         if (!options.set_dun && data_rec->fs_mgr_flags.checkpoint_blk) {
             LOG(ERROR)
diff --git a/VoldUtil.h b/VoldUtil.h
index ce6b411..e0945bf 100644
--- a/VoldUtil.h
+++ b/VoldUtil.h
@@ -21,3 +21,4 @@
 extern android::fs_mgr::Fstab fstab_default;
 
 #define DATA_MNT_POINT "/data"
+#define METADATA_MNT_POINT "/metadata"
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index d932ec8..fa2b699 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -73,6 +73,7 @@
 #include "model/StubVolume.h"
 
 using android::OK;
+using android::base::GetProperty;
 using android::base::GetBoolProperty;
 using android::base::StartsWith;
 using android::base::StringAppendF;
@@ -208,6 +209,7 @@
 
     std::string eventPath(evt->findParam("DEVPATH") ? evt->findParam("DEVPATH") : "");
     std::string devType(evt->findParam("DEVTYPE") ? evt->findParam("DEVTYPE") : "");
+    std::string devName(evt->findParam("DEVNAME") ? evt->findParam("DEVNAME") : "");
 
     if (devType != "disk") return;
 
@@ -229,6 +231,17 @@
                         flags |= android::vold::Disk::Flags::kUsb;
                     }
 
+                    if (GetBoolProperty("sys.vendor.vold.skip_root_mnt", false)) {
+                        // dont add this device as voldmanaged
+                        std::string rootDev = GetProperty("dev.mnt.blk.root", "");
+                        if (!rootDev.empty()) {
+                            if (rootDev.find(devName) != std::string::npos) {
+                                LOG(INFO) << "VolumeManager: skip dev = " << devName << " it is the boot device";
+                                break;
+                            }
+                        }
+                    }
+
                     auto disk =
                         new android::vold::Disk(eventPath, device, source->getNickname(), flags);
                     handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));