Android 系统之安全KEY的哪些事儿

目录

一、APK应用签名

1、什么是APK应用签名?

1.1 目的和作用?

1.2 长什么样子?

2、APK应用签名使用流程

步骤一:如何生成APK应用签名文件?

步骤二:如何集成APK应用签名文件?

步骤三:如何使用APK应用签名文件?

3、相关案例

案例一:因为APK应用签名不匹配,导致OTA无法正常升级

案例二:因为APK应用签名为系统默认,导致CtsSecurityTestCases

案例三:因为APK应用签名为系统默认,导致GtsAppBlacklistDeviceTestCases

二、Android安全架构

1、什么是Android安全架构?

1.1 KeyStore的发展历史

1.2 为什么要密钥认证?

2、KeyStore架构

3、Google KEY

3.1 什么是Google KEY?

3.1.1 Google Keybox

3.1.2 Google Attestation Keybox

3.1.3 与TEE的关系

3.2 Google KEY使用流程

步骤一:Google KEY的申请

步骤二:Google KEY的切割

步骤三:Google KEY的写入

重点说明:Google KEY是否必须要写入?

4、Widevine KEY

4.1 什么是Widevine KEY?

4.1.1 Widevine相关支持

4.1.2 与TEE的关系?

4.4 Widevine KEY使用流程

4.4.1 Widevine 代码集成

4.4.2 Widevine KEY的写入

4.4.3 Widevine KEY的查询

5、相关案例

案例一:Google KEY缺少导致VtsHalKeymasterV4_0TargetTest

案例二:Widevine Version过低导致WvtsDeviceTestCases

案例二:keystore数据库被损坏,导致所有应用无法打开

三、Secure Boot

1、什么是Secure Boot?

1.1 Secure Boot有什么用?

1.2 Secure Boot如何运作?

1.3 Secure Boot概念总结

2、Secure Boot使用流程

2.1 生成产商自己的KEY

2.2 对镜像进行签名

2.2.1 高通镜像签名脚本

2.2.2 MTK镜像签名脚本

2.2.3 镜像签名前后差异

2.3 对设备进行熔断

2.3.1 高通设备的熔断

2.3.2 MTK设备的熔断

2.3.3 设备是否熔断?

方法一:xbl的日志查看

方法二:fastboot模式查看sercure boot

3、 相关案例

案例一:熔断后刷入签名的镜像设备进入了fastboot模式

案例二:非熔断的设备刷入sec.dat之后IMEI号丢失


Android中涉及到KEY和秘钥相关的地方有好几处,而且还比较容易混淆。这里记录一下我们常用的一些KEY以及他们的目的和作用。

一、APK应用签名

1、什么是APK应用签名?

他是google的一套原生机制,google官方对其详细说明了一下:https://source.android.com/docs/core/ota/sign_builds?hl=zh-cn

1.1 目的和作用?

  • 为什么要针对apk包进行签名?同google官方网站的描述,如果你更新apk的时候,系统会检测你的apk的签名秘钥是否和系统指定的签名秘钥匹配,如果不匹配,系统将会拒绝安装改应用,这样能够保证被更新的应用是没有掉过包的。
  • 为什么要针对ota包进行签名?同前面提到的apk应用一样,OTA包其实也可以简单的理解为一个大型apk,我们在安装OTA包之前需要对其进行校验(通过RecoverySystem.verifyPackage()),如果签名秘钥对不匹配,讲拒绝OTA升级,同样保证被更新的OTA是没有掉过包的。

1.2 长什么样子?

每个密钥都包含两个文件:一个是扩展名为 .x509.pem 的证书,另一个是扩展名为 .pk8 的私钥。 私钥需要加以保密,并用于对 apk 包进行签名。 密钥本身也可能受密码保护。相比之下,证书只包含公开的一半密钥,因此可以大范围地分发。证书用于验证某个 apk 包是否由相应的私钥进行签名。

标准 Android build 使用四个密钥,所有这些密钥都位于 build/target/product/security 中

  • testkey:适用于未另外指定密钥的 apk 包的通用默认密钥。
  • platform:适用于核心平台所包含的 apk 包的测试密钥。
  • shared:适用于家庭/联系人进程中的共享内容的测试密钥。
  • media:适用于媒体/下载系统所包含的 apk 包的测试密钥。
  • networkstack:适用于网络系统所包含的 apk 包的测试密钥

2、APK应用签名使用流程

步骤一:如何生成APK应用签名文件?

在android根目录/build/target/product/security/有详细说明如何生成秘钥对,其中

在项目开发过程中,我们通常需要更换上面的秘钥对,使用客户提供或者我们自己的秘钥对,生成方式如上。

步骤二:如何集成APK应用签名文件?

