什么是Keybox
Android O 开始谷歌要求每台机器预制谷歌提供的 Attestion Key的需求,该需求要求,每台机器都预制谷歌提供的 key,因此需要 oem 厂商在工厂完成预制。没有预制该key 将直接导致机器 cts 相关测试项失败。Google attestation key的集合又称作为Google keybox。不同的attestation key通过DeviceID 来区分,在配置时选择不同的 DeviceID 可以进行不同的 attestion key 配置。Keybox包含若干组key, 每组key包含了ECDSA和RSA两种算法,KmInstallKeybox将每组key写入到手机的安全内存中,已知的地方有RPMB和Persist分区;
当Google GSM app或第三方APP需要使用key时,调用keymaster接口,使用该key进行签名、认证等。
每条 Attestion key 由两条证书链组成,分别对应算法为 ECDSA和 RSA,证书链包括一个私钥和三级证书,以ECDSA算法为例,具体形式如下,其中有一个私钥和三组证书,具体内容如下:
通常我们会向Google申请keybox,结合可能得出货量,提供如下信息给到的Google。
1. fingerprint : branch/deivce/product/user/build
2. device id 列表 : 这里的device id是一个临时定义的名称。
举个例子,我预计将要生产1KK的设备,并销往欧美。那么需要为10个device id申请keybox。由于单个device id的keybox可以生产并安装在100K的设备上,那么我们需要10个这样的device id。逻辑上讲,一种类型的设备,我为什么需要不同的device id?这里确实是个知识点,晚点提个google case 问一下。
Keybox内容
这里的DeviceID对应keybox中的DeviceID,通常就是对应key的名称。简单看一个我最新申请的keybox内容和简单的标注。
目前是单个Devcice ID可以在100K的设备上安装同一个keybox。那么n个Device ID也就是对应n*100K的设备。
Keybox 安装
KmInstallKeybox
由于使用的是QC code中自带的命令工具:KmInstallKeybox.
安装前提条件(RPMB 初始化)
在预制 attestion key 前需要保证 RPMB 已经初始化,否则 RPMB 无法使用会导致预制key 功能失效。
初始化 RPMB(手机连接电脑,确保 adb 可以使用)
adb root
adb shell
qseecom_sample_client smple64 v 14 1
一般情况下,安装步骤如下:
- adb root
- adb push keybox.xml data/
- adb shell LD_LIBIRARY_PATH=/vendor/lib64/hw KmInstallKeybox data/keybox.xml DeviceID false // 一共是5个参数,0,1,2,3,4
KminstallKeybox代码内容
using namespace keymasterdevice;
int main(int argc, char** argv) {if ((argc != 4) && (argc != 5) && (argc != 7) && (argc != 8)) {cout << "usage: LD_LIBRARY_PATH=/vendor/lib64/hw KmInstallKeybox Keybox_file Device_ID ""provision_device_ids(true/false)""Strongbox_Keybox_file Strongbox_Device_ID ""strongbox_provision_device_ids(true/false)"<< endl;cout << "e.g.,: LD_LIBRARY_PATH=/vendor/lib64/hw KmInstallKeybox keybox.xml ""mfgID_xxxx_0000 true""strongbox_keybox.xml strongbox_mfgID_xxxx_0000 true"<< endl;cout << "KmInstallKeybox will install the attestation""keys (both RSA and ECC) along with all the device identifiers\n""(brand, device, product, serial#, IMEI, MEID (if available), model""and manufacturer).\n""\n""The tool will use KM HAL API's to genrate RSA / ECC keys and\n""verify the attestation certificate signed with the provisioned keys.\n""If the validation is successful, the tool will set 'Provisioning Success'""to KM TA / KM Strongbox.\n""Else all the provisioned keys are deleted and it can be re-provisioned""\n""Once 'Provisioning Success' state is set in KM TA / Strongbox,\n""attestation keys / Device ID's cannot be re-provisioned\n""\n""\n""**RMA Use Case **\n""For RMA use case, OEM's can set the following devcfg parameter in ""'keymaster_oem_config.xml'\n""Please ensure to sign this debug devcfg with the serial# of the device as this ""will enable\n""re-provisioning of keys and if used incorrectly can open up the device to be ""re-provisioned.\n""<props name=\"allow_reprovision\" type=DALPROP_ATTR_TYPE_UINT32>\n""1""Strongbox provisioning is optional and is only supported on chipsets SPU/ ""strongbox is supported."<< endl;exit(-1);}std::string deviceId(argv[2]);// TEEbool provision_device_id = false;if (!memcmp(argv[3], "true", strlen("true")))provision_device_id = true;else if (!memcmp(argv[3], "false", strlen("false")))provision_device_id = false;elsereturn GENERIC_FAILURE;bool provision_only_device_id = false;if (argc==5 && !memcmp(argv[4], "rkp", strlen("rkp")))provision_only_device_id = true;else if (argc==8 && !memcmp(argv[7], "rkp", strlen("rkp")))provision_only_device_id = true;int ret = GENERIC_FAILURE;// This is required only for offtarget emulator, will be compiled out.SetUpOffTarget();KeymasterHalDevice device(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);SetUpOffTargetConfig(&device, 0, 0, 0);InstallKeybox installer(argv[1], deviceId, provision_device_id,KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);PROV_EXIT(installer.ParseFile(provision_only_device_id));if (!provision_only_device_id)PROV_EXIT(installer.ValidateProvisionedKeys());cout << "TEE done" << endl;if (argc == 7 || argc == 8) {std::string deviceIdSb(argv[5]);// SBbool provision_device_sb_id = false;if (!memcmp(argv[6], "true", strlen("true")))provision_device_sb_id = true;else if (!memcmp(argv[6], "false", strlen("false")))provision_device_sb_id = false;elsereturn GENERIC_FAILURE;InstallKeybox installer_sb(argv[4], deviceIdSb, provision_device_sb_id,keymaster::KM_SECURITY_LEVEL_STRONGBOX);PROV_EXIT(installer_sb.ParseFile(false));PROV_EXIT(installer_sb.ValidateProvisionedKeys());}cout << "InstallKeybox is done!" << endl;return 0;
}
针对这个工具,其实我们也可以结合实际进行定制。
Attestation Key的相关使用
简单例子如下:
// 导入相关库
import android.hardware.biometrics.BiometricManager;
import android.security.KeyCharacteristics;
import android.security.keystore.KeyProperties;
import android.util.Base64;// ...
BiometricManager biometricManager = BiometricManager.from(context);
KeymasterArguments keygenArgs = new KeymasterArguments.Builder().setOperation(KeymasterOperation.KEY_GEN).setAlias("my_key").setLabels("application-specific", "encryption").setKeyProperties(new KeyProperties.Builder().setAlgorithm(KeyProperties.AES).setKeySize(256).setUserAuthenticationRequired(true).build()).build();// 请求用户输入密码
String password = getPasswordFromUser();// 执行密钥生成
try {KeymasterOperationResult result = KeymasterHelper.generateKey(context, keygenArgs, password);if (result.getResult()) {// 如果成功,获取并保存密钥byte[] key = result.getKey();String encryptedData = Base64.encodeToString(encryptData(key), Base64.DEFAULT);saveEncryptedDataToFile(encryptedData);} else {handleEncryptionError(result.getErrorCode());}
} catch (Exception e) {logError(e);
}