Introduce support for ephemeral users.
BUG: 24883058
Change-Id: I77d4757f87214166e7c41c7eb0d06b1cd5f06b20
diff --git a/Ext4Crypt.cpp b/Ext4Crypt.cpp
index f90ba56..34f0a46 100644
--- a/Ext4Crypt.cpp
+++ b/Ext4Crypt.cpp
@@ -78,6 +78,8 @@
time_t expiry_time;
};
std::map<std::string, keys> s_key_store;
+ // Maps the key paths of ephemeral keys to the keys
+ std::map<std::string, std::string> s_ephemeral_user_keys;
// ext4enc:TODO get these consts from somewhere good
const int SHA512_LENGTH = 64;
@@ -553,12 +555,22 @@
return StringPrintf("%s/%d", key_dir.c_str(), user_id);
}
+static bool e4crypt_is_key_ephemeral(const std::string &key_path) {
+ return s_ephemeral_user_keys.find(key_path) != s_ephemeral_user_keys.end();
+}
+
// ext4enc:TODO this can't be the only place keys are read from /dev/urandom
// we should unite those places.
static std::string e4crypt_get_key(
const std::string &key_path,
- bool create_if_absent)
+ bool create_if_absent,
+ bool create_ephemeral)
{
+ const auto ephemeral_key_it = s_ephemeral_user_keys.find(key_path);
+ if (ephemeral_key_it != s_ephemeral_user_keys.end()) {
+ return ephemeral_key_it->second;
+ }
+
std::string content;
if (android::base::ReadFileToString(key_path, &content)) {
if (content.size() != key_length/8) {
@@ -584,7 +596,10 @@
return "";
}
std::string key(key_bytes, sizeof(key_bytes));
- if (!android::base::WriteStringToFile(key, key_path)) {
+ if (create_ephemeral) {
+ // If the key should be created as ephemeral, store it in memory only.
+ s_ephemeral_user_keys[key_path] = key;
+ } else if (!android::base::WriteStringToFile(key, key_path)) {
SLOGE("Unable to write key to %s (%s)",
key_path.c_str(), strerror(errno));
return "";
@@ -593,10 +608,10 @@
}
static int e4crypt_set_user_policy(const char *mount_path, userid_t user_id,
- const char *path, bool create_if_absent) {
+ const char *path, bool create_if_absent, bool create_ephemeral) {
SLOGD("e4crypt_set_user_policy for %d", user_id);
auto user_key = e4crypt_get_key(get_key_path(mount_path, user_id),
- create_if_absent);
+ create_if_absent, create_ephemeral);
if (user_key.empty()) {
return -1;
}
@@ -639,7 +654,7 @@
auto user_id = atoi(result->d_name);
auto user_dir = std::string() + dir + "/" + result->d_name;
// ext4enc:TODO don't hardcode /data
- if (e4crypt_set_user_policy("/data", user_id, user_dir.c_str(), false)) {
+ if (e4crypt_set_user_policy("/data", user_id, user_dir.c_str(), false, false)) {
// ext4enc:TODO If this function fails, stop the boot: we must
// deliver on promised encryption.
SLOGE("Unable to set policy on %s\n", user_dir.c_str());
@@ -648,10 +663,11 @@
return 0;
}
-int e4crypt_create_user_key(userid_t user_id) {
+int e4crypt_create_user_key(userid_t user_id, bool ephemeral) {
SLOGD("e4crypt_create_user_key(%d)", user_id);
// TODO: create second key for user_de data
- if (e4crypt_get_key(get_key_path(DATA_MNT_POINT, user_id), true).empty()) {
+ if (e4crypt_get_key(
+ get_key_path(DATA_MNT_POINT, user_id), true, ephemeral).empty()) {
return -1;
} else {
return 0;
@@ -662,7 +678,7 @@
SLOGD("e4crypt_destroy_user_key(%d)", user_id);
// TODO: destroy second key for user_de data
auto key_path = get_key_path(DATA_MNT_POINT, user_id);
- auto key = e4crypt_get_key(key_path, false);
+ auto key = e4crypt_get_key(key_path, false, false);
auto ext4_key = fill_key(key);
auto ref = keyname(generate_key_ref(ext4_key.raw, ext4_key.size));
auto key_serial = keyctl_search(e4crypt_keyring(), "logon", ref.c_str(), 0);
@@ -672,6 +688,10 @@
SLOGE("Failed to revoke key with serial %ld ref %s: %s\n",
key_serial, ref.c_str(), strerror(errno));
}
+ if (e4crypt_is_key_ephemeral(key_path)) {
+ s_ephemeral_user_keys.erase(key_path);
+ return 0;
+ }
int pid = fork();
if (pid < 0) {
SLOGE("Unable to fork: %s", strerror(errno));
@@ -694,7 +714,7 @@
int e4crypt_unlock_user_key(userid_t user_id, const char* token) {
if (e4crypt_is_native()) {
- auto user_key = e4crypt_get_key(get_key_path(DATA_MNT_POINT, user_id), false);
+ auto user_key = e4crypt_get_key(get_key_path(DATA_MNT_POINT, user_id), false, false);
if (user_key.empty()) {
return -1;
}
@@ -733,7 +753,7 @@
return 0;
}
-int e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id) {
+int e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, bool ephemeral) {
std::string system_ce_path(android::vold::BuildDataSystemCePath(user_id));
std::string user_ce_path(android::vold::BuildDataUserPath(volume_uuid, user_id));
std::string user_de_path(android::vold::BuildDataUserDePath(volume_uuid, user_id));
@@ -752,8 +772,16 @@
}
if (e4crypt_crypto_complete(DATA_MNT_POINT) == 0) {
- if (e4crypt_set_user_policy(DATA_MNT_POINT, user_id, system_ce_path.c_str(), true)
- || e4crypt_set_user_policy(DATA_MNT_POINT, user_id, user_ce_path.c_str(), true)) {
+ if (e4crypt_set_user_policy(DATA_MNT_POINT,
+ user_id,
+ system_ce_path.c_str(),
+ true,
+ ephemeral)
+ || e4crypt_set_user_policy(DATA_MNT_POINT,
+ user_id,
+ user_ce_path.c_str(),
+ true,
+ ephemeral)) {
return -1;
}
}