Android Google KEY

Android安全架构这篇文章中,我们了解到了Android系统的整体安全架构,那么这套架构,应用于那些场景呢?Google KEY就是其中非常重要的场景。本篇就详细介绍一下Google KEY的这套机制。

google提供了gms package应用,还有gms core等核心服务,那么这些应用和功能到底要怎么激活呢?肯定需要得到google的授权和认可,因此google通过gms包和xts来进行授权与认证。因此我们在做一个海外项目,首先要做的就是像google注册,提供白名单申请google keybox,google通过keybox机制来管理控制每台android手机的是否能使用google的这些核心服务。

1、Google Attestation

Google Attestation (通常指 Android Key AttestationHardware Attestation )是 Android 系统提供的一种密码学证明机制

它的核心作用是:让设备向外部(通常是云端服务器或 App)提供一份"数字证书",以数学方式证明设备的硬件完整性、软件状态以及密钥的真实性。

简单来说,就是设备拿着自己的"身份证"和"体检报告",通过加密签名的方式告诉服务器:"我是真正的 Google 认证设备,我的系统没有被 Root,我的启动锁是锁着的,这个密钥是在安全芯片里生成的。"

1)核心原理

Attestation 的本质是建立一条从 Google 根证书设备具体密钥 的信任链

2)应用场景

2、Widevine DRM

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级‌:最高安全级别,依赖硬件安全模块(如可信执行环境TEE),支持高清和HDR内容播放,是商业级DRM的标准
  • L2级‌:部分硬件安全级别,兼容性较好,但安全性低于L1
  • L3级‌:软件级别,安全性最低,作为 fallback 选项在设备不支持硬件级时使用

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

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

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

即Widevine KEY需要基于google attestation,并且依赖于TEE的环境。

2)Widevine L3如何实现?

详细参考https://blog.csdn.net/qq_27672101/article/details/160451924

3)Widevine L1如何实现?

详细参考https://blog.csdn.net/qq_27672101/article/details/160451924

3、Google Keybox

Google Keybox (通常指文件名为 keybox.xml 的文件)是 Android 生态系统中最核心、最敏感的安全凭证文件

它是 Google 分发给手机厂商(OEM),用于在工厂生产线上"激活"设备硬件安全芯片的原始密钥包。你可以把它理解为:Android 设备的"数字出生证明"和"身份印章"的母版。

1)核心原理

详细参考https://blog.csdn.net/chenhao0568/article/details/139146452

  • 文件格式 :一个标准的 XML 文本文件
  • 核心内容 :包含了一组或多组非对称加密密钥对(公钥 + 私钥 )。最关键的是 设备唯一密钥 (Device Unique Key, DUK)。理论上,全球每一台通过 Google 认证的手机,其 DUK 私钥都是独一无二的。可能还包含用于加密用户数据的密钥(在旧版本 Android 中)。
  • 来源 :由 Google 生成,并通过安全渠道分发给获得 GMS(Google Mobile Services)认证的厂商(如三星、小米、OPPO 等)。

2)使用流程

步骤一:google keybox的申请
  • 每个device单独申请keybox(attestation key),首先需要去跑CTS白名单
  • 根据CTS白名单的报告提交到google官方网站进行keybox申请
步骤二:google keybox的切割
  • google审核通过之后会返回一个keybox,为了工厂生产的需要,我们需要对其进行切割
  • 申请下来的keybox是一个很大的output文件,解压之后发现其实就是几万个如下字符串
步骤三:google keybox的写入
  • 对如上output进行切割,其实就是output文件存储了上万个key,我们截取其中一个keybox就行了并组成keybox.xml文件
  • MTK平台进入meta模式进行安装keybox.xml
  • 高通某A14平台可以通过如下命令进行写入
bash 复制代码
#第一步:擦除KEYBOX
C:\Users\pengcheng.ding>adb root
C:\Users\pengcheng.ding>adb shell
SH4-1:/ # qseecom_sample_client -v samplap64 15 1
Note: Command line arguments do not belong to legacy test
        ---------------------------------------------------------------
         WARNING!!! You are about to erase the entire RPMB partition.
        ----------------------------------------------------------------
         Do you want to proceed (y/n)? y
RPMB partition erase failed (-1)
#这里擦除失败/可以先不管
#第二步:删除KEYBOX,keybox就在mnt/vendor/persist/data/Da目录下
C:\Users\pengcheng.ding>adb shell rm -rf /mnt/vendor/persist/data/Dd*
#第三步:推送KEYBOX
C:\Users\pengcheng.ding>adb push F:\TempTinno\rkp\keybox-sku1.xml /sdcard/
F:\TempTinno\rkp\keybox-sku1.xml: 1 file pushed, 0 skipped. 0.6 MB/s (12720 bytes in 0.019s)
#第四步:写入KEYBOX
C:\Users\pengcheng.ding>adb shell LD_LIBRARY_PATH=/vendor/lib64/hw KmInstallKeybox sdcard/keybox-sku1.xml Ascom_SH4-1_00000000 true
Brand: Ascom
Device: SH4-1
Product: SH4-ABCE
SerialNum: 5a33bdcc
Manufacturer: Ascom
Model: Myco 4 Slim Cellular Wi-Fi
Imei: 355822900209444
Meid:
Number of keyboxes 1
myDeviceID: Ascom_SH4-1_00000000
keyboxCtx.device_id.data: Ascom_SH4-1_00000000
KeyMaster Attestation Key Provisioning success for KeyIDAscom_SH4-1_00000000
TEE done
InstallKeybox is done!
#表示安装keybox成功
步骤四:google keybox查询是否写入

不同项目查看方式不一样:

  • 有些项目可以通过查看/mnt/vendor/persist/attest_keybox.so是否存在
  • 有些项目可以执行adb shell getprop |grep "googlekey"或者进入工模模式是否有android key:OK (注意这个功能是ODM自己开发)
  • 高通某A14项目需要cd /mnt/vendor/persist/data/Dd*目录下看有东西是否存在:
重点说明:google keybox是否必须要写入?

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

4、Google RKP

由于 Keybox 模式存在"工厂泄露"的巨大风险,Google 正在大力推行 RKP (Remote Key Provisioning,远程密钥配置) 来取代它。

  • Keybox 模式:密钥在工厂生成并烧录(风险在工厂)。
  • RKP 模式 :手机出厂时没有唯一密钥。用户第一次开机联网时,手机直接向 Google 云端申请密钥,云端动态生成并下发给手机(风险在云端,工厂接触不到密钥)。

Google RKP (Remote Key Provisioning,远程密钥配置) 是 Google 为 Android 生态系统设计的一种云端动态密钥分发机制

它是传统 Keybox (keybox.xml) 模式的现代化继任者 ,旨在解决传统模式下密钥在工厂环节容易泄露、难以管理以及扩展性差等核心安全问题。简单来说:RKP 让手机在出厂时"没有身份",直到用户第一次联网激活时,才从 Google 云端"领取"独一无二的数字身份证。

1)Google RKP的优势

特性 传统 Keybox 模式 RKP (远程密钥配置) 优势解读
密钥生成地 工厂/离线生成 Google 云端实时生成 工厂永远接触不到具体设备的私钥,彻底杜绝工厂泄露风险。
供应链安全 低 (需严格审计工厂) 极高 即使工厂被攻破,黑客也拿不到任何有效密钥,只能拿到无法使用的通用初始密钥。
扩展性 有限 (需预先规划数量) 无限 按需生成,卖多少台就生成多少个密钥,无需预测销量,避免密钥浪费或短缺。
密钥轮换 困难 (几乎不可能) 支持 如果检测到异常,云端可以撤销旧密钥并在下次请求时下发新密钥(取决于策略)。
隐私保护 一般 更强 密钥生成与生产批次解耦,减少了通过密钥追踪特定生产批次的可能性。
合规成本 高 (厂商需建立高等级密钥库) 厂商无需维护庞大的密钥管理系统 (KMS),责任转移给 Google。