我们可以通过宏变量PRODUCT_DEFAULT_DEV_CERTIFICATE来指定如上步骤生成的签名文件的路径。如ChatGPT的回答:

步骤三:如何使用APK应用签名文件?

  • Android编译构建的时候引入KEY

  • 应用集成的时候指定使用的KEY
include $(CLEAR_VARS)
LOCAL_MODULE := AOSPLauncherR
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_MODULE_CLASS := APPS
LOCAL_CERTIFICATE := platform   //指定平台签名
LOCAL_PRIVILEGED_MODULE := true
LOCAL_REQUIRED_MODULES := privapp_permissions_AOSPLauncherR.xml
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 \
    Launcher3QuickStep Launcher3Go Launcher3QuickStepGo \
    MtkLauncher3 MtkLauncher3QuickStep MtkLauncher3Go MtkLauncher3QuickStepGo MtkLauncher3GoIconRecents
include $(BUILD_PREBUILT)
include $(CLEAR_VARS)
LOCAL_MODULE := privapp_permissions_AOSPLauncherR.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_PRODUCT_MODULE := true
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)

这里集成的AOSPLauncherR因为是平台的应用,LOCAL_CERTIFICATE = platform,因此编译构建的时候针对AOSPLancherR应用会使用步骤一中指定的plat签名文件进行签名

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := MobileFeliCaSettingApp
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
LOCAL_MODULE_PATH := $(TARGET_OUT_APPS)
# indicate to generate .odex file in special built/core/prebuilt.mk
LOCAL_DEX_PREOPT:=true
include $(BUILD_PREBUILT)

这里集成的MobileXXX应用是三方应用,使用LOCAL_CERTIFICATE := PRESIGNED,因此编译构建的时候使用的是testKey?

3、相关案例

案例一:因为APK应用签名为系统默认,导致XTS问题

CtsSecurityTestCases

如上报错日志表示一堆应用使用了android默认的应用签名,解决方案就是生成新的应用签名文件

GtsAppBlacklistDeviceTestCases

如上报错日志表示一堆应用使用了android默认的应用签名,解决方案就是生成新的应用签名文件

GtsMbaPrivilegedPermissionTestCases 

testPackageSignatures和testForBlacklistedApps和testMbaPrivilegedPermission 这样的测试用例是针对APK应用签名的校验,即编译的时候需要对所有应用或者OTA包进行应用签名,使用默认android的签名就会被检查出来,解决方案就是更新自己的应用签名

BTS which has been signed by a certificate that is known to be compromised and should be replaced

是针对系统应用签名的一个检测,即编译的时候需要对所有应用或者OTA包进行应用签名,使用默认android的签名就会被检查出来,解决方案就是更新自己的应用签名

案例二:因为APK应用签名不匹配,导致OTA无法正常升级

二、Android安全架构

1、什么是Android安全架构?

Android的密钥库已经有很多年了,它为应用程序开发者提供了一种使用加密密钥进行验证和加密的方法。 Keystore将密钥保留在应用程序的进程空间之外,以便应用程序不会无意中将其泄露给可能被钓鱼的用户,通过其他渠道泄漏,或者在应用程序遭到破坏时。 许多设备还为安全硬件中的密钥库密钥提供了基于硬件的安全性,从而将密钥材料完全保留在Android系统之外,从而即使Linux内核泄露也不会泄露密钥材料。 在绝大多数Android设备中,安全硬件是主CPU的特殊模式,硬件强制与Linux内核和Android用户空间隔离。比如基于Arm的TrustZone技术实现的TEE安全操作系统, 或者,某些设备使用单独的安全微处理器。比如SE芯片

Android提供的API允许应用程序确定给定的密钥库密钥是否在安全硬件中,但是如果操作系统受到威胁,这些API可能不可靠。

1.1 KeyStore的发展历史

Keystore最初是在Android 4.0中引入的,而且密钥是用用户的密码加密的。 在Android 4.1中增加了使用设备安全硬件的基础设施。

直到Android 6.0,Keystore支持RSA和ECDSA。 在Android 6.0中,Keystore得到了显着增强,增加了对AES和HMAC的支持。 此外,加密操作的其他关键要素(如RSA填充1和AES块链接2模式)也被转移到安全的硬件中。

在Android 6.0中,Keystore也获得了限制特定密钥的使用方式的能力。 可以应用的最明显有用的限制是用户身份验证绑定。 这允许密钥的使用被“绑定”到用户的密码 - 它们的PIN,图案或密码 - 或指纹。 对于密码认证绑定,应用程序开发人员可以在几秒钟内指定超时。 如果用户上次输入的密码超过了指定的时间,安全硬件将拒绝任何使用该密钥的请求。 每次使用密钥时,指纹绑定密钥都需要新的用户身份验证。

