blob: 7710a9cf6ac7524f23d5ee2859d77d2f73e0e2e1 [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;
28import android.os.IBinder;
Chad Brubakera91a8502015-05-07 10:02:22 -070029import android.os.Process;
Kenny Root6b776452012-11-02 15:40:32 -070030import android.os.RemoteException;
31import android.os.ServiceManager;
Chad Brubakera91a8502015-05-07 10:02:22 -070032import android.os.UserHandle;
Janis Danisevskis1864c952018-08-09 11:14:49 -070033import android.security.KeyStoreException;
Chad Brubakere6a461342015-02-10 21:33:23 -080034import android.security.keymaster.ExportResult;
35import android.security.keymaster.KeyCharacteristics;
36import android.security.keymaster.KeymasterArguments;
Chad Brubaker5e73c0e2015-03-21 22:46:43 -070037import android.security.keymaster.KeymasterBlob;
Shawn Willden8d8c7472016-02-02 08:27:39 -070038import android.security.keymaster.KeymasterCertificateChain;
Alex Klyubinb4834ae2015-04-02 15:53:46 -070039import android.security.keymaster.KeymasterDefs;
Chad Brubakere6a461342015-02-10 21:33:23 -080040import android.security.keymaster.OperationResult;
Janis Danisevskisb0358e72018-11-02 10:34:07 -070041import android.security.keystore.IKeystoreService;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070042import android.security.keystore.KeyExpiredException;
43import android.security.keystore.KeyNotYetValidException;
44import android.security.keystore.KeyPermanentlyInvalidatedException;
Janis Danisevskis1864c952018-08-09 11:14:49 -070045import android.security.keystore.KeyProperties;
46import android.security.keystore.KeyProtection;
Janis Danisevskisb0358e72018-11-02 10:34:07 -070047import android.security.keystore.KeystoreResponse;
Frank Salimea5e0382018-01-23 22:42:29 -080048import android.security.keystore.StrongBoxUnavailableException;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070049import android.security.keystore.UserNotAuthenticatedException;
Kenny Root6b776452012-11-02 15:40:32 -070050import android.util.Log;
Janis Danisevskis1864c952018-08-09 11:14:49 -070051import com.android.org.bouncycastle.asn1.ASN1InputStream;
52import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
Alex Klyubinae6cb7a2015-06-22 18:09:35 -070053import java.math.BigInteger;
Janis Danisevskis1864c952018-08-09 11:14:49 -070054import java.io.ByteArrayInputStream;
55import java.io.IOException;
Alex Klyubinad9ba102015-04-21 15:17:24 -070056import java.security.InvalidKeyException;
Rob Barnesf1a678e2018-11-13 15:57:22 -070057import java.util.Arrays;
Janis Danisevskis2b106ad2018-11-15 09:27:16 -080058import java.util.Date;
Alex Klyubin708fc9402015-04-28 18:58:47 -070059import java.util.List;
Kenny Rootb91773b2013-09-05 13:03:16 -070060import java.util.Locale;
Janis Danisevskisb0358e72018-11-02 10:34:07 -070061import java.util.concurrent.CompletableFuture;
62import java.util.concurrent.ExecutionException;
Janis Danisevskis1864c952018-08-09 11:14:49 -070063import sun.security.util.ObjectIdentifier;
64import sun.security.x509.AlgorithmId;
Kenny Rootb91773b2013-09-05 13:03:16 -070065
Chia-chi Yeh44039172009-09-21 11:53:59 +080066/**
Brian Carlstrom46703b02011-04-06 15:41:29 -070067 * @hide This should not be made public in its present form because it
68 * assumes that private and secret key bytes are available and would
69 * preclude the use of hardware crypto.
Chia-chi Yeh44039172009-09-21 11:53:59 +080070 */
71public class KeyStore {
Kenny Root6b776452012-11-02 15:40:32 -070072 private static final String TAG = "KeyStore";
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070073
Dmitry Dementyevefc43112017-10-27 23:10:28 -070074 // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
Mathew Inwood4dbdcf42018-08-16 18:49:37 +010075 @UnsupportedAppUsage
Brian Carlstrom7e4b1a42011-06-01 15:29:29 -070076 public static final int NO_ERROR = 1;
77 public static final int LOCKED = 2;
78 public static final int UNINITIALIZED = 3;
79 public static final int SYSTEM_ERROR = 4;
80 public static final int PROTOCOL_ERROR = 5;
81 public static final int PERMISSION_DENIED = 6;
82 public static final int KEY_NOT_FOUND = 7;
83 public static final int VALUE_CORRUPTED = 8;
84 public static final int UNDEFINED_ACTION = 9;
85 public static final int WRONG_PASSWORD = 10;
Janis Danisevskisd2575382018-10-08 07:56:58 -070086 public static final int KEY_ALREADY_EXISTS = 16;
Eran Messeri61692392018-03-26 16:43:14 +010087 public static final int CANNOT_ATTEST_IDS = -66;
Frank Salimea5e0382018-01-23 22:42:29 -080088 public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070089
Chad Brubaker560d6532015-04-24 10:32:18 -070090 /**
91 * Per operation authentication is needed before this operation is valid.
92 * This is returned from {@link #begin} when begin succeeds but the operation uses
93 * per-operation authentication and must authenticate before calling {@link #update} or
94 * {@link #finish}.
95 */
96 public static final int OP_AUTH_NEEDED = 15;
97
Max Biresb2cc3dc2018-11-02 10:50:40 -070098 // Used when a user changes their pin, invalidating old auth bound keys.
99 public static final int KEY_PERMANENTLY_INVALIDATED = 17;
100
Kenny Root2eeda722013-04-10 11:30:58 -0700101 // Used for UID field to indicate the calling UID.
102 public static final int UID_SELF = -1;
103
104 // Flags for "put" "import" and "generate"
105 public static final int FLAG_NONE = 0;
Alex Klyubin54183932015-05-08 15:25:48 -0700106
107 /**
108 * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key
109 * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern).
110 *
111 * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set
112 * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key
113 * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or
114 * a Device Administrator). Finally, this key (or key pair) cannot be used until the user
115 * unlocks the secure lock screen after boot.
116 *
117 * @see KeyguardManager#isDeviceSecure()
118 */
Kenny Roota3788b02013-04-10 10:37:55 -0700119 public static final int FLAG_ENCRYPTED = 1;
120
Rubin Xu12b644d2017-04-21 19:21:42 +0100121 /**
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800122 * Select Software keymaster device, which as of this writing is the lowest security
123 * level available on an android device. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
124 * A TEE based keymaster implementation is implied.
125 *
126 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
127 * For historical reasons this corresponds to the KEYSTORE_FLAG_FALLBACK flag.
128 */
129 public static final int FLAG_SOFTWARE = 1 << 1;
130
131 /**
Rubin Xu12b644d2017-04-21 19:21:42 +0100132 * A private flag that's only available to system server to indicate that this key is part of
133 * device encryption flow so it receives special treatment from keystore. For example this key
134 * will not be super encrypted, and it will be stored separately under an unique UID instead
135 * of the caller UID i.e. SYSTEM.
136 *
137 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
138 */
139 public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
140
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800141 /**
142 * Select Strongbox keymaster device, which as of this writing the the highest security level
143 * available an android devices. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
144 * A TEE based keymaster implementation is implied.
145 *
146 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
147 */
148 public static final int FLAG_STRONGBOX = 1 << 4;
149
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700150 // States
Mathew Inwoodefb48162018-08-01 10:24:49 +0100151 public enum State {
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100152 @UnsupportedAppUsage
Mathew Inwoodefb48162018-08-01 10:24:49 +0100153 UNLOCKED,
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100154 @UnsupportedAppUsage
Mathew Inwoodefb48162018-08-01 10:24:49 +0100155 LOCKED,
156 UNINITIALIZED
157 };
Chia-chi Yeh44039172009-09-21 11:53:59 +0800158
Chia-chi Yeh44039172009-09-21 11:53:59 +0800159 private int mError = NO_ERROR;
160
Kenny Root6b776452012-11-02 15:40:32 -0700161 private final IKeystoreService mBinder;
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700162 private final Context mContext;
Kenny Root6b776452012-11-02 15:40:32 -0700163
Chad Brubakere6a461342015-02-10 21:33:23 -0800164 private IBinder mToken;
165
Kenny Root6b776452012-11-02 15:40:32 -0700166 private KeyStore(IKeystoreService binder) {
167 mBinder = binder;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -0700168 mContext = getApplicationContext();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700169 }
170
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100171 @UnsupportedAppUsage
Alex Klyubindcdaf872015-05-13 15:57:09 -0700172 public static Context getApplicationContext() {
Alex Klyubina99b8b52015-06-11 13:27:34 -0700173 Application application = ActivityThread.currentApplication();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700174 if (application == null) {
175 throw new IllegalStateException(
Alex Klyubina99b8b52015-06-11 13:27:34 -0700176 "Failed to obtain application Context from ActivityThread");
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700177 }
178 return application;
Kenny Root6b776452012-11-02 15:40:32 -0700179 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800180
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100181 @UnsupportedAppUsage
Chia-chi Yeh44039172009-09-21 11:53:59 +0800182 public static KeyStore getInstance() {
Kenny Root6b776452012-11-02 15:40:32 -0700183 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
184 .getService("android.security.keystore"));
185 return new KeyStore(keystore);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800186 }
187
Chad Brubakere6a461342015-02-10 21:33:23 -0800188 private synchronized IBinder getToken() {
189 if (mToken == null) {
190 mToken = new Binder();
191 }
192 return mToken;
193 }
194
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100195 @UnsupportedAppUsage
Chad Brubakere35d49f2015-05-12 15:19:52 -0700196 public State state(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700197 final int ret;
198 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700199 ret = mBinder.getState(userId);
Kenny Root6b776452012-11-02 15:40:32 -0700200 } catch (RemoteException e) {
201 Log.w(TAG, "Cannot connect to keystore", e);
202 throw new AssertionError(e);
203 }
204
205 switch (ret) {
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700206 case NO_ERROR: return State.UNLOCKED;
207 case LOCKED: return State.LOCKED;
208 case UNINITIALIZED: return State.UNINITIALIZED;
209 default: throw new AssertionError(mError);
210 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800211 }
212
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100213 @UnsupportedAppUsage
Chad Brubakere35d49f2015-05-12 15:19:52 -0700214 public State state() {
215 return state(UserHandle.myUserId());
216 }
217
Kenny Rootb9594ce2013-02-14 10:18:38 -0800218 public boolean isUnlocked() {
219 return state() == State.UNLOCKED;
220 }
221
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700222 public byte[] get(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700223 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700224 key = key != null ? key : "";
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700225 return mBinder.get(key, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700226 } catch (RemoteException e) {
227 Log.w(TAG, "Cannot connect to keystore", e);
228 return null;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700229 } catch (android.os.ServiceSpecificException e) {
230 Log.w(TAG, "KeyStore exception", e);
231 return null;
Kenny Root6b776452012-11-02 15:40:32 -0700232 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800233 }
234
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100235 @UnsupportedAppUsage
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700236 public byte[] get(String key) {
237 return get(key, UID_SELF);
238 }
239
Kenny Roota3788b02013-04-10 10:37:55 -0700240 public boolean put(String key, byte[] value, int uid, int flags) {
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700241 return insert(key, value, uid, flags) == NO_ERROR;
242 }
243
244 public int insert(String key, byte[] value, int uid, int flags) {
Kenny Root6b776452012-11-02 15:40:32 -0700245 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700246 if (value == null) {
247 value = new byte[0];
248 }
Janis Danisevskisd2575382018-10-08 07:56:58 -0700249 int error = mBinder.insert(key, value, uid, flags);
250 if (error == KEY_ALREADY_EXISTS) {
251 mBinder.del(key, uid);
252 error = mBinder.insert(key, value, uid, flags);
253 }
254 return error;
Kenny Root78ad8492013-02-13 17:02:57 -0800255 } catch (RemoteException e) {
256 Log.w(TAG, "Cannot connect to keystore", e);
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700257 return SYSTEM_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800258 }
259 }
260
Janis Danisevskis906147c2018-11-06 14:14:05 -0800261 int delete2(String key, int uid) {
Kenny Root78ad8492013-02-13 17:02:57 -0800262 try {
Janis Danisevskis906147c2018-11-06 14:14:05 -0800263 return mBinder.del(key, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700264 } catch (RemoteException e) {
265 Log.w(TAG, "Cannot connect to keystore", e);
Janis Danisevskis906147c2018-11-06 14:14:05 -0800266 return SYSTEM_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700267 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800268 }
269
Janis Danisevskis906147c2018-11-06 14:14:05 -0800270 public boolean delete(String key, int uid) {
271 int ret = delete2(key, uid);
272 return ret == NO_ERROR || ret == KEY_NOT_FOUND;
273 }
274
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100275 @UnsupportedAppUsage
Chia-chi Yeh44039172009-09-21 11:53:59 +0800276 public boolean delete(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700277 return delete(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800278 }
279
280 public boolean contains(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700281 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800282 return mBinder.exist(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700283 } catch (RemoteException e) {
284 Log.w(TAG, "Cannot connect to keystore", e);
285 return false;
286 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800287 }
288
289 public boolean contains(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700290 return contains(key, UID_SELF);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800291 }
292
Chad Brubakere35d49f2015-05-12 15:19:52 -0700293 /**
294 * List all entries in the keystore for {@code uid} starting with {@code prefix}.
295 */
296 public String[] list(String prefix, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700297 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700298 return mBinder.list(prefix, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700299 } catch (RemoteException e) {
300 Log.w(TAG, "Cannot connect to keystore", e);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800301 return null;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700302 } catch (android.os.ServiceSpecificException e) {
303 Log.w(TAG, "KeyStore exception", e);
304 return null;
Chia-chi Yeh44039172009-09-21 11:53:59 +0800305 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800306 }
307
Rob Barnesf1a678e2018-11-13 15:57:22 -0700308 /**
309 * List uids of all keys that are auth bound to the current user.
310 * Only system is allowed to call this method.
311 */
312 @UnsupportedAppUsage
313 public int[] listUidsOfAuthBoundKeys() {
314 final int MAX_RESULT_SIZE = 100;
315 int[] uidsOut = new int[MAX_RESULT_SIZE];
316 try {
317 int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
318 if (rc != NO_ERROR) {
319 Log.w(TAG, String.format("listUidsOfAuthBoundKeys failed with error code %d", rc));
320 return null;
321 }
322 } catch (RemoteException e) {
323 Log.w(TAG, "Cannot connect to keystore", e);
324 return null;
325 } catch (android.os.ServiceSpecificException e) {
326 Log.w(TAG, "KeyStore exception", e);
327 return null;
328 }
329 // Remove any 0 entries
330 return Arrays.stream(uidsOut).filter(x -> x > 0).toArray();
331 }
332
Chad Brubakere35d49f2015-05-12 15:19:52 -0700333 public String[] list(String prefix) {
334 return list(prefix, UID_SELF);
335 }
336
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100337 @UnsupportedAppUsage
Chia-chi Yeh44039172009-09-21 11:53:59 +0800338 public boolean reset() {
Kenny Root6b776452012-11-02 15:40:32 -0700339 try {
340 return mBinder.reset() == NO_ERROR;
341 } catch (RemoteException e) {
342 Log.w(TAG, "Cannot connect to keystore", e);
343 return false;
344 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800345 }
346
Chad Brubakere35d49f2015-05-12 15:19:52 -0700347 /**
348 * Attempt to lock the keystore for {@code user}.
349 *
Brian Young36716eb2018-02-23 18:04:20 +0000350 * @param userId Android user to lock.
Chad Brubakere35d49f2015-05-12 15:19:52 -0700351 * @return whether {@code user}'s keystore was locked.
352 */
353 public boolean lock(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700354 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700355 return mBinder.lock(userId) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700356 } catch (RemoteException e) {
357 Log.w(TAG, "Cannot connect to keystore", e);
358 return false;
359 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800360 }
361
Chad Brubakere35d49f2015-05-12 15:19:52 -0700362 public boolean lock() {
363 return lock(UserHandle.myUserId());
364 }
365
Chad Brubakera91a8502015-05-07 10:02:22 -0700366 /**
367 * Attempt to unlock the keystore for {@code user} with the password {@code password}.
368 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
369 * created.
370 *
Brian Young36716eb2018-02-23 18:04:20 +0000371 * @param userId Android user ID to operate on
Chad Brubakera91a8502015-05-07 10:02:22 -0700372 * @param password user's keystore password. Should be the most recent value passed to
373 * {@link #onUserPasswordChanged} for the user.
374 *
375 * @return whether the keystore was unlocked.
376 */
377 public boolean unlock(int userId, String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700378 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700379 password = password != null ? password : "";
Chad Brubakera91a8502015-05-07 10:02:22 -0700380 mError = mBinder.unlock(userId, password);
Kenny Root6b776452012-11-02 15:40:32 -0700381 return mError == NO_ERROR;
382 } catch (RemoteException e) {
383 Log.w(TAG, "Cannot connect to keystore", e);
384 return false;
385 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800386 }
387
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100388 @UnsupportedAppUsage
Chad Brubakera91a8502015-05-07 10:02:22 -0700389 public boolean unlock(String password) {
390 return unlock(UserHandle.getUserId(Process.myUid()), password);
391 }
392
Chad Brubakere35d49f2015-05-12 15:19:52 -0700393 /**
394 * Check if the keystore for {@code userId} is empty.
395 */
396 public boolean isEmpty(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700397 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700398 return mBinder.isEmpty(userId) != 0;
Kenny Root6b776452012-11-02 15:40:32 -0700399 } catch (RemoteException e) {
400 Log.w(TAG, "Cannot connect to keystore", e);
401 return false;
402 }
Kenny Root5423e682011-11-14 08:43:13 -0800403 }
404
Mathew Inwood4dbdcf42018-08-16 18:49:37 +0100405 @UnsupportedAppUsage
Chad Brubakere35d49f2015-05-12 15:19:52 -0700406 public boolean isEmpty() {
407 return isEmpty(UserHandle.myUserId());
408 }
409
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700410 public String grant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700411 try {
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700412 String grantAlias = mBinder.grant(key, uid);
413 if (grantAlias == "") return null;
414 return grantAlias;
Kenny Root6b776452012-11-02 15:40:32 -0700415 } catch (RemoteException e) {
416 Log.w(TAG, "Cannot connect to keystore", e);
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700417 return null;
Kenny Root6b776452012-11-02 15:40:32 -0700418 }
Kenny Root5423e682011-11-14 08:43:13 -0800419 }
420
421 public boolean ungrant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700422 try {
423 return mBinder.ungrant(key, uid) == NO_ERROR;
424 } catch (RemoteException e) {
425 Log.w(TAG, "Cannot connect to keystore", e);
426 return false;
Kenny Root473c7122012-08-17 21:13:48 -0700427 }
Kenny Root473c7122012-08-17 21:13:48 -0700428 }
429
430 /**
431 * Returns the last modification time of the key in milliseconds since the
432 * epoch. Will return -1L if the key could not be found or other error.
433 */
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700434 public long getmtime(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700435 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700436 final long millis = mBinder.getmtime(key, uid);
Kenny Roote66769a2013-02-04 15:49:11 -0800437 if (millis == -1L) {
438 return -1L;
439 }
440
441 return millis * 1000L;
Kenny Root6b776452012-11-02 15:40:32 -0700442 } catch (RemoteException e) {
443 Log.w(TAG, "Cannot connect to keystore", e);
444 return -1L;
445 }
Kenny Root473c7122012-08-17 21:13:48 -0700446 }
447
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700448 public long getmtime(String key) {
449 return getmtime(key, UID_SELF);
450 }
451
Alex Klyubin469cbf52015-06-04 12:36:27 -0700452 // TODO: remove this when it's removed from Settings
Kenny Root5cb5cec2013-03-29 11:14:17 -0700453 public boolean isHardwareBacked() {
Kenny Rootb91773b2013-09-05 13:03:16 -0700454 return isHardwareBacked("RSA");
455 }
456
457 public boolean isHardwareBacked(String keyType) {
Kenny Root5cb5cec2013-03-29 11:14:17 -0700458 try {
Kenny Rootb91773b2013-09-05 13:03:16 -0700459 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
Kenny Root5cb5cec2013-03-29 11:14:17 -0700460 } catch (RemoteException e) {
461 Log.w(TAG, "Cannot connect to keystore", e);
462 return false;
463 }
464 }
465
Kenny Rootd72317a2013-04-01 15:59:59 -0700466 public boolean clearUid(int uid) {
467 try {
468 return mBinder.clear_uid(uid) == NO_ERROR;
469 } catch (RemoteException e) {
470 Log.w(TAG, "Cannot connect to keystore", e);
471 return false;
472 }
473 }
474
Chia-chi Yeh44039172009-09-21 11:53:59 +0800475 public int getLastError() {
476 return mError;
477 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800478
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800479 public boolean addRngEntropy(byte[] data, int flags) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800480 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700481 KeystoreResultPromise promise = new KeystoreResultPromise();
482 int errorCode = mBinder.addRngEntropy(promise, data, flags);
483 if (errorCode == NO_ERROR) {
484 return promise.getFuture().get().getErrorCode() == NO_ERROR;
485 } else {
486 return false;
487 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800488 } catch (RemoteException e) {
489 Log.w(TAG, "Cannot connect to keystore", e);
490 return false;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700491 } catch (ExecutionException | InterruptedException e) {
492 Log.e(TAG, "AddRngEntropy completed with exception", e);
493 return false;
Chad Brubakere6a461342015-02-10 21:33:23 -0800494 }
495 }
496
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700497 private class KeyCharacteristicsCallbackResult {
498 private KeystoreResponse keystoreResponse;
499 private KeyCharacteristics keyCharacteristics;
500
501 public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
502 KeyCharacteristics keyCharacteristics) {
503 this.keystoreResponse = keystoreResponse;
504 this.keyCharacteristics = keyCharacteristics;
505 }
506
507 public KeystoreResponse getKeystoreResponse() {
508 return keystoreResponse;
509 }
510
511 public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
512 this.keystoreResponse = keystoreResponse;
513 }
514
515 public KeyCharacteristics getKeyCharacteristics() {
516 return keyCharacteristics;
517 }
518
519 public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
520 this.keyCharacteristics = keyCharacteristics;
521 }
522 }
523
524 private class KeyCharacteristicsPromise
525 extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
526 final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
527 new CompletableFuture<KeyCharacteristicsCallbackResult>();
528 @Override
529 public void onFinished(KeystoreResponse keystoreResponse,
530 KeyCharacteristics keyCharacteristics)
531 throws android.os.RemoteException {
532 future.complete(
533 new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
534 }
535 public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
536 return future;
537 }
538 };
539
540 private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
541 int flags, KeyCharacteristics outCharacteristics)
542 throws RemoteException, ExecutionException, InterruptedException {
543 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
544 int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
545 if (error != NO_ERROR) {
546 Log.e(TAG, "generateKeyInternal failed on request " + error);
547 return error;
548 }
549
550 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
551 error = result.getKeystoreResponse().getErrorCode();
552 if (error != NO_ERROR) {
553 Log.e(TAG, "generateKeyInternal failed on response " + error);
554 return error;
555 }
556 KeyCharacteristics characteristics = result.getKeyCharacteristics();
557 if (characteristics == null) {
558 Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
559 return SYSTEM_ERROR;
560 }
561 outCharacteristics.shallowCopyFrom(characteristics);
562 return NO_ERROR;
563 }
564
Chad Brubakerdae79e52015-03-27 14:28:35 -0700565 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
566 int flags, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800567 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700568 entropy = entropy != null ? entropy : new byte[0];
569 args = args != null ? args : new KeymasterArguments();
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700570 int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700571 if (error == KEY_ALREADY_EXISTS) {
572 mBinder.del(alias, uid);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700573 error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700574 }
575 return error;
Chad Brubakere6a461342015-02-10 21:33:23 -0800576 } catch (RemoteException e) {
577 Log.w(TAG, "Cannot connect to keystore", e);
578 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700579 } catch (ExecutionException | InterruptedException e) {
580 Log.e(TAG, "generateKey completed with exception", e);
581 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800582 }
583 }
584
Chad Brubakerdae79e52015-03-27 14:28:35 -0700585 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800586 KeyCharacteristics outCharacteristics) {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700587 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800588 }
589
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700590 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700591 int uid, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800592 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700593 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
594 appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700595 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
596 int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
597 if (error != NO_ERROR) return error;
598
599 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
600 error = result.getKeystoreResponse().getErrorCode();
601 if (error != NO_ERROR) return error;
602
603 KeyCharacteristics characteristics = result.getKeyCharacteristics();
604 if (characteristics == null) return SYSTEM_ERROR;
605 outCharacteristics.shallowCopyFrom(characteristics);
606 return NO_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800607 } catch (RemoteException e) {
608 Log.w(TAG, "Cannot connect to keystore", e);
609 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700610 } catch (ExecutionException | InterruptedException e) {
611 Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
612 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800613 }
614 }
615
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700616 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
617 KeyCharacteristics outCharacteristics) {
618 return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
619 }
620
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700621 private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
622 int uid, int flags, KeyCharacteristics outCharacteristics)
623 throws RemoteException, ExecutionException, InterruptedException {
624 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
625 int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
626 if (error != NO_ERROR) return error;
627
628 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
629 error = result.getKeystoreResponse().getErrorCode();
630 if (error != NO_ERROR) return error;
631
632 KeyCharacteristics characteristics = result.getKeyCharacteristics();
633 if (characteristics == null) return SYSTEM_ERROR;
634 outCharacteristics.shallowCopyFrom(characteristics);
635 return NO_ERROR;
636 }
637
Chad Brubakere6a461342015-02-10 21:33:23 -0800638 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
639 int uid, int flags, KeyCharacteristics outCharacteristics) {
640 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700641 int error = importKeyInternal(alias, args, format, keyData, uid, flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800642 outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700643 if (error == KEY_ALREADY_EXISTS) {
644 mBinder.del(alias, uid);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700645 error = importKeyInternal(alias, args, format, keyData, uid, flags,
Janis Danisevskisd2575382018-10-08 07:56:58 -0700646 outCharacteristics);
647 }
648 return error;
Chad Brubakere6a461342015-02-10 21:33:23 -0800649 } catch (RemoteException e) {
650 Log.w(TAG, "Cannot connect to keystore", e);
651 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700652 } catch (ExecutionException | InterruptedException e) {
653 Log.e(TAG, "ImportKey completed with exception", e);
654 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800655 }
656 }
657
658 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
659 int flags, KeyCharacteristics outCharacteristics) {
660 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
661 }
662
Janis Danisevskis1864c952018-08-09 11:14:49 -0700663 private String getAlgorithmFromPKCS8(byte[] keyData) {
664 try {
665 final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
666 final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
667 final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
668 return new AlgorithmId(new ObjectIdentifier(algOid)).getName();
669 } catch (IOException e) {
670 Log.e(TAG, "getAlgorithmFromPKCS8 Failed to parse key data");
671 Log.e(TAG, Log.getStackTraceString(e));
672 return null;
673 }
674 }
675
676 private KeymasterArguments makeLegacyArguments(String algorithm) {
677 KeymasterArguments args = new KeymasterArguments();
678 args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
679 KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(algorithm));
680 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN);
681 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_VERIFY);
682 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
683 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
684 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
685 if (algorithm.equalsIgnoreCase(KeyProperties.KEY_ALGORITHM_RSA)) {
686 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
687 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
688 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
689 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PSS);
690 }
691 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
692 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
693 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
694 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
695 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
696 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
697 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
698 args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
Janis Danisevskis2b106ad2018-11-15 09:27:16 -0800699 args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
700 args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
701 args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, new Date(0));
Janis Danisevskis1864c952018-08-09 11:14:49 -0700702 return args;
703 }
704
705 public boolean importKey(String alias, byte[] keyData, int uid, int flags) {
706 String algorithm = getAlgorithmFromPKCS8(keyData);
707 if (algorithm == null) return false;
708 KeymasterArguments args = makeLegacyArguments(algorithm);
709 KeyCharacteristics out = new KeyCharacteristics();
710 int result = importKey(alias, args, KeymasterDefs.KM_KEY_FORMAT_PKCS8, keyData, uid,
711 flags, out);
712 if (result != NO_ERROR) {
713 Log.e(TAG, Log.getStackTraceString(
714 new KeyStoreException(result, "legacy key import failed")));
715 return false;
716 }
717 return true;
718 }
719
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700720 private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
721 String wrappingKeyAlias,
722 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
723 KeyCharacteristics outCharacteristics)
724 throws RemoteException, ExecutionException, InterruptedException {
725 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
726 int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
727 maskingKey, args, rootSid, fingerprintSid);
728 if (error != NO_ERROR) return error;
729
730 KeyCharacteristicsCallbackResult result = promise.getFuture().get();
731 error = result.getKeystoreResponse().getErrorCode();
732 if (error != NO_ERROR) return error;
733
734 KeyCharacteristics characteristics = result.getKeyCharacteristics();
735 if (characteristics == null) return SYSTEM_ERROR;
736 outCharacteristics.shallowCopyFrom(characteristics);
737 return NO_ERROR;
738 }
739
Frank Salim21d9c1d2017-12-19 22:38:09 -0800740 public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
741 String wrappingKeyAlias,
742 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
743 KeyCharacteristics outCharacteristics) {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700744 // TODO b/119217337 uid parameter gets silently ignored.
Frank Salim21d9c1d2017-12-19 22:38:09 -0800745 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700746 int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
Frank Salim21d9c1d2017-12-19 22:38:09 -0800747 maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
Janis Danisevskisd2575382018-10-08 07:56:58 -0700748 if (error == KEY_ALREADY_EXISTS) {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700749 mBinder.del(wrappedKeyAlias, UID_SELF);
750 error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
Janis Danisevskisd2575382018-10-08 07:56:58 -0700751 maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
752 }
753 return error;
Frank Salim21d9c1d2017-12-19 22:38:09 -0800754 } catch (RemoteException e) {
755 Log.w(TAG, "Cannot connect to keystore", e);
756 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700757 } catch (ExecutionException | InterruptedException e) {
758 Log.e(TAG, "ImportWrappedKey completed with exception", e);
759 return SYSTEM_ERROR;
Frank Salim21d9c1d2017-12-19 22:38:09 -0800760 }
761 }
762
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700763 private class ExportKeyPromise
764 extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
765 final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
766 @Override
767 public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
768 future.complete(exportKeyResult);
769 }
770 public final CompletableFuture<ExportResult> getFuture() {
771 return future;
772 }
773 };
774
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700775 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700776 KeymasterBlob appId, int uid) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800777 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700778 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
779 appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700780 ExportKeyPromise promise = new ExportKeyPromise();
781 int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
782 if (error == NO_ERROR) {
783 return promise.getFuture().get();
784 } else {
785 return new ExportResult(error);
786 }
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700787 } catch (RemoteException e) {
788 Log.w(TAG, "Cannot connect to keystore", e);
789 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700790 } catch (ExecutionException | InterruptedException e) {
791 Log.e(TAG, "ExportKey completed with exception", e);
792 return null;
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700793 }
794 }
795 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
796 KeymasterBlob appId) {
797 return exportKey(alias, format, clientId, appId, UID_SELF);
798 }
799
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700800 private class OperationPromise
801 extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
802 final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
803 @Override
804 public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
805 future.complete(operationResult);
806 }
807 public final CompletableFuture<OperationResult> getFuture() {
808 return future;
809 }
810 };
811
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700812 public OperationResult begin(String alias, int purpose, boolean pruneable,
813 KeymasterArguments args, byte[] entropy, int uid) {
814 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700815 args = args != null ? args : new KeymasterArguments();
816 entropy = entropy != null ? entropy : new byte[0];
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700817 OperationPromise promise = new OperationPromise();
818 int errorCode = mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
819 entropy, uid);
820 if (errorCode == NO_ERROR) {
821 return promise.getFuture().get();
822 } else {
823 return new OperationResult(errorCode);
824 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800825 } catch (RemoteException e) {
826 Log.w(TAG, "Cannot connect to keystore", e);
827 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700828 } catch (ExecutionException | InterruptedException e) {
829 Log.e(TAG, "Begin completed with exception", e);
830 return null;
Chad Brubakere6a461342015-02-10 21:33:23 -0800831 }
832 }
833
834 public OperationResult begin(String alias, int purpose, boolean pruneable,
Chad Brubaker966486e2015-06-01 12:57:06 -0700835 KeymasterArguments args, byte[] entropy) {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700836 entropy = entropy != null ? entropy : new byte[0];
837 args = args != null ? args : new KeymasterArguments();
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700838 return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
Chad Brubakere6a461342015-02-10 21:33:23 -0800839 }
840
841 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
842 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700843 arguments = arguments != null ? arguments : new KeymasterArguments();
844 input = input != null ? input : new byte[0];
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700845 OperationPromise promise = new OperationPromise();
846 int errorCode = mBinder.update(promise, token, arguments, input);
847 if (errorCode == NO_ERROR) {
848 return promise.getFuture().get();
849 } else {
850 return new OperationResult(errorCode);
851 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800852 } catch (RemoteException e) {
853 Log.w(TAG, "Cannot connect to keystore", e);
854 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700855 } catch (ExecutionException | InterruptedException e) {
856 Log.e(TAG, "Update completed with exception", e);
857 return null;
Chad Brubakere6a461342015-02-10 21:33:23 -0800858 }
859 }
860
Chad Brubaker8a077012015-05-29 12:32:51 -0700861 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
862 byte[] entropy) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800863 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700864 arguments = arguments != null ? arguments : new KeymasterArguments();
865 entropy = entropy != null ? entropy : new byte[0];
866 signature = signature != null ? signature : new byte[0];
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700867 OperationPromise promise = new OperationPromise();
868 int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
869 if (errorCode == NO_ERROR) {
870 return promise.getFuture().get();
871 } else {
872 return new OperationResult(errorCode);
873 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800874 } catch (RemoteException e) {
875 Log.w(TAG, "Cannot connect to keystore", e);
876 return null;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700877 } catch (ExecutionException | InterruptedException e) {
878 Log.e(TAG, "Finish completed with exception", e);
879 return null;
Chad Brubakere6a461342015-02-10 21:33:23 -0800880 }
881 }
882
Chad Brubaker8a077012015-05-29 12:32:51 -0700883 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
884 return finish(token, arguments, signature, null);
885 }
886
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700887 private class KeystoreResultPromise
888 extends android.security.keystore.IKeystoreResponseCallback.Stub {
889 final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
890 @Override
891 public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
892 future.complete(keystoreResponse);
893 }
894 public final CompletableFuture<KeystoreResponse> getFuture() {
895 return future;
896 }
897 };
898
Chad Brubakere6a461342015-02-10 21:33:23 -0800899 public int abort(IBinder token) {
900 try {
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700901 KeystoreResultPromise promise = new KeystoreResultPromise();
902 int errorCode = mBinder.abort(promise, token);
903 if (errorCode == NO_ERROR) {
904 return promise.getFuture().get().getErrorCode();
905 } else {
906 return errorCode;
907 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800908 } catch (RemoteException e) {
909 Log.w(TAG, "Cannot connect to keystore", e);
910 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700911 } catch (ExecutionException | InterruptedException e) {
912 Log.e(TAG, "Abort completed with exception", e);
913 return SYSTEM_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800914 }
915 }
Chad Brubaker5654b362015-03-17 16:59:52 -0700916
917 /**
Chad Brubaker5654b362015-03-17 16:59:52 -0700918 * Add an authentication record to the keystore authorization table.
919 *
920 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
921 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
922 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
923 */
Brian Youngda82e2c2018-02-22 23:36:34 +0000924 public int addAuthToken(byte[] authToken) {
Chad Brubaker5654b362015-03-17 16:59:52 -0700925 try {
Brian Youngda82e2c2018-02-22 23:36:34 +0000926 return mBinder.addAuthToken(authToken);
Chad Brubaker5654b362015-03-17 16:59:52 -0700927 } catch (RemoteException e) {
928 Log.w(TAG, "Cannot connect to keystore", e);
929 return SYSTEM_ERROR;
930 }
931 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700932
Alex Klyubinad9ba102015-04-21 15:17:24 -0700933 /**
Chad Brubakera91a8502015-05-07 10:02:22 -0700934 * Notify keystore that a user's password has changed.
935 *
936 * @param userId the user whose password changed.
937 * @param newPassword the new password or "" if the password was removed.
938 */
939 public boolean onUserPasswordChanged(int userId, String newPassword) {
940 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
941 // explicit here.
942 if (newPassword == null) {
943 newPassword = "";
944 }
945 try {
946 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
947 } catch (RemoteException e) {
948 Log.w(TAG, "Cannot connect to keystore", e);
949 return false;
950 }
951 }
952
Chad Brubaker83ce0952015-05-12 13:00:02 -0700953 /**
954 * Notify keystore that a user was added.
955 *
956 * @param userId the new user.
957 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
958 * specified then the new user's keystore will be intialized with the same secure lockscreen
959 * password as the parent.
960 */
961 public void onUserAdded(int userId, int parentId) {
962 try {
963 mBinder.onUserAdded(userId, parentId);
964 } catch (RemoteException e) {
965 Log.w(TAG, "Cannot connect to keystore", e);
966 }
967 }
968
969 /**
970 * Notify keystore that a user was added.
971 *
972 * @param userId the new user.
973 */
974 public void onUserAdded(int userId) {
975 onUserAdded(userId, -1);
976 }
977
978 /**
979 * Notify keystore that a user was removed.
980 *
981 * @param userId the removed user.
982 */
983 public void onUserRemoved(int userId) {
984 try {
985 mBinder.onUserRemoved(userId);
986 } catch (RemoteException e) {
987 Log.w(TAG, "Cannot connect to keystore", e);
988 }
989 }
990
Chad Brubakera91a8502015-05-07 10:02:22 -0700991 public boolean onUserPasswordChanged(String newPassword) {
992 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
993 }
994
Janis Danisevskisb0358e72018-11-02 10:34:07 -0700995 private class KeyAttestationCallbackResult {
996 private KeystoreResponse keystoreResponse;
997 private KeymasterCertificateChain certificateChain;
998
999 public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
1000 KeymasterCertificateChain certificateChain) {
1001 this.keystoreResponse = keystoreResponse;
1002 this.certificateChain = certificateChain;
1003 }
1004
1005 public KeystoreResponse getKeystoreResponse() {
1006 return keystoreResponse;
1007 }
1008
1009 public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
1010 this.keystoreResponse = keystoreResponse;
1011 }
1012
1013 public KeymasterCertificateChain getCertificateChain() {
1014 return certificateChain;
1015 }
1016
1017 public void setCertificateChain(KeymasterCertificateChain certificateChain) {
1018 this.certificateChain = certificateChain;
1019 }
1020 }
1021
1022 private class CertificateChainPromise
1023 extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
1024 final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
1025 @Override
1026 public void onFinished(KeystoreResponse keystoreResponse,
1027 KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
1028 future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
1029 }
1030 public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
1031 return future;
1032 }
1033 };
1034
1035
Shawn Willden8d8c7472016-02-02 08:27:39 -07001036 public int attestKey(
1037 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
1038 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -07001039 if (params == null) {
1040 params = new KeymasterArguments();
1041 }
1042 if (outChain == null) {
1043 outChain = new KeymasterCertificateChain();
1044 }
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001045 CertificateChainPromise promise = new CertificateChainPromise();
1046 int error = mBinder.attestKey(promise, alias, params);
1047 if (error != NO_ERROR) return error;
1048 KeyAttestationCallbackResult result = promise.getFuture().get();
1049 error = result.getKeystoreResponse().getErrorCode();
1050 if (error == NO_ERROR) {
1051 outChain.shallowCopyFrom(result.getCertificateChain());
1052 }
1053 return error;
Shawn Willden8d8c7472016-02-02 08:27:39 -07001054 } catch (RemoteException e) {
1055 Log.w(TAG, "Cannot connect to keystore", e);
1056 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001057 } catch (ExecutionException | InterruptedException e) {
1058 Log.e(TAG, "AttestKey completed with exception", e);
1059 return SYSTEM_ERROR;
Shawn Willden8d8c7472016-02-02 08:27:39 -07001060 }
1061 }
1062
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +02001063 public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) {
1064 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -07001065 if (params == null) {
1066 params = new KeymasterArguments();
1067 }
1068 if (outChain == null) {
1069 outChain = new KeymasterCertificateChain();
1070 }
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001071 CertificateChainPromise promise = new CertificateChainPromise();
1072 int error = mBinder.attestDeviceIds(promise, params);
1073 if (error != NO_ERROR) return error;
1074 KeyAttestationCallbackResult result = promise.getFuture().get();
1075 error = result.getKeystoreResponse().getErrorCode();
1076 if (error == NO_ERROR) {
1077 outChain.shallowCopyFrom(result.getCertificateChain());
1078 }
1079 return error;
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +02001080 } catch (RemoteException e) {
1081 Log.w(TAG, "Cannot connect to keystore", e);
1082 return SYSTEM_ERROR;
Janis Danisevskisb0358e72018-11-02 10:34:07 -07001083 } catch (ExecutionException | InterruptedException e) {
1084 Log.e(TAG, "AttestDevicdeIds completed with exception", e);
1085 return SYSTEM_ERROR;
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +02001086 }
1087 }
1088
Tucker Sylvestrob32aae22016-06-23 17:23:33 -04001089 /**
1090 * Notify keystore that the device went off-body.
1091 */
1092 public void onDeviceOffBody() {
1093 try {
1094 mBinder.onDeviceOffBody();
1095 } catch (RemoteException e) {
1096 Log.w(TAG, "Cannot connect to keystore", e);
1097 }
1098 }
Shawn Willden8d8c7472016-02-02 08:27:39 -07001099
Janis Danisevskis7dacad82018-01-24 15:12:11 -08001100 // Keep in sync with confirmationui/1.0/types.hal.
1101 public static final int CONFIRMATIONUI_OK = 0;
1102 public static final int CONFIRMATIONUI_CANCELED = 1;
1103 public static final int CONFIRMATIONUI_ABORTED = 2;
1104 public static final int CONFIRMATIONUI_OPERATION_PENDING = 3;
1105 public static final int CONFIRMATIONUI_IGNORED = 4;
1106 public static final int CONFIRMATIONUI_SYSTEM_ERROR = 5;
1107 public static final int CONFIRMATIONUI_UNIMPLEMENTED = 6;
1108 public static final int CONFIRMATIONUI_UNEXPECTED = 7;
1109 public static final int CONFIRMATIONUI_UIERROR = 0x10000;
1110 public static final int CONFIRMATIONUI_UIERROR_MISSING_GLYPH = 0x10001;
1111 public static final int CONFIRMATIONUI_UIERROR_MESSAGE_TOO_LONG = 0x10002;
1112 public static final int CONFIRMATIONUI_UIERROR_MALFORMED_UTF8_ENCODING = 0x10003;
1113
1114 /**
1115 * Requests keystore call into the confirmationui HAL to display a prompt.
1116 *
1117 * @param listener the binder to use for callbacks.
1118 * @param promptText the prompt to display.
1119 * @param extraData extra data / nonce from application.
1120 * @param locale the locale as a BCP 47 langauge tag.
1121 * @param uiOptionsAsFlags the UI options to use, as flags.
1122 * @return one of the {@code CONFIRMATIONUI_*} constants, for
1123 * example {@code KeyStore.CONFIRMATIONUI_OK}.
1124 */
1125 public int presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData,
1126 String locale, int uiOptionsAsFlags) {
1127 try {
1128 return mBinder.presentConfirmationPrompt(listener, promptText, extraData, locale,
1129 uiOptionsAsFlags);
1130 } catch (RemoteException e) {
1131 Log.w(TAG, "Cannot connect to keystore", e);
1132 return CONFIRMATIONUI_SYSTEM_ERROR;
1133 }
1134 }
1135
1136 /**
1137 * Requests keystore call into the confirmationui HAL to cancel displaying a prompt.
1138 *
1139 * @param listener the binder passed to the {@link #presentConfirmationPrompt} method.
1140 * @return one of the {@code CONFIRMATIONUI_*} constants, for
1141 * example {@code KeyStore.CONFIRMATIONUI_OK}.
1142 */
1143 public int cancelConfirmationPrompt(IBinder listener) {
1144 try {
1145 return mBinder.cancelConfirmationPrompt(listener);
1146 } catch (RemoteException e) {
1147 Log.w(TAG, "Cannot connect to keystore", e);
1148 return CONFIRMATIONUI_SYSTEM_ERROR;
1149 }
1150 }
1151
Chad Brubakera91a8502015-05-07 10:02:22 -07001152 /**
David Zeuthenbbb7f652018-02-26 11:04:18 -05001153 * Requests keystore to check if the confirmationui HAL is available.
1154 *
1155 * @return whether the confirmationUI HAL is available.
1156 */
1157 public boolean isConfirmationPromptSupported() {
1158 try {
1159 return mBinder.isConfirmationPromptSupported();
1160 } catch (RemoteException e) {
1161 Log.w(TAG, "Cannot connect to keystore", e);
1162 return false;
1163 }
1164 }
1165
1166 /**
Alex Klyubinad9ba102015-04-21 15:17:24 -07001167 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
1168 * code.
1169 */
Mathew Inwood4dbdcf42018-08-16 18:49:37 +01001170 @UnsupportedAppUsage
Alex Klyubindcdaf872015-05-13 15:57:09 -07001171 public static KeyStoreException getKeyStoreException(int errorCode) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001172 if (errorCode > 0) {
1173 // KeyStore layer error
1174 switch (errorCode) {
1175 case NO_ERROR:
1176 return new KeyStoreException(errorCode, "OK");
1177 case LOCKED:
Alex Klyubin54183932015-05-08 15:25:48 -07001178 return new KeyStoreException(errorCode, "User authentication required");
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001179 case UNINITIALIZED:
1180 return new KeyStoreException(errorCode, "Keystore not initialized");
1181 case SYSTEM_ERROR:
1182 return new KeyStoreException(errorCode, "System error");
1183 case PERMISSION_DENIED:
1184 return new KeyStoreException(errorCode, "Permission denied");
1185 case KEY_NOT_FOUND:
1186 return new KeyStoreException(errorCode, "Key not found");
1187 case VALUE_CORRUPTED:
1188 return new KeyStoreException(errorCode, "Key blob corrupted");
Alex Klyubin058de022015-04-29 17:32:00 -07001189 case OP_AUTH_NEEDED:
1190 return new KeyStoreException(errorCode, "Operation requires authorization");
Max Biresb2cc3dc2018-11-02 10:50:40 -07001191 case KEY_PERMANENTLY_INVALIDATED:
1192 return new KeyStoreException(errorCode, "Key permanently invalidated");
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001193 default:
1194 return new KeyStoreException(errorCode, String.valueOf(errorCode));
1195 }
1196 } else {
1197 // Keymaster layer error
1198 switch (errorCode) {
1199 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
1200 // The name of this parameter significantly differs between Keymaster and
1201 // framework APIs. Use the framework wording to make life easier for developers.
1202 return new KeyStoreException(errorCode,
1203 "Invalid user authentication validity duration");
1204 default:
1205 return new KeyStoreException(errorCode,
1206 KeymasterDefs.getErrorMessage(errorCode));
1207 }
1208 }
1209 }
1210
Alex Klyubinad9ba102015-04-21 15:17:24 -07001211 /**
1212 * Returns an {@link InvalidKeyException} corresponding to the provided
1213 * {@link KeyStoreException}.
1214 */
Alex Klyubindcdaf872015-05-13 15:57:09 -07001215 public InvalidKeyException getInvalidKeyException(
Alex Klyubin3876b1b2015-09-09 14:55:03 -07001216 String keystoreKeyAlias, int uid, KeyStoreException e) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001217 switch (e.getErrorCode()) {
Brian Youngda82e2c2018-02-22 23:36:34 +00001218 case LOCKED:
Alex Klyubin54183932015-05-08 15:25:48 -07001219 return new UserNotAuthenticatedException();
Brian Youngda82e2c2018-02-22 23:36:34 +00001220 case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001221 return new KeyExpiredException();
Brian Youngda82e2c2018-02-22 23:36:34 +00001222 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001223 return new KeyNotYetValidException();
Brian Youngda82e2c2018-02-22 23:36:34 +00001224 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
1225 case OP_AUTH_NEEDED:
Alex Klyubin708fc9402015-04-28 18:58:47 -07001226 {
1227 // We now need to determine whether the key/operation can become usable if user
1228 // authentication is performed, or whether it can never become usable again.
1229 // User authentication requirements are contained in the key's characteristics. We
1230 // need to check whether these requirements can be be satisfied by asking the user
1231 // to authenticate.
1232 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
1233 int getKeyCharacteristicsErrorCode =
Alex Klyubin3876b1b2015-09-09 14:55:03 -07001234 getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
1235 keyCharacteristics);
Alex Klyubin708fc9402015-04-28 18:58:47 -07001236 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
1237 return new InvalidKeyException(
1238 "Failed to obtained key characteristics",
1239 getKeyStoreException(getKeyCharacteristicsErrorCode));
1240 }
Alex Klyubinae6cb7a2015-06-22 18:09:35 -07001241 List<BigInteger> keySids =
1242 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
Alex Klyubin708fc9402015-04-28 18:58:47 -07001243 if (keySids.isEmpty()) {
1244 // Key is not bound to any SIDs -- no amount of authentication will help here.
1245 return new KeyPermanentlyInvalidatedException();
1246 }
1247 long rootSid = GateKeeper.getSecureUserId();
Alex Klyubinae6cb7a2015-06-22 18:09:35 -07001248 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -07001249 // One of the key's SIDs is the current root SID -- user can be authenticated
1250 // against that SID.
1251 return new UserNotAuthenticatedException();
1252 }
1253
1254 long fingerprintOnlySid = getFingerprintOnlySid();
1255 if ((fingerprintOnlySid != 0)
Alex Klyubinae6cb7a2015-06-22 18:09:35 -07001256 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -07001257 // One of the key's SIDs is the current fingerprint SID -- user can be
1258 // authenticated against that SID.
1259 return new UserNotAuthenticatedException();
1260 }
1261
1262 // None of the key's SIDs can ever be authenticated
1263 return new KeyPermanentlyInvalidatedException();
1264 }
Brian Youngda82e2c2018-02-22 23:36:34 +00001265 case UNINITIALIZED:
Janis Danisevskisd07d3382017-09-01 14:45:16 -07001266 return new KeyPermanentlyInvalidatedException();
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001267 default:
Alex Klyubinad9ba102015-04-21 15:17:24 -07001268 return new InvalidKeyException("Keystore operation failed", e);
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001269 }
1270 }
1271
Alex Klyubin2d7a85c2015-04-30 11:43:53 -07001272 private long getFingerprintOnlySid() {
Kevin Chyn55966422017-10-23 16:08:47 -07001273 final PackageManager packageManager = mContext.getPackageManager();
1274 if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
1275 return 0;
1276 }
Alex Klyubina99b8b52015-06-11 13:27:34 -07001277 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
Alex Klyubin2d7a85c2015-04-30 11:43:53 -07001278 if (fingerprintManager == null) {
Alex Klyubin708fc9402015-04-28 18:58:47 -07001279 return 0;
1280 }
1281
Alex Klyubina99b8b52015-06-11 13:27:34 -07001282 // TODO: Restore USE_FINGERPRINT permission check in
1283 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
Alex Klyubin2d7a85c2015-04-30 11:43:53 -07001284 return fingerprintManager.getAuthenticatorId();
Svetoslav2dac95d2015-04-30 11:30:33 -07001285 }
1286
Alex Klyubinad9ba102015-04-21 15:17:24 -07001287 /**
1288 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
1289 * code.
1290 */
Alex Klyubin3876b1b2015-09-09 14:55:03 -07001291 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
1292 int errorCode) {
1293 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
Alex Klyubinb4834ae2015-04-02 15:53:46 -07001294 }
Chia-chi Yeh44039172009-09-21 11:53:59 +08001295}