如果把 Android 设备比作一个人:

  • Keybox 像是**"出生前就印好的身份证"**,由工厂保管,容易被盗版复印。
  • RKP 像是**"本人亲自去派出所按指纹领身份证"** 。
    • 工厂只负责把你生出来(制造硬件)。
    • 你自己(用户开机)去公安局(Google 云端)。
    • 公安局核实你是你之后,当场制作并发放身份证(密钥)。
    • 工厂永远不知道你的身份证号是多少。

Google RKP 是 Android 安全架构的一次重大升级,它将信任的锚点从不可控的供应链(工厂) 转移到了可控的云端(Google),是未来所有 Android 设备安全身份的基石。

在A16系统上google强制要求集成RKP机制

如果同时需要支持widevine L3,那么在生成csr的时候可以不用生成widevine key

如果同时需要支持widevine L1,那么在生成csr的时候必须同时生成widevine key

2)高通平台如何实现?

高通平台的实现思路,最核心的就是通过工具生成csr,然后把csr上传到google云服务器,这样在每台机器首次激活的时候,就能通过网络与google云服务器进行密码学认证:

步骤一:集成rkp_factory_extraction_tool工具

AOSP已经封装了rkp_factory_extraction_tool工具的实现,这个工具貌似是在A14之后才有,我记得A13的项目上面是预制了google释放的一个bin文件,然而这个预制在A12上面会不兼容,所以比较老的android版本可能不支持这个功能。

此模块的代码路径system/security/provisioner/:

本案以A16为例,如上A16已经实现了rkp_factory_extraction_tool模块,被定义为bin文件,因此只需要将其添加到PRODUCT_PACKAGES:

PRODUCT_PACKAGES += rkp_factory_extraction_tool

PS:可以在vendor/bin/中集成也可以在system/bin中集成,只要有这个工具即可,在A16 64位机器上面亲测之后编译出来的产物是64位后搓:

步骤二:擦除attestation ID

Attestation ID是什么?Google Attestation ID 是用于设备或系统在安全认证过程中证明自身身份和完整性的关键标识。

AOSP默认不允许Attestation ID重复生成,如下报错:

  • 解决方案1:擦除现有Attestation ID

235|SH4-2:/ # qseecom_sample_client v smplap64 15 1

Note: Command line arguments do not belong to legacy test


WARNING!!! You are about to erase the entire RPMB partition.


Do you want to proceed (y/n)? y
RPMB erase completed

PS:重启生效

  • 解决方案2:配置宏控允许重复生成
步骤三:生成attestation ID

SH4-2:/ # LD_LIBRARY_PATH=/vendor/lib64/hw KmInstallKeybox 1 1 true rkp

qmi_client_init_instance error:-3

Warning! Modem device ids will not be provisioned

Brand: XXX

Device: XXX

Product: XXXX

SerialNum: 824d42fc

Manufacturer: XXXX

Model: XXXXX

TEE done
InstallKeybox is done!

PS:执行之前需要root,执行KmInstallKeybo进程,生成attestation ID

步骤四:生成CSR

SH4-2:/ # /vendor/bin/rkp_factory_extraction_tool64 --allow_degenerate=default --output_format build+csr

{"build_fingerprint":"XXX:16/BQ2A.251125.001-BP2A.250605.031.A3/A16_001.00:userdebug/release-keys",

"csr":"hQGggqUBAQMnIAYEgQIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLIRDoQEnoFhYpAFpUVVBTENPTU0AAm9SS1AgRGV2aWNlIEtleQA6AEdEV1gtpQEBAycgBgSBAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwsOgBHRFhBIFhA6nUjlIL12YLLjGdSP3mUvTTbz1gSjOGox6gqcESFcMmD7yGGCmnVnepWk/yo78mjCUvumfzzbKgT+mhtke3nDYRDoQEnoFkBc4JYQO3paJC83/DwnLxnl3X/KA+Y7U99wi1spg1+p/oEbjjjPX1K7fqgTBvIFrgzdBo3bNaqjoY+pyKixCT1cN4Nb0lZAS2EA2drZXltaW50rmVicmFuZGVBc2NvbWVmdXNlZAFlbW9kZWxxTXljbyA0IERFQ1QgV2ktRmlmZGV2aWNlZVNINC0yZ3Byb2R1Y3RoU0g0LUFBREVodmJfc3RhdGVmb3Jhbmdlam9zX3ZlcnNpb25mMTYwMDAwbG1hbnVmYWN0dXJlcmVBc2NvbW12Ym1ldGFfZGlnZXN0WCD44H3tgenkKY7pXxY06JKkmOSmuk+FYa5kNDi69tgilG5zZWN1cml0eV9sZXZlbGN0ZWVwYm9vdF9wYXRjaF9sZXZlbBoBNSXRcGJvb3Rsb2FkZXJfc3RhdGVodW5sb2NrZWRyc3lzdGVtX3BhdGNoX2xldmVsGgADF2tydmVuZG9yX3BhdGNoX2xldmVsGgE1JdGAWEBdpoNyCiXeIorumV3GwifnZH0e57MY3TaE9lOQpkngxHgveZomPZo2bwFKjXVkEFSkFCVBeh9wInL3wthrJWgNoWtmaW5nZXJwcmludHhcQXNjb20vU0g0LUFBREUvU0g0LTI6MTYvQlEyQS4yNTExMjUuMDAxLUJQMkEuMjUwNjA1LjAzMS5BMy9BMTZfMDAxLjAwOnVzZXJkZWJ1Zy9yZWxlYXNlLWtleXM=",

"name":"default",

"serialno" :"e99df9f8"}

Bundle extraction failed for 'widevine'. Description: Status(-8, EX_SERVICE_SPECIFIC): '1: Failed to parse the verified device info cbor.'.
Unable to build CSR for 'android.hardware.drm.IDrmFactory/widevine': Status(-8, EX_SERVICE_SPECIFIC): '1: Failed to parse the verified device info cbor.', exiting.

如上生成的json字符串中的csr字段就是我们的秘钥,后续的报错是因为命令没有指定widevine参数,所以widevine的秘钥生成失败。

步骤五:上传CSR

最后一步,就是把上述的json文件上传到google服务器,上传方式也非常的多,这里介绍其中通过google工具(device_info_uploader.py/需要从google网站下载)的方式上传:

C:\Users\junhui.li>python device_info_uploader.py --credentials cred.json --json-csr dpc_csr.json --company-id=13??????44 --verbose

1/1: Uploading batch containing 1 csr(s)

request body:

{'device_payloads': [{'certificate_payloads': [
{'certificate_signing_request': 'hQGggqUBAQMnIAYEgQIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLIRDoQEnoFhYpAFpUVVBTENPTU0AAm9SS1AgRGV2aWNlIEtleQA6AEdEV1gtpQEBAycgBgSBAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwsOgBHRFhBIFhA6nUjlIL12YLLjGdSP3mUvTTbz1gSjOGox6gqcESFcMmD7yGGCmnVnepWk/yo78mjCUvumfzzbKgT+mhtke3nDYRDoQEnoFkBfYJYQOF1q9lxMkzqKCuH711d9t678eUP/2qvHt10d/RQTGDadDPS1WYD4ym+kmKU6zWFgfPS0+iWws/LtI3ozk/cKF9ZATeEA2drZXltaW50rmVicmFuZGVBc2NvbWVmdXNlZAFlbW9kZWx4Gk15Y28gNCBTbGltIENlbGx1bGFyIFdpLUZpZmRldmljZWVTSDQtMWdwcm9kdWN0aFNINC1BQkNFaHZiX3N0YXRlZm9yYW5nZWpvc192ZXJzaW9uZjE2MDAwMGxtYW51ZmFjdHVyZXJlQXNjb21tdmJtZXRhX2RpZ2VzdFgg//2vigkltzjPJmhSudF7E7TXHu5/uqgI0gKRuvV7i6Vuc2VjdXJpdHlfbGV2ZWxjdGVlcGJvb3RfcGF0Y2hfbGV2ZWwaATUl0XBib290bG9hZGVyX3N0YXRlaHVubG9ja2VkcnN5c3RlbV9wYXRjaF9sZXZlbBoAAxdrcnZlbmRvcl9wYXRjaF9sZXZlbBoBNSXRgFhAeNyMnZZp0ElR0od+rBpTU9sAfpiM8CcR/reVkupNt5WPcsy0l3RpEHgJo8sXyti8++fdsJeAxKEgV52L3rGtAKFrZmluZ2VycHJpbnR4WUFzY29tL1NINC1BQkNFL1NINC0xOjE2L0JRMkEuMjYwMTAzLjAwMS1CUDJBLjI1MDcwNS4wMDgvZW5nLmFuZHJvaTp1c2VyZGVidWcvcmVsZWFzZS1rZXlz'}

]}], 'company_id': '1398696844', 'is_test': False}
Opening your web browser to authenticate... --->这里会启动浏览器
Waiting for a response from the Google OAuth service. --->这里会登陆google特定账号,只有特定账号才有权限进行上传