其他更技术性的限制也可以应用于Android 6.0及更高版本。 特别是在密钥创建或导入时,有必要指定可以使用密钥的加密目的(加密,解密,签名或验证)以及填充和块模式,摘要,熵源 用于初始化向量或随机数,以及密码操作的其他细节。 由于指定的信息是永久性的,并且密码上与密钥材料绑定,所以密钥库不允许以任何其他方式使用密钥。 因此,获得应用程序或系统控制权的攻击者不能误用密钥。 为了帮助防止攻击,开发人员应该为给定的密钥指定可能的最窄范围。

Android密钥库最重要的变化之一是在Android 7.0中引入的。 使用安全锁屏启动Android 7.0+的新设备必须具有安全的硬件,并支持基于硬件的密码验证和密钥库密钥。 在Android 7.0之前,安全的硬件支持非常普遍,但是在未来的几年里,它将会变得普遍。

在Android 8.0中,所有安装了Google Play的新设备都必须提供关键证明。

1.2 为什么要密钥认证?

简单来说,Google的keystore机制提供了一套密钥管理机制,应用越来多,越来越重要了,但是密钥认证问题如果不解决,这一切都是不可靠的!

  • keymaster HAL可以是假的,你没办法判断系统HAL以下是否真实,简单来说,如果没有使用TEE,你也可以通过keymaster HAL欺骗Framwork层。
  • 即使设备是正常的,应用也可以欺骗第三方。

假设您正在开发一个应用程序,为银行的客户提供银行余额,交易历史记录和账单支付系统。 安全是重要的。 您不希望任何拿起用户手机的人访问他们的银行帐户。 一种方法是使用用户的网站密码。 但是这对用户来说通常是不方便的,因为网站经常需要长而复杂的密码,这在小的触摸屏上是不方便的。

使用Android Keystore,可以生成非对称身份验证密钥,例如256位ECDSA密钥,并让每个用户使用其复杂的Web密码登录一次,然后在银行的客户帐户数据库中注册公钥。 每次打开应用程序时,您都可以使用该ECDSA密钥执行质询 - 响应身份验证协议。 此外,如果您将密钥认证绑定,则用户每次打开应用程序时都可以使用其锁屏密码或指纹进行身份验证。 这使得他们可以在手机上使用更简单,更方便的认证机制。

如果攻击者危及Android并尝试提取密钥,则他们不会成功,因为密钥在安全硬件中。

作为应用程序开发人员,密钥认证允许您在服务器上验证您的应用程序所请求的ECDSA密钥实际上是否安全地存在于硬件中。 请注意,在您的应用程序本身中使用证明是没有意义的。 如果Android操作系统是不妥协和可信的,那么您可以使用6.0中引入的KeyInfo类来发现密钥是否在安全硬件中。 如果它被攻破,那么这个API和你在设备上验证证明的任何尝试都是不可靠的。

请注意,密钥证明不同于SafetyNet认证。 他们是相同的概念,但是证明不同的事物来自不同的地方。 密钥库密钥证明确认密钥存在于安全的硬件中并具有特定的特征。 SafetyNet认证确认设备是真实的(不是仿真器),并且运行已知的软件。 SafetyNet使用Keystore密钥证明,所以如果你想了解设备的完整性使用。 如果您想确认您的密钥是否在安全硬件中,请使用密钥认证。

2、KeyStore架构

当前比较新的Android 例如S的系统默认使用了keymaster的机制,如下图,Android系统中的应用进程加解密的逻辑处理,通过binder方式和HAL接口在TEE这个安全环境下(独立于linux/android系统的上下文,这个下节将会提到)执行。

KeyStore的源码解读参考专栏:keystore/keystore2/keymaster/keymint 深入学习-CSDN博客

这里我简单的总结一下:

  • TEE:TEE是独立于Android和Linux内核的一套系统,他和Linux内核一样,由bootloader启动。他给整个设备提供了一套安全的环境,这里说的安全并不仅仅指软件,还特别包含加密硬件的相关支撑。即高通芯片/MTK芯片他们需要提供这样的硬件加密能力,TEE就是一套闭源的安全系统,他可以使用调用芯片的这些硬件加密能力。当然他们之间可能存在一些接口或者协议,就跟ARM架构和Linux系统之间一样。重点:TEE是提供安全的软硬件系统,站在软件的角度上他和Linux内核是同一级别的
  • KeymasterHAL:这里说的KeymasterHAL是运行在Android世界里面,它跟普通的硬件抽象层HAL服务没有本质的区别,唯一的区别就是他可以通过Linux内核去和TEE进行数据通信。
  • KeyStoreService:它被init进程启动,即和其他native进程也没有本质的区别,但是他维护了一个秘钥相关的复杂数据库,同事完成了一些加密,解密,秘钥查询等事情。例如指纹锁/图案锁等涉及到的秘钥的一些信息数据被存储在这个数据库里面,这些操作都需要通过KeymasterHAL去和TEE进行交互,实际操作的地方还是在TEE空间里面。
  • KeyStore:作为KeyStoreService为framework层提供的客户端,即上层应用可以通过KeyStore来调用native层的keystoreservice
  • Application:需要使用秘钥相关的应用,常见的有锁屏应用、生物锁、银行金融APP等

