@ -45,6 +45,7 @@
# include <fs_mgr.h>
# include <fscrypt/fscrypt.h>
# include <hardware_legacy/power.h>
# include <libdm/dm.h>
# include <log/log.h>
# include <logwrap/logwrap.h>
# include <openssl/evp.h>
@ -56,13 +57,11 @@
# include <fcntl.h>
# include <inttypes.h>
# include <libgen.h>
# include <linux/dm-ioctl.h>
# include <linux/kdev_t.h>
# include <math.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/ioctl.h>
# include <sys/mount.h>
# include <sys/param.h>
# include <sys/stat.h>
@ -78,12 +77,11 @@ extern "C" {
using android : : base : : ParseUint ;
using android : : base : : StringPrintf ;
using android : : fs_mgr : : GetEntryForMountPoint ;
using namespace android : : dm ;
using namespace std : : chrono_literals ;
# define UNUSED __attribute__((unused))
# define DM_CRYPT_BUF_SIZE 4096
# define HASH_COUNT 2000
constexpr size_t INTERMEDIATE_KEY_LEN_BYTES = 16 ;
@ -253,19 +251,6 @@ static void cryptfs_reboot(RebootType rt) {
return ;
}
static void ioctl_init ( struct dm_ioctl * io , size_t dataSize , const char * name , unsigned flags ) {
memset ( io , 0 , dataSize ) ;
io - > data_size = dataSize ;
io - > data_start = sizeof ( struct dm_ioctl ) ;
io - > version [ 0 ] = 4 ;
io - > version [ 1 ] = 0 ;
io - > version [ 2 ] = 0 ;
io - > flags = flags ;
if ( name ) {
strlcpy ( io - > name , name , sizeof ( io - > name ) ) ;
}
}
namespace {
struct CryptoType ;
@ -973,109 +958,12 @@ static void convert_key_to_hex_ascii(const unsigned char* master_key, unsigned i
master_key_ascii [ a ] = ' \0 ' ;
}
static int load_crypto_mapping_table ( struct crypt_mnt_ftr * crypt_ftr ,
const unsigned char * master_key , const char * real_blk_name ,
const char * name , int fd , const char * extra_params ) {
alignas ( struct dm_ioctl ) char buffer [ DM_CRYPT_BUF_SIZE ] ;
struct dm_ioctl * io ;
struct dm_target_spec * tgt ;
char * crypt_params ;
// We need two ASCII characters to represent each byte, and need space for
// the '\0' terminator.
char master_key_ascii [ MAX_KEY_LEN * 2 + 1 ] ;
size_t buff_offset ;
int i ;
io = ( struct dm_ioctl * ) buffer ;
/* Load the mapping table for this device */
tgt = ( struct dm_target_spec * ) & buffer [ sizeof ( struct dm_ioctl ) ] ;
ioctl_init ( io , DM_CRYPT_BUF_SIZE , name , 0 ) ;
io - > target_count = 1 ;
tgt - > status = 0 ;
tgt - > sector_start = 0 ;
tgt - > length = crypt_ftr - > fs_size ;
strlcpy ( tgt - > target_type , " crypt " , DM_MAX_TYPE_NAME ) ;
crypt_params = buffer + sizeof ( struct dm_ioctl ) + sizeof ( struct dm_target_spec ) ;
convert_key_to_hex_ascii ( master_key , crypt_ftr - > keysize , master_key_ascii ) ;
buff_offset = crypt_params - buffer ;
SLOGI (
" Creating crypto dev \" %s \" ; cipher=%s, keysize=%u, real_dev=%s, len=%llu, params= \" %s \" \n " ,
name , crypt_ftr - > crypto_type_name , crypt_ftr - > keysize , real_blk_name , tgt - > length * 512 ,
extra_params ) ;
snprintf ( crypt_params , sizeof ( buffer ) - buff_offset , " %s %s 0 %s 0 %s " ,
crypt_ftr - > crypto_type_name , master_key_ascii , real_blk_name , extra_params ) ;
crypt_params + = strlen ( crypt_params ) + 1 ;
crypt_params =
( char * ) ( ( ( unsigned long ) crypt_params + 7 ) & ~ 8 ) ; /* Align to an 8 byte boundary */
tgt - > next = crypt_params - buffer ;
for ( i = 0 ; i < TABLE_LOAD_RETRIES ; i + + ) {
if ( ! ioctl ( fd , DM_TABLE_LOAD , io ) ) {
break ;
}
usleep ( 500000 ) ;
}
if ( i = = TABLE_LOAD_RETRIES ) {
/* We failed to load the table, return an error */
return - 1 ;
} else {
return i + 1 ;
}
}
static int get_dm_crypt_version ( int fd , const char * name , int * version ) {
char buffer [ DM_CRYPT_BUF_SIZE ] ;
struct dm_ioctl * io ;
struct dm_target_versions * v ;
io = ( struct dm_ioctl * ) buffer ;
ioctl_init ( io , DM_CRYPT_BUF_SIZE , name , 0 ) ;
if ( ioctl ( fd , DM_LIST_VERSIONS , io ) ) {
return - 1 ;
}
/* Iterate over the returned versions, looking for name of "crypt".
* When found , get and return the version .
*/
v = ( struct dm_target_versions * ) & buffer [ sizeof ( struct dm_ioctl ) ] ;
while ( v - > next ) {
if ( ! strcmp ( v - > name , " crypt " ) ) {
/* We found the crypt driver, return the version, and get out */
version [ 0 ] = v - > version [ 0 ] ;
version [ 1 ] = v - > version [ 1 ] ;
version [ 2 ] = v - > version [ 2 ] ;
return 0 ;
}
v = ( struct dm_target_versions * ) ( ( ( char * ) v ) + v - > next ) ;
}
return - 1 ;
}
static std : : string extra_params_as_string ( const std : : vector < std : : string > & extra_params_vec ) {
if ( extra_params_vec . empty ( ) ) return " " ;
std : : string extra_params = std : : to_string ( extra_params_vec . size ( ) ) ;
for ( const auto & p : extra_params_vec ) {
extra_params . append ( " " ) ;
extra_params . append ( p ) ;
}
return extra_params ;
}
/*
* If the ro . crypto . fde_sector_size system property is set , append the
* parameters to make dm - crypt use the specified crypto sector size and round
* the crypto device size down to a crypto sector boundary .
*/
static int add_sector_size_param ( std : : vector < std : : string > * extra_params_vec ,
struct crypt_mnt_ftr * ftr ) {
static int add_sector_size_param ( DmTargetCrypt * target , struct crypt_mnt_ftr * ftr ) {
constexpr char DM_CRYPT_SECTOR_SIZE [ ] = " ro.crypto.fde_sector_size " ;
char value [ PROPERTY_VALUE_MAX ] ;
@ -1089,12 +977,11 @@ static int add_sector_size_param(std::vector<std::string>* extra_params_vec,
return - 1 ;
}
std : : string param = StringPrintf ( " sector_size:%u " , sector_size ) ;
extra_params_vec - > push_back ( std : : move ( param ) ) ;
target - > SetSectorSize ( sector_size ) ;
// With this option, IVs will match the sector numbering, instead
// of being hard-coded to being based on 512-byte sectors.
extra_params_vec- > emplace_back ( " iv_large_sectors " ) ;
target- > SetIvLargeSectors ( ) ;
// Round the crypto device size down to a crypto sector boundary.
ftr - > fs_size & = ~ ( ( sector_size / 512 ) - 1 ) ;
@ -1105,112 +992,67 @@ static int add_sector_size_param(std::vector<std::string>* extra_params_vec,
static int create_crypto_blk_dev ( struct crypt_mnt_ftr * crypt_ftr , const unsigned char * master_key ,
const char * real_blk_name , char * crypto_blk_name , const char * name ,
uint32_t flags ) {
char buffer [ DM_CRYPT_BUF_SIZE ] ;
struct dm_ioctl * io ;
unsigned int minor ;
int fd = 0 ;
int err ;
int retval = - 1 ;
int version [ 3 ] ;
int load_count ;
std : : vector < std : : string > extra_params_vec ;
if ( ( fd = open ( " /dev/device-mapper " , O_RDWR | O_CLOEXEC ) ) < 0 ) {
SLOGE ( " Cannot open device-mapper \n " ) ;
goto errout ;
}
auto & dm = DeviceMapper : : Instance ( ) ;
io = ( struct dm_ioctl * ) buffer ;
ioctl_init ( io , DM_CRYPT_BUF_SIZE , name , 0 ) ;
err = ioctl ( fd , DM_DEV_CREATE , io ) ;
if ( err ) {
SLOGE ( " Cannot create dm-crypt device %s: %s \n " , name , strerror ( errno ) ) ;
goto errout ;
}
// We need two ASCII characters to represent each byte, and need space for
// the '\0' terminator.
char master_key_ascii [ MAX_KEY_LEN * 2 + 1 ] ;
convert_key_to_hex_ascii ( master_key , crypt_ftr - > keysize , master_key_ascii ) ;
/* Get the device status, in particular, the name of it's device file */
ioctl_init ( io , DM_CRYPT_BUF_SIZE , name , 0 ) ;
if ( ioctl ( fd , DM_DEV_STATUS , io ) ) {
SLOGE ( " Cannot retrieve dm-crypt device status \n " ) ;
goto errout ;
}
minor = ( io - > dev & 0xff ) | ( ( io - > dev > > 12 ) & 0xfff00 ) ;
snprintf ( crypto_blk_name , MAXPATHLEN , " /dev/block/dm-%u " , minor ) ;
auto target = std : : make_unique < DmTargetCrypt > ( 0 , crypt_ftr - > fs_size ,
( const char * ) crypt_ftr - > crypto_type_name ,
master_key_ascii , 0 , real_blk_name , 0 ) ;
target - > AllowDiscards ( ) ;
if ( ! get_dm_crypt_version ( fd , name , version ) ) {
/* Support for allow_discards was added in version 1.11.0 */
if ( ( version [ 0 ] > = 2 ) | | ( ( version [ 0 ] = = 1 ) & & ( version [ 1 ] > = 11 ) ) ) {
extra_params_vec . emplace_back ( " allow_discards " ) ;
}
}
if ( flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE ) {
extra_params_vec. emplace_back ( " allow_encrypt_override " ) ;
target - > AllowEncryptOverride ( ) ;
}
if ( add_sector_size_param ( & extra_params_vec , crypt_ftr ) ) {
if ( add_sector_size_param ( target . get ( ) , crypt_ftr ) ) {
SLOGE ( " Error processing dm-crypt sector size param \n " ) ;
goto errout ;
return - 1 ;
}
load_count = load_crypto_mapping_table ( crypt_ftr , master_key , real_blk_name , name , fd ,
extra_params_as_string ( extra_params_vec ) . c_str ( ) ) ;
if ( load_count < 0 ) {
DmTable table ;
table . AddTarget ( std : : move ( target ) ) ;
int load_count = 1 ;
while ( load_count < TABLE_LOAD_RETRIES ) {
if ( dm . CreateDevice ( name , table ) ) {
break ;
}
load_count + + ;
}
if ( load_count > = TABLE_LOAD_RETRIES ) {
SLOGE ( " Cannot load dm-crypt mapping table. \n " ) ;
goto errout ;
} else if ( load_count > 1 ) {
return - 1 ;
}
if ( load_count > 1 ) {
SLOGI ( " Took %d tries to load dmcrypt table. \n " , load_count ) ;
}
/* Resume this device to activate it */
ioctl_init ( io , DM_CRYPT_BUF_SIZE , name , 0 ) ;
if ( ioctl ( fd , DM_DEV_SUSPEND , io ) ) {
SLOGE ( " Cannot resume the dm-crypt device \n " ) ;
goto errout ;
std : : string path ;
if ( ! dm . GetDmDevicePathByName ( name , & path ) ) {
SLOGE ( " Cannot determine dm-crypt path for %s. \n " , name ) ;
return - 1 ;
}
snprintf ( crypto_blk_name , MAXPATHLEN , " %s " , path . c_str ( ) ) ;
/* Ensure the dm device has been created before returning. */
if ( android : : vold : : WaitForFile ( crypto_blk_name , 1 s ) < 0 ) {
// WaitForFile generates a suitable log message
goto errout ;
return - 1 ;
}
/* We made it here with no errors. Woot! */
retval = 0 ;
errout :
close ( fd ) ; /* If fd is <0 from a failed open call, it's safe to just ignore the close error */
return retval ;
return 0 ;
}
static int delete_crypto_blk_dev ( const char * name ) {
int fd ;
char buffer [ DM_CRYPT_BUF_SIZE ] ;
struct dm_ioctl * io ;
int retval = - 1 ;
int err ;
if ( ( fd = open ( " /dev/device-mapper " , O_RDWR | O_CLOEXEC ) ) < 0 ) {
SLOGE ( " Cannot open device-mapper \n " ) ;
goto errout ;
}
io = ( struct dm_ioctl * ) buffer ;
ioctl_init ( io , DM_CRYPT_BUF_SIZE , name , 0 ) ;
err = ioctl ( fd , DM_DEV_REMOVE , io ) ;
if ( err ) {
SLOGE ( " Cannot remove dm-crypt device %s: %s \n " , name , strerror ( errno ) ) ;
goto errout ;
static int delete_crypto_blk_dev ( const std : : string & name ) {
auto & dm = DeviceMapper : : Instance ( ) ;
if ( ! dm . DeleteDevice ( name ) ) {
SLOGE ( " Cannot remove dm-crypt device %s: %s \n " , name . c_str ( ) , strerror ( errno ) ) ;
return - 1 ;
}
/* We made it here with no errors. Woot! */
retval = 0 ;
errout :
close ( fd ) ; /* If fd is <0 from a failed open call, it's safe to just ignore the close error */
return retval ;
return 0 ;
}
static int pbkdf2 ( const char * passwd , const unsigned char * salt , unsigned char * ikey ,
@ -1924,7 +1766,7 @@ int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const u
* storage volume .
*/
int cryptfs_revert_ext_volume ( const char * label ) {
return delete_crypto_blk_dev ( ( char * ) label ) ;
return delete_crypto_blk_dev ( label ) ;
}
int cryptfs_crypto_complete ( void ) {