If you receive an error in your browser, interrupt this script.

GET path: /?iss=https://accounts.google.com&code=4/0Aci98E-WSBq5vxyGljCIiNEXuSrmOPepkDwJKHJNpoHJqAfJO4oLfs8EuMtl4b-DZjo5lA&scope=https://www.googleapis.com/auth/androidPartner

127.0.0.1 - - [15/Apr/2026 21:32:44] "GET /?iss=https://accounts.google.com&code=4/0Aci98E-WSBq5vxyGljCIiNEXuSrmOPepkDwJKHJNpoHJqAfJO4oLfs8EuMtl4b-DZjo5lA&scope=https://www.googleapis.com/auth/androidPartner HTTP/1.1" 200 -

Batch API response:{

"errors": [

{

"certificatePayload":
{ "certificateSigningRequest": "hQGggqUBAQMnIAYEgQIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLIRDoQEnoFhYpAFpUVVBTENPTU0AAm9SS1AgRGV2aWNlIEtleQA6AEdEV1gtpQEBAycgBgSBAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwsOgBHRFhBIFhA6nUjlIL12YLLjGdSP3mUvTTbz1gSjOGox6gqcESFcMmD7yGGCmnVnepWk/yo78mjCUvumfzzbKgT+mhtke3nDYRDoQEnoFkBfYJYQOF1q9lxMkzqKCuH711d9t678eUP/2qvHt10d/RQTGDadDPS1WYD4ym+kmKU6zWFgfPS0+iWws/LtI3ozk/cKF9ZATeEA2drZXltaW50rmVicmFuZGVBc2NvbWVmdXNlZAFlbW9kZWx4Gk15Y28gNCBTbGltIENlbGx1bGFyIFdpLUZpZmRldmljZWVTSDQtMWdwcm9kdWN0aFNINC1BQkNFaHZiX3N0YXRlZm9yYW5nZWpvc192ZXJzaW9uZjE2MDAwMGxtYW51ZmFjdHVyZXJlQXNjb21tdmJtZXRhX2RpZ2VzdFgg//2vigkltzjPJmhSudF7E7TXHu5/uqgI0gKRuvV7i6Vuc2VjdXJpdHlfbGV2ZWxjdGVlcGJvb3RfcGF0Y2hfbGV2ZWwaATUl0XBib290bG9hZGVyX3N0YXRlaHVubG9ja2VkcnN5c3RlbV9wYXRjaF9sZXZlbBoAAxdrcnZlbmRvcl9wYXRjaF9sZXZlbBoBNSXRgFhAeNyMnZZp0ElR0od+rBpTU9sAfpiM8CcR/reVkupNt5WPcsy0l3RpEHgJo8sXyti8++fdsJeAxKEgV52L3rGtAKFrZmluZ2VycHJpbnR4WUFzY29tL1NINC1BQkNFL1NINC0xOjE2L0JRMkEuMjYwMTAzLjAwMS1CUDJBLjI1MDcwNS4wMDgvZW5nLmFuZHJvaTp1c2VyZGVidWcvcmVsZWFzZS1rZXlz" }

,
"status": --->返回值200,状态码6表示CSR的公钥已经在服务器中存在
{ "code": 6, "message": "This CSR was not uploaded. Device public key (o\u001d+ɣ]4\u0005;g 6Va z3 1 Ŷ \\,) already exists. Please call BatchUpdate to modify an existing key's data." }

}

],

"requestId": "fb4fb6e0-eefb-4c6d-9f91-c803e2ae2372"

}

Errors occurred when uploading csrs: 200

注意在执行device_info_uploader.py之前,需要配置python环境,配置浏览器并在浏览器完成身份证认证,最后调用这个py脚本会默认启动本地浏览器,完成上传操作。

RPMB命令:模拟rmpb安全环境

此步可以跳过,此步是模拟rmpb安全环境,如果在实际调试过程中可能可能生成失败,是因为当前环境不安全,我们可以通过如下方式模拟安全环境:

adb root && adb shell qseecom_sample_client v smplap64 14 1

  • 检查RPMB状态:秘钥未配置

SH4-2:/ # qseecom_sample_client v smplap64 14 1

Note: Command line arguments do not belong to legacy test


WARNING!!! You are about to provision the RPMB key.

This is a ONE time operation and CANNOT be reversed.


0 -> Provision Production key

1 -> Provision Test key

2 -> Check RPMB key provision status


Select an option to proceed: 2
RMPB Key status: RPMB_KEY_NOT_PROVISIONED (f) --->未配置秘钥

  • 配置RPMB状态:配置秘钥

SH4-2:/ # qseecom_sample_client v smplap64 14 1

Note: Command line arguments do not belong to legacy test


WARNING!!! You are about to provision the RPMB key.

This is a ONE time operation and CANNOT be reversed.


0 -> Provision Production key

1 -> Provision Test key

2 -> Check RPMB key provision status


Select an option to proceed: 1
RPMB key provisioning completed --->配置成功

  • 检查RPMB状态:秘钥已配置

SH4-2:/ # qseecom_sample_client v smplap64 14 1

Note: Command line arguments do not belong to legacy test


WARNING!!! You are about to provision the RPMB key.

This is a ONE time operation and CANNOT be reversed.


0 -> Provision Production key

1 -> Provision Test key

2 -> Check RPMB key provision status


Select an option to proceed: 2
RMPB Key status: RPMB_KEY_PROVISIONED_AND_OK (0) --->秘钥已经配置

3)MTK平台如何实现?

MTK平台的实现思路,最核心的就是通过工具生成csr,然后把csr上传到google云服务器,这样在每台机器首次激活的时候,这个流程基本上同高通平台一致,只是因为平台不一样,可能存在一些细节上的差异。本小节的背景同时支持Widevine L1,因此需要在工具生成google的csr之外,还要生成Widevine csr,本例一起介绍:

步骤一:集成rkp_factory_extraction_tool工具

同高通,在MTK平台也存在rkp_factory_extraction_tool模块

PRODUCT_PACKAGES += rkp_factory_extraction_tool

步骤二:集成kmsetkey_ca工具

PRODUCT_PACKAGES += kmsetkey_ca

PS:kmsetkey_ca工具为MTK定制开发的二进制bin文件,用来生成attestation ID,等同于高通平台的KmInstallKeybox工具

如上源码,参数可以传-i -c -v -d,其中-d就是安装attestation ID

步骤三:生成attestation ID

kmsetkey_ca -d

步骤四:生成CSR

rkp_factory_extraction_tool --output_format build+csr

步骤五:上传CSR

C:\Users\???>python device_info_uploader.py --credentials cred.json --json-csr xxx_csr.json --company-id=13??????44 --verbose

1/1: Uploading batch containing 1 csr(s)

request body:

