@ -1429,6 +1429,40 @@ static int prep_data_fs(void)
}
}
static void cryptfs_set_corrupt ( )
{
// Mark the footer as bad
struct crypt_mnt_ftr crypt_ftr ;
if ( get_crypt_ftr_and_key ( & crypt_ftr ) ) {
SLOGE ( " Failed to get crypto footer - panic " ) ;
return ;
}
crypt_ftr . flags | = CRYPT_DATA_CORRUPT ;
if ( put_crypt_ftr_and_key ( & crypt_ftr ) ) {
SLOGE ( " Failed to set crypto footer - panic " ) ;
return ;
}
}
static void cryptfs_trigger_restart_min_framework ( )
{
if ( fs_mgr_do_tmpfs_mount ( DATA_MNT_POINT ) ) {
SLOGE ( " Failed to mount tmpfs on data - panic " ) ;
return ;
}
if ( property_set ( " vold.decrypt " , " trigger_post_fs_data " ) ) {
SLOGE ( " Failed to trigger post fs data - panic " ) ;
return ;
}
if ( property_set ( " vold.decrypt " , " trigger_restart_min_framework " ) ) {
SLOGE ( " Failed to trigger restart min framework - panic " ) ;
return ;
}
}
static int cryptfs_restart_internal ( int restart_main )
{
char fs_type [ 32 ] ;
@ -1503,7 +1537,13 @@ static int cryptfs_restart_internal(int restart_main)
}
/* If that succeeded, then mount the decrypted filesystem */
fs_mgr_do_mount ( fstab , DATA_MNT_POINT , crypto_blkdev , 0 ) ;
if ( fs_mgr_do_mount ( fstab , DATA_MNT_POINT , crypto_blkdev , 0 ) ) {
SLOGE ( " Failed to mount decrypted data " ) ;
cryptfs_set_corrupt ( ) ;
cryptfs_trigger_restart_min_framework ( ) ;
SLOGI ( " Started framework to offer wipe " ) ;
return - 1 ;
}
property_set ( " vold.decrypt " , " trigger_load_persist_props " ) ;
/* Create necessary paths on /data */
@ -1541,7 +1581,7 @@ static int do_crypto_complete(char *mount_point UNUSED)
property_get ( " ro.crypto.state " , encrypted_state , " " ) ;
if ( strcmp ( encrypted_state , " encrypted " ) ) {
SLOGE ( " not running with encryption, aborting " ) ;
return 1 ;
return CRYPTO_COMPLETE_NOT_ENCRYPTED ;
}
if ( get_crypt_ftr_and_key ( & crypt_ftr ) ) {
@ -1556,22 +1596,31 @@ static int do_crypto_complete(char *mount_point UNUSED)
*/
if ( ( key_loc [ 0 ] = = ' / ' ) & & ( access ( " key_loc " , F_OK ) = = - 1 ) ) {
SLOGE ( " master key file does not exist, aborting " ) ;
return 1 ;
return CRYPTO_COMPLETE_NOT_ENCRYPTED ;
} else {
SLOGE ( " Error getting crypt footer and key \n " ) ;
return - 1 ;
return CRYPTO_COMPLETE_BAD_METADATA ;
}
}
if ( crypt_ftr . flags
& ( CRYPT_ENCRYPTION_IN_PROGRESS | CRYPT_INCONSISTENT_STATE ) ) {
SLOGE ( " Encryption process didn't finish successfully \n " ) ;
return - 2 ; /* -2 is the clue to the UI that there is no usable data on the disk,
* and give the user an option to wipe the disk */
// Test for possible error flags
if ( crypt_ftr . flags & CRYPT_ENCRYPTION_IN_PROGRESS ) {
SLOGE ( " Encryption process is partway completed \n " ) ;
return CRYPTO_COMPLETE_PARTIAL ;
}
if ( crypt_ftr . flags & CRYPT_INCONSISTENT_STATE ) {
SLOGE ( " Encryption process was interrupted but cannot continue \n " ) ;
return CRYPTO_COMPLETE_INCONSISTENT ;
}
if ( crypt_ftr . flags & CRYPT_DATA_CORRUPT ) {
SLOGE ( " Encryption is successful but data is corrupt \n " ) ;
return CRYPTO_COMPLETE_CORRUPT ;
}
/* We passed the test! We shall diminish, and return to the west */
return 0 ;
return CRYPTO_COMPLETE_ENCRYPTED ;
}
static int test_mount_encrypted_fs ( struct crypt_mnt_ftr * crypt_ftr ,
@ -1605,72 +1654,68 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
fs_mgr_get_crypt_info ( fstab , 0 , real_blkdev , sizeof ( real_blkdev ) ) ;
// Create crypto block device - all (non fatal) code paths
// need it
if ( create_crypto_blk_dev ( crypt_ftr , decrypted_master_key ,
real_blkdev , crypto_blkdev , label ) ) {
SLOGE ( " Error creating decrypted block device \n " ) ;
rc = - 1 ;
goto errout ;
SLOGE ( " Error creating decrypted block device \n " ) ;
rc = - 1 ;
goto errout ;
}
/* If init detects an encrypted filesystem, it writes a file for each such
* encrypted fs into the tmpfs / data filesystem , and then the framework finds those
* files and passes that data to me */
/* Create a tmp mount point to try mounting the decryptd fs
* Since we ' re here , the mount_point should be a tmpfs filesystem , so make
* a directory in it to test mount the decrypted filesystem .
*/
sprintf ( tmp_mount_point , " %s/tmp_mnt " , mount_point ) ;
mkdir ( tmp_mount_point , 0755 ) ;
if ( fs_mgr_do_mount ( fstab , DATA_MNT_POINT , crypto_blkdev , tmp_mount_point ) ) {
SLOGE ( " Error temp mounting decrypted block device \n " ) ;
delete_crypto_blk_dev ( label ) ;
/* Work out if the problem is the password or the data */
unsigned char scrypted_intermediate_key [ sizeof ( crypt_ftr - >
scrypted_intermediate_key ) ] ;
int N = 1 < < crypt_ftr - > N_factor ;
int r = 1 < < crypt_ftr - > r_factor ;
int p = 1 < < crypt_ftr - > p_factor ;
/* Work out if the problem is the password or the data */
unsigned char scrypted_intermediate_key [ sizeof ( crypt_ftr - >
scrypted_intermediate_key ) ] ;
int N = 1 < < crypt_ftr - > N_factor ;
int r = 1 < < crypt_ftr - > r_factor ;
int p = 1 < < crypt_ftr - > p_factor ;
rc = crypto_scrypt ( intermediate_key , intermediate_key_size ,
crypt_ftr - > salt , sizeof ( crypt_ftr - > salt ) ,
N , r , p , scrypted_intermediate_key ,
sizeof ( scrypted_intermediate_key ) ) ;
// Does the key match the crypto footer?
if ( rc = = 0 & & memcmp ( scrypted_intermediate_key ,
crypt_ftr - > scrypted_intermediate_key ,
sizeof ( scrypted_intermediate_key ) ) = = 0 ) {
SLOGI ( " Password matches " ) ;
rc = 0 ;
} else {
/* Try mounting the file system anyway, just in case the problem's with
* the footer , not the key . */
sprintf ( tmp_mount_point , " %s/tmp_mnt " , mount_point ) ;
mkdir ( tmp_mount_point , 0755 ) ;
if ( fs_mgr_do_mount ( fstab , DATA_MNT_POINT , crypto_blkdev , tmp_mount_point ) ) {
SLOGE ( " Error temp mounting decrypted block device \n " ) ;
delete_crypto_blk_dev ( label ) ;
rc = crypto_scrypt ( intermediate_key , intermediate_key_size ,
crypt_ftr - > salt , sizeof ( crypt_ftr - > salt ) ,
N , r , p , scrypted_intermediate_key ,
sizeof ( scrypted_intermediate_key ) ) ;
if ( rc = = 0 & & memcmp ( scrypted_intermediate_key ,
crypt_ftr - > scrypted_intermediate_key ,
sizeof ( scrypted_intermediate_key ) ) = = 0 ) {
SLOGE ( " Right password, so wipe " ) ;
rc = - 1 ;
} else {
SLOGE ( rc ? " scrypt failure, so allow retry " :
" Wrong password, so allow retry " ) ;
rc = + + crypt_ftr - > failed_decrypt_count ;
put_crypt_ftr_and_key ( crypt_ftr ) ;
} else {
/* Success! */
SLOGI ( " Password did not match but decrypted drive mounted - continue " ) ;
umount ( tmp_mount_point ) ;
rc = 0 ;
}
} else {
/* Success!
* umount and we ' ll mount it properly when we restart the framework .
*/
umount ( tmp_mount_point ) ;
crypt_ftr - > failed_decrypt_count = 0 ;
}
if ( rc = = 0 ) {
crypt_ftr - > failed_decrypt_count = 0 ;
/* Save the name of the crypto block device
* so we can mount it when restarting the framework .
*/
* so we can mount it when restarting the framework . */
property_set ( " ro.crypto.fs_crypto_blkdev " , crypto_blkdev ) ;
/* Also save a the master key so we can reencrypted the key
* the key when we want to change the password on it .
*/
* the key when we want to change the password on it . */
memcpy ( saved_master_key , decrypted_master_key , KEY_LEN_BYTES ) ;
saved_mount_point = strdup ( mount_point ) ;
master_key_saved = 1 ;
SLOGD ( " %s(): Master key saved \n " , __FUNCTION__ ) ;
rc = 0 ;
/*
* Upgrade if we ' re not using the latest KDF .
*/
// Upgrade if we're not using the latest KDF.
use_keymaster = keymaster_check_compatibility ( ) ;
if ( crypt_ftr - > kdf_type = = KDF_SCRYPT_KEYMASTER ) {
// Don't allow downgrade to KDF_SCRYPT
@ -2139,7 +2184,7 @@ static int cryptfs_enable_inplace_ext4(char *crypto_blkdev,
{
u32 i ;
struct encryptGroupsData data ;
int rc = - 1 ;
int rc ; // Can't initialize without causing warning -Wclobbered
if ( previously_encrypted_upto > * size_already_done ) {
SLOGD ( " Not fast encrypting since resuming part way through " ) ;
@ -2153,22 +2198,26 @@ static int cryptfs_enable_inplace_ext4(char *crypto_blkdev,
if ( ( data . realfd = open ( real_blkdev , O_RDWR ) ) < 0 ) {
SLOGE ( " Error opening real_blkdev %s for inplace encrypt \n " ,
real_blkdev ) ;
rc = - 1 ;
goto errout ;
}
if ( ( data . cryptofd = open ( crypto_blkdev , O_WRONLY ) ) < 0 ) {
SLOGE ( " Error opening crypto_blkdev %s for inplace encrypt \n " ,
crypto_blkdev ) ;
rc = - 1 ;
goto errout ;
}
if ( setjmp ( setjmp_env ) ) {
SLOGE ( " Reading extent caused an exception " ) ;
rc = - 1 ;
goto errout ;
}
if ( read_ext ( data . realfd , 0 ) ! = 0 ) {
SLOGE ( " Failed to read extent " ) ;
rc = - 1 ;
goto errout ;
}