1 /* 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 17 package android.security; 18 19 import android.app.ActivityThread; 20 import android.app.Application; 21 import android.app.KeyguardManager; 22 23 import android.content.Context; 24 import android.hardware.fingerprint.FingerprintManager; 25 import android.os.Binder; 26 import android.os.IBinder; 27 import android.os.Process; 28 import android.os.RemoteException; 29 import android.os.ServiceManager; 30 import android.os.UserHandle; 31 import android.security.keymaster.ExportResult; 32 import android.security.keymaster.KeyCharacteristics; 33 import android.security.keymaster.KeymasterArguments; 34 import android.security.keymaster.KeymasterBlob; 35 import android.security.keymaster.KeymasterDefs; 36 import android.security.keymaster.OperationResult; 37 import android.security.keystore.KeyExpiredException; 38 import android.security.keystore.KeyNotYetValidException; 39 import android.security.keystore.KeyPermanentlyInvalidatedException; 40 import android.security.keystore.UserNotAuthenticatedException; 41 import android.util.Log; 42 43 import java.math.BigInteger; 44 import java.security.InvalidKeyException; 45 import java.util.List; 46 import java.util.Locale; 47 48 /** 49 * @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. 52 */ 53 public class KeyStore { 54 private static final String TAG = "KeyStore"; 55 56 // ResponseCodes 57 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; 67 68 /** 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 76 // 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; 81 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 */ 94 public static final int FLAG_ENCRYPTED = 1; 95 96 // States 97 public enum State { UNLOCKED, LOCKED, UNINITIALIZED }; 98 99 private int mError = NO_ERROR; 100 101 private final IKeystoreService mBinder; 102 private final Context mContext; 103 104 private IBinder mToken; 105 KeyStore(IKeystoreService binder)106 private KeyStore(IKeystoreService binder) { 107 mBinder = binder; 108 mContext = getApplicationContext(); 109 } 110 getApplicationContext()111 public static Context getApplicationContext() { 112 Application application = ActivityThread.currentApplication(); 113 if (application == null) { 114 throw new IllegalStateException( 115 "Failed to obtain application Context from ActivityThread"); 116 } 117 return application; 118 } 119 getInstance()120 public static KeyStore getInstance() { 121 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager 122 .getService("android.security.keystore")); 123 return new KeyStore(keystore); 124 } 125 getToken()126 private synchronized IBinder getToken() { 127 if (mToken == null) { 128 mToken = new Binder(); 129 } 130 return mToken; 131 } 132 state(int userId)133 public State state(int userId) { 134 final int ret; 135 try { 136 ret = mBinder.getState(userId); 137 } catch (RemoteException e) { 138 Log.w(TAG, "Cannot connect to keystore", e); 139 throw new AssertionError(e); 140 } 141 142 switch (ret) { 143 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 } 148 } 149 state()150 public State state() { 151 return state(UserHandle.myUserId()); 152 } 153 isUnlocked()154 public boolean isUnlocked() { 155 return state() == State.UNLOCKED; 156 } 157 get(String key)158 public byte[] get(String key) { 159 try { 160 return mBinder.get(key); 161 } catch (RemoteException e) { 162 Log.w(TAG, "Cannot connect to keystore", e); 163 return null; 164 } 165 } 166 put(String key, byte[] value, int uid, int flags)167 public boolean put(String key, byte[] value, int uid, int flags) { 168 return insert(key, value, uid, flags) == NO_ERROR; 169 } 170 insert(String key, byte[] value, int uid, int flags)171 public int insert(String key, byte[] value, int uid, int flags) { 172 try { 173 return mBinder.insert(key, value, uid, flags); 174 } catch (RemoteException e) { 175 Log.w(TAG, "Cannot connect to keystore", e); 176 return SYSTEM_ERROR; 177 } 178 } 179 delete(String key, int uid)180 public boolean delete(String key, int uid) { 181 try { 182 return mBinder.del(key, uid) == NO_ERROR; 183 } catch (RemoteException e) { 184 Log.w(TAG, "Cannot connect to keystore", e); 185 return false; 186 } 187 } 188 delete(String key)189 public boolean delete(String key) { 190 return delete(key, UID_SELF); 191 } 192 contains(String key, int uid)193 public boolean contains(String key, int uid) { 194 try { 195 return mBinder.exist(key, uid) == NO_ERROR; 196 } catch (RemoteException e) { 197 Log.w(TAG, "Cannot connect to keystore", e); 198 return false; 199 } 200 } 201 contains(String key)202 public boolean contains(String key) { 203 return contains(key, UID_SELF); 204 } 205 206 /** 207 * List all entries in the keystore for {@code uid} starting with {@code prefix}. 208 */ list(String prefix, int uid)209 public String[] list(String prefix, int uid) { 210 try { 211 return mBinder.list(prefix, uid); 212 } catch (RemoteException e) { 213 Log.w(TAG, "Cannot connect to keystore", e); 214 return null; 215 } 216 } 217 list(String prefix)218 public String[] list(String prefix) { 219 return list(prefix, UID_SELF); 220 } 221 reset()222 public boolean reset() { 223 try { 224 return mBinder.reset() == NO_ERROR; 225 } catch (RemoteException e) { 226 Log.w(TAG, "Cannot connect to keystore", e); 227 return false; 228 } 229 } 230 231 /** 232 * Attempt to lock the keystore for {@code user}. 233 * 234 * @param user Android user to lock. 235 * @return whether {@code user}'s keystore was locked. 236 */ lock(int userId)237 public boolean lock(int userId) { 238 try { 239 return mBinder.lock(userId) == NO_ERROR; 240 } catch (RemoteException e) { 241 Log.w(TAG, "Cannot connect to keystore", e); 242 return false; 243 } 244 } 245 lock()246 public boolean lock() { 247 return lock(UserHandle.myUserId()); 248 } 249 250 /** 251 * Attempt to unlock the keystore for {@code user} with the password {@code password}. 252 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or 253 * created. 254 * 255 * @param user Android user ID to operate on 256 * @param password user's keystore password. Should be the most recent value passed to 257 * {@link #onUserPasswordChanged} for the user. 258 * 259 * @return whether the keystore was unlocked. 260 */ unlock(int userId, String password)261 public boolean unlock(int userId, String password) { 262 try { 263 mError = mBinder.unlock(userId, password); 264 return mError == NO_ERROR; 265 } catch (RemoteException e) { 266 Log.w(TAG, "Cannot connect to keystore", e); 267 return false; 268 } 269 } 270 unlock(String password)271 public boolean unlock(String password) { 272 return unlock(UserHandle.getUserId(Process.myUid()), password); 273 } 274 275 /** 276 * Check if the keystore for {@code userId} is empty. 277 */ isEmpty(int userId)278 public boolean isEmpty(int userId) { 279 try { 280 return mBinder.isEmpty(userId) != 0; 281 } catch (RemoteException e) { 282 Log.w(TAG, "Cannot connect to keystore", e); 283 return false; 284 } 285 } 286 isEmpty()287 public boolean isEmpty() { 288 return isEmpty(UserHandle.myUserId()); 289 } 290 generate(String key, int uid, int keyType, int keySize, int flags, byte[][] args)291 public boolean generate(String key, int uid, int keyType, int keySize, int flags, 292 byte[][] args) { 293 try { 294 return mBinder.generate(key, uid, keyType, keySize, flags, 295 new KeystoreArguments(args)) == NO_ERROR; 296 } catch (RemoteException e) { 297 Log.w(TAG, "Cannot connect to keystore", e); 298 return false; 299 } 300 } 301 importKey(String keyName, byte[] key, int uid, int flags)302 public boolean importKey(String keyName, byte[] key, int uid, int flags) { 303 try { 304 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR; 305 } catch (RemoteException e) { 306 Log.w(TAG, "Cannot connect to keystore", e); 307 return false; 308 } 309 } 310 sign(String key, byte[] data)311 public byte[] sign(String key, byte[] data) { 312 try { 313 return mBinder.sign(key, data); 314 } catch (RemoteException e) { 315 Log.w(TAG, "Cannot connect to keystore", e); 316 return null; 317 } 318 } 319 verify(String key, byte[] data, byte[] signature)320 public boolean verify(String key, byte[] data, byte[] signature) { 321 try { 322 return mBinder.verify(key, data, signature) == NO_ERROR; 323 } catch (RemoteException e) { 324 Log.w(TAG, "Cannot connect to keystore", e); 325 return false; 326 } 327 } 328 grant(String key, int uid)329 public boolean grant(String key, int uid) { 330 try { 331 return mBinder.grant(key, uid) == NO_ERROR; 332 } catch (RemoteException e) { 333 Log.w(TAG, "Cannot connect to keystore", e); 334 return false; 335 } 336 } 337 ungrant(String key, int uid)338 public boolean ungrant(String key, int uid) { 339 try { 340 return mBinder.ungrant(key, uid) == NO_ERROR; 341 } catch (RemoteException e) { 342 Log.w(TAG, "Cannot connect to keystore", e); 343 return false; 344 } 345 } 346 347 /** 348 * Returns the last modification time of the key in milliseconds since the 349 * epoch. Will return -1L if the key could not be found or other error. 350 */ getmtime(String key)351 public long getmtime(String key) { 352 try { 353 final long millis = mBinder.getmtime(key); 354 if (millis == -1L) { 355 return -1L; 356 } 357 358 return millis * 1000L; 359 } catch (RemoteException e) { 360 Log.w(TAG, "Cannot connect to keystore", e); 361 return -1L; 362 } 363 } 364 duplicate(String srcKey, int srcUid, String destKey, int destUid)365 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) { 366 try { 367 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR; 368 } catch (RemoteException e) { 369 Log.w(TAG, "Cannot connect to keystore", e); 370 return false; 371 } 372 } 373 374 // TODO: remove this when it's removed from Settings isHardwareBacked()375 public boolean isHardwareBacked() { 376 return isHardwareBacked("RSA"); 377 } 378 isHardwareBacked(String keyType)379 public boolean isHardwareBacked(String keyType) { 380 try { 381 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR; 382 } catch (RemoteException e) { 383 Log.w(TAG, "Cannot connect to keystore", e); 384 return false; 385 } 386 } 387 clearUid(int uid)388 public boolean clearUid(int uid) { 389 try { 390 return mBinder.clear_uid(uid) == NO_ERROR; 391 } catch (RemoteException e) { 392 Log.w(TAG, "Cannot connect to keystore", e); 393 return false; 394 } 395 } 396 getLastError()397 public int getLastError() { 398 return mError; 399 } 400 addRngEntropy(byte[] data)401 public boolean addRngEntropy(byte[] data) { 402 try { 403 return mBinder.addRngEntropy(data) == NO_ERROR; 404 } catch (RemoteException e) { 405 Log.w(TAG, "Cannot connect to keystore", e); 406 return false; 407 } 408 } 409 generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid, int flags, KeyCharacteristics outCharacteristics)410 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid, 411 int flags, KeyCharacteristics outCharacteristics) { 412 try { 413 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics); 414 } catch (RemoteException e) { 415 Log.w(TAG, "Cannot connect to keystore", e); 416 return SYSTEM_ERROR; 417 } 418 } 419 generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags, KeyCharacteristics outCharacteristics)420 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags, 421 KeyCharacteristics outCharacteristics) { 422 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics); 423 } 424 getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, KeyCharacteristics outCharacteristics)425 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, 426 KeyCharacteristics outCharacteristics) { 427 try { 428 return mBinder.getKeyCharacteristics(alias, clientId, appId, outCharacteristics); 429 } catch (RemoteException e) { 430 Log.w(TAG, "Cannot connect to keystore", e); 431 return SYSTEM_ERROR; 432 } 433 } 434 importKey(String alias, KeymasterArguments args, int format, byte[] keyData, int uid, int flags, KeyCharacteristics outCharacteristics)435 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 436 int uid, int flags, KeyCharacteristics outCharacteristics) { 437 try { 438 return mBinder.importKey(alias, args, format, keyData, uid, flags, 439 outCharacteristics); 440 } catch (RemoteException e) { 441 Log.w(TAG, "Cannot connect to keystore", e); 442 return SYSTEM_ERROR; 443 } 444 } 445 importKey(String alias, KeymasterArguments args, int format, byte[] keyData, int flags, KeyCharacteristics outCharacteristics)446 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 447 int flags, KeyCharacteristics outCharacteristics) { 448 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics); 449 } 450 exportKey(String alias, int format, KeymasterBlob clientId, KeymasterBlob appId)451 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId, 452 KeymasterBlob appId) { 453 try { 454 return mBinder.exportKey(alias, format, clientId, appId); 455 } catch (RemoteException e) { 456 Log.w(TAG, "Cannot connect to keystore", e); 457 return null; 458 } 459 } 460 begin(String alias, int purpose, boolean pruneable, KeymasterArguments args, byte[] entropy)461 public OperationResult begin(String alias, int purpose, boolean pruneable, 462 KeymasterArguments args, byte[] entropy) { 463 try { 464 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy); 465 } catch (RemoteException e) { 466 Log.w(TAG, "Cannot connect to keystore", e); 467 return null; 468 } 469 } 470 update(IBinder token, KeymasterArguments arguments, byte[] input)471 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) { 472 try { 473 return mBinder.update(token, arguments, input); 474 } catch (RemoteException e) { 475 Log.w(TAG, "Cannot connect to keystore", e); 476 return null; 477 } 478 } 479 finish(IBinder token, KeymasterArguments arguments, byte[] signature, byte[] entropy)480 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature, 481 byte[] entropy) { 482 try { 483 return mBinder.finish(token, arguments, signature, entropy); 484 } catch (RemoteException e) { 485 Log.w(TAG, "Cannot connect to keystore", e); 486 return null; 487 } 488 } 489 finish(IBinder token, KeymasterArguments arguments, byte[] signature)490 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) { 491 return finish(token, arguments, signature, null); 492 } 493 abort(IBinder token)494 public int abort(IBinder token) { 495 try { 496 return mBinder.abort(token); 497 } catch (RemoteException e) { 498 Log.w(TAG, "Cannot connect to keystore", e); 499 return SYSTEM_ERROR; 500 } 501 } 502 503 /** 504 * Check if the operation referenced by {@code token} is currently authorized. 505 * 506 * @param token An operation token returned by a call to 507 * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}. 508 */ isOperationAuthorized(IBinder token)509 public boolean isOperationAuthorized(IBinder token) { 510 try { 511 return mBinder.isOperationAuthorized(token); 512 } catch (RemoteException e) { 513 Log.w(TAG, "Cannot connect to keystore", e); 514 return false; 515 } 516 } 517 518 /** 519 * Add an authentication record to the keystore authorization table. 520 * 521 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster. 522 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to 523 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode. 524 */ addAuthToken(byte[] authToken)525 public int addAuthToken(byte[] authToken) { 526 try { 527 return mBinder.addAuthToken(authToken); 528 } catch (RemoteException e) { 529 Log.w(TAG, "Cannot connect to keystore", e); 530 return SYSTEM_ERROR; 531 } 532 } 533 534 /** 535 * Notify keystore that a user's password has changed. 536 * 537 * @param userId the user whose password changed. 538 * @param newPassword the new password or "" if the password was removed. 539 */ onUserPasswordChanged(int userId, String newPassword)540 public boolean onUserPasswordChanged(int userId, String newPassword) { 541 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that 542 // explicit here. 543 if (newPassword == null) { 544 newPassword = ""; 545 } 546 try { 547 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR; 548 } catch (RemoteException e) { 549 Log.w(TAG, "Cannot connect to keystore", e); 550 return false; 551 } 552 } 553 554 /** 555 * Notify keystore that a user was added. 556 * 557 * @param userId the new user. 558 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is 559 * specified then the new user's keystore will be intialized with the same secure lockscreen 560 * password as the parent. 561 */ onUserAdded(int userId, int parentId)562 public void onUserAdded(int userId, int parentId) { 563 try { 564 mBinder.onUserAdded(userId, parentId); 565 } catch (RemoteException e) { 566 Log.w(TAG, "Cannot connect to keystore", e); 567 } 568 } 569 570 /** 571 * Notify keystore that a user was added. 572 * 573 * @param userId the new user. 574 */ onUserAdded(int userId)575 public void onUserAdded(int userId) { 576 onUserAdded(userId, -1); 577 } 578 579 /** 580 * Notify keystore that a user was removed. 581 * 582 * @param userId the removed user. 583 */ onUserRemoved(int userId)584 public void onUserRemoved(int userId) { 585 try { 586 mBinder.onUserRemoved(userId); 587 } catch (RemoteException e) { 588 Log.w(TAG, "Cannot connect to keystore", e); 589 } 590 } 591 onUserPasswordChanged(String newPassword)592 public boolean onUserPasswordChanged(String newPassword) { 593 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword); 594 } 595 596 /** 597 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error 598 * code. 599 */ getKeyStoreException(int errorCode)600 public static KeyStoreException getKeyStoreException(int errorCode) { 601 if (errorCode > 0) { 602 // KeyStore layer error 603 switch (errorCode) { 604 case NO_ERROR: 605 return new KeyStoreException(errorCode, "OK"); 606 case LOCKED: 607 return new KeyStoreException(errorCode, "User authentication required"); 608 case UNINITIALIZED: 609 return new KeyStoreException(errorCode, "Keystore not initialized"); 610 case SYSTEM_ERROR: 611 return new KeyStoreException(errorCode, "System error"); 612 case PERMISSION_DENIED: 613 return new KeyStoreException(errorCode, "Permission denied"); 614 case KEY_NOT_FOUND: 615 return new KeyStoreException(errorCode, "Key not found"); 616 case VALUE_CORRUPTED: 617 return new KeyStoreException(errorCode, "Key blob corrupted"); 618 case OP_AUTH_NEEDED: 619 return new KeyStoreException(errorCode, "Operation requires authorization"); 620 default: 621 return new KeyStoreException(errorCode, String.valueOf(errorCode)); 622 } 623 } else { 624 // Keymaster layer error 625 switch (errorCode) { 626 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT: 627 // The name of this parameter significantly differs between Keymaster and 628 // framework APIs. Use the framework wording to make life easier for developers. 629 return new KeyStoreException(errorCode, 630 "Invalid user authentication validity duration"); 631 default: 632 return new KeyStoreException(errorCode, 633 KeymasterDefs.getErrorMessage(errorCode)); 634 } 635 } 636 } 637 638 /** 639 * Returns an {@link InvalidKeyException} corresponding to the provided 640 * {@link KeyStoreException}. 641 */ getInvalidKeyException( String keystoreKeyAlias, KeyStoreException e)642 public InvalidKeyException getInvalidKeyException( 643 String keystoreKeyAlias, KeyStoreException e) { 644 switch (e.getErrorCode()) { 645 case LOCKED: 646 return new UserNotAuthenticatedException(); 647 case KeymasterDefs.KM_ERROR_KEY_EXPIRED: 648 return new KeyExpiredException(); 649 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: 650 return new KeyNotYetValidException(); 651 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: 652 case OP_AUTH_NEEDED: 653 { 654 // We now need to determine whether the key/operation can become usable if user 655 // authentication is performed, or whether it can never become usable again. 656 // User authentication requirements are contained in the key's characteristics. We 657 // need to check whether these requirements can be be satisfied by asking the user 658 // to authenticate. 659 KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); 660 int getKeyCharacteristicsErrorCode = 661 getKeyCharacteristics(keystoreKeyAlias, null, null, keyCharacteristics); 662 if (getKeyCharacteristicsErrorCode != NO_ERROR) { 663 return new InvalidKeyException( 664 "Failed to obtained key characteristics", 665 getKeyStoreException(getKeyCharacteristicsErrorCode)); 666 } 667 List<BigInteger> keySids = 668 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID); 669 if (keySids.isEmpty()) { 670 // Key is not bound to any SIDs -- no amount of authentication will help here. 671 return new KeyPermanentlyInvalidatedException(); 672 } 673 long rootSid = GateKeeper.getSecureUserId(); 674 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) { 675 // One of the key's SIDs is the current root SID -- user can be authenticated 676 // against that SID. 677 return new UserNotAuthenticatedException(); 678 } 679 680 long fingerprintOnlySid = getFingerprintOnlySid(); 681 if ((fingerprintOnlySid != 0) 682 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) { 683 // One of the key's SIDs is the current fingerprint SID -- user can be 684 // authenticated against that SID. 685 return new UserNotAuthenticatedException(); 686 } 687 688 // None of the key's SIDs can ever be authenticated 689 return new KeyPermanentlyInvalidatedException(); 690 } 691 default: 692 return new InvalidKeyException("Keystore operation failed", e); 693 } 694 } 695 getFingerprintOnlySid()696 private long getFingerprintOnlySid() { 697 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class); 698 if (fingerprintManager == null) { 699 return 0; 700 } 701 702 // TODO: Restore USE_FINGERPRINT permission check in 703 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here. 704 return fingerprintManager.getAuthenticatorId(); 705 } 706 707 /** 708 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error 709 * code. 710 */ getInvalidKeyException(String keystoreKeyAlias, int errorCode)711 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int errorCode) { 712 return getInvalidKeyException(keystoreKeyAlias, getKeyStoreException(errorCode)); 713 } 714 } 715