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