Verified Boot
转载自http://luomingmao.com/2016/08/29/Verified-Boot/
简介
Verified Boot 是 Android 4.4 开始引入的一个新特性,作用是在系统启动时校验 system 分区是否被篡改。好处在于可以检测到 system “发生过” 改动,比如用户使用 root 软件强行植入 su 文件,但最后删除了 su, 这种情况也能检测出来。一旦检验不过,系统就不能正常启动,并且有相关的图文提示,请参看:https://source.android.com/security/verifiedboot/index.html
Android 6.0 的 CDD 文档,章节 9.10. Verified Boot 对该特性有详细的描述。可知,在出厂搭载 Android 6.0 系统的设备上,如果硬件达到要求,是必须激活这一特性的。请参看:https://static.googleusercontent.com/media/source.android.com/en//compatibility/android-cdd.pdf
启用
在编译系统中开启签名 boot.img 和 recovery.img功能:
build/target/product/verity.mk文件中添加:
PRODUCT_SUPPORTS_VERITY := true
修改device/qcom/msm8996/msm8996.mk文件:
PRODUCT_SPPORTS_VERITY := true
开启 LK 验证 Boot 和 Recovery 功能:
Bootable/bootloader/lk/AndroidBoot.mk 文件中:
ifeq($PRODUCT.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY), true)VERIFIED_BOOT := VERIFIED_BOOT = 1
elseVERIFIED_BOOT := VERIFIED_BOOT = 0
endif
在 device/OEM/project_name/project_name.mk 中添加:
PRODUCT_SUPPORTS_VERITY := true
PRODUCT_SYSTEM_VERITY_PARTITION := /dev/block/bootdevice/by-name/system
$(call inherit-product, build/target/product/verity.mk)PRODUCT_COPY_FILES += \frameworks/native/data/etc/android.software.verified_boot.xm:system/etc/permissions/android.software.verified_boot.xml
在 device/OEM/project_name/fstab.qcom中添加verify标志:
/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1,discard wait,verify
签名key
默认开发 key
包括公钥和私钥,它们位于:build/target/product/security/. 它们用来给 boot 和 recovery 签名,以及验证 system partition 的 metadata table. 它们的位置定义位于:build/target/product/verity.mk 文件中:
PRODUCT_VERITY_SIGNING_KDY := build/target/product/security/verity
Key 文件作用说明:
build/target/product/security/
- verity.pk8 – private key used to sign boot.img and system.img
- verity.x509.pem – certificate include public key
- verity_key – public key used in dm verity for system.img
有些老的版本只有两个key文件: - verity_private_dev_key – private key used to sign boot.img and system.img
- verity_key – public key used in dm verity for system image
我们可以看到在 build/core/Makefile 文件中:
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER) $(BOOTIMAGE_EXTRA_DEPS)
$(call pretty,"Target boot image: $@")
$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
$(BOOT_SIGNER) /boot $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $@
$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
生成 OEM 自己的公钥密钥对
在 Linux 系统中,确保所安装的 openssl 版本足够新,可以参看: /m8996/build/target/product/security_releasekey/README 文件。
>openssl version
OpenSSL 1.0.2d 9 Jul 2015
>development/tools/make_key mykey '/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
不用输入密码,然后 mykey.pk8 和 mykey.x509.pem 将会在当前目录生成。
为DM-Verity 功能生成 verity key
生成 generate_verity_key
使用下面的命令来生成 verity key 的工具 generate_verity_key:
source build/envsetup.sh
choosecombo
make generate_verity_key (mmm system/extras/verity/)
将 *.x509.pem 转换成 verity key
generate_verity_key 的代码位于:system/extra/verity/generate_verity_key.c
generate_verity_key 的用法:generate_verity_key | -convert
out/host/linux-x86/bin/generate_verity_key -convert mykey.x509.pem verity_key
拷贝并重命名
拷贝mykey.pk8,mykey.x509.pem,verity_key.pub 至 build/target/product/security/ 目录,将其重命名: verity.pk8, verity.x509.pem,verity_key ,并替换默认的开发 key。
生成 keystore
在 LK 里面,有两个 keystore:
oem_keystore: 编译到 LK 里面,它定义在 /bootloader/lk/platform/msm_shared/include/oem_keystore.h 中。
user_keystore: 存储在”keystore”分区里面。
LK 将使用 OEM keystore 来验证 keystore 分区, 如果验证通过, 将从里面读取 user_keystore,然后用其验证 boot.img 和 recovery.img。
Google 已经在后来的 release 里移除 user_keystore,不需要 keystore 分区。
使用system/extras/verity/keystore_signer, 它实际上是调用openssl 的一个脚本,所以也可以直接调用 openssl来实现。
keystore_signer <privatekey.pk8> <crefificate.x509.pem> <outfile> <publickey0.der>
>openssl rsa -in mykey.pk8 -inform DER -pubout -outform DER -out mypub.der
>java -Xmx512M -jar out/host/linux-x86/framework/KeystoreSigner.jar mykey.pk8 mykey.x509.pem keystore.img mypub.der
如果在没有 pk8 格式的老版本上,则可以使用下面的命令:
>keystore_signer <PRIVATE_KEY> <KEYSTORE_IMG> <RSA_PUBLIC_KEY_DER>
>java -Xmx512M -jar out/host/linux-x86/framework/KeystoreSigner.jar verity_private_dev_key keystore.img mypub.der
通过上述命令获取 keystore.img之后,可以通过fast boot来刷。
Fastboot flash keystore keystore.img
当然,如果没有keystore分区,这步可以忽略
Oem_keystore可以通过下面的方法使用相同的key
通过下面的脚本将keystore.img生成oem_keystore.h文件
function generate_oem_keystore_h()
{ echo \#ifndef __OEM_KEYSTORE_H echo \#define __OEM_KEYSTORE_H xxd -i $1 | sed -e 's/unsigned char .* = {/const unsigned char OEM_KEYSTORE[] = {/g' -e 's/unsigned int .* =.*;//g' echo \#endif
}
generate_oem_keystore_h keystore.img > oem_keystore.h
将该oem_keystore.h文件拷贝到:bootable/bootloader/lk/platform/msm_shared/include
在 LK 中的代码调用流程
- boot_linux_from_mmc
- boot_verifier_init
- verify_signed_bootimg -> boot_verify_image -> verify_image_with_sig
手机安全状态
开启 Verified Boot 功能的设备有三种安全状态:locked, verified 和 unlocked。任何状态的转换都需要使用 fastboot 命令,同时也会擦除 /data 分区(分区置0),当手机启动的时候,新的状态才会改变,同时会将一个新的文件系统挂载到 /data。除此之外,安全状态的改变用户通过物理按键(开机键,音量上下键等)的方式来确认,另外,如果是转换到 unlocked 状态,需要在开发者选项者将 OEM unlock 打开(这步需要屏幕锁验证),同时通过 fastboot oem unlock 打开。
locked state:
- 用户不能使用 fastboot 命令下载或者擦除任何分区。
- boot 和 recovery 分区将会被 keystore 验证 (从 LK 里面的 OEM keystore开始)。
- 唯一能使用的 fastboot 命令只有 fastboot oem unlock,但如果要使用该命令,还必须在开发者选项中将 OEM unlock打开(默认关闭)。
verified state:
- 用户可以使用 fastboot 命令来下载或者擦除特定的分区(bootable/bootloader/lk/app/aboot/aboot.c中的 critical_flash_allowed_ptn 结构体)。
- 不允许登记 keystore或者篡改 persisten data block。
- 对于使用用户或者第三方软件来来,这是个比较合适的状态,特别是开发者需要频繁地烧写软件。
- 如果使用了没有被OEM签名的 keystore,那需要处理开机时的警告信息。
unlock state:
- 所有的 fastboot 命令都可以使用。
- 用户 keystore 可以被登记或者擦除。
- 在这种状态下,boot和recovery不会被验证。同时开机时会有警告,需要按音量上键才能继续启动。
影响
- 软件集成和 OTA 升级,必须使用 block 方式做包和升级,相关工程师需要注意在适配。
- 售后,用户自行刷三方固件以及 root 检测等。
- 开机速度和 performance, Idol 4S 上实测,从校验开始到 system 分区挂载完成耗时 50 ms 以内,对开机 速度的影响可以忽略,当前没有任何证据表明会影响 performance。
- 工程师日常开发调试。
注意事项
- 该功能在 eng 软件上是关闭的,刷 eng 的 boot.img 不会受影响。
- 混刷 boot.img 和 system.img 会启动不了,使能后的 userdebug 或 user 版本的 boot.img 搭配的 eng 版本的 system.img 或者未使能前的 system.img 会开不起来,因为生成时用的 key 不同。
- 可以通过开机后查看 system 分区的挂载信息来查看是否开启了 Verified Boot 功能:
adb shell mount | grep /system
开启显示
/dev/block/dm-0 /system ext4 ro,seclabel,relatime,discard,data=ordered 0 0
关闭显示
/dev/block/bootdevice/by-name/system /system ext4 ro,seclabel,relatime,discard,data=ordered 0 0
- 通常会使用 userdebug 软件(或者刷 userdebug 版本的 boot.img) 来调试,但使能后,system 是无法挂载成 rw 状态的,不能 push
$ adb root
Restarting adbd as root
$ adb remount
Reremount succeeded
$ adb shell mount | grep /systtem
/dev/block/dm-0 /system ext4 ro,seclabel,relatime,discard,data=ordered 0 0
$ adb push out/target/product/project_name/system/xbin/su /system/xbin/su
failed to copy 'out/target/product/project_name/system/xbin/su' to '/system/xbin/su': Read-only file system
- 在 userdebug 软件(或者刷 userdebug 版本的 boot.img)有两种方法可以关闭:
- 用 adb 命令,重启后生效:
$ adb disable-verity
$ adb enable-verity
注意,如果重新刷 了 system.img 就要重新操作,因为关闭标志是写在 system.img 尾部的。当启用boot verity功能,一旦你修改了手机里的 system 分区,比如 push 进去一个 apk,再打开的话,手机会起不来。
2. 替换 eng.img ,也可以修改 fstab.qcom 文件,重新编译 userdebug 的 boot.img:
具体操作是修改 device/OEM/project_name/fstab.qcom文件,去掉 verify 标志,例如:
/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1,discard wait,verify
/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1,discard wait
user 软件没有办法,如果需要修改 system, 请刷 userdebug 或者 eng 的 boot.img。
旧版的 adb 可能不支持 disable-verity 和 enable-verity 命令,请更新到最新的 Android SDK,或者使用工程编译出来的 adb (out/host/linux-x86/bin/adb)。
Verified Boot相关推荐
- Magisk root 原理分析之二 :Android Verified Boot (AVB)
1. Android Verified Boot (AVB) 或称 Verified Boot 2.0 简介 官方解释:验证用户设备上运行的软件完整性.它通常从设备固件的只读部分开始,该部分加载代码并 ...
- Android Verified Boot 2.0 最新安卓P AVB详解
什么是AVB 验证启动是确保用户设备运行软件完整性的一整套流程. 它通常从设备固件的只读部分启动,使用加密方式验证代码是可靠且没有任何已知的安全缺陷之后才会执行. AVB是验证启动的一种实现. VBM ...
- AVB校验微观版本:android avb(Android Verified Boot)验证
前辈原文:https://blog.csdn.net/weixin_43836778/article/details/90400147 其实可能有人会说,怎么整这么多重复的,其实不是的.这是为了不断地 ...
- Android安全启动学习(五):Android Verified Boot 2.0
1.AVB概要 AVB2.0被用于启动引导,此用法添加一个"vbmeta.img"镜像. public key被编译到bootloader中用于校验vbmeta数据,vbmeta. ...
- Android Verified Boot dm-verity 优化和实战
目录 一.AVB 技术背景 二.代码实现逻辑 一.AVB 技术背景 Android O/P 版本以来,谷歌加入了system-as-root的特性,此时ramdisk和system是一起放在同一个sy ...
- ro.boot.verifiedbootstate 为 orange
问题现象 adb shell getprop ro.boot.verifiedbootstate 返回值为 orange 期望返回值为green 与测试沟通后,得到的反馈是测试用例中要求的检查项. 问 ...
- 高通8155/8295 boot分析
目录 前言 通用boot流程 8155/8295 boot流程概述 前言 本文将基于高通8155/8295 Q+A hypervisor平台分析整个boot的启动流程.高通其他SOC芯片的启动流程大致 ...
- Android 8.1 源码_启动篇(一) -- 深入研究 init(转 Android 9.0 分析)
前言 init进程,它是一个由内核启动的用户级进程,当Linux内核启动之后,运行的第一个进程是init,这个进程是一个守护进程,确切的说,它是Linux系统中用户控件的第一个进程,所以它的进程号是1 ...
- Image打包流程-Android10.0编译系统(四)
摘要:本节主要来进行Android10.0 Image打包流程,理解system.img是如何打包的 阅读本文大约需要花费28分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源 ...
- 深入浅出Android系统启动流程
转载请标明出处:[顾林海的博客] 本篇文章已授权微信公众号 顾林海 独家发布 init进程启动过程 init进程概述 Android系统基于Linux,init进程是Android系统中用户空间的第一 ...
最新文章
- 聊聊动画引擎 pop
- VMware View把iPad从娱乐工具变成强大办公平台
- ABP理论学习之工作单元(Unit of Work)
- 蓝桥杯-删除数组零元素(java)
- Python 常见优化技巧,让你的程序溜溜的跑起来!
- 1276A. As Simple as One and Two
- 使用Addressable更好的管理内存
- json and .net
- 骨牌铺方格的3种做法
- C语言程序设计(2020)编程题答案——第14章结构体、共用体和用户定义类型
- Oracle Clob大于4000字节报错,那是你不懂Clob,XML类型的Clob在过程中就是取不到,我帮你
- 软件测试面试注意事项汇总
- 手机、浏览器的分辨率、状态栏参数
- 三层交换机与单臂路由的优缺点
- 详解Unity中的粒子系统Particle System (十二 | 终)
- AppleID的双重认证
- SSH常见问题及其解决方法
- android逆向开发工程师需要掌握的技能--实习一个月总结报告
- c语言变量周围堆栈损坏csdn,围绕变量“输入”的堆栈已损坏(Stack around the variable 'input' was corrupted)...
- 「只推荐一位」一个全是Python干货的公众号
热门文章
- Winxp U盘无法复制磁盘写保护解决办法。
- MySQL45讲 读书笔记 22讲MySQL有哪些“饮鸩止渴”提高性能的方法
- [数据可视化] 折线图(Line Chart)
- git 工作区、暂存区、版本库(本地)、远程版本库区别
- docker-compose配置固定网段Pool overlaps with other one on this address space
- 痛并快乐着,我的程序世界
- Kotlin:Outdated Kotlin Runtime问题修复
- 2019清明期间qbxt培训qwq
- 步骤教学 :安装下载Oracle VM VirtualBox + 安装win7 win10镜像文件
- Android 常用控件详解