android keystore源码分析

news/2025/2/27 5:57:23

架构

Android Keystore API 和底层 Keymaster HAL 提供了一套基本的但足以满足需求的加密基元,以便使用访问受控且由硬件支持的密钥实现相关协议。
Keymaster HAL 是由原始设备制造商 (OEM) 提供的动态加载库,密钥库服务使用它来提供由硬件支持的加密服务。为了确保安全性,HAL 实现不会在用户空间乃至内核空间中执行任何敏感操作。敏感操作会被分配给通过某个内核接口连接的安全处理器。 最终的架构如下所示:
访问 Keymaster

源码分析

源码分析基于Android 9.0

####AndroidKeyStore服务提供者

img

应用层调用时provider必须指明为"AndroidKeyStore",否则默使用的是BC库。

Android KeyStore 是Java 安全框架的一个提供者的实现,类名为AndroidKeyStoreProvider.java。

此类中定义了一些引擎类的实现:

  • AndroidKeyStoreSpi 存储服务
  • AndroidKeyStoreKeyPairGeneratorSpi$EC ECC密钥对生成
  • AndroidKeyStoreKeyPairGeneratorSpi$RSA RSA密钥对生成

等等,这部分的代码在

/frameworks/base/keystore/java/android/security/keystore/

这些引擎类的实现内部有一个android.security.KeyStore对象。此对象是一个binder代理。通过binder通信转到系统服务的KeyStoreSerivce。

KeyStoreService服务

服务代码在/system/security/keystore/key_store_service.cpp

KeyStoreService 内部持有一个KeyStore对象,

代码在/system/security/keystore/KeyStore.cpp

KeyStore对象内部持有一个device,此device是KeymasterDevices,此对象是三个Keymaster的数组,分别对应软实现、TEE实现和SE实现。如果是TEE实现的话,keymaster hal 应该就是CA程序。

当系统启动时会加载keymaster hal的实现,并把他注册到硬件的servicemanager 中。

keymaster hal

keymaster hal的注册,这里是安卓模拟器goldfish中的服务注册示例。

Cross Reference: /device/generic/goldfish/keymaster/strongbox/service.cpp


int main() {
    ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);

    using android::hardware::keymaster::V4_0::SecurityLevel;
    using ::keymaster::V4_0::ng::CreateKeymasterDevice;

    /*
     * Create two software keymaster devices claiming different security levels for testing
     * purposes. They do not have the certificates of real TEE or Strongbox keymaster devices.
     */
    auto keymaster = CreateKeymasterDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
    auto status = keymaster->registerAsService("default");
    if (status != android::OK) {
        LOG(FATAL) << "Could not register default service for Keymaster 4.0 (" << status << ")";
    }

    auto strongbox = CreateKeymasterDevice(SecurityLevel::STRONGBOX);
    status = strongbox->registerAsService("strongbox");
    if (status != android::OK) {
        LOG(FATAL) << "Could not register strongbox service for Keymaster 4.0 (" << status << ")";
    }

    android::hardware::joinRpcThreadpool();
    return -1;  // Should never get here.
}

keymaster枚举

Cross Reference: /system/security/keystore/keystore_main.cpp

KeymasterDevices enumerateKeymasterDevices(IServiceManager* serviceManager) {
    KeymasterDevices result;
    serviceManager->listByInterface(
        Wrapper::WrappedIKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {})
}

通过枚举获取keymaster的实现。构造keystore对象。

keymaster hal实现最终通过调用安全环境实现密钥生成、加密解密、签名验签。

keymaster 实现的接口定义如下。厂商只要按照规范要求实现此接口即可。

Cross Reference: /hardware/interfaces/keymaster/3.0/IKeymasterDevice.hal

Cross Reference: /hardware/interfaces/keymaster/4.0/IKeymasterDevice.hal

Android Keystore 机制总结

Android Keystore 提供安全的密钥管理和加密操作,其核心机制涉及多进程协作和跨空间调用。以下是关键组件及其交互流程:


