Move all crypto commands over to Binder.

Prefix FDE related commands with "fde" to make it clear which devices
they apply to.  This will also make it easier to remove once FDE
is fully deprecated in a future release.

To emulate the single-threaded nature of the old socket, introduce a
lock that is acquired for all encryption related methods.

Sprinkle some "const" around older files to make C++ happy.

Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.DirectBootHostTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AdoptableHostTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsOsTestCases -t android.os.storage.cts.StorageManagerTest
Bug: 13758960
Change-Id: I0a6ec6e3660bbddc61424c344ff6ac6da953ccf0
gugelfrei
Jeff Sharkey 7 years ago
parent ec4fda2459
commit 83b559ced4

@ -80,6 +80,7 @@ common_static_libraries := \
# TODO: include "cert-err34-c" once we move to Binder
# TODO: include "cert-err58-cpp" once 36656327 is fixed
common_local_tidy_enabled := true
common_local_tidy_flags := -warnings-as-errors=clang-analyzer-security*,cert-*
common_local_tidy_checks := -*,clang-analyzer-security*,cert-*,-cert-err34-c,-cert-err58-cpp
@ -96,7 +97,7 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE := libvold
LOCAL_CLANG := true
LOCAL_TIDY := true
LOCAL_TIDY := $(common_local_tidy_enabled)
LOCAL_TIDY_FLAGS := $(common_local_tidy_flags)
LOCAL_TIDY_CHECKS := $(common_local_tidy_checks)
LOCAL_SRC_FILES := $(common_src_files)
@ -115,7 +116,7 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_MODULE := vold
LOCAL_CLANG := true
LOCAL_TIDY := true
LOCAL_TIDY := $(common_local_tidy_enabled)
LOCAL_TIDY_FLAGS := $(common_local_tidy_flags)
LOCAL_TIDY_CHECKS := $(common_local_tidy_checks)
LOCAL_SRC_FILES := \
@ -140,7 +141,7 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_CLANG := true
LOCAL_TIDY := true
LOCAL_TIDY := $(common_local_tidy_enabled)
LOCAL_TIDY_FLAGS := $(common_local_tidy_flags)
LOCAL_TIDY_CHECKS := $(common_local_tidy_checks)
LOCAL_SRC_FILES := vdc.cpp
@ -156,7 +157,7 @@ include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_CLANG := true
LOCAL_TIDY := true
LOCAL_TIDY := $(common_local_tidy_enabled)
LOCAL_TIDY_FLAGS := $(common_local_tidy_flags)
LOCAL_TIDY_CHECKS := $(common_local_tidy_checks)
LOCAL_SRC_FILES:= \