3、Google KEY

3.1 什么是Google KEY?

参考Google Keybox功能与TEE关系介绍 Google attenstation keybox CTS认证 KEYBOX-CSDN博客

3.1.1 Google Keybox

Google Keybox 是一项由谷歌提供的安全功能,主要用于保护加密密钥和其他敏感数据。Keybox 通常与可信执行环境(TEE, Trusted Execution Environment)紧密结合,以增强其安全性。主要如下功能:

  • 密钥管理:Keybox 主要用于安全地存储和管理加密密钥。这些密钥可以用于加密数据、保护用户凭证和其他敏感信息。
  • 密钥保护:通过硬件级别的保护,Keybox 能确保密钥在使用过程中不会被暴露。它利用硬件安全模块(HSM, Hardware Security Module)或可信执行环境来实现这一点。
  • 加密操作:Keybox 支持各种加密操作,如加密、解密、签名和验证。这些操作在硬件安全模块内执行,以防止密钥泄露。
  • 设备认证:Keybox 还用于设备认证,确保只有经过认证的设备才能访问特定服务或数据。它可以存储设备唯一标识符(如设备 ID)和相关的认证密钥。

我们常见的使用场景如下:

  • Android 安全性:在 Android 设备上,Keybox 与 TEE 紧密结合。Android 使用 TrustZone 作为 TEE,确保关键加密操作和密钥存储在安全的环境中进行。
  • 设备认证与 DRM:Keybox 和 TEE 常用于设备认证和数字版权管理(DRM)。例如,流媒体服务会利用这些技术确保内容只能在认证过的设备上播放,防止盗版和未授权访问。
3.1.2 Google Attestation Keybox

Google Attestation Keybox 是一种安全机制,旨在验证设备的身份和完整性。这种机制依赖于设备内的硬件安全模块和可信执行环境(TEE),以确保设备在执行敏感操作时的可信度。其功能如下:

  • 设备认证:Attestation Keybox 用于生成和存储设备唯一的认证密钥。这些密钥在设备与服务器通信时用于证明设备的真实性。
  • 安全密钥存储:利用硬件安全模块和 TEE,Attestation Keybox 确保认证密钥存储在高度安全的环境中,不易受到恶意攻击或篡改。
  • 远程证明:设备可以通过 Attestation Keybox 生成证明其身份和状态的证书。服务器可以验证这些证书,以确保设备没有被篡改并且是可信的。
  • 数据完整性验证:通过生成和验证数字签名,Attestation Keybox 确保设备传输的数据没有被篡改,保障数据的完整性。

我们常见的使用场景如下:

  • 设备初始化:在首次配置或重置设备时,Attestation Keybox 通过认证流程确保设备是合法的。
  • 应用验证:一些应用程序在安装或运行时会使用设备证明来确保其运行环境安全。
  • 安全更新:在软件更新过程中,利用设备证明来确保更新包是从可信源下载的,并且在更新过程中没有被篡改。
3.1.3 与TEE的关系

因为TEE 提供了一个安全隔离的环境(密钥在存储和使用过程中能得到有效保护,不易受到外部攻击),所以google keybox的存储和保护以及google attestation keybox的所有关键操作(如秘钥生成/签名等)都需要依赖TEE,即这些操作和实现都经过keysotre服务,在TEE中完成的。

3.2 Google KEY使用流程

步骤一:Google KEY的申请
  • 每个device单独申请keybox(attestation key),首先需要去跑CTS白名单
  • 根据CTS白名单的报告提交到google官方网站进行keybox申请
步骤二:Google KEY的切割
  • google审核通过之后会返回一个keybox,为了工厂生产的需要,我们需要对其进行切割
步骤三:Google KEY的写入
  • 切割之后的key,需要通过工具写入到android设备里面,通常进入meta模式来进行写key
步骤四:Google KEY查询是否写入
  • 成功写入后/mnt/vendor/persist/attest_keybox.so是否存在
  • adb shell getprop |grep “googlekey”或者进入工模模式是否有android key:OK
重点说明:Google KEY是否必须要写入?