{'device_payloads': [{'certificate_payloads': [{'certificate_signing_request': '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'}]}], 'company_id': '1398696844', 'is_test': False}

Opening your web browser to authenticate...

Waiting for a response from the Google OAuth service.

If you receive an error in your browser, interrupt this script.

GET path: /?iss=https://accounts.google.com&code=4/0Aci98E-k0shhmZxSLcmPwhigCOdMXXdzCrsE4lGQ4oSkNt0eBP7FcjkuzH8Hm-ivulNxpQ&scope=https://www.googleapis.com/auth/androidPartner

127.0.0.1 - - [23/Apr/2026 16:05:04] "GET /?iss=https://accounts.google.com&code=4/0Aci98E-k0shhmZxSLcmPwhigCOdMXXdzCrsE4lGQ4oSkNt0eBP7FcjkuzH8Hm-ivulNxpQ&scope=https://www.googleapis.com/auth/androidPartner HTTP/1.1" 200 -

Batch API response:{

"requestId": "2b7460f4-163d-420d-ad83-f6dbdc7eac05"

}

Batch processing complete. --->表示上传成功

4)Google RKP流程详解

Google官方有介绍:https://source.android.com/docs/core/ota/modular-system/remote-key-provisioning?hl=zh-cn

解析来我结合google官方文档的描述,和我在实际开发中生成CSR/上传CSR/验证CSR的整套步骤和Google RKP服务架构进行结合,来详细解读一下一个完整流程链条:

阶段一:开发准备

集成rkp_factory_extraction_tool工具,准备版本

阶段二:CSR生成与上传

这个阶段通常在工厂生成的时候完成,主要包含如下几个步骤:

  • 生成 Attestation ID(设备唯一标识)
  • 生成Google CSR和Widevine CSR(Widevine L1使能就能正确生成,否则不用管Widevine CSR报错信息)
阶段三:Google签发证书

在上传CSR的时候,Google服务器收到CSR请求的时候,就会在后台同步做如下几个事情:

  • 验证CSR中的设备信息
  • 验证设备是否在APA注册(brand product device name是否向google申请注册?)
  • 签发Attestation Certificate Chain证书
  • 存储Attestation Certificate Chain证书到Google RKP服务器
阶段四:设备运行时获取证书

对应我司的User版本首次激活,通过网络会和google服务器进行沟通,如果Google RKP服务器存储过此设备(brand product device name)对应的Attestation Certificate Chain证书,就会自动下载获取。

Android系统RKP Client客户端进程会在后台执行如下几个事情:

  • 检测设备首次激活
  • 连接 Google RKP 服务器
  • 发送设备标识 + 证明
  • 接收Google签发的Attestation Certificate Chain证书
  • Android系统RKP Client客户端进程将证书写入TEE
阶段五:验证CSR有效性

参考后文,可以跑GtsGoogleAttestationHostTestCases进行验证。推测大致流程如下:

  • 检查是否存在attestation ID
  • 检查TEE中是否存在Attestation Certificate Chain证书

5)如何验证CSR的有效性?

GTS测试GtsGoogleAttestationHostTestCases和testEcAttestationChainTee专门用来检查CSR密钥的有效性。

针对这两条失败项的解读:

错误一:ATTESTATION_KEYS_NOT_PROVISIONED -74

如上错误码ATTESTATION_KEYS_NOT_PROVISIONED -74。表示在KeyMint在请求开始的早期阶段,就检测到没有认证密钥,直接拒绝。很明确的告诉你没有生成attestation ID,没有通过RKP工具生成CSR。

错误二:ERROR_KEYMINT_FAILURE -10021

如上错误码ERROR_KEYMINT_FAILURE -10021。表示在KeyMint HAL 后期阶段,尝试使用认证密钥,即尝试检查Attestation Certificate Chain证书是否正确。但是认证失败的通用错误码,失败的具体原因可能有如下几种情况:

  • CSR 未生成或未上传

  • CSR 格式错误或被 Google 拒绝

  • CSR 成功但证书未正确配置

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.ICredentialStoreStubProxy.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编译),更新之后的版本记录如下:

案例四:验证keymaster hal层模块是否正常

VTS测试有针对hal层模块的相关测试,google这套安全架构里面处于这层的就是keymaster hal,这块代码通常平台闭源,我们能做的事情不多,遇到此类问题通常需要提高通case。

PS:在A16之后,keymaster变成了AIDL,并且还多了一个VtsHalRemotelyProvisionedComponentTargetTest来对远程秘钥生成RKP的一个校验

VtsHalKeymasterV4_0TargetTest

报错日志:PerInstance/AttestationTest#RsaAttestation/0_default 和 PerInstance/AttestationTest#EcAttestation/0_default 和

问题分析:boot_a分区没有匹配google key,报的是keymaster的异常,不清楚和google key有什么关系

解决方案:写google key重新跑此条PASS

总结:VtsHalKeymasterV4_0TargetTest子项PerInstance/AttestationTest关于google key的测试,通常保证google key一致,写入google key都可以pass

VtsAidlKeyMintTargetTest

报错日志:arm64-v8a VtsAidlKeyMintTargetTest

Test Result Details

PerInstance/AttestKeyTest#EcdsaAttestationID/0_android_hardware_security_keymint_IKeyMintDevice_default

fail

Device IMEI: Permission denied.

PerInstance/NewKeyGenerationTest#EcdsaAttestationIdTags/0_android_hardware_security_keymint_IKeyMintDevice_default

fail

Device IMEI: Permission denied.

PerInstance/NewKeyGenerationTest#EcdsaAttestationIdAllTags/0_android_hardware_security_keymint_IKeyMintDevice_default

fail

Device IMEI: Permission denied.

问题分析:此条测试项无论是keybox的方式,还是rkp的方式,最后都pass了

总结:同VtsHalKeymasterV4_0TargetTest是针对比较老的keymaster hidl服务进程的测试,VtsAidlKeyMintTargetTest是针对比较新的keymaster aidl服务进程的一个测试,如果此项无法通过,那么需要找平台进行跟进。

VtsHalRemotelyProvisionedComponentTargetTest

报错日志:arm64-v8a VtsHalRemotelyProvisionedComponentTargetTest

Test Result Details

PerInstance/CertificateRequestV2Test#EmptyRequest/0_android_hardware_security_keymint_IRemotelyProvisionedComponent_default

fail

hardware/interfaces/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp:941: Failure

PerInstance/CertificateRequestV2Test#NonEmptyRequest/0_android_hardware_security_keymint_IRemotelyProvisionedComponent_default

fail

hardware/interfaces/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp:963: Failure

PerInstance/CertificateRequestV2Test#NonEmptyRequestReproducible/0_android_hardware_security_keymint_IRemotelyProvisionedComponent_default

fail

hardware/interfaces/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp:994: Failure

PerInstance/CertificateRequestV2Test#NonEmptyRequestMultipleKeys/0_android_hardware_security_keymint_IRemotelyProvisionedComponent_default

fail

hardware/interfaces/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp:1020: Failure

问题分析:此条报错在生成了Attestation ID之后就能够全部pass

总结:同前面两条不一样的,VtsHalRemotelyProvisionedComponentTargetTest是针对远程RKP的服务进程进行测试,如果此项无法通过,那么还是得需要找平台进行跟进。

案例五:RKP方式没有生成Attestation ID的案例

GtsEdiHostTestCases

报错日志:arm64-v8a GtsEdiHostTestCases

Test Result Details

com.google.android.gts.edi.HardwareTrustDeviceInfo#testCollectDeviceInfo

fail

java.lang.AssertionError: Failed to collect device info (HardwareTrustDeviceInfo.deviceinfo.json): File is empty: HardwareTrustDeviceInfo.deviceinfo.json

用例分析:使用keybox的方式进行测试,就会报如上异常日志;但是使用RKP的方式去生成Attstation ID之后,并生成CSR秘钥,但是这个CSR秘钥并没有上传到google服务器,报告如下跳过了此条测试项