@ -17,8 +17,13 @@
#include "VoldNativeService.h"
#include "VolumeManager.h"
#include "MoveTask.h"
#include "Process.h"
#include "TrimTask.h"
#include "cryptfs.h"
#include "Ext4Crypt.h"
#include "MetadataCrypt.h"
#include <fstream>
#include <android-base/logging.h>
@ -54,7 +59,7 @@ static binder::Status error(const std::string& msg) {
return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
}
static binder::Status translate(uint32_t status) {
static binder::Status translate(int status) {
if (status == 0) {
return binder::Status::ok();
} else {
@ -62,6 +67,14 @@ static binder::Status translate(uint32_t status) {
}
}
static binder::Status translateBool(bool status) {
if (status) {
return binder::Status::ok();
} else {
return binder::Status::fromServiceSpecificError(status);
}
}
binder::Status checkPermission(const char* permission) {
pid_t pid;
uid_t uid;
@ -154,7 +167,11 @@ binder::Status checkArgumentHex(const std::string& hex) {
} \
}
#define ACQUIRE_LOCK std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
#define ACQUIRE_LOCK \
std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getLock());
#define ACQUIRE_CRYPT_LOCK \
std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getCryptLock());
} // namespace
@ -277,7 +294,7 @@ binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountF
vol->setMountUserId(mountUserId);
int res = vol->mount();
if (mountFlags & MOUNT_FLAG_PRIMARY) {
if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
VolumeManager::Instance()->setPrimary(vol);
}
return translate(res);
@ -399,5 +416,253 @@ binder::Status VoldNativeService::unmountAppFuse(int32_t uid, int32_t pid, int32
return translate(VolumeManager::Instance()->unmountAppFuse(uid, pid, mountId));
}
binder::Status VoldNativeService::fdeCheckPassword(const std::string& password) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_check_passwd(password.c_str()));
}
binder::Status VoldNativeService::fdeRestart() {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
// Spawn as thread so init can issue commands back to vold without
// causing deadlock, usually as a result of prep_data_fs.
std::thread(&cryptfs_restart).detach();
return ok();
}
binder::Status VoldNativeService::fdeComplete(int32_t* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
*_aidl_return = cryptfs_crypto_complete();
return ok();
}
static int fdeEnableInternal(int32_t passwordType, const std::string& password,
int32_t encryptionFlags) {
bool noUi = (encryptionFlags & VoldNativeService::ENCRYPTION_FLAG_NO_UI) != 0;
std::string how;
if ((encryptionFlags & VoldNativeService::ENCRYPTION_FLAG_IN_PLACE) != 0) {
how = "inplace";
} else if ((encryptionFlags & VoldNativeService::ENCRYPTION_FLAG_WIPE) != 0) {
how = "wipe";
} else {
LOG(ERROR) << "Missing encryption flag";
return -1;
}
for (int tries = 0; tries < 2; ++tries) {
int rc;
if (passwordType == VoldNativeService::PASSWORD_TYPE_DEFAULT) {
rc = cryptfs_enable_default(how.c_str(), noUi);
} else {
rc = cryptfs_enable(how.c_str(), passwordType, password.c_str(), noUi);
}
if (rc == 0) {
return 0;
} else if (tries == 0) {
Process::killProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL);
}
}
return -1;
}
binder::Status VoldNativeService::fdeEnable(int32_t passwordType,
const std::string& password, int32_t encryptionFlags) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
if (e4crypt_is_native()) {
if (passwordType != PASSWORD_TYPE_DEFAULT) {
return error("Unexpected password type");
}
if (encryptionFlags != (ENCRYPTION_FLAG_IN_PLACE | ENCRYPTION_FLAG_NO_UI)) {
return error("Unexpected flags");
}
return translateBool(e4crypt_enable_crypto());
}
// Spawn as thread so init can issue commands back to vold without
// causing deadlock, usually as a result of prep_data_fs.
std::thread(&fdeEnableInternal, passwordType, password, encryptionFlags).detach();
return ok();
}
binder::Status VoldNativeService::fdeChangePassword(int32_t passwordType,
const std::string& password) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_changepw(passwordType, password.c_str()));
}
binder::Status VoldNativeService::fdeVerifyPassword(const std::string& password) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_verify_passwd(password.c_str()));
}
binder::Status VoldNativeService::fdeGetField(const std::string& key,
std::string* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
char buf[PROPERTY_VALUE_MAX];
if (cryptfs_getfield(key.c_str(), buf, sizeof(buf)) != CRYPTO_GETFIELD_OK) {
return error(StringPrintf("Failed to read field %s", key.c_str()));
} else {
*_aidl_return = buf;
return ok();
}
}
binder::Status VoldNativeService::fdeSetField(const std::string& key,
const std::string& value) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_setfield(key.c_str(), value.c_str()));
}
binder::Status VoldNativeService::fdeGetPasswordType(int32_t* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
*_aidl_return = cryptfs_get_password_type();
return ok();
}
binder::Status VoldNativeService::fdeGetPassword(std::string* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
const char* res = cryptfs_get_password();
if (res != nullptr) {
*_aidl_return = res;
}
return ok();
}
binder::Status VoldNativeService::fdeClearPassword() {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
cryptfs_clear_password();
return ok();
}
binder::Status VoldNativeService::fbeEnable() {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_initialize_global_de());
}
binder::Status VoldNativeService::mountDefaultEncrypted() {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
if (e4crypt_is_native()) {
return translateBool(e4crypt_mount_metadata_encrypted());
} else {
// Spawn as thread so init can issue commands back to vold without
// causing deadlock, usually as a result of prep_data_fs.
std::thread(&cryptfs_mount_default_encrypted).detach();
return ok();
}
}
binder::Status VoldNativeService::initUser0() {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_init_user0());
}
binder::Status VoldNativeService::isConvertibleToFbe(bool* _aidl_return) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
*_aidl_return = cryptfs_isConvertibleToFBE() != 0;
return ok();
}
binder::Status VoldNativeService::createUserKey(int32_t userId, int32_t userSerial,
bool ephemeral) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_vold_create_user_key(userId, userSerial, ephemeral));
}
binder::Status VoldNativeService::destroyUserKey(int32_t userId) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_destroy_user_key(userId));
}
binder::Status VoldNativeService::addUserKeyAuth(int32_t userId, int32_t userSerial,
const std::string& token, const std::string& secret) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_add_user_key_auth(userId, userSerial, token.c_str(), secret.c_str()));
}
binder::Status VoldNativeService::fixateNewestUserKeyAuth(int32_t userId) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_fixate_newest_user_key_auth(userId));
}
binder::Status VoldNativeService::unlockUserKey(int32_t userId, int32_t userSerial,
const std::string& token, const std::string& secret) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_unlock_user_key(userId, userSerial, token.c_str(), secret.c_str()));
}
binder::Status VoldNativeService::lockUserKey(int32_t userId) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_lock_user_key(userId));
}
binder::Status VoldNativeService::prepareUserStorage(const std::unique_ptr<std::string>& uuid,
int32_t userId, int32_t userSerial, int32_t flags) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
return translateBool(e4crypt_prepare_user_storage(uuid_, userId, userSerial, flags));
}
binder::Status VoldNativeService::destroyUserStorage(const std::unique_ptr<std::string>& uuid,
int32_t userId, int32_t flags) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
const char* uuid_ = uuid ? uuid->c_str() : nullptr;
return translateBool(e4crypt_destroy_user_storage(uuid_, userId, flags));
}
binder::Status VoldNativeService::secdiscard(const std::string& path) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_CRYPT_LOCK;
return translateBool(e4crypt_secdiscard(path.c_str()));
}
} // namespace vold
} // namespace android