google key可以不写入,通常我们在调试开发中很少写这个东西,不影响我们的基本功能使用。但是正常出货的设备或者需要做XTS的设备需要写google key,因为他会导致一些功能无法使用。

4、Widevine KEY

4.1 什么是Widevine KEY?

Android Widevine 自 Honey Comb ( 对手机是Ice Cream Sandwitch 4.0) 推出后成为CTS强制测试选项,厂商必须支持。无论是网络传输或者是消费类电子设备,Widevine针对数字媒体提供了视频格式无关的加解密方式。截止2012年,已经有5.39亿台设备支持 Android Widevine,截止2012年, Widevine 推行无软件授权费的发行方式。

Widevine是Google的数字版权管理(DRM)平台,用于保护流媒体服务的内容,防止盗版。它通过CENC加密、许可密钥交换和自适应流媒体质量管理视频,支持L3、L2和L1三个安全级别,其中L1适用于高清和HDR内容。Android和Chrome OS设备支持不同级别的Widevine,L1需要硬件的可信执行环境(TEE)以确保安全性。要流式传输高清内容,用户设备需通过Widevine L1认证。检查设备兼容性可使用DRM Info等应用或参考Netflix的设备列表。

详情参考:什么是 Widevine 数字版权管理 (DRM),它为什么重要-CSDN博客

4.1.1 Widevine相关支持

主要支持平台

  • Smart Phone
  • STB
  • Blue Ray player
  • Cloud TV
  • Game console.  ( Sony PS3, Nintendo Wii )
  • Desktop ( Windows, Mac)

Widevine Security Level

  • Level 1     Strictest  Mandatory factory provision
  • Level 2     Intermediate requirements
  • Level 3  Field Provision

Android Widevine DRM Framework

  • 自Honey Comb版本开始引入Android
  • 受保护的音视频媒体播放
  • 框架配置需要和DRM机制协同
  • 利用插件体系结构,设备制造商可灵活配置以支持多DRM代理和机制
  • 数字内容存储需要完成Widevine DRM软件集成
  • 支持Widevine DRM 的Honey Comb版本最早发布于2011 Q2 
4.1.2 与TEE的关系?

Widevine 是如何实现的Android设备支持L1或L3安全级别,具体取决于硬件和软件a实现,ChromeE OS也是如此。台式机上的Chrome最多只能支持L3,如果您的设备仅符合 L3 标准,则您的分辨率上限为 sub-HD。只有完全在TEE中进行处理的L1 安全设备才能播放来自Widevine安全服务的高清或更高质量的内容。关于Widevine最需要注意的一点可能是它不收取许可费以实施其保护技术。因此一些智能手机的缺失没有经济上的原因。

即Widevine KEY同Google KEY一样,需要依赖于TEE的环境。
 

4.4 Widevine KEY使用流程

4.4.1 Widevine 代码集成

Widevine的源代码需要从官方网站去下载,然后集成到我们的项目中,如下为其中一个高通项目集成的代码目录。

Android.mk配置如下,从中可知我们如果需要使用只需要讲android.hardware.drm的几个包集成到系统里面就可以了

Widevine的版本更新也比较简单,直接从官方网站下载最新的包,全部替换上面目录即可。替换完成之后需要使用Netflix APP验证一下能否正常播放即可(因为Netflix里面的视频都是数字版权的视频)。

4.4.2 Widevine KEY的写入

同google key的写入一致?

4.4.3 Widevine KEY的查询

可以通过一个apk来进行查询:drminfo_v1.1.8.210515_itmop.com.apk,此apk打开之后会获取相关信息,信息如下:

5、相关案例

案例一:Google KEY缺少导致一系列XTS问题

CtsKeystoreTestCases模块如下用例

android.keystore.cts.KeyAttestationTest#testRsaAttestation

android.keystore.cts.KeyAttestationTest#testEcAttestation

android.keystore.cts.KeyAttestationTest#testEcAttestation_UniqueIdWorksWithCorrectPermission

android.keystore.cts.KeyAttestationTest#testEcAttestation_DeviceLocked

android.keystore.cts.KeyAttestationTest#testRsaAttestation_DeviceLocked

GtsGmscoreHostTestCases模块如下用例

com.google.android.gts.security.AttestationRootHostTest#testRsaAttestationChainTee

com.google.android.gts.security.AttestationRootHostTest#testEcAttestationChainTee

VtsHalKeymasterV4_0TargetTest模块如下用例

PerInstance/AttestationTest#RsaAttestation/0_default

PerInstance/AttestationTest#EcAttestation/0_default

odsign_e2e_tests模块如下用例

com.android.tests.odsign.OnDeviceSigningHostTest#verifyArtUpgradeGeneratesAnyArtifacts

com.android.tests.odsign.OnDeviceSigningHostTest#verifyArtUpgradeSignsFiles