重要类与组件
类/组件所在进程运行空间描述
android.security.KeyStore应用进程(如App进程)用户空间应用层API,提供密钥生成、存储等接口。开发者通过此类访问Keystore功能。
KeyStoreServicekeystore进程用户空间系统服务,处理应用请求,管理密钥生命周期,通过Binder与客户端通信。
KeymasterHAL (HIDL接口)厂商HAL进程(如vendor.some.process用户空间硬件抽象层接口,由厂商实现,执行加密操作(如密钥生成、签名)。
内核驱动(如/dev/keymaster内核内核空间与硬件安全模块(HSM/TEE/StrongBox)通信,处理安全环境内的敏感操作。

调用流程与通信机制
  1. 应用层调用
    • 进程: 应用进程 → keystore
    • 机制: Binder IPC
      • 应用通过 android.security.KeyStore 发起请求(如生成密钥)。
      • 调用通过 Binder 传递至 KeyStoreService(运行在 keystore)。
  2. 系统服务处理
    • 进程: keystore → 厂商HAL进程
    • 机制: HIDL/AIDL IPC
      • KeyStoreService 将请求转换为 Keymaster 操作(如调用 generateKey)。
      • 通过 HIDL 接口(如 IKeymasterDevice)与厂商的 KeymasterHAL 实现通信。
  3. 硬件抽象层执行
    • 进程: 厂商HAL进程 → 内核
    • 机制: 系统调用(ioctl)
      • KeymasterHAL 通过 ioctl 调用内核驱动(如 /dev/keymaster)。
      • 驱动将操作转发至安全环境(如 TEE 或 StrongBox)。
  4. 安全环境操作
    • 空间: 内核 → TEE/HSM
    • 机制: SMC指令或安全监控调用
      • 内核驱动通过安全机制(如 ARM TrustZone 的 SMC)触发安全环境内的操作。
      • 密钥在安全环境内生成/使用,不会暴露到非安全内存。

关键点总结
  • 用户空间与内核空间协作:敏感操作(如密钥生成)最终由安全环境(TEE/HSM)处理,确保密钥不泄露至普通内存。
  • 跨进程通信
    • Binder:用于应用与系统服务的高效通信。
    • HIDL/AIDL:解耦系统服务与厂商实现,支持向前兼容。
  • 安全边界:内核驱动作为用户空间与安全环境的桥梁,通过严格权限控制保障隔离性。
[应用进程] --Binder--> [keystore进程] --HIDL--> [KeymasterHAL进程] --ioctl--> [内核驱动] --> [TEE/HSM]
  ↑                       |                         |
  | (android.security.KeyStore) | (KeyStoreService)  | (厂商实现)
 用户空间                  用户空间                  用户空间              内核空间

应用代码示例

                 try {
                        final String KEY_ALIAS = "myKeyAliasx";
                        KeyStore keyStore;
                        keyStore = KeyStore.getInstance("AndroidKeyStore");
                        keyStore.load(null);

                        // 检查密钥是否已存在,如果不存在则生成新的密钥对
                        if (!keyStore.containsAlias(KEY_ALIAS)) {
                            //生成密钥
                            KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
                                    KEY_ALIAS,
                                    KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
                                    .setDigests(KeyProperties.DIGEST_SHA256)
                                    .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS)
                                    .setKeySize(2048)
                                    .build();

                            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
                                    KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
                            keyPairGenerator.initialize(spec);
                            KeyPair keyPair = keyPairGenerator.generateKeyPair();


                        }
                        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(
                                KEY_ALIAS, null);
                        PrivateKey privateKey = privateKeyEntry.getPrivateKey();
                        KeyFactory factory = KeyFactory.getInstance(privateKey.getAlgorithm(), "AndroidKeyStore");
                        KeyInfo keyInfo;
                        //获取密钥信息
                        keyInfo = factory.getKeySpec(privateKey, KeyInfo.class);
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                            int securityLevel = keyInfo.getSecurityLevel();
                            if (securityLevel == KeyProperties.SECURITY_LEVEL_TRUSTED_ENVIRONMENT

                            ) {
                                System.out.println("key is in trusted environment");
                            } else if (securityLevel == KeyProperties.SECURITY_LEVEL_STRONGBOX) {
                                System.out.println("key is in strongbox");
                            } else {
                                System.out.println("key is in software");
                            }
                        } else {
                            boolean insideSecureHardware = keyInfo.isInsideSecureHardware();
                            System.out.println("insideSecureHardware=" + insideSecureHardware);
                        }
                        // 签名
                        Signature signature = Signature.getInstance("SHA256withRSA/PSS");
                        signature.initSign(privateKey);
                        signature.update("adgfdfd".getBytes("UTF-8"));
                        byte[] sign = signature.sign();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

http://www.niftyadmin.cn/n/5869587.html

相关文章

OpenCV计算摄影学(3)CUDA 图像去噪函数fastNlMeansDenoising()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 使用非局部均值去噪算法&#xff08;Non-local Means Denoising algorithm&#xff09;执行图像去噪&#xff0c;该算法来源于 http://www.ipol.…

【错误记录】Arrays.asList 的坑

文章目录 概要原因小结 概要 最近在写一个需求的时候用到了这个方法生成一个 List&#xff0c;接着再往里面添加数据的时候就报错了&#xff0c;比如下面的例子。 public class Main {public static void main(String[] args) {List<Integer> res Arrays.asList(1, 2,…

apache-maven-3.2.1

MAVEN_HOME D:\apache-maven-3.2.1 PATH D:\apache-maven-3.2.1\bin cmd mvn -v <localRepository>d:\localRepository</localRepository> setting.xml <?xml version"1.0" encoding"UTF-8"?><!-- Licensed to the Apache Soft…

java23种设计模式-中介者模式

中介者模式&#xff08;Mediator Pattern&#xff09;学习笔记 编程相关书籍分享&#xff1a;https://blog.csdn.net/weixin_47763579/article/details/145855793 DeepSeek使用技巧pdf资料分享&#xff1a;https://blog.csdn.net/weixin_47763579/article/details/145884039 1.…

卡 bug 了?

与工作搭子的日常&#xff1a; 远光小天&#xff1a; 卡 bug&#xff1f;不存在的&#xff01; 这是三岁孩童的正确打开方式&#xff5e; Tips&#xff1a; 远光小天是基于九天研发大模型面向企业研发用户打造的一体化 AI 研发解决方案。基于通用大模型底座&#xff0c;通过模型…

小折叠手机变身老式掌上电脑,Clicks推出新款外置QWERTY键盘

在科技飞速发展的今天,手机的形态和功能日新月异,直板大屏触控手机一统天下,虚拟键盘成为了我们与手机交互的主要方式。但你是否偶尔会怀念曾经那个按动实体按键,噼里啪啦打字的时代?嘿,还真就有人懂你的这份“复古情怀”,这不,Clicks推出了新款外置QWERTY键盘,直接让…

uniapp 测试 IPA 包安装到测试 iPhone

将uniapp测试IPA包安装到测试iPhone有以下几种方法&#xff1a; 使用Xcode安装 确保计算机上安装了Xcode&#xff0c;并将iOS设备通过数据线连接到计算机。打开Xcode&#xff0c;在菜单栏中选择Window->Devices and Simulators&#xff0c;在设备列表中找到要安装的iPhone…

基于帧差分法的车辆检测系统(Matlab)

基于帧差分法的视频目标检测系统&#xff08;Matlab&#xff09; Matlab车辆行驶检测与定位&#xff08;可用于车辆&#xff09; 【完整源码GUI界面&#xff0c;可根据需求帮改界面内容】 【可作报告和伦纹PPT等资料】 需要可随时联系博主&#xff0c;常在线能秒回&#xff01…