vold: support v2 encryption policies
Add support for setting v2 encryption policies when configured in the
fstab (for internal storage) or in system properties (for adoptable
storage), and for installing and evicting the keys for such policies.
v2 policies support the same encryption modes and flags as v1 policies,
but internally they use a more standard, secure, and flexible KDF. Due
to this, some future features will be supported by v2 policies only.
Bug: 140500999
Test: Configured a device to use v2 encryption policies (applied the
needed kernel patches and added
"fileencryption=aes-256-xts:aes-256-cts:v2" to fstab, and set the
corresponding system properties for adoptable storage). Wiped
userdata, booted device and checked logs to verify that v2
policies were being used.
Also enabled virtual SD card and formatted as adoptable storage;
verified it works and that v2 policies were being used on it.
Also created, started, and stopped a 2nd user and verified their
keys were evicted.
Also verified that the device comes up again after rebooting.
Also verified that a device using v1 encryption policies continues
to work, both with and without an updated kernel -- including
stopping a user so that their keys get evicted.
Change-Id: If64028d8580584b2c33c614cabd5d6b93657f608
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index e28002f..bea9328 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -57,6 +57,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
using android::base::StringPrintf;
@@ -70,7 +71,10 @@
struct PolicyKeyRef {
std::string contents_mode;
std::string filenames_mode;
+ int policy_version;
std::string key_raw_ref;
+
+ PolicyKeyRef() : policy_version(0) {}
};
const std::string device_key_dir = std::string() + DATA_MNT_POINT + fscrypt_unencrypted_folder;
@@ -199,14 +203,57 @@
return false;
}
+// Retrieve the options to use for encryption policies on the /data filesystem.
+static void get_data_file_encryption_options(PolicyKeyRef* key_ref) {
+ auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
+ if (entry == nullptr) {
+ return;
+ }
+ key_ref->contents_mode = entry->file_contents_mode;
+ key_ref->filenames_mode = entry->file_names_mode;
+ key_ref->policy_version = entry->file_policy_version;
+}
+
+// Retrieve the version to use for encryption policies on the /data filesystem.
+static int get_data_file_policy_version(void) {
+ auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
+ if (entry == nullptr) {
+ return 0;
+ }
+ return entry->file_policy_version;
+}
+
+// Retrieve the options to use for encryption policies on adoptable storage.
+static bool get_volume_file_encryption_options(PolicyKeyRef* key_ref) {
+ key_ref->contents_mode =
+ android::base::GetProperty("ro.crypto.volume.contents_mode", "aes-256-xts");
+ key_ref->filenames_mode =
+ android::base::GetProperty("ro.crypto.volume.filenames_mode", "aes-256-heh");
+ key_ref->policy_version = 1;
+
+ std::string raw_flags = android::base::GetProperty("ro.crypto.volume.flags", "");
+ auto flags = android::base::Split(raw_flags, "+");
+ for (const auto& flag : flags) {
+ if (flag == "v1") {
+ key_ref->policy_version = 1;
+ } else if (flag == "v2") {
+ key_ref->policy_version = 2;
+ } else {
+ LOG(ERROR) << "Unknown flag in ro.crypto.volume.flags: " << flag;
+ return false;
+ }
+ }
+ return true;
+}
+
// Install a key for use by encrypted files on the /data filesystem.
static bool install_data_key(const KeyBuffer& key, std::string* raw_ref) {
- return android::vold::installKey(key, DATA_MNT_POINT, raw_ref);
+ return android::vold::installKey(key, DATA_MNT_POINT, get_data_file_policy_version(), raw_ref);
}
// Evict a key for use by encrypted files on the /data filesystem.
static bool evict_data_key(const std::string& raw_ref) {
- return android::vold::evictKey(DATA_MNT_POINT, raw_ref);
+ return android::vold::evictKey(DATA_MNT_POINT, raw_ref, get_data_file_policy_version());
}
static bool read_and_install_user_ce_key(userid_t user_id,
@@ -286,19 +333,10 @@
return true;
}
-static void get_data_file_encryption_modes(PolicyKeyRef* key_ref) {
- auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
- if (entry == nullptr) {
- return;
- }
- key_ref->contents_mode = entry->file_contents_mode;
- key_ref->filenames_mode = entry->file_names_mode;
-}
-
static bool ensure_policy(const PolicyKeyRef& key_ref, const std::string& path) {
return fscrypt_policy_ensure(path.c_str(), key_ref.key_raw_ref.data(),
key_ref.key_raw_ref.size(), key_ref.contents_mode.c_str(),
- key_ref.filenames_mode.c_str()) == 0;
+ key_ref.filenames_mode.c_str(), key_ref.policy_version) == 0;
}
static bool is_numeric(const char* name) {
@@ -354,14 +392,18 @@
}
PolicyKeyRef device_ref;
- if (!android::vold::retrieveAndInstallKey(true, kEmptyAuthentication, device_key_path,
- device_key_temp, "", &device_ref.key_raw_ref))
- return false;
- get_data_file_encryption_modes(&device_ref);
+ get_data_file_encryption_options(&device_ref);
- std::string modestring = device_ref.contents_mode + ":" + device_ref.filenames_mode;
- std::string mode_filename = std::string("/data") + fscrypt_key_mode;
- if (!android::vold::writeStringToFile(modestring, mode_filename)) return false;
+ if (!android::vold::retrieveAndInstallKey(true, kEmptyAuthentication, device_key_path,
+ device_key_temp, "", device_ref.policy_version,
+ &device_ref.key_raw_ref))
+ return false;
+
+ std::string options_string =
+ StringPrintf("%s:%s:v%d", device_ref.contents_mode.c_str(),
+ device_ref.filenames_mode.c_str(), device_ref.policy_version);
+ std::string options_filename = std::string("/data") + fscrypt_key_mode;
+ if (!android::vold::writeStringToFile(options_string, options_filename)) return false;
std::string ref_filename = std::string("/data") + fscrypt_key_ref;
if (!android::vold::writeStringToFile(device_ref.key_raw_ref, ref_filename)) return false;
@@ -560,14 +602,12 @@
return false;
}
android::vold::KeyAuthentication auth("", secdiscardable_hash);
- if (!android::vold::retrieveAndInstallKey(true, auth, key_path, key_path + "_tmp", volume_uuid,
- &key_ref->key_raw_ref))
- return false;
- key_ref->contents_mode =
- android::base::GetProperty("ro.crypto.volume.contents_mode", "aes-256-xts");
- key_ref->filenames_mode =
- android::base::GetProperty("ro.crypto.volume.filenames_mode", "aes-256-heh");
- return true;
+
+ if (!get_volume_file_encryption_options(key_ref)) return false;
+
+ return android::vold::retrieveAndInstallKey(true, auth, key_path, key_path + "_tmp",
+ volume_uuid, key_ref->policy_version,
+ &key_ref->key_raw_ref);
}
static bool destroy_volkey(const std::string& misc_path, const std::string& volume_uuid) {
@@ -715,7 +755,7 @@
PolicyKeyRef de_ref;
if (volume_uuid.empty()) {
if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_ref.key_raw_ref)) return false;
- get_data_file_encryption_modes(&de_ref);
+ get_data_file_encryption_options(&de_ref);
if (!ensure_policy(de_ref, system_de_path)) return false;
if (!ensure_policy(de_ref, misc_de_path)) return false;
if (!ensure_policy(de_ref, vendor_de_path)) return false;
@@ -746,7 +786,7 @@
PolicyKeyRef ce_ref;
if (volume_uuid.empty()) {
if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_ref.key_raw_ref)) return false;
- get_data_file_encryption_modes(&ce_ref);
+ get_data_file_encryption_options(&ce_ref);
if (!ensure_policy(ce_ref, system_ce_path)) return false;
if (!ensure_policy(ce_ref, misc_ce_path)) return false;
if (!ensure_policy(ce_ref, vendor_ce_path)) return false;