写google key能够pass

案例二:CtsIdentityTestCases

04-03 13:50:53.478 10218 12577 12589 E TestRunner: failed: dynamicAuthTest(android.security.identity.cts.DynamicAuthTest)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: ----- begin exception -----
04-03 13:50:53.478 10218 12577 12589 E TestRunner: java.lang.RuntimeException: Unexpected ServiceSpecificException with code 1
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.security.identity.CredstoreIdentityCredentialStore.createCredential(CredstoreIdentityCredentialStore.java:135)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.security.identity.cts.ProvisioningTest.createCredentialWithChallengeAndAcpId(ProvisioningTest.java:142)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.security.identity.cts.ProvisioningTest.createCredential(ProvisioningTest.java:121)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.security.identity.cts.DynamicAuthTest.dynamicAuthTest(DynamicAuthTest.java:76)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at java.lang.reflect.Method.invoke(Native Method)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:61)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:148)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at org.junit.internal.runners.statements.FailOnTimeout$CallableStatement.call(FailOnTimeout.java:142)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at java.util.concurrent.FutureTask.run(FutureTask.java:264)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at java.lang.Thread.run(Thread.java:1012)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: Caused by: android.os.ServiceSpecificException: HAL failed with exception code -8 (EX_SERVICE_SPECIFIC), service-specific error code 1, message 'Error initializing WritableIdentityCredential' (code 1)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.os.Parcel.createExceptionOrNull(Parcel.java:3093)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.os.Parcel.createException(Parcel.java:3063)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.os.Parcel.readException(Parcel.java:3046)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.os.Parcel.readException(Parcel.java:2988)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.security.identity.ICredentialStore$Stub$Proxy.createCredential(ICredentialStore.java:197)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: at android.security.identity.CredstoreIdentityCredentialStore.createCredential(CredstoreIdentityCredentialStore.java:125)
04-03 13:50:53.478 10218 12577 12589 E TestRunner: ... 12 more

此案例比较奇怪,我司内部版本在没有写google key的时候,单跑第一条报如上错误,从报错日志来看android.hardware.identity硬件抽象层服务存在问题,在写入了google key之后,此条能够PASS;但是在客户版本写了google key之后,还是出现一模一样的错误,就跟google key没有写一样。

初步分析同样环境排除google环境问题,剩下只有两种可能情况:google key秘钥不匹配;代码引入需要夹版本。最后确定为代码引入,客户注释了android.hardware.identity上层服务,但是没有注释hal层的声明。跟踪identity模块源码如下:

此问题原因没有搞清楚,但是可以大胆猜测,identity服务是针对身份等相关信息秘钥的认证,其依赖keystore<->tee架构,另外此服务放在google目录,因此需要通过google key来进行相关秘钥校验,因此在此案例中写了google key之后,因为上层服务被干掉,CtsIdentityTestCases针对identity服务的测试,identity服务无法正常实现功能,因此失败。

案例三:Widevine Version过低导致WvtsDeviceTestCases

因为widevine version过低,需要更新Widevine的版本(注意需要clean编译),更新之后的版本记录如下:

案例四:keystore数据库被损坏,导致所有应用无法打开

因为keystore数据库被损坏,导致使用了加密手机,即使输入正确的密码, 进入系统之后也无法正常解密文件系统,导致三方应用数据库无法加载,无法启动成功。后使用了keystore数据库备份方案:省略

 案例五:因为KM版本太老导致odsign校验耗时开机时长超过100S

问题描述:格式化刷机第一次开机时长耗时110秒,第二次开机时长80秒,第三次开机时长100秒,第四次开机时长80秒,第五次开机时长100秒

日志分析:抓取开机日志发现奇数次和偶数次日志不一样,存在odsign去创建秘钥,验证秘钥失败删除秘钥,然后apex进行校验等。最后开机时长变长原因为init进程在等待odsign进行校验

问题分析:odsign为keysotre2里面的一个实例对象,因此验证了google key相关的, 最后发现和google key并没有什么关联,咨询google,google回复这里校验的key并不是google key,而是odsign自己的key,如下回复:

如上沟通记录最终和TEE供应商确定为我们的KM4.0不支持MAX_USES_PER_BOOT,KM4.1支持

解决方案:升级KM4.0到KM4.1,因为其源码在MTK基线都存在,因此做如下修改即可,开机时长恢复为40秒

device/mediateksample/$(ProjectName)/ProjectConfig.mk
KEYMASTER_VERSION = 4.1

三、Secure Boot

