blob: 3090ac1c6180a63967f64de8e1e3533f68828c95 [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 {
186 return mBinder.del(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700187 } catch (RemoteException e) {
188 Log.w(TAG, "Cannot connect to keystore", e);
189 return false;
190 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800191 }
192
193 public boolean delete(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700194 return delete(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800195 }
196
197 public boolean contains(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700198 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800199 return mBinder.exist(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700200 } catch (RemoteException e) {
201 Log.w(TAG, "Cannot connect to keystore", e);
202 return false;
203 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800204 }
205
206 public boolean contains(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700207 return contains(key, UID_SELF);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800208 }
209
Chad Brubakere35d49f2015-05-12 15:19:52 -0700210 /**
211 * List all entries in the keystore for {@code uid} starting with {@code prefix}.
212 */
213 public String[] list(String prefix, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700214 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700215 return mBinder.list(prefix, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700216 } catch (RemoteException e) {
217 Log.w(TAG, "Cannot connect to keystore", e);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800218 return null;
219 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800220 }
221
Chad Brubakere35d49f2015-05-12 15:19:52 -0700222 public String[] list(String prefix) {
223 return list(prefix, UID_SELF);
224 }
225
Chia-chi Yeh44039172009-09-21 11:53:59 +0800226 public boolean reset() {
Kenny Root6b776452012-11-02 15:40:32 -0700227 try {
228 return mBinder.reset() == NO_ERROR;
229 } catch (RemoteException e) {
230 Log.w(TAG, "Cannot connect to keystore", e);
231 return false;
232 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800233 }
234
Chad Brubakere35d49f2015-05-12 15:19:52 -0700235 /**
236 * Attempt to lock the keystore for {@code user}.
237 *
238 * @param user Android user to lock.
239 * @return whether {@code user}'s keystore was locked.
240 */
241 public boolean lock(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700242 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700243 return mBinder.lock(userId) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700244 } catch (RemoteException e) {
245 Log.w(TAG, "Cannot connect to keystore", e);
246 return false;
247 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800248 }
249
Chad Brubakere35d49f2015-05-12 15:19:52 -0700250 public boolean lock() {
251 return lock(UserHandle.myUserId());
252 }
253
Chad Brubakera91a8502015-05-07 10:02:22 -0700254 /**
255 * Attempt to unlock the keystore for {@code user} with the password {@code password}.
256 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
257 * created.
258 *
259 * @param user Android user ID to operate on
260 * @param password user's keystore password. Should be the most recent value passed to
261 * {@link #onUserPasswordChanged} for the user.
262 *
263 * @return whether the keystore was unlocked.
264 */
265 public boolean unlock(int userId, String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700266 try {
Chad Brubakera91a8502015-05-07 10:02:22 -0700267 mError = mBinder.unlock(userId, password);
Kenny Root6b776452012-11-02 15:40:32 -0700268 return mError == NO_ERROR;
269 } catch (RemoteException e) {
270 Log.w(TAG, "Cannot connect to keystore", e);
271 return false;
272 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800273 }
274
Chad Brubakera91a8502015-05-07 10:02:22 -0700275 public boolean unlock(String password) {
276 return unlock(UserHandle.getUserId(Process.myUid()), password);
277 }
278
Chad Brubakere35d49f2015-05-12 15:19:52 -0700279 /**
280 * Check if the keystore for {@code userId} is empty.
281 */
282 public boolean isEmpty(int userId) {
Kenny Root6b776452012-11-02 15:40:32 -0700283 try {
Chad Brubakere35d49f2015-05-12 15:19:52 -0700284 return mBinder.isEmpty(userId) != 0;
Kenny Root6b776452012-11-02 15:40:32 -0700285 } catch (RemoteException e) {
286 Log.w(TAG, "Cannot connect to keystore", e);
287 return false;
288 }
Kenny Root5423e682011-11-14 08:43:13 -0800289 }
290
Chad Brubakere35d49f2015-05-12 15:19:52 -0700291 public boolean isEmpty() {
292 return isEmpty(UserHandle.myUserId());
293 }
294
Kenny Roota3985982013-08-16 14:03:29 -0700295 public boolean generate(String key, int uid, int keyType, int keySize, int flags,
296 byte[][] args) {
Kenny Root6b776452012-11-02 15:40:32 -0700297 try {
Chad Brubaker7a2c9732015-01-13 17:41:22 -0800298 return mBinder.generate(key, uid, keyType, keySize, flags,
299 new KeystoreArguments(args)) == NO_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800300 } catch (RemoteException e) {
301 Log.w(TAG, "Cannot connect to keystore", e);
302 return false;
303 }
304 }
305
Kenny Roota3788b02013-04-10 10:37:55 -0700306 public boolean importKey(String keyName, byte[] key, int uid, int flags) {
Kenny Root78ad8492013-02-13 17:02:57 -0800307 try {
Kenny Roota3788b02013-04-10 10:37:55 -0700308 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700309 } catch (RemoteException e) {
310 Log.w(TAG, "Cannot connect to keystore", e);
311 return false;
312 }
Kenny Root5423e682011-11-14 08:43:13 -0800313 }
314
Kenny Root5423e682011-11-14 08:43:13 -0800315 public byte[] sign(String key, byte[] data) {
Kenny Root6b776452012-11-02 15:40:32 -0700316 try {
317 return mBinder.sign(key, data);
318 } catch (RemoteException e) {
319 Log.w(TAG, "Cannot connect to keystore", e);
320 return null;
321 }
Kenny Root5423e682011-11-14 08:43:13 -0800322 }
323
324 public boolean verify(String key, byte[] data, byte[] signature) {
Kenny Root6b776452012-11-02 15:40:32 -0700325 try {
326 return mBinder.verify(key, data, signature) == NO_ERROR;
327 } catch (RemoteException e) {
328 Log.w(TAG, "Cannot connect to keystore", e);
329 return false;
330 }
Kenny Root5423e682011-11-14 08:43:13 -0800331 }
332
333 public boolean grant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700334 try {
335 return mBinder.grant(key, uid) == NO_ERROR;
336 } catch (RemoteException e) {
337 Log.w(TAG, "Cannot connect to keystore", e);
338 return false;
339 }
Kenny Root5423e682011-11-14 08:43:13 -0800340 }
341
342 public boolean ungrant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700343 try {
344 return mBinder.ungrant(key, uid) == NO_ERROR;
345 } catch (RemoteException e) {
346 Log.w(TAG, "Cannot connect to keystore", e);
347 return false;
Kenny Root473c7122012-08-17 21:13:48 -0700348 }
Kenny Root473c7122012-08-17 21:13:48 -0700349 }
350
351 /**
352 * Returns the last modification time of the key in milliseconds since the
353 * epoch. Will return -1L if the key could not be found or other error.
354 */
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700355 public long getmtime(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700356 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700357 final long millis = mBinder.getmtime(key, uid);
Kenny Roote66769a2013-02-04 15:49:11 -0800358 if (millis == -1L) {
359 return -1L;
360 }
361
362 return millis * 1000L;
Kenny Root6b776452012-11-02 15:40:32 -0700363 } catch (RemoteException e) {
364 Log.w(TAG, "Cannot connect to keystore", e);
365 return -1L;
366 }
Kenny Root473c7122012-08-17 21:13:48 -0700367 }
368
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700369 public long getmtime(String key) {
370 return getmtime(key, UID_SELF);
371 }
372
Kenny Root5f1d9652013-03-21 14:21:50 -0700373 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
Kenny Rootbd794192013-03-20 11:36:50 -0700374 try {
Kenny Root5f1d9652013-03-21 14:21:50 -0700375 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
Kenny Rootbd794192013-03-20 11:36:50 -0700376 } catch (RemoteException e) {
377 Log.w(TAG, "Cannot connect to keystore", e);
378 return false;
379 }
380 }
381
Alex Klyubin469cbf52015-06-04 12:36:27 -0700382 // TODO: remove this when it's removed from Settings
Kenny Root5cb5cec2013-03-29 11:14:17 -0700383 public boolean isHardwareBacked() {
Kenny Rootb91773b2013-09-05 13:03:16 -0700384 return isHardwareBacked("RSA");
385 }
386
387 public boolean isHardwareBacked(String keyType) {
Kenny Root5cb5cec2013-03-29 11:14:17 -0700388 try {
Kenny Rootb91773b2013-09-05 13:03:16 -0700389 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
Kenny Root5cb5cec2013-03-29 11:14:17 -0700390 } catch (RemoteException e) {
391 Log.w(TAG, "Cannot connect to keystore", e);
392 return false;
393 }
394 }
395
Kenny Rootd72317a2013-04-01 15:59:59 -0700396 public boolean clearUid(int uid) {
397 try {
398 return mBinder.clear_uid(uid) == NO_ERROR;
399 } catch (RemoteException e) {
400 Log.w(TAG, "Cannot connect to keystore", e);
401 return false;
402 }
403 }
404
Chia-chi Yeh44039172009-09-21 11:53:59 +0800405 public int getLastError() {
406 return mError;
407 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800408
409 public boolean addRngEntropy(byte[] data) {
410 try {
411 return mBinder.addRngEntropy(data) == NO_ERROR;
412 } catch (RemoteException e) {
413 Log.w(TAG, "Cannot connect to keystore", e);
414 return false;
415 }
416 }
417
Chad Brubakerdae79e52015-03-27 14:28:35 -0700418 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
419 int flags, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800420 try {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700421 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800422 } catch (RemoteException e) {
423 Log.w(TAG, "Cannot connect to keystore", e);
424 return SYSTEM_ERROR;
425 }
426 }
427
Chad Brubakerdae79e52015-03-27 14:28:35 -0700428 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800429 KeyCharacteristics outCharacteristics) {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700430 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800431 }
432
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700433 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700434 int uid, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800435 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700436 return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800437 } catch (RemoteException e) {
438 Log.w(TAG, "Cannot connect to keystore", e);
439 return SYSTEM_ERROR;
440 }
441 }
442
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700443 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
444 KeyCharacteristics outCharacteristics) {
445 return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
446 }
447
Chad Brubakere6a461342015-02-10 21:33:23 -0800448 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
449 int uid, int flags, KeyCharacteristics outCharacteristics) {
450 try {
451 return mBinder.importKey(alias, args, format, keyData, uid, flags,
452 outCharacteristics);
453 } catch (RemoteException e) {
454 Log.w(TAG, "Cannot connect to keystore", e);
455 return SYSTEM_ERROR;
456 }
457 }
458
459 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
460 int flags, KeyCharacteristics outCharacteristics) {
461 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
462 }
463
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700464 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700465 KeymasterBlob appId, int uid) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800466 try {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700467 return mBinder.exportKey(alias, format, clientId, appId, uid);
468 } catch (RemoteException e) {
469 Log.w(TAG, "Cannot connect to keystore", e);
470 return null;
471 }
472 }
473 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
474 KeymasterBlob appId) {
475 return exportKey(alias, format, clientId, appId, UID_SELF);
476 }
477
478 public OperationResult begin(String alias, int purpose, boolean pruneable,
479 KeymasterArguments args, byte[] entropy, int uid) {
480 try {
481 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
Chad Brubakere6a461342015-02-10 21:33:23 -0800482 } catch (RemoteException e) {
483 Log.w(TAG, "Cannot connect to keystore", e);
484 return null;
485 }
486 }
487
488 public OperationResult begin(String alias, int purpose, boolean pruneable,
Chad Brubaker966486e2015-06-01 12:57:06 -0700489 KeymasterArguments args, byte[] entropy) {
Chad Brubaker5bbf0482015-09-09 14:53:52 -0700490 return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
Chad Brubakere6a461342015-02-10 21:33:23 -0800491 }
492
493 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
494 try {
495 return mBinder.update(token, arguments, input);
496 } catch (RemoteException e) {
497 Log.w(TAG, "Cannot connect to keystore", e);
498 return null;
499 }
500 }
501
Chad Brubaker8a077012015-05-29 12:32:51 -0700502 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
503 byte[] entropy) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800504 try {
Chad Brubaker8a077012015-05-29 12:32:51 -0700505 return mBinder.finish(token, arguments, signature, entropy);
Chad Brubakere6a461342015-02-10 21:33:23 -0800506 } catch (RemoteException e) {
507 Log.w(TAG, "Cannot connect to keystore", e);
508 return null;
509 }
510 }
511
Chad Brubaker8a077012015-05-29 12:32:51 -0700512 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
513 return finish(token, arguments, signature, null);
514 }
515
Chad Brubakere6a461342015-02-10 21:33:23 -0800516 public int abort(IBinder token) {
517 try {
518 return mBinder.abort(token);
519 } catch (RemoteException e) {
520 Log.w(TAG, "Cannot connect to keystore", e);
521 return SYSTEM_ERROR;
522 }
523 }
Chad Brubaker5654b362015-03-17 16:59:52 -0700524
525 /**
526 * Check if the operation referenced by {@code token} is currently authorized.
527 *
Alex Klyubin708fc9402015-04-28 18:58:47 -0700528 * @param token An operation token returned by a call to
529 * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
Chad Brubaker5654b362015-03-17 16:59:52 -0700530 */
531 public boolean isOperationAuthorized(IBinder token) {
532 try {
533 return mBinder.isOperationAuthorized(token);
534 } catch (RemoteException e) {
535 Log.w(TAG, "Cannot connect to keystore", e);
536 return false;
537 }
538 }
539
540 /**
541 * Add an authentication record to the keystore authorization table.
542 *
543 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
544 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
545 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
546 */
547 public int addAuthToken(byte[] authToken) {
548 try {
549 return mBinder.addAuthToken(authToken);
550 } catch (RemoteException e) {
551 Log.w(TAG, "Cannot connect to keystore", e);
552 return SYSTEM_ERROR;
553 }
554 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700555
Alex Klyubinad9ba102015-04-21 15:17:24 -0700556 /**
Chad Brubakera91a8502015-05-07 10:02:22 -0700557 * Notify keystore that a user's password has changed.
558 *
559 * @param userId the user whose password changed.
560 * @param newPassword the new password or "" if the password was removed.
561 */
562 public boolean onUserPasswordChanged(int userId, String newPassword) {
563 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
564 // explicit here.
565 if (newPassword == null) {
566 newPassword = "";
567 }
568 try {
569 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
570 } catch (RemoteException e) {
571 Log.w(TAG, "Cannot connect to keystore", e);
572 return false;
573 }
574 }
575
Chad Brubaker83ce0952015-05-12 13:00:02 -0700576 /**
577 * Notify keystore that a user was added.
578 *
579 * @param userId the new user.
580 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
581 * specified then the new user's keystore will be intialized with the same secure lockscreen
582 * password as the parent.
583 */
584 public void onUserAdded(int userId, int parentId) {
585 try {
586 mBinder.onUserAdded(userId, parentId);
587 } catch (RemoteException e) {
588 Log.w(TAG, "Cannot connect to keystore", e);
589 }
590 }
591
592 /**
593 * Notify keystore that a user was added.
594 *
595 * @param userId the new user.
596 */
597 public void onUserAdded(int userId) {
598 onUserAdded(userId, -1);
599 }
600
601 /**
602 * Notify keystore that a user was removed.
603 *
604 * @param userId the removed user.
605 */
606 public void onUserRemoved(int userId) {
607 try {
608 mBinder.onUserRemoved(userId);
609 } catch (RemoteException e) {
610 Log.w(TAG, "Cannot connect to keystore", e);
611 }
612 }
613
Chad Brubakera91a8502015-05-07 10:02:22 -0700614 public boolean onUserPasswordChanged(String newPassword) {
615 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
616 }
617
Shawn Willden8d8c7472016-02-02 08:27:39 -0700618 public int attestKey(
619 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
620 try {
621 return mBinder.attestKey(alias, params, outChain);
622 } catch (RemoteException e) {
623 Log.w(TAG, "Cannot connect to keystore", e);
624 return SYSTEM_ERROR;
625 }
626 }
627
628
Chad Brubakera91a8502015-05-07 10:02:22 -0700629 /**
Alex Klyubinad9ba102015-04-21 15:17:24 -0700630 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
631 * code.
632 */
Alex Klyubindcdaf872015-05-13 15:57:09 -0700633 public static KeyStoreException getKeyStoreException(int errorCode) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700634 if (errorCode > 0) {
635 // KeyStore layer error
636 switch (errorCode) {
637 case NO_ERROR:
638 return new KeyStoreException(errorCode, "OK");
639 case LOCKED:
Alex Klyubin54183932015-05-08 15:25:48 -0700640 return new KeyStoreException(errorCode, "User authentication required");
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700641 case UNINITIALIZED:
642 return new KeyStoreException(errorCode, "Keystore not initialized");
643 case SYSTEM_ERROR:
644 return new KeyStoreException(errorCode, "System error");
645 case PERMISSION_DENIED:
646 return new KeyStoreException(errorCode, "Permission denied");
647 case KEY_NOT_FOUND:
648 return new KeyStoreException(errorCode, "Key not found");
649 case VALUE_CORRUPTED:
650 return new KeyStoreException(errorCode, "Key blob corrupted");
Alex Klyubin058de022015-04-29 17:32:00 -0700651 case OP_AUTH_NEEDED:
652 return new KeyStoreException(errorCode, "Operation requires authorization");
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700653 default:
654 return new KeyStoreException(errorCode, String.valueOf(errorCode));
655 }
656 } else {
657 // Keymaster layer error
658 switch (errorCode) {
659 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
660 // The name of this parameter significantly differs between Keymaster and
661 // framework APIs. Use the framework wording to make life easier for developers.
662 return new KeyStoreException(errorCode,
663 "Invalid user authentication validity duration");
664 default:
665 return new KeyStoreException(errorCode,
666 KeymasterDefs.getErrorMessage(errorCode));
667 }
668 }
669 }
670
Alex Klyubinad9ba102015-04-21 15:17:24 -0700671 /**
672 * Returns an {@link InvalidKeyException} corresponding to the provided
673 * {@link KeyStoreException}.
674 */
Alex Klyubindcdaf872015-05-13 15:57:09 -0700675 public InvalidKeyException getInvalidKeyException(
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700676 String keystoreKeyAlias, int uid, KeyStoreException e) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700677 switch (e.getErrorCode()) {
Alex Klyubin54183932015-05-08 15:25:48 -0700678 case LOCKED:
679 return new UserNotAuthenticatedException();
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700680 case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
681 return new KeyExpiredException();
682 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
683 return new KeyNotYetValidException();
684 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
Alex Klyubin058de022015-04-29 17:32:00 -0700685 case OP_AUTH_NEEDED:
Alex Klyubin708fc9402015-04-28 18:58:47 -0700686 {
687 // We now need to determine whether the key/operation can become usable if user
688 // authentication is performed, or whether it can never become usable again.
689 // User authentication requirements are contained in the key's characteristics. We
690 // need to check whether these requirements can be be satisfied by asking the user
691 // to authenticate.
692 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
693 int getKeyCharacteristicsErrorCode =
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700694 getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
695 keyCharacteristics);
Alex Klyubin708fc9402015-04-28 18:58:47 -0700696 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
697 return new InvalidKeyException(
698 "Failed to obtained key characteristics",
699 getKeyStoreException(getKeyCharacteristicsErrorCode));
700 }
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700701 List<BigInteger> keySids =
702 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
Alex Klyubin708fc9402015-04-28 18:58:47 -0700703 if (keySids.isEmpty()) {
704 // Key is not bound to any SIDs -- no amount of authentication will help here.
705 return new KeyPermanentlyInvalidatedException();
706 }
707 long rootSid = GateKeeper.getSecureUserId();
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700708 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700709 // One of the key's SIDs is the current root SID -- user can be authenticated
710 // against that SID.
711 return new UserNotAuthenticatedException();
712 }
713
714 long fingerprintOnlySid = getFingerprintOnlySid();
715 if ((fingerprintOnlySid != 0)
Alex Klyubinae6cb7a2015-06-22 18:09:35 -0700716 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700717 // One of the key's SIDs is the current fingerprint SID -- user can be
718 // authenticated against that SID.
719 return new UserNotAuthenticatedException();
720 }
721
722 // None of the key's SIDs can ever be authenticated
723 return new KeyPermanentlyInvalidatedException();
724 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700725 default:
Alex Klyubinad9ba102015-04-21 15:17:24 -0700726 return new InvalidKeyException("Keystore operation failed", e);
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700727 }
728 }
729
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700730 private long getFingerprintOnlySid() {
Alex Klyubina99b8b52015-06-11 13:27:34 -0700731 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700732 if (fingerprintManager == null) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700733 return 0;
734 }
735
Alex Klyubina99b8b52015-06-11 13:27:34 -0700736 // TODO: Restore USE_FINGERPRINT permission check in
737 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
Alex Klyubin2d7a85c2015-04-30 11:43:53 -0700738 return fingerprintManager.getAuthenticatorId();
Svetoslav2dac95d2015-04-30 11:30:33 -0700739 }
740
Alex Klyubinad9ba102015-04-21 15:17:24 -0700741 /**
742 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
743 * code.
744 */
Alex Klyubin3876b1b2015-09-09 14:55:03 -0700745 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
746 int errorCode) {
747 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700748 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800749}