Replace string secret with a byte[] for CE storage in vold binder
Replace the current `string secret` argument to the lock/unlock of CE storage with a `byte[]`. This is part of an effort to remove instances of the LSKF and LSKF-derived secrets that are available in a RAMdump -- since the strings are passed from Java, they cannot be cleared, but `byte[]` can be. This CL is the described argument change, and the propagation of this change to the various functions that are called by the vold binder functions. Bug: 320392352 Test: Manual upgrade test: 1. Flash the device with a build not including these changes 2. Rebuild with these changes 3. Flash the device (but do not wipe) with the build including these changes 4. See if the device boots and works normally -- if the CE storage cannot be unlocked it will not start up and be usable when the user logs in. Change-Id: Icd4c925f2fd79e7533fdf9027e16f6736dbe1ab3
This commit is contained in:
parent
e76fb7a810
commit
5177ed2e50
5 changed files with 22 additions and 36 deletions
41
FsCrypt.cpp
41
FsCrypt.cpp
|
@ -675,26 +675,13 @@ bool fscrypt_destroy_user_keys(userid_t user_id) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_hex(const std::string& hex, std::string* result) {
|
static android::vold::KeyAuthentication authentication_from_secret(
|
||||||
if (hex == "!") {
|
const std::vector<uint8_t>& secret) {
|
||||||
*result = "";
|
std::string secret_str(secret.begin(), secret.end());
|
||||||
return true;
|
if (secret_str.empty()) {
|
||||||
}
|
|
||||||
if (android::vold::HexToStr(hex, *result) != 0) {
|
|
||||||
LOG(ERROR) << "Invalid FBE hex string"; // Don't log the string for security reasons
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::optional<android::vold::KeyAuthentication> authentication_from_hex(
|
|
||||||
const std::string& secret_hex) {
|
|
||||||
std::string secret;
|
|
||||||
if (!parse_hex(secret_hex, &secret)) return std::optional<android::vold::KeyAuthentication>();
|
|
||||||
if (secret.empty()) {
|
|
||||||
return kEmptyAuthentication;
|
return kEmptyAuthentication;
|
||||||
} else {
|
} else {
|
||||||
return android::vold::KeyAuthentication(secret);
|
return android::vold::KeyAuthentication(secret_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,12 +730,11 @@ static bool destroy_volkey(const std::string& misc_path, const std::string& volu
|
||||||
// re-encrypting the CE key upon upgrade from an Android version where the CE
|
// re-encrypting the CE key upon upgrade from an Android version where the CE
|
||||||
// key was stored with kEmptyAuthentication when the user didn't have an LSKF.
|
// key was stored with kEmptyAuthentication when the user didn't have an LSKF.
|
||||||
// See the comments below for the different cases handled.
|
// See the comments below for the different cases handled.
|
||||||
bool fscrypt_set_ce_key_protection(userid_t user_id, const std::string& secret_hex) {
|
bool fscrypt_set_ce_key_protection(userid_t user_id, const std::vector<uint8_t>& secret) {
|
||||||
LOG(DEBUG) << "fscrypt_set_ce_key_protection " << user_id;
|
LOG(DEBUG) << "fscrypt_set_ce_key_protection " << user_id;
|
||||||
if (!IsFbeEnabled()) return true;
|
if (!IsFbeEnabled()) return true;
|
||||||
auto auth = authentication_from_hex(secret_hex);
|
auto auth = authentication_from_secret(secret);
|
||||||
if (!auth) return false;
|
if (auth.secret.empty()) {
|
||||||
if (auth->secret.empty()) {
|
|
||||||
LOG(ERROR) << "fscrypt_set_ce_key_protection: secret must be nonempty";
|
LOG(ERROR) << "fscrypt_set_ce_key_protection: secret must be nonempty";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -776,7 +762,7 @@ bool fscrypt_set_ce_key_protection(userid_t user_id, const std::string& secret_h
|
||||||
// with the given secret. This isn't expected, but in theory it
|
// with the given secret. This isn't expected, but in theory it
|
||||||
// could happen if an upgrade is requested for a user more than once
|
// could happen if an upgrade is requested for a user more than once
|
||||||
// due to a power-off or other interruption.
|
// due to a power-off or other interruption.
|
||||||
if (read_and_fixate_user_ce_key(user_id, *auth, &ce_key)) {
|
if (read_and_fixate_user_ce_key(user_id, auth, &ce_key)) {
|
||||||
LOG(WARNING) << "CE key is already protected by given secret";
|
LOG(WARNING) << "CE key is already protected by given secret";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -802,7 +788,7 @@ bool fscrypt_set_ce_key_protection(userid_t user_id, const std::string& secret_h
|
||||||
auto const paths = get_ce_key_paths(directory_path);
|
auto const paths = get_ce_key_paths(directory_path);
|
||||||
std::string ce_key_path;
|
std::string ce_key_path;
|
||||||
if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
|
if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
|
||||||
if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, *auth, ce_key)) return false;
|
if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, auth, ce_key)) return false;
|
||||||
|
|
||||||
// Fixate the key, i.e. delete all other bindings of it. (In practice this
|
// Fixate the key, i.e. delete all other bindings of it. (In practice this
|
||||||
// just means the kEmptyAuthentication binding, if there is one.) However,
|
// just means the kEmptyAuthentication binding, if there is one.) However,
|
||||||
|
@ -845,17 +831,16 @@ std::vector<int> fscrypt_get_unlocked_users() {
|
||||||
// Unlocks internal CE storage for the given user. This only unlocks internal storage, since
|
// Unlocks internal CE storage for the given user. This only unlocks internal storage, since
|
||||||
// fscrypt_prepare_user_storage() has to be called for each adoptable storage volume anyway (since
|
// fscrypt_prepare_user_storage() has to be called for each adoptable storage volume anyway (since
|
||||||
// the volume might have been absent when the user was created), and that handles the unlocking.
|
// the volume might have been absent when the user was created), and that handles the unlocking.
|
||||||
bool fscrypt_unlock_ce_storage(userid_t user_id, const std::string& secret_hex) {
|
bool fscrypt_unlock_ce_storage(userid_t user_id, const std::vector<uint8_t>& secret) {
|
||||||
LOG(DEBUG) << "fscrypt_unlock_ce_storage " << user_id;
|
LOG(DEBUG) << "fscrypt_unlock_ce_storage " << user_id;
|
||||||
if (!IsFbeEnabled()) return true;
|
if (!IsFbeEnabled()) return true;
|
||||||
if (s_ce_policies.count(user_id) != 0) {
|
if (s_ce_policies.count(user_id) != 0) {
|
||||||
LOG(WARNING) << "CE storage for user " << user_id << " is already unlocked";
|
LOG(WARNING) << "CE storage for user " << user_id << " is already unlocked";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto auth = authentication_from_hex(secret_hex);
|
auto auth = authentication_from_secret(secret);
|
||||||
if (!auth) return false;
|
|
||||||
KeyBuffer ce_key;
|
KeyBuffer ce_key;
|
||||||
if (!read_and_fixate_user_ce_key(user_id, *auth, &ce_key)) return false;
|
if (!read_and_fixate_user_ce_key(user_id, auth, &ce_key)) return false;
|
||||||
EncryptionPolicy ce_policy;
|
EncryptionPolicy ce_policy;
|
||||||
if (!install_storage_key(DATA_MNT_POINT, s_data_options, ce_key, &ce_policy)) return false;
|
if (!install_storage_key(DATA_MNT_POINT, s_data_options, ce_key, &ce_policy)) return false;
|
||||||
s_ce_policies[user_id].internal = ce_policy;
|
s_ce_policies[user_id].internal = ce_policy;
|
||||||
|
|
|
@ -25,11 +25,11 @@ bool fscrypt_init_user0();
|
||||||
extern bool fscrypt_init_user0_done;
|
extern bool fscrypt_init_user0_done;
|
||||||
bool fscrypt_create_user_keys(userid_t user_id, bool ephemeral);
|
bool fscrypt_create_user_keys(userid_t user_id, bool ephemeral);
|
||||||
bool fscrypt_destroy_user_keys(userid_t user_id);
|
bool fscrypt_destroy_user_keys(userid_t user_id);
|
||||||
bool fscrypt_set_ce_key_protection(userid_t user_id, const std::string& secret);
|
bool fscrypt_set_ce_key_protection(userid_t user_id, const std::vector<uint8_t>& secret);
|
||||||
void fscrypt_deferred_fixate_ce_keys();
|
void fscrypt_deferred_fixate_ce_keys();
|
||||||
|
|
||||||
std::vector<int> fscrypt_get_unlocked_users();
|
std::vector<int> fscrypt_get_unlocked_users();
|
||||||
bool fscrypt_unlock_ce_storage(userid_t user_id, const std::string& secret);
|
bool fscrypt_unlock_ce_storage(userid_t user_id, const std::vector<uint8_t>& secret);
|
||||||
bool fscrypt_lock_ce_storage(userid_t user_id);
|
bool fscrypt_lock_ce_storage(userid_t user_id);
|
||||||
|
|
||||||
bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
|
bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
|
||||||
|
|
|
@ -630,7 +630,7 @@ binder::Status VoldNativeService::destroyUserStorageKeys(int32_t userId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
binder::Status VoldNativeService::setCeStorageProtection(int32_t userId,
|
binder::Status VoldNativeService::setCeStorageProtection(int32_t userId,
|
||||||
const std::string& secret) {
|
const std::vector<uint8_t>& secret) {
|
||||||
ENFORCE_SYSTEM_OR_ROOT;
|
ENFORCE_SYSTEM_OR_ROOT;
|
||||||
ACQUIRE_CRYPT_LOCK;
|
ACQUIRE_CRYPT_LOCK;
|
||||||
|
|
||||||
|
@ -645,7 +645,8 @@ binder::Status VoldNativeService::getUnlockedUsers(std::vector<int>* _aidl_retur
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
binder::Status VoldNativeService::unlockCeStorage(int32_t userId, const std::string& secret) {
|
binder::Status VoldNativeService::unlockCeStorage(int32_t userId,
|
||||||
|
const std::vector<uint8_t>& secret) {
|
||||||
ENFORCE_SYSTEM_OR_ROOT;
|
ENFORCE_SYSTEM_OR_ROOT;
|
||||||
ACQUIRE_CRYPT_LOCK;
|
ACQUIRE_CRYPT_LOCK;
|
||||||
|
|
||||||
|
|
|
@ -116,10 +116,10 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
|
||||||
binder::Status createUserStorageKeys(int32_t userId, bool ephemeral);
|
binder::Status createUserStorageKeys(int32_t userId, bool ephemeral);
|
||||||
binder::Status destroyUserStorageKeys(int32_t userId);
|
binder::Status destroyUserStorageKeys(int32_t userId);
|
||||||
|
|
||||||
binder::Status setCeStorageProtection(int32_t userId, const std::string& secret);
|
binder::Status setCeStorageProtection(int32_t userId, const std::vector<uint8_t>& secret);
|
||||||
|
|
||||||
binder::Status getUnlockedUsers(std::vector<int>* _aidl_return);
|
binder::Status getUnlockedUsers(std::vector<int>* _aidl_return);
|
||||||
binder::Status unlockCeStorage(int32_t userId, const std::string& secret);
|
binder::Status unlockCeStorage(int32_t userId, const std::vector<uint8_t>& secret);
|
||||||
binder::Status lockCeStorage(int32_t userId);
|
binder::Status lockCeStorage(int32_t userId);
|
||||||
|
|
||||||
binder::Status prepareUserStorage(const std::optional<std::string>& uuid, int32_t userId,
|
binder::Status prepareUserStorage(const std::optional<std::string>& uuid, int32_t userId,
|
||||||
|
|
|
@ -91,10 +91,10 @@ interface IVold {
|
||||||
void createUserStorageKeys(int userId, boolean ephemeral);
|
void createUserStorageKeys(int userId, boolean ephemeral);
|
||||||
void destroyUserStorageKeys(int userId);
|
void destroyUserStorageKeys(int userId);
|
||||||
|
|
||||||
void setCeStorageProtection(int userId, @utf8InCpp String secret);
|
void setCeStorageProtection(int userId, in byte[] secret);
|
||||||
|
|
||||||
int[] getUnlockedUsers();
|
int[] getUnlockedUsers();
|
||||||
void unlockCeStorage(int userId, @utf8InCpp String secret);
|
void unlockCeStorage(int userId, in byte[] secret);
|
||||||
void lockCeStorage(int userId);
|
void lockCeStorage(int userId);
|
||||||
|
|
||||||
void prepareUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
|
void prepareUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
|
||||||
|
|
Loading…
Reference in a new issue