blob: f3b447e035402d59fe64072584f4b4b936507f65 [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
Adam Langley6bf52c42015-04-24 09:59:35 -070019import com.android.org.conscrypt.NativeConstants;
Kenny Roota3985982013-08-16 14:03:29 -070020
Alex Klyubin708fc9402015-04-28 18:58:47 -070021import android.content.Context;
22import android.hardware.fingerprint.IFingerprintService;
Chad Brubakere6a461342015-02-10 21:33:23 -080023import android.os.Binder;
24import android.os.IBinder;
Kenny Root6b776452012-11-02 15:40:32 -070025import android.os.RemoteException;
26import android.os.ServiceManager;
Chad Brubakere6a461342015-02-10 21:33:23 -080027import android.security.keymaster.ExportResult;
28import android.security.keymaster.KeyCharacteristics;
29import android.security.keymaster.KeymasterArguments;
Chad Brubaker5e73c0e2015-03-21 22:46:43 -070030import android.security.keymaster.KeymasterBlob;
Alex Klyubinb4834ae2015-04-02 15:53:46 -070031import android.security.keymaster.KeymasterDefs;
Chad Brubakere6a461342015-02-10 21:33:23 -080032import android.security.keymaster.OperationResult;
Kenny Root6b776452012-11-02 15:40:32 -070033import android.util.Log;
Chia-chi Yeh44039172009-09-21 11:53:59 +080034
Alex Klyubinad9ba102015-04-21 15:17:24 -070035import java.security.InvalidKeyException;
Alex Klyubin708fc9402015-04-28 18:58:47 -070036import java.util.List;
Kenny Rootb91773b2013-09-05 13:03:16 -070037import java.util.Locale;
38
Chia-chi Yeh44039172009-09-21 11:53:59 +080039/**
Brian Carlstrom46703b02011-04-06 15:41:29 -070040 * @hide This should not be made public in its present form because it
41 * assumes that private and secret key bytes are available and would
42 * preclude the use of hardware crypto.
Chia-chi Yeh44039172009-09-21 11:53:59 +080043 */
44public class KeyStore {
Kenny Root6b776452012-11-02 15:40:32 -070045 private static final String TAG = "KeyStore";
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070046
47 // ResponseCodes
Brian Carlstrom7e4b1a42011-06-01 15:29:29 -070048 public static final int NO_ERROR = 1;
49 public static final int LOCKED = 2;
50 public static final int UNINITIALIZED = 3;
51 public static final int SYSTEM_ERROR = 4;
52 public static final int PROTOCOL_ERROR = 5;
53 public static final int PERMISSION_DENIED = 6;
54 public static final int KEY_NOT_FOUND = 7;
55 public static final int VALUE_CORRUPTED = 8;
56 public static final int UNDEFINED_ACTION = 9;
57 public static final int WRONG_PASSWORD = 10;
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070058
Chad Brubaker560d6532015-04-24 10:32:18 -070059 /**
60 * Per operation authentication is needed before this operation is valid.
61 * This is returned from {@link #begin} when begin succeeds but the operation uses
62 * per-operation authentication and must authenticate before calling {@link #update} or
63 * {@link #finish}.
64 */
65 public static final int OP_AUTH_NEEDED = 15;
66
Kenny Root2eeda722013-04-10 11:30:58 -070067 // Used for UID field to indicate the calling UID.
68 public static final int UID_SELF = -1;
69
70 // Flags for "put" "import" and "generate"
71 public static final int FLAG_NONE = 0;
Kenny Roota3788b02013-04-10 10:37:55 -070072 public static final int FLAG_ENCRYPTED = 1;
73
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -070074 // States
75 public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
Chia-chi Yeh44039172009-09-21 11:53:59 +080076
Chia-chi Yeh44039172009-09-21 11:53:59 +080077 private int mError = NO_ERROR;
78
Kenny Root6b776452012-11-02 15:40:32 -070079 private final IKeystoreService mBinder;
80
Chad Brubakere6a461342015-02-10 21:33:23 -080081 private IBinder mToken;
82
Kenny Root6b776452012-11-02 15:40:32 -070083 private KeyStore(IKeystoreService binder) {
84 mBinder = binder;
85 }
Chia-chi Yeh44039172009-09-21 11:53:59 +080086
87 public static KeyStore getInstance() {
Kenny Root6b776452012-11-02 15:40:32 -070088 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
89 .getService("android.security.keystore"));
90 return new KeyStore(keystore);
Chia-chi Yeh44039172009-09-21 11:53:59 +080091 }
92
Chad Brubakere6a461342015-02-10 21:33:23 -080093 private synchronized IBinder getToken() {
94 if (mToken == null) {
95 mToken = new Binder();
96 }
97 return mToken;
98 }
99
Alex Klyubin21a76df2015-01-14 13:35:32 -0800100 static int getKeyTypeForAlgorithm(String keyType) {
Kenny Roota3985982013-08-16 14:03:29 -0700101 if ("RSA".equalsIgnoreCase(keyType)) {
Adam Langley6bf52c42015-04-24 09:59:35 -0700102 return NativeConstants.EVP_PKEY_RSA;
Kenny Roota3985982013-08-16 14:03:29 -0700103 } else if ("EC".equalsIgnoreCase(keyType)) {
Adam Langley6bf52c42015-04-24 09:59:35 -0700104 return NativeConstants.EVP_PKEY_EC;
Kenny Roota3985982013-08-16 14:03:29 -0700105 } else {
Alex Klyubin21a76df2015-01-14 13:35:32 -0800106 return -1;
Kenny Roota3985982013-08-16 14:03:29 -0700107 }
108 }
109
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700110 public State state() {
Kenny Root6b776452012-11-02 15:40:32 -0700111 final int ret;
112 try {
113 ret = mBinder.test();
114 } catch (RemoteException e) {
115 Log.w(TAG, "Cannot connect to keystore", e);
116 throw new AssertionError(e);
117 }
118
119 switch (ret) {
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700120 case NO_ERROR: return State.UNLOCKED;
121 case LOCKED: return State.LOCKED;
122 case UNINITIALIZED: return State.UNINITIALIZED;
123 default: throw new AssertionError(mError);
124 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800125 }
126
Kenny Rootb9594ce2013-02-14 10:18:38 -0800127 public boolean isUnlocked() {
128 return state() == State.UNLOCKED;
129 }
130
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700131 public byte[] get(String key) {
Kenny Root6b776452012-11-02 15:40:32 -0700132 try {
133 return mBinder.get(key);
134 } catch (RemoteException e) {
135 Log.w(TAG, "Cannot connect to keystore", e);
136 return null;
137 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800138 }
139
Kenny Roota3788b02013-04-10 10:37:55 -0700140 public boolean put(String key, byte[] value, int uid, int flags) {
Kenny Root6b776452012-11-02 15:40:32 -0700141 try {
Kenny Roota3788b02013-04-10 10:37:55 -0700142 return mBinder.insert(key, value, uid, flags) == NO_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800143 } catch (RemoteException e) {
144 Log.w(TAG, "Cannot connect to keystore", e);
145 return false;
146 }
147 }
148
Kenny Root78ad8492013-02-13 17:02:57 -0800149 public boolean delete(String key, int uid) {
150 try {
151 return mBinder.del(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700152 } catch (RemoteException e) {
153 Log.w(TAG, "Cannot connect to keystore", e);
154 return false;
155 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800156 }
157
158 public boolean delete(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700159 return delete(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800160 }
161
162 public boolean contains(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700163 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800164 return mBinder.exist(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700165 } catch (RemoteException e) {
166 Log.w(TAG, "Cannot connect to keystore", e);
167 return false;
168 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800169 }
170
171 public boolean contains(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700172 return contains(key, UID_SELF);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800173 }
174
Kenny Root78ad8492013-02-13 17:02:57 -0800175 public String[] saw(String prefix, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700176 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800177 return mBinder.saw(prefix, uid);
Kenny Root6b776452012-11-02 15:40:32 -0700178 } catch (RemoteException e) {
179 Log.w(TAG, "Cannot connect to keystore", e);
Chia-chi Yeh44039172009-09-21 11:53:59 +0800180 return null;
181 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800182 }
183
Kenny Root78ad8492013-02-13 17:02:57 -0800184 public String[] saw(String prefix) {
Kenny Root2eeda722013-04-10 11:30:58 -0700185 return saw(prefix, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800186 }
187
Chia-chi Yeh44039172009-09-21 11:53:59 +0800188 public boolean reset() {
Kenny Root6b776452012-11-02 15:40:32 -0700189 try {
190 return mBinder.reset() == NO_ERROR;
191 } catch (RemoteException e) {
192 Log.w(TAG, "Cannot connect to keystore", e);
193 return false;
194 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800195 }
196
Chia-chi Yeh44039172009-09-21 11:53:59 +0800197 public boolean password(String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700198 try {
199 return mBinder.password(password) == NO_ERROR;
200 } 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 lock() {
Kenny Root6b776452012-11-02 15:40:32 -0700207 try {
208 return mBinder.lock() == NO_ERROR;
209 } catch (RemoteException e) {
210 Log.w(TAG, "Cannot connect to keystore", e);
211 return false;
212 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800213 }
214
215 public boolean unlock(String password) {
Kenny Root6b776452012-11-02 15:40:32 -0700216 try {
217 mError = mBinder.unlock(password);
218 return mError == NO_ERROR;
219 } catch (RemoteException e) {
220 Log.w(TAG, "Cannot connect to keystore", e);
221 return false;
222 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800223 }
224
Brian Carlstrom5cfee3f2011-05-31 01:00:15 -0700225 public boolean isEmpty() {
Kenny Root6b776452012-11-02 15:40:32 -0700226 try {
227 return mBinder.zero() == KEY_NOT_FOUND;
228 } catch (RemoteException e) {
229 Log.w(TAG, "Cannot connect to keystore", e);
230 return false;
231 }
Kenny Root5423e682011-11-14 08:43:13 -0800232 }
233
Kenny Roota3985982013-08-16 14:03:29 -0700234 public boolean generate(String key, int uid, int keyType, int keySize, int flags,
235 byte[][] args) {
Kenny Root6b776452012-11-02 15:40:32 -0700236 try {
Chad Brubaker7a2c9732015-01-13 17:41:22 -0800237 return mBinder.generate(key, uid, keyType, keySize, flags,
238 new KeystoreArguments(args)) == NO_ERROR;
Kenny Root78ad8492013-02-13 17:02:57 -0800239 } catch (RemoteException e) {
240 Log.w(TAG, "Cannot connect to keystore", e);
241 return false;
242 }
243 }
244
Kenny Roota3788b02013-04-10 10:37:55 -0700245 public boolean importKey(String keyName, byte[] key, int uid, int flags) {
Kenny Root78ad8492013-02-13 17:02:57 -0800246 try {
Kenny Roota3788b02013-04-10 10:37:55 -0700247 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700248 } catch (RemoteException e) {
249 Log.w(TAG, "Cannot connect to keystore", e);
250 return false;
251 }
Kenny Root5423e682011-11-14 08:43:13 -0800252 }
253
Kenny Root5423e682011-11-14 08:43:13 -0800254 public byte[] getPubkey(String key) {
Kenny Root6b776452012-11-02 15:40:32 -0700255 try {
256 return mBinder.get_pubkey(key);
257 } catch (RemoteException e) {
258 Log.w(TAG, "Cannot connect to keystore", e);
259 return null;
260 }
Kenny Root5423e682011-11-14 08:43:13 -0800261 }
262
Kenny Root78ad8492013-02-13 17:02:57 -0800263 public boolean delKey(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700264 try {
Kenny Root78ad8492013-02-13 17:02:57 -0800265 return mBinder.del_key(key, uid) == NO_ERROR;
Kenny Root6b776452012-11-02 15:40:32 -0700266 } catch (RemoteException e) {
267 Log.w(TAG, "Cannot connect to keystore", e);
268 return false;
269 }
Kenny Root5423e682011-11-14 08:43:13 -0800270 }
271
Kenny Root78ad8492013-02-13 17:02:57 -0800272 public boolean delKey(String key) {
Kenny Root2eeda722013-04-10 11:30:58 -0700273 return delKey(key, UID_SELF);
Kenny Root78ad8492013-02-13 17:02:57 -0800274 }
275
Kenny Root5423e682011-11-14 08:43:13 -0800276 public byte[] sign(String key, byte[] data) {
Kenny Root6b776452012-11-02 15:40:32 -0700277 try {
278 return mBinder.sign(key, data);
279 } catch (RemoteException e) {
280 Log.w(TAG, "Cannot connect to keystore", e);
281 return null;
282 }
Kenny Root5423e682011-11-14 08:43:13 -0800283 }
284
285 public boolean verify(String key, byte[] data, byte[] signature) {
Kenny Root6b776452012-11-02 15:40:32 -0700286 try {
287 return mBinder.verify(key, data, signature) == NO_ERROR;
288 } catch (RemoteException e) {
289 Log.w(TAG, "Cannot connect to keystore", e);
290 return false;
291 }
Kenny Root5423e682011-11-14 08:43:13 -0800292 }
293
294 public boolean grant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700295 try {
296 return mBinder.grant(key, uid) == NO_ERROR;
297 } catch (RemoteException e) {
298 Log.w(TAG, "Cannot connect to keystore", e);
299 return false;
300 }
Kenny Root5423e682011-11-14 08:43:13 -0800301 }
302
303 public boolean ungrant(String key, int uid) {
Kenny Root6b776452012-11-02 15:40:32 -0700304 try {
305 return mBinder.ungrant(key, uid) == NO_ERROR;
306 } catch (RemoteException e) {
307 Log.w(TAG, "Cannot connect to keystore", e);
308 return false;
Kenny Root473c7122012-08-17 21:13:48 -0700309 }
Kenny Root473c7122012-08-17 21:13:48 -0700310 }
311
312 /**
313 * Returns the last modification time of the key in milliseconds since the
314 * epoch. Will return -1L if the key could not be found or other error.
315 */
316 public long getmtime(String key) {
Kenny Root6b776452012-11-02 15:40:32 -0700317 try {
Kenny Roote66769a2013-02-04 15:49:11 -0800318 final long millis = mBinder.getmtime(key);
319 if (millis == -1L) {
320 return -1L;
321 }
322
323 return millis * 1000L;
Kenny Root6b776452012-11-02 15:40:32 -0700324 } catch (RemoteException e) {
325 Log.w(TAG, "Cannot connect to keystore", e);
326 return -1L;
327 }
Kenny Root473c7122012-08-17 21:13:48 -0700328 }
329
Kenny Root5f1d9652013-03-21 14:21:50 -0700330 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
Kenny Rootbd794192013-03-20 11:36:50 -0700331 try {
Kenny Root5f1d9652013-03-21 14:21:50 -0700332 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
Kenny Rootbd794192013-03-20 11:36:50 -0700333 } catch (RemoteException e) {
334 Log.w(TAG, "Cannot connect to keystore", e);
335 return false;
336 }
337 }
338
Kenny Rootb91773b2013-09-05 13:03:16 -0700339 // TODO remove this when it's removed from Settings
Kenny Root5cb5cec2013-03-29 11:14:17 -0700340 public boolean isHardwareBacked() {
Kenny Rootb91773b2013-09-05 13:03:16 -0700341 return isHardwareBacked("RSA");
342 }
343
344 public boolean isHardwareBacked(String keyType) {
Kenny Root5cb5cec2013-03-29 11:14:17 -0700345 try {
Kenny Rootb91773b2013-09-05 13:03:16 -0700346 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
Kenny Root5cb5cec2013-03-29 11:14:17 -0700347 } catch (RemoteException e) {
348 Log.w(TAG, "Cannot connect to keystore", e);
349 return false;
350 }
351 }
352
Kenny Rootd72317a2013-04-01 15:59:59 -0700353 public boolean clearUid(int uid) {
354 try {
355 return mBinder.clear_uid(uid) == NO_ERROR;
356 } catch (RemoteException e) {
357 Log.w(TAG, "Cannot connect to keystore", e);
358 return false;
359 }
360 }
361
Robin Leef0246a82014-08-13 09:50:25 +0100362 public boolean resetUid(int uid) {
363 try {
364 mError = mBinder.reset_uid(uid);
365 return mError == NO_ERROR;
366 } catch (RemoteException e) {
367 Log.w(TAG, "Cannot connect to keystore", e);
368 return false;
369 }
370 }
371
372 public boolean syncUid(int sourceUid, int targetUid) {
373 try {
374 mError = mBinder.sync_uid(sourceUid, targetUid);
375 return mError == NO_ERROR;
376 } catch (RemoteException e) {
377 Log.w(TAG, "Cannot connect to keystore", e);
378 return false;
379 }
380 }
381
382 public boolean passwordUid(String password, int uid) {
383 try {
384 mError = mBinder.password_uid(password, uid);
385 return mError == NO_ERROR;
386 } catch (RemoteException e) {
387 Log.w(TAG, "Cannot connect to keystore", e);
388 return false;
389 }
390 }
391
Chia-chi Yeh44039172009-09-21 11:53:59 +0800392 public int getLastError() {
393 return mError;
394 }
Chad Brubakere6a461342015-02-10 21:33:23 -0800395
396 public boolean addRngEntropy(byte[] data) {
397 try {
398 return mBinder.addRngEntropy(data) == NO_ERROR;
399 } catch (RemoteException e) {
400 Log.w(TAG, "Cannot connect to keystore", e);
401 return false;
402 }
403 }
404
Chad Brubakerdae79e52015-03-27 14:28:35 -0700405 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
406 int flags, KeyCharacteristics outCharacteristics) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800407 try {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700408 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800409 } catch (RemoteException e) {
410 Log.w(TAG, "Cannot connect to keystore", e);
411 return SYSTEM_ERROR;
412 }
413 }
414
Chad Brubakerdae79e52015-03-27 14:28:35 -0700415 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
Chad Brubakere6a461342015-02-10 21:33:23 -0800416 KeyCharacteristics outCharacteristics) {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700417 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
Chad Brubakere6a461342015-02-10 21:33:23 -0800418 }
419
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700420 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
Chad Brubakere6a461342015-02-10 21:33:23 -0800421 KeyCharacteristics outCharacteristics) {
422 try {
423 return mBinder.getKeyCharacteristics(alias, clientId, appId, outCharacteristics);
424 } catch (RemoteException e) {
425 Log.w(TAG, "Cannot connect to keystore", e);
426 return SYSTEM_ERROR;
427 }
428 }
429
430 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
431 int uid, int flags, KeyCharacteristics outCharacteristics) {
432 try {
433 return mBinder.importKey(alias, args, format, keyData, uid, flags,
434 outCharacteristics);
435 } catch (RemoteException e) {
436 Log.w(TAG, "Cannot connect to keystore", e);
437 return SYSTEM_ERROR;
438 }
439 }
440
441 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
442 int flags, KeyCharacteristics outCharacteristics) {
443 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
444 }
445
Chad Brubaker5e73c0e2015-03-21 22:46:43 -0700446 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
447 KeymasterBlob appId) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800448 try {
449 return mBinder.exportKey(alias, format, clientId, appId);
450 } catch (RemoteException e) {
451 Log.w(TAG, "Cannot connect to keystore", e);
452 return null;
453 }
454 }
455
456 public OperationResult begin(String alias, int purpose, boolean pruneable,
Chad Brubakerdae79e52015-03-27 14:28:35 -0700457 KeymasterArguments args, byte[] entropy, KeymasterArguments outArgs) {
Chad Brubakere6a461342015-02-10 21:33:23 -0800458 try {
Chad Brubakerdae79e52015-03-27 14:28:35 -0700459 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, outArgs);
Chad Brubakere6a461342015-02-10 21:33:23 -0800460 } catch (RemoteException e) {
461 Log.w(TAG, "Cannot connect to keystore", e);
462 return null;
463 }
464 }
465
466 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
467 try {
468 return mBinder.update(token, arguments, input);
469 } catch (RemoteException e) {
470 Log.w(TAG, "Cannot connect to keystore", e);
471 return null;
472 }
473 }
474
475 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
476 try {
477 return mBinder.finish(token, arguments, signature);
478 } catch (RemoteException e) {
479 Log.w(TAG, "Cannot connect to keystore", e);
480 return null;
481 }
482 }
483
484 public int abort(IBinder token) {
485 try {
486 return mBinder.abort(token);
487 } catch (RemoteException e) {
488 Log.w(TAG, "Cannot connect to keystore", e);
489 return SYSTEM_ERROR;
490 }
491 }
Chad Brubaker5654b362015-03-17 16:59:52 -0700492
493 /**
494 * Check if the operation referenced by {@code token} is currently authorized.
495 *
Alex Klyubin708fc9402015-04-28 18:58:47 -0700496 * @param token An operation token returned by a call to
497 * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
Chad Brubaker5654b362015-03-17 16:59:52 -0700498 */
499 public boolean isOperationAuthorized(IBinder token) {
500 try {
501 return mBinder.isOperationAuthorized(token);
502 } catch (RemoteException e) {
503 Log.w(TAG, "Cannot connect to keystore", e);
504 return false;
505 }
506 }
507
508 /**
509 * Add an authentication record to the keystore authorization table.
510 *
511 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
512 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
513 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
514 */
515 public int addAuthToken(byte[] authToken) {
516 try {
517 return mBinder.addAuthToken(authToken);
518 } catch (RemoteException e) {
519 Log.w(TAG, "Cannot connect to keystore", e);
520 return SYSTEM_ERROR;
521 }
522 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700523
Alex Klyubinad9ba102015-04-21 15:17:24 -0700524 /**
525 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
526 * code.
527 */
528 static KeyStoreException getKeyStoreException(int errorCode) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700529 if (errorCode > 0) {
530 // KeyStore layer error
531 switch (errorCode) {
532 case NO_ERROR:
533 return new KeyStoreException(errorCode, "OK");
534 case LOCKED:
535 return new KeyStoreException(errorCode, "Keystore locked");
536 case UNINITIALIZED:
537 return new KeyStoreException(errorCode, "Keystore not initialized");
538 case SYSTEM_ERROR:
539 return new KeyStoreException(errorCode, "System error");
540 case PERMISSION_DENIED:
541 return new KeyStoreException(errorCode, "Permission denied");
542 case KEY_NOT_FOUND:
543 return new KeyStoreException(errorCode, "Key not found");
544 case VALUE_CORRUPTED:
545 return new KeyStoreException(errorCode, "Key blob corrupted");
546 default:
547 return new KeyStoreException(errorCode, String.valueOf(errorCode));
548 }
549 } else {
550 // Keymaster layer error
551 switch (errorCode) {
552 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
553 // The name of this parameter significantly differs between Keymaster and
554 // framework APIs. Use the framework wording to make life easier for developers.
555 return new KeyStoreException(errorCode,
556 "Invalid user authentication validity duration");
557 default:
558 return new KeyStoreException(errorCode,
559 KeymasterDefs.getErrorMessage(errorCode));
560 }
561 }
562 }
563
Alex Klyubinad9ba102015-04-21 15:17:24 -0700564 /**
565 * Returns an {@link InvalidKeyException} corresponding to the provided
566 * {@link KeyStoreException}.
567 */
Alex Klyubin708fc9402015-04-28 18:58:47 -0700568 InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, KeyStoreException e) {
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700569 switch (e.getErrorCode()) {
570 case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
571 return new KeyExpiredException();
572 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
573 return new KeyNotYetValidException();
574 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
Alex Klyubin708fc9402015-04-28 18:58:47 -0700575 {
576 // We now need to determine whether the key/operation can become usable if user
577 // authentication is performed, or whether it can never become usable again.
578 // User authentication requirements are contained in the key's characteristics. We
579 // need to check whether these requirements can be be satisfied by asking the user
580 // to authenticate.
581 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
582 int getKeyCharacteristicsErrorCode =
583 getKeyCharacteristics(keystoreKeyAlias, null, null, keyCharacteristics);
584 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
585 return new InvalidKeyException(
586 "Failed to obtained key characteristics",
587 getKeyStoreException(getKeyCharacteristicsErrorCode));
588 }
589 List<Long> keySids =
590 keyCharacteristics.getLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
591 if (keySids.isEmpty()) {
592 // Key is not bound to any SIDs -- no amount of authentication will help here.
593 return new KeyPermanentlyInvalidatedException();
594 }
595 long rootSid = GateKeeper.getSecureUserId();
596 if ((rootSid != 0) && (keySids.contains(Long.valueOf(rootSid)))) {
597 // One of the key's SIDs is the current root SID -- user can be authenticated
598 // against that SID.
599 return new UserNotAuthenticatedException();
600 }
601
602 long fingerprintOnlySid = getFingerprintOnlySid();
603 if ((fingerprintOnlySid != 0)
604 && (keySids.contains(Long.valueOf(fingerprintOnlySid)))) {
605 // One of the key's SIDs is the current fingerprint SID -- user can be
606 // authenticated against that SID.
607 return new UserNotAuthenticatedException();
608 }
609
610 // None of the key's SIDs can ever be authenticated
611 return new KeyPermanentlyInvalidatedException();
612 }
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700613 default:
Alex Klyubinad9ba102015-04-21 15:17:24 -0700614 return new InvalidKeyException("Keystore operation failed", e);
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700615 }
616 }
617
Alex Klyubin708fc9402015-04-28 18:58:47 -0700618 private static long getFingerprintOnlySid() {
619 IFingerprintService service = IFingerprintService.Stub.asInterface(
620 ServiceManager.getService(Context.FINGERPRINT_SERVICE));
621 if (service == null) {
622 return 0;
623 }
624
625 try {
626 long deviceId = 0; // TODO: plumb hardware id to FPMS
627 if (!service.isHardwareDetected(deviceId)) {
628 return 0;
629 }
630
631 return service.getAuthenticatorId();
632 } catch (RemoteException e) {
633 throw new IllegalStateException("Failed to communicate with fingerprint service", e);
634 }
635 }
636
Alex Klyubinad9ba102015-04-21 15:17:24 -0700637 /**
638 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
639 * code.
640 */
Alex Klyubin708fc9402015-04-28 18:58:47 -0700641 InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int errorCode) {
642 return getInvalidKeyException(keystoreKeyAlias, getKeyStoreException(errorCode));
Alex Klyubinb4834ae2015-04-02 15:53:46 -0700643 }
Chia-chi Yeh44039172009-09-21 11:53:59 +0800644}