安全分析
编者:厦门大学信息学院通信工程系2015级研究生:杨江河,阮晓杨,赖雅玲
源码目录位置:bdk/system/security/
1.概述
在Android中/system/ keystore进程提供了一个安全存储的服务。每一个Android用户都有一块其私有的安全存储区域。keystore是java的密钥库,用来进行通信加密,比如数字签名。同时keystore用来保存密钥对,比如公钥和私钥。所有秘钥信息使用一个随机key并用AES加密算法加密,加密好的密文采用另外一个key加密后保存到本地磁盘。在近期的一些Android版本中,证书管理(例如RSA算法的私有key)是可以通过专门的硬件做支持的。这也就是说,keystore的key只是用来标识存储在专有硬件上的真正key。Fig.1很好的阐述了keystore安全存储机制的工作原理。
Fig.1 The keystore service
2.Security目录重要文件框架
+--Keystore
| +--include
| +--test
| --keystore_main.cpp
| --keystore_cli_v2.cpp
+--keystore-engine
| --android_engine.cpp
| --keyhandle.cpp
+--softkeymaster
| +--include
| | --keymaster
| --softkeymaster
| --Android.mk
| --keymaster_openssl.cpp
| --module
--MODULE_LICENSE_APACHE2
--NOTICE
3.keystore主函数解释说明
*keystore_main.cpp
KeyStore是密钥对的安全容器。在这个工具中,每个文件储存在一个密钥对中。密钥被编码到文件中,键值用校验和加密。加密的键值被用户定义的密码保护。为了让事情变得简单,缓存总是大于所需的最大空间,所以缓存的边界检查总是被省略。
keymaster2_device_t* dev; if (keymaster_device_initialize(&dev)) { ALOGE("keystore keymaster could not be initialized; exiting"); return 1; }
密钥设备初始化
keymaster2_device_t* fallback; if (fallback_keymaster_device_initialize(&fallback)) { ALOGE("software keymaster could not be initialized; exiting"); return 1; }
回调密钥设备初始化程序
android::IPCThreadState::self()->joinThreadPool();
因为只存在一个进程,所以我们只能把处理绑定事物处理当成一个单线程程序
keymaster_device_release(dev);
删除密钥设备
KeyStore主要文件功能描述
文件名 | 功能描述 |
---|---|
auth_token_table.cpp | 基于标准算法的遍历模板封装以及授权的相关操作 |
blob.cpp | 二进制大文件的读写和,大小控制和加密控制 |
entropy.cpp | 加密算法的开启和随机数据的生成 |
IKeystoreService.cpp | Parcel数据的读写,Token接口数据的增加,删除,更新和列出 |
key_store_service.cpp | 密钥服务的增加,删除,更新显示;密钥服务的状态获取和重启 |
keyblob_utils.cpp | 获取软键头尺寸并添加软键头 |
keystore.cpp | 密钥库的构造和析构,密钥库的初始化以及管理键的复制和读写 |
keystore_cli_v2.cpp | 文件的读写和密钥的产生、删除和导出 |
keystore_client_impl.cpp | 主要是密钥库客户端实现的操作,包括生成随机数加密,导入、导出、生成、删除和列出密钥,加密算法采用AES-256-CBC,并且授权算法是HMAC-SHA256 |
keystore_get.cpp | 密钥库的获取 |
keystore_utils.cpp | 文件的读写,添加密钥授权以及APP和用户ID的获取 |
operation.cpp | 操作图的添加,获取,更新和移除 |
permissions.cpp | SELinux系统的配置,SELinux系统下密钥库的权限检查以及密钥库euid的获取 |
user_state.cpp | 用户状态的初始化、设置和重启;键值文件的复制以及从密码中生成密钥 |
4.Makefile文件分析
keystore-engine/Android.mk
LOCAL_PATH := $(call my-dir)
提示当前文件的路径,必须定义在文件开头 my-dir 返回当前Android.mk所在的目录路径。
include $(CLEAR_VARS)
CLEAR_VARS 变量由Build System提供。并指向一个指定的GNU Makefile,由它负责清理很多LOCAL_xxx.
例如:LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES等等。但不清理LOCAL_PATH.
这个清理动作是必须的,因为所有的编译控制文件由同一个GNU Make解析和执行,其变量是全局的。所以清理后才能避免相互影响。
ifneq (,$(wildcard $(TOP)/external/boringssl/flavor.mk))
include $(TOP)/external/boringssl/flavor.mk
else
include $(TOP)/external/openssl/flavor.mk
endif
如果boringssl/flavor.mk文件存在,则先读取/boringssl中的flavor.mk。
否则读取/openssl下的flavor.mk文件。
LOCAL_MODULE := libkeystore-engine
指定当前模块的名字为libkeystore-engine,这个模块名字是唯一的且不能被更改。
Build System会自动添加适当的前缀和后缀。例如:foo;要产生动态库则生成libfoo.so。 但请注意!如果模块名被定为:libfoo.则生成libfoo.so不再加前缀。
LOCAL_SRC_FILES := \
android_engine.cpp
指定当前模块所包含的文件为android_engine.cpp。 不必列出头文件,build System会自动帮我们找出依赖文件
LOCAL_C_INCLUDES+= \
external/openssl/include \
external/openssl
设置头文件的搜索路径,默认的头文件的搜索路径是LOCAL_PATH目录。
LOCAL_SHARED_LIBRARIES += \
libcrypto \
liblog \
libcutils \
libutils \
libbinder \
libkeystore_binder
表示模块在运行时要依赖的共享库(动态库),在链接时就需要,以便在生成文件时嵌入其相应的信息。
注意:它不会附加列出的模块到编译图,也就是仍然需要在Application.mk中把它们添加到程序要求的模块中。
LOCAL_MODULE_TAGS := optional
指定模块编译运行的版本,一共有四个选项:
user: 指该模块只在user版本下才编译
eng: 指该模块只在eng版本下才编译
tests: 指该模块只在tests版本下才编译
optional:指该模块在所有版本下都编译
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
增加额外的依赖 如果模块需要依靠一些并不直接建立的文件,就可以将这些编译标签加入到LOCAL_MODULE_TAGS里面去,通常这个是一些无法自动创建的附属工程文件。
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY:是Build System提供的一个变量,指向一个GNU Makefile Script。
它负责收集自从上次调用 include $(CLEAR_VARS) 后的所有LOCAL_XXX信息。并决定编译为什么。
softkeymaster/Android.mk
ifeq ($(USE_32_BIT_KEYSTORE), true)
LOCAL_MULTILIB := 32
endif
设置如果使用的是32位的静态库的时候,要将LOCAL_MULTILIB的值设置为32。
LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
一个可选的设置,在编译C/C++ source 时添加如Flags。
用来附加编译选项。 注意:不要尝试在此处修改编译的优化选项和Debug等级。它会通过您Application.mk中的信息自动指定。
也可以指定include 目录通过:LOCAL_CFLAGS += -I
keystore/Android.mk
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_CLASS 标识了所编译模块最后放置的位置,如果不指定,不会放到系统中,之后放在最后的obj目录下的对应目录中。
代码 | 注释 |
---|---|
LOCAL_MODULE_CLASS := ETC | #表示放于system/etc目录 |
LOCAL_MODULE_CLASS := EXECUTABLES | #放于/system/bin |
LOCAL_MODULE_CLASS := SHARED_LIBRARIES | #放在/system/lib下 |