【输出文档】 Android 加密 模块源码分析

本文详细解析了Android 6.0系统中加密模块的工作流程,涵盖了不同情况下的设备加密,包括强制加密设备的首次开机、已加密设备的开机、已加密设备有密码和无密码状态的开机。文章深入探讨了从检查forceencrypt标志位、加密/data、挂载tmpfs到启动framework显示加密进度的全过程,涉及vold、init、fs_mgr等多个关键组件。此外,还分析了加密类型、do_mount_all、handle_encryptable和vold加密流程等关键步骤,为理解Android系统的加密机制提供了详尽的指南。
摘要由CSDN通过智能技术生成

 

 

 

 

                           Android6.0 加密模块解析

 

 

前言:

加密流程就是用一个加密了的key对Android 系统中的用户数据进行加密。一旦设备被加密了,所有用户创建的数据在提交到磁盘前都会被自动加密,并且在返回到调用的进程前,所有的用户数据会被自动解密。

   Android 的disk机密是基于dm-crypt的,dm-crypt是kernl上运行在block 设备层的一个加密工具。因此,加密实际操作对象是对嵌入式多媒体存储设备(eMMC)和类似的闪存设备中保存的数据信息。加密是不可能基于YAFFS工具的,因为YAFFS是直接与NAND闪存芯片进行通信的。

  1. 加密类型

加密流程对于一个设备来说,有可能出现4中不同的情况,但是一般情况下,都是对设备进行一次加密,然后再进行一个正常的开机流程:

    ●加密一个之前没有加密的设备:

      • 在fstab配置信息中标注了forceencrypt= true,第一次开机时会强制性进行加密;

      • 在fstab配置信息中没有标注 forceencrypt= true,第一次开机不会强制性进行加密,需要用户开机后手动触发加密流程。

 

    ●一个已经加密设备的开机:

  • 在无密码状态下对已加密的设备进行开机

  • 在有密码需求的状态下对加密设备的开机

针对以上4中情况,我们把加密具体分为以下4中具体的流程:

 

1.1 对强制要求加密的设备进行加密

 

   这是从Android 5.0 开始,google原生机默认的开机模式,即在google原生机的fstab配置文件中,/data分区都是标注了forceencrypt = true 信息的。

1.1.1 检查forceencrypt 标志位

init 先按照fstab的配置信息检查 forceencrypt 配置信息,需要加密,init Unmount /data.

1.1.2 加密/data

init服务会设置vold.decrypt = "trigger_encryption",这个属性的变化触发init 挂载fstab文件中的分区配置时返回“FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION”值,触发vold.decrypt = trigger_encryption,init 启动surfaceflinger 和encrypt服务。

 

on property:vold.decrypt=trigger_encryption

    start surfaceflinger

    start encrypt

 

 

1.1.3 mount tmpfs

vold服务将挂载一个临时的“/data”,将记录加密进度的系统属性vold.encrypt_progress 赋值为“0”。vold 挂载这个tmpfs data 的作用在于

1.2 对已经正常开机的设备进行加密

对一个未加密的设备进行加密

这个流程就是由用户触发的,并且将指向“inplace encryption”这个流程,这时UI 会要求手机电池是充满状态而且USB 线是连接状态。

注:加密流程中如果断电,必须恢复出厂设置后才能继续使用

使能“inplace encryption”,vold会启动一个loop来读取real block device 的每个sector并且将它写入crypto block device。vold 会在读写sector之前先检查它是否有被调用,这个让encryption在左右一点数据记录的新设备上比较迅速。

 

设备状态相关:设置 ro.crypto.state = “unencrypted” 并且执行init中“on nonencrypted ”触发的流程

 

1.2.1.检查password:

  UI会通过"cryptfs enable inplace"这个命令来要求输入锁屏的password来开始流程;

 

1.2.2.关闭framework:

  vold会检查errors,返回 -1 就表示无法加密并且打印相应log。如果可以加密,将会设置 系统属性 “vold.decrypt =trigger_shutdown_framework.”,这将会导致init.rc 关闭 late_started 和main 类的services.

 

1.2.3.卸载 /data分区:

  vold 会卸载“ mnt/sdcard” 和“/data” 分区

 

1.2.4.开始加密 /data分区

  vold 会开启crupto mapping,这会创建一个虚拟的crypto block device,它会在真实的block device 上进行“map”并且会在write时进行加密,read时进行解密。vold将会创建并写出 crypto metadata.

 

1.2.5.在加密过程中,挂载tmpfs:

  vold 会在/data分区挂载一个tmpfs(挂载时是option 属性通过ro.crpto.tmpfs_option来确定)。然后设置属性“vold.encrypt_progress = 0”。vold 将/data这个tmpfs用于启动一个加密了的system并且设置系统属性 vold.decrypt = trigger_restart_min_fraemwork.

 

1.2.6.启动framework来展示加密进度

trigger_restart_min_framework 会唤起init.rc来start main class services.当famework监听到vold.encrypt_progress = 0时,它会启动显示进度条的UI,它每隔5秒钟就检查这个系统属性并且跟新进度条。encryptiom loop每次加密完成其他的partition后,它都会更新vold.encrypt_progress这个属性。

 

1.2.7.当/data加密完成,重启

当/data分区加密成功,vold会清除metadata中的ENCRYPTION_IN_PROGRESS这个flags,并且重启system

如果重启失败,vold会设置属性vold.encrypt_progress = error_failed 并且在UI 中展示一条信息,要求用户重启。

 

1.3 已加密的设备有密码状态下的开机

