vold: Add Hardware FDE feature

Add HW FDE changes to new tip along with soong rules for
conditional compilation.

Following changes for HW FDE as well ported:
- Restart Android framework after HW FDE key has been created
- Add support of Inline Cryto Engine
- Use new HW FDE apis to update password
- vold: Tie HW FDE keys with Root of Trust(ROT)
- vold: Fix HW FDE OTA support on SW FDE encrypted device
- vold: Fix return value from get_keymaster_hw_fde_passwd()
- vold: Remove creation of new keymaster key for password update
- vold: Fix password update issue with HW FDE
- vold: hw_fde: fix OTA issues from L to M
- vold: Branch out SW and HW FDE paths to improve boot up time
- cryptfs: Use lower case alphabets for hex key during OTA upgrades
- vold: Improve device boot up time (Tune sleep calls)
- Retry mount if mount fails after setting HW FDE key
- cryptfs: Fix compilation error
- cryptfs: Fix mount failure when encryption triggered from settings
- cryptfs: fix issue that caused problems with forced HW encryption
- cryptfs: fix wrong password set by user during bootup.

CRs-Fixed: 2210986
Change-Id: I77279fc7e309ac94535123a2b2dbcb228bb47251
gugelfrei
AnilKumar Chimata 6 years ago committed by Michael Bestas
parent c856e2fe8a
commit 659d3765c0