前文讲解的Keystore和应用签名都是google原有的安全机制,属于Android系统的强制要求,Google的XTS测试也会对其进行检测和验证。这里讲解的Secure Boot确实芯片厂商自己设计定义的功能,因此不属于Android系统强制要求,XTS也不会针对这些进行测试,然而基本所有的厂商在生产的时候都会做Secure Boot。这里根据安全模块的同事对secure boot文档简单总结一下。

1、什么是Secure Boot?

Secure Boot从字面上面来讲,是安全启动,就是为了保证设备里刷入的镜像是安全的,这里
安全的意思是,这些刷入的镜像是由厂商编译生成的,而不是刷入的别的厂商或者恶意破坏后
的镜像。

1.1 Secure Boot有什么用?

上面已经提到了,secure boot 特性是,保证安全启动,保证刷入设备的镜像,是厂商自己生成
的。避免设备遭受攻击。这里列举几个可能遭受攻击的场景:

  • 由其他厂商生成镜像来获取一些信息:高通的代码会给到不同的厂商,如果没有 secure boot,A 、B 厂商都有相同的代码,假如A 厂商要攻击 B 厂商的设备,A 厂商可以自己编译镜像,刷入到 B 厂商的设备,从而绕过 B 厂商自己代码中的一些限制。
  • 由其他厂商生成镜像来获取敏感信息:我们知道,有些支付信息什么的,都是在安全世界运行,如果没有 secure boot,可以在TEE 或者 TA 中添加恶意代码,编译镜像,刷入设备,就可以很轻松的获取到一些用户的敏感信息。
  • 获取其他信息:secure boot 不仅能够保证安全启动,还可以关闭一些调试通道,如:自动给 fastboot 上锁、关闭 JTAG 调试等,万一厂商在出厂的时候,因为某些疏忽,有些信息没有去掉,黑客在拿到设备的时候,可以通过这些漏洞获取一些敏感数据,如果开启了 secure boot,那么就可以关闭这些信息。(如:TEE log,dump 信息等)

从上面看,开启 secure boot 是每个出厂设备的必须要做的,还有就是要保护好自己的私钥。

1.2 Secure Boot如何运作?

高通芯片内部有一段固化的程序,我们称为 PBL(Primary Boot Loader),同时内部有一个
硬件模块,我们称为 eFuse。eFuse 在熔断的时候,会存储一些验证信息,如:root key 证书的
hash 值。在启动的时候,PBL 会根据 eFuse 的状态(熔断?还是非熔断?)来对后面的要加
载的镜像进行校验。只有校验通过的镜像才会加载。这样只有正确签名的镜像才会被加载运行
,从而实现了安全启动。
注意:这里 PBL 的代码,我们是看不到的,上面的回答,只是根据经验而得,比如:efuse 里面烧录了什么信息?这部分我暂无法知道怎么去查看。

root key证书的hash值安全,就可以判断root key证书是否可信。(root key证书的hash值在熔断的时候,就写死在efuse中,是必然安全)

root key 证书可信,就可以判断ca key证书是否可信。ca key证书可信,就可以判断镜像是否可信。

1.3 Secure Boot概念总结

  • Secure boot主要是保证BP 侧镜像,在加载kernel 之前的镜像的安全,防止刷入设备的镜像,不是由厂商自己编译生成,使设备遭受到恶意攻击。
  • Secure boot是高通这样的厂商的一个特性,在芯片内部是有一个硬件单元的,只能一次烧录,是不可逆的,烧录的东西和root key密切相关,efuse被熔断了,那么root key就不能改变,同时这块芯片只能运行和root key相关的key签名的镜像。
  • Secure boot这个模块的工作,我们只需要生成相关的key,然后生成熔断的文件(包含了root key 的hash信息),签名镜像,知道如何debug 就行,其他里面的运行机理高通已经实现,对我们来说也是黑盒子,不必深究。
  • EFUS是高通/MTK等CPU芯片内部的一小段存储器件,这段器件只允许写入一次,即写入了之后就不允许在写入其他数据,哪怕是拆掉芯片也不行。因为此特性,我们可以考虑用它来保存永久不会改变的东西,例如Secure Boot的秘钥信息。
  • 熔断

2、Secure Boot使用流程

上面说了那么多secure boot的好处,那么我们如何在设备上使能secure boot呢?其实,高通都实现了这个功能,默认使用的高通的秘钥,我们要做的就是替换成我们自己的秘钥信息而已。做之前,我们可以在高通/MTK的网站上搜索:Secure Boot Enablement,找到适合我们产品的平台,其实里面的步骤会指导我们如何去使能secure boot。

2.1 生成产商自己的KEY

这里不详细说明KEY的生成,通常只有安全模块的同事才会需要到,详情请参阅官方文档,

这一步的最后产物就是:生成了root key和证书、生产了CA key和证书、还要root key的hash值。

2.2 对镜像进行签名

