blob: a64ce83d91c43eb010c0a207f98c22088ff45bff [file] [log] [blame]
Chia-chi Yeh44039172009-09-21 11:53:59 +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
Mathew Inwood4dbdcf42018-08-16 18:49:37 +010019import android.annotation.UnsupportedAppUsage;
Brian Young9272dab2018-02-23 18:04:20 +000020import android.app.ActivityManager;
Svetoslav2dac95d2015-04-30 11:30:33 -070021import android.app.ActivityThread;
22import android.app.Application;
Alex Klyubin54183932015-05-08 15:25:48 -070023import android.app.KeyguardManager;
Alex Klyubin708fc9402015-04-28 18:58:47 -070024import android.content.Context;
Kevin Chyn55966422017-10-23 16:08:47 -070025import android.content.pm.PackageManager;
Alex Klyubin2d7a85c2015-04-30 11:43:53 -070026import android.hardware.fingerprint.FingerprintManager;
Chad Brubakere6a461342015-02-10 21:33:23 -080027import android.os.Binder;
Mathew Inwood55418ea2018-12-20 15:30:45 +000028import android.os.Build;
Chad Brubakere6a461342015-02-10 21:33:23 -080029import android.os.IBinder;
Chad Brubakera91a8502015-05-07 10:02:22 -070030import android.os.Process;
Kenny Root6b776452012-11-02 15:40:32 -070031import android.os.RemoteException;
32import android.os.ServiceManager;
Chad Brubakera91a8502015-05-07 10:02:22 -070033import android.os.UserHandle;
Janis Danisevskis1864c952018-08-09 11:14:49 -070034import android.security.KeyStoreException;
Chad Brubakere6a461342015-02-10 21:33:23 -080035import android.security.keymaster.ExportResult;
36import android.security.keymaster.KeyCharacteristics;
37import android.security.keymaster.KeymasterArguments;
Chad Brubaker5e73c0e2015-03-21 22:46:43 -070038import android.security.keymaster.KeymasterBlob;
Shawn Willden8d8c7472016-02-02 08:27:39 -070039import android.security.keymaster.KeymasterCertificateChain;
Alex Klyubinb4834ae2015-04-02 15:53:46 -070040import android.security.keymaster.KeymasterDefs;
Chad Brubakere6a461342015-02-10 21:33:23 -080041import android.security.keymaster.OperationResult;
Janis Danisevskisb0358e72018-11-02 10:34:07 -070042import android.security.keystore.IKeystoreService;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070043import android.security.keystore.KeyExpiredException;
44import android.security.keystore.KeyNotYetValidException;
45import android.security.keystore.KeyPermanentlyInvalidatedException;
Janis Danisevskis1864c952018-08-09 11:14:49 -070046import android.security.keystore.KeyProperties;
47import android.security.keystore.KeyProtection;
Janis Danisevskisb0358e72018-11-02 10:34:07 -070048import android.security.keystore.KeystoreResponse;
Frank Salimea5e0382018-01-23 22:42:29 -080049import android.security.keystore.StrongBoxUnavailableException;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070050import android.security.keystore.UserNotAuthenticatedException;
Kenny Root6b776452012-11-02 15:40:32 -070051import android.util.Log;
Janis Danisevskis1864c952018-08-09 11:14:49 -070052import com.android.org.bouncycastle.asn1.ASN1InputStream;
53import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
Alex Klyubinae6cb7a2015-06-22 18:09:35 -070054import java.math.BigInteger;
Janis Danisevskis1864c952018-08-09 11:14:49 -070055import java.io.ByteArrayInputStream;
56import java.io.IOException;
Alex Klyubinad9ba102015-04-21 15:17:24 -070057import java.security.InvalidKeyException;
Rob Barnesebe26742018-11-13 15:57:22 -070058import java.util.ArrayList;
Rob Barnesf1a678e2018-11-13 15:57:22 -070059import java.util.Arrays;
Janis Danisevskis2b106ad2018-11-15 09:27:16 -080060import java.util.Date;
Alex Klyubin708fc9402015-04-28 18:58:47 -070061import java.util.List;
Kenny Rootb91773b2013-09-05 13:03:16 -070062import java.util.Locale;
Janis Danisevskisb0358e72018-11-02 10:34:07 -070063import java.util.concurrent.CompletableFuture;
64import java.util.concurrent.ExecutionException;
Janis Danisevskis1864c952018-08-09 11:14:49 -070065import sun.security.util.ObjectIdentifier;
66import sun.security.x509.AlgorithmId;
Kenny Rootb91773b2013-09-05 13:03:16 -070067
Chia-chi Yeh44039172009-09-21 11:53:59 +080068/**
Brian Carlstrom46703b02011-04-06 15:41:29 -070069 * @hide This should not be made public in its present form because it
70 * assumes that private and secret key bytes are available and would
71 * preclude the use of hardware crypto.
Chia-chi Yeh44039172009-09-21 11:53:59 +080072 */
73public class KeyStore {
Kenny Root6b776452012-11-02 15:40:32 -070074 private static final String TAG = "KeyStore";
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070075
Dmitry Dementyevefc43112017-10-27 23:10:28 -070076 // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
Mathew Inwood4dbdcf42018-08-16 18:49:37 +010077 @UnsupportedAppUsage
Brian Carlstrom7e4b1a42011-06-01 15:29:29 -070078 public static final int NO_ERROR = 1;
79 public static final int LOCKED = 2;
80 public static final int UNINITIALIZED = 3;
81 public static final int SYSTEM_ERROR = 4;
82 public static final int PROTOCOL_ERROR = 5;
83 public static final int PERMISSION_DENIED = 6;
84 public static final int KEY_NOT_FOUND = 7;
85 public static final int VALUE_CORRUPTED = 8;
86 public static final int UNDEFINED_ACTION = 9;
87 public static final int WRONG_PASSWORD = 10;
Janis Danisevskisd2575382018-10-08 07:56:58 -070088 public static final int KEY_ALREADY_EXISTS = 16;
Eran Messeri61692392018-03-26 16:43:14 +010089 public static final int CANNOT_ATTEST_IDS = -66;
Frank Salimea5e0382018-01-23 22:42:29 -080090 public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070091
Chad Brubaker560d6532015-04-24 10:32:18 -070092 /**
93 * Per operation authentication is needed before this operation is valid.
94 * This is returned from {@link #begin} when begin succeeds but the operation uses
95 * per-operation authentication and must authenticate before calling {@link #update} or
96 * {@link #finish}.
97 */
98 public static final int OP_AUTH_NEEDED = 15;
99
Kenny Root2eeda722013-04-10 11:30:58 -0700100 // Used for UID field to indicate the calling UID.
101 public static final int UID_SELF = -1;
102
103 // Flags for "put" "import" and "generate"
104 public static final int FLAG_NONE = 0;
Alex Klyubin54183932015-05-08 15:25:48 -0700105
106 /**
107 * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key
108 * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern).
109 *
110 * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set
111 * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key
112 * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or
113 * a Device Administrator). Finally, this key (or key pair) cannot be used until the user
114 * unlocks the secure lock screen after boot.
115 *
116 * @see KeyguardManager#isDeviceSecure()
117 */
Kenny Roota3788b02013-04-10 10:37:55 -0700118 public static final int FLAG_ENCRYPTED = 1;
119
Rubin Xu12b644d2017-04-21 19:21:42 +0100120 /**
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800121 * Select Software keymaster device, which as of this writing is the lowest security
122 * level available on an android device. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
123 * A TEE based keymaster implementation is implied.
124 *
125 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
126 * For historical reasons this corresponds to the KEYSTORE_FLAG_FALLBACK flag.
127 */
128 public static final int FLAG_SOFTWARE = 1 << 1;
129
130 /**
Rubin Xu12b644d2017-04-21 19:21:42 +0100131 * A private flag that's only available to system server to indicate that this key is part of
132 * device encryption flow so it receives special treatment from keystore. For example this key
133 * will not be super encrypted, and it will be stored separately under an unique UID instead
134 * of the caller UID i.e. SYSTEM.
135 *
136 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
137 */
138 public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
139
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800140 /**
141 * Select Strongbox keymaster device, which as of this writing the the highest security level
142 * available an android devices. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
143 * A TEE based keymaster implementation is implied.
144 *
145 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
146 */
147 public static final int FLAG_STRONGBOX = 1 << 4;
148
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700149 // States
Mathew Inwoodefb48162018-08-01 10:24:49 +0100150 public enum State {
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100151 @UnsupportedAppUsage
Mathew Inwoodefb48162018-08-01 10:24:49 +0100152 UNLOCKED,
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100153 @UnsupportedAppUsage
Mathew Inwoodefb48162018-08-01 10:24:49 +0100154 LOCKED,
155 UNINITIALIZED
156 };
Chia-chi Yeh44039172009-09-21 11:53:59 +0800157
Chia-chi Yeh44039172009-09-21 11:53:59 +0800158 private int mError = NO_ERROR;
159
Kenny Root6b776452012-11-02 15:40:32 -0700160 private final IKeystoreService mBinder;
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700161 private final Context mContext;
Kenny Root6b776452012-11-02 15:40:32 -0700162
Chad Brubakere6a461342015-02-10 21:33:23 -0800163 private IBinder mToken;
164
Kenny Root6b776452012-11-02 15:40:32 -0700165 private KeyStore(IKeystoreService binder) {
166 mBinder = binder;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -0700167 mContext = getApplicationContext();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700168 }
169
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100170 @UnsupportedAppUsage
Alex Klyubindcdaf872015-05-13 15:57:09 -0700171 public static Context getApplicationContext() {
Alex Klyubina99b8b52015-06-11 13:27:34 -0700172 Application application = ActivityThread.currentApplication();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700173 if (application == null) {
174 throw new IllegalStateException(
Alex Klyubina99b8b52015-06-11 13:27:34 -0700175 "Failed to obtain application Context from ActivityThread");
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700176 }
177 return application;
Kenny Root6b776452012-11-02 15:40:32 -0700178 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800179
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100180 @UnsupportedAppUsage
Chia-chi Yeh44039172009-09-21 11:53:59 +0800181 public static KeyStore getInstance() {
Kenny Root6b776452012-11-02 15:40:32 -0700182 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
183 .getService("android.security.keystore"));
184 return new KeyStore(keystore);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800185 }
186
Chad Brubakere6a461342015-02-10 21:33:23 -0800187 private synchronized IBinder getToken() {
188 if (mToken == null) {
189 mToken = new Binder();
190 }
191 return mToken;
192 }
193
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100194 @UnsupportedAppUsage
Chad Brubakere35d49f2015-05-12 15:19:52 -0700195 public State state(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700196 final int ret;
197 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700198 ret = mBinder.getState(userId);
Kenny Root6b776452012-11-02 15:40:32 -0700199 } catch (RemoteException e) {
200 Log.w(TAG, "Cannot connect to keystore", e);
201 throw new AssertionError(e);
202 }
203
204 switch (ret) {
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700205 case NO_ERROR: return State.UNLOCKED;
206 case LOCKED: return State.LOCKED;
207 case UNINITIALIZED: return State.UNINITIALIZED;
208 default: throw new AssertionError(mError);
209 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800210 }
211
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100212 @UnsupportedAppUsage
Chad Brubakere35d49f2015-05-12 15:19:52 -0700213 public State state() {
214 return state(UserHandle.myUserId());
215 }
216
Kenny Rootb9594ce2013-02-14 10:18:38 -0800217 public boolean isUnlocked() {
218 return state() == State.UNLOCKED;
219 }
220
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700221 public byte[] get(String key, int uid) {
Irina Dumitrescu203bd1b2018-06-08 19:36:34 +0100222 return get(key, uid, false);
223 }
224
225 @UnsupportedAppUsage
226 public byte[] get(String key) {
227 return get(key, UID_SELF);
228 }
229
230 public byte[] get(String key, int uid, boolean suppressKeyNotFoundWarning) {
Kenny Root6b776452012-11-02 15:40:32 -0700231 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700232 key = key != null ? key : "";
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700233 return mBinder.get(key, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700234 } catch (RemoteException e) {
235 Log.w(TAG, "Cannot connect to keystore", e);
236 return null;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700237 } catch (android.os.ServiceSpecificException e) {
Irina Dumitrescu203bd1b2018-06-08 19:36:34 +0100238 if (!suppressKeyNotFoundWarning || e.errorCode != KEY_NOT_FOUND) {
239 Log.w(TAG, "KeyStore exception", e);
240 }
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700241 return null;
Kenny Root6b776452012-11-02 15:40:32 -0700242 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800243 }
244
Irina Dumitrescu203bd1b2018-06-08 19:36:34 +0100245 public byte[] get(String key, boolean suppressKeyNotFoundWarning) {
246 return get(key, UID_SELF, suppressKeyNotFoundWarning);
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700247 }
248
Irina Dumitrescu203bd1b2018-06-08 19:36:34 +0100249
Kenny Roota3788b02013-04-10 10:37:55 -0700250 public boolean put(String key, byte[] value, int uid, int flags) {
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700251 return insert(key, value, uid, flags) == NO_ERROR;
252 }
253
254 public int insert(String key, byte[] value, int uid, int flags) {
Kenny Root6b776452012-11-02 15:40:32 -0700255 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700256 if (value == null) {
257 value = new byte[0];
258 }
Janis Danisevskisd2575382018-10-08 07:56:58 -0700259 int error = mBinder.insert(key, value, uid, flags);
260 if (error == KEY_ALREADY_EXISTS) {
261 mBinder.del(key, uid);
262 error = mBinder.insert(key, value, uid, flags);
263 }
264 return error;
Kenny Root78ad8492013-02-13 17:02:57 -0800265 } catch (RemoteException e) {
266 Log.w(TAG, "Cannot connect to keystore", e);
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700267 return SYSTEM_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800268 }
269 }
270
Janis Danisevskis906147c2018-11-06 14:14:05 -0800271 int delete2(String key, int uid) {
Kenny Root78ad8492013-02-13 17:02:57 -0800272 try {
Janis Danisevskis906147c2018-11-06 14:14:05 -0800273 return mBinder.del(key, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700274 } catch (RemoteException e) {
275 Log.w(TAG, "Cannot connect to keystore", e);
Janis Danisevskis906147c2018-11-06 14:14:05 -0800276 return SYSTEM_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700277 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800278 }
279
Janis Danisevskis906147c2018-11-06 14:14:05 -0800280 public boolean delete(String key, int uid) {
281 int ret = delete2(key, uid);
282 return ret == NO_ERROR || ret == KEY_NOT_FOUND;
283 }
284
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100285 @UnsupportedAppUsage
Chia-chi Yeh44039172009-09-21 11:53:59 +0800286 public boolean delete(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700287 return delete(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800288 }
289
290 public boolean contains(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700291 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800292 return mBinder.exist(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700293 } catch (RemoteException e) {
294 Log.w(TAG, "Cannot connect to keystore", e);
295 return false;
296 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800297 }
298
299 public boolean contains(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700300 return contains(key, UID_SELF);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800301 }
302
Chad Brubakere35d49f2015-05-12 15:19:52 -0700303 /**
304 * List all entries in the keystore for {@code uid} starting with {@code prefix}.
305 */
306 public String[] list(String prefix, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700307 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700308 return mBinder.list(prefix, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700309 } catch (RemoteException e) {
310 Log.w(TAG, "Cannot connect to keystore", e);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800311 return null;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700312 } catch (android.os.ServiceSpecificException e) {
313 Log.w(TAG, "KeyStore exception", e);
314 return null;
Chia-chi Yeh44039172009-09-21 11:53:59 +0800315 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800316 }
317
Rob Barnesf1a678e2018-11-13 15:57:22 -0700318 /**
Rob Barnesebe26742018-11-13 15:57:22 -0700319 * List uids of all keys that are auth bound to the current user.
Rob Barnesf1a678e2018-11-13 15:57:22 -0700320 * Only system is allowed to call this method.
321 */
322 @UnsupportedAppUsage
323 public int[] listUidsOfAuthBoundKeys() {
Rob Barnesebe26742018-11-13 15:57:22 -0700324 // uids are returned as a list of strings because list of integers
325 // as an output parameter is not supported by aidl-cpp.
326 List<String> uidsOut = new ArrayList<>();
Rob Barnesf1a678e2018-11-13 15:57:22 -0700327 try {
328 int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
329 if (rc != NO_ERROR) {
330 Log.w(TAG, String.format("listUidsOfAuthBoundKeys failed with error code %d", rc));
331 return null;
332 }
333 } catch (RemoteException e) {
334 Log.w(TAG, "Cannot connect to keystore", e);
335 return null;
336 } catch (android.os.ServiceSpecificException e) {
337 Log.w(TAG, "KeyStore exception", e);
338 return null;
339 }
Rob Barnesebe26742018-11-13 15:57:22 -0700340 // Turn list of strings into an array of uid integers.
341 return uidsOut.stream().mapToInt(Integer::parseInt).toArray();
Rob Barnesf1a678e2018-11-13 15:57:22 -0700342 }
343
Chad Brubakere35d49f2015-05-12 15:19:52 -0700344 public String[] list(String prefix) {
345 return list(prefix, UID_SELF);
346 }
347
Mathew Inwood55418ea2018-12-20 15:30:45 +0000348 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Chia-chi Yeh44039172009-09-21 11:53:59 +0800349 public boolean reset() {
Kenny Root6b776452012-11-02 15:40:32 -0700350 try {
351 return mBinder.reset() == NO_ERROR;
352 } catch (RemoteException e) {
353 Log.w(TAG, "Cannot connect to keystore", e);
354 return false;
355 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800356 }
357
Chad Brubakere35d49f2015-05-12 15:19:52 -0700358 /**
359 * Attempt to lock the keystore for {@code user}.
360 *
Brian Young36716eb2018-02-23 18:04:20 +0000361 * @param userId Android user to lock.
Chad Brubakere35d49f2015-05-12 15:19:52 -0700362 * @return whether {@code user}'s keystore was locked.
363 */
364 public boolean lock(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700365 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700366 return mBinder.lock(userId) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700367 } catch (RemoteException e) {
368 Log.w(TAG, "Cannot connect to keystore", e);
369 return false;
370 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800371 }
372
Chad Brubakere35d49f2015-05-12 15:19:52 -0700373 public boolean lock() {
374 return lock(UserHandle.myUserId());
375 }
376
Chad Brubakera91a8502015-05-07 10:02:22 -0700377 /**
378 * Attempt to unlock the keystore for {@code user} with the password {@code password}.
379 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
380 * created.
381 *
Brian Young36716eb2018-02-23 18:04:20 +0000382 * @param userId Android user ID to operate on
Chad Brubakera91a8502015-05-07 10:02:22 -0700383 * @param password user's keystore password. Should be the most recent value passed to
384 * {@link #onUserPasswordChanged} for the user.
385 *
386 * @return whether the keystore was unlocked.
387 */
388 public boolean unlock(int userId, String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700389 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700390 password = password != null ? password : "";
Chad Brubakera91a8502015-05-07 10:02:22 -0700391 mError = mBinder.unlock(userId, password);
Kenny Root6b776452012-11-02 15:40:32 -0700392 return mError == NO_ERROR;
393 } catch (RemoteException e) {
394 Log.w(TAG, "Cannot connect to keystore", e);
395 return false;
396 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800397 }
398
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100399 @UnsupportedAppUsage
Chad Brubakera91a8502015-05-07 10:02:22 -0700400 public boolean unlock(String password) {
401 return unlock(UserHandle.getUserId(Process.myUid()), password);
402 }
403
Chad Brubakere35d49f2015-05-12 15:19:52 -0700404 /**
405 * Check if the keystore for {@code userId} is empty.
406 */
407 public boolean isEmpty(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700408 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700409 return mBinder.isEmpty(userId) != 0;
Kenny Root6b776452012-11-02 15:40:32 -0700410 } catch (RemoteException e) {
411 Log.w(TAG, "Cannot connect to keystore", e);
412 return false;
413 }
Kenny Root5423e682011-11-14 08:43:13 -0800414 }
415
Mathew Inwood55418ea2018-12-20 15:30:45 +0000416 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Chad Brubakere35d49f2015-05-12 15:19:52 -0700417 public boolean isEmpty() {
418 return isEmpty(UserHandle.myUserId());
419 }
420
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700421 public String grant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700422 try {
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700423 String grantAlias = mBinder.grant(key, uid);
424 if (grantAlias == "") return null;
425 return grantAlias;
Kenny Root6b776452012-11-02 15:40:32 -0700426 } catch (RemoteException e) {
427 Log.w(TAG, "Cannot connect to keystore", e);
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700428 return null;
Kenny Root6b776452012-11-02 15:40:32 -0700429 }
Kenny Root5423e682011-11-14 08:43:13 -0800430 }
431
432 public boolean ungrant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700433 try {
434 return mBinder.ungrant(key, uid) == NO_ERROR;
435 } catch (RemoteException e) {
436 Log.w(TAG, "Cannot connect to keystore", e);
437 return false;
Kenny Root473c7122012-08-17 21:13:48 -0700438 }
Kenny Root473c7122012-08-17 21:13:48 -0700439 }
440
441 /**
442 * Returns the last modification time of the key in milliseconds since the
443 * epoch. Will return -1L if the key could not be found or other error.
444 */
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700445 public long getmtime(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700446 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700447 final long millis = mBinder.getmtime(key, uid);
Kenny Roote66769a2013-02-04 15:49:11 -0800448 if (millis == -1L) {
449 return -1L;
450 }
451
452 return millis * 1000L;
Kenny Root6b776452012-11-02 15:40:32 -0700453 } catch (RemoteException e) {
454 Log.w(TAG, "Cannot connect to keystore", e);
455 return -1L;
456 }
Kenny Root473c7122012-08-17 21:13:48 -0700457 }
458
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700459 public long getmtime(String key) {
460 return getmtime(key, UID_SELF);
461 }
462
Alex Klyubin469cbf52015-06-04 12:36:27 -0700463 // TODO: remove this when it's removed from Settings
Kenny Root5cb5cec2013-03-29 11:14:17 -0700464 public boolean isHardwareBacked() {
Kenny Rootb91773b2013-09-05 13:03:16 -0700465 return isHardwareBacked("RSA");
466 }
467
468 public boolean isHardwareBacked(String keyType) {
Kenny Root5cb5cec2013-03-29 11:14:17 -0700469 try {
Kenny Rootb91773b2013-09-05 13:03:16 -0700470 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
Kenny Root5cb5cec2013-03-29 11:14:17 -0700471 } catch (RemoteException e) {
472 Log.w(TAG, "Cannot connect to keystore", e);
473 return false;
474 }
475 }
476
Kenny Rootd72317a2013-04-01 15:59:59 -0700477 public boolean clearUid(int uid) {
478 try {
479 return mBinder.clear_uid(uid) == NO_ERROR;
480 } catch (RemoteException e) {
481 Log.w(TAG, "Cannot connect to keystore", e);
482 return false;
483 }
484 }
485
Chia-chi Yeh44039172009-09-21 11:53:59 +0800486 public int getLastError() {
487 return mError;
488 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800489
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800490 public boolean addRngEntropy(byte[] data, int flags) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800491 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700492 KeystoreResultPromise promise = new KeystoreResultPromise();
493 int errorCode = mBinder.addRngEntropy(promise, data, flags);
494 if (errorCode == NO_ERROR) {
495 return promise.getFuture().get().getErrorCode() == NO_ERROR;
496 } else {
497 return false;
498 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800499 } catch (RemoteException e) {
500 Log.w(TAG, "Cannot connect to keystore", e);
501 return false;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700502 } catch (ExecutionException | InterruptedException e) {
503 Log.e(TAG, "AddRngEntropy completed with exception", e);
504 return false;
Chad Brubakere6a461342015-02-10 21:33:23 -0800505 }
506 }
507
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700508 private class KeyCharacteristicsCallbackResult {
509 private KeystoreResponse keystoreResponse;
510 private KeyCharacteristics keyCharacteristics;
511
512 public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
513 KeyCharacteristics keyCharacteristics) {
514 this.keystoreResponse = keystoreResponse;
515 this.keyCharacteristics = keyCharacteristics;
516 }
517
518 public KeystoreResponse getKeystoreResponse() {
519 return keystoreResponse;
520 }
521
522 public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
523 this.keystoreResponse = keystoreResponse;
524 }
525
526 public KeyCharacteristics getKeyCharacteristics() {
527 return keyCharacteristics;
528 }
529
530 public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
531 this.keyCharacteristics = keyCharacteristics;
532 }
533 }
534
535 private class KeyCharacteristicsPromise
536 extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
537 final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
538 new CompletableFuture<KeyCharacteristicsCallbackResult>();
539 @Override
540 public void onFinished(KeystoreResponse keystoreResponse,
541 KeyCharacteristics keyCharacteristics)
542 throws android.os.RemoteException {
543 future.complete(
544 new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
545 }
546 public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
547 return future;
548 }
549 };
550
551 private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
552 int flags, KeyCharacteristics outCharacteristics)
553 throws RemoteException, ExecutionException, InterruptedException {
554 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
555 int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
556 if (error != NO_ERROR) {
557 Log.e(TAG, "generateKeyInternal failed on request " + error);
558 return error;
559 }
560
561 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
562 error = result.getKeystoreResponse().getErrorCode();
563 if (error != NO_ERROR) {
564 Log.e(TAG, "generateKeyInternal failed on response " + error);
565 return error;
566 }
567 KeyCharacteristics characteristics = result.getKeyCharacteristics();
568 if (characteristics == null) {
569 Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
570 return SYSTEM_ERROR;
571 }
572 outCharacteristics.shallowCopyFrom(characteristics);
573 return NO_ERROR;
574 }
575
Chad Brubakerdae79e52015-03-27 14:28:35 -0700576 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
577 int flags, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800578 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700579 entropy = entropy != null ? entropy : new byte[0];
580 args = args != null ? args : new KeymasterArguments();
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700581 int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700582 if (error == KEY_ALREADY_EXISTS) {
583 mBinder.del(alias, uid);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700584 error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700585 }
586 return error;
Chad Brubakere6a461342015-02-10 21:33:23 -0800587 } catch (RemoteException e) {
588 Log.w(TAG, "Cannot connect to keystore", e);
589 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700590 } catch (ExecutionException | InterruptedException e) {
591 Log.e(TAG, "generateKey completed with exception", e);
592 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800593 }
594 }
595
Chad Brubakerdae79e52015-03-27 14:28:35 -0700596 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800597 KeyCharacteristics outCharacteristics) {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700598 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800599 }
600
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700601 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700602 int uid, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800603 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700604 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
605 appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700606 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
607 int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
608 if (error != NO_ERROR) return error;
609
610 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
611 error = result.getKeystoreResponse().getErrorCode();
612 if (error != NO_ERROR) return error;
613
614 KeyCharacteristics characteristics = result.getKeyCharacteristics();
615 if (characteristics == null) return SYSTEM_ERROR;
616 outCharacteristics.shallowCopyFrom(characteristics);
617 return NO_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800618 } catch (RemoteException e) {
619 Log.w(TAG, "Cannot connect to keystore", e);
620 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700621 } catch (ExecutionException | InterruptedException e) {
622 Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
623 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800624 }
625 }
626
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700627 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
628 KeyCharacteristics outCharacteristics) {
629 return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
630 }
631
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700632 private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
633 int uid, int flags, KeyCharacteristics outCharacteristics)
634 throws RemoteException, ExecutionException, InterruptedException {
635 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
636 int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
637 if (error != NO_ERROR) return error;
638
639 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
640 error = result.getKeystoreResponse().getErrorCode();
641 if (error != NO_ERROR) return error;
642
643 KeyCharacteristics characteristics = result.getKeyCharacteristics();
644 if (characteristics == null) return SYSTEM_ERROR;
645 outCharacteristics.shallowCopyFrom(characteristics);
646 return NO_ERROR;
647 }
648
Chad Brubakere6a461342015-02-10 21:33:23 -0800649 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
650 int uid, int flags, KeyCharacteristics outCharacteristics) {
651 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700652 int error = importKeyInternal(alias, args, format, keyData, uid, flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800653 outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700654 if (error == KEY_ALREADY_EXISTS) {
655 mBinder.del(alias, uid);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700656 error = importKeyInternal(alias, args, format, keyData, uid, flags,
Janis Danisevskisd2575382018-10-08 07:56:58 -0700657 outCharacteristics);
658 }
659 return error;
Chad Brubakere6a461342015-02-10 21:33:23 -0800660 } catch (RemoteException e) {
661 Log.w(TAG, "Cannot connect to keystore", e);
662 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700663 } catch (ExecutionException | InterruptedException e) {
664 Log.e(TAG, "ImportKey completed with exception", e);
665 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800666 }
667 }
668
669 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
670 int flags, KeyCharacteristics outCharacteristics) {
671 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
672 }
673
Janis Danisevskis1864c952018-08-09 11:14:49 -0700674 private String getAlgorithmFromPKCS8(byte[] keyData) {
675 try {
676 final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
677 final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
678 final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
679 return new AlgorithmId(new ObjectIdentifier(algOid)).getName();
680 } catch (IOException e) {
681 Log.e(TAG, "getAlgorithmFromPKCS8 Failed to parse key data");
682 Log.e(TAG, Log.getStackTraceString(e));
683 return null;
684 }
685 }
686
687 private KeymasterArguments makeLegacyArguments(String algorithm) {
688 KeymasterArguments args = new KeymasterArguments();
689 args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
690 KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(algorithm));
691 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN);
692 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_VERIFY);
693 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
694 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
695 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
696 if (algorithm.equalsIgnoreCase(KeyProperties.KEY_ALGORITHM_RSA)) {
697 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
698 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
699 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
700 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PSS);
701 }
702 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
703 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
704 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
705 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
706 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
707 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
708 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
709 args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
Janis Danisevskis2b106ad2018-11-15 09:27:16 -0800710 args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
711 args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
712 args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, new Date(0));
Janis Danisevskis1864c952018-08-09 11:14:49 -0700713 return args;
714 }
715
716 public boolean importKey(String alias, byte[] keyData, int uid, int flags) {
717 String algorithm = getAlgorithmFromPKCS8(keyData);
718 if (algorithm == null) return false;
719 KeymasterArguments args = makeLegacyArguments(algorithm);
720 KeyCharacteristics out = new KeyCharacteristics();
721 int result = importKey(alias, args, KeymasterDefs.KM_KEY_FORMAT_PKCS8, keyData, uid,
722 flags, out);
723 if (result != NO_ERROR) {
724 Log.e(TAG, Log.getStackTraceString(
725 new KeyStoreException(result, "legacy key import failed")));
726 return false;
727 }
728 return true;
729 }
730
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700731 private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
732 String wrappingKeyAlias,
733 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
734 KeyCharacteristics outCharacteristics)
735 throws RemoteException, ExecutionException, InterruptedException {
736 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
737 int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
738 maskingKey, args, rootSid, fingerprintSid);
739 if (error != NO_ERROR) return error;
740
741 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
742 error = result.getKeystoreResponse().getErrorCode();
743 if (error != NO_ERROR) return error;
744
745 KeyCharacteristics characteristics = result.getKeyCharacteristics();
746 if (characteristics == null) return SYSTEM_ERROR;
747 outCharacteristics.shallowCopyFrom(characteristics);
748 return NO_ERROR;
749 }
750
Frank Salim21d9c1d2017-12-19 22:38:09 -0800751 public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
752 String wrappingKeyAlias,
753 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
754 KeyCharacteristics outCharacteristics) {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700755 // TODO b/119217337 uid parameter gets silently ignored.
Frank Salim21d9c1d2017-12-19 22:38:09 -0800756 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700757 int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
Frank Salim21d9c1d2017-12-19 22:38:09 -0800758 maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700759 if (error == KEY_ALREADY_EXISTS) {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700760 mBinder.del(wrappedKeyAlias, UID_SELF);
761 error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
Janis Danisevskisd2575382018-10-08 07:56:58 -0700762 maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
763 }
764 return error;
Frank Salim21d9c1d2017-12-19 22:38:09 -0800765 } catch (RemoteException e) {
766 Log.w(TAG, "Cannot connect to keystore", e);
767 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700768 } catch (ExecutionException | InterruptedException e) {
769 Log.e(TAG, "ImportWrappedKey completed with exception", e);
770 return SYSTEM_ERROR;
Frank Salim21d9c1d2017-12-19 22:38:09 -0800771 }
772 }
773
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700774 private class ExportKeyPromise
775 extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
776 final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
777 @Override
778 public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
779 future.complete(exportKeyResult);
780 }
781 public final CompletableFuture<ExportResult> getFuture() {
782 return future;
783 }
784 };
785
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700786 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700787 KeymasterBlob appId, int uid) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800788 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700789 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
790 appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700791 ExportKeyPromise promise = new ExportKeyPromise();
792 int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
793 if (error == NO_ERROR) {
794 return promise.getFuture().get();
795 } else {
796 return new ExportResult(error);
797 }
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700798 } catch (RemoteException e) {
799 Log.w(TAG, "Cannot connect to keystore", e);
800 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700801 } catch (ExecutionException | InterruptedException e) {
802 Log.e(TAG, "ExportKey completed with exception", e);
803 return null;
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700804 }
805 }
806 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
807 KeymasterBlob appId) {
808 return exportKey(alias, format, clientId, appId, UID_SELF);
809 }
810
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700811 private class OperationPromise
812 extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
813 final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
814 @Override
815 public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
816 future.complete(operationResult);
817 }
818 public final CompletableFuture<OperationResult> getFuture() {
819 return future;
820 }
821 };
822
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700823 public OperationResult begin(String alias, int purpose, boolean pruneable,
824 KeymasterArguments args, byte[] entropy, int uid) {
825 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700826 args = args != null ? args : new KeymasterArguments();
827 entropy = entropy != null ? entropy : new byte[0];
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700828 OperationPromise promise = new OperationPromise();
829 int errorCode = mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
830 entropy, uid);
831 if (errorCode == NO_ERROR) {
832 return promise.getFuture().get();
833 } else {
834 return new OperationResult(errorCode);
835 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800836 } catch (RemoteException e) {
837 Log.w(TAG, "Cannot connect to keystore", e);
838 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700839 } catch (ExecutionException | InterruptedException e) {
840 Log.e(TAG, "Begin completed with exception", e);
841 return null;
Chad Brubakere6a461342015-02-10 21:33:23 -0800842 }
843 }
844
845 public OperationResult begin(String alias, int purpose, boolean pruneable,
Chad Brubaker966486e2015-06-01 12:57:06 -0700846 KeymasterArguments args, byte[] entropy) {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700847 entropy = entropy != null ? entropy : new byte[0];
848 args = args != null ? args : new KeymasterArguments();
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700849 return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
Chad Brubakere6a461342015-02-10 21:33:23 -0800850 }
851
852 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
853 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700854 arguments = arguments != null ? arguments : new KeymasterArguments();
855 input = input != null ? input : new byte[0];
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700856 OperationPromise promise = new OperationPromise();
857 int errorCode = mBinder.update(promise, token, arguments, input);
858 if (errorCode == NO_ERROR) {
859 return promise.getFuture().get();
860 } else {
861 return new OperationResult(errorCode);
862 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800863 } catch (RemoteException e) {
864 Log.w(TAG, "Cannot connect to keystore", e);
865 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700866 } catch (ExecutionException | InterruptedException e) {
867 Log.e(TAG, "Update completed with exception", e);
868 return null;
Chad Brubakere6a461342015-02-10 21:33:23 -0800869 }
870 }
871
Chad Brubaker8a077012015-05-29 12:32:51 -0700872 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
873 byte[] entropy) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800874 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700875 arguments = arguments != null ? arguments : new KeymasterArguments();
876 entropy = entropy != null ? entropy : new byte[0];
877 signature = signature != null ? signature : new byte[0];
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700878 OperationPromise promise = new OperationPromise();
879 int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
880 if (errorCode == NO_ERROR) {
881 return promise.getFuture().get();
882 } else {
883 return new OperationResult(errorCode);
884 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800885 } catch (RemoteException e) {
886 Log.w(TAG, "Cannot connect to keystore", e);
887 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700888 } catch (ExecutionException | InterruptedException e) {
889 Log.e(TAG, "Finish completed with exception", e);
890 return null;
Chad Brubakere6a461342015-02-10 21:33:23 -0800891 }
892 }
893
Chad Brubaker8a077012015-05-29 12:32:51 -0700894 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
895 return finish(token, arguments, signature, null);
896 }
897
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700898 private class KeystoreResultPromise
899 extends android.security.keystore.IKeystoreResponseCallback.Stub {
900 final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
901 @Override
902 public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
903 future.complete(keystoreResponse);
904 }
905 public final CompletableFuture<KeystoreResponse> getFuture() {
906 return future;
907 }
908 };
909
Chad Brubakere6a461342015-02-10 21:33:23 -0800910 public int abort(IBinder token) {
911 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700912 KeystoreResultPromise promise = new KeystoreResultPromise();
913 int errorCode = mBinder.abort(promise, token);
914 if (errorCode == NO_ERROR) {
915 return promise.getFuture().get().getErrorCode();
916 } else {
917 return errorCode;
918 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800919 } catch (RemoteException e) {
920 Log.w(TAG, "Cannot connect to keystore", e);
921 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700922 } catch (ExecutionException | InterruptedException e) {
923 Log.e(TAG, "Abort completed with exception", e);
924 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800925 }
926 }
Chad Brubaker5654b362015-03-17 16:59:52 -0700927
928 /**
Chad Brubaker5654b362015-03-17 16:59:52 -0700929 * Add an authentication record to the keystore authorization table.
930 *
931 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
932 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
933 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
934 */
Brian Youngda82e2c2018-02-22 23:36:34 +0000935 public int addAuthToken(byte[] authToken) {
Chad Brubaker5654b362015-03-17 16:59:52 -0700936 try {
Brian Youngda82e2c2018-02-22 23:36:34 +0000937 return mBinder.addAuthToken(authToken);
Chad Brubaker5654b362015-03-17 16:59:52 -0700938 } catch (RemoteException e) {
939 Log.w(TAG, "Cannot connect to keystore", e);
940 return SYSTEM_ERROR;
941 }
942 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700943
Alex Klyubinad9ba102015-04-21 15:17:24 -0700944 /**
Chad Brubakera91a8502015-05-07 10:02:22 -0700945 * Notify keystore that a user's password has changed.
946 *
947 * @param userId the user whose password changed.
948 * @param newPassword the new password or "" if the password was removed.
949 */
950 public boolean onUserPasswordChanged(int userId, String newPassword) {
951 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
952 // explicit here.
953 if (newPassword == null) {
954 newPassword = "";
955 }
956 try {
957 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
958 } catch (RemoteException e) {
959 Log.w(TAG, "Cannot connect to keystore", e);
960 return false;
961 }
962 }
963
Chad Brubaker83ce0952015-05-12 13:00:02 -0700964 /**
965 * Notify keystore that a user was added.
966 *
967 * @param userId the new user.
968 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
969 * specified then the new user's keystore will be intialized with the same secure lockscreen
970 * password as the parent.
971 */
972 public void onUserAdded(int userId, int parentId) {
973 try {
974 mBinder.onUserAdded(userId, parentId);
975 } catch (RemoteException e) {
976 Log.w(TAG, "Cannot connect to keystore", e);
977 }
978 }
979
980 /**
981 * Notify keystore that a user was added.
982 *
983 * @param userId the new user.
984 */
985 public void onUserAdded(int userId) {
986 onUserAdded(userId, -1);
987 }
988
989 /**
990 * Notify keystore that a user was removed.
991 *
992 * @param userId the removed user.
993 */
994 public void onUserRemoved(int userId) {
995 try {
996 mBinder.onUserRemoved(userId);
997 } catch (RemoteException e) {
998 Log.w(TAG, "Cannot connect to keystore", e);
999 }
1000 }
1001
Chad Brubakera91a8502015-05-07 10:02:22 -07001002 public boolean onUserPasswordChanged(String newPassword) {
1003 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
1004 }
1005
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001006 private class KeyAttestationCallbackResult {
1007 private KeystoreResponse keystoreResponse;
1008 private KeymasterCertificateChain certificateChain;
1009
1010 public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
1011 KeymasterCertificateChain certificateChain) {
1012 this.keystoreResponse = keystoreResponse;
1013 this.certificateChain = certificateChain;
1014 }
1015
1016 public KeystoreResponse getKeystoreResponse() {
1017 return keystoreResponse;
1018 }
1019
1020 public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
1021 this.keystoreResponse = keystoreResponse;
1022 }
1023
1024 public KeymasterCertificateChain getCertificateChain() {
1025 return certificateChain;
1026 }
1027
1028 public void setCertificateChain(KeymasterCertificateChain certificateChain) {
1029 this.certificateChain = certificateChain;
1030 }
1031 }
1032
1033 private class CertificateChainPromise
1034 extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
1035 final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
1036 @Override
1037 public void onFinished(KeystoreResponse keystoreResponse,
1038 KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
1039 future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
1040 }
1041 public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
1042 return future;
1043 }
1044 };
1045
1046
Shawn Willden8d8c7472016-02-02 08:27:39 -07001047 public int attestKey(
1048 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
1049 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -07001050 if (params == null) {
1051 params = new KeymasterArguments();
1052 }
1053 if (outChain == null) {
1054 outChain = new KeymasterCertificateChain();
1055 }
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001056 CertificateChainPromise promise = new CertificateChainPromise();
1057 int error = mBinder.attestKey(promise, alias, params);
1058 if (error != NO_ERROR) return error;
1059 KeyAttestationCallbackResult result = promise.getFuture().get();
1060 error = result.getKeystoreResponse().getErrorCode();
1061 if (error == NO_ERROR) {
1062 outChain.shallowCopyFrom(result.getCertificateChain());
1063 }
1064 return error;
Shawn Willden8d8c7472016-02-02 08:27:39 -07001065 } catch (RemoteException e) {
1066 Log.w(TAG, "Cannot connect to keystore", e);
1067 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001068 } catch (ExecutionException | InterruptedException e) {
1069 Log.e(TAG, "AttestKey completed with exception", e);
1070 return SYSTEM_ERROR;
Shawn Willden8d8c7472016-02-02 08:27:39 -07001071 }
1072 }
1073
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +02001074 public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) {
1075 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -07001076 if (params == null) {
1077 params = new KeymasterArguments();
1078 }
1079 if (outChain == null) {
1080 outChain = new KeymasterCertificateChain();
1081 }
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001082 CertificateChainPromise promise = new CertificateChainPromise();
1083 int error = mBinder.attestDeviceIds(promise, params);
1084 if (error != NO_ERROR) return error;
1085 KeyAttestationCallbackResult result = promise.getFuture().get();
1086 error = result.getKeystoreResponse().getErrorCode();
1087 if (error == NO_ERROR) {
1088 outChain.shallowCopyFrom(result.getCertificateChain());
1089 }
1090 return error;
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +02001091 } catch (RemoteException e) {
1092 Log.w(TAG, "Cannot connect to keystore", e);
1093 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001094 } catch (ExecutionException | InterruptedException e) {
1095 Log.e(TAG, "AttestDevicdeIds completed with exception", e);
1096 return SYSTEM_ERROR;
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +02001097 }
1098 }
1099
Tucker Sylvestrob32aae22016-06-23 17:23:33 -04001100 /**
1101 * Notify keystore that the device went off-body.
1102 */
1103 public void onDeviceOffBody() {
1104 try {
1105 mBinder.onDeviceOffBody();
1106 } catch (RemoteException e) {
1107 Log.w(TAG, "Cannot connect to keystore", e);
1108 }
1109 }
Shawn Willden8d8c7472016-02-02 08:27:39 -07001110
Janis Danisevskis7dacad82018-01-24 15:12:11 -08001111 // Keep in sync with confirmationui/1.0/types.hal.
1112 public static final int CONFIRMATIONUI_OK = 0;
1113 public static final int CONFIRMATIONUI_CANCELED = 1;
1114 public static final int CONFIRMATIONUI_ABORTED = 2;
1115 public static final int CONFIRMATIONUI_OPERATION_PENDING = 3;
1116 public static final int CONFIRMATIONUI_IGNORED = 4;
1117 public static final int CONFIRMATIONUI_SYSTEM_ERROR = 5;
1118 public static final int CONFIRMATIONUI_UNIMPLEMENTED = 6;
1119 public static final int CONFIRMATIONUI_UNEXPECTED = 7;
1120 public static final int CONFIRMATIONUI_UIERROR = 0x10000;
1121 public static final int CONFIRMATIONUI_UIERROR_MISSING_GLYPH = 0x10001;
1122 public static final int CONFIRMATIONUI_UIERROR_MESSAGE_TOO_LONG = 0x10002;
1123 public static final int CONFIRMATIONUI_UIERROR_MALFORMED_UTF8_ENCODING = 0x10003;
1124
1125 /**
1126 * Requests keystore call into the confirmationui HAL to display a prompt.
1127 *
1128 * @param listener the binder to use for callbacks.
1129 * @param promptText the prompt to display.
1130 * @param extraData extra data / nonce from application.
1131 * @param locale the locale as a BCP 47 langauge tag.
1132 * @param uiOptionsAsFlags the UI options to use, as flags.
1133 * @return one of the {@code CONFIRMATIONUI_*} constants, for
1134 * example {@code KeyStore.CONFIRMATIONUI_OK}.
1135 */
1136 public int presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData,
1137 String locale, int uiOptionsAsFlags) {
1138 try {
1139 return mBinder.presentConfirmationPrompt(listener, promptText, extraData, locale,
1140 uiOptionsAsFlags);
1141 } catch (RemoteException e) {
1142 Log.w(TAG, "Cannot connect to keystore", e);
1143 return CONFIRMATIONUI_SYSTEM_ERROR;
1144 }
1145 }
1146
1147 /**
1148 * Requests keystore call into the confirmationui HAL to cancel displaying a prompt.
1149 *
1150 * @param listener the binder passed to the {@link #presentConfirmationPrompt} method.
1151 * @return one of the {@code CONFIRMATIONUI_*} constants, for
1152 * example {@code KeyStore.CONFIRMATIONUI_OK}.
1153 */
1154 public int cancelConfirmationPrompt(IBinder listener) {
1155 try {
1156 return mBinder.cancelConfirmationPrompt(listener);
1157 } catch (RemoteException e) {
1158 Log.w(TAG, "Cannot connect to keystore", e);
1159 return CONFIRMATIONUI_SYSTEM_ERROR;
1160 }
1161 }
1162
Chad Brubakera91a8502015-05-07 10:02:22 -07001163 /**
David Zeuthenbbb7f652018-02-26 11:04:18 -05001164 * Requests keystore to check if the confirmationui HAL is available.
1165 *
1166 * @return whether the confirmationUI HAL is available.
1167 */
1168 public boolean isConfirmationPromptSupported() {
1169 try {
1170 return mBinder.isConfirmationPromptSupported();
1171 } catch (RemoteException e) {
1172 Log.w(TAG, "Cannot connect to keystore", e);
1173 return false;
1174 }
1175 }
1176
1177 /**
Alex Klyubinad9ba102015-04-21 15:17:24 -07001178 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
1179 * code.
1180 */
Mathew Inwood4dbdcf42018-08-16 18:49:37 +01001181 @UnsupportedAppUsage
Alex Klyubindcdaf872015-05-13 15:57:09 -07001182 public static KeyStoreException getKeyStoreException(int errorCode) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001183 if (errorCode > 0) {
1184 // KeyStore layer error
1185 switch (errorCode) {
1186 case NO_ERROR:
1187 return new KeyStoreException(errorCode, "OK");
1188 case LOCKED:
Alex Klyubin54183932015-05-08 15:25:48 -07001189 return new KeyStoreException(errorCode, "User authentication required");
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001190 case UNINITIALIZED:
1191 return new KeyStoreException(errorCode, "Keystore not initialized");
1192 case SYSTEM_ERROR:
1193 return new KeyStoreException(errorCode, "System error");
1194 case PERMISSION_DENIED:
1195 return new KeyStoreException(errorCode, "Permission denied");
1196 case KEY_NOT_FOUND:
1197 return new KeyStoreException(errorCode, "Key not found");
1198 case VALUE_CORRUPTED:
1199 return new KeyStoreException(errorCode, "Key blob corrupted");
Alex Klyubin058de022015-04-29 17:32:00 -07001200 case OP_AUTH_NEEDED:
1201 return new KeyStoreException(errorCode, "Operation requires authorization");
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001202 default:
1203 return new KeyStoreException(errorCode, String.valueOf(errorCode));
1204 }
1205 } else {
1206 // Keymaster layer error
1207 switch (errorCode) {
1208 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
1209 // The name of this parameter significantly differs between Keymaster and
1210 // framework APIs. Use the framework wording to make life easier for developers.
1211 return new KeyStoreException(errorCode,
1212 "Invalid user authentication validity duration");
1213 default:
1214 return new KeyStoreException(errorCode,
1215 KeymasterDefs.getErrorMessage(errorCode));
1216 }
1217 }
1218 }
1219
Alex Klyubinad9ba102015-04-21 15:17:24 -07001220 /**
1221 * Returns an {@link InvalidKeyException} corresponding to the provided
1222 * {@link KeyStoreException}.
1223 */
Alex Klyubindcdaf872015-05-13 15:57:09 -07001224 public InvalidKeyException getInvalidKeyException(
Alex Klyubin3876b1b2015-09-09 14:55:03 -07001225 String keystoreKeyAlias, int uid, KeyStoreException e) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001226 switch (e.getErrorCode()) {
Brian Youngda82e2c2018-02-22 23:36:34 +00001227 case LOCKED:
Alex Klyubin54183932015-05-08 15:25:48 -07001228 return new UserNotAuthenticatedException();
Brian Youngda82e2c2018-02-22 23:36:34 +00001229 case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001230 return new KeyExpiredException();
Brian Youngda82e2c2018-02-22 23:36:34 +00001231 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001232 return new KeyNotYetValidException();
Brian Youngda82e2c2018-02-22 23:36:34 +00001233 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
1234 case OP_AUTH_NEEDED:
Alex Klyubin708fc9402015-04-28 18:58:47 -07001235 {
1236 // We now need to determine whether the key/operation can become usable if user
1237 // authentication is performed, or whether it can never become usable again.
1238 // User authentication requirements are contained in the key's characteristics. We
1239 // need to check whether these requirements can be be satisfied by asking the user
1240 // to authenticate.
1241 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
1242 int getKeyCharacteristicsErrorCode =
Alex Klyubin3876b1b2015-09-09 14:55:03 -07001243 getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
1244 keyCharacteristics);
Alex Klyubin708fc9402015-04-28 18:58:47 -07001245 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
1246 return new InvalidKeyException(
1247 "Failed to obtained key characteristics",
1248 getKeyStoreException(getKeyCharacteristicsErrorCode));
1249 }
Alex Klyubinae6cb7a2015-06-22 18:09:35 -07001250 List<BigInteger> keySids =
1251 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
Alex Klyubin708fc9402015-04-28 18:58:47 -07001252 if (keySids.isEmpty()) {
1253 // Key is not bound to any SIDs -- no amount of authentication will help here.
1254 return new KeyPermanentlyInvalidatedException();
1255 }
1256 long rootSid = GateKeeper.getSecureUserId();
Alex Klyubinae6cb7a2015-06-22 18:09:35 -07001257 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -07001258 // One of the key's SIDs is the current root SID -- user can be authenticated
1259 // against that SID.
1260 return new UserNotAuthenticatedException();
1261 }
1262
1263 long fingerprintOnlySid = getFingerprintOnlySid();
1264 if ((fingerprintOnlySid != 0)
Alex Klyubinae6cb7a2015-06-22 18:09:35 -07001265 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -07001266 // One of the key's SIDs is the current fingerprint SID -- user can be
1267 // authenticated against that SID.
1268 return new UserNotAuthenticatedException();
1269 }
1270
1271 // None of the key's SIDs can ever be authenticated
1272 return new KeyPermanentlyInvalidatedException();
1273 }
Brian Youngda82e2c2018-02-22 23:36:34 +00001274 case UNINITIALIZED:
Janis Danisevskisd07d3382017-09-01 14:45:16 -07001275 return new KeyPermanentlyInvalidatedException();
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001276 default:
Alex Klyubinad9ba102015-04-21 15:17:24 -07001277 return new InvalidKeyException("Keystore operation failed", e);
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001278 }
1279 }
1280
Alex Klyubin2d7a85c2015-04-30 11:43:53 -07001281 private long getFingerprintOnlySid() {
Kevin Chyn55966422017-10-23 16:08:47 -07001282 final PackageManager packageManager = mContext.getPackageManager();
1283 if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
1284 return 0;
1285 }
Alex Klyubina99b8b52015-06-11 13:27:34 -07001286 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
Alex Klyubin2d7a85c2015-04-30 11:43:53 -07001287 if (fingerprintManager == null) {
Alex Klyubin708fc9402015-04-28 18:58:47 -07001288 return 0;
1289 }
1290
Alex Klyubina99b8b52015-06-11 13:27:34 -07001291 // TODO: Restore USE_FINGERPRINT permission check in
1292 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
Alex Klyubin2d7a85c2015-04-30 11:43:53 -07001293 return fingerprintManager.getAuthenticatorId();
Svetoslav2dac95d2015-04-30 11:30:33 -07001294 }
1295
Alex Klyubinad9ba102015-04-21 15:17:24 -07001296 /**
1297 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
1298 * code.
1299 */
Alex Klyubin3876b1b2015-09-09 14:55:03 -07001300 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
1301 int errorCode) {
1302 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001303 }
Chia-chi Yeh44039172009-09-21 11:53:59 +08001304}