blob: e25386baf969f02386fdb10dc4590cca6d2ce97e [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
Svetoslav2dac95d2015-04-30 11:30:33 -070019import android.app.ActivityThread;
20import android.app.Application;
Alex Klyubin54183932015-05-08 15:25:48 -070021import android.app.KeyguardManager;
Alex Klyubin708fc9402015-04-28 18:58:47 -070022import android.content.Context;
Kevin Chyn55966422017-10-23 16:08:47 -070023import android.content.pm.PackageManager;
Alex Klyubin2d7a85c2015-04-30 11:43:53 -070024import android.hardware.fingerprint.FingerprintManager;
Chad Brubakere6a461342015-02-10 21:33:23 -080025import android.os.Binder;
26import android.os.IBinder;
Chad Brubakera91a8502015-05-07 10:02:22 -070027import android.os.Process;
Kenny Root6b776452012-11-02 15:40:32 -070028import android.os.RemoteException;
29import android.os.ServiceManager;
Chad Brubakera91a8502015-05-07 10:02:22 -070030import android.os.UserHandle;
Chad Brubakere6a461342015-02-10 21:33:23 -080031import android.security.keymaster.ExportResult;
32import android.security.keymaster.KeyCharacteristics;
33import android.security.keymaster.KeymasterArguments;
Chad Brubaker5e73c0e2015-03-21 22:46:43 -070034import android.security.keymaster.KeymasterBlob;
Shawn Willden8d8c7472016-02-02 08:27:39 -070035import android.security.keymaster.KeymasterCertificateChain;
Alex Klyubinb4834ae2015-04-02 15:53:46 -070036import android.security.keymaster.KeymasterDefs;
Chad Brubakere6a461342015-02-10 21:33:23 -080037import android.security.keymaster.OperationResult;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070038import android.security.keystore.KeyExpiredException;
39import android.security.keystore.KeyNotYetValidException;
40import android.security.keystore.KeyPermanentlyInvalidatedException;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070041import android.security.keystore.UserNotAuthenticatedException;
Kenny Root6b776452012-11-02 15:40:32 -070042import android.util.Log;
Chia-chi Yeh44039172009-09-21 11:53:59 +080043
Alex Klyubinae6cb7a2015-06-22 18:09:35 -070044import java.math.BigInteger;
Alex Klyubinad9ba102015-04-21 15:17:24 -070045import java.security.InvalidKeyException;
Alex Klyubin708fc9402015-04-28 18:58:47 -070046import java.util.List;
Kenny Rootb91773b2013-09-05 13:03:16 -070047import java.util.Locale;
48
Chia-chi Yeh44039172009-09-21 11:53:59 +080049/**
Brian Carlstrom46703b02011-04-06 15:41:29 -070050 * @hide This should not be made public in its present form because it
51 * assumes that private and secret key bytes are available and would
52 * preclude the use of hardware crypto.
Chia-chi Yeh44039172009-09-21 11:53:59 +080053 */
54public class KeyStore {
Kenny Root6b776452012-11-02 15:40:32 -070055 private static final String TAG = "KeyStore";
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070056
Dmitry Dementyevefc43112017-10-27 23:10:28 -070057 // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
Brian Carlstrom7e4b1a42011-06-01 15:29:29 -070058 public static final int NO_ERROR = 1;
59 public static final int LOCKED = 2;
60 public static final int UNINITIALIZED = 3;
61 public static final int SYSTEM_ERROR = 4;
62 public static final int PROTOCOL_ERROR = 5;
63 public static final int PERMISSION_DENIED = 6;
64 public static final int KEY_NOT_FOUND = 7;
65 public static final int VALUE_CORRUPTED = 8;
66 public static final int UNDEFINED_ACTION = 9;
67 public static final int WRONG_PASSWORD = 10;
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070068
Chad Brubaker560d6532015-04-24 10:32:18 -070069 /**
70 * Per operation authentication is needed before this operation is valid.
71 * This is returned from {@link #begin} when begin succeeds but the operation uses
72 * per-operation authentication and must authenticate before calling {@link #update} or
73 * {@link #finish}.
74 */
75 public static final int OP_AUTH_NEEDED = 15;
76
Kenny Root2eeda722013-04-10 11:30:58 -070077 // Used for UID field to indicate the calling UID.
78 public static final int UID_SELF = -1;
79
80 // Flags for "put" "import" and "generate"
81 public static final int FLAG_NONE = 0;
Alex Klyubin54183932015-05-08 15:25:48 -070082
83 /**
84 * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key
85 * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern).
86 *
87 * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set
88 * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key
89 * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or
90 * a Device Administrator). Finally, this key (or key pair) cannot be used until the user
91 * unlocks the secure lock screen after boot.
92 *
93 * @see KeyguardManager#isDeviceSecure()
94 */
Kenny Roota3788b02013-04-10 10:37:55 -070095 public static final int FLAG_ENCRYPTED = 1;
96
Rubin Xu12b644d2017-04-21 19:21:42 +010097 /**
Janis Danisevskis0aadf932017-12-18 17:28:52 -080098 * Select Software keymaster device, which as of this writing is the lowest security
99 * level available on an android device. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
100 * A TEE based keymaster implementation is implied.
101 *
102 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
103 * For historical reasons this corresponds to the KEYSTORE_FLAG_FALLBACK flag.
104 */
105 public static final int FLAG_SOFTWARE = 1 << 1;
106
107 /**
Rubin Xu12b644d2017-04-21 19:21:42 +0100108 * A private flag that's only available to system server to indicate that this key is part of
109 * device encryption flow so it receives special treatment from keystore. For example this key
110 * will not be super encrypted, and it will be stored separately under an unique UID instead
111 * of the caller UID i.e. SYSTEM.
112 *
113 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
114 */
115 public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
116
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800117 /**
118 * Select Strongbox keymaster device, which as of this writing the the highest security level
119 * available an android devices. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
120 * A TEE based keymaster implementation is implied.
121 *
122 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
123 */
124 public static final int FLAG_STRONGBOX = 1 << 4;
125
126
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700127 // States
128 public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
Chia-chi Yeh44039172009-09-21 11:53:59 +0800129
Chia-chi Yeh44039172009-09-21 11:53:59 +0800130 private int mError = NO_ERROR;
131
Kenny Root6b776452012-11-02 15:40:32 -0700132 private final IKeystoreService mBinder;
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700133 private final Context mContext;
Kenny Root6b776452012-11-02 15:40:32 -0700134
Chad Brubakere6a461342015-02-10 21:33:23 -0800135 private IBinder mToken;
136
Kenny Root6b776452012-11-02 15:40:32 -0700137 private KeyStore(IKeystoreService binder) {
138 mBinder = binder;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -0700139 mContext = getApplicationContext();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700140 }
141
Alex Klyubindcdaf872015-05-13 15:57:09 -0700142 public static Context getApplicationContext() {
Alex Klyubina99b8b52015-06-11 13:27:34 -0700143 Application application = ActivityThread.currentApplication();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700144 if (application == null) {
145 throw new IllegalStateException(
Alex Klyubina99b8b52015-06-11 13:27:34 -0700146 "Failed to obtain application Context from ActivityThread");
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700147 }
148 return application;
Kenny Root6b776452012-11-02 15:40:32 -0700149 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800150
151 public static KeyStore getInstance() {
Kenny Root6b776452012-11-02 15:40:32 -0700152 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
153 .getService("android.security.keystore"));
154 return new KeyStore(keystore);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800155 }
156
Chad Brubakere6a461342015-02-10 21:33:23 -0800157 private synchronized IBinder getToken() {
158 if (mToken == null) {
159 mToken = new Binder();
160 }
161 return mToken;
162 }
163
Chad Brubakere35d49f2015-05-12 15:19:52 -0700164 public State state(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700165 final int ret;
166 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700167 ret = mBinder.getState(userId);
Kenny Root6b776452012-11-02 15:40:32 -0700168 } catch (RemoteException e) {
169 Log.w(TAG, "Cannot connect to keystore", e);
170 throw new AssertionError(e);
171 }
172
173 switch (ret) {
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700174 case NO_ERROR: return State.UNLOCKED;
175 case LOCKED: return State.LOCKED;
176 case UNINITIALIZED: return State.UNINITIALIZED;
177 default: throw new AssertionError(mError);
178 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800179 }
180
Chad Brubakere35d49f2015-05-12 15:19:52 -0700181 public State state() {
182 return state(UserHandle.myUserId());
183 }
184
Kenny Rootb9594ce2013-02-14 10:18:38 -0800185 public boolean isUnlocked() {
186 return state() == State.UNLOCKED;
187 }
188
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700189 public byte[] get(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700190 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700191 key = key != null ? key : "";
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700192 return mBinder.get(key, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700193 } catch (RemoteException e) {
194 Log.w(TAG, "Cannot connect to keystore", e);
195 return null;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700196 } catch (android.os.ServiceSpecificException e) {
197 Log.w(TAG, "KeyStore exception", e);
198 return null;
Kenny Root6b776452012-11-02 15:40:32 -0700199 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800200 }
201
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700202 public byte[] get(String key) {
203 return get(key, UID_SELF);
204 }
205
Kenny Roota3788b02013-04-10 10:37:55 -0700206 public boolean put(String key, byte[] value, int uid, int flags) {
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700207 return insert(key, value, uid, flags) == NO_ERROR;
208 }
209
210 public int insert(String key, byte[] value, int uid, int flags) {
Kenny Root6b776452012-11-02 15:40:32 -0700211 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700212 if (value == null) {
213 value = new byte[0];
214 }
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700215 return mBinder.insert(key, value, uid, flags);
Kenny Root78ad8492013-02-13 17:02:57 -0800216 } catch (RemoteException e) {
217 Log.w(TAG, "Cannot connect to keystore", e);
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700218 return SYSTEM_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800219 }
220 }
221
Kenny Root78ad8492013-02-13 17:02:57 -0800222 public boolean delete(String key, int uid) {
223 try {
Robin Leee4487ea2016-02-29 17:43:54 +0000224 int ret = mBinder.del(key, uid);
225 return (ret == NO_ERROR || ret == KEY_NOT_FOUND);
Kenny Root6b776452012-11-02 15:40:32 -0700226 } catch (RemoteException e) {
227 Log.w(TAG, "Cannot connect to keystore", e);
228 return false;
229 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800230 }
231
232 public boolean delete(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700233 return delete(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800234 }
235
236 public boolean contains(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700237 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800238 return mBinder.exist(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700239 } catch (RemoteException e) {
240 Log.w(TAG, "Cannot connect to keystore", e);
241 return false;
242 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800243 }
244
245 public boolean contains(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700246 return contains(key, UID_SELF);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800247 }
248
Chad Brubakere35d49f2015-05-12 15:19:52 -0700249 /**
250 * List all entries in the keystore for {@code uid} starting with {@code prefix}.
251 */
252 public String[] list(String prefix, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700253 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700254 return mBinder.list(prefix, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700255 } catch (RemoteException e) {
256 Log.w(TAG, "Cannot connect to keystore", e);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800257 return null;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700258 } catch (android.os.ServiceSpecificException e) {
259 Log.w(TAG, "KeyStore exception", e);
260 return null;
Chia-chi Yeh44039172009-09-21 11:53:59 +0800261 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800262 }
263
Chad Brubakere35d49f2015-05-12 15:19:52 -0700264 public String[] list(String prefix) {
265 return list(prefix, UID_SELF);
266 }
267
Chia-chi Yeh44039172009-09-21 11:53:59 +0800268 public boolean reset() {
Kenny Root6b776452012-11-02 15:40:32 -0700269 try {
270 return mBinder.reset() == NO_ERROR;
271 } catch (RemoteException e) {
272 Log.w(TAG, "Cannot connect to keystore", e);
273 return false;
274 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800275 }
276
Chad Brubakere35d49f2015-05-12 15:19:52 -0700277 /**
278 * Attempt to lock the keystore for {@code user}.
279 *
280 * @param user Android user to lock.
281 * @return whether {@code user}'s keystore was locked.
282 */
283 public boolean lock(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700284 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700285 return mBinder.lock(userId) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700286 } catch (RemoteException e) {
287 Log.w(TAG, "Cannot connect to keystore", e);
288 return false;
289 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800290 }
291
Chad Brubakere35d49f2015-05-12 15:19:52 -0700292 public boolean lock() {
293 return lock(UserHandle.myUserId());
294 }
295
Chad Brubakera91a8502015-05-07 10:02:22 -0700296 /**
297 * Attempt to unlock the keystore for {@code user} with the password {@code password}.
298 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
299 * created.
300 *
301 * @param user Android user ID to operate on
302 * @param password user's keystore password. Should be the most recent value passed to
303 * {@link #onUserPasswordChanged} for the user.
304 *
305 * @return whether the keystore was unlocked.
306 */
307 public boolean unlock(int userId, String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700308 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700309 password = password != null ? password : "";
Chad Brubakera91a8502015-05-07 10:02:22 -0700310 mError = mBinder.unlock(userId, password);
Kenny Root6b776452012-11-02 15:40:32 -0700311 return mError == NO_ERROR;
312 } catch (RemoteException e) {
313 Log.w(TAG, "Cannot connect to keystore", e);
314 return false;
315 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800316 }
317
Chad Brubakera91a8502015-05-07 10:02:22 -0700318 public boolean unlock(String password) {
319 return unlock(UserHandle.getUserId(Process.myUid()), password);
320 }
321
Chad Brubakere35d49f2015-05-12 15:19:52 -0700322 /**
323 * Check if the keystore for {@code userId} is empty.
324 */
325 public boolean isEmpty(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700326 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700327 return mBinder.isEmpty(userId) != 0;
Kenny Root6b776452012-11-02 15:40:32 -0700328 } catch (RemoteException e) {
329 Log.w(TAG, "Cannot connect to keystore", e);
330 return false;
331 }
Kenny Root5423e682011-11-14 08:43:13 -0800332 }
333
Chad Brubakere35d49f2015-05-12 15:19:52 -0700334 public boolean isEmpty() {
335 return isEmpty(UserHandle.myUserId());
336 }
337
Kenny Roota3985982013-08-16 14:03:29 -0700338 public boolean generate(String key, int uid, int keyType, int keySize, int flags,
339 byte[][] args) {
Kenny Root6b776452012-11-02 15:40:32 -0700340 try {
Chad Brubaker7a2c9732015-01-13 17:41:22 -0800341 return mBinder.generate(key, uid, keyType, keySize, flags,
342 new KeystoreArguments(args)) == NO_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800343 } catch (RemoteException e) {
344 Log.w(TAG, "Cannot connect to keystore", e);
345 return false;
346 }
347 }
348
Kenny Roota3788b02013-04-10 10:37:55 -0700349 public boolean importKey(String keyName, byte[] key, int uid, int flags) {
Kenny Root78ad8492013-02-13 17:02:57 -0800350 try {
Kenny Roota3788b02013-04-10 10:37:55 -0700351 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700352 } catch (RemoteException e) {
353 Log.w(TAG, "Cannot connect to keystore", e);
354 return false;
355 }
Kenny Root5423e682011-11-14 08:43:13 -0800356 }
357
Kenny Root5423e682011-11-14 08:43:13 -0800358 public byte[] sign(String key, byte[] data) {
Kenny Root6b776452012-11-02 15:40:32 -0700359 try {
360 return mBinder.sign(key, data);
361 } catch (RemoteException e) {
362 Log.w(TAG, "Cannot connect to keystore", e);
363 return null;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700364 } catch (android.os.ServiceSpecificException e) {
365 Log.w(TAG, "KeyStore exception", e);
366 return null;
Kenny Root6b776452012-11-02 15:40:32 -0700367 }
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700368
Kenny Root5423e682011-11-14 08:43:13 -0800369 }
370
371 public boolean verify(String key, byte[] data, byte[] signature) {
Kenny Root6b776452012-11-02 15:40:32 -0700372 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700373 signature = signature != null ? signature : new byte[0];
Kenny Root6b776452012-11-02 15:40:32 -0700374 return mBinder.verify(key, data, signature) == NO_ERROR;
375 } catch (RemoteException e) {
376 Log.w(TAG, "Cannot connect to keystore", e);
377 return false;
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700378 } catch (android.os.ServiceSpecificException e) {
379 Log.w(TAG, "KeyStore exception", e);
380 return false;
Kenny Root6b776452012-11-02 15:40:32 -0700381 }
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700382
Kenny Root5423e682011-11-14 08:43:13 -0800383 }
384
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700385 public String grant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700386 try {
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700387 String grantAlias = mBinder.grant(key, uid);
388 if (grantAlias == "") return null;
389 return grantAlias;
Kenny Root6b776452012-11-02 15:40:32 -0700390 } catch (RemoteException e) {
391 Log.w(TAG, "Cannot connect to keystore", e);
Janis Danisevskisb50e9f62017-06-08 17:53:34 -0700392 return null;
Kenny Root6b776452012-11-02 15:40:32 -0700393 }
Kenny Root5423e682011-11-14 08:43:13 -0800394 }
395
396 public boolean ungrant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700397 try {
398 return mBinder.ungrant(key, uid) == NO_ERROR;
399 } catch (RemoteException e) {
400 Log.w(TAG, "Cannot connect to keystore", e);
401 return false;
Kenny Root473c7122012-08-17 21:13:48 -0700402 }
Kenny Root473c7122012-08-17 21:13:48 -0700403 }
404
405 /**
406 * Returns the last modification time of the key in milliseconds since the
407 * epoch. Will return -1L if the key could not be found or other error.
408 */
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700409 public long getmtime(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700410 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700411 final long millis = mBinder.getmtime(key, uid);
Kenny Roote66769a2013-02-04 15:49:11 -0800412 if (millis == -1L) {
413 return -1L;
414 }
415
416 return millis * 1000L;
Kenny Root6b776452012-11-02 15:40:32 -0700417 } catch (RemoteException e) {
418 Log.w(TAG, "Cannot connect to keystore", e);
419 return -1L;
420 }
Kenny Root473c7122012-08-17 21:13:48 -0700421 }
422
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700423 public long getmtime(String key) {
424 return getmtime(key, UID_SELF);
425 }
426
Alex Klyubin469cbf52015-06-04 12:36:27 -0700427 // TODO: remove this when it's removed from Settings
Kenny Root5cb5cec2013-03-29 11:14:17 -0700428 public boolean isHardwareBacked() {
Kenny Rootb91773b2013-09-05 13:03:16 -0700429 return isHardwareBacked("RSA");
430 }
431
432 public boolean isHardwareBacked(String keyType) {
Kenny Root5cb5cec2013-03-29 11:14:17 -0700433 try {
Kenny Rootb91773b2013-09-05 13:03:16 -0700434 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
Kenny Root5cb5cec2013-03-29 11:14:17 -0700435 } catch (RemoteException e) {
436 Log.w(TAG, "Cannot connect to keystore", e);
437 return false;
438 }
439 }
440
Kenny Rootd72317a2013-04-01 15:59:59 -0700441 public boolean clearUid(int uid) {
442 try {
443 return mBinder.clear_uid(uid) == NO_ERROR;
444 } catch (RemoteException e) {
445 Log.w(TAG, "Cannot connect to keystore", e);
446 return false;
447 }
448 }
449
Chia-chi Yeh44039172009-09-21 11:53:59 +0800450 public int getLastError() {
451 return mError;
452 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800453
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800454 public boolean addRngEntropy(byte[] data, int flags) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800455 try {
Janis Danisevskis0aadf932017-12-18 17:28:52 -0800456 return mBinder.addRngEntropy(data, flags) == NO_ERROR;
Chad Brubakere6a461342015-02-10 21:33:23 -0800457 } catch (RemoteException e) {
458 Log.w(TAG, "Cannot connect to keystore", e);
459 return false;
460 }
461 }
462
Chad Brubakerdae79e52015-03-27 14:28:35 -0700463 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
464 int flags, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800465 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700466 entropy = entropy != null ? entropy : new byte[0];
467 args = args != null ? args : new KeymasterArguments();
Chad Brubakerdae79e52015-03-27 14:28:35 -0700468 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800469 } catch (RemoteException e) {
470 Log.w(TAG, "Cannot connect to keystore", e);
471 return SYSTEM_ERROR;
472 }
473 }
474
Chad Brubakerdae79e52015-03-27 14:28:35 -0700475 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800476 KeyCharacteristics outCharacteristics) {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700477 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800478 }
479
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700480 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700481 int uid, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800482 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700483 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
484 appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700485 return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800486 } catch (RemoteException e) {
487 Log.w(TAG, "Cannot connect to keystore", e);
488 return SYSTEM_ERROR;
489 }
490 }
491
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700492 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
493 KeyCharacteristics outCharacteristics) {
494 return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
495 }
496
Chad Brubakere6a461342015-02-10 21:33:23 -0800497 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
498 int uid, int flags, KeyCharacteristics outCharacteristics) {
499 try {
500 return mBinder.importKey(alias, args, format, keyData, uid, flags,
501 outCharacteristics);
502 } catch (RemoteException e) {
503 Log.w(TAG, "Cannot connect to keystore", e);
504 return SYSTEM_ERROR;
505 }
506 }
507
508 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
509 int flags, KeyCharacteristics outCharacteristics) {
510 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
511 }
512
Frank Salim21d9c1d2017-12-19 22:38:09 -0800513 public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
514 String wrappingKeyAlias,
515 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
516 KeyCharacteristics outCharacteristics) {
517 try {
518 return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
519 maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
520 } catch (RemoteException e) {
521 Log.w(TAG, "Cannot connect to keystore", e);
522 return SYSTEM_ERROR;
523 }
524 }
525
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700526 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700527 KeymasterBlob appId, int uid) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800528 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700529 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
530 appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700531 return mBinder.exportKey(alias, format, clientId, appId, uid);
532 } catch (RemoteException e) {
533 Log.w(TAG, "Cannot connect to keystore", e);
534 return null;
535 }
536 }
537 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
538 KeymasterBlob appId) {
539 return exportKey(alias, format, clientId, appId, UID_SELF);
540 }
541
542 public OperationResult begin(String alias, int purpose, boolean pruneable,
543 KeymasterArguments args, byte[] entropy, int uid) {
544 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700545 args = args != null ? args : new KeymasterArguments();
546 entropy = entropy != null ? entropy : new byte[0];
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700547 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
Chad Brubakere6a461342015-02-10 21:33:23 -0800548 } catch (RemoteException e) {
549 Log.w(TAG, "Cannot connect to keystore", e);
550 return null;
551 }
552 }
553
554 public OperationResult begin(String alias, int purpose, boolean pruneable,
Chad Brubaker966486e2015-06-01 12:57:06 -0700555 KeymasterArguments args, byte[] entropy) {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700556 entropy = entropy != null ? entropy : new byte[0];
557 args = args != null ? args : new KeymasterArguments();
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700558 return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
Chad Brubakere6a461342015-02-10 21:33:23 -0800559 }
560
561 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
562 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700563 arguments = arguments != null ? arguments : new KeymasterArguments();
564 input = input != null ? input : new byte[0];
Chad Brubakere6a461342015-02-10 21:33:23 -0800565 return mBinder.update(token, arguments, input);
566 } catch (RemoteException e) {
567 Log.w(TAG, "Cannot connect to keystore", e);
568 return null;
569 }
570 }
571
Chad Brubaker8a077012015-05-29 12:32:51 -0700572 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
573 byte[] entropy) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800574 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700575 arguments = arguments != null ? arguments : new KeymasterArguments();
576 entropy = entropy != null ? entropy : new byte[0];
577 signature = signature != null ? signature : new byte[0];
Chad Brubaker8a077012015-05-29 12:32:51 -0700578 return mBinder.finish(token, arguments, signature, entropy);
Chad Brubakere6a461342015-02-10 21:33:23 -0800579 } catch (RemoteException e) {
580 Log.w(TAG, "Cannot connect to keystore", e);
581 return null;
582 }
583 }
584
Chad Brubaker8a077012015-05-29 12:32:51 -0700585 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
586 return finish(token, arguments, signature, null);
587 }
588
Chad Brubakere6a461342015-02-10 21:33:23 -0800589 public int abort(IBinder token) {
590 try {
591 return mBinder.abort(token);
592 } catch (RemoteException e) {
593 Log.w(TAG, "Cannot connect to keystore", e);
594 return SYSTEM_ERROR;
595 }
596 }
Chad Brubaker5654b362015-03-17 16:59:52 -0700597
598 /**
599 * Check if the operation referenced by {@code token} is currently authorized.
600 *
Alex Klyubin708fc9402015-04-28 18:58:47 -0700601 * @param token An operation token returned by a call to
602 * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
Chad Brubaker5654b362015-03-17 16:59:52 -0700603 */
604 public boolean isOperationAuthorized(IBinder token) {
605 try {
606 return mBinder.isOperationAuthorized(token);
607 } catch (RemoteException e) {
608 Log.w(TAG, "Cannot connect to keystore", e);
609 return false;
610 }
611 }
612
613 /**
614 * Add an authentication record to the keystore authorization table.
615 *
616 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
617 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
618 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
619 */
620 public int addAuthToken(byte[] authToken) {
621 try {
622 return mBinder.addAuthToken(authToken);
623 } catch (RemoteException e) {
624 Log.w(TAG, "Cannot connect to keystore", e);
625 return SYSTEM_ERROR;
626 }
627 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700628
Alex Klyubinad9ba102015-04-21 15:17:24 -0700629 /**
Chad Brubakera91a8502015-05-07 10:02:22 -0700630 * Notify keystore that a user's password has changed.
631 *
632 * @param userId the user whose password changed.
633 * @param newPassword the new password or "" if the password was removed.
634 */
635 public boolean onUserPasswordChanged(int userId, String newPassword) {
636 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
637 // explicit here.
638 if (newPassword == null) {
639 newPassword = "";
640 }
641 try {
642 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
643 } catch (RemoteException e) {
644 Log.w(TAG, "Cannot connect to keystore", e);
645 return false;
646 }
647 }
648
Chad Brubaker83ce0952015-05-12 13:00:02 -0700649 /**
650 * Notify keystore that a user was added.
651 *
652 * @param userId the new user.
653 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
654 * specified then the new user's keystore will be intialized with the same secure lockscreen
655 * password as the parent.
656 */
657 public void onUserAdded(int userId, int parentId) {
658 try {
659 mBinder.onUserAdded(userId, parentId);
660 } catch (RemoteException e) {
661 Log.w(TAG, "Cannot connect to keystore", e);
662 }
663 }
664
665 /**
666 * Notify keystore that a user was added.
667 *
668 * @param userId the new user.
669 */
670 public void onUserAdded(int userId) {
671 onUserAdded(userId, -1);
672 }
673
674 /**
675 * Notify keystore that a user was removed.
676 *
677 * @param userId the removed user.
678 */
679 public void onUserRemoved(int userId) {
680 try {
681 mBinder.onUserRemoved(userId);
682 } catch (RemoteException e) {
683 Log.w(TAG, "Cannot connect to keystore", e);
684 }
685 }
686
Chad Brubakera91a8502015-05-07 10:02:22 -0700687 public boolean onUserPasswordChanged(String newPassword) {
688 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
689 }
690
Shawn Willden8d8c7472016-02-02 08:27:39 -0700691 public int attestKey(
692 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
693 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700694 if (params == null) {
695 params = new KeymasterArguments();
696 }
697 if (outChain == null) {
698 outChain = new KeymasterCertificateChain();
699 }
Shawn Willden8d8c7472016-02-02 08:27:39 -0700700 return mBinder.attestKey(alias, params, outChain);
701 } catch (RemoteException e) {
702 Log.w(TAG, "Cannot connect to keystore", e);
703 return SYSTEM_ERROR;
704 }
705 }
706
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +0200707 public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) {
708 try {
Dmitry Dementyevefc43112017-10-27 23:10:28 -0700709 if (params == null) {
710 params = new KeymasterArguments();
711 }
712 if (outChain == null) {
713 outChain = new KeymasterCertificateChain();
714 }
Bartosz Fabianowski237f4b362017-04-24 13:57:46 +0200715 return mBinder.attestDeviceIds(params, outChain);
716 } catch (RemoteException e) {
717 Log.w(TAG, "Cannot connect to keystore", e);
718 return SYSTEM_ERROR;
719 }
720 }
721
Tucker Sylvestrob32aae22016-06-23 17:23:33 -0400722 /**
723 * Notify keystore that the device went off-body.
724 */
725 public void onDeviceOffBody() {
726 try {
727 mBinder.onDeviceOffBody();
728 } catch (RemoteException e) {
729 Log.w(TAG, "Cannot connect to keystore", e);
730 }
731 }
Shawn Willden8d8c7472016-02-02 08:27:39 -0700732
Chad Brubakera91a8502015-05-07 10:02:22 -0700733 /**
Alex Klyubinad9ba102015-04-21 15:17:24 -0700734 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
735 * code.
736 */
Alex Klyubindcdaf872015-05-13 15:57:09 -0700737 public static KeyStoreException getKeyStoreException(int errorCode) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700738 if (errorCode > 0) {
739 // KeyStore layer error
740 switch (errorCode) {
741 case NO_ERROR:
742 return new KeyStoreException(errorCode, "OK");
743 case LOCKED:
Alex Klyubin54183932015-05-08 15:25:48 -0700744 return new KeyStoreException(errorCode, "User authentication required");
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700745 case UNINITIALIZED:
746 return new KeyStoreException(errorCode, "Keystore not initialized");
747 case SYSTEM_ERROR:
748 return new KeyStoreException(errorCode, "System error");
749 case PERMISSION_DENIED:
750 return new KeyStoreException(errorCode, "Permission denied");
751 case KEY_NOT_FOUND:
752 return new KeyStoreException(errorCode, "Key not found");
753 case VALUE_CORRUPTED:
754 return new KeyStoreException(errorCode, "Key blob corrupted");
Alex Klyubin058de022015-04-29 17:32:00 -0700755 case OP_AUTH_NEEDED:
756 return new KeyStoreException(errorCode, "Operation requires authorization");
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700757 default:
758 return new KeyStoreException(errorCode, String.valueOf(errorCode));
759 }
760 } else {
761 // Keymaster layer error
762 switch (errorCode) {
763 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
764 // The name of this parameter significantly differs between Keymaster and
765 // framework APIs. Use the framework wording to make life easier for developers.
766 return new KeyStoreException(errorCode,
767 "Invalid user authentication validity duration");
768 default:
769 return new KeyStoreException(errorCode,
770 KeymasterDefs.getErrorMessage(errorCode));
771 }
772 }
773 }
774
Alex Klyubinad9ba102015-04-21 15:17:24 -0700775 /**
776 * Returns an {@link InvalidKeyException} corresponding to the provided
777 * {@link KeyStoreException}.
778 */
Alex Klyubindcdaf872015-05-13 15:57:09 -0700779 public InvalidKeyException getInvalidKeyException(
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700780 String keystoreKeyAlias, int uid, KeyStoreException e) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700781 switch (e.getErrorCode()) {
Alex Klyubin54183932015-05-08 15:25:48 -0700782 case LOCKED:
783 return new UserNotAuthenticatedException();
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700784 case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
785 return new KeyExpiredException();
786 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
787 return new KeyNotYetValidException();
788 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
Alex Klyubin058de022015-04-29 17:32:00 -0700789 case OP_AUTH_NEEDED:
Alex Klyubin708fc9402015-04-28 18:58:47 -0700790 {
791 // We now need to determine whether the key/operation can become usable if user
792 // authentication is performed, or whether it can never become usable again.
793 // User authentication requirements are contained in the key's characteristics. We
794 // need to check whether these requirements can be be satisfied by asking the user
795 // to authenticate.
796 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
797 int getKeyCharacteristicsErrorCode =
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700798 getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
799 keyCharacteristics);
Alex Klyubin708fc9402015-04-28 18:58:47 -0700800 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
801 return new InvalidKeyException(
802 "Failed to obtained key characteristics",
803 getKeyStoreException(getKeyCharacteristicsErrorCode));
804 }
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700805 List<BigInteger> keySids =
806 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
Alex Klyubin708fc9402015-04-28 18:58:47 -0700807 if (keySids.isEmpty()) {
808 // Key is not bound to any SIDs -- no amount of authentication will help here.
809 return new KeyPermanentlyInvalidatedException();
810 }
811 long rootSid = GateKeeper.getSecureUserId();
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700812 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700813 // One of the key's SIDs is the current root SID -- user can be authenticated
814 // against that SID.
815 return new UserNotAuthenticatedException();
816 }
817
818 long fingerprintOnlySid = getFingerprintOnlySid();
819 if ((fingerprintOnlySid != 0)
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700820 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700821 // One of the key's SIDs is the current fingerprint SID -- user can be
822 // authenticated against that SID.
823 return new UserNotAuthenticatedException();
824 }
825
826 // None of the key's SIDs can ever be authenticated
827 return new KeyPermanentlyInvalidatedException();
828 }
Janis Danisevskisd07d3382017-09-01 14:45:16 -0700829 case UNINITIALIZED:
830 return new KeyPermanentlyInvalidatedException();
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700831 default:
Alex Klyubinad9ba102015-04-21 15:17:24 -0700832 return new InvalidKeyException("Keystore operation failed", e);
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700833 }
834 }
835
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700836 private long getFingerprintOnlySid() {
Kevin Chyn55966422017-10-23 16:08:47 -0700837 final PackageManager packageManager = mContext.getPackageManager();
838 if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
839 return 0;
840 }
Alex Klyubina99b8b52015-06-11 13:27:34 -0700841 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700842 if (fingerprintManager == null) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700843 return 0;
844 }
845
Alex Klyubina99b8b52015-06-11 13:27:34 -0700846 // TODO: Restore USE_FINGERPRINT permission check in
847 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700848 return fingerprintManager.getAuthenticatorId();
Svetoslav2dac95d2015-04-30 11:30:33 -0700849 }
850
Alex Klyubinad9ba102015-04-21 15:17:24 -0700851 /**
852 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
853 * code.
854 */
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700855 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
856 int errorCode) {
857 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700858 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800859}