这种情况指的是: 你启动的是一个设置了密码的加密系统,这个系统的加密密码 可能是一个pin ,pattern 或者密码

1.3.1.检测加密设备的密码
通过判断标志位 ro.crypto.state = "encrypted"来确定设备已经被加密了
vold 会设置 “vold.decrypt = trigger_restart_min_framework”,因为 /data 已经被一个密码加密了

1.3.2.挂载tmpfs
init.rc中传递下来的关于/data 挂载的options 被init进程用5个系统属性保存下来。vold使用这些系统属性来启动加密流程:
  1.ro.crypto.fs_type
  2.ro.crypto.fs_real_blkdev
  3.ro.crypto.fs_mnt_point
  4.ro.crypto.fs_options
  5.ro.crypto.fs_flags

1.2.3.启动framework来要求输入password
framework启动后会监听vold.decrypt = trigger_restart_min_framework.此时framerwork就知道现在是正在启动一个tmpfs /data并且它需要获取用户的password。
然而,首先我们必须确定disk已经被正确的加密了。我们会向vold发送命令“cryptfs cryptocomplete ”,如果加密成功,vold会返回0;如果出现错误,会返回 -1;如果加密没有完全完成,会返回-2.
vold是通过检查crypto metadata的CRYPTO_ENCRYPTION_IN_PROCESS标志位。如果crypto metadata中的这个标志位被设定了,加密的流程就被打断,并且设备上就不再有可用的数据了。如果vold返回一
个错误,UI会要求用户重启并对设备恢复出厂设置。

1.2.4.获取password后对data分区进行解密
  一旦cryptfs crytocomplete 成功了,framework会展示一个UI 界面来请求disk的password。UI 会将用户传入的password通过下发cryptfs checkpw命令到vold来检查。如果password是正确的(检查password正确的方法是可以成功的在一个暂时的区域挂载加密了的/data并且可以卸载它),vold将会保存加密了的块设备的名称在属性ro.crypto.fs_crypto_blkdev中并且返回0 到UI 进程,如果passworf是错误的,返回-1 到UI 进程。
 
1.2.5.关闭framework
  UI将会启动一个crypto boot graphic 并且通过cryptfs restart.vold 这个命令来设置系统属性 vold.decrypt = trigger_restart_min_main,这导致init.rc来启动class_reset main.这会停止所有的main类的service,而这些service保证了/data 这个tmpf处于未挂载状态。
 
1.2.6. 挂载/data分区
  vold 会挂载已经加密了的/data 分区并且准备新的分区,如果这个分区是按照wipe命令进行加密的,这个分区可能未初始化好的。然后会修改系统属性 vold.post_fs_data_done = 0 然后设置vold.decrypt = trigger_post_fs_data.这导致init.rc来运行post-fs-data命令。它们会创建必要的路径或者链接然后设置vold.post_fs_data_done = 1.一旦vold 监听到这个属性等于1,vold将设置系统属性 vold.decrypt = trigger_restart_framework.这导致init.rc重新启动main 类的service并且同时启动lte_start类的services。
1.2.7.启动整个framework

1.4 已加密的设备无密码状态下的开机

与1.3 相同,唯一的区别在于启动framework层后不会初始化输入密码的界面。

  1. 具体模块解析

流程图:

  1. 机密流程

3.1 do_mount_all 分析

3.1.1 do_mount_all 代码

init 会调用fs_mgr中do_mount_all 解析fstab文件,并对其中的配置信息进行挂载:

 

system/core/init/builtins.cpp

 

int do_mount_all(int nargs, char **args)

{

... ...

//fork 一个子进程,执行mount

    pid = fork();

    if (pid > 0) {

        /* Parent.  Wait for the child to return */

        int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));

... ...

ret = WEXITSTATUS(status);

... ...

    } else if (pid == 0) {

//子进程,args[1]参数就是”/fstab.flo”,fs_mgr_read_fstab将解析fstab文件

        fstab = fs_mgr_read_fstab(args[1]);

        child_ret = fs_mgr_mount_all(fstab);

        fs_mgr_free_fstab(fstab);

... ...

    }

if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {

    //fstab 中设置了默认强制加密

        property_set("vold.decrypt", "trigger_encryption");

} else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {

    //设备已经加密

        property_set("ro.crypto.state", "encrypted");

        property_set("ro.crypto.type", "block");

        property_set("vold.decrypt", "trigger_default_encryption");

} else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {

    //设备未加密,什么都不用处理

        property_set("ro.crypto.state", "unencrypted");

        /* If fs_mgr determined this is an unencrypted device, then trigger

         * that action.

         */

        action_for_each_trigger("nonencrypted", action_add_queue_tail);

    } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {

... ...

    } else if (ret == FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED) {

... ...

    } else if (ret == FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED) {

... ...

    } else if (ret > 0) {

        ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);

    }

}

 

● do_mount_all 的作用就是:

   •系统第一次开机,而且系统设置为强制加密,就走FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION

   •系统机密后开机,发现设备加密了,FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED

   •系统正常开机,不用加密,

FS_MGR_MNTALL_DEV_NOT_ENCRYPTED

 

3.1.2 fs_mgr_mount_all

system/core/fs_mgr/fs_mgr.c

 

int fs_mgr_mount_all(struct fstab *fstab)

{

... ...

    int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;

... ...

for (i = 0; i < fstab->num_entries; i++) {

... ...

        mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);

... ...

//如果设备已机密,mret = -1/data 分区是无法正常挂载的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值