blob: d8109ce2df99981558742628d317e514724751a0 [file] [log] [blame]
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +08001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.security;
18
19import android.content.ActivityNotFoundException;
20import android.content.Context;
21import android.content.Intent;
22import android.util.Log;
Brian Carlstrom0efca172012-09-04 23:01:07 -070023import com.android.org.bouncycastle.util.io.pem.PemObject;
24import com.android.org.bouncycastle.util.io.pem.PemReader;
25import com.android.org.bouncycastle.util.io.pem.PemWriter;
Brian Carlstrom9d7faa92011-06-07 13:45:33 -070026import java.io.ByteArrayInputStream;
27import java.io.ByteArrayOutputStream;
28import java.io.IOException;
29import java.io.InputStreamReader;
Kenny Root5423e682011-11-14 08:43:13 -080030import java.io.ObjectOutputStream;
Brian Carlstrom9d7faa92011-06-07 13:45:33 -070031import java.io.OutputStreamWriter;
32import java.io.Reader;
33import java.io.Writer;
34import java.nio.charset.Charsets;
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +080035import java.security.KeyPair;
Brian Carlstrom0efca172012-09-04 23:01:07 -070036import java.security.cert.Certificate;
37import java.security.cert.CertificateEncodingException;
38import java.security.cert.CertificateException;
39import java.security.cert.CertificateFactory;
Kenny Root5423e682011-11-14 08:43:13 -080040import java.security.cert.X509Certificate;
Brian Carlstrom9d7faa92011-06-07 13:45:33 -070041import java.util.ArrayList;
42import java.util.List;
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +080043
44/**
45 * {@hide}
46 */
47public class Credentials {
48 private static final String LOGTAG = "Credentials";
Chia-chi Yeh44039172009-09-21 11:53:59 +080049
Chia-chi Yeh44039172009-09-21 11:53:59 +080050 public static final String INSTALL_ACTION = "android.credentials.INSTALL";
51
Brian Carlstrom4a9e1a22011-04-22 15:45:22 -070052 public static final String UNLOCK_ACTION = "com.android.credentials.UNLOCK";
53
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +080054 /** Key prefix for CA certificates. */
55 public static final String CA_CERTIFICATE = "CACERT_";
56
57 /** Key prefix for user certificates. */
58 public static final String USER_CERTIFICATE = "USRCERT_";
59
60 /** Key prefix for user private keys. */
61 public static final String USER_PRIVATE_KEY = "USRPKEY_";
62
63 /** Key prefix for VPN. */
64 public static final String VPN = "VPN_";
65
66 /** Key prefix for WIFI. */
67 public static final String WIFI = "WIFI_";
68
Jeff Sharkey69ddab42012-08-25 00:05:46 -070069 /** Key containing suffix of lockdown VPN profile. */
70 public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN";
71
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +080072 /** Data type for public keys. */
Brian Carlstroma00a2b32011-06-29 10:42:35 -070073 public static final String EXTRA_PUBLIC_KEY = "KEY";
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +080074
75 /** Data type for private keys. */
Brian Carlstroma00a2b32011-06-29 10:42:35 -070076 public static final String EXTRA_PRIVATE_KEY = "PKEY";
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +080077
Brian Carlstrom67c30df2011-06-24 02:13:23 -070078 // historically used by Android
79 public static final String EXTENSION_CRT = ".crt";
80 public static final String EXTENSION_P12 = ".p12";
81 // commonly used on Windows
82 public static final String EXTENSION_CER = ".cer";
83 public static final String EXTENSION_PFX = ".pfx";
84
Brian Carlstrom9d7faa92011-06-07 13:45:33 -070085 /**
Kenny Root5423e682011-11-14 08:43:13 -080086 * Intent extra: name for the user's private key.
87 */
88 public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name";
89
90 /**
91 * Intent extra: data for the user's private key in PEM-encoded PKCS#8.
92 */
93 public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data";
94
95 /**
96 * Intent extra: name for the user's certificate.
97 */
98 public static final String EXTRA_USER_CERTIFICATE_NAME = "user_certificate_name";
99
100 /**
101 * Intent extra: data for the user's certificate in PEM-encoded X.509.
102 */
103 public static final String EXTRA_USER_CERTIFICATE_DATA = "user_certificate_data";
104
105 /**
106 * Intent extra: name for CA certificate chain
107 */
108 public static final String EXTRA_CA_CERTIFICATES_NAME = "ca_certificates_name";
109
110 /**
111 * Intent extra: data for CA certificate chain in PEM-encoded X.509.
112 */
113 public static final String EXTRA_CA_CERTIFICATES_DATA = "ca_certificates_data";
114
115 /**
Brian Carlstrom0efca172012-09-04 23:01:07 -0700116 * Convert objects to a PEM format which is used for
117 * CA_CERTIFICATE and USER_CERTIFICATE entries.
Brian Carlstrom9d7faa92011-06-07 13:45:33 -0700118 */
Brian Carlstrom0efca172012-09-04 23:01:07 -0700119 public static byte[] convertToPem(Certificate... objects)
120 throws IOException, CertificateEncodingException {
Brian Carlstrom9d7faa92011-06-07 13:45:33 -0700121 ByteArrayOutputStream bao = new ByteArrayOutputStream();
122 Writer writer = new OutputStreamWriter(bao, Charsets.US_ASCII);
Brian Carlstrom0efca172012-09-04 23:01:07 -0700123 PemWriter pw = new PemWriter(writer);
124 for (Certificate o : objects) {
125 pw.writeObject(new PemObject("CERTIFICATE", o.getEncoded()));
Brian Carlstrom9d7faa92011-06-07 13:45:33 -0700126 }
127 pw.close();
128 return bao.toByteArray();
129 }
130 /**
131 * Convert objects from PEM format, which is used for
Brian Carlstrom0efca172012-09-04 23:01:07 -0700132 * CA_CERTIFICATE and USER_CERTIFICATE entries.
Brian Carlstrom9d7faa92011-06-07 13:45:33 -0700133 */
Brian Carlstrom0efca172012-09-04 23:01:07 -0700134 public static List<X509Certificate> convertFromPem(byte[] bytes)
135 throws IOException, CertificateException {
Brian Carlstrom9d7faa92011-06-07 13:45:33 -0700136 ByteArrayInputStream bai = new ByteArrayInputStream(bytes);
137 Reader reader = new InputStreamReader(bai, Charsets.US_ASCII);
Brian Carlstrom0efca172012-09-04 23:01:07 -0700138 PemReader pr = new PemReader(reader);
Brian Carlstrom9d7faa92011-06-07 13:45:33 -0700139
Brian Carlstrom0efca172012-09-04 23:01:07 -0700140 CertificateFactory cf = CertificateFactory.getInstance("X509");
141
142 List<X509Certificate> result = new ArrayList<X509Certificate>();
143 PemObject o;
144 while ((o = pr.readPemObject()) != null) {
145 if (o.getType().equals("CERTIFICATE")) {
146 Certificate c = cf.generateCertificate(new ByteArrayInputStream(o.getContent()));
147 result.add((X509Certificate) c);
148 } else {
149 throw new IllegalArgumentException("Unknown type " + o.getType());
150 }
Brian Carlstrom9d7faa92011-06-07 13:45:33 -0700151 }
152 pr.close();
153 return result;
154 }
155
Chia-chi Yeh44039172009-09-21 11:53:59 +0800156 private static Credentials singleton;
157
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +0800158 public static Credentials getInstance() {
159 if (singleton == null) {
160 singleton = new Credentials();
161 }
162 return singleton;
163 }
164
165 public void unlock(Context context) {
166 try {
Brian Carlstrom4a9e1a22011-04-22 15:45:22 -0700167 Intent intent = new Intent(UNLOCK_ACTION);
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +0800168 context.startActivity(intent);
169 } catch (ActivityNotFoundException e) {
170 Log.w(LOGTAG, e.toString());
171 }
172 }
173
Brian Carlstrom67c30df2011-06-24 02:13:23 -0700174 public void install(Context context) {
175 try {
Brian Carlstroma00a2b32011-06-29 10:42:35 -0700176 Intent intent = KeyChain.createInstallIntent();
Brian Carlstrom67c30df2011-06-24 02:13:23 -0700177 context.startActivity(intent);
178 } catch (ActivityNotFoundException e) {
179 Log.w(LOGTAG, e.toString());
180 }
181 }
182
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +0800183 public void install(Context context, KeyPair pair) {
184 try {
Brian Carlstroma00a2b32011-06-29 10:42:35 -0700185 Intent intent = KeyChain.createInstallIntent();
186 intent.putExtra(EXTRA_PRIVATE_KEY, pair.getPrivate().getEncoded());
187 intent.putExtra(EXTRA_PUBLIC_KEY, pair.getPublic().getEncoded());
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +0800188 context.startActivity(intent);
189 } catch (ActivityNotFoundException e) {
190 Log.w(LOGTAG, e.toString());
191 }
192 }
193
194 public void install(Context context, String type, byte[] value) {
195 try {
Brian Carlstroma00a2b32011-06-29 10:42:35 -0700196 Intent intent = KeyChain.createInstallIntent();
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +0800197 intent.putExtra(type, value);
198 context.startActivity(intent);
199 } catch (ActivityNotFoundException e) {
200 Log.w(LOGTAG, e.toString());
201 }
202 }
Kenny Rootdb026712012-08-20 10:48:46 -0700203
204 /**
205 * Delete all types (private key, certificate, CA certificate) for a
206 * particular {@code alias}. All three can exist for any given alias.
207 * Returns {@code true} if there was at least one of those types.
208 */
209 static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) {
210 /*
211 * Make sure every type is deleted. There can be all three types, so
212 * don't use a conditional here.
213 */
214 return keystore.delKey(Credentials.USER_PRIVATE_KEY + alias)
Kenny Root802768d2012-08-21 15:23:35 -0700215 | deleteCertificateTypesForAlias(keystore, alias);
216 }
217
218 /**
219 * Delete all types (private key, certificate, CA certificate) for a
220 * particular {@code alias}. All three can exist for any given alias.
221 * Returns {@code true} if there was at least one of those types.
222 */
223 static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) {
224 /*
225 * Make sure every certificate type is deleted. There can be two types,
226 * so don't use a conditional here.
227 */
228 return keystore.delete(Credentials.USER_CERTIFICATE + alias)
Kenny Rootdb026712012-08-20 10:48:46 -0700229 | keystore.delete(Credentials.CA_CERTIFICATE + alias);
230 }
Chia-chi Yeh9b7a3f12009-09-18 12:00:12 +0800231}