@ -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 20 0
/* 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 retrie s */
/* If allowed, be increasingly aggressive before the last 2 second s */
if ( kill ) {
if ( i = = ( WAIT_UNMOUNT_COUNT - 3 ) ) {
if ( i = = ( WAIT_UNMOUNT_COUNT - 3 0 ) ) {
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 - 2 0 ) ) {
SLOGW ( " sending SIGKILL to processes with open files \n " ) ;
android : : vold : : KillProcessesWithOpenFiles ( mountpoint , SIGKILL ) ;
}
}
sleep( 1 ) ;
u sleep( 1 00000 ) ;
}
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 ) ;
}