blob: 5b0e74a135a4d4b4bbb6aa53dc56bc889b39f08e [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;
Adam Langley6bf52c42015-04-24 09:59:35 -070021import com.android.org.conscrypt.NativeConstants;
Kenny Roota3985982013-08-16 14:03:29 -070022
Alex Klyubin708fc9402015-04-28 18:58:47 -070023import android.content.Context;
24import android.hardware.fingerprint.IFingerprintService;
Chad Brubakere6a461342015-02-10 21:33:23 -080025import android.os.Binder;
26import android.os.IBinder;
Kenny Root6b776452012-11-02 15:40:32 -070027import android.os.RemoteException;
28import android.os.ServiceManager;
Chad Brubakere6a461342015-02-10 21:33:23 -080029import android.security.keymaster.ExportResult;
30import android.security.keymaster.KeyCharacteristics;
31import android.security.keymaster.KeymasterArguments;
Chad Brubaker5e73c0e2015-03-21 22:46:43 -070032import android.security.keymaster.KeymasterBlob;
Alex Klyubinb4834ae2015-04-02 15:53:46 -070033import android.security.keymaster.KeymasterDefs;
Chad Brubakere6a461342015-02-10 21:33:23 -080034import android.security.keymaster.OperationResult;
Kenny Root6b776452012-11-02 15:40:32 -070035import android.util.Log;
Chia-chi Yeh44039172009-09-21 11:53:59 +080036
Alex Klyubinad9ba102015-04-21 15:17:24 -070037import java.security.InvalidKeyException;
Alex Klyubin708fc9402015-04-28 18:58:47 -070038import java.util.List;
Kenny Rootb91773b2013-09-05 13:03:16 -070039import java.util.Locale;
40
Chia-chi Yeh44039172009-09-21 11:53:59 +080041/**
Brian Carlstrom46703b02011-04-06 15:41:29 -070042 * @hide This should not be made public in its present form because it
43 * assumes that private and secret key bytes are available and would
44 * preclude the use of hardware crypto.
Chia-chi Yeh44039172009-09-21 11:53:59 +080045 */
46public class KeyStore {
Kenny Root6b776452012-11-02 15:40:32 -070047 private static final String TAG = "KeyStore";
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070048
49 // ResponseCodes
Brian Carlstrom7e4b1a42011-06-01 15:29:29 -070050 public static final int NO_ERROR = 1;
51 public static final int LOCKED = 2;
52 public static final int UNINITIALIZED = 3;
53 public static final int SYSTEM_ERROR = 4;
54 public static final int PROTOCOL_ERROR = 5;
55 public static final int PERMISSION_DENIED = 6;
56 public static final int KEY_NOT_FOUND = 7;
57 public static final int VALUE_CORRUPTED = 8;
58 public static final int UNDEFINED_ACTION = 9;
59 public static final int WRONG_PASSWORD = 10;
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070060
Chad Brubaker560d6532015-04-24 10:32:18 -070061 /**
62 * Per operation authentication is needed before this operation is valid.
63 * This is returned from {@link #begin} when begin succeeds but the operation uses
64 * per-operation authentication and must authenticate before calling {@link #update} or
65 * {@link #finish}.
66 */
67 public static final int OP_AUTH_NEEDED = 15;
68
Kenny Root2eeda722013-04-10 11:30:58 -070069 // Used for UID field to indicate the calling UID.
70 public static final int UID_SELF = -1;
71
72 // Flags for "put" "import" and "generate"
73 public static final int FLAG_NONE = 0;
Kenny Roota3788b02013-04-10 10:37:55 -070074 public static final int FLAG_ENCRYPTED = 1;
75
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070076 // States
77 public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
Chia-chi Yeh44039172009-09-21 11:53:59 +080078
Chia-chi Yeh44039172009-09-21 11:53:59 +080079 private int mError = NO_ERROR;
80
Kenny Root6b776452012-11-02 15:40:32 -070081 private final IKeystoreService mBinder;
82
Chad Brubakere6a461342015-02-10 21:33:23 -080083 private IBinder mToken;
84
Kenny Root6b776452012-11-02 15:40:32 -070085 private KeyStore(IKeystoreService binder) {
86 mBinder = binder;
87 }
Chia-chi Yeh44039172009-09-21 11:53:59 +080088
89 public static KeyStore getInstance() {
Kenny Root6b776452012-11-02 15:40:32 -070090 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
91 .getService("android.security.keystore"));
92 return new KeyStore(keystore);
Chia-chi Yeh44039172009-09-21 11:53:59 +080093 }
94
Chad Brubakere6a461342015-02-10 21:33:23 -080095 private synchronized IBinder getToken() {
96 if (mToken == null) {
97 mToken = new Binder();
98 }
99 return mToken;
100 }
101
Alex Klyubin21a76df2015-01-14 13:35:32 -0800102 static int getKeyTypeForAlgorithm(String keyType) {
Kenny Roota3985982013-08-16 14:03:29 -0700103 if ("RSA".equalsIgnoreCase(keyType)) {
Adam Langley6bf52c42015-04-24 09:59:35 -0700104 return NativeConstants.EVP_PKEY_RSA;
Kenny Roota3985982013-08-16 14:03:29 -0700105 } else if ("EC".equalsIgnoreCase(keyType)) {
Adam Langley6bf52c42015-04-24 09:59:35 -0700106 return NativeConstants.EVP_PKEY_EC;
Kenny Roota3985982013-08-16 14:03:29 -0700107 } else {
Alex Klyubin21a76df2015-01-14 13:35:32 -0800108 return -1;
Kenny Roota3985982013-08-16 14:03:29 -0700109 }
110 }
111
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700112 public State state() {
Kenny Root6b776452012-11-02 15:40:32 -0700113 final int ret;
114 try {
115 ret = mBinder.test();
116 } catch (RemoteException e) {
117 Log.w(TAG, "Cannot connect to keystore", e);
118 throw new AssertionError(e);
119 }
120
121 switch (ret) {
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700122 case NO_ERROR: return State.UNLOCKED;
123 case LOCKED: return State.LOCKED;
124 case UNINITIALIZED: return State.UNINITIALIZED;
125 default: throw new AssertionError(mError);
126 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800127 }
128
Kenny Rootb9594ce2013-02-14 10:18:38 -0800129 public boolean isUnlocked() {
130 return state() == State.UNLOCKED;
131 }
132
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700133 public byte[] get(String key) {
Kenny Root6b776452012-11-02 15:40:32 -0700134 try {
135 return mBinder.get(key);
136 } catch (RemoteException e) {
137 Log.w(TAG, "Cannot connect to keystore", e);
138 return null;
139 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800140 }
141
Kenny Roota3788b02013-04-10 10:37:55 -0700142 public boolean put(String key, byte[] value, int uid, int flags) {
Kenny Root6b776452012-11-02 15:40:32 -0700143 try {
Kenny Roota3788b02013-04-10 10:37:55 -0700144 return mBinder.insert(key, value, uid, flags) == NO_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800145 } catch (RemoteException e) {
146 Log.w(TAG, "Cannot connect to keystore", e);
147 return false;
148 }
149 }
150
Kenny Root78ad8492013-02-13 17:02:57 -0800151 public boolean delete(String key, int uid) {
152 try {
153 return mBinder.del(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700154 } catch (RemoteException e) {
155 Log.w(TAG, "Cannot connect to keystore", e);
156 return false;
157 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800158 }
159
160 public boolean delete(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700161 return delete(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800162 }
163
164 public boolean contains(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700165 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800166 return mBinder.exist(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700167 } catch (RemoteException e) {
168 Log.w(TAG, "Cannot connect to keystore", e);
169 return false;
170 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800171 }
172
173 public boolean contains(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700174 return contains(key, UID_SELF);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800175 }
176
Kenny Root78ad8492013-02-13 17:02:57 -0800177 public String[] saw(String prefix, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700178 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800179 return mBinder.saw(prefix, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700180 } catch (RemoteException e) {
181 Log.w(TAG, "Cannot connect to keystore", e);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800182 return null;
183 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800184 }
185
Kenny Root78ad8492013-02-13 17:02:57 -0800186 public String[] saw(String prefix) {
Kenny Root2eeda722013-04-10 11:30:58 -0700187 return saw(prefix, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800188 }
189
Chia-chi Yeh44039172009-09-21 11:53:59 +0800190 public boolean reset() {
Kenny Root6b776452012-11-02 15:40:32 -0700191 try {
192 return mBinder.reset() == NO_ERROR;
193 } catch (RemoteException e) {
194 Log.w(TAG, "Cannot connect to keystore", e);
195 return false;
196 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800197 }
198
Chia-chi Yeh44039172009-09-21 11:53:59 +0800199 public boolean password(String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700200 try {
201 return mBinder.password(password) == NO_ERROR;
202 } catch (RemoteException e) {
203 Log.w(TAG, "Cannot connect to keystore", e);
204 return false;
205 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800206 }
207
208 public boolean lock() {
Kenny Root6b776452012-11-02 15:40:32 -0700209 try {
210 return mBinder.lock() == NO_ERROR;
211 } catch (RemoteException e) {
212 Log.w(TAG, "Cannot connect to keystore", e);
213 return false;
214 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800215 }
216
217 public boolean unlock(String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700218 try {
219 mError = mBinder.unlock(password);
220 return mError == NO_ERROR;
221 } catch (RemoteException e) {
222 Log.w(TAG, "Cannot connect to keystore", e);
223 return false;
224 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800225 }
226
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700227 public boolean isEmpty() {
Kenny Root6b776452012-11-02 15:40:32 -0700228 try {
229 return mBinder.zero() == KEY_NOT_FOUND;
230 } catch (RemoteException e) {
231 Log.w(TAG, "Cannot connect to keystore", e);
232 return false;
233 }
Kenny Root5423e682011-11-14 08:43:13 -0800234 }
235
Kenny Roota3985982013-08-16 14:03:29 -0700236 public boolean generate(String key, int uid, int keyType, int keySize, int flags,
237 byte[][] args) {
Kenny Root6b776452012-11-02 15:40:32 -0700238 try {
Chad Brubaker7a2c9732015-01-13 17:41:22 -0800239 return mBinder.generate(key, uid, keyType, keySize, flags,
240 new KeystoreArguments(args)) == NO_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800241 } catch (RemoteException e) {
242 Log.w(TAG, "Cannot connect to keystore", e);
243 return false;
244 }
245 }
246
Kenny Roota3788b02013-04-10 10:37:55 -0700247 public boolean importKey(String keyName, byte[] key, int uid, int flags) {
Kenny Root78ad8492013-02-13 17:02:57 -0800248 try {
Kenny Roota3788b02013-04-10 10:37:55 -0700249 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700250 } catch (RemoteException e) {
251 Log.w(TAG, "Cannot connect to keystore", e);
252 return false;
253 }
Kenny Root5423e682011-11-14 08:43:13 -0800254 }
255
Kenny Root5423e682011-11-14 08:43:13 -0800256 public byte[] getPubkey(String key) {
Kenny Root6b776452012-11-02 15:40:32 -0700257 try {
258 return mBinder.get_pubkey(key);
259 } catch (RemoteException e) {
260 Log.w(TAG, "Cannot connect to keystore", e);
261 return null;
262 }
Kenny Root5423e682011-11-14 08:43:13 -0800263 }
264
Kenny Root78ad8492013-02-13 17:02:57 -0800265 public boolean delKey(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700266 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800267 return mBinder.del_key(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700268 } catch (RemoteException e) {
269 Log.w(TAG, "Cannot connect to keystore", e);
270 return false;
271 }
Kenny Root5423e682011-11-14 08:43:13 -0800272 }
273
Kenny Root78ad8492013-02-13 17:02:57 -0800274 public boolean delKey(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700275 return delKey(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800276 }
277
Kenny Root5423e682011-11-14 08:43:13 -0800278 public byte[] sign(String key, byte[] data) {
Kenny Root6b776452012-11-02 15:40:32 -0700279 try {
280 return mBinder.sign(key, data);
281 } catch (RemoteException e) {
282 Log.w(TAG, "Cannot connect to keystore", e);
283 return null;
284 }
Kenny Root5423e682011-11-14 08:43:13 -0800285 }
286
287 public boolean verify(String key, byte[] data, byte[] signature) {
Kenny Root6b776452012-11-02 15:40:32 -0700288 try {
289 return mBinder.verify(key, data, signature) == NO_ERROR;
290 } catch (RemoteException e) {
291 Log.w(TAG, "Cannot connect to keystore", e);
292 return false;
293 }
Kenny Root5423e682011-11-14 08:43:13 -0800294 }
295
296 public boolean grant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700297 try {
298 return mBinder.grant(key, uid) == NO_ERROR;
299 } catch (RemoteException e) {
300 Log.w(TAG, "Cannot connect to keystore", e);
301 return false;
302 }
Kenny Root5423e682011-11-14 08:43:13 -0800303 }
304
305 public boolean ungrant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700306 try {
307 return mBinder.ungrant(key, uid) == NO_ERROR;
308 } catch (RemoteException e) {
309 Log.w(TAG, "Cannot connect to keystore", e);
310 return false;
Kenny Root473c7122012-08-17 21:13:48 -0700311 }
Kenny Root473c7122012-08-17 21:13:48 -0700312 }
313
314 /**
315 * Returns the last modification time of the key in milliseconds since the
316 * epoch. Will return -1L if the key could not be found or other error.
317 */
318 public long getmtime(String key) {
Kenny Root6b776452012-11-02 15:40:32 -0700319 try {
Kenny Roote66769a2013-02-04 15:49:11 -0800320 final long millis = mBinder.getmtime(key);
321 if (millis == -1L) {
322 return -1L;
323 }
324
325 return millis * 1000L;
Kenny Root6b776452012-11-02 15:40:32 -0700326 } catch (RemoteException e) {
327 Log.w(TAG, "Cannot connect to keystore", e);
328 return -1L;
329 }
Kenny Root473c7122012-08-17 21:13:48 -0700330 }
331
Kenny Root5f1d9652013-03-21 14:21:50 -0700332 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
Kenny Rootbd794192013-03-20 11:36:50 -0700333 try {
Kenny Root5f1d9652013-03-21 14:21:50 -0700334 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
Kenny Rootbd794192013-03-20 11:36:50 -0700335 } catch (RemoteException e) {
336 Log.w(TAG, "Cannot connect to keystore", e);
337 return false;
338 }
339 }
340
Kenny Rootb91773b2013-09-05 13:03:16 -0700341 // TODO remove this when it's removed from Settings
Kenny Root5cb5cec2013-03-29 11:14:17 -0700342 public boolean isHardwareBacked() {
Kenny Rootb91773b2013-09-05 13:03:16 -0700343 return isHardwareBacked("RSA");
344 }
345
346 public boolean isHardwareBacked(String keyType) {
Kenny Root5cb5cec2013-03-29 11:14:17 -0700347 try {
Kenny Rootb91773b2013-09-05 13:03:16 -0700348 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
Kenny Root5cb5cec2013-03-29 11:14:17 -0700349 } catch (RemoteException e) {
350 Log.w(TAG, "Cannot connect to keystore", e);
351 return false;
352 }
353 }
354
Kenny Rootd72317a2013-04-01 15:59:59 -0700355 public boolean clearUid(int uid) {
356 try {
357 return mBinder.clear_uid(uid) == NO_ERROR;
358 } catch (RemoteException e) {
359 Log.w(TAG, "Cannot connect to keystore", e);
360 return false;
361 }
362 }
363
Robin Leef0246a82014-08-13 09:50:25 +0100364 public boolean resetUid(int uid) {
365 try {
366 mError = mBinder.reset_uid(uid);
367 return mError == NO_ERROR;
368 } catch (RemoteException e) {
369 Log.w(TAG, "Cannot connect to keystore", e);
370 return false;
371 }
372 }
373
374 public boolean syncUid(int sourceUid, int targetUid) {
375 try {
376 mError = mBinder.sync_uid(sourceUid, targetUid);
377 return mError == NO_ERROR;
378 } catch (RemoteException e) {
379 Log.w(TAG, "Cannot connect to keystore", e);
380 return false;
381 }
382 }
383
384 public boolean passwordUid(String password, int uid) {
385 try {
386 mError = mBinder.password_uid(password, uid);
387 return mError == NO_ERROR;
388 } catch (RemoteException e) {
389 Log.w(TAG, "Cannot connect to keystore", e);
390 return false;
391 }
392 }
393
Chia-chi Yeh44039172009-09-21 11:53:59 +0800394 public int getLastError() {
395 return mError;
396 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800397
398 public boolean addRngEntropy(byte[] data) {
399 try {
400 return mBinder.addRngEntropy(data) == NO_ERROR;
401 } catch (RemoteException e) {
402 Log.w(TAG, "Cannot connect to keystore", e);
403 return false;
404 }
405 }
406
Chad Brubakerdae79e52015-03-27 14:28:35 -0700407 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
408 int flags, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800409 try {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700410 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800411 } catch (RemoteException e) {
412 Log.w(TAG, "Cannot connect to keystore", e);
413 return SYSTEM_ERROR;
414 }
415 }
416
Chad Brubakerdae79e52015-03-27 14:28:35 -0700417 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800418 KeyCharacteristics outCharacteristics) {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700419 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800420 }
421
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700422 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
Chad Brubakere6a461342015-02-10 21:33:23 -0800423 KeyCharacteristics outCharacteristics) {
424 try {
425 return mBinder.getKeyCharacteristics(alias, clientId, appId, outCharacteristics);
426 } catch (RemoteException e) {
427 Log.w(TAG, "Cannot connect to keystore", e);
428 return SYSTEM_ERROR;
429 }
430 }
431
432 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
433 int uid, int flags, KeyCharacteristics outCharacteristics) {
434 try {
435 return mBinder.importKey(alias, args, format, keyData, uid, flags,
436 outCharacteristics);
437 } catch (RemoteException e) {
438 Log.w(TAG, "Cannot connect to keystore", e);
439 return SYSTEM_ERROR;
440 }
441 }
442
443 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
444 int flags, KeyCharacteristics outCharacteristics) {
445 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
446 }
447
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700448 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
449 KeymasterBlob appId) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800450 try {
451 return mBinder.exportKey(alias, format, clientId, appId);
452 } catch (RemoteException e) {
453 Log.w(TAG, "Cannot connect to keystore", e);
454 return null;
455 }
456 }
457
458 public OperationResult begin(String alias, int purpose, boolean pruneable,
Chad Brubakerdae79e52015-03-27 14:28:35 -0700459 KeymasterArguments args, byte[] entropy, KeymasterArguments outArgs) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800460 try {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700461 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, outArgs);
Chad Brubakere6a461342015-02-10 21:33:23 -0800462 } catch (RemoteException e) {
463 Log.w(TAG, "Cannot connect to keystore", e);
464 return null;
465 }
466 }
467
468 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
469 try {
470 return mBinder.update(token, arguments, input);
471 } catch (RemoteException e) {
472 Log.w(TAG, "Cannot connect to keystore", e);
473 return null;
474 }
475 }
476
477 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
478 try {
479 return mBinder.finish(token, arguments, signature);
480 } catch (RemoteException e) {
481 Log.w(TAG, "Cannot connect to keystore", e);
482 return null;
483 }
484 }
485
486 public int abort(IBinder token) {
487 try {
488 return mBinder.abort(token);
489 } catch (RemoteException e) {
490 Log.w(TAG, "Cannot connect to keystore", e);
491 return SYSTEM_ERROR;
492 }
493 }
Chad Brubaker5654b362015-03-17 16:59:52 -0700494
495 /**
496 * Check if the operation referenced by {@code token} is currently authorized.
497 *
Alex Klyubin708fc9402015-04-28 18:58:47 -0700498 * @param token An operation token returned by a call to
499 * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
Chad Brubaker5654b362015-03-17 16:59:52 -0700500 */
501 public boolean isOperationAuthorized(IBinder token) {
502 try {
503 return mBinder.isOperationAuthorized(token);
504 } catch (RemoteException e) {
505 Log.w(TAG, "Cannot connect to keystore", e);
506 return false;
507 }
508 }
509
510 /**
511 * Add an authentication record to the keystore authorization table.
512 *
513 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
514 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
515 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
516 */
517 public int addAuthToken(byte[] authToken) {
518 try {
519 return mBinder.addAuthToken(authToken);
520 } catch (RemoteException e) {
521 Log.w(TAG, "Cannot connect to keystore", e);
522 return SYSTEM_ERROR;
523 }
524 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700525
Alex Klyubinad9ba102015-04-21 15:17:24 -0700526 /**
527 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
528 * code.
529 */
530 static KeyStoreException getKeyStoreException(int errorCode) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700531 if (errorCode > 0) {
532 // KeyStore layer error
533 switch (errorCode) {
534 case NO_ERROR:
535 return new KeyStoreException(errorCode, "OK");
536 case LOCKED:
537 return new KeyStoreException(errorCode, "Keystore locked");
538 case UNINITIALIZED:
539 return new KeyStoreException(errorCode, "Keystore not initialized");
540 case SYSTEM_ERROR:
541 return new KeyStoreException(errorCode, "System error");
542 case PERMISSION_DENIED:
543 return new KeyStoreException(errorCode, "Permission denied");
544 case KEY_NOT_FOUND:
545 return new KeyStoreException(errorCode, "Key not found");
546 case VALUE_CORRUPTED:
547 return new KeyStoreException(errorCode, "Key blob corrupted");
Alex Klyubin058de022015-04-29 17:32:00 -0700548 case OP_AUTH_NEEDED:
549 return new KeyStoreException(errorCode, "Operation requires authorization");
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700550 default:
551 return new KeyStoreException(errorCode, String.valueOf(errorCode));
552 }
553 } else {
554 // Keymaster layer error
555 switch (errorCode) {
556 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
557 // The name of this parameter significantly differs between Keymaster and
558 // framework APIs. Use the framework wording to make life easier for developers.
559 return new KeyStoreException(errorCode,
560 "Invalid user authentication validity duration");
561 default:
562 return new KeyStoreException(errorCode,
563 KeymasterDefs.getErrorMessage(errorCode));
564 }
565 }
566 }
567
Alex Klyubinad9ba102015-04-21 15:17:24 -0700568 /**
569 * Returns an {@link InvalidKeyException} corresponding to the provided
570 * {@link KeyStoreException}.
571 */
Alex Klyubin708fc9402015-04-28 18:58:47 -0700572 InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, KeyStoreException e) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700573 switch (e.getErrorCode()) {
574 case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
575 return new KeyExpiredException();
576 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
577 return new KeyNotYetValidException();
578 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
Alex Klyubin058de022015-04-29 17:32:00 -0700579 case OP_AUTH_NEEDED:
Alex Klyubin708fc9402015-04-28 18:58:47 -0700580 {
581 // We now need to determine whether the key/operation can become usable if user
582 // authentication is performed, or whether it can never become usable again.
583 // User authentication requirements are contained in the key's characteristics. We
584 // need to check whether these requirements can be be satisfied by asking the user
585 // to authenticate.
586 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
587 int getKeyCharacteristicsErrorCode =
588 getKeyCharacteristics(keystoreKeyAlias, null, null, keyCharacteristics);
589 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
590 return new InvalidKeyException(
591 "Failed to obtained key characteristics",
592 getKeyStoreException(getKeyCharacteristicsErrorCode));
593 }
594 List<Long> keySids =
595 keyCharacteristics.getLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
596 if (keySids.isEmpty()) {
597 // Key is not bound to any SIDs -- no amount of authentication will help here.
598 return new KeyPermanentlyInvalidatedException();
599 }
600 long rootSid = GateKeeper.getSecureUserId();
601 if ((rootSid != 0) && (keySids.contains(Long.valueOf(rootSid)))) {
602 // One of the key's SIDs is the current root SID -- user can be authenticated
603 // against that SID.
604 return new UserNotAuthenticatedException();
605 }
606
607 long fingerprintOnlySid = getFingerprintOnlySid();
608 if ((fingerprintOnlySid != 0)
609 && (keySids.contains(Long.valueOf(fingerprintOnlySid)))) {
610 // One of the key's SIDs is the current fingerprint SID -- user can be
611 // authenticated against that SID.
612 return new UserNotAuthenticatedException();
613 }
614
615 // None of the key's SIDs can ever be authenticated
616 return new KeyPermanentlyInvalidatedException();
617 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700618 default:
Alex Klyubinad9ba102015-04-21 15:17:24 -0700619 return new InvalidKeyException("Keystore operation failed", e);
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700620 }
621 }
622
Alex Klyubin708fc9402015-04-28 18:58:47 -0700623 private static long getFingerprintOnlySid() {
624 IFingerprintService service = IFingerprintService.Stub.asInterface(
625 ServiceManager.getService(Context.FINGERPRINT_SERVICE));
626 if (service == null) {
627 return 0;
628 }
629
Svetoslav2dac95d2015-04-30 11:30:33 -0700630 String opPackageName = getMyOpPackageName();
631
Alex Klyubin708fc9402015-04-28 18:58:47 -0700632 try {
633 long deviceId = 0; // TODO: plumb hardware id to FPMS
Svetoslav2dac95d2015-04-30 11:30:33 -0700634 if (!service.isHardwareDetected(deviceId, opPackageName)) {
Alex Klyubin708fc9402015-04-28 18:58:47 -0700635 return 0;
636 }
637
Svetoslav2dac95d2015-04-30 11:30:33 -0700638 return service.getAuthenticatorId(opPackageName);
Alex Klyubin708fc9402015-04-28 18:58:47 -0700639 } catch (RemoteException e) {
640 throw new IllegalStateException("Failed to communicate with fingerprint service", e);
641 }
642 }
643
Svetoslav2dac95d2015-04-30 11:30:33 -0700644 private static String getMyOpPackageName() {
645 ActivityThread activityThread = ActivityThread.currentActivityThread();
646 if (activityThread != null) {
647 Application application = activityThread.getApplication();
648 if (application != null) {
649 return application.getOpPackageName();
650 }
651 }
652 throw new IllegalStateException("Cannot create AudioRecord outside of an app");
653 }
654
Alex Klyubinad9ba102015-04-21 15:17:24 -0700655 /**
656 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
657 * code.
658 */
Alex Klyubin708fc9402015-04-28 18:58:47 -0700659 InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int errorCode) {
660 return getInvalidKeyException(keystoreKeyAlias, getKeyStoreException(errorCode));
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700661 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800662}