通过第一步已经完成了我们的签名文件、key和证书、secimage.xml 文件,接下来就是把他们作为高通或者MTK的签名工具的输入,就可以得到我们需要的签名文件。

这个过程的实现,在版本编译构建的后面阶段,即就是我们通常所说的镜像签名。编译脚本在生成了各个img之后,通过调用高通或者MTK的签名脚本来对需要签名的img或者其他文件进行签名。因此这里说的镜像签名都属于各个平台自己的机制,和google没有任何关联。

2.2.1 高通镜像签名脚本
2.2.2 MTK镜像签名脚本
2.2.3 镜像签名前后差异

2.3 对设备进行熔断

对设备的熔断的概念就是第一章讲解的把签名key相关信息写入到efus存储里面,因为被写入后就不能在修改,因此它是不可逆的,通常成为硬件的熔断,所以需要慎重。

2.3.1 高通设备的熔断

高通设备只要将制作的sec.dat 文件刷入到sec分区,就实现了secure boot硬件上的熔断。这里只介绍一下sec.dat文件是怎么生成的。其实也是通过高通签名脚本,命令如下:

python sectools.py fuseblower -p <chipset_name> -g -d

-d is for debug information which generates file with fuse information in the <sectools>\fuseblower_output\v1\debug\secdat_repr.txt file.

-p is platform or chipset. The configuration files for platform are at <sectools>\config\

-g generates the SEC.DAT file

最后在工具的输出目录生产文件<sectools>\fuseblower_output\v2\sec.dat,这个文件就是我们配置后,编译的生成物,使用命令:hexdump -C sec.dat可看到内容如下:

可以从大概我圈起来的地方,看到root key的hash值。高通默认的sec.dat 是如下这样的:

sec.dat只是高通的工具生成的一个文件而已,要解析它,只要知道它的结构就行,我感觉没必要解析其结构,我们通过secdat_repr.txt 就可以知道,里面的详细配置。

但是网上确实有人分析了sectools这个工具,有兴趣的可以查看这个链接:独角兽暑期训练营系列 | 高通芯片安全相关熔丝设定及检测方法研究-安全KER - 安全资讯平台

最后的熔断,就是将sec.dat文件写到设备中:

Fastboot flash sec <sectools>\fuseblower_output\v2\sec.dat

During reboot, eFuses will be blown and RoT is configured to the device. The device will reboot again. After the reboot, secure boot is enabled to the device and will only run with signed and trusted software.

2.3.2 MTK设备的熔断
2.3.3 设备是否熔断?

上面我们已经将设备熔断了,那么我们如何查看呢?

方法一:xbl的日志查看

Format: Log Type - Time(microsec) - Message - Optional Info
Log Type: B - Since Boot(Power On Reset),  D - Delta,  S - Statistic
S - QC_IMAGE_VERSION_STRING=BOOT.BF.3.3.2-00078
S - IMAGE_VARIANT_STRING=PAASANAZA
S - OEM_IMAGE_VERSION_STRING=SHC0273
S - Secure Boot: On
S - JTAG ID @ 0x000a4120 = 0x90400106
S - Serial Number @ 0x000a4128 = 0xe8c134c3
S - Feature Config Row 0 @ 0x000a4160 = 0x3d018400d8800000
S - Feature Config Row 1 @ 0x000a4168 = 0x02c2f80004000005
S - Boot Config, 0x000000e1

这是sbl1 的日志,我们从日志上看到Secure Boot: On 代表设备已经熔断了,同时还能看到JTAG ID、Serial Number等信息。

方法二:fastboot模式查看sercure boot

3、 相关案例

案例一:熔断后刷入签名的镜像设备进入了fastboot模式

问题分析:如下过程

  • 获取串口日志,发现是avb 中,vbmeta.img 镜像校验不通过。
  • avb这边,我们没有配置,只是打开了开关,所有的设置都是默认的配置,同时avb和secure boot没有关系。
  • 结合代码,分析日志,vbmeta.img 校验不过会进入到fastboot模式,属于正常现象。
  • 综上,可能是我们刷入的vbmeta.img 确实可能被破坏了,我们需要重新编译。

解决方案:经过全部整体编译,然后进行签名,发现设备启动正常

案例二:非熔断的设备刷入sec.dat之后IMEI号丢失

  • IMEI 这个部分是和modem有关,也是和QCN相关,大概率在modem部分。
  • 非熔断的设备,刷入sec.dat后,就使能了secure boot,efs文件系统加密产生变化,所以会导致参数异常,熔断后需要重新校准
  • 生产时先全擦再刷入mini版本,将设备熔断;然后进行写号操作等;然后通过upgrade的方式升级到出货版本(user版本)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸神黄昏EX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值