总结:com.google.android.gts.edi.HardwareTrustDeviceInfo#testCollectDeviceInfo在生成Attstation ID之后能够pass,但是这条会跳过。

CtsKeystoreTestCases

报错日志:此条测试项报错如下几类

  • android.keystore.cts.DeviceOwnerKeyManagementTest#testAllVariationsOfDeviceIdAttestation

Unexpected failure while generating key RSA with ID flags 1: java.lang.UnsupportedOperationException: Device does not support Device ID attestation. In case of AOSP/GSI builds, system provided properties could be different from provisioned properties in KeyMaster/KeyMint. In such cases, make sure attestation specific properties (Build.*_FOR_ATTESTATION) are configured correctly. expected to be true at android.keystore.cts.DeviceOwnerKeyManagementTest.generateKeyAndCheckAttestation(DeviceOwnerKeyManagementTest.java:432) at android.keystore.cts.DeviceOwnerKeyManagementTest.assertAllVariantsOfDeviceIdAttestation(DeviceOwnerKeyManagementTest.java:484) at android.keystore.cts.DeviceOwnerKeyManagementTest.testAllVariationsOfDeviceIdAttestation(DeviceOwnerKe

KeyMint 在带 设备 ID/设备标识 的 attestation 请求上返回 CANNOT_ATTEST_IDS,框架侧映射为「不支持 Device ID attestation」。常见方向:未实现/未开启设备 ID 证明、Keybox/工厂数据与系统 Build(含 FOR_ATTESTATION)不一致。

  • testRsaAttestation/testEcAttestation/testCurve25519Attestation

在 devicePropertiesAttestation true 时要把 ATTESTATION_ID_* 写进证书,KeyMint 拒绝 → CANNOT_ATTEST_IDS。同模块里 testRsaAttestation_NoChallenge 等未开设备属性证明的用例能通过,说明 普通密钥证明可用,卡在「设备属性/ID 证明」

  • KeyAttestationTest#testEcAttestation_DeviceLocked/KeyAttestationTest#testRsaAttestation_DeviceLocked

java.lang.AssertionError:The device's bootloader must be locked. This may not be the default for pre-production devices. at org.junit.Assert.fail(Assert.java:89) at org.junit.Assert.assertTrue(Assert.java:42) at android.keystore.cts.KeyAttestationTest.checkRootOfTrust(KeyAttestationTest.java:1875) at android.keystore.cts.KeyAttestationTest.checkDeviceLocked(KeyAttestationTest.java:1806) at android.keystore.cts.KeyAttestationTest.testEcAttestation_DeviceLocked(KeyAttestationTest.java:491) at android.keystore.cts.KeyAttestationTest.testEcAttestation_DeviceLocked(KeyAttestationTest.java:502)

attestation 扩展里的 Root of Trust,要求 bootloader 处于 locked。当前设备(或工程配置)为 unlock 或 RoT 未反映为 locked,与 logcat 里大量 keyguard deviceLocked(用户锁屏)不是同一概念------测的是 引导加载程序锁定状态。

原因分析:此条第一条报错,是因为没有生成attestation ID,第二条报错是因为attestation ID没有导致无法写入秘钥,第三条是设备处于解锁状态。最后通过RKP的方式生成Attestation ID之后,此条除了testEcAttestation_DeviceLocked和testRsaAttestation_DeviceLocked之外都能PASS

总结:在RKP的方式里面Attestation相关的测试项,需要依赖设备具有attestation ID,否则一定会失败。这些测试项也没有真正的和google服务器进行秘钥校验。另外DeviceLocked相关的测试项需要使用已经锁定的设备进行测试才能PASS。

CtsDevicePolicyManagerTestCases

报错日志:arm64-v8a CtsDevicePolicyManagerTestCases

Test Result Details

com.android.cts.devicepolicy.MixedDeviceOwnerTest#testDelegatedCertInstallerDeviceIdAttestation

fail

java.lang.AssertionError: on-device tests failed:

com.android.cts.devicepolicy.MixedDeviceOwnerTest#testKeyManagement

fail

java.lang.AssertionError: on-device tests failed:

com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testKeyManagement

fail

org.junit.ComparisonFailure: expected:<[Success:]> but was:<[]>

com.android.cts.devicepolicy.MixedProfileOwnerTest#testKeyManagement

fail

java.lang.AssertionError: on-device tests failed:

com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testDelegatedCertInstallerDeviceIdAttestation

fail

org.junit.ComparisonFailure: expected:<[Success:]> but was:<[]>

com.android.cts.devicepolicy.OrgOwnedProfileOwnerTest#testDeviceIdAttestationForProfileOwner

fail

java.lang.AssertionError: on-device tests failed:

分析过程:此条在ASCOM A16项目最初也是通过keybox的方式来进行测试,也报了很多attestation相关的异常,在通过rkp的方式生成了attestation ID之后,这些项能够全部PASS

总结:CtsDevicePolicyManagerTestCases中关于Attestation相关的测试项也是需要生成attestation ID之后才能PASS

案例六:RKP CSR秘钥校验是否有效

前文的大部分XTS问题在生成了attestation ID之后就能PASS,但是接下来这条却不行,是google真正校验csr秘钥是否有效,即必须在把CSR上传到google服务器才能通过的测试项

报错日志:com.google.android.gts.security.AttestationRootHostTest#testRsaAttestationChainTee/com.google.android.gts.security.AttestationRootHostTest#testEcAttestationChainTee

如下报错表示如下秘钥没有得到google认证,原因是RKP生成的CSR并没有上传到google服务器

bash 复制代码
java.lang.AssertionError: on-device tests failed:
com.google.android.gts.security.AttestationRootTest#testRsaAttestationChainTee:
java.security.ProviderException: Failed to generate key pair.
at android.security.keystore2.AndroidKeyStoreKeyPairGeneratorSpi.generateKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:712)
at java.security.KeyPairGenerator$Delegate.generateKeyPair(KeyPairGenerator.java:750)
at com.google.android.gts.security.AttestationRootTest.generateKeyPair(AttestationRootTest.java:248)
at com.google.android.gts.security.AttestationRootTest.testRsaAttestationChainTee(AttestationRootTest.java:197)
... 8 trimmed
Caused by: android.security.KeyStoreException: -74 (internal Keystore code: -74 message: system/security/keystore2/src/security_level.rs:680

Caused by:
0: system/security/keystore2/src/security_level.rs:674: While generating without a provided attestation key and params: [KeyParameter

{ tag: r#KEY_SIZE, value: Integer(2048) }
, KeyParameter

{ tag: r#ALGORITHM, value: Algorithm(r#RSA) }
, KeyParameter

{ tag: r#PURPOSE, value: KeyPurpose(r#SIGN) }
, KeyParameter

{ tag: r#PURPOSE, value: KeyPurpose(r#VERIFY) }
, KeyParameter

{ tag: r#PADDING, value: PaddingMode(r#RSA_PSS) }
, KeyParameter

{ tag: r#DIGEST, value: Digest(r#SHA_2_256) }
, KeyParameter

{ tag: r#NO_AUTH_REQUIRED, value: BoolValue(true) }
, KeyParameter

{ tag: r#CERTIFICATE_NOT_AFTER, value: DateTime(2461449600000) }
, KeyParameter

{ tag: r#CERTIFICATE_NOT_BEFORE, value: DateTime(0) }
, KeyParameter

{ tag: r#CERTIFICATE_SERIAL, value: Blob([1]) }
, KeyParameter

{ tag: r#CERTIFICATE_SUBJECT, value: Blob([48, 31, 49, 29, 48, 27, 6, 3, 85, 4, 3, 19, 20, 65, 110, 100, 114, 111, 105, 100, 32, 75, 101, 121, 115, 116, 111, 114, 101, 32, 75, 101, 121]) }
, KeyParameter

{ tag: r#RSA_PUBLIC_EXPONENT, value: LongInteger(65537) }
, KeyParameter

{ tag: r#ATTESTATION_CHALLENGE, value: Blob([99, 104, 97, 108, 108, 101, 110, 103, 101]) }
, KeyParameter

{ tag: r#CREATION_DATETIME, value: DateTime(1774884669430) }
, KeyParameter

{ tag: r#ATTESTATION_APPLICATION_ID, value: Blob([48, 76, 49, 38, 48, 36, 4, 31, 99, 111, 109, 46, 103, 111, 111, 103, 108, 101, 46, 97, 110, 100, 114, 111, 105, 100, 46, 103, 116, 115, 46, 115, 101, 99, 117, 114, 105, 116, 121, 2, 1, 37, 49, 34, 4, 32, 25, 117, 178, 241, 113, 119, 188, 137, 165, 223, 243, 31, 158, 100, 166, 202, 226, 129, 165, 61, 193, 209, 213, 155, 29, 20, 127, 225, 200, 42, 250, 0]) }
].
1: Error::Km(r#ATTESTATION_KEYS_NOT_PROVISIONED)) (public error code: 10 internal Keystore code: -74)
at android.security.KeyStore2.getKeyStoreException(KeyStore2.java:428)
at android.security.KeyStoreSecurityLevel.handleExceptions(KeyStoreSecurityLevel.java:58)
at android.security.KeyStoreSecurityLevel.generateKey(KeyStoreSecurityLevel.java:149)
at android.security.keystore2.AndroidKeyStoreKeyPairGeneratorSpi.generateKeyPair(AndroidKeyStoreKeyPairGeneratorSpi.java:699)
... 12 more

at com.android.tradefed.testtype.junit4.BaseHostJUnit4Test.runDeviceTests(BaseHostJUnit4Test.java:755)
at com.android.tradefed.testtype.junit4.BaseHostJUnit4Test.runDeviceTests(BaseHostJUnit4Test.java:486)
at com.google.android.gts.security.AttestationRootHostTest.runMethod(AttestationRootHostTest.java:263)
at com.google.android.gts.security.AttestationRootHostTest.testRsaAttestationChainTee(AttestationRootHostTest.java:134)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:61)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.runChild(DeviceJUnit4ClassRunner.java:111)
at com.android.tradefed.testtype.DeviceJUnit4ClassRunner.runChild(DeviceJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)

分析记录:此案例主要原因就是CSR无法上传到google服务器,接下来针对这个问题进行说明,主要有如下几个步骤

步骤一:生成attestation id
bash 复制代码
C:\Users\pengcheng.ding>adb root
restarting adbd as root
C:\Users\pengcheng.ding>adb shell
SH4-1:/ # LD_LIBRARY_PATH=/vendor/lib64/hw KmInstallKeybox 1 1 true rkp
qmi_client_send_msg_sync success for get dev_ser_num 0
qmi_client_send_msg_sync success for get dev_ser_num 1
Brand: Ascom
Device: SH4-1
Product: SH4-ABCE
SerialNum: 532c7d54
Manufacturer: Ascom
Model: Myco 4 Slim Cellular Wi-Fi
TEE done
InstallKeybox is done!
SH4-1:/ # exit
步骤二:结合高通命令生成CSR
bash 复制代码
C:\Users\pengcheng.ding>adb shell /vendor/bin/rkp_factory_extraction_tool64 --output_format build+csr --allow_degenerate default > dpc_csr.json
Bundle extraction failed for 'widevine'. Description: Status(-8, EX_SERVICE_SPECIFIC): '1: Failed to parse the verified device info cbor.'.
Unable to build CSR for 'android.hardware.drm.IDrmFactory/widevine': Status(-8, EX_SERVICE_SPECIFIC): '1: Failed to parse the verified device info cbor.', exiting.
C:\Users\pengcheng.ding>type dpc_csr.json
{"build_fingerprint":"Ascom/SH4-ABCE/SH4-1:16/BQ2A.260103.001-BP2A.250705.008/eng.androi:userdebug/release-keys","csr":"hQGggqUBAQMnIAYEgQIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLIRDoQEnoFhYpAFpUVVBTENPTU0AAm9SS1AgRGV2aWNlIEtleQA6AEdEV1gtpQEBAycgBgSBAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwsOgBHRFhBIFhA6nUjlIL12YLLjGdSP3mUvTTbz1gSjOGox6gqcESFcMmD7yGGCmnVnepWk/yo78mjCUvumfzzbKgT+mhtke3nDYRDoQEnoFkBfYJYQOF1q9lxMkzqKCuH711d9t678eUP/2qvHt10d/RQTGDadDPS1WYD4ym+kmKU6zWFgfPS0+iWws/LtI3ozk/cKF9ZATeEA2drZXltaW50rmVicmFuZGVBc2NvbWVmdXNlZAFlbW9kZWx4Gk15Y28gNCBTbGltIENlbGx1bGFyIFdpLUZpZmRldmljZWVTSDQtMWdwcm9kdWN0aFNINC1BQkNFaHZiX3N0YXRlZm9yYW5nZWpvc192ZXJzaW9uZjE2MDAwMGxtYW51ZmFjdHVyZXJlQXNjb21tdmJtZXRhX2RpZ2VzdFgg//2vigkltzjPJmhSudF7E7TXHu5/uqgI0gKRuvV7i6Vuc2VjdXJpdHlfbGV2ZWxjdGVlcGJvb3RfcGF0Y2hfbGV2ZWwaATUl0XBib290bG9hZGVyX3N0YXRlaHVubG9ja2VkcnN5c3RlbV9wYXRjaF9sZXZlbBoAAxdrcnZlbmRvcl9wYXRjaF9sZXZlbBoBNSXRgFhAeNyMnZZp0ElR0od+rBpTU9sAfpiM8CcR/reVkupNt5WPcsy0l3RpEHgJo8sXyti8++fdsJeAxKEgV52L3rGtAKFrZmluZ2VycHJpbnR4WUFzY29tL1NINC1BQkNFL1NINC0xOjE2L0JRMkEuMjYwMTAzLjAwMS1CUDJBLjI1MDcwNS4wMDgvZW5nLmFuZHJvaTp1c2VyZGVidWcvcmVsZWFzZS1rZXlz","name":"default","serialno":"532c7d54"}
步骤三:上传CSR到google服务器报格式错误
bash 复制代码
C:\Users\junhui.li>python device_info_uploader.py --credentials cred.json --json-csr csr.json --cache-token --company-id 1398696844
1/1: Uploading batch containing 1 csr(s)
Opening your web browser to authenticate...
Waiting for a response from the Google OAuth service.
If you receive an error in your browser, interrupt this script.
GET path: /?iss=https://accounts.google.com&code=4/0AfrIepAEdNjMkwQe8chGTin-Tpe6a1CRjqcrxd2YjVHCgvb4mTCvWRscqW4x5iuxxhvbfg&scope=https://www.googleapis.com/auth/androidPartner
127.0.0.1 - - [06/Mar/2026 15:38:01] "GET /?iss=https://accounts.google.com&code=4/0AfrIepAEdNjMkwQe8chGTin-Tpe6a1CRjqcrxd2YjVHCgvb4mTCvWRscqW4x5iuxxhvbfg&scope=https://www.googleapis.com/auth/androidPartner HTTP/1.1" 200 -
Batch API response:{
  "errors": [
    {
      "certificatePayload": {
        "certificateSigningRequest": "hQGggqUBAQMnIAYEAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwshEOhASegWFekAWlRVUFMQ09NTQACb1JLUCBEZXZpY2UgS2V5ADoAR0RXWCylAQEDJyAGBAIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLDoAR0RYQSBYQEznD5bkSImf9ltxKjkY+4GM0lkJPFVBKp7yI7tq0LPCiC/19Iy5kYJwDXQ6/KwJo1ZoN0qm4F6i4v2UEkEuTwKEQ6EBJ6BZAW6CWEBHdIwMNGChnnMEyXj062qnz3habMIFmR1XMoIobyxFPrueKHPUTLu/tb1Gv1IEx2XqwdYubXfKV+WChea8z1epWQEohANna2V5bWludK5lYnJhbmRlQXNjb21lZnVzZWQBZW1vZGVsbE15Y28gNCBXaS1GaWZkZXZpY2VlU0g0LTJncHJvZHVjdGhTSDQtQUFCQ2h2Yl9zdGF0ZWZvcmFuZ2Vqb3NfdmVyc2lvbmYxNjAwMDBsbWFudWZhY3R1cmVyZUFzY29tbXZibWV0YV9kaWdlc3RYIEyi4i/PAPXjWjH9vi8dE3L0gnmHZincp0yvXCXT7piJbnNlY3VyaXR5X2xldmVsY3RlZXBib290X3BhdGNoX2xldmVsGgE1JW1wYm9vdGxvYWRlcl9zdGF0ZWh1bmxvY2tlZHJzeXN0ZW1fcGF0Y2hfbGV2ZWwaAAMXanJ2ZW5kb3JfcGF0Y2hfbGV2ZWwaATUlbYBYQOUnv3I/OR2h8O+ZwSpfxJ2zfSlEquD4lomMg+/vgVcMS1D7nA8PxIfvdE2HrVv+xqFkUSl6PZyyI51p89asGwOha2ZpbmdlcnByaW50eFxBc2NvbS9TSDQtQUFCQy9TSDQtMjoxNi9CUTJBLjI1MTEyNS4wMDEtQlAyQS4yNTA2MDUuMDMxLkEzL0ExNl8wMDEuMDA6dXNlcmRlYnVnL3JlbGVhc2Uta2V5cw=="
      },
      "status": {
        "code": 3,
        "message": "Can't deserialize certificate signing requests during registration. Please make sure that your CSR is not corrupted: Couldn't parse Signing CoseKey (Ec2SigningKey/OkpSigningKey) from provided cbor"
      }
    }
  ],
  "requestId": "ec74b12e-54c9-4053-9ef6-e8faf00b331e"
}

Errors occurred when uploading csrs: 200
{
  "errors": [
    {
      "certificatePayload": {
        "certificateSigningRequest": "hQGggqUBAQMnIAYEAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwshEOhASegWFekAWlRVUFMQ09NTQACb1JLUCBEZXZpY2UgS2V5ADoAR0RXWCylAQEDJyAGBAIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLDoAR0RYQSBYQEznD5bkSImf9ltxKjkY+4GM0lkJPFVBKp7yI7tq0LPCiC/19Iy5kYJwDXQ6/KwJo1ZoN0qm4F6i4v2UEkEuTwKEQ6EBJ6BZAW6CWEBHdIwMNGChnnMEyXj062qnz3habMIFmR1XMoIobyxFPrueKHPUTLu/tb1Gv1IEx2XqwdYubXfKV+WChea8z1epWQEohANna2V5bWludK5lYnJhbmRlQXNjb21lZnVzZWQBZW1vZGVsbE15Y28gNCBXaS1GaWZkZXZpY2VlU0g0LTJncHJvZHVjdGhTSDQtQUFCQ2h2Yl9zdGF0ZWZvcmFuZ2Vqb3NfdmVyc2lvbmYxNjAwMDBsbWFudWZhY3R1cmVyZUFzY29tbXZibWV0YV9kaWdlc3RYIEyi4i/PAPXjWjH9vi8dE3L0gnmHZincp0yvXCXT7piJbnNlY3VyaXR5X2xldmVsY3RlZXBib290X3BhdGNoX2xldmVsGgE1JW1wYm9vdGxvYWRlcl9zdGF0ZWh1bmxvY2tlZHJzeXN0ZW1fcGF0Y2hfbGV2ZWwaAAMXanJ2ZW5kb3JfcGF0Y2hfbGV2ZWwaATUlbYBYQOUnv3I/OR2h8O+ZwSpfxJ2zfSlEquD4lomMg+/vgVcMS1D7nA8PxIfvdE2HrVv+xqFkUSl6PZyyI51p89asGwOha2ZpbmdlcnByaW50eFxBc2NvbS9TSDQtQUFCQy9TSDQtMjoxNi9CUTJBLjI1MTEyNS4wMDEtQlAyQS4yNTA2MDUuMDMxLkEzL0ExNl8wMDEuMDA6dXNlcmRlYnVnL3JlbGVhc2Uta2V5cw=="
      },
      "status": {
        "code": 3,
        "message": "Can't deserialize certificate signing requests during registration. Please make sure that your CSR is not corrupted: Couldn't parse Signing CoseKey (Ec2SigningKey/OkpSigningKey) from provided cbor"
      }
    }
  ],
  "requestId": "ec74b12e-54c9-4053-9ef6-e8faf00b331e"
}

Refer to https://docs.partner.android.com/gms/building/integrating/att-keys/rkp-errors for detailed explanations of each error code.

如上秘钥上传到google服务器,google服务器解析报错,高通说google问题,google也不知道找高通去看,最后我把这个秘钥丢给了扣子空间进行解析,得出了如下结论:

最后结论是秘钥算法是符合要求,但是组装的格式不太对,可能是keymaster返回的数据异常,给到高通之后,高通提供了新的keymint.mbn文件,重新生成,再次上传google服务器:

步骤四:更新高通keymint文件上传CSR到google服务器
bash 复制代码
C:\Users\junhui.li>python device_info_uploader.py --credentials cred.json --json-csr dpc_csr.json --company-id=1398696844 --verbose
1/1: Uploading batch containing 1 csr(s)
request body:
{'device_payloads': [{'certificate_payloads': [

{'certificate_signing_request': 'hQGggqUBAQMnIAYEgQIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLIRDoQEnoFhYpAFpUVVBTENPTU0AAm9SS1AgRGV2aWNlIEtleQA6AEdEV1gtpQEBAycgBgSBAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwsOgBHRFhBIFhA6nUjlIL12YLLjGdSP3mUvTTbz1gSjOGox6gqcESFcMmD7yGGCmnVnepWk/yo78mjCUvumfzzbKgT+mhtke3nDYRDoQEnoFkBfYJYQOF1q9lxMkzqKCuH711d9t678eUP/2qvHt10d/RQTGDadDPS1WYD4ym+kmKU6zWFgfPS0+iWws/LtI3ozk/cKF9ZATeEA2drZXltaW50rmVicmFuZGVBc2NvbWVmdXNlZAFlbW9kZWx4Gk15Y28gNCBTbGltIENlbGx1bGFyIFdpLUZpZmRldmljZWVTSDQtMWdwcm9kdWN0aFNINC1BQkNFaHZiX3N0YXRlZm9yYW5nZWpvc192ZXJzaW9uZjE2MDAwMGxtYW51ZmFjdHVyZXJlQXNjb21tdmJtZXRhX2RpZ2VzdFgg//2vigkltzjPJmhSudF7E7TXHu5/uqgI0gKRuvV7i6Vuc2VjdXJpdHlfbGV2ZWxjdGVlcGJvb3RfcGF0Y2hfbGV2ZWwaATUl0XBib290bG9hZGVyX3N0YXRlaHVubG9ja2VkcnN5c3RlbV9wYXRjaF9sZXZlbBoAAxdrcnZlbmRvcl9wYXRjaF9sZXZlbBoBNSXRgFhAeNyMnZZp0ElR0od+rBpTU9sAfpiM8CcR/reVkupNt5WPcsy0l3RpEHgJo8sXyti8++fdsJeAxKEgV52L3rGtAKFrZmluZ2VycHJpbnR4WUFzY29tL1NINC1BQkNFL1NINC0xOjE2L0JRMkEuMjYwMTAzLjAwMS1CUDJBLjI1MDcwNS4wMDgvZW5nLmFuZHJvaTp1c2VyZGVidWcvcmVsZWFzZS1rZXlz'}
]}], 'company_id': '1398696844', 'is_test': False}
Opening your web browser to authenticate...
Waiting for a response from the Google OAuth service.
If you receive an error in your browser, interrupt this script.
GET path: /?iss=https://accounts.google.com&code=4/0Aci98E-WSBq5vxyGljCIiNEXuSrmOPepkDwJKHJNpoHJqAfJO4oLfs8EuMtl4b-DZjo5lA&scope=https://www.googleapis.com/auth/androidPartner
127.0.0.1 - - [15/Apr/2026 21:32:44] "GET /?iss=https://accounts.google.com&code=4/0Aci98E-WSBq5vxyGljCIiNEXuSrmOPepkDwJKHJNpoHJqAfJO4oLfs8EuMtl4b-DZjo5lA&scope=https://www.googleapis.com/auth/androidPartner HTTP/1.1" 200 -
Batch API response:{
"errors": [
{
"certificatePayload":

{ "certificateSigningRequest": "hQGggqUBAQMnIAYEgQIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLIRDoQEnoFhYpAFpUVVBTENPTU0AAm9SS1AgRGV2aWNlIEtleQA6AEdEV1gtpQEBAycgBgSBAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwsOgBHRFhBIFhA6nUjlIL12YLLjGdSP3mUvTTbz1gSjOGox6gqcESFcMmD7yGGCmnVnepWk/yo78mjCUvumfzzbKgT+mhtke3nDYRDoQEnoFkBfYJYQOF1q9lxMkzqKCuH711d9t678eUP/2qvHt10d/RQTGDadDPS1WYD4ym+kmKU6zWFgfPS0+iWws/LtI3ozk/cKF9ZATeEA2drZXltaW50rmVicmFuZGVBc2NvbWVmdXNlZAFlbW9kZWx4Gk15Y28gNCBTbGltIENlbGx1bGFyIFdpLUZpZmRldmljZWVTSDQtMWdwcm9kdWN0aFNINC1BQkNFaHZiX3N0YXRlZm9yYW5nZWpvc192ZXJzaW9uZjE2MDAwMGxtYW51ZmFjdHVyZXJlQXNjb21tdmJtZXRhX2RpZ2VzdFgg//2vigkltzjPJmhSudF7E7TXHu5/uqgI0gKRuvV7i6Vuc2VjdXJpdHlfbGV2ZWxjdGVlcGJvb3RfcGF0Y2hfbGV2ZWwaATUl0XBib290bG9hZGVyX3N0YXRlaHVubG9ja2VkcnN5c3RlbV9wYXRjaF9sZXZlbBoAAxdrcnZlbmRvcl9wYXRjaF9sZXZlbBoBNSXRgFhAeNyMnZZp0ElR0od+rBpTU9sAfpiM8CcR/reVkupNt5WPcsy0l3RpEHgJo8sXyti8++fdsJeAxKEgV52L3rGtAKFrZmluZ2VycHJpbnR4WUFzY29tL1NINC1BQkNFL1NINC0xOjE2L0JRMkEuMjYwMTAzLjAwMS1CUDJBLjI1MDcwNS4wMDgvZW5nLmFuZHJvaTp1c2VyZGVidWcvcmVsZWFzZS1rZXlz" }
,
"status":

{ "code": 6, "message": "This CSR was not uploaded. Device public key (o\u001d+ɣ]4\u0005;g 6Va z3 1 Ŷ \\,) already exists. Please call BatchUpdate to modify an existing key's data." }
}
],
"requestId": "fb4fb6e0-eefb-4c6d-9f91-c803e2ae2372"
}

Errors occurred when uploading csrs: 200
{
"errors": [
{
"certificatePayload":

{ "certificateSigningRequest": "hQGggqUBAQMnIAYEgQIhWCBvHSvJo100BTtnqa2ciDZWYejHejObmtcx9qXFto1cLIRDoQEnoFhYpAFpUVVBTENPTU0AAm9SS1AgRGV2aWNlIEtleQA6AEdEV1gtpQEBAycgBgSBAiFYIG8dK8mjXTQFO2eprZyINlZh6Md6M5ua1zH2pcW2jVwsOgBHRFhBIFhA6nUjlIL12YLLjGdSP3mUvTTbz1gSjOGox6gqcESFcMmD7yGGCmnVnepWk/yo78mjCUvumfzzbKgT+mhtke3nDYRDoQEnoFkBfYJYQOF1q9lxMkzqKCuH711d9t678eUP/2qvHt10d/RQTGDadDPS1WYD4ym+kmKU6zWFgfPS0+iWws/LtI3ozk/cKF9ZATeEA2drZXltaW50rmVicmFuZGVBc2NvbWVmdXNlZAFlbW9kZWx4Gk15Y28gNCBTbGltIENlbGx1bGFyIFdpLUZpZmRldmljZWVTSDQtMWdwcm9kdWN0aFNINC1BQkNFaHZiX3N0YXRlZm9yYW5nZWpvc192ZXJzaW9uZjE2MDAwMGxtYW51ZmFjdHVyZXJlQXNjb21tdmJtZXRhX2RpZ2VzdFgg//2vigkltzjPJmhSudF7E7TXHu5/uqgI0gKRuvV7i6Vuc2VjdXJpdHlfbGV2ZWxjdGVlcGJvb3RfcGF0Y2hfbGV2ZWwaATUl0XBib290bG9hZGVyX3N0YXRlaHVubG9ja2VkcnN5c3RlbV9wYXRjaF9sZXZlbBoAAxdrcnZlbmRvcl9wYXRjaF9sZXZlbBoBNSXRgFhAeNyMnZZp0ElR0od+rBpTU9sAfpiM8CcR/reVkupNt5WPcsy0l3RpEHgJo8sXyti8++fdsJeAxKEgV52L3rGtAKFrZmluZ2VycHJpbnR4WUFzY29tL1NINC1BQkNFL1NINC0xOjE2L0JRMkEuMjYwMTAzLjAwMS1CUDJBLjI1MDcwNS4wMDgvZW5nLmFuZHJvaTp1c2VyZGVidWcvcmVsZWFzZS1rZXlz" }
,
"status":

{ "code": 6, "message": "This CSR was not uploaded. Device public key (o\u001d+ɣ]4\u0005;g 6Va z3 1 Ŷ \\,) already exists. Please call BatchUpdate to modify an existing key's data." }
}
],
"requestId": "fb4fb6e0-eefb-4c6d-9f91-c803e2ae2372"
}

Refer to https://docs.partner.android.com/gms/building/integrating/att-keys/rkp-errors for detailed explanations of each error code.
步骤五:这次上传报错不再是格式不对了,因此重新去跑了一下此条测试项:

此项不再是秘钥相关的错误,从日志打印来看,秘钥有效,但是未处于根设备的证书,即设备并没有在安全状态下,计划使用efus熔断并且lock的设备重新来跑这一条。

步骤六:最后了解到如上报错是Google XTS工具问题,因此使用PAB工具重新跑了此条测试项:
相关推荐
一起搞IT吧2 小时前
Android性能系列专题理论之十一:block IO问题分析思路
android·嵌入式硬件·智能手机·性能优化
小妖6662 小时前
怎么用 tauri 创建编译 android 应用程序
android·tauri
鸟儿不吃草3 小时前
安卓实现左右布局聊天界面
android·开发语言·python
xxjj998a5 小时前
Laravel 1.x:PHP框架的原始魅力
android·php·laravel
formula100005 小时前
在iOS/安卓上远程连接任何 Agent!Claude、Codex、Copilot、Gemini、OpenCode 等
android·copilot
该用户可能存在5 小时前
Blbl-android 更新至 v0.1.24,体验更流畅、更稳定
android·哔哩哔哩·电视app·androidtv·bbll·blbl·bilibilitv
lKWO OMET6 小时前
mysql之字符串函数
android·数据库·mysql
liang_jy16 小时前
Android SparseArray
android·源码
liang_jy16 小时前
Activity 启动流程扩展篇(一)—— startActivityInner 任务决策全解析
android·源码