@ -161,6 +161,11 @@ cc_library_static {
debuggable: {
cppflags: ["-D__ANDROID_DEBUGGABLE__"],
},
device_support_hwfde: {
cflags: ["-DCONFIG_HW_DISK_ENCRYPTION"],
header_libs: ["libcryptfs_hw_headers"],
shared_libs: ["libcryptfs_hw"],
},
},
shared_libs: [
"android.hardware.health.storage@1.0",
@ -187,6 +192,9 @@ cc_binary {
"libarcobbvolume",
],
},
device_support_hwfde: {
shared_libs: ["libcryptfs_hw"],
},
},
init_rc: [
"vold.rc",

@ -584,11 +584,12 @@ binder::Status VoldNativeService::fdeEnable(int32_t passwordType, const std::str
}
binder::Status VoldNativeService::fdeChangePassword(int32_t passwordType,
const std::string& currentPassword,
const std::string& password) {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_changepw(passwordType, password.c_str()));
return translate(cryptfs_changepw(passwordType, currentPassword.c_str(), password.c_str()));
}
binder::Status VoldNativeService::fdeVerifyPassword(const std::string& password) {

@ -97,7 +97,9 @@ class VoldNativeService : public BinderService<VoldNativeService>, public os::Bn
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 fdeChangePassword(int32_t passwordType,
const std::string& currentPassword,
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);

@ -74,7 +74,7 @@ interface IVold {
void fdeRestart();
int fdeComplete();
void fdeEnable(int passwordType, @utf8InCpp String password, int encryptionFlags);
void fdeChangePassword(int passwordType, @utf8InCpp String password);
void fdeChangePassword(int passwordType, @utf8InCpp String currentPassword, @utf8InCpp String password);
void fdeVerifyPassword(@utf8InCpp String password);
@utf8InCpp String fdeGetField(@utf8InCpp String key);
void fdeSetField(@utf8InCpp String key, @utf8InCpp String value);

@ -70,6 +70,9 @@
#include <chrono>
#include <thread>
#ifdef CONFIG_HW_DISK_ENCRYPTION
#include <cryptfs_hw.h>
#endif
extern "C" {
#include <crypto_scrypt.h>
}
@ -276,6 +279,7 @@ static_assert(INTERMEDIATE_BUF_SIZE == SCRYPT_LEN, "Mismatch of intermediate key
#define KEY_IN_FOOTER "footer"
#define DEFAULT_HEX_PASSWORD "64656661756c745f70617373776f7264"
#define DEFAULT_PASSWORD "default_password"
#define CRYPTO_BLOCK_DEVICE "userdata"
@ -291,6 +295,7 @@ static_assert(INTERMEDIATE_BUF_SIZE == SCRYPT_LEN, "Mismatch of intermediate key
#define RSA_KEY_SIZE_BYTES (RSA_KEY_SIZE / 8)
#define RSA_EXPONENT 0x10001
#define KEYMASTER_CRYPTFS_RATE_LIMIT 1 // Maximum one try per second
#define KEY_LEN_BYTES 16
#define RETRY_MOUNT_ATTEMPTS 10
#define RETRY_MOUNT_DELAY_SECONDS 1
@ -304,6 +309,151 @@ static char* saved_mount_point;
static int master_key_saved = 0;
static struct crypt_persist_data* persist_data = NULL;
static int previous_type;
#ifdef CONFIG_HW_DISK_ENCRYPTION
static int scrypt_keymaster(const char *passwd, const unsigned char *salt,
unsigned char *ikey, void *params);
static void convert_key_to_hex_ascii(const unsigned char *master_key,
unsigned int keysize, char *master_key_ascii);
static int put_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr);
static int test_mount_hw_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
const char *passwd, const char *mount_point, const char *label);
int cryptfs_changepw_hw_fde(int crypt_type, const char *currentpw,
const char *newpw);
int cryptfs_check_passwd_hw(char *passwd);
int cryptfs_get_master_key(struct crypt_mnt_ftr* ftr, const char* password,
unsigned char* master_key);
static void convert_key_to_hex_ascii_for_upgrade(const unsigned char *master_key,
unsigned int keysize, char *master_key_ascii)
{
unsigned int i, a;
unsigned char nibble;
for (i = 0, a = 0; i < keysize; i++, a += 2) {
/* For each byte, write out two ascii hex digits */
nibble = (master_key[i] >> 4) & 0xf;
master_key_ascii[a] = nibble + (nibble > 9 ? 0x57 : 0x30);
nibble = master_key[i] & 0xf;
master_key_ascii[a + 1] = nibble + (nibble > 9 ? 0x57 : 0x30);
}
/* Add the null termination */
master_key_ascii[a] = '\0';
}
static int get_keymaster_hw_fde_passwd(const char* passwd, unsigned char* newpw,
unsigned char* salt,
const struct crypt_mnt_ftr *ftr)
{
/* if newpw updated, return 0
* if newpw not updated return -1
*/
int rc = -1;
if (should_use_keymaster()) {
if (scrypt_keymaster(passwd, salt, newpw, (void*)ftr)) {
SLOGE("scrypt failed");
} else {
rc = 0;
}
}
return rc;
}
static int verify_hw_fde_passwd(const char *passwd, struct crypt_mnt_ftr* crypt_ftr)
{
unsigned char newpw[32] = {0};
int key_index;
if (get_keymaster_hw_fde_passwd(passwd, newpw, crypt_ftr->salt, crypt_ftr))
key_index = set_hw_device_encryption_key(passwd,
(char*) crypt_ftr->crypto_type_name);
else
key_index = set_hw_device_encryption_key((const char*)newpw,
(char*) crypt_ftr->crypto_type_name);
return key_index;
}
static int verify_and_update_hw_fde_passwd(const char *passwd,
struct crypt_mnt_ftr* crypt_ftr)
{
char* new_passwd = NULL;
unsigned char newpw[32] = {0};
int key_index = -1;
int passwd_updated = -1;
int ascii_passwd_updated = (crypt_ftr->flags & CRYPT_ASCII_PASSWORD_UPDATED);
key_index = verify_hw_fde_passwd(passwd, crypt_ftr);
if (key_index < 0) {
++crypt_ftr->failed_decrypt_count;
if (ascii_passwd_updated) {
SLOGI("Ascii password was updated");
} else {
/* Code in else part would execute only once:
* When device is upgraded from L->M release.
* Once upgraded, code flow should never come here.
* L release passed actual password in hex, so try with hex
* Each nible of passwd was encoded as a byte, so allocate memory
* twice of password len plus one more byte for null termination
*/
if (crypt_ftr->crypt_type == CRYPT_TYPE_DEFAULT) {
new_passwd = (char*)malloc(strlen(DEFAULT_HEX_PASSWORD) + 1);
if (new_passwd == NULL) {
SLOGE("System out of memory. Password verification incomplete");
goto out;
}
strlcpy(new_passwd, DEFAULT_HEX_PASSWORD, strlen(DEFAULT_HEX_PASSWORD) + 1);
} else {
new_passwd = (char*)malloc(strlen(passwd) * 2 + 1);
if (new_passwd == NULL) {
SLOGE("System out of memory. Password verification incomplete");
goto out;
}
convert_key_to_hex_ascii_for_upgrade((const unsigned char*)passwd,
strlen(passwd), new_passwd);
}
key_index = set_hw_device_encryption_key((const char*)new_passwd,
(char*) crypt_ftr->crypto_type_name);
if (key_index >=0) {
crypt_ftr->failed_decrypt_count = 0;
SLOGI("Hex password verified...will try to update with Ascii value");
/* Before updating password, tie that with keymaster to tie with ROT */
if (get_keymaster_hw_fde_passwd(passwd, newpw,
crypt_ftr->salt, crypt_ftr)) {
passwd_updated = update_hw_device_encryption_key(new_passwd,
passwd, (char*)crypt_ftr->crypto_type_name);
} else {
passwd_updated = update_hw_device_encryption_key(new_passwd,
(const char*)newpw, (char*)crypt_ftr->crypto_type_name);
}
if (passwd_updated >= 0) {
crypt_ftr->flags |= CRYPT_ASCII_PASSWORD_UPDATED;
SLOGI("Ascii password recorded and updated");
} else {
SLOGI("Passwd verified, could not update...Will try next time");
}
} else {
++crypt_ftr->failed_decrypt_count;
}
free(new_passwd);
}
} else {
if (!ascii_passwd_updated)
crypt_ftr->flags |= CRYPT_ASCII_PASSWORD_UPDATED;
}
out:
// update footer before leaving
put_crypt_ftr_and_key(crypt_ftr);
return key_index;
}
#endif
constexpr CryptoType aes_128_cbc = CryptoType()
.set_config_name("AES-128-CBC")
.set_kernel_name("aes-cbc-essiv:sha256")
@ -1220,7 +1370,8 @@ static int scrypt_keymaster(const char* passwd, const unsigned char* salt, unsig
static int encrypt_master_key(const char* passwd, const unsigned char* salt,
const unsigned char* decrypted_master_key,
unsigned char* encrypted_master_key, struct crypt_mnt_ftr* crypt_ftr) {
unsigned char* encrypted_master_key, struct crypt_mnt_ftr* crypt_ftr,
bool create_keymaster_key) {
unsigned char ikey[INTERMEDIATE_BUF_SIZE] = {0};
EVP_CIPHER_CTX e_ctx;
int encrypted_len, final_len;
@ -1231,7 +1382,7 @@ static int encrypt_master_key(const char* passwd, const unsigned char* salt,
switch (crypt_ftr->kdf_type) {
case KDF_SCRYPT_KEYMASTER:
if (keymaster_create_key(crypt_ftr)) {
if (create_keymaster_key && keymaster_create_key(crypt_ftr)) {
SLOGE("keymaster_create_key failed");
return -1;
}
@ -1395,7 +1546,7 @@ static int create_encrypted_random_key(const char* passwd, unsigned char* master
}
/* Now encrypt it with the password */
return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr);
return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr, true);
}
static void ensure_subdirectory_unmounted(const char *prefix) {
@ -1438,7 +1589,7 @@ static int wait_and_unmount(const char* mountpoint, bool kill) {
// Subdirectory mount will cause a failure of umount.
ensure_subdirectory_unmounted(mountpoint);
#define WAIT_UNMOUNT_COUNT 20
#define WAIT_UNMOUNT_COUNT 200
/* Now umount the tmpfs filesystem */
for (i = 0; i < WAIT_UNMOUNT_COUNT; i++) {
@ -1455,18 +1606,18 @@ static int wait_and_unmount(const char* mountpoint, bool kill) {
err = errno;
/* If allowed, be increasingly aggressive before the last two retries */
/* If allowed, be increasingly aggressive before the last 2 seconds */
if (kill) {
if (i == (WAIT_UNMOUNT_COUNT - 3)) {
if (i == (WAIT_UNMOUNT_COUNT - 30)) {
SLOGW("sending SIGHUP to processes with open files\n");
android::vold::KillProcessesWithOpenFiles(mountpoint, SIGTERM);
} else if (i == (WAIT_UNMOUNT_COUNT - 2)) {
} else if (i == (WAIT_UNMOUNT_COUNT - 20)) {
SLOGW("sending SIGKILL to processes with open files\n");
android::vold::KillProcessesWithOpenFiles(mountpoint, SIGKILL);
}
}
sleep(1);
usleep(100000);
}
if (i < WAIT_UNMOUNT_COUNT) {
@ -1639,6 +1790,17 @@ static int cryptfs_restart_internal(int restart_main) {
cryptfs_reboot(RebootType::reboot);
}
} else {
#ifdef CONFIG_HW_DISK_ENCRYPTION
if (--retries) {
sleep(RETRY_MOUNT_DELAY_SECONDS);
} else {
SLOGE("Failed to mount decrypted data");
cryptfs_set_corrupt();
cryptfs_trigger_restart_min_framework();
SLOGI("Started framework to offer wipe");
return -1;
}
#else
SLOGE("Failed to mount decrypted data");
cryptfs_set_corrupt();
cryptfs_trigger_restart_min_framework();
@ -1647,6 +1809,7 @@ static int cryptfs_restart_internal(int restart_main) {
SLOGE("Failed to setexeccon");
}
return -1;
#endif
}
}
if (setexeccon(NULL)) {
@ -1739,6 +1902,65 @@ static int do_crypto_complete(const char* mount_point) {
return CRYPTO_COMPLETE_ENCRYPTED;
}
#ifdef CONFIG_HW_DISK_ENCRYPTION
static int test_mount_hw_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
const char *passwd, const char *mount_point, const char *label)
{
/* Allocate enough space for a 256 bit key, but we may use less */
unsigned char decrypted_master_key[32];
char crypto_blkdev[MAXPATHLEN];
char real_blkdev[MAXPATHLEN];
unsigned int orig_failed_decrypt_count;
int rc = 0;
SLOGD("crypt_ftr->fs_size = %lld\n", crypt_ftr->fs_size);
orig_failed_decrypt_count = crypt_ftr->failed_decrypt_count;
fs_mgr_get_crypt_info(fstab_default, 0, real_blkdev, sizeof(real_blkdev));
int key_index = 0;
if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) {
key_index = verify_and_update_hw_fde_passwd(passwd, crypt_ftr);
if (key_index < 0) {
rc = crypt_ftr->failed_decrypt_count;
goto errout;
}
else {
if (is_ice_enabled()) {
if (create_crypto_blk_dev(crypt_ftr, (unsigned char*)&key_index,
real_blkdev, crypto_blkdev, label, 0)) {
SLOGE("Error creating decrypted block device");
rc = -1;
goto errout;
}
} else {
if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
real_blkdev, crypto_blkdev, label, 0)) {
SLOGE("Error creating decrypted block device");
rc = -1;
goto errout;
}
}
}
}
if (rc == 0) {
crypt_ftr->failed_decrypt_count = 0;
if (orig_failed_decrypt_count != 0) {
put_crypt_ftr_and_key(crypt_ftr);
}
/* Save the name of the crypto block device
* so we can mount it when restarting the framework. */
property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
master_key_saved = 1;
}
errout:
return rc;
}
#endif
static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, const char* passwd,
const char* mount_point, const char* label) {
unsigned char decrypted_master_key[MAX_KEY_LEN];
@ -1842,7 +2064,7 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, const char*
if (upgrade) {
rc = encrypt_master_key(passwd, crypt_ftr->salt, saved_master_key,
crypt_ftr->master_key, crypt_ftr);
crypt_ftr->master_key, crypt_ftr, true);
if (!rc) {
rc = put_crypt_ftr_and_key(crypt_ftr);
}
@ -1927,6 +2149,66 @@ int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr) {
return 0;
}
#ifdef CONFIG_HW_DISK_ENCRYPTION
int cryptfs_check_passwd_hw(const char* passwd)
{
struct crypt_mnt_ftr crypt_ftr;
int rc;
unsigned char master_key[KEY_LEN_BYTES];
/* get key */
if (get_crypt_ftr_and_key(&crypt_ftr)) {
SLOGE("Error getting crypt footer and key");
return -1;
}
/*
* in case of manual encryption (from GUI), the encryption is done with
* default password
*/
if (crypt_ftr.flags & CRYPT_FORCE_COMPLETE) {
/* compare scrypted_intermediate_key with stored scrypted_intermediate_key
* which was created with actual password before reboot.
*/
rc = cryptfs_get_master_key(&crypt_ftr, passwd, master_key);
if (rc) {
SLOGE("password doesn't match");
rc = ++crypt_ftr.failed_decrypt_count;
put_crypt_ftr_and_key(&crypt_ftr);
return rc;
}
rc = test_mount_hw_encrypted_fs(&crypt_ftr, DEFAULT_PASSWORD,
DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
if (rc) {
SLOGE("Default password did not match on reboot encryption");
return rc;
}
crypt_ftr.flags &= ~CRYPT_FORCE_COMPLETE;
put_crypt_ftr_and_key(&crypt_ftr);
rc = cryptfs_changepw(crypt_ftr.crypt_type, DEFAULT_PASSWORD, passwd);
if (rc) {
SLOGE("Could not change password on reboot encryption");
return rc;
}
} else
rc = test_mount_hw_encrypted_fs(&crypt_ftr, passwd,
DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
if (crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
cryptfs_clear_password();
password = strdup(passwd);
struct timespec now;
clock_gettime(CLOCK_BOOTTIME, &now);
password_expiry_time = now.tv_sec + password_max_age_seconds;
}
return rc;
}
#endif
int cryptfs_check_passwd(const char* passwd) {
SLOGI("cryptfs_check_passwd");
if (fscrypt_is_native()) {
@ -1943,6 +2225,11 @@ int cryptfs_check_passwd(const char* passwd) {
return rc;
}
#ifdef CONFIG_HW_DISK_ENCRYPTION
if (is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name))
return cryptfs_check_passwd_hw(passwd);
#endif
rc = test_mount_encrypted_fs(&crypt_ftr, passwd, DATA_MNT_POINT, CRYPTO_BLOCK_DEVICE);
if (rc) {
SLOGE("Password did not match");
@ -1964,7 +2251,7 @@ int cryptfs_check_passwd(const char* passwd) {
crypt_ftr.flags &= ~CRYPT_FORCE_COMPLETE;
put_crypt_ftr_and_key(&crypt_ftr);
rc = cryptfs_changepw(crypt_ftr.crypt_type, passwd);
rc = cryptfs_changepw(crypt_ftr.crypt_type, DEFAULT_PASSWORD, passwd);
if (rc) {
SLOGE("Could not change password on reboot encryption");
return rc;
@ -2013,6 +2300,24 @@ int cryptfs_verify_passwd(const char* passwd) {
/* If the device has no password, then just say the password is valid */
rc = 0;
} else {
#ifdef CONFIG_HW_DISK_ENCRYPTION
if(is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name)) {
if (verify_hw_fde_passwd(passwd, &crypt_ftr) >= 0)
rc = 0;
else
rc = -1;
} else {
decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) {
/* They match, the password is correct */
rc = 0;
} else {
/* If incorrect, sleep for a bit to prevent dictionary attacks */
sleep(1);
rc = 1;
}
}
#else
decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) {
/* They match, the password is correct */
@ -2022,6 +2327,7 @@ int cryptfs_verify_passwd(const char* passwd) {
sleep(1);
rc = 1;
}
#endif
}
return rc;
@ -2143,6 +2449,11 @@ int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
off64_t previously_encrypted_upto = 0;
bool rebootEncryption = false;
bool onlyCreateHeader = false;
#ifdef CONFIG_HW_DISK_ENCRYPTION
unsigned char newpw[32];
int key_index = 0;
#endif
int index = 0;
std::unique_ptr<android::wakelock::WakeLock> wakeLock = nullptr;
if (get_crypt_ftr_and_key(&crypt_ftr) == 0) {
@ -2284,8 +2595,13 @@ int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
}
crypt_ftr.crypt_type = crypt_type;
#ifdef CONFIG_HW_DISK_ENCRYPTION
strlcpy((char*)crypt_ftr.crypto_type_name, "aes-xts",
MAX_CRYPTO_TYPE_NAME_LEN);
#else
strlcpy((char*)crypt_ftr.crypto_type_name, get_crypto_type().get_kernel_name(),
MAX_CRYPTO_TYPE_NAME_LEN);
#endif
/* Make an encrypted master key */
if (create_encrypted_random_key(onlyCreateHeader ? DEFAULT_PASSWORD : passwd,
@ -2300,7 +2616,7 @@ int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
unsigned char encrypted_fake_master_key[MAX_KEY_LEN];
memset(fake_master_key, 0, sizeof(fake_master_key));
encrypt_master_key(passwd, crypt_ftr.salt, fake_master_key, encrypted_fake_master_key,
&crypt_ftr);
&crypt_ftr, true);
}
/* Write the key to the end of the partition */
@ -2321,12 +2637,57 @@ int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
}
}
/* When encryption triggered from settings, encryption starts after reboot.
So set the encryption key when the actual encryption starts.
*/
#ifdef CONFIG_HW_DISK_ENCRYPTION
if (previously_encrypted_upto == 0) {
if (!rebootEncryption)
clear_hw_device_encryption_key();
if (get_keymaster_hw_fde_passwd(
onlyCreateHeader ? DEFAULT_PASSWORD : passwd,
newpw, crypt_ftr.salt, &crypt_ftr))
key_index = set_hw_device_encryption_key(
onlyCreateHeader ? DEFAULT_PASSWORD : passwd,
(char*)crypt_ftr.crypto_type_name);
else
key_index = set_hw_device_encryption_key((const char*)newpw,
(char*) crypt_ftr.crypto_type_name);
if (key_index < 0)
goto error_shutting_down;
crypt_ftr.flags |= CRYPT_ASCII_PASSWORD_UPDATED;
put_crypt_ftr_and_key(&crypt_ftr);
}
#endif
if (onlyCreateHeader) {
sleep(2);
cryptfs_reboot(RebootType::reboot);
}
} else {
/* Do extra work for a better UX when doing the long inplace encryption */
/* Now that /data is unmounted, we need to mount a tmpfs
* /data, set a property saying we're doing inplace encryption,
* and restart the framework.
*/
if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) {
goto error_shutting_down;
}
/* Tells the framework that inplace encryption is starting */
property_set("vold.encrypt_progress", "0");
/* restart the framework. */
/* Create necessary paths on /data */
prep_data_fs();
/* Ugh, shutting down the framework is not synchronous, so until it
* can be fixed, this horrible hack will wait a moment for it all to
* shut down before proceeding. Without it, some devices cannot
* restart the graphics services.
*/
sleep(2);
if (!no_ui || rebootEncryption) {
/* startup service classes main and late_start */
property_set("vold.decrypt", "trigger_restart_min_framework");
SLOGD("Just triggered restart_min_framework\n");
@ -2339,8 +2700,17 @@ int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
}
decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
#ifdef CONFIG_HW_DISK_ENCRYPTION
if (is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name) && is_ice_enabled())
create_crypto_blk_dev(&crypt_ftr, (unsigned char*)&key_index, real_blkdev.c_str(), &crypto_blkdev,
CRYPTO_BLOCK_DEVICE, 0);
else
create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), &crypto_blkdev,
CRYPTO_BLOCK_DEVICE, 0);
#else
create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev.c_str(), &crypto_blkdev,
CRYPTO_BLOCK_DEVICE, 0);
#endif
/* If we are continuing, check checksums match */
rc = 0;
@ -2466,7 +2836,7 @@ int cryptfs_enable_default(int no_ui) {
return cryptfs_enable_internal(CRYPT_TYPE_DEFAULT, DEFAULT_PASSWORD, no_ui);
}
int cryptfs_changepw(int crypt_type, const char* newpw) {
int cryptfs_changepw(int crypt_type, const char* currentpw, const char* newpw) {
if (fscrypt_is_native()) {
SLOGE("cryptfs_changepw not valid for file encryption");
return -1;
@ -2492,10 +2862,33 @@ int cryptfs_changepw(int crypt_type, const char* newpw) {
return -1;
}
#ifdef CONFIG_HW_DISK_ENCRYPTION
if(is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name))
return cryptfs_changepw_hw_fde(crypt_type, currentpw, newpw);
else {
crypt_ftr.crypt_type = crypt_type;
rc = encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ?
DEFAULT_PASSWORD : newpw,
crypt_ftr.salt,
saved_master_key,
crypt_ftr.master_key,
&crypt_ftr, false);
if (rc) {
SLOGE("Encrypt master key failed: %d", rc);
return -1;
}
/* save the key */
put_crypt_ftr_and_key(&crypt_ftr);
return 0;
}
#else
crypt_ftr.crypt_type = crypt_type;
rc = encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD : newpw,
crypt_ftr.salt, saved_master_key, crypt_ftr.master_key, &crypt_ftr);
crypt_ftr.salt, saved_master_key, crypt_ftr.master_key, &crypt_ftr,
false);
if (rc) {
SLOGE("Encrypt master key failed: %d", rc);
return -1;
@ -2504,8 +2897,57 @@ int cryptfs_changepw(int crypt_type, const char* newpw) {
put_crypt_ftr_and_key(&crypt_ftr);
return 0;
#endif
}
#ifdef CONFIG_HW_DISK_ENCRYPTION
int cryptfs_changepw_hw_fde(int crypt_type, const char *currentpw, const char *newpw)
{
struct crypt_mnt_ftr crypt_ftr;
int rc;
int previous_type;
/* get key */
if (get_crypt_ftr_and_key(&crypt_ftr)) {
SLOGE("Error getting crypt footer and key");
return -1;
}
previous_type = crypt_ftr.crypt_type;
int rc1;
unsigned char tmp_curpw[32] = {0};
rc1 = get_keymaster_hw_fde_passwd(crypt_ftr.crypt_type == CRYPT_TYPE_DEFAULT ?
DEFAULT_PASSWORD : currentpw, tmp_curpw,
crypt_ftr.salt, &crypt_ftr);
crypt_ftr.crypt_type = crypt_type;
int ret, rc2;
unsigned char tmp_newpw[32] = {0};
rc2 = get_keymaster_hw_fde_passwd(crypt_type == CRYPT_TYPE_DEFAULT ?
DEFAULT_PASSWORD : newpw , tmp_newpw,
crypt_ftr.salt, &crypt_ftr);
if (is_hw_disk_encryption((char*)crypt_ftr.crypto_type_name)) {
ret = update_hw_device_encryption_key(
rc1 ? (previous_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD : currentpw) : (const char*)tmp_curpw,
rc2 ? (crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD : newpw): (const char*)tmp_newpw,
(char*)crypt_ftr.crypto_type_name);
if (ret) {
SLOGE("Error updating device encryption hardware key ret %d", ret);
return -1;
} else {
SLOGI("Encryption hardware key updated");
}
}
/* save the key */
put_crypt_ftr_and_key(&crypt_ftr);
return 0;
}
#endif
static unsigned int persist_get_max_entries(int encrypted) {
struct crypt_mnt_ftr crypt_ftr;
unsigned int dsize;
@ -2897,3 +3339,62 @@ int cryptfs_isConvertibleToFBE() {
auto entry = GetEntryForMountPoint(&fstab_default, DATA_MNT_POINT);
return entry && entry->fs_mgr_flags.force_fde_or_fbe;
}
int cryptfs_create_default_ftr(struct crypt_mnt_ftr* crypt_ftr, __attribute__((unused))int key_length)
{
if (cryptfs_init_crypt_mnt_ftr(crypt_ftr)) {
SLOGE("Failed to initialize crypt_ftr");
return -1;
}
if (create_encrypted_random_key(DEFAULT_PASSWORD, crypt_ftr->master_key,
crypt_ftr->salt, crypt_ftr)) {
SLOGE("Cannot create encrypted master key\n");
return -1;
}
//crypt_ftr->keysize = key_length / 8;
return 0;
}
int cryptfs_get_master_key(struct crypt_mnt_ftr* ftr, const char* password,
unsigned char* master_key)
{
int rc;
unsigned char* intermediate_key = 0;
size_t intermediate_key_size = 0;
if (password == 0 || *password == 0) {
password = DEFAULT_PASSWORD;
}
rc = decrypt_master_key(password, master_key, ftr, &intermediate_key,
&intermediate_key_size);
if (rc) {
SLOGE("Can't calculate intermediate key");
return rc;
}
int N = 1 << ftr->N_factor;
int r = 1 << ftr->r_factor;
int p = 1 << ftr->p_factor;
unsigned char scrypted_intermediate_key[sizeof(ftr->scrypted_intermediate_key)];
rc = crypto_scrypt(intermediate_key, intermediate_key_size,
ftr->salt, sizeof(ftr->salt), N, r, p,
scrypted_intermediate_key,
sizeof(scrypted_intermediate_key));
free(intermediate_key);
if (rc) {
SLOGE("Can't scrypt intermediate key");
return rc;
}
return memcmp(scrypted_intermediate_key, ftr->scrypted_intermediate_key,
intermediate_key_size);
}

@ -30,6 +30,15 @@
#define CRYPT_FOOTER_OFFSET 0x4000
#ifdef CONFIG_HW_DISK_ENCRYPTION
/* This flag is used to transition from L->M upgrade. L release passed
* a byte for every nible of user password while M release is passing
* ascii value of user password.
* Random flag value is chosen so that it does not conflict with other use cases
*/
#define CRYPT_ASCII_PASSWORD_UPDATED 0x1000
#endif
/* Return values for cryptfs_crypto_complete */
#define CRYPTO_COMPLETE_NOT_ENCRYPTED 1
#define CRYPTO_COMPLETE_ENCRYPTED 0
@ -63,7 +72,7 @@ int cryptfs_check_passwd(const char* pw);
int cryptfs_verify_passwd(const char* pw);
int cryptfs_restart(void);
int cryptfs_enable(int type, const char* passwd, int no_ui);
int cryptfs_changepw(int type, const char* newpw);
int cryptfs_changepw(int type, const char* currentpw, const char* newpw);
int cryptfs_enable_default(int no_ui);
int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev,
const android::vold::KeyBuffer& key, std::string* out_crypto_blkdev);

Loading…
Cancel
Save