@ -14,7 +14,7 @@
* limitations under the License .
* limitations under the License .
*/
*/
# include " Ext4 Crypt.h"
# include " Fs Crypt.h"
# include "KeyStorage.h"
# include "KeyStorage.h"
# include "KeyUtil.h"
# include "KeyUtil.h"
@ -50,7 +50,7 @@
# include <cutils/fs.h>
# include <cutils/fs.h>
# include <cutils/properties.h>
# include <cutils/properties.h>
# include < ext4_utils/ext4_ crypt.h>
# include < fscrypt/fs crypt.h>
# include <keyutils.h>
# include <keyutils.h>
# include <android-base/file.h>
# include <android-base/file.h>
@ -71,7 +71,7 @@ struct PolicyKeyRef {
std : : string key_raw_ref ;
std : : string key_raw_ref ;
} ;
} ;
const std : : string device_key_dir = std : : string ( ) + DATA_MNT_POINT + e4 crypt_unencrypted_folder;
const std : : string device_key_dir = std : : string ( ) + DATA_MNT_POINT + fs crypt_unencrypted_folder;
const std : : string device_key_path = device_key_dir + " /key " ;
const std : : string device_key_path = device_key_dir + " /key " ;
const std : : string device_key_temp = device_key_dir + " /temp " ;
const std : : string device_key_temp = device_key_dir + " /temp " ;
@ -95,7 +95,7 @@ std::map<userid_t, KeyBuffer> s_ce_keys;
} // namespace
} // namespace
static bool e4 crypt_is_emulated( ) {
static bool fs crypt_is_emulated( ) {
return property_get_bool ( " persist.sys.emulate_fbe " , false ) ;
return property_get_bool ( " persist.sys.emulate_fbe " , false ) ;
}
}
@ -282,7 +282,7 @@ static void get_data_file_encryption_modes(PolicyKeyRef* key_ref) {
}
}
static bool ensure_policy ( const PolicyKeyRef & key_ref , const std : : string & path ) {
static bool ensure_policy ( const PolicyKeyRef & key_ref , const std : : string & path ) {
return e4 crypt_policy_ensure( path . c_str ( ) , key_ref . key_raw_ref . data ( ) ,
return fs crypt_policy_ensure( path . c_str ( ) , key_ref . key_raw_ref . data ( ) ,
key_ref . key_raw_ref . size ( ) , key_ref . contents_mode . c_str ( ) ,
key_ref . key_raw_ref . size ( ) , key_ref . contents_mode . c_str ( ) ,
key_ref . filenames_mode . c_str ( ) ) = = 0 ;
key_ref . filenames_mode . c_str ( ) ) = = 0 ;
}
}
@ -326,13 +326,13 @@ static bool load_all_de_keys() {
LOG ( DEBUG ) < < " Installed de key for user " < < user_id ;
LOG ( DEBUG ) < < " Installed de key for user " < < user_id ;
}
}
}
}
// ext4enc :TODO: go through all DE directories, ensure that all user dirs have the
// fscrypt :TODO: go through all DE directories, ensure that all user dirs have the
// correct policy set on them, and that no rogue ones exist.
// correct policy set on them, and that no rogue ones exist.
return true ;
return true ;
}
}
bool e4 crypt_initialize_global_de( ) {
bool fs crypt_initialize_global_de( ) {
LOG ( INFO ) < < " e4 crypt_initialize_global_de" ;
LOG ( INFO ) < < " fs crypt_initialize_global_de" ;
if ( s_global_de_initialized ) {
if ( s_global_de_initialized ) {
LOG ( INFO ) < < " Already initialized " ;
LOG ( INFO ) < < " Already initialized " ;
@ -346,13 +346,13 @@ bool e4crypt_initialize_global_de() {
get_data_file_encryption_modes ( & device_ref ) ;
get_data_file_encryption_modes ( & device_ref ) ;
std : : string modestring = device_ref . contents_mode + " : " + device_ref . filenames_mode ;
std : : string modestring = device_ref . contents_mode + " : " + device_ref . filenames_mode ;
std : : string mode_filename = std : : string ( " /data " ) + e4 crypt_key_mode;
std : : string mode_filename = std : : string ( " /data " ) + fs crypt_key_mode;
if ( ! android : : base : : WriteStringToFile ( modestring , mode_filename ) ) {
if ( ! android : : base : : WriteStringToFile ( modestring , mode_filename ) ) {
PLOG ( ERROR ) < < " Cannot save type " ;
PLOG ( ERROR ) < < " Cannot save type " ;
return false ;
return false ;
}
}
std : : string ref_filename = std : : string ( " /data " ) + e4 crypt_key_ref;
std : : string ref_filename = std : : string ( " /data " ) + fs crypt_key_ref;
if ( ! android : : base : : WriteStringToFile ( device_ref . key_raw_ref , ref_filename ) ) {
if ( ! android : : base : : WriteStringToFile ( device_ref . key_raw_ref , ref_filename ) ) {
PLOG ( ERROR ) < < " Cannot save key reference to: " < < ref_filename ;
PLOG ( ERROR ) < < " Cannot save key reference to: " < < ref_filename ;
return false ;
return false ;
@ -363,9 +363,9 @@ bool e4crypt_initialize_global_de() {
return true ;
return true ;
}
}
bool e4 crypt_init_user0( ) {
bool fs crypt_init_user0( ) {
LOG ( DEBUG ) < < " e4 crypt_init_user0" ;
LOG ( DEBUG ) < < " fs crypt_init_user0" ;
if ( e4 crypt_is_native( ) ) {
if ( fs crypt_is_native( ) ) {
if ( ! prepare_dir ( user_key_dir , 0700 , AID_ROOT , AID_ROOT ) ) return false ;
if ( ! prepare_dir ( user_key_dir , 0700 , AID_ROOT , AID_ROOT ) ) return false ;
if ( ! prepare_dir ( user_key_dir + " /ce " , 0700 , AID_ROOT , AID_ROOT ) ) return false ;
if ( ! prepare_dir ( user_key_dir + " /ce " , 0700 , AID_ROOT , AID_ROOT ) ) return false ;
if ( ! prepare_dir ( user_key_dir + " /de " , 0700 , AID_ROOT , AID_ROOT ) ) return false ;
if ( ! prepare_dir ( user_key_dir + " /de " , 0700 , AID_ROOT , AID_ROOT ) ) return false ;
@ -379,28 +379,28 @@ bool e4crypt_init_user0() {
// We can only safely prepare DE storage here, since CE keys are probably
// We can only safely prepare DE storage here, since CE keys are probably
// entangled with user credentials. The framework will always prepare CE
// entangled with user credentials. The framework will always prepare CE
// storage once CE keys are installed.
// storage once CE keys are installed.
if ( ! e4 crypt_prepare_user_storage( " " , 0 , 0 , android : : os : : IVold : : STORAGE_FLAG_DE ) ) {
if ( ! fs crypt_prepare_user_storage( " " , 0 , 0 , android : : os : : IVold : : STORAGE_FLAG_DE ) ) {
LOG ( ERROR ) < < " Failed to prepare user 0 storage " ;
LOG ( ERROR ) < < " Failed to prepare user 0 storage " ;
return false ;
return false ;
}
}
// If this is a non-FBE device that recently left an emulated mode,
// If this is a non-FBE device that recently left an emulated mode,
// restore user data directories to known-good state.
// restore user data directories to known-good state.
if ( ! e4crypt_is_native( ) & & ! e4 crypt_is_emulated( ) ) {
if ( ! fscrypt_is_native( ) & & ! fs crypt_is_emulated( ) ) {
e4 crypt_unlock_user_key( 0 , 0 , " ! " , " ! " ) ;
fs crypt_unlock_user_key( 0 , 0 , " ! " , " ! " ) ;
}
}
return true ;
return true ;
}
}
bool e4 crypt_vold_create_user_key( userid_t user_id , int serial , bool ephemeral ) {
bool fs crypt_vold_create_user_key( userid_t user_id , int serial , bool ephemeral ) {
LOG ( DEBUG ) < < " e4 crypt_vold_create_user_key for " < < user_id < < " serial " < < serial ;
LOG ( DEBUG ) < < " fs crypt_vold_create_user_key for " < < user_id < < " serial " < < serial ;
if ( ! e4 crypt_is_native( ) ) {
if ( ! fs crypt_is_native( ) ) {
return true ;
return true ;
}
}
// FIXME test for existence of key that is not loaded yet
// FIXME test for existence of key that is not loaded yet
if ( s_ce_key_raw_refs . count ( user_id ) ! = 0 ) {
if ( s_ce_key_raw_refs . count ( user_id ) ! = 0 ) {
LOG ( ERROR ) < < " Already exists, can't e4 crypt_vold_create_user_key for " < < user_id
LOG ( ERROR ) < < " Already exists, can't fs crypt_vold_create_user_key for " < < user_id
< < " serial " < < serial ;
< < " serial " < < serial ;
// FIXME should we fail the command?
// FIXME should we fail the command?
return true ;
return true ;
@ -433,9 +433,9 @@ static bool evict_ce_key(userid_t user_id) {
return success ;
return success ;
}
}
bool e4 crypt_destroy_user_key( userid_t user_id ) {
bool fs crypt_destroy_user_key( userid_t user_id ) {
LOG ( DEBUG ) < < " e4 crypt_destroy_user_key(" < < user_id < < " ) " ;
LOG ( DEBUG ) < < " fs crypt_destroy_user_key(" < < user_id < < " ) " ;
if ( ! e4 crypt_is_native( ) ) {
if ( ! fs crypt_is_native( ) ) {
return true ;
return true ;
}
}
bool success = true ;
bool success = true ;
@ -479,13 +479,13 @@ static bool emulated_unlock(const std::string& path, mode_t mode) {
if ( chmod ( path . c_str ( ) , mode ) ! = 0 ) {
if ( chmod ( path . c_str ( ) , mode ) ! = 0 ) {
PLOG ( ERROR ) < < " Failed to chmod " < < path ;
PLOG ( ERROR ) < < " Failed to chmod " < < path ;
// FIXME temporary workaround for b/26713622
// FIXME temporary workaround for b/26713622
if ( e4 crypt_is_emulated( ) ) return false ;
if ( fs crypt_is_emulated( ) ) return false ;
}
}
# if EMULATED_USES_SELINUX
# if EMULATED_USES_SELINUX
if ( selinux_android_restorecon ( path . c_str ( ) , SELINUX_ANDROID_RESTORECON_FORCE ) ! = 0 ) {
if ( selinux_android_restorecon ( path . c_str ( ) , SELINUX_ANDROID_RESTORECON_FORCE ) ! = 0 ) {
PLOG ( WARNING ) < < " Failed to restorecon " < < path ;
PLOG ( WARNING ) < < " Failed to restorecon " < < path ;
// FIXME temporary workaround for b/26713622
// FIXME temporary workaround for b/26713622
if ( e4 crypt_is_emulated( ) ) return false ;
if ( fs crypt_is_emulated( ) ) return false ;
}
}
# endif
# endif
return true ;
return true ;
@ -548,11 +548,11 @@ static bool destroy_volkey(const std::string& misc_path, const std::string& volu
return android : : vold : : destroyKey ( path ) ;
return android : : vold : : destroyKey ( path ) ;
}
}
bool e4 crypt_add_user_key_auth( userid_t user_id , int serial , const std : : string & token_hex ,
bool fs crypt_add_user_key_auth( userid_t user_id , int serial , const std : : string & token_hex ,
const std : : string & secret_hex ) {
const std : : string & secret_hex ) {
LOG ( DEBUG ) < < " e4 crypt_add_user_key_auth " < < user_id < < " serial= " < < serial
LOG ( DEBUG ) < < " fs crypt_add_user_key_auth " < < user_id < < " serial= " < < serial
< < " token_present= " < < ( token_hex ! = " ! " ) ;
< < " token_present= " < < ( token_hex ! = " ! " ) ;
if ( ! e4 crypt_is_native( ) ) return true ;
if ( ! fs crypt_is_native( ) ) return true ;
if ( s_ephemeral_users . count ( user_id ) ! = 0 ) return true ;
if ( s_ephemeral_users . count ( user_id ) ! = 0 ) return true ;
std : : string token , secret ;
std : : string token , secret ;
if ( ! parse_hex ( token_hex , & token ) ) return false ;
if ( ! parse_hex ( token_hex , & token ) ) return false ;
@ -573,9 +573,9 @@ bool e4crypt_add_user_key_auth(userid_t user_id, int serial, const std::string&
return true ;
return true ;
}
}
bool e4 crypt_fixate_newest_user_key_auth( userid_t user_id ) {
bool fs crypt_fixate_newest_user_key_auth( userid_t user_id ) {
LOG ( DEBUG ) < < " e4 crypt_fixate_newest_user_key_auth " < < user_id ;
LOG ( DEBUG ) < < " fs crypt_fixate_newest_user_key_auth " < < user_id ;
if ( ! e4 crypt_is_native( ) ) return true ;
if ( ! fs crypt_is_native( ) ) return true ;
if ( s_ephemeral_users . count ( user_id ) ! = 0 ) return true ;
if ( s_ephemeral_users . count ( user_id ) ! = 0 ) return true ;
auto const directory_path = get_ce_key_directory_path ( user_id ) ;
auto const directory_path = get_ce_key_directory_path ( user_id ) ;
auto const paths = get_ce_key_paths ( directory_path ) ;
auto const paths = get_ce_key_paths ( directory_path ) ;
@ -588,11 +588,11 @@ bool e4crypt_fixate_newest_user_key_auth(userid_t user_id) {
}
}
// TODO: rename to 'install' for consistency, and take flags to know which keys to install
// TODO: rename to 'install' for consistency, and take flags to know which keys to install
bool e4 crypt_unlock_user_key( userid_t user_id , int serial , const std : : string & token_hex ,
bool fs crypt_unlock_user_key( userid_t user_id , int serial , const std : : string & token_hex ,
const std : : string & secret_hex ) {
const std : : string & secret_hex ) {
LOG ( DEBUG ) < < " e4 crypt_unlock_user_key " < < user_id < < " serial= " < < serial
LOG ( DEBUG ) < < " fs crypt_unlock_user_key " < < user_id < < " serial= " < < serial
< < " token_present= " < < ( token_hex ! = " ! " ) ;
< < " token_present= " < < ( token_hex ! = " ! " ) ;
if ( e4 crypt_is_native( ) ) {
if ( fs crypt_is_native( ) ) {
if ( s_ce_key_raw_refs . count ( user_id ) ! = 0 ) {
if ( s_ce_key_raw_refs . count ( user_id ) ! = 0 ) {
LOG ( WARNING ) < < " Tried to unlock already-unlocked key for user " < < user_id ;
LOG ( WARNING ) < < " Tried to unlock already-unlocked key for user " < < user_id ;
return true ;
return true ;
@ -621,11 +621,11 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial, const std::string& to
}
}
// TODO: rename to 'evict' for consistency
// TODO: rename to 'evict' for consistency
bool e4 crypt_lock_user_key( userid_t user_id ) {
bool fs crypt_lock_user_key( userid_t user_id ) {
LOG ( DEBUG ) < < " e4 crypt_lock_user_key " < < user_id ;
LOG ( DEBUG ) < < " fs crypt_lock_user_key " < < user_id ;
if ( e4 crypt_is_native( ) ) {
if ( fs crypt_is_native( ) ) {
return evict_ce_key ( user_id ) ;
return evict_ce_key ( user_id ) ;
} else if ( e4 crypt_is_emulated( ) ) {
} else if ( fs crypt_is_emulated( ) ) {
// When in emulation mode, we just use chmod
// When in emulation mode, we just use chmod
if ( ! emulated_lock ( android : : vold : : BuildDataSystemCePath ( user_id ) ) | |
if ( ! emulated_lock ( android : : vold : : BuildDataSystemCePath ( user_id ) ) | |
! emulated_lock ( android : : vold : : BuildDataMiscCePath ( user_id ) ) | |
! emulated_lock ( android : : vold : : BuildDataMiscCePath ( user_id ) ) | |
@ -650,9 +650,9 @@ static bool prepare_subdirs(const std::string& action, const std::string& volume
return true ;
return true ;
}
}
bool e4 crypt_prepare_user_storage( const std : : string & volume_uuid , userid_t user_id , int serial ,
bool fs crypt_prepare_user_storage( const std : : string & volume_uuid , userid_t user_id , int serial ,
int flags ) {
int flags ) {
LOG ( DEBUG ) < < " e4 crypt_prepare_user_storage for volume " < < escape_empty ( volume_uuid )
LOG ( DEBUG ) < < " fs crypt_prepare_user_storage for volume " < < escape_empty ( volume_uuid )
< < " , user " < < user_id < < " , serial " < < serial < < " , flags " < < flags ;
< < " , user " < < user_id < < " , serial " < < serial < < " , flags " < < flags ;
if ( flags & android : : os : : IVold : : STORAGE_FLAG_DE ) {
if ( flags & android : : os : : IVold : : STORAGE_FLAG_DE ) {
@ -682,7 +682,7 @@ bool e4crypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_
}
}
if ( ! prepare_dir ( user_de_path , 0771 , AID_SYSTEM , AID_SYSTEM ) ) return false ;
if ( ! prepare_dir ( user_de_path , 0771 , AID_SYSTEM , AID_SYSTEM ) ) return false ;
if ( e4 crypt_is_native( ) ) {
if ( fs crypt_is_native( ) ) {
PolicyKeyRef de_ref ;
PolicyKeyRef de_ref ;
if ( volume_uuid . empty ( ) ) {
if ( volume_uuid . empty ( ) ) {
if ( ! lookup_key_ref ( s_de_key_raw_refs , user_id , & de_ref . key_raw_ref ) ) return false ;
if ( ! lookup_key_ref ( s_de_key_raw_refs , user_id , & de_ref . key_raw_ref ) ) return false ;
@ -713,7 +713,7 @@ bool e4crypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_
if ( ! prepare_dir ( media_ce_path , 0770 , AID_MEDIA_RW , AID_MEDIA_RW ) ) return false ;
if ( ! prepare_dir ( media_ce_path , 0770 , AID_MEDIA_RW , AID_MEDIA_RW ) ) return false ;
if ( ! prepare_dir ( user_ce_path , 0771 , AID_SYSTEM , AID_SYSTEM ) ) return false ;
if ( ! prepare_dir ( user_ce_path , 0771 , AID_SYSTEM , AID_SYSTEM ) ) return false ;
if ( e4 crypt_is_native( ) ) {
if ( fs crypt_is_native( ) ) {
PolicyKeyRef ce_ref ;
PolicyKeyRef ce_ref ;
if ( volume_uuid . empty ( ) ) {
if ( volume_uuid . empty ( ) ) {
if ( ! lookup_key_ref ( s_ce_key_raw_refs , user_id , & ce_ref . key_raw_ref ) ) return false ;
if ( ! lookup_key_ref ( s_ce_key_raw_refs , user_id , & ce_ref . key_raw_ref ) ) return false ;
@ -742,8 +742,8 @@ bool e4crypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_
return true ;
return true ;
}
}
bool e4 crypt_destroy_user_storage( const std : : string & volume_uuid , userid_t user_id , int flags ) {
bool fs crypt_destroy_user_storage( const std : : string & volume_uuid , userid_t user_id , int flags ) {
LOG ( DEBUG ) < < " e4 crypt_destroy_user_storage for volume " < < escape_empty ( volume_uuid )
LOG ( DEBUG ) < < " fs crypt_destroy_user_storage for volume " < < escape_empty ( volume_uuid )
< < " , user " < < user_id < < " , flags " < < flags ;
< < " , user " < < user_id < < " , flags " < < flags ;
bool res = true ;
bool res = true ;
@ -764,7 +764,7 @@ bool e4crypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_
res & = destroy_dir ( misc_ce_path ) ;
res & = destroy_dir ( misc_ce_path ) ;
res & = destroy_dir ( vendor_ce_path ) ;
res & = destroy_dir ( vendor_ce_path ) ;
} else {
} else {
if ( e4 crypt_is_native( ) ) {
if ( fs crypt_is_native( ) ) {
res & = destroy_volkey ( misc_ce_path , volume_uuid ) ;
res & = destroy_volkey ( misc_ce_path , volume_uuid ) ;
}
}
}
}
@ -793,7 +793,7 @@ bool e4crypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_
res & = destroy_dir ( misc_de_path ) ;
res & = destroy_dir ( misc_de_path ) ;
res & = destroy_dir ( vendor_de_path ) ;
res & = destroy_dir ( vendor_de_path ) ;
} else {
} else {
if ( e4 crypt_is_native( ) ) {
if ( fs crypt_is_native( ) ) {
res & = destroy_volkey ( misc_de_path , volume_uuid ) ;
res & = destroy_volkey ( misc_de_path , volume_uuid ) ;
}
}
}
}
@ -828,9 +828,9 @@ static bool destroy_volume_keys(const std::string& directory_path, const std::st
return res ;
return res ;
}
}
bool e4 crypt_destroy_volume_keys( const std : : string & volume_uuid ) {
bool fs crypt_destroy_volume_keys( const std : : string & volume_uuid ) {
bool res = true ;
bool res = true ;
LOG ( DEBUG ) < < " e4 crypt_destroy_volume_keys for volume " < < escape_empty ( volume_uuid ) ;
LOG ( DEBUG ) < < " fs crypt_destroy_volume_keys for volume " < < escape_empty ( volume_uuid ) ;
auto secdiscardable_path = volume_secdiscardable_path ( volume_uuid ) ;
auto secdiscardable_path = volume_secdiscardable_path ( volume_uuid ) ;
res & = android : : vold : : runSecdiscardSingle ( secdiscardable_path ) ;
res & = android : : vold : : runSecdiscardSingle ( secdiscardable_path ) ;
res & = destroy_volume_keys ( " /data/misc_ce " , volume_uuid ) ;
res & = destroy_volume_keys ( " /data/misc_ce " , volume_uuid ) ;