blob: 70e4b6ff2e59081603b171bc39e5d554d2a7a8f7 [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;
Alex Klyubin2d7a85c2015-04-30 11:43:53 -070023import android.hardware.fingerprint.FingerprintManager;
Chad Brubakere6a461342015-02-10 21:33:23 -080024import android.os.Binder;
25import android.os.IBinder;
Chad Brubakera91a8502015-05-07 10:02:22 -070026import android.os.Process;
Kenny Root6b776452012-11-02 15:40:32 -070027import android.os.RemoteException;
28import android.os.ServiceManager;
Chad Brubakera91a8502015-05-07 10:02:22 -070029import android.os.UserHandle;
Chad Brubakere6a461342015-02-10 21:33:23 -080030import android.security.keymaster.ExportResult;
31import android.security.keymaster.KeyCharacteristics;
32import android.security.keymaster.KeymasterArguments;
Chad Brubaker5e73c0e2015-03-21 22:46:43 -070033import android.security.keymaster.KeymasterBlob;
Shawn Willden8d8c7472016-02-02 08:27:39 -070034import android.security.keymaster.KeymasterCertificateChain;
Alex Klyubinb4834ae2015-04-02 15:53:46 -070035import android.security.keymaster.KeymasterDefs;
Chad Brubakere6a461342015-02-10 21:33:23 -080036import android.security.keymaster.OperationResult;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070037import android.security.keystore.KeyExpiredException;
38import android.security.keystore.KeyNotYetValidException;
39import android.security.keystore.KeyPermanentlyInvalidatedException;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -070040import android.security.keystore.UserNotAuthenticatedException;
Kenny Root6b776452012-11-02 15:40:32 -070041import android.util.Log;
Chia-chi Yeh44039172009-09-21 11:53:59 +080042
Alex Klyubinae6cb7a2015-06-22 18:09:35 -070043import java.math.BigInteger;
Alex Klyubinad9ba102015-04-21 15:17:24 -070044import java.security.InvalidKeyException;
Alex Klyubin708fc9402015-04-28 18:58:47 -070045import java.util.List;
Kenny Rootb91773b2013-09-05 13:03:16 -070046import java.util.Locale;
47
Chia-chi Yeh44039172009-09-21 11:53:59 +080048/**
Brian Carlstrom46703b02011-04-06 15:41:29 -070049 * @hide This should not be made public in its present form because it
50 * assumes that private and secret key bytes are available and would
51 * preclude the use of hardware crypto.
Chia-chi Yeh44039172009-09-21 11:53:59 +080052 */
53public class KeyStore {
Kenny Root6b776452012-11-02 15:40:32 -070054 private static final String TAG = "KeyStore";
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070055
56 // ResponseCodes
Brian Carlstrom7e4b1a42011-06-01 15:29:29 -070057 public static final int NO_ERROR = 1;
58 public static final int LOCKED = 2;
59 public static final int UNINITIALIZED = 3;
60 public static final int SYSTEM_ERROR = 4;
61 public static final int PROTOCOL_ERROR = 5;
62 public static final int PERMISSION_DENIED = 6;
63 public static final int KEY_NOT_FOUND = 7;
64 public static final int VALUE_CORRUPTED = 8;
65 public static final int UNDEFINED_ACTION = 9;
66 public static final int WRONG_PASSWORD = 10;
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070067
Chad Brubaker560d6532015-04-24 10:32:18 -070068 /**
69 * Per operation authentication is needed before this operation is valid.
70 * This is returned from {@link #begin} when begin succeeds but the operation uses
71 * per-operation authentication and must authenticate before calling {@link #update} or
72 * {@link #finish}.
73 */
74 public static final int OP_AUTH_NEEDED = 15;
75
Kenny Root2eeda722013-04-10 11:30:58 -070076 // Used for UID field to indicate the calling UID.
77 public static final int UID_SELF = -1;
78
79 // Flags for "put" "import" and "generate"
80 public static final int FLAG_NONE = 0;
Alex Klyubin54183932015-05-08 15:25:48 -070081
82 /**
83 * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key
84 * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern).
85 *
86 * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set
87 * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key
88 * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or
89 * a Device Administrator). Finally, this key (or key pair) cannot be used until the user
90 * unlocks the secure lock screen after boot.
91 *
92 * @see KeyguardManager#isDeviceSecure()
93 */
Kenny Roota3788b02013-04-10 10:37:55 -070094 public static final int FLAG_ENCRYPTED = 1;
95
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070096 // States
97 public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
Chia-chi Yeh44039172009-09-21 11:53:59 +080098
Chia-chi Yeh44039172009-09-21 11:53:59 +080099 private int mError = NO_ERROR;
100
Kenny Root6b776452012-11-02 15:40:32 -0700101 private final IKeystoreService mBinder;
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700102 private final Context mContext;
Kenny Root6b776452012-11-02 15:40:32 -0700103
Chad Brubakere6a461342015-02-10 21:33:23 -0800104 private IBinder mToken;
105
Kenny Root6b776452012-11-02 15:40:32 -0700106 private KeyStore(IKeystoreService binder) {
107 mBinder = binder;
Alex Klyubin3f8d4d82015-05-13 09:15:00 -0700108 mContext = getApplicationContext();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700109 }
110
Alex Klyubindcdaf872015-05-13 15:57:09 -0700111 public static Context getApplicationContext() {
Alex Klyubina99b8b52015-06-11 13:27:34 -0700112 Application application = ActivityThread.currentApplication();
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700113 if (application == null) {
114 throw new IllegalStateException(
Alex Klyubina99b8b52015-06-11 13:27:34 -0700115 "Failed to obtain application Context from ActivityThread");
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700116 }
117 return application;
Kenny Root6b776452012-11-02 15:40:32 -0700118 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800119
120 public static KeyStore getInstance() {
Kenny Root6b776452012-11-02 15:40:32 -0700121 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
122 .getService("android.security.keystore"));
123 return new KeyStore(keystore);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800124 }
125
Chad Brubakere6a461342015-02-10 21:33:23 -0800126 private synchronized IBinder getToken() {
127 if (mToken == null) {
128 mToken = new Binder();
129 }
130 return mToken;
131 }
132
Chad Brubakere35d49f2015-05-12 15:19:52 -0700133 public State state(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700134 final int ret;
135 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700136 ret = mBinder.getState(userId);
Kenny Root6b776452012-11-02 15:40:32 -0700137 } catch (RemoteException e) {
138 Log.w(TAG, "Cannot connect to keystore", e);
139 throw new AssertionError(e);
140 }
141
142 switch (ret) {
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700143 case NO_ERROR: return State.UNLOCKED;
144 case LOCKED: return State.LOCKED;
145 case UNINITIALIZED: return State.UNINITIALIZED;
146 default: throw new AssertionError(mError);
147 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800148 }
149
Chad Brubakere35d49f2015-05-12 15:19:52 -0700150 public State state() {
151 return state(UserHandle.myUserId());
152 }
153
Kenny Rootb9594ce2013-02-14 10:18:38 -0800154 public boolean isUnlocked() {
155 return state() == State.UNLOCKED;
156 }
157
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700158 public byte[] get(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700159 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700160 return mBinder.get(key, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700161 } catch (RemoteException e) {
162 Log.w(TAG, "Cannot connect to keystore", e);
163 return null;
164 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800165 }
166
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700167 public byte[] get(String key) {
168 return get(key, UID_SELF);
169 }
170
Kenny Roota3788b02013-04-10 10:37:55 -0700171 public boolean put(String key, byte[] value, int uid, int flags) {
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700172 return insert(key, value, uid, flags) == NO_ERROR;
173 }
174
175 public int insert(String key, byte[] value, int uid, int flags) {
Kenny Root6b776452012-11-02 15:40:32 -0700176 try {
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700177 return mBinder.insert(key, value, uid, flags);
Kenny Root78ad8492013-02-13 17:02:57 -0800178 } catch (RemoteException e) {
179 Log.w(TAG, "Cannot connect to keystore", e);
Alex Klyubin3ceb1a02015-06-05 15:51:06 -0700180 return SYSTEM_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800181 }
182 }
183
Kenny Root78ad8492013-02-13 17:02:57 -0800184 public boolean delete(String key, int uid) {
185 try {
Robin Leee4487ea2016-02-29 17:43:54 +0000186 int ret = mBinder.del(key, uid);
187 return (ret == NO_ERROR || ret == KEY_NOT_FOUND);
Kenny Root6b776452012-11-02 15:40:32 -0700188 } catch (RemoteException e) {
189 Log.w(TAG, "Cannot connect to keystore", e);
190 return false;
191 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800192 }
193
194 public boolean delete(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700195 return delete(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800196 }
197
198 public boolean contains(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700199 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800200 return mBinder.exist(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700201 } catch (RemoteException e) {
202 Log.w(TAG, "Cannot connect to keystore", e);
203 return false;
204 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800205 }
206
207 public boolean contains(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700208 return contains(key, UID_SELF);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800209 }
210
Chad Brubakere35d49f2015-05-12 15:19:52 -0700211 /**
212 * List all entries in the keystore for {@code uid} starting with {@code prefix}.
213 */
214 public String[] list(String prefix, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700215 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700216 return mBinder.list(prefix, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700217 } catch (RemoteException e) {
218 Log.w(TAG, "Cannot connect to keystore", e);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800219 return null;
220 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800221 }
222
Chad Brubakere35d49f2015-05-12 15:19:52 -0700223 public String[] list(String prefix) {
224 return list(prefix, UID_SELF);
225 }
226
Chia-chi Yeh44039172009-09-21 11:53:59 +0800227 public boolean reset() {
Kenny Root6b776452012-11-02 15:40:32 -0700228 try {
229 return mBinder.reset() == NO_ERROR;
230 } catch (RemoteException e) {
231 Log.w(TAG, "Cannot connect to keystore", e);
232 return false;
233 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800234 }
235
Chad Brubakere35d49f2015-05-12 15:19:52 -0700236 /**
237 * Attempt to lock the keystore for {@code user}.
238 *
239 * @param user Android user to lock.
240 * @return whether {@code user}'s keystore was locked.
241 */
242 public boolean lock(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700243 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700244 return mBinder.lock(userId) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700245 } catch (RemoteException e) {
246 Log.w(TAG, "Cannot connect to keystore", e);
247 return false;
248 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800249 }
250
Chad Brubakere35d49f2015-05-12 15:19:52 -0700251 public boolean lock() {
252 return lock(UserHandle.myUserId());
253 }
254
Chad Brubakera91a8502015-05-07 10:02:22 -0700255 /**
256 * Attempt to unlock the keystore for {@code user} with the password {@code password}.
257 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
258 * created.
259 *
260 * @param user Android user ID to operate on
261 * @param password user's keystore password. Should be the most recent value passed to
262 * {@link #onUserPasswordChanged} for the user.
263 *
264 * @return whether the keystore was unlocked.
265 */
266 public boolean unlock(int userId, String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700267 try {
Chad Brubakera91a8502015-05-07 10:02:22 -0700268 mError = mBinder.unlock(userId, password);
Kenny Root6b776452012-11-02 15:40:32 -0700269 return mError == NO_ERROR;
270 } catch (RemoteException e) {
271 Log.w(TAG, "Cannot connect to keystore", e);
272 return false;
273 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800274 }
275
Chad Brubakera91a8502015-05-07 10:02:22 -0700276 public boolean unlock(String password) {
277 return unlock(UserHandle.getUserId(Process.myUid()), password);
278 }
279
Chad Brubakere35d49f2015-05-12 15:19:52 -0700280 /**
281 * Check if the keystore for {@code userId} is empty.
282 */
283 public boolean isEmpty(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700284 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700285 return mBinder.isEmpty(userId) != 0;
Kenny Root6b776452012-11-02 15:40:32 -0700286 } catch (RemoteException e) {
287 Log.w(TAG, "Cannot connect to keystore", e);
288 return false;
289 }
Kenny Root5423e682011-11-14 08:43:13 -0800290 }
291
Chad Brubakere35d49f2015-05-12 15:19:52 -0700292 public boolean isEmpty() {
293 return isEmpty(UserHandle.myUserId());
294 }
295
Kenny Roota3985982013-08-16 14:03:29 -0700296 public boolean generate(String key, int uid, int keyType, int keySize, int flags,
297 byte[][] args) {
Kenny Root6b776452012-11-02 15:40:32 -0700298 try {
Chad Brubaker7a2c9732015-01-13 17:41:22 -0800299 return mBinder.generate(key, uid, keyType, keySize, flags,
300 new KeystoreArguments(args)) == NO_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800301 } catch (RemoteException e) {
302 Log.w(TAG, "Cannot connect to keystore", e);
303 return false;
304 }
305 }
306
Kenny Roota3788b02013-04-10 10:37:55 -0700307 public boolean importKey(String keyName, byte[] key, int uid, int flags) {
Kenny Root78ad8492013-02-13 17:02:57 -0800308 try {
Kenny Roota3788b02013-04-10 10:37:55 -0700309 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700310 } catch (RemoteException e) {
311 Log.w(TAG, "Cannot connect to keystore", e);
312 return false;
313 }
Kenny Root5423e682011-11-14 08:43:13 -0800314 }
315
Kenny Root5423e682011-11-14 08:43:13 -0800316 public byte[] sign(String key, byte[] data) {
Kenny Root6b776452012-11-02 15:40:32 -0700317 try {
318 return mBinder.sign(key, data);
319 } catch (RemoteException e) {
320 Log.w(TAG, "Cannot connect to keystore", e);
321 return null;
322 }
Kenny Root5423e682011-11-14 08:43:13 -0800323 }
324
325 public boolean verify(String key, byte[] data, byte[] signature) {
Kenny Root6b776452012-11-02 15:40:32 -0700326 try {
327 return mBinder.verify(key, data, signature) == NO_ERROR;
328 } 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
334 public boolean grant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700335 try {
336 return mBinder.grant(key, uid) == NO_ERROR;
337 } catch (RemoteException e) {
338 Log.w(TAG, "Cannot connect to keystore", e);
339 return false;
340 }
Kenny Root5423e682011-11-14 08:43:13 -0800341 }
342
343 public boolean ungrant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700344 try {
345 return mBinder.ungrant(key, uid) == NO_ERROR;
346 } catch (RemoteException e) {
347 Log.w(TAG, "Cannot connect to keystore", e);
348 return false;
Kenny Root473c7122012-08-17 21:13:48 -0700349 }
Kenny Root473c7122012-08-17 21:13:48 -0700350 }
351
352 /**
353 * Returns the last modification time of the key in milliseconds since the
354 * epoch. Will return -1L if the key could not be found or other error.
355 */
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700356 public long getmtime(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700357 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700358 final long millis = mBinder.getmtime(key, uid);
Kenny Roote66769a2013-02-04 15:49:11 -0800359 if (millis == -1L) {
360 return -1L;
361 }
362
363 return millis * 1000L;
Kenny Root6b776452012-11-02 15:40:32 -0700364 } catch (RemoteException e) {
365 Log.w(TAG, "Cannot connect to keystore", e);
366 return -1L;
367 }
Kenny Root473c7122012-08-17 21:13:48 -0700368 }
369
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700370 public long getmtime(String key) {
371 return getmtime(key, UID_SELF);
372 }
373
Kenny Root5f1d9652013-03-21 14:21:50 -0700374 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
Kenny Rootbd794192013-03-20 11:36:50 -0700375 try {
Kenny Root5f1d9652013-03-21 14:21:50 -0700376 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
Kenny Rootbd794192013-03-20 11:36:50 -0700377 } catch (RemoteException e) {
378 Log.w(TAG, "Cannot connect to keystore", e);
379 return false;
380 }
381 }
382
Alex Klyubin469cbf52015-06-04 12:36:27 -0700383 // TODO: remove this when it's removed from Settings
Kenny Root5cb5cec2013-03-29 11:14:17 -0700384 public boolean isHardwareBacked() {
Kenny Rootb91773b2013-09-05 13:03:16 -0700385 return isHardwareBacked("RSA");
386 }
387
388 public boolean isHardwareBacked(String keyType) {
Kenny Root5cb5cec2013-03-29 11:14:17 -0700389 try {
Kenny Rootb91773b2013-09-05 13:03:16 -0700390 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
Kenny Root5cb5cec2013-03-29 11:14:17 -0700391 } catch (RemoteException e) {
392 Log.w(TAG, "Cannot connect to keystore", e);
393 return false;
394 }
395 }
396
Kenny Rootd72317a2013-04-01 15:59:59 -0700397 public boolean clearUid(int uid) {
398 try {
399 return mBinder.clear_uid(uid) == NO_ERROR;
400 } catch (RemoteException e) {
401 Log.w(TAG, "Cannot connect to keystore", e);
402 return false;
403 }
404 }
405
Chia-chi Yeh44039172009-09-21 11:53:59 +0800406 public int getLastError() {
407 return mError;
408 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800409
410 public boolean addRngEntropy(byte[] data) {
411 try {
412 return mBinder.addRngEntropy(data) == NO_ERROR;
413 } catch (RemoteException e) {
414 Log.w(TAG, "Cannot connect to keystore", e);
415 return false;
416 }
417 }
418
Chad Brubakerdae79e52015-03-27 14:28:35 -0700419 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
420 int flags, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800421 try {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700422 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800423 } catch (RemoteException e) {
424 Log.w(TAG, "Cannot connect to keystore", e);
425 return SYSTEM_ERROR;
426 }
427 }
428
Chad Brubakerdae79e52015-03-27 14:28:35 -0700429 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800430 KeyCharacteristics outCharacteristics) {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700431 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800432 }
433
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700434 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700435 int uid, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800436 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700437 return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800438 } catch (RemoteException e) {
439 Log.w(TAG, "Cannot connect to keystore", e);
440 return SYSTEM_ERROR;
441 }
442 }
443
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700444 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
445 KeyCharacteristics outCharacteristics) {
446 return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
447 }
448
Chad Brubakere6a461342015-02-10 21:33:23 -0800449 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
450 int uid, int flags, KeyCharacteristics outCharacteristics) {
451 try {
452 return mBinder.importKey(alias, args, format, keyData, uid, flags,
453 outCharacteristics);
454 } catch (RemoteException e) {
455 Log.w(TAG, "Cannot connect to keystore", e);
456 return SYSTEM_ERROR;
457 }
458 }
459
460 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
461 int flags, KeyCharacteristics outCharacteristics) {
462 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
463 }
464
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700465 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700466 KeymasterBlob appId, int uid) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800467 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700468 return mBinder.exportKey(alias, format, clientId, appId, uid);
469 } catch (RemoteException e) {
470 Log.w(TAG, "Cannot connect to keystore", e);
471 return null;
472 }
473 }
474 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
475 KeymasterBlob appId) {
476 return exportKey(alias, format, clientId, appId, UID_SELF);
477 }
478
479 public OperationResult begin(String alias, int purpose, boolean pruneable,
480 KeymasterArguments args, byte[] entropy, int uid) {
481 try {
482 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
Chad Brubakere6a461342015-02-10 21:33:23 -0800483 } catch (RemoteException e) {
484 Log.w(TAG, "Cannot connect to keystore", e);
485 return null;
486 }
487 }
488
489 public OperationResult begin(String alias, int purpose, boolean pruneable,
Chad Brubaker966486e2015-06-01 12:57:06 -0700490 KeymasterArguments args, byte[] entropy) {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700491 return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
Chad Brubakere6a461342015-02-10 21:33:23 -0800492 }
493
494 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
495 try {
496 return mBinder.update(token, arguments, input);
497 } catch (RemoteException e) {
498 Log.w(TAG, "Cannot connect to keystore", e);
499 return null;
500 }
501 }
502
Chad Brubaker8a077012015-05-29 12:32:51 -0700503 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
504 byte[] entropy) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800505 try {
Chad Brubaker8a077012015-05-29 12:32:51 -0700506 return mBinder.finish(token, arguments, signature, entropy);
Chad Brubakere6a461342015-02-10 21:33:23 -0800507 } catch (RemoteException e) {
508 Log.w(TAG, "Cannot connect to keystore", e);
509 return null;
510 }
511 }
512
Chad Brubaker8a077012015-05-29 12:32:51 -0700513 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
514 return finish(token, arguments, signature, null);
515 }
516
Chad Brubakere6a461342015-02-10 21:33:23 -0800517 public int abort(IBinder token) {
518 try {
519 return mBinder.abort(token);
520 } catch (RemoteException e) {
521 Log.w(TAG, "Cannot connect to keystore", e);
522 return SYSTEM_ERROR;
523 }
524 }
Chad Brubaker5654b362015-03-17 16:59:52 -0700525
526 /**
527 * Check if the operation referenced by {@code token} is currently authorized.
528 *
Alex Klyubin708fc9402015-04-28 18:58:47 -0700529 * @param token An operation token returned by a call to
530 * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
Chad Brubaker5654b362015-03-17 16:59:52 -0700531 */
532 public boolean isOperationAuthorized(IBinder token) {
533 try {
534 return mBinder.isOperationAuthorized(token);
535 } catch (RemoteException e) {
536 Log.w(TAG, "Cannot connect to keystore", e);
537 return false;
538 }
539 }
540
541 /**
542 * Add an authentication record to the keystore authorization table.
543 *
544 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
545 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
546 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
547 */
548 public int addAuthToken(byte[] authToken) {
549 try {
550 return mBinder.addAuthToken(authToken);
551 } catch (RemoteException e) {
552 Log.w(TAG, "Cannot connect to keystore", e);
553 return SYSTEM_ERROR;
554 }
555 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700556
Alex Klyubinad9ba102015-04-21 15:17:24 -0700557 /**
Chad Brubakera91a8502015-05-07 10:02:22 -0700558 * Notify keystore that a user's password has changed.
559 *
560 * @param userId the user whose password changed.
561 * @param newPassword the new password or "" if the password was removed.
562 */
563 public boolean onUserPasswordChanged(int userId, String newPassword) {
564 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
565 // explicit here.
566 if (newPassword == null) {
567 newPassword = "";
568 }
569 try {
570 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
571 } catch (RemoteException e) {
572 Log.w(TAG, "Cannot connect to keystore", e);
573 return false;
574 }
575 }
576
Chad Brubaker83ce0952015-05-12 13:00:02 -0700577 /**
578 * Notify keystore that a user was added.
579 *
580 * @param userId the new user.
581 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
582 * specified then the new user's keystore will be intialized with the same secure lockscreen
583 * password as the parent.
584 */
585 public void onUserAdded(int userId, int parentId) {
586 try {
587 mBinder.onUserAdded(userId, parentId);
588 } catch (RemoteException e) {
589 Log.w(TAG, "Cannot connect to keystore", e);
590 }
591 }
592
593 /**
594 * Notify keystore that a user was added.
595 *
596 * @param userId the new user.
597 */
598 public void onUserAdded(int userId) {
599 onUserAdded(userId, -1);
600 }
601
602 /**
603 * Notify keystore that a user was removed.
604 *
605 * @param userId the removed user.
606 */
607 public void onUserRemoved(int userId) {
608 try {
609 mBinder.onUserRemoved(userId);
610 } catch (RemoteException e) {
611 Log.w(TAG, "Cannot connect to keystore", e);
612 }
613 }
614
Chad Brubakera91a8502015-05-07 10:02:22 -0700615 public boolean onUserPasswordChanged(String newPassword) {
616 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
617 }
618
Shawn Willden8d8c7472016-02-02 08:27:39 -0700619 public int attestKey(
620 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
621 try {
622 return mBinder.attestKey(alias, params, outChain);
623 } catch (RemoteException e) {
624 Log.w(TAG, "Cannot connect to keystore", e);
625 return SYSTEM_ERROR;
626 }
627 }
628
629
Chad Brubakera91a8502015-05-07 10:02:22 -0700630 /**
Alex Klyubinad9ba102015-04-21 15:17:24 -0700631 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
632 * code.
633 */
Alex Klyubindcdaf872015-05-13 15:57:09 -0700634 public static KeyStoreException getKeyStoreException(int errorCode) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700635 if (errorCode > 0) {
636 // KeyStore layer error
637 switch (errorCode) {
638 case NO_ERROR:
639 return new KeyStoreException(errorCode, "OK");
640 case LOCKED:
Alex Klyubin54183932015-05-08 15:25:48 -0700641 return new KeyStoreException(errorCode, "User authentication required");
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700642 case UNINITIALIZED:
643 return new KeyStoreException(errorCode, "Keystore not initialized");
644 case SYSTEM_ERROR:
645 return new KeyStoreException(errorCode, "System error");
646 case PERMISSION_DENIED:
647 return new KeyStoreException(errorCode, "Permission denied");
648 case KEY_NOT_FOUND:
649 return new KeyStoreException(errorCode, "Key not found");
650 case VALUE_CORRUPTED:
651 return new KeyStoreException(errorCode, "Key blob corrupted");
Alex Klyubin058de022015-04-29 17:32:00 -0700652 case OP_AUTH_NEEDED:
653 return new KeyStoreException(errorCode, "Operation requires authorization");
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700654 default:
655 return new KeyStoreException(errorCode, String.valueOf(errorCode));
656 }
657 } else {
658 // Keymaster layer error
659 switch (errorCode) {
660 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
661 // The name of this parameter significantly differs between Keymaster and
662 // framework APIs. Use the framework wording to make life easier for developers.
663 return new KeyStoreException(errorCode,
664 "Invalid user authentication validity duration");
665 default:
666 return new KeyStoreException(errorCode,
667 KeymasterDefs.getErrorMessage(errorCode));
668 }
669 }
670 }
671
Alex Klyubinad9ba102015-04-21 15:17:24 -0700672 /**
673 * Returns an {@link InvalidKeyException} corresponding to the provided
674 * {@link KeyStoreException}.
675 */
Alex Klyubindcdaf872015-05-13 15:57:09 -0700676 public InvalidKeyException getInvalidKeyException(
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700677 String keystoreKeyAlias, int uid, KeyStoreException e) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700678 switch (e.getErrorCode()) {
Alex Klyubin54183932015-05-08 15:25:48 -0700679 case LOCKED:
680 return new UserNotAuthenticatedException();
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700681 case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
682 return new KeyExpiredException();
683 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
684 return new KeyNotYetValidException();
685 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
Alex Klyubin058de022015-04-29 17:32:00 -0700686 case OP_AUTH_NEEDED:
Alex Klyubin708fc9402015-04-28 18:58:47 -0700687 {
688 // We now need to determine whether the key/operation can become usable if user
689 // authentication is performed, or whether it can never become usable again.
690 // User authentication requirements are contained in the key's characteristics. We
691 // need to check whether these requirements can be be satisfied by asking the user
692 // to authenticate.
693 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
694 int getKeyCharacteristicsErrorCode =
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700695 getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
696 keyCharacteristics);
Alex Klyubin708fc9402015-04-28 18:58:47 -0700697 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
698 return new InvalidKeyException(
699 "Failed to obtained key characteristics",
700 getKeyStoreException(getKeyCharacteristicsErrorCode));
701 }
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700702 List<BigInteger> keySids =
703 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
Alex Klyubin708fc9402015-04-28 18:58:47 -0700704 if (keySids.isEmpty()) {
705 // Key is not bound to any SIDs -- no amount of authentication will help here.
706 return new KeyPermanentlyInvalidatedException();
707 }
708 long rootSid = GateKeeper.getSecureUserId();
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700709 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700710 // One of the key's SIDs is the current root SID -- user can be authenticated
711 // against that SID.
712 return new UserNotAuthenticatedException();
713 }
714
715 long fingerprintOnlySid = getFingerprintOnlySid();
716 if ((fingerprintOnlySid != 0)
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700717 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700718 // One of the key's SIDs is the current fingerprint SID -- user can be
719 // authenticated against that SID.
720 return new UserNotAuthenticatedException();
721 }
722
723 // None of the key's SIDs can ever be authenticated
724 return new KeyPermanentlyInvalidatedException();
725 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700726 default:
Alex Klyubinad9ba102015-04-21 15:17:24 -0700727 return new InvalidKeyException("Keystore operation failed", e);
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700728 }
729 }
730
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700731 private long getFingerprintOnlySid() {
Alex Klyubina99b8b52015-06-11 13:27:34 -0700732 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700733 if (fingerprintManager == null) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700734 return 0;
735 }
736
Alex Klyubina99b8b52015-06-11 13:27:34 -0700737 // TODO: Restore USE_FINGERPRINT permission check in
738 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700739 return fingerprintManager.getAuthenticatorId();
Svetoslav2dac95d2015-04-30 11:30:33 -0700740 }
741
Alex Klyubinad9ba102015-04-21 15:17:24 -0700742 /**
743 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
744 * code.
745 */
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700746 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
747 int errorCode) {
748 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700749 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800750}