分享好友 最新资讯首页 最新资讯分类 切换频道
Android加密之全盘加密手机加密「Android加密之全盘加密」
2025-05-12 12:23

前言

Android 的安全性问题一直备受关注,Google 在 Android 系统的安全方面也是一直没有停止过更新,努力做到更加安全的手机移动操作系统。
在 Android 的安全性方面,有很多模块

  1. 内核安全性
  2. 应用安全性
  3. 应用签名
  4. 身份验证
  5. Trusty TEE
  6. SELinux
  7. 加密 

 

等等其中,加密又分全盘加密(Android 4.4 引入)和文件级加密(Android 7.0 引入,本文将论述加密中的全盘加密的基本知识。全盘加密在 Android 4.4 中引入,在 Android 5.0 中做了比较大的更新。

本文部分片段摘自 Android 官网,融合笔者的个人理解和知识。

 

什么是全盘加密

全盘加密是使用已加密的密钥对 Android 设备上的所有用户数据进行编码的过程。设备经过加密后,所有由用户创建的数据在写入磁盘之前都会自动加密,并且所有读取操作都会在将数据返回给调用进程之前自动解密数据。
Android 5.0 中又引入了以下新功能

  • 创建了快速加密方式,这种加密方式只会对数据分区中已使用的分块进行加密,以免首次启动用时过长。目前只有 EXT4 和 F2FS 文件系统支持快速加密。
  • 添加了 forceencrypt fstab 标记,以便在首次启动时进行加密。
  • 添加了对解锁图案和无密码加密的支持。
  • 添加了由硬件支持的加密密钥存储空间,该空间使用可信执行环境(TEE,例如 TrustZone)的签名功能。

 

全盘加密运作方式

Android 全盘加密基于在块设备层运行的内核功能 dm-crypt。因此,这种加密方式适用于以块设备的形式呈现给内核的嵌入式多媒体卡 (eMMC) 和类似闪存设备。YAFFS 会直接与原始 NAND 闪存芯片交互,无法进行全盘加密。全盘加密采用的是 128 位高级加密标准 (AES) 算法(搭配密码块链接 (CBC) 和 ESSIV:SHA256)。对主密钥进行加密时使用的是 128 位 AES 算法,并会调用 OpenSSL 库。对于该密钥,您必须使用 128 位或更多位(可以选择 256 位)。
Android 5.0 版中有以下 4 种加密状态

  • 默认
  • PIN 码
  • 密码
  • 解锁图案

首次启动时,设备会创建一个随机生成的 128 位主密钥,然后会使用默认密码和存储的盐对其进行哈希处理。默认密码是“default_password”。不过,设备还会通过 TEE(例如 TrustZone)为生成的哈希签名。TEE 会使用相应签名的哈希来加密主密钥。
您可以在 Android 开放源代码项目 cryptfs.c 文件中找到定义的默认密码。
当用户在设备上设置 PIN 码/通行码或密码时,只有 128 位的密钥会被重新加密并存储起来(也就是说,更改用户 PIN 码/通行码/解锁图案不会导致重新加密用户数据)。请注意,受管理的设备可能受 PIN 码、解锁图案或密码限制。
加密操作由 init 和 vold 管理。 init 负责调用 vold,然后 vold 会设置相关属性以触发 init 中的事件。系统的其他部分也会查看这些属性以执行各项任务,例如报告状态、提示输入密码,或有严重错误发生时提示恢复出厂设置。为了调用 vold 中的加密功能,系统会使用命令行工具 vdc 的 cryptfs 命令:checkpw、restart、enablecrypto、changepw、cryptocomplete、verifypw、setfield、getfield、mountdefaultencrypted、getpwtype、getpw 以及 clearpw。
要加密、解密或清空 /data,/data 不得处于装载状态。但要显示任何界面,框架都必须启动,而框架需要 /data 才能运行。为了解决这一冲突,/data 上会装载一个临时文件系统。通过该文件系统,Android 可以提示输入密码、显示进度或根据需要建议清除数据。不过,该文件系统会带来以下限制:要从临时文件系统切换到实际的 /data 文件系统,系统必须停止临时文件系统中打开了文件的所有进程,并在实际的 /data 文件系统中重启这些进程。为此,所有服务都必须位于以下其中一个组内:core、main 和 late_start

  • core:启动后一直不会关闭。
  • main:关闭,然后在用户输入磁盘密码后会重启。
  • late_start:在 /data 未解密并装载之前,一直不会启动。

为了触发这些操作,vold.decrypt 属性会被设为多种字符串。要结束和重启服务,请使用以下 init 命令

  • class_reset:停止相应服务,但允许通过 class_start 重启该服务。
  • class_start:重启相应服务。
  • class_stop:停止相应服务并添加 SVC_DISABLED 标记。被停止的服务不会对。
  • class_start 做出响应。

 

加密流程和启动流程

使用 forceencrypt 加密新设备

这是 Android 5.0 设备首次启动时的常规流程。
1、检测带有 forceencrypt 标记的未加密文件系统
/data 未加密,但需要加密,因为 forceencrypt 强制要求进行此项加密。卸载 /data。

2、开始加密 /data
vold.decrypt = “trigger_encryption” 会触发 init.rc,从而使 vold 对 /data 进行无密码加密。(因为这应该是新设备,还没有设置密码。

3、装载 tmpfs
vold 会装载一个 tmpfs /data(使用 ro.crypto.tmpfs_options 中的 tmpfs 选项,并会将 vold.encrypt_progress 属性设为 0。 vold 会准备 tmpfs /data 以便启动已加密的系统,并会将 vold.decrypt 属性设为 trigger_restart_min_framework
4、启动框架以显示进度
由于设备上几乎没有要加密的数据,加密过程很快就会完成,因此实际上通常并不会显示进度条。如需关于进度界面的更多详细信息,请参阅加密现有设备。
5、/data 加密后,关闭框架
vold 会将 vold.decrypt 设为 trigger_default_encryption,这会启动 defaultcrypto 服务。(这会启动以下流程来装载默认的已加密用户数据。)trigger_default_encryption 会检查加密类型,以了解 /data 加密是否使用了密码。由于 Android 5.0 设备是在首次启动时加密,应该没有设置任何密码,因此我们要解密并装载 /data。
6、装载 /data
接下来,init 会使用从 ro.crypto.tmpfs_options(在 init.rc 中设置)中选取的参数在 tmpfs RAMDisk 中装载 /data
7、启动框架
将 vold 设为 trigger_restart_framework,这会继续常规启动过程。
 

启动未进行默认加密的已加密设备

当您启动设有密码的已加密设备时,则会发生该流程。设备的密码可以是 PIN 码、解锁图案或密码。
1、检测设有密码的已加密设备
会发现 Android 设备已加密,因为设置了 ro.crypto.state = “encrypted” 标记
由于 /data 是使用密码加密的,因此 vold 会将 vold.decrypt 设为 trigger_restart_min_framework。

2、装载 tmpfs
init 会设置 5 个属性,以保存为 /data(包含从 init.rc 传入的参数)提供的初始装载选项。 vold 会使用这些属性来设置加密映射: 
ro.crypto.fs_type 
ro.crypto.fs_real_blkdev 
ro.crypto.fs_mnt_point 
ro.crypto.fs_options 
ro.crypto.fs_flags (ASCII 码 8 位十六进制数字,以 0x 开头

3、启动框架以提示输入密码
框架会启动并看到 vold.decrypt 已设为 trigger_restart_min_framework。这让框架知道自己是在 tmpfs /data 磁盘中启动的,并且需要获取用户密码。

不过,它首先需要确认磁盘是否已经过适当加密。它会向 vold 发送 cryptfs cryptocomplete 命令。 如果加密已成功完成,vold 会返回 0;如果发生内部错误,则会返回 -1;如果加密未成功完成,则会返回 -2。vold 通过查看 CRYPTO_ENCRYPTION_IN_PROGRESS 标记的加密元数据来确定应返回的值。如果设置了此标记,则表示加密过程中断了,并且设备上没有可用的数据。如果 vold 返回错误,界面中应显示一条消息,提示用户重新启动设备并将其恢复出厂设置,并且界面中应为用户提供一个用于执行该操作的按钮。

4、通过密码解密数据
cryptfs cryptocomplete 成功后,框架会显示一个界面,提示用户输入磁盘密码。界面会向 vold 发送 cryptfs checkpw 命令来检查用户输入的密码。如果密码正确(通过以下方式判定:在临时位置成功装载已解密的 /data,然后将其卸载,vold 会将已解密块设备的名称保存在 ro.crypto.fs_crypto_blkdev 属性中,并向界面返回状态 0。如果密码不正确,则向界面返回 -1。

5、停止框架
界面会显示加密启动图形,然后使用 cryptfs restart 命令调用 vold。vold 会将 vold.decrypt 属性设为 trigger_reset_main,这会使 init.rc 执行 class_reset main 命令。此命令会停止 main 类中的所有服务,以便卸载 tmpfs /data。

6、装载 /data
然后,vold 会装载已解密的实际 /data 分区,并准备新的分区(如果加密时采用了首次发布不支持的数据清除选项,则可能永远无法准备就绪)。它会将 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.decrypt 属性设为 trigger_restart_framework。这会使 init.rc 再次启动 main 类中的服务,并启动 late_start 类中的服务(这是设备启动后首次启动这些服务)。

7、启动整个框架
现在,框架会使用已解密的 /data 文件系统启动其所有服务,接下来系统就可以使用了。

 

 

代码解读

结合上章节的流程,下面用代码来解析启动未进行默认加密的已加密设备这个流程。

这个配置定义在 device/lge/bullhead/fstab_fbe.bullhead 文件中。
如上面的代码,在 /data 的末尾加上 fileencryption,便会进行全盘加密。

 

步骤1:检测设有密码的已加密设备

这个方法定义在文件 system/core/init/builtins.cpp 中。

 

这个服务定义在文件 system/vold/vdc.rc 中。

 

这个方法定义在文件 vold/CryptCommandListener.cpp 中。

 

这个方法定义在文件 system/vold/cryptfs.c 中。

 

这个服务定义在服务 system/core/rootdir/init.rc 中。

class_start main 可知重启 main 类别的服务。main 类别的服务包括:

会重启 zygote。

 

步骤2:装载 tmpfs

Zygote 启动后,会 fork() system_process 进程,就是运行 SystemServer 代码了。但是 system_process 的运行需要正常的用户空间(/data,所以,需要临时挂载 tmpfs 分区,这个分区是在内存里分配的临时空间。

这个方法定义在文件 system/vold/CommandListener.cpp 中。

 

这个方法定义在文件 system/core/fs_mgr/fs_mgr.c 中。

 

 

步骤3:启动框架以提示输入密码

这个方法定义在文件frameworks/base/services/java/com/android/server/SystemServer.java 中。

 

这个方法定义在文件 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java 中

 

这个方法定义在文件 frameworks/base/core/java/android/content/pm/PackageParser.java 中。

安卓中定义为 coreApp 的应用有

Framework-res.apk 的 manifest 配置文件如下

 

 

步骤4:通过密码解密数据

这个过程不再阐述。

 

步骤5:停止框架

这个 setion 定义在文件 system/core/rootdir/init.rc 中。

 

步骤6:装载 /data

这个方法定义在文件 system/core/init/builtins.cpp 中。

 

这个 setion 定义在文件 system/vold/vdc.rc 中。

 

这个 setion 定义在文件 system/vold/vdc.rc 中。

 

这个方法定义在文件 system/vold/CryptCommandListener.cpp 中。


int cryptfs_enable(char *howarg, int type, char *passwd, int no_ui)

这个方法定义在文件 system/vold/CryptCommandListener.cpp 中。

 

这个方法定义在文件 system/vold/cryptfs.c 中。

 

这个方法定义在文件 system/vold/cryptfs.c 中。

 

这个方法定义在文件 system/vold/cryptfs.c 中。

 

这个 setion 定义在文件 system/core/rootdir/init.rc 中。

 

这个 setion 定义在文件 system/core/rootdir/init.rc 中。

 

这个方法定义在文件 system/vold/cryptfs.c 中。

 

 

步骤7:启动整个框架

vold.decrypt = trigger_restart_framework, framework 就可以正常启动了。

 

加密属性

vold 和 init 之间通过设置属性进行通信。下面列出了可用的加密属性。

 

vold属性

 

init 属性

 

init 操作

 

 


Android 全盘加密分析到此为止。

参考 https://source.android.com/security/encryption/full-disk

转载:http://blog.csdn.net/myfriend0/article/details/76615114

 

 

最新文章
原创上市27个月狂卖100万台!同级销冠,配智能座舱高阶,仅售7.88万
作为隔壁老王,我最近可是被比亚迪海鸥这款小车给彻底圈粉了。倒不是说它有多完美,而是它实实在在地戳中了我们这些普通老百姓的
原创难怪科学家总被暗杀,伊朗查清原委敲警钟:联合国机构已被渗透
前言最近,伊朗揭露了一个震惊全球的消息:国际原子能机构(IAEA)竟然被以色列的摩萨德间谍渗透,背后隐藏着令人震惊的情报交易
财经资讯AI速递:昨夜今晨财经热点一览 丨2025年7月3日
  金融市场瞬息万变,投资与经济政策深刻影响全球。我们为您带来昨夜今晨的财经新闻,涵盖股市动态、经济数据、企业财务和政策
英媒:以军使用重型炸弹袭击加沙平民
  参考消息网7月4日报道 据英国《卫报》网站7月2日报道,《卫报》看到的证据显示,周一以军在袭击加沙一家拥挤的海滨咖啡馆目
团结奋进再谱新篇
  中新社发  今天是香港回归祖国28周年纪念日。连日来,香港举办多场庆祝活动,街头巷尾处处喜庆祥和。接受本报记者采访时,
聚善汇力,声生不息:如新中国“善的力量月”交出亮眼公益答卷
  每年 6 月,是如新(中国)的 “善的力量月”。作为企业发起的年度慈善公益活动,它既是如新践行社会公益的具体行动,也积极
微纪录片《淬心》第三集 | 留取丹心照汗青
  习近平总书记强调,“党性教育是共产党人修身养性的必修课,也是共产党人的‘心学 ’。”修炼共产党人的“心学”,是习近平
爆出猛料,白宫急了
  原标题:爆出猛料,白宫急了  美国是否真的已“彻底摧毁”伊朗关键核设施,这一争议仍在继续发酵。当地时间6月29日,美国
第一观察 | 这份发展战略彰显深沉而持久的力量
  1985年6月,32岁的习近平同志来到厦门工作,“第一次直接参与沿海发达地区的改革开放,第一次亲历城市的建设和管理”。  
胡欣:特朗普军改,玩的什么“高端局”
【文/胡欣】 特朗普是个大刀阔斧、我行我素的“狠角色”,其第二任期开启以来,把大量精力花在对内精简政府机构、对外打关税战之
推荐文章