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 attestKey( String alias, KeymasterArguments params, KeymasterCertificateChain outChain)694 public int attestKey( 695 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) { 696 try { 697 if (params == null) { 698 params = new KeymasterArguments(); 699 } 700 if (outChain == null) { 701 outChain = new KeymasterCertificateChain(); 702 } 703 return mBinder.attestKey(alias, params, outChain); 704 } catch (RemoteException e) { 705 Log.w(TAG, "Cannot connect to keystore", e); 706 return SYSTEM_ERROR; 707 } 708 } 709 attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain)710 public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) { 711 try { 712 if (params == null) { 713 params = new KeymasterArguments(); 714 } 715 if (outChain == null) { 716 outChain = new KeymasterCertificateChain(); 717 } 718 return mBinder.attestDeviceIds(params, outChain); 719 } catch (RemoteException e) { 720 Log.w(TAG, "Cannot connect to keystore", e); 721 return SYSTEM_ERROR; 722 } 723 } 724 725 /** 726 * Notify keystore that the device went off-body. 727 */ onDeviceOffBody()728 public void onDeviceOffBody() { 729 try { 730 mBinder.onDeviceOffBody(); 731 } catch (RemoteException e) { 732 Log.w(TAG, "Cannot connect to keystore", e); 733 } 734 } 735 736 // Keep in sync with confirmationui/1.0/types.hal. 737 public static final int CONFIRMATIONUI_OK = 0; 738 public static final int CONFIRMATIONUI_CANCELED = 1; 739 public static final int CONFIRMATIONUI_ABORTED = 2; 740 public static final int CONFIRMATIONUI_OPERATION_PENDING = 3; 741 public static final int CONFIRMATIONUI_IGNORED = 4; 742 public static final int CONFIRMATIONUI_SYSTEM_ERROR = 5; 743 public static final int CONFIRMATIONUI_UNIMPLEMENTED = 6; 744 public static final int CONFIRMATIONUI_UNEXPECTED = 7; 745 public static final int CONFIRMATIONUI_UIERROR = 0x10000; 746 public static final int CONFIRMATIONUI_UIERROR_MISSING_GLYPH = 0x10001; 747 public static final int CONFIRMATIONUI_UIERROR_MESSAGE_TOO_LONG = 0x10002; 748 public static final int CONFIRMATIONUI_UIERROR_MALFORMED_UTF8_ENCODING = 0x10003; 749 750 /** 751 * Requests keystore call into the confirmationui HAL to display a prompt. 752 * 753 * @param listener the binder to use for callbacks. 754 * @param promptText the prompt to display. 755 * @param extraData extra data / nonce from application. 756 * @param locale the locale as a BCP 47 langauge tag. 757 * @param uiOptionsAsFlags the UI options to use, as flags. 758 * @return one of the {@code CONFIRMATIONUI_*} constants, for 759 * example {@code KeyStore.CONFIRMATIONUI_OK}. 760 */ presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData, String locale, int uiOptionsAsFlags)761 public int presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData, 762 String locale, int uiOptionsAsFlags) { 763 try { 764 return mBinder.presentConfirmationPrompt(listener, promptText, extraData, locale, 765 uiOptionsAsFlags); 766 } catch (RemoteException e) { 767 Log.w(TAG, "Cannot connect to keystore", e); 768 return CONFIRMATIONUI_SYSTEM_ERROR; 769 } 770 } 771 772 /** 773 * Requests keystore call into the confirmationui HAL to cancel displaying a prompt. 774 * 775 * @param listener the binder passed to the {@link #presentConfirmationPrompt} method. 776 * @return one of the {@code CONFIRMATIONUI_*} constants, for 777 * example {@code KeyStore.CONFIRMATIONUI_OK}. 778 */ cancelConfirmationPrompt(IBinder listener)779 public int cancelConfirmationPrompt(IBinder listener) { 780 try { 781 return mBinder.cancelConfirmationPrompt(listener); 782 } catch (RemoteException e) { 783 Log.w(TAG, "Cannot connect to keystore", e); 784 return CONFIRMATIONUI_SYSTEM_ERROR; 785 } 786 } 787 788 /** 789 * Requests keystore to check if the confirmationui HAL is available. 790 * 791 * @return whether the confirmationUI HAL is available. 792 */ isConfirmationPromptSupported()793 public boolean isConfirmationPromptSupported() { 794 try { 795 return mBinder.isConfirmationPromptSupported(); 796 } catch (RemoteException e) { 797 Log.w(TAG, "Cannot connect to keystore", e); 798 return false; 799 } 800 } 801 802 /** 803 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error 804 * code. 805 */ getKeyStoreException(int errorCode)806 public static KeyStoreException getKeyStoreException(int errorCode) { 807 if (errorCode > 0) { 808 // KeyStore layer error 809 switch (errorCode) { 810 case NO_ERROR: 811 return new KeyStoreException(errorCode, "OK"); 812 case LOCKED: 813 return new KeyStoreException(errorCode, "User authentication required"); 814 case UNINITIALIZED: 815 return new KeyStoreException(errorCode, "Keystore not initialized"); 816 case SYSTEM_ERROR: 817 return new KeyStoreException(errorCode, "System error"); 818 case PERMISSION_DENIED: 819 return new KeyStoreException(errorCode, "Permission denied"); 820 case KEY_NOT_FOUND: 821 return new KeyStoreException(errorCode, "Key not found"); 822 case VALUE_CORRUPTED: 823 return new KeyStoreException(errorCode, "Key blob corrupted"); 824 case OP_AUTH_NEEDED: 825 return new KeyStoreException(errorCode, "Operation requires authorization"); 826 default: 827 return new KeyStoreException(errorCode, String.valueOf(errorCode)); 828 } 829 } else { 830 // Keymaster layer error 831 switch (errorCode) { 832 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT: 833 // The name of this parameter significantly differs between Keymaster and 834 // framework APIs. Use the framework wording to make life easier for developers. 835 return new KeyStoreException(errorCode, 836 "Invalid user authentication validity duration"); 837 default: 838 return new KeyStoreException(errorCode, 839 KeymasterDefs.getErrorMessage(errorCode)); 840 } 841 } 842 } 843 844 /** 845 * Returns an {@link InvalidKeyException} corresponding to the provided 846 * {@link KeyStoreException}. 847 */ getInvalidKeyException( String keystoreKeyAlias, int uid, KeyStoreException e)848 public InvalidKeyException getInvalidKeyException( 849 String keystoreKeyAlias, int uid, KeyStoreException e) { 850 switch (e.getErrorCode()) { 851 case LOCKED: 852 return new UserNotAuthenticatedException(); 853 case KeymasterDefs.KM_ERROR_KEY_EXPIRED: 854 return new KeyExpiredException(); 855 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: 856 return new KeyNotYetValidException(); 857 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: 858 case OP_AUTH_NEEDED: 859 { 860 // We now need to determine whether the key/operation can become usable if user 861 // authentication is performed, or whether it can never become usable again. 862 // User authentication requirements are contained in the key's characteristics. We 863 // need to check whether these requirements can be be satisfied by asking the user 864 // to authenticate. 865 KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); 866 int getKeyCharacteristicsErrorCode = 867 getKeyCharacteristics(keystoreKeyAlias, null, null, uid, 868 keyCharacteristics); 869 if (getKeyCharacteristicsErrorCode != NO_ERROR) { 870 return new InvalidKeyException( 871 "Failed to obtained key characteristics", 872 getKeyStoreException(getKeyCharacteristicsErrorCode)); 873 } 874 List<BigInteger> keySids = 875 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID); 876 if (keySids.isEmpty()) { 877 // Key is not bound to any SIDs -- no amount of authentication will help here. 878 return new KeyPermanentlyInvalidatedException(); 879 } 880 long rootSid = GateKeeper.getSecureUserId(); 881 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) { 882 // One of the key's SIDs is the current root SID -- user can be authenticated 883 // against that SID. 884 return new UserNotAuthenticatedException(); 885 } 886 887 long fingerprintOnlySid = getFingerprintOnlySid(); 888 if ((fingerprintOnlySid != 0) 889 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) { 890 // One of the key's SIDs is the current fingerprint SID -- user can be 891 // authenticated against that SID. 892 return new UserNotAuthenticatedException(); 893 } 894 895 // None of the key's SIDs can ever be authenticated 896 return new KeyPermanentlyInvalidatedException(); 897 } 898 case UNINITIALIZED: 899 return new KeyPermanentlyInvalidatedException(); 900 default: 901 return new InvalidKeyException("Keystore operation failed", e); 902 } 903 } 904 getFingerprintOnlySid()905 private long getFingerprintOnlySid() { 906 final PackageManager packageManager = mContext.getPackageManager(); 907 if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 908 return 0; 909 } 910 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class); 911 if (fingerprintManager == null) { 912 return 0; 913 } 914 915 // TODO: Restore USE_FINGERPRINT permission check in 916 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here. 917 return fingerprintManager.getAuthenticatorId(); 918 } 919 920 /** 921 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error 922 * code. 923 */ getInvalidKeyException(String keystoreKeyAlias, int uid, int errorCode)924 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid, 925 int errorCode) { 926 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode)); 927 } 928 } 929