summaryrefslogtreecommitdiffstats
path: root/keystore/java/android/security/CertTool.java
blob: 1dc575bccb88125858afb0e5e39ecd4f3003d314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.security;

import android.content.Context;
import android.content.Intent;
import android.security.Keystore;
import android.text.TextUtils;


/**
 * The CertTool class provides the functions to list the certs/keys,
 * generate the certificate request(csr) and store the certificate into
 * keystore.
 *
 * {@hide}
 */
public class CertTool {
    public static final String ACTION_ADD_CREDENTIAL =
            "android.security.ADD_CREDENTIAL";
    public static final String KEY_TYPE_NAME = "typeName";
    public static final String KEY_ITEM = "item";
    public static final String KEY_NAMESPACE = "namespace";
    public static final String KEY_DESCRIPTION = "description";

    private static final String TAG = "CertTool";

    private static final String TITLE_CA_CERT = "CA Certificate";
    private static final String TITLE_USER_CERT = "User Certificate";
    private static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore";
    private static final String TITLE_PRIVATE_KEY = "Private Key";
    private static final String UNKNOWN = "Unknown";
    private static final String ISSUER_NAME = "Issuer Name:";
    private static final String DISTINCT_NAME = "Distinct Name:";

    private static final String CA_CERTIFICATE = "CACERT";
    private static final String USER_CERTIFICATE = "USRCERT";
    private static final String USER_KEY = "USRKEY";

    private static final String KEYNAME_DELIMITER = "_";
    private static final Keystore keystore = Keystore.getInstance();

    private native String generateCertificateRequest(int bits, String subject);
    private native boolean isPkcs12Keystore(byte[] data);
    private native int generateX509Certificate(byte[] data);
    private native boolean isCaCertificate(int handle);
    private native String getIssuerDN(int handle);
    private native String getCertificateDN(int handle);
    private native String getPrivateKeyPEM(int handle);
    private native void freeX509Certificate(int handle);

    public String getUserPrivateKey(String key) {
        return USER_KEY + KEYNAME_DELIMITER + key;
    }

    public String getUserCertificate(String key) {
        return USER_CERTIFICATE + KEYNAME_DELIMITER + key;
    }

    public String getCaCertificate(String key) {
        return CA_CERTIFICATE + KEYNAME_DELIMITER + key;
    }

    public String[] getAllUserCertificateKeys() {
        return keystore.listKeys(USER_KEY);
    }

    public String[] getAllCaCertificateKeys() {
        return keystore.listKeys(CA_CERTIFICATE);
    }

    public String[] getSupportedKeyStrenghs() {
        return new String[] {"High Grade", "Medium Grade"};
    }

    private int getKeyLength(int index) {
        if (index == 0) return 2048;
        return 1024;
    }

    public String generateKeyPair(int keyStrengthIndex, String challenge,
            String dirName) {
        return generateCertificateRequest(getKeyLength(keyStrengthIndex),
                dirName);
    }

    private Intent prepareIntent(String title, byte[] data, String namespace,
            String issuer, String distinctName) {
        Intent intent = new Intent(ACTION_ADD_CREDENTIAL);
        intent.putExtra(KEY_TYPE_NAME, title);
        intent.putExtra(KEY_ITEM + "0", data);
        intent.putExtra(KEY_NAMESPACE + "0", namespace);
        intent.putExtra(KEY_DESCRIPTION + "0", ISSUER_NAME + issuer);
        intent.putExtra(KEY_DESCRIPTION + "1", DISTINCT_NAME + distinctName);
        return intent;
    }

    private void addExtraIntentInfo(Intent intent, String namespace,
            String data) {
        intent.putExtra(KEY_ITEM + "1", data);
        intent.putExtra(KEY_NAMESPACE + "1", namespace);
    }

    public synchronized void addCertificate(byte[] data, Context context) {
        int handle;
        Intent intent = null;

        if (isPkcs12Keystore(data)) {
            intent = prepareIntent(TITLE_PKCS12_KEYSTORE, data, USER_KEY,
                    UNKNOWN, UNKNOWN);
        } else if ((handle = generateX509Certificate(data)) != 0) {
            String issuer = getIssuerDN(handle);
            String distinctName = getCertificateDN(handle);
            String privateKeyPEM = getPrivateKeyPEM(handle);
            if (isCaCertificate(handle)) {
                intent = prepareIntent(TITLE_CA_CERT, data, CA_CERTIFICATE,
                        issuer, distinctName);
            } else {
                intent = prepareIntent(TITLE_USER_CERT, data, USER_CERTIFICATE,
                        issuer, distinctName);
                if (!TextUtils.isEmpty(privateKeyPEM)) {
                    addExtraIntentInfo(intent, USER_KEY, privateKeyPEM);
                }
            }
            freeX509Certificate(handle);
        }
        if (intent != null) context.startActivity(intent);
    }
}