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.ActivityManager; 20 import android.app.ActivityThread; 21 import android.app.Application; 22 import android.app.KeyguardManager; 23 import android.content.Context; 24 import android.content.pm.PackageManager; 25 import android.hardware.fingerprint.FingerprintManager; 26 import android.os.Binder; 27 import android.os.IBinder; 28 import android.os.Process; 29 import android.os.RemoteException; 30 import android.os.ServiceManager; 31 import android.os.UserHandle; 32 import android.security.keymaster.ExportResult; 33 import android.security.keymaster.KeyCharacteristics; 34 import android.security.keymaster.KeymasterArguments; 35 import android.security.keymaster.KeymasterBlob; 36 import android.security.keymaster.KeymasterCertificateChain; 37 import android.security.keymaster.KeymasterDefs; 38 import android.security.keymaster.OperationResult; 39 import android.security.keystore.KeyExpiredException; 40 import android.security.keystore.KeyNotYetValidException; 41 import android.security.keystore.KeyPermanentlyInvalidatedException; 42 import android.security.keystore.StrongBoxUnavailableException; 43 import android.security.keystore.UserNotAuthenticatedException; 44 import android.util.Log; 45 46 import java.math.BigInteger; 47 import java.security.InvalidKeyException; 48 import java.util.List; 49 import java.util.Locale; 50 51 /** 52 * @hide This should not be made public in its present form because it 53 * assumes that private and secret key bytes are available and would 54 * preclude the use of hardware crypto. 55 */ 56 public class KeyStore { 57 private static final String TAG = "KeyStore"; 58 59 // ResponseCodes - see system/security/keystore/include/keystore/keystore.h 60 public static final int NO_ERROR = 1; 61 public static final int LOCKED = 2; 62 public static final int UNINITIALIZED = 3; 63 public static final int SYSTEM_ERROR = 4; 64 public static final int PROTOCOL_ERROR = 5; 65 public static final int PERMISSION_DENIED = 6; 66 public static final int KEY_NOT_FOUND = 7; 67 public static final int VALUE_CORRUPTED = 8; 68 public static final int UNDEFINED_ACTION = 9; 69 public static final int WRONG_PASSWORD = 10; 70 public static final int CANNOT_ATTEST_IDS = -66; 71 public static final int HARDWARE_TYPE_UNAVAILABLE = -68; 72 73 /** 74 * Per operation authentication is needed before this operation is valid. 75 * This is returned from {@link #begin} when begin succeeds but the operation uses 76 * per-operation authentication and must authenticate before calling {@link #update} or 77 * {@link #finish}. 78 */ 79 public static final int OP_AUTH_NEEDED = 15; 80 81 // Used for UID field to indicate the calling UID. 82 public static final int UID_SELF = -1; 83 84 // Flags for "put" "import" and "generate" 85 public static final int FLAG_NONE = 0; 86 87 /** 88 * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key 89 * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern). 90 * 91 * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set 92 * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key 93 * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or 94 * a Device Administrator). Finally, this key (or key pair) cannot be used until the user 95 * unlocks the secure lock screen after boot. 96 * 97 * @see KeyguardManager#isDeviceSecure() 98 */ 99 public static final int FLAG_ENCRYPTED = 1; 100 101 /** 102 * Select Software keymaster device, which as of this writing is the lowest security 103 * level available on an android device. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided 104 * A TEE based keymaster implementation is implied. 105 * 106 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h 107 * For historical reasons this corresponds to the KEYSTORE_FLAG_FALLBACK flag. 108 */ 109 public static final int FLAG_SOFTWARE = 1 << 1; 110 111 /** 112 * A private flag that's only available to system server to indicate that this key is part of 113 * device encryption flow so it receives special treatment from keystore. For example this key 114 * will not be super encrypted, and it will be stored separately under an unique UID instead 115 * of the caller UID i.e. SYSTEM. 116 * 117 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h 118 */ 119 public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3; 120 121 /** 122 * Select Strongbox keymaster device, which as of this writing the the highest security level 123 * available an android devices. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided 124 * A TEE based keymaster implementation is implied. 125 * 126 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h 127 */ 128 public static final int FLAG_STRONGBOX = 1 << 4; 129 130 // States 131 public enum State { UNLOCKED, LOCKED, UNINITIALIZED }; 132 133 private int mError = NO_ERROR; 134 135 private final IKeystoreService mBinder; 136 private final Context mContext; 137 138 private IBinder mToken; 139 KeyStore(IKeystoreService binder)140 private KeyStore(IKeystoreService binder) { 141 mBinder = binder; 142 mContext = getApplicationContext(); 143 } 144 getApplicationContext()145 public static Context getApplicationContext() { 146 Application application = ActivityThread.currentApplication(); 147 if (application == null) { 148 throw new IllegalStateException( 149 "Failed to obtain application Context from ActivityThread"); 150 } 151 return application; 152 } 153 getInstance()154 public static KeyStore getInstance() { 155 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager 156 .getService("android.security.keystore")); 157 return new KeyStore(keystore); 158 } 159 getToken()160 private synchronized IBinder getToken() { 161 if (mToken == null) { 162 mToken = new Binder(); 163 } 164 return mToken; 165 } 166 state(int userId)167 public State state(int userId) { 168 final int ret; 169 try { 170 ret = mBinder.getState(userId); 171 } catch (RemoteException e) { 172 Log.w(TAG, "Cannot connect to keystore", e); 173 throw new AssertionError(e); 174 } 175 176 switch (ret) { 177 case NO_ERROR: return State.UNLOCKED; 178 case LOCKED: return State.LOCKED; 179 case UNINITIALIZED: return State.UNINITIALIZED; 180 default: throw new AssertionError(mError); 181 } 182 } 183 state()184 public State state() { 185 return state(UserHandle.myUserId()); 186 } 187 isUnlocked()188 public boolean isUnlocked() { 189 return state() == State.UNLOCKED; 190 } 191 get(String key, int uid)192 public byte[] get(String key, int uid) { 193 try { 194 key = key != null ? key : ""; 195 return mBinder.get(key, uid); 196 } catch (RemoteException e) { 197 Log.w(TAG, "Cannot connect to keystore", e); 198 return null; 199 } catch (android.os.ServiceSpecificException e) { 200 Log.w(TAG, "KeyStore exception", e); 201 return null; 202 } 203 } 204 get(String key)205 public byte[] get(String key) { 206 return get(key, UID_SELF); 207 } 208 put(String key, byte[] value, int uid, int flags)209 public boolean put(String key, byte[] value, int uid, int flags) { 210 return insert(key, value, uid, flags) == NO_ERROR; 211 } 212 insert(String key, byte[] value, int uid, int flags)213 public int insert(String key, byte[] value, int uid, int flags) { 214 try { 215 if (value == null) { 216 value = new byte[0]; 217 } 218 return mBinder.insert(key, value, uid, flags); 219 } catch (RemoteException e) { 220 Log.w(TAG, "Cannot connect to keystore", e); 221 return SYSTEM_ERROR; 222 } 223 } 224 delete(String key, int uid)225 public boolean delete(String key, int uid) { 226 try { 227 int ret = mBinder.del(key, uid); 228 return (ret == NO_ERROR || ret == KEY_NOT_FOUND); 229 } catch (RemoteException e) { 230 Log.w(TAG, "Cannot connect to keystore", e); 231 return false; 232 } 233 } 234 delete(String key)235 public boolean delete(String key) { 236 return delete(key, UID_SELF); 237 } 238 contains(String key, int uid)239 public boolean contains(String key, int uid) { 240 try { 241 return mBinder.exist(key, uid) == NO_ERROR; 242 } catch (RemoteException e) { 243 Log.w(TAG, "Cannot connect to keystore", e); 244 return false; 245 } 246 } 247 contains(String key)248 public boolean contains(String key) { 249 return contains(key, UID_SELF); 250 } 251 252 /** 253 * List all entries in the keystore for {@code uid} starting with {@code prefix}. 254 */ list(String prefix, int uid)255 public String[] list(String prefix, int uid) { 256 try { 257 return mBinder.list(prefix, uid); 258 } catch (RemoteException e) { 259 Log.w(TAG, "Cannot connect to keystore", e); 260 return null; 261 } catch (android.os.ServiceSpecificException e) { 262 Log.w(TAG, "KeyStore exception", e); 263 return null; 264 } 265 } 266 list(String prefix)267 public String[] list(String prefix) { 268 return list(prefix, UID_SELF); 269 } 270 reset()271 public boolean reset() { 272 try { 273 return mBinder.reset() == NO_ERROR; 274 } catch (RemoteException e) { 275 Log.w(TAG, "Cannot connect to keystore", e); 276 return false; 277 } 278 } 279 280 /** 281 * Attempt to lock the keystore for {@code user}. 282 * 283 * @param userId Android user to lock. 284 * @return whether {@code user}'s keystore was locked. 285 */ lock(int userId)286 public boolean lock(int userId) { 287 try { 288 return mBinder.lock(userId) == NO_ERROR; 289 } catch (RemoteException e) { 290 Log.w(TAG, "Cannot connect to keystore", e); 291 return false; 292 } 293 } 294 lock()295 public boolean lock() { 296 return lock(UserHandle.myUserId()); 297 } 298 299 /** 300 * Attempt to unlock the keystore for {@code user} with the password {@code password}. 301 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or 302 * created. 303 * 304 * @param userId Android user ID to operate on 305 * @param password user's keystore password. Should be the most recent value passed to 306 * {@link #onUserPasswordChanged} for the user. 307 * 308 * @return whether the keystore was unlocked. 309 */ unlock(int userId, String password)310 public boolean unlock(int userId, String password) { 311 try { 312 password = password != null ? password : ""; 313 mError = mBinder.unlock(userId, password); 314 return mError == NO_ERROR; 315 } catch (RemoteException e) { 316 Log.w(TAG, "Cannot connect to keystore", e); 317 return false; 318 } 319 } 320 unlock(String password)321 public boolean unlock(String password) { 322 return unlock(UserHandle.getUserId(Process.myUid()), password); 323 } 324 325 /** 326 * Check if the keystore for {@code userId} is empty. 327 */ isEmpty(int userId)328 public boolean isEmpty(int userId) { 329 try { 330 return mBinder.isEmpty(userId) != 0; 331 } catch (RemoteException e) { 332 Log.w(TAG, "Cannot connect to keystore", e); 333 return false; 334 } 335 } 336 isEmpty()337 public boolean isEmpty() { 338 return isEmpty(UserHandle.myUserId()); 339 } 340 generate(String key, int uid, int keyType, int keySize, int flags, byte[][] args)341 public boolean generate(String key, int uid, int keyType, int keySize, int flags, 342 byte[][] args) { 343 try { 344 return mBinder.generate(key, uid, keyType, keySize, flags, 345 new KeystoreArguments(args)) == NO_ERROR; 346 } catch (RemoteException e) { 347 Log.w(TAG, "Cannot connect to keystore", e); 348 return false; 349 } 350 } 351 importKey(String keyName, byte[] key, int uid, int flags)352 public boolean importKey(String keyName, byte[] key, int uid, int flags) { 353 try { 354 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR; 355 } catch (RemoteException e) { 356 Log.w(TAG, "Cannot connect to keystore", e); 357 return false; 358 } 359 } 360 sign(String key, byte[] data)361 public byte[] sign(String key, byte[] data) { 362 try { 363 return mBinder.sign(key, data); 364 } catch (RemoteException e) { 365 Log.w(TAG, "Cannot connect to keystore", e); 366 return null; 367 } catch (android.os.ServiceSpecificException e) { 368 Log.w(TAG, "KeyStore exception", e); 369 return null; 370 } 371 372 } 373 verify(String key, byte[] data, byte[] signature)374 public boolean verify(String key, byte[] data, byte[] signature) { 375 try { 376 signature = signature != null ? signature : new byte[0]; 377 return mBinder.verify(key, data, signature) == NO_ERROR; 378 } catch (RemoteException e) { 379 Log.w(TAG, "Cannot connect to keystore", e); 380 return false; 381 } catch (android.os.ServiceSpecificException e) { 382 Log.w(TAG, "KeyStore exception", e); 383 return false; 384 } 385 386 } 387 grant(String key, int uid)388 public String grant(String key, int uid) { 389 try { 390 String grantAlias = mBinder.grant(key, uid); 391 if (grantAlias == "") return null; 392 return grantAlias; 393 } catch (RemoteException e) { 394 Log.w(TAG, "Cannot connect to keystore", e); 395 return null; 396 } 397 } 398 ungrant(String key, int uid)399 public boolean ungrant(String key, int uid) { 400 try { 401 return mBinder.ungrant(key, uid) == NO_ERROR; 402 } catch (RemoteException e) { 403 Log.w(TAG, "Cannot connect to keystore", e); 404 return false; 405 } 406 } 407 408 /** 409 * Returns the last modification time of the key in milliseconds since the 410 * epoch. Will return -1L if the key could not be found or other error. 411 */ getmtime(String key, int uid)412 public long getmtime(String key, int uid) { 413 try { 414 final long millis = mBinder.getmtime(key, uid); 415 if (millis == -1L) { 416 return -1L; 417 } 418 419 return millis * 1000L; 420 } catch (RemoteException e) { 421 Log.w(TAG, "Cannot connect to keystore", e); 422 return -1L; 423 } 424 } 425 getmtime(String key)426 public long getmtime(String key) { 427 return getmtime(key, UID_SELF); 428 } 429 430 // TODO: remove this when it's removed from Settings isHardwareBacked()431 public boolean isHardwareBacked() { 432 return isHardwareBacked("RSA"); 433 } 434 isHardwareBacked(String keyType)435 public boolean isHardwareBacked(String keyType) { 436 try { 437 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR; 438 } catch (RemoteException e) { 439 Log.w(TAG, "Cannot connect to keystore", e); 440 return false; 441 } 442 } 443 clearUid(int uid)444 public boolean clearUid(int uid) { 445 try { 446 return mBinder.clear_uid(uid) == NO_ERROR; 447 } catch (RemoteException e) { 448 Log.w(TAG, "Cannot connect to keystore", e); 449 return false; 450 } 451 } 452 getLastError()453 public int getLastError() { 454 return mError; 455 } 456 addRngEntropy(byte[] data, int flags)457 public boolean addRngEntropy(byte[] data, int flags) { 458 try { 459 return mBinder.addRngEntropy(data, flags) == NO_ERROR; 460 } catch (RemoteException e) { 461 Log.w(TAG, "Cannot connect to keystore", e); 462 return false; 463 } 464 } 465 generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid, int flags, KeyCharacteristics outCharacteristics)466 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid, 467 int flags, KeyCharacteristics outCharacteristics) { 468 try { 469 entropy = entropy != null ? entropy : new byte[0]; 470 args = args != null ? args : new KeymasterArguments(); 471 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics); 472 } catch (RemoteException e) { 473 Log.w(TAG, "Cannot connect to keystore", e); 474 return SYSTEM_ERROR; 475 } 476 } 477 generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags, KeyCharacteristics outCharacteristics)478 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags, 479 KeyCharacteristics outCharacteristics) { 480 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics); 481 } 482 getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, int uid, KeyCharacteristics outCharacteristics)483 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, 484 int uid, KeyCharacteristics outCharacteristics) { 485 try { 486 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]); 487 appId = appId != null ? appId : new KeymasterBlob(new byte[0]); 488 return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics); 489 } catch (RemoteException e) { 490 Log.w(TAG, "Cannot connect to keystore", e); 491 return SYSTEM_ERROR; 492 } 493 } 494 getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, KeyCharacteristics outCharacteristics)495 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, 496 KeyCharacteristics outCharacteristics) { 497 return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics); 498 } 499 importKey(String alias, KeymasterArguments args, int format, byte[] keyData, int uid, int flags, KeyCharacteristics outCharacteristics)500 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 501 int uid, int flags, KeyCharacteristics outCharacteristics) { 502 try { 503 return mBinder.importKey(alias, args, format, keyData, uid, flags, 504 outCharacteristics); 505 } catch (RemoteException e) { 506 Log.w(TAG, "Cannot connect to keystore", e); 507 return SYSTEM_ERROR; 508 } 509 } 510 importKey(String alias, KeymasterArguments args, int format, byte[] keyData, int flags, KeyCharacteristics outCharacteristics)511 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 512 int flags, KeyCharacteristics outCharacteristics) { 513 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics); 514 } 515 importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey, String wrappingKeyAlias, byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid, KeyCharacteristics outCharacteristics)516 public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey, 517 String wrappingKeyAlias, 518 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid, 519 KeyCharacteristics outCharacteristics) { 520 try { 521 return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias, 522 maskingKey, args, rootSid, fingerprintSid, outCharacteristics); 523 } catch (RemoteException e) { 524 Log.w(TAG, "Cannot connect to keystore", e); 525 return SYSTEM_ERROR; 526 } 527 } 528 exportKey(String alias, int format, KeymasterBlob clientId, KeymasterBlob appId, int uid)529 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId, 530 KeymasterBlob appId, int uid) { 531 try { 532 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]); 533 appId = appId != null ? appId : new KeymasterBlob(new byte[0]); 534 return mBinder.exportKey(alias, format, clientId, appId, uid); 535 } catch (RemoteException e) { 536 Log.w(TAG, "Cannot connect to keystore", e); 537 return null; 538 } 539 } exportKey(String alias, int format, KeymasterBlob clientId, KeymasterBlob appId)540 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId, 541 KeymasterBlob appId) { 542 return exportKey(alias, format, clientId, appId, UID_SELF); 543 } 544 begin(String alias, int purpose, boolean pruneable, KeymasterArguments args, byte[] entropy, int uid)545 public OperationResult begin(String alias, int purpose, boolean pruneable, 546 KeymasterArguments args, byte[] entropy, int uid) { 547 try { 548 args = args != null ? args : new KeymasterArguments(); 549 entropy = entropy != null ? entropy : new byte[0]; 550 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid); 551 } catch (RemoteException e) { 552 Log.w(TAG, "Cannot connect to keystore", e); 553 return null; 554 } 555 } 556 begin(String alias, int purpose, boolean pruneable, KeymasterArguments args, byte[] entropy)557 public OperationResult begin(String alias, int purpose, boolean pruneable, 558 KeymasterArguments args, byte[] entropy) { 559 entropy = entropy != null ? entropy : new byte[0]; 560 args = args != null ? args : new KeymasterArguments(); 561 return begin(alias, purpose, pruneable, args, entropy, UID_SELF); 562 } 563 update(IBinder token, KeymasterArguments arguments, byte[] input)564 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) { 565 try { 566 arguments = arguments != null ? arguments : new KeymasterArguments(); 567 input = input != null ? input : new byte[0]; 568 return mBinder.update(token, arguments, input); 569 } catch (RemoteException e) { 570 Log.w(TAG, "Cannot connect to keystore", e); 571 return null; 572 } 573 } 574 finish(IBinder token, KeymasterArguments arguments, byte[] signature, byte[] entropy)575 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature, 576 byte[] entropy) { 577 try { 578 arguments = arguments != null ? arguments : new KeymasterArguments(); 579 entropy = entropy != null ? entropy : new byte[0]; 580 signature = signature != null ? signature : new byte[0]; 581 return mBinder.finish(token, arguments, signature, entropy); 582 } catch (RemoteException e) { 583 Log.w(TAG, "Cannot connect to keystore", e); 584 return null; 585 } 586 } 587 finish(IBinder token, KeymasterArguments arguments, byte[] signature)588 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) { 589 return finish(token, arguments, signature, null); 590 } 591 abort(IBinder token)592 public int abort(IBinder token) { 593 try { 594 return mBinder.abort(token); 595 } catch (RemoteException e) { 596 Log.w(TAG, "Cannot connect to keystore", e); 597 return SYSTEM_ERROR; 598 } 599 } 600 601 /** 602 * Check if the operation referenced by {@code token} is currently authorized. 603 * 604 * @param token An operation token returned by a call to 605 * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}. 606 */ isOperationAuthorized(IBinder token)607 public boolean isOperationAuthorized(IBinder token) { 608 try { 609 return mBinder.isOperationAuthorized(token); 610 } catch (RemoteException e) { 611 Log.w(TAG, "Cannot connect to keystore", e); 612 return false; 613 } 614 } 615 616 /** 617 * Add an authentication record to the keystore authorization table. 618 * 619 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster. 620 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to 621 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode. 622 */ addAuthToken(byte[] authToken)623 public int addAuthToken(byte[] authToken) { 624 try { 625 return mBinder.addAuthToken(authToken); 626 } catch (RemoteException e) { 627 Log.w(TAG, "Cannot connect to keystore", e); 628 return SYSTEM_ERROR; 629 } 630 } 631 632 /** 633 * Notify keystore that a user's password has changed. 634 * 635 * @param userId the user whose password changed. 636 * @param newPassword the new password or "" if the password was removed. 637 */ onUserPasswordChanged(int userId, String newPassword)638 public boolean onUserPasswordChanged(int userId, String newPassword) { 639 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that 640 // explicit here. 641 if (newPassword == null) { 642 newPassword = ""; 643 } 644 try { 645 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR; 646 } catch (RemoteException e) { 647 Log.w(TAG, "Cannot connect to keystore", e); 648 return false; 649 } 650 } 651 652 /** 653 * Notify keystore that a user was added. 654 * 655 * @param userId the new user. 656 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is 657 * specified then the new user's keystore will be intialized with the same secure lockscreen 658 * password as the parent. 659 */ onUserAdded(int userId, int parentId)660 public void onUserAdded(int userId, int parentId) { 661 try { 662 mBinder.onUserAdded(userId, parentId); 663 } catch (RemoteException e) { 664 Log.w(TAG, "Cannot connect to keystore", e); 665 } 666 } 667 668 /** 669 * Notify keystore that a user was added. 670 * 671 * @param userId the new user. 672 */ onUserAdded(int userId)673 public void onUserAdded(int userId) { 674 onUserAdded(userId, -1); 675 } 676 677 /** 678 * Notify keystore that a user was removed. 679 * 680 * @param userId the removed user. 681 */ onUserRemoved(int userId)682 public void onUserRemoved(int userId) { 683 try { 684 mBinder.onUserRemoved(userId); 685 } catch (RemoteException e) { 686 Log.w(TAG, "Cannot connect to keystore", e); 687 } 688 } 689 onUserPasswordChanged(String newPassword)690 public boolean onUserPasswordChanged(String newPassword) { 691 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword); 692 } 693 694 /** 695 * Notify keystore about the latest user locked state. This is to support keyguard-bound key. 696 */ onUserLockedStateChanged(int userHandle, boolean locked)697 public void onUserLockedStateChanged(int userHandle, boolean locked) { 698 try { 699 mBinder.onKeyguardVisibilityChanged(locked, userHandle); 700 } catch (RemoteException e) { 701 Log.w(TAG, "Failed to update user locked state " + userHandle, e); 702 } 703 } 704 attestKey( String alias, KeymasterArguments params, KeymasterCertificateChain outChain)705 public int attestKey( 706 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) { 707 try { 708 if (params == null) { 709 params = new KeymasterArguments(); 710 } 711 if (outChain == null) { 712 outChain = new KeymasterCertificateChain(); 713 } 714 return mBinder.attestKey(alias, params, outChain); 715 } catch (RemoteException e) { 716 Log.w(TAG, "Cannot connect to keystore", e); 717 return SYSTEM_ERROR; 718 } 719 } 720 attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain)721 public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) { 722 try { 723 if (params == null) { 724 params = new KeymasterArguments(); 725 } 726 if (outChain == null) { 727 outChain = new KeymasterCertificateChain(); 728 } 729 return mBinder.attestDeviceIds(params, outChain); 730 } catch (RemoteException e) { 731 Log.w(TAG, "Cannot connect to keystore", e); 732 return SYSTEM_ERROR; 733 } 734 } 735 736 /** 737 * Notify keystore that the device went off-body. 738 */ onDeviceOffBody()739 public void onDeviceOffBody() { 740 try { 741 mBinder.onDeviceOffBody(); 742 } catch (RemoteException e) { 743 Log.w(TAG, "Cannot connect to keystore", e); 744 } 745 } 746 747 // Keep in sync with confirmationui/1.0/types.hal. 748 public static final int CONFIRMATIONUI_OK = 0; 749 public static final int CONFIRMATIONUI_CANCELED = 1; 750 public static final int CONFIRMATIONUI_ABORTED = 2; 751 public static final int CONFIRMATIONUI_OPERATION_PENDING = 3; 752 public static final int CONFIRMATIONUI_IGNORED = 4; 753 public static final int CONFIRMATIONUI_SYSTEM_ERROR = 5; 754 public static final int CONFIRMATIONUI_UNIMPLEMENTED = 6; 755 public static final int CONFIRMATIONUI_UNEXPECTED = 7; 756 public static final int CONFIRMATIONUI_UIERROR = 0x10000; 757 public static final int CONFIRMATIONUI_UIERROR_MISSING_GLYPH = 0x10001; 758 public static final int CONFIRMATIONUI_UIERROR_MESSAGE_TOO_LONG = 0x10002; 759 public static final int CONFIRMATIONUI_UIERROR_MALFORMED_UTF8_ENCODING = 0x10003; 760 761 /** 762 * Requests keystore call into the confirmationui HAL to display a prompt. 763 * 764 * @param listener the binder to use for callbacks. 765 * @param promptText the prompt to display. 766 * @param extraData extra data / nonce from application. 767 * @param locale the locale as a BCP 47 langauge tag. 768 * @param uiOptionsAsFlags the UI options to use, as flags. 769 * @return one of the {@code CONFIRMATIONUI_*} constants, for 770 * example {@code KeyStore.CONFIRMATIONUI_OK}. 771 */ presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData, String locale, int uiOptionsAsFlags)772 public int presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData, 773 String locale, int uiOptionsAsFlags) { 774 try { 775 return mBinder.presentConfirmationPrompt(listener, promptText, extraData, locale, 776 uiOptionsAsFlags); 777 } catch (RemoteException e) { 778 Log.w(TAG, "Cannot connect to keystore", e); 779 return CONFIRMATIONUI_SYSTEM_ERROR; 780 } 781 } 782 783 /** 784 * Requests keystore call into the confirmationui HAL to cancel displaying a prompt. 785 * 786 * @param listener the binder passed to the {@link #presentConfirmationPrompt} method. 787 * @return one of the {@code CONFIRMATIONUI_*} constants, for 788 * example {@code KeyStore.CONFIRMATIONUI_OK}. 789 */ cancelConfirmationPrompt(IBinder listener)790 public int cancelConfirmationPrompt(IBinder listener) { 791 try { 792 return mBinder.cancelConfirmationPrompt(listener); 793 } catch (RemoteException e) { 794 Log.w(TAG, "Cannot connect to keystore", e); 795 return CONFIRMATIONUI_SYSTEM_ERROR; 796 } 797 } 798 799 /** 800 * Requests keystore to check if the confirmationui HAL is available. 801 * 802 * @return whether the confirmationUI HAL is available. 803 */ isConfirmationPromptSupported()804 public boolean isConfirmationPromptSupported() { 805 try { 806 return mBinder.isConfirmationPromptSupported(); 807 } catch (RemoteException e) { 808 Log.w(TAG, "Cannot connect to keystore", e); 809 return false; 810 } 811 } 812 813 /** 814 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error 815 * code. 816 */ getKeyStoreException(int errorCode)817 public static KeyStoreException getKeyStoreException(int errorCode) { 818 if (errorCode > 0) { 819 // KeyStore layer error 820 switch (errorCode) { 821 case NO_ERROR: 822 return new KeyStoreException(errorCode, "OK"); 823 case LOCKED: 824 return new KeyStoreException(errorCode, "User authentication required"); 825 case UNINITIALIZED: 826 return new KeyStoreException(errorCode, "Keystore not initialized"); 827 case SYSTEM_ERROR: 828 return new KeyStoreException(errorCode, "System error"); 829 case PERMISSION_DENIED: 830 return new KeyStoreException(errorCode, "Permission denied"); 831 case KEY_NOT_FOUND: 832 return new KeyStoreException(errorCode, "Key not found"); 833 case VALUE_CORRUPTED: 834 return new KeyStoreException(errorCode, "Key blob corrupted"); 835 case OP_AUTH_NEEDED: 836 return new KeyStoreException(errorCode, "Operation requires authorization"); 837 default: 838 return new KeyStoreException(errorCode, String.valueOf(errorCode)); 839 } 840 } else { 841 // Keymaster layer error 842 switch (errorCode) { 843 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT: 844 // The name of this parameter significantly differs between Keymaster and 845 // framework APIs. Use the framework wording to make life easier for developers. 846 return new KeyStoreException(errorCode, 847 "Invalid user authentication validity duration"); 848 default: 849 return new KeyStoreException(errorCode, 850 KeymasterDefs.getErrorMessage(errorCode)); 851 } 852 } 853 } 854 855 /** 856 * Returns an {@link InvalidKeyException} corresponding to the provided 857 * {@link KeyStoreException}. 858 */ getInvalidKeyException( String keystoreKeyAlias, int uid, KeyStoreException e)859 public InvalidKeyException getInvalidKeyException( 860 String keystoreKeyAlias, int uid, KeyStoreException e) { 861 switch (e.getErrorCode()) { 862 case LOCKED: 863 return new UserNotAuthenticatedException(); 864 case KeymasterDefs.KM_ERROR_KEY_EXPIRED: 865 return new KeyExpiredException(); 866 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: 867 return new KeyNotYetValidException(); 868 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: 869 case OP_AUTH_NEEDED: 870 { 871 // We now need to determine whether the key/operation can become usable if user 872 // authentication is performed, or whether it can never become usable again. 873 // User authentication requirements are contained in the key's characteristics. We 874 // need to check whether these requirements can be be satisfied by asking the user 875 // to authenticate. 876 KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); 877 int getKeyCharacteristicsErrorCode = 878 getKeyCharacteristics(keystoreKeyAlias, null, null, uid, 879 keyCharacteristics); 880 if (getKeyCharacteristicsErrorCode != NO_ERROR) { 881 return new InvalidKeyException( 882 "Failed to obtained key characteristics", 883 getKeyStoreException(getKeyCharacteristicsErrorCode)); 884 } 885 List<BigInteger> keySids = 886 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID); 887 if (keySids.isEmpty()) { 888 // Key is not bound to any SIDs -- no amount of authentication will help here. 889 return new KeyPermanentlyInvalidatedException(); 890 } 891 long rootSid = GateKeeper.getSecureUserId(); 892 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) { 893 // One of the key's SIDs is the current root SID -- user can be authenticated 894 // against that SID. 895 return new UserNotAuthenticatedException(); 896 } 897 898 long fingerprintOnlySid = getFingerprintOnlySid(); 899 if ((fingerprintOnlySid != 0) 900 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) { 901 // One of the key's SIDs is the current fingerprint SID -- user can be 902 // authenticated against that SID. 903 return new UserNotAuthenticatedException(); 904 } 905 906 // None of the key's SIDs can ever be authenticated 907 return new KeyPermanentlyInvalidatedException(); 908 } 909 case UNINITIALIZED: 910 return new KeyPermanentlyInvalidatedException(); 911 default: 912 return new InvalidKeyException("Keystore operation failed", e); 913 } 914 } 915 getFingerprintOnlySid()916 private long getFingerprintOnlySid() { 917 final PackageManager packageManager = mContext.getPackageManager(); 918 if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 919 return 0; 920 } 921 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class); 922 if (fingerprintManager == null) { 923 return 0; 924 } 925 926 // TODO: Restore USE_FINGERPRINT permission check in 927 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here. 928 return fingerprintManager.getAuthenticatorId(); 929 } 930 931 /** 932 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error 933 * code. 934 */ getInvalidKeyException(String keystoreKeyAlias, int uid, int errorCode)935 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid, 936 int errorCode) { 937 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode)); 938 } 939 } 940