@ -63,6 +63,44 @@ public:
binder::Status mountAppFuse(int32_t uid, int32_t pid, int32_t mountId,
android::base::unique_fd* _aidl_return);
binder::Status unmountAppFuse(int32_t uid, int32_t pid, int32_t mountId);
binder::Status fdeCheckPassword(const std::string& password);
binder::Status fdeRestart();
binder::Status fdeComplete(int32_t* _aidl_return);
binder::Status fdeEnable(int32_t passwordType,
const std::string& password, int32_t encryptionFlags);
binder::Status fdeChangePassword(int32_t passwordType,
const std::string& password);
binder::Status fdeVerifyPassword(const std::string& password);
binder::Status fdeGetField(const std::string& key, std::string* _aidl_return);
binder::Status fdeSetField(const std::string& key, const std::string& value);
binder::Status fdeGetPasswordType(int32_t* _aidl_return);
binder::Status fdeGetPassword(std::string* _aidl_return);
binder::Status fdeClearPassword();
binder::Status fbeEnable();
binder::Status mountDefaultEncrypted();
binder::Status initUser0();
binder::Status isConvertibleToFbe(bool* _aidl_return);
binder::Status createUserKey(int32_t userId, int32_t userSerial, bool ephemeral);
binder::Status destroyUserKey(int32_t userId);
binder::Status addUserKeyAuth(int32_t userId, int32_t userSerial,
const std::string& token, const std::string& secret);
binder::Status fixateNewestUserKeyAuth(int32_t userId);
binder::Status unlockUserKey(int32_t userId, int32_t userSerial,
const std::string& token, const std::string& secret);
binder::Status lockUserKey(int32_t userId);
binder::Status prepareUserStorage(const std::unique_ptr<std::string>& uuid,
int32_t userId, int32_t userSerial, int32_t flags);
binder::Status destroyUserStorage(const std::unique_ptr<std::string>& uuid,
int32_t userId, int32_t flags);
binder::Status secdiscard(const std::string& path);
};
} // namespace vold

@ -94,6 +94,7 @@ public:
// TODO: pipe all requests through VM to avoid exposing this lock
std::mutex& getLock() { return mLock; }
std::mutex& getCryptLock() { return mCryptLock; }
int start();
int stop();
@ -218,6 +219,7 @@ private:
int linkPrimary(userid_t userId);
std::mutex mLock;
std::mutex mCryptLock;
std::list<std::shared_ptr<DiskSource>> mDiskSources;
std::list<std::shared_ptr<android::vold::Disk>> mDisks;

