• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.security;
18 
19 import com.android.org.bouncycastle.util.io.pem.PemObject;
20 import com.android.org.bouncycastle.util.io.pem.PemReader;
21 import com.android.org.bouncycastle.util.io.pem.PemWriter;
22 
23 import android.annotation.UnsupportedAppUsage;
24 import java.io.ByteArrayInputStream;
25 import java.io.ByteArrayOutputStream;
26 import java.io.IOException;
27 import java.io.InputStreamReader;
28 import java.io.OutputStreamWriter;
29 import java.io.Reader;
30 import java.io.Writer;
31 import java.nio.charset.StandardCharsets;
32 import java.security.cert.Certificate;
33 import java.security.cert.CertificateEncodingException;
34 import java.security.cert.CertificateException;
35 import java.security.cert.CertificateFactory;
36 import java.security.cert.X509Certificate;
37 import java.util.ArrayList;
38 import java.util.List;
39 
40 /**
41  * {@hide}
42  */
43 public class Credentials {
44     private static final String LOGTAG = "Credentials";
45 
46     public static final String INSTALL_ACTION = "android.credentials.INSTALL";
47 
48     public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER";
49 
50     /** Key prefix for CA certificates. */
51     public static final String CA_CERTIFICATE = "CACERT_";
52 
53     /** Key prefix for user certificates. */
54     public static final String USER_CERTIFICATE = "USRCERT_";
55 
56     /** Key prefix for user private and secret keys. */
57     public static final String USER_PRIVATE_KEY = "USRPKEY_";
58 
59     /** Key prefix for user secret keys.
60      *  @deprecated use {@code USER_PRIVATE_KEY} for this category instead.
61      */
62     public static final String USER_SECRET_KEY = "USRSKEY_";
63 
64     /** Key prefix for VPN. */
65     public static final String VPN = "VPN_";
66 
67     /** Key prefix for WIFI. */
68     public static final String WIFI = "WIFI_";
69 
70     /** Key containing suffix of lockdown VPN profile. */
71     public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN";
72 
73     /** Data type for public keys. */
74     public static final String EXTRA_PUBLIC_KEY = "KEY";
75 
76     /** Data type for private keys. */
77     public static final String EXTRA_PRIVATE_KEY = "PKEY";
78 
79     // historically used by Android
80     public static final String EXTENSION_CRT = ".crt";
81     public static final String EXTENSION_P12 = ".p12";
82     // commonly used on Windows
83     public static final String EXTENSION_CER = ".cer";
84     public static final String EXTENSION_PFX = ".pfx";
85 
86     /**
87      * Intent extra: install the certificate bundle as this UID instead of
88      * system.
89      */
90     public static final String EXTRA_INSTALL_AS_UID = "install_as_uid";
91 
92     /**
93      * Intent extra: name for the user's private key.
94      */
95     public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name";
96 
97     /**
98      * Intent extra: data for the user's private key in PEM-encoded PKCS#8.
99      */
100     public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data";
101 
102     /**
103      * Intent extra: name for the user's certificate.
104      */
105     public static final String EXTRA_USER_CERTIFICATE_NAME = "user_certificate_name";
106 
107     /**
108      * Intent extra: data for the user's certificate in PEM-encoded X.509.
109      */
110     public static final String EXTRA_USER_CERTIFICATE_DATA = "user_certificate_data";
111 
112     /**
113      * Intent extra: name for CA certificate chain
114      */
115     public static final String EXTRA_CA_CERTIFICATES_NAME = "ca_certificates_name";
116 
117     /**
118      * Intent extra: data for CA certificate chain in PEM-encoded X.509.
119      */
120     public static final String EXTRA_CA_CERTIFICATES_DATA = "ca_certificates_data";
121 
122     /**
123      * Convert objects to a PEM format which is used for
124      * CA_CERTIFICATE and USER_CERTIFICATE entries.
125      */
126     @UnsupportedAppUsage
convertToPem(Certificate... objects)127     public static byte[] convertToPem(Certificate... objects)
128             throws IOException, CertificateEncodingException {
129         ByteArrayOutputStream bao = new ByteArrayOutputStream();
130         Writer writer = new OutputStreamWriter(bao, StandardCharsets.US_ASCII);
131         PemWriter pw = new PemWriter(writer);
132         for (Certificate o : objects) {
133             pw.writeObject(new PemObject("CERTIFICATE", o.getEncoded()));
134         }
135         pw.close();
136         return bao.toByteArray();
137     }
138     /**
139      * Convert objects from PEM format, which is used for
140      * CA_CERTIFICATE and USER_CERTIFICATE entries.
141      */
convertFromPem(byte[] bytes)142     public static List<X509Certificate> convertFromPem(byte[] bytes)
143             throws IOException, CertificateException {
144         ByteArrayInputStream bai = new ByteArrayInputStream(bytes);
145         Reader reader = new InputStreamReader(bai, StandardCharsets.US_ASCII);
146         PemReader pr = new PemReader(reader);
147 
148         try {
149             CertificateFactory cf = CertificateFactory.getInstance("X509");
150 
151             List<X509Certificate> result = new ArrayList<X509Certificate>();
152             PemObject o;
153             while ((o = pr.readPemObject()) != null) {
154                 if (o.getType().equals("CERTIFICATE")) {
155                     Certificate c = cf.generateCertificate(new ByteArrayInputStream(o.getContent()));
156                     result.add((X509Certificate) c);
157                 } else {
158                     throw new IllegalArgumentException("Unknown type " + o.getType());
159                 }
160             }
161             return result;
162         } finally {
163             pr.close();
164         }
165     }
166 
167     /**
168      * Delete all types (private key, user certificate, CA certificate) for a
169      * particular {@code alias}. All three can exist for any given alias.
170      * Returns {@code true} if the alias no longer contains any types.
171      */
deleteAllTypesForAlias(KeyStore keystore, String alias)172     public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias) {
173         return deleteAllTypesForAlias(keystore, alias, KeyStore.UID_SELF);
174     }
175 
176     /**
177      * Delete all types (private key, user certificate, CA certificate) for a
178      * particular {@code alias}. All three can exist for any given alias.
179      * Returns {@code true} if the alias no longer contains any types.
180      */
deleteAllTypesForAlias(KeyStore keystore, String alias, int uid)181     public static boolean deleteAllTypesForAlias(KeyStore keystore, String alias, int uid) {
182         /*
183          * Make sure every type is deleted. There can be all three types, so
184          * don't use a conditional here.
185          */
186         return deleteUserKeyTypeForAlias(keystore, alias, uid)
187                 & deleteCertificateTypesForAlias(keystore, alias, uid);
188     }
189 
190     /**
191      * Delete certificate types (user certificate, CA certificate) for a
192      * particular {@code alias}. Both can exist for any given alias.
193      * Returns {@code true} if the alias no longer contains either type.
194      */
deleteCertificateTypesForAlias(KeyStore keystore, String alias)195     public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias) {
196         return deleteCertificateTypesForAlias(keystore, alias, KeyStore.UID_SELF);
197     }
198 
199     /**
200      * Delete certificate types (user certificate, CA certificate) for a
201      * particular {@code alias}. Both can exist for any given alias.
202      * Returns {@code true} if the alias no longer contains either type.
203      */
deleteCertificateTypesForAlias(KeyStore keystore, String alias, int uid)204     public static boolean deleteCertificateTypesForAlias(KeyStore keystore, String alias, int uid) {
205         /*
206          * Make sure every certificate type is deleted. There can be two types,
207          * so don't use a conditional here.
208          */
209         return keystore.delete(Credentials.USER_CERTIFICATE + alias, uid)
210                 & keystore.delete(Credentials.CA_CERTIFICATE + alias, uid);
211     }
212 
213     /**
214      * Delete user key for a particular {@code alias}.
215      * Returns {@code true} if the entry no longer exists.
216      */
deleteUserKeyTypeForAlias(KeyStore keystore, String alias)217     public static boolean deleteUserKeyTypeForAlias(KeyStore keystore, String alias) {
218         return deleteUserKeyTypeForAlias(keystore, alias, KeyStore.UID_SELF);
219     }
220 
221     /**
222      * Delete user key for a particular {@code alias}.
223      * Returns {@code true} if the entry no longer exists.
224      */
deleteUserKeyTypeForAlias(KeyStore keystore, String alias, int uid)225     public static boolean deleteUserKeyTypeForAlias(KeyStore keystore, String alias, int uid) {
226         int ret = keystore.delete2(Credentials.USER_PRIVATE_KEY + alias, uid);
227         if (ret == KeyStore.KEY_NOT_FOUND) {
228             return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
229         }
230         return ret == KeyStore.NO_ERROR;
231     }
232 
233     /**
234      * Delete legacy prefixed entry for a particular {@code alias}
235      * Returns {@code true} if the entry no longer exists.
236      */
deleteLegacyKeyForAlias(KeyStore keystore, String alias, int uid)237     public static boolean deleteLegacyKeyForAlias(KeyStore keystore, String alias, int uid) {
238         return keystore.delete(Credentials.USER_SECRET_KEY + alias, uid);
239     }
240 }
241