diff --git a/Android.mk b/Android.mk index 7263a5b..49d58c2 100644 --- a/Android.mk +++ b/Android.mk @@ -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:= \ diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 7cf45d9..374cb4c 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -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 #include @@ -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 lock(VolumeManager::Instance()->getLock()); +#define ACQUIRE_LOCK \ + std::lock_guard lock(VolumeManager::Instance()->getLock()); + +#define ACQUIRE_CRYPT_LOCK \ + std::lock_guard 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& 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& 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 diff --git a/VoldNativeService.h b/VoldNativeService.h index f412bfc..50244d2 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -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& uuid, + int32_t userId, int32_t userSerial, int32_t flags); + binder::Status destroyUserStorage(const std::unique_ptr& uuid, + int32_t userId, int32_t flags); + + binder::Status secdiscard(const std::string& path); }; } // namespace vold diff --git a/VolumeManager.h b/VolumeManager.h index 097ce6a..7dc69f3 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -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> mDiskSources; std::list> mDisks; diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index d945357..e8a8f2a 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -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; diff --git a/cryptfs.cpp b/cryptfs.cpp index 764d441..adfb284 100644 --- a/cryptfs.cpp +++ b/cryptfs.cpp @@ -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); diff --git a/cryptfs.h b/cryptfs.h index d20d96d..a7b650f 100644 --- a/cryptfs.h +++ b/cryptfs.h @@ -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);