前言:
这是一篇关于Android安全的翻译,这是原文地址。接上一篇翻译。这一篇主要讲述了密钥和证书的后台服务,IKeyChainService.aidl
的实现:KeyChain.apk
,以及密钥和证书的访问权限管理,授权数据库的维护。
我会一段一段地复制原文,然后在下面给出翻译,如有图片,我会重新保存再上传,以免出现“图片无法显示的情况”。
原文:
ICS Credential Storage Implementation, Part 2
December 01, 2011
译文:
ICS 证书存储实现第二部分
2011年12月1日
原文:
In the previous entry, we found how Android's keystore
daemon manages keys and certificates, and how to connect to it using the provided keystore_cli
utility. Now we will look at the intermediate layers between the OS daemon and the public KeyChain
API introduced in ICS.
译文:
在前一部分,我们知道了Android的keystore
守护进程是如何管理密钥和证书的,并且使用系统提供的keystore_cli
工具连接这个服务。现在我们将要看一下系统守护进程和ICS引入的 KeyChain
API的中间层实现。
原文:
Browsing the android.security
package, we find two AIDL files: IKeyChainService.aidl
and IKeyChainAliasCallback.aidl
. This is a hint that the actual key store functionality, like most Android OS services, is implemented as a remote service that the public API's bind to. IKeyChainAliasCallback
is just the callback called when you select a key via KeyStore#choosePrivateKeyAlias()
, so it's of little interest. IKeyChainService
has the actual methods KeyChain
uses to get a handle to a private key or a certificate, plus some internal API's used by the Settings and certificate installer applications. Naturally, the whole interface is marked as hidden, so SDK applications cannot directly bind to the service.
译文:
浏览 android.security
包,我们找到两个AIDL文件,IKeyChainService.aidl
和 IKeyChainAliasCallback.aidl
,这暗示着,实际的 key store 方法,像很多Android系统服务一样,是以公开的API绑定一个远程服务实现的。IKeyChainAliasCallback
仅仅是一个回调,在你通过KeyStore#choosePrivateKeyAlias()
选中一个密钥时调用,所以对它不感兴趣。IKeyChainService
有 KeyChain
实际使用的方法,用来处理一个私钥或者证书,外加几个内部的API,给设置和证书安装应用使用。当然,整个接口被标记成hidden,因此SDK应用不能直接绑定到这个服务。
原文:
The IKeyChainService interface has one implementation, the KeyChainService in the KeyChain.apk system package. We find the source in packages/apps/KeyChain, so let's explore the app's configuration. Looking at the manifest reveals that it consists of three components: the KeyChainService, a KeyChainActivity, and a broadcast receiver, you guessed it, KeyChainBroadcastReceiver. The package is com.android.keychain and its sharedUserId is set to 'android.uid.system', which, as we saw in the previous article, is necessary to be able to send management commands to the native keystore daemon. Let's first examine the service.
译文:
IKeyChainService
接口有一个实现KeyChainService
, 在系统包的KeyChain.apk
中。我们在packages/apps/KeyChain
中找到了源码,让我们探索这个应用的配置。查看manifest
信息,它是由三个组件构成:KeyChainService
,KeyChainActivity
和一个 broadcast receiver,你猜到了,是KeyChainBroadcastReceiver
。包名是com.android.keychain
,它的sharedUserId
设置成了'android.uid.system'
,我们在前面的文章中看到了,这是向底层的keystore
守护进程发送管理命令所必须的。让我们先查看一下这个service。
原文:
As can be expected, the KeyChainService is a wrapper for the android.security.KeyStore class that directly communicates with the native keystore daemon. It provides 4 sets of functionality:
译文:
正如所料,KeyChainService
是 android.security.KeyStore
类的一个包装,它和底层的 keystore
守护进程直接通信,提供了4个方法集合:
原文:
- key store management: methods for getting private keys and certificates
- trust store management: methods for installing and deleting CA certificates in the user trust store
- key and trust store initialization: a reset() method that deletes all key store entries, including the master key, thus returning the key store to a 'not initialized' state; it also removes all user-installed trusted certificates
- methods for querying and adding entries to the key access grant database (more on this later)
译文:
- 密钥存储管理:获取私钥和证书的方法
- 受信任存储管理:在用户信受任存储中安装和删除CA证书的方法
- 密钥和证书存储初始化:
reset()
方法删除所有密钥存储实体,包括master key
,这让key store
回到了'not initialized'
状态,它还会删除所有用户安装的受信任证书 - 查询和添加密钥授权数据库实体的方法(稍后详细介绍)
原文:
Since the KeyChain application is running as the system user, any process that binds to its remote interface would technically be able to perform all key and trust store operations. To prevent this, the KeyChainService imposes additional access control on its users. It employs two mechanisms to achieve this: controlling access based on the caller's UID and a key access grant database. Deleting a CA certificate and resetting the key and trust stores are only allowed to the system user (those operations are typically called via the Settings app's UI, which runs as system), and installing a trusted CA certificate is only allowed to the system user or the certificate installer application (com.android.certinstaller package). Controlling access to the key store is a little bit more interesting: KeyChainService maintains a grants database (in /data/data/com.android.keychain/databases/grants.db) that maps UID's to the key aliases they are allowed to use. Let's have a look inside:
译文:
由于KeyChain
应用以 system user
(译注:具有系统权限)运行,从技术上来说,任何绑定到它远程接口的进程,能够执行所有的密钥和受信任操作。为了防止这种情况,KeyChainService
给它的用户强加了额外的访问控制。它利用两个机制达到这一点: 基于调用者的UID和一个密钥访问授权数据库控制访问。只允许系统用户删除一个CA证书和重置密钥及受信任存储(这些操作的典型调用是通过'设置'应用的界面,以'system'身份运行),只允许系统用户或者证书安装应用('com.android.certinstaller 应用'
)安装一个受信任的CA证书。控制密钥存储的访问比较有意思:KeyChainService
维护一个授权数据库(在 /data/data/com.android.keychain/databases/grants.db
),它把UID映射到了允许使用的密钥别名。让我们一探究竟:
# cd /data/data/com.android.keychain/databases
cd /data/data/com.android.keychain/databases
# ls
ls
grants.db
grants.db-journal
# sqlite3 grants.db
sqlite3 grants.db
sqlite> .schema
.schema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE grants ( alias STRING NOT NULL, uid INTEGER NOT NULL, UNIQUE (al
ias,uid));
sqlite> select * from grants;
select * from grants;
test|10044
key1|10044
原文:
In this example, the application with UID 10044 (our test application) is granted access to the keys with the test and key1 aliases.
译文:
在这个例子中,UID是10044的应用(我们的测试应用)被授权访问别名为'test'和'key1'的私钥。
原文:
Each call to getPrivateKey()
or getCertificate()
is subject to a check against the grants database, and results in a exception if a grant for the required alias is not found. As stated before, KeyChainService
has API's for adding and querying grants, and only the system
user is allowed to call them. But who is responsible for actually granting and revoking access? Remember the private key selection dialog from the first article? When you call KeyChain#choosePrivateKeyAlias()
, it will start the KeyChainActivity
introduced above, which will check if the key store is unlocked, and if so, show they key selection dialog. Clicking the 'Allow' button will return to the KeyChainActivity
, which will then call KeyChainService#setGrant()
with the selected alias, adding it to the grants database. Thus, even if the activity requesting access to a private key has the needed permissions, the user has to unlock the key store and explicitly authorize access to each individual key.
译文:
每一次 getPrivateKey()
或getCertificate()
调用,都要经受授权数据库的检查,如果没有找到所需别名的授权,将会产生一个异常。正如前面所说,KeyChainService
有添加和查询授权的API,并且只允许system
应用调用。那么谁在真正负责授权和撤消授权呢?还记得第一篇的private key selection dialog吗?当你调用KeyChain#choosePrivateKeyAlias()
时,会启动前面介绍的 KeyChainActivity
,它会检查密钥存储是否解锁,如果是,显示密钥选择对话框。点击 'Allow'按钮,会回到KeyChainActivity
,这时它用已选的别名调用KeyChainService#setGrant()
,把它添加到授权数据库。这样,即使请求访问一个私钥的activity拥有所需权限,用户不得不解锁key store
并且显式地给每个私钥授权。
原文:
Besides controlling private key storage, the KeyChainService also offers trust store management by using the newly added TrustedCertificateStore class (part of libcore). This class provides both the ability to add user-installed trusted CA certificates and remove (mark as not trusted) system (pre-installed) CA's. Since the implementation is fairly complex and rather interesting, it will be the topic of another post.
译文:
除了控制密钥存储,KeyChainService
还通过新添加的TrustedCertificateStore
类(libcore的一部分),提供了信任存储管理,这个类即提供了添加用户安装的受信任CA证书的能力,还提供了删除(被标记为不受信任的)系统(预先安装的)的CA证书的能力。由于这个实现相当地复杂并且非常有趣,所以将是另一篇文章的主题。
原文:
The last component of the KeyChain app is the KeyChainBroadcastReceiver. It listens for a android.intent.action.PACKAGE_REMOVED broadcast and simply forwards control to the KeyChainService. On receiving the PACKAGE_REMOVED action, the service does some grant database maintenance: it goes through all entries and deletes those referencing packages that are no longer available (i.e., uninstalled ones). With this we now have the (almost) complete picture (click to enlarge):
译文:
KeyChain
应用的最后一个组件是KeyChainBroadcastReceiver
。 它监听 android.intent.action.PACKAGE_REMOVED
广播,简单地把控制转发到KeyChainService
。当接收到 PACKAGE_REMOVED
action,这个 service 做了一些授权数据库维护:它遍历所有的条目,删除那些不再可用的引用package(例如,被卸载的应用)。现在我们有个(几乎)完整的图像(点击放大):
原文:
ICS introduces a new service that grants access to both the system key store (managed by the keystore daemon) and trust store (manged by the TrustedCertificateStore
class) that backs the KeyChain
API exposed in the public SDK. That makes it possible to control access to keys based on both the calling process's UID and the key access grant database, thus allowing for fine-grained, user-driven control over what keys each application can access. We've discussed most of the components this framework consists of in this and the previous entry. What remains is to look into the new trust store implementation introduced in Android 4.0. That will be the focus of the next post of this series.
译文:
ICS 引入了一个新的 service, 它给系统密钥存储(由keystore 守护进程管理)和受信任存储(由 TrustedCertificateStore
类管理)授权,它是暴露在公开的SDK中的KeyChain
API的后台。它使得能够基于调用者进程的UID和密钥授权数据库控制访问。我们在这篇和前一篇文章中已经讨论了很多组成这个框架的组件。剩下的是查看 Android 4.0引入的新的受信任存储。这将是下一篇
的重点。
网友评论