@ -50,6 +50,49 @@ interface IVold {
FileDescriptor mountAppFuse(int uid, int pid, int mountId);
void unmountAppFuse(int uid, int pid, int mountId);
void fdeCheckPassword(@utf8InCpp String password);
void fdeRestart();
int fdeComplete();
void fdeEnable(int passwordType, @utf8InCpp String password, int encryptionFlags);
void fdeChangePassword(int passwordType, @utf8InCpp String password);
void fdeVerifyPassword(@utf8InCpp String password);
@utf8InCpp String fdeGetField(@utf8InCpp String key);
void fdeSetField(@utf8InCpp String key, @utf8InCpp String value);
int fdeGetPasswordType();
@utf8InCpp String fdeGetPassword();
void fdeClearPassword();
void fbeEnable();
void mountDefaultEncrypted();
void initUser0();
boolean isConvertibleToFbe();
void createUserKey(int userId, int userSerial, boolean ephemeral);
void destroyUserKey(int userId);
void addUserKeyAuth(int userId, int userSerial, @utf8InCpp String token, @utf8InCpp String secret);
void fixateNewestUserKeyAuth(int userId);
void unlockUserKey(int userId, int userSerial, @utf8InCpp String token, @utf8InCpp String secret);
void lockUserKey(int userId);
void prepareUserStorage(@nullable @utf8InCpp String uuid, int userId, int userSerial, int storageFlags);
void destroyUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
void secdiscard(@utf8InCpp String path);
const int ENCRYPTION_FLAG_WIPE = 1;
const int ENCRYPTION_FLAG_IN_PLACE = 2;
const int ENCRYPTION_FLAG_NO_UI = 4;
const int ENCRYPTION_STATE_NONE = 1;
const int ENCRYPTION_STATE_OK = 0;
const int ENCRYPTION_STATE_ERROR_UNKNOWN = -1;
const int ENCRYPTION_STATE_ERROR_INCOMPLETE = -2;
const int ENCRYPTION_STATE_ERROR_INCONSISTENT = -3;
const int ENCRYPTION_STATE_ERROR_CORRUPT = -4;
const int FSTRIM_FLAG_DEEP_TRIM = 1;
const int FSTRIM_FLAG_BENCHMARK_AFTER = 2;
@ -60,6 +103,14 @@ interface IVold {
const int PARTITION_TYPE_PRIVATE = 1;
const int PARTITION_TYPE_MIXED = 2;
const int PASSWORD_TYPE_PASSWORD = 0;
const int PASSWORD_TYPE_DEFAULT = 1;
const int PASSWORD_TYPE_PIN = 2;
const int PASSWORD_TYPE_PATTERN = 3;
const int STORAGE_FLAG_DE = 1;
const int STORAGE_FLAG_CE = 2;
const int REMOUNT_MODE_NONE = 0;
const int REMOUNT_MODE_DEFAULT = 1;
const int REMOUNT_MODE_READ = 2;

@ -1813,7 +1813,7 @@ int cryptfs_check_passwd(const char *passwd)
return rc;
}
int cryptfs_verify_passwd(char *passwd)
int cryptfs_verify_passwd(const char *passwd)
{
struct crypt_mnt_ftr crypt_ftr;
/* Allocate enough space for a 256 bit key, but we may use less */
@ -2058,7 +2058,7 @@ static int cryptfs_enable_all_volumes(struct crypt_mnt_ftr *crypt_ftr, int how,
return rc;
}
int cryptfs_enable_internal(char *howarg, int crypt_type, const char *passwd,
int cryptfs_enable_internal(const char *howarg, int crypt_type, const char *passwd,
int no_ui)
{
int how = 0;
@ -2417,12 +2417,12 @@ error_shutting_down:
return -1;
}
int cryptfs_enable(char *howarg, int type, char *passwd, int no_ui)
int cryptfs_enable(const char *howarg, int type, const char *passwd, int no_ui)
{
return cryptfs_enable_internal(howarg, type, passwd, no_ui);
}
int cryptfs_enable_default(char *howarg, int no_ui)
int cryptfs_enable_default(const char *howarg, int no_ui)
{
return cryptfs_enable_internal(howarg, CRYPT_TYPE_DEFAULT,
DEFAULT_PASSWORD, no_ui);

@ -229,11 +229,11 @@ extern "C" {
int cryptfs_crypto_complete(void);
int cryptfs_check_passwd(const char *pw);
int cryptfs_verify_passwd(char *newpw);
int cryptfs_verify_passwd(const char *pw);
int cryptfs_restart(void);
int cryptfs_enable(char *flag, int type, char *passwd, int no_ui);
int cryptfs_enable(const char *flag, int type, const char *passwd, int no_ui);
int cryptfs_changepw(int type, const char *newpw);
int cryptfs_enable_default(char *flag, int no_ui);
int cryptfs_enable_default(const char *flag, int no_ui);
int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev,
const unsigned char* key, int keysize, char* out_crypto_blkdev);
int cryptfs_revert_ext_volume(const char* label);

Loading…
Cancel
Save