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.compat.annotation.UnsupportedAppUsage; 23 import android.content.Context; 24 import android.content.pm.PackageManager; 25 import android.hardware.face.FaceManager; 26 import android.hardware.fingerprint.FingerprintManager; 27 import android.os.Binder; 28 import android.os.Build; 29 import android.os.IBinder; 30 import android.os.Process; 31 import android.os.RemoteException; 32 import android.os.ServiceManager; 33 import android.os.UserHandle; 34 import android.security.keymaster.ExportResult; 35 import android.security.keymaster.KeyCharacteristics; 36 import android.security.keymaster.KeymasterArguments; 37 import android.security.keymaster.KeymasterBlob; 38 import android.security.keymaster.KeymasterCertificateChain; 39 import android.security.keymaster.KeymasterDefs; 40 import android.security.keymaster.OperationResult; 41 import android.security.keystore.IKeystoreService; 42 import android.security.keystore.KeyExpiredException; 43 import android.security.keystore.KeyNotYetValidException; 44 import android.security.keystore.KeyPermanentlyInvalidatedException; 45 import android.security.keystore.KeyProperties; 46 import android.security.keystore.KeystoreResponse; 47 import android.security.keystore.UserNotAuthenticatedException; 48 import android.util.Log; 49 50 import com.android.org.bouncycastle.asn1.ASN1InputStream; 51 import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 52 53 import java.io.ByteArrayInputStream; 54 import java.io.IOException; 55 import java.math.BigInteger; 56 import java.security.InvalidKeyException; 57 import java.util.ArrayList; 58 import java.util.Date; 59 import java.util.List; 60 import java.util.Locale; 61 import java.util.concurrent.CompletableFuture; 62 import java.util.concurrent.ExecutionException; 63 64 import sun.security.util.ObjectIdentifier; 65 import sun.security.x509.AlgorithmId; 66 67 /** 68 * @hide This should not be made public in its present form because it 69 * assumes that private and secret key bytes are available and would 70 * preclude the use of hardware crypto. 71 */ 72 public class KeyStore { 73 private static final String TAG = "KeyStore"; 74 75 // ResponseCodes - see system/security/keystore/include/keystore/keystore.h 76 @UnsupportedAppUsage 77 public static final int NO_ERROR = 1; 78 public static final int LOCKED = 2; 79 public static final int UNINITIALIZED = 3; 80 public static final int SYSTEM_ERROR = 4; 81 public static final int PROTOCOL_ERROR = 5; 82 public static final int PERMISSION_DENIED = 6; 83 public static final int KEY_NOT_FOUND = 7; 84 public static final int VALUE_CORRUPTED = 8; 85 public static final int UNDEFINED_ACTION = 9; 86 public static final int WRONG_PASSWORD = 10; 87 public static final int KEY_ALREADY_EXISTS = 16; 88 public static final int CANNOT_ATTEST_IDS = -66; 89 public static final int HARDWARE_TYPE_UNAVAILABLE = -68; 90 91 /** 92 * Per operation authentication is needed before this operation is valid. 93 * This is returned from {@link #begin} when begin succeeds but the operation uses 94 * per-operation authentication and must authenticate before calling {@link #update} or 95 * {@link #finish}. 96 */ 97 public static final int OP_AUTH_NEEDED = 15; 98 99 // Used when a user changes their pin, invalidating old auth bound keys. 100 public static final int KEY_PERMANENTLY_INVALIDATED = 17; 101 102 // Used for UID field to indicate the calling UID. 103 public static final int UID_SELF = -1; 104 105 // Flags for "put" "import" and "generate" 106 public static final int FLAG_NONE = 0; 107 108 /** 109 * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key 110 * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern). 111 * 112 * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set 113 * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key 114 * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or 115 * a Device Administrator). Finally, this key (or key pair) cannot be used until the user 116 * unlocks the secure lock screen after boot. 117 * 118 * @see KeyguardManager#isDeviceSecure() 119 */ 120 public static final int FLAG_ENCRYPTED = 1; 121 122 /** 123 * Select Software keymaster device, which as of this writing is the lowest security 124 * level available on an android device. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided 125 * A TEE based keymaster implementation is implied. 126 * 127 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h 128 * For historical reasons this corresponds to the KEYSTORE_FLAG_FALLBACK flag. 129 */ 130 public static final int FLAG_SOFTWARE = 1 << 1; 131 132 /** 133 * A private flag that's only available to system server to indicate that this key is part of 134 * device encryption flow so it receives special treatment from keystore. For example this key 135 * will not be super encrypted, and it will be stored separately under an unique UID instead 136 * of the caller UID i.e. SYSTEM. 137 * 138 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h 139 */ 140 public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3; 141 142 /** 143 * Select Strongbox keymaster device, which as of this writing the the highest security level 144 * available an android devices. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided 145 * A TEE based keymaster implementation is implied. 146 * 147 * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h 148 */ 149 public static final int FLAG_STRONGBOX = 1 << 4; 150 151 // States 152 public enum State { 153 @UnsupportedAppUsage 154 UNLOCKED, 155 @UnsupportedAppUsage 156 LOCKED, 157 UNINITIALIZED 158 }; 159 160 private int mError = NO_ERROR; 161 162 private final IKeystoreService mBinder; 163 private final Context mContext; 164 165 private IBinder mToken; 166 KeyStore(IKeystoreService binder)167 private KeyStore(IKeystoreService binder) { 168 mBinder = binder; 169 mContext = getApplicationContext(); 170 } 171 172 @UnsupportedAppUsage getApplicationContext()173 public static Context getApplicationContext() { 174 Application application = ActivityThread.currentApplication(); 175 if (application == null) { 176 throw new IllegalStateException( 177 "Failed to obtain application Context from ActivityThread"); 178 } 179 return application; 180 } 181 182 @UnsupportedAppUsage getInstance()183 public static KeyStore getInstance() { 184 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager 185 .getService("android.security.keystore")); 186 return new KeyStore(keystore); 187 } 188 getToken()189 private synchronized IBinder getToken() { 190 if (mToken == null) { 191 mToken = new Binder(); 192 } 193 return mToken; 194 } 195 196 @UnsupportedAppUsage state(int userId)197 public State state(int userId) { 198 final int ret; 199 try { 200 ret = mBinder.getState(userId); 201 } catch (RemoteException e) { 202 Log.w(TAG, "Cannot connect to keystore", e); 203 throw new AssertionError(e); 204 } 205 206 switch (ret) { 207 case NO_ERROR: return State.UNLOCKED; 208 case LOCKED: return State.LOCKED; 209 case UNINITIALIZED: return State.UNINITIALIZED; 210 default: throw new AssertionError(mError); 211 } 212 } 213 214 @UnsupportedAppUsage state()215 public State state() { 216 return state(UserHandle.myUserId()); 217 } 218 isUnlocked()219 public boolean isUnlocked() { 220 return state() == State.UNLOCKED; 221 } 222 get(String key, int uid)223 public byte[] get(String key, int uid) { 224 return get(key, uid, false); 225 } 226 227 @UnsupportedAppUsage get(String key)228 public byte[] get(String key) { 229 return get(key, UID_SELF); 230 } 231 get(String key, int uid, boolean suppressKeyNotFoundWarning)232 public byte[] get(String key, int uid, boolean suppressKeyNotFoundWarning) { 233 try { 234 key = key != null ? key : ""; 235 return mBinder.get(key, uid); 236 } catch (RemoteException e) { 237 Log.w(TAG, "Cannot connect to keystore", e); 238 return null; 239 } catch (android.os.ServiceSpecificException e) { 240 if (!suppressKeyNotFoundWarning || e.errorCode != KEY_NOT_FOUND) { 241 Log.w(TAG, "KeyStore exception", e); 242 } 243 return null; 244 } 245 } 246 get(String key, boolean suppressKeyNotFoundWarning)247 public byte[] get(String key, boolean suppressKeyNotFoundWarning) { 248 return get(key, UID_SELF, suppressKeyNotFoundWarning); 249 } 250 251 put(String key, byte[] value, int uid, int flags)252 public boolean put(String key, byte[] value, int uid, int flags) { 253 return insert(key, value, uid, flags) == NO_ERROR; 254 } 255 insert(String key, byte[] value, int uid, int flags)256 public int insert(String key, byte[] value, int uid, int flags) { 257 try { 258 if (value == null) { 259 value = new byte[0]; 260 } 261 int error = mBinder.insert(key, value, uid, flags); 262 if (error == KEY_ALREADY_EXISTS) { 263 mBinder.del(key, uid); 264 error = mBinder.insert(key, value, uid, flags); 265 } 266 return error; 267 } catch (RemoteException e) { 268 Log.w(TAG, "Cannot connect to keystore", e); 269 return SYSTEM_ERROR; 270 } 271 } 272 delete2(String key, int uid)273 int delete2(String key, int uid) { 274 try { 275 return mBinder.del(key, uid); 276 } catch (RemoteException e) { 277 Log.w(TAG, "Cannot connect to keystore", e); 278 return SYSTEM_ERROR; 279 } 280 } 281 delete(String key, int uid)282 public boolean delete(String key, int uid) { 283 int ret = delete2(key, uid); 284 return ret == NO_ERROR || ret == KEY_NOT_FOUND; 285 } 286 287 @UnsupportedAppUsage delete(String key)288 public boolean delete(String key) { 289 return delete(key, UID_SELF); 290 } 291 contains(String key, int uid)292 public boolean contains(String key, int uid) { 293 try { 294 return mBinder.exist(key, uid) == NO_ERROR; 295 } catch (RemoteException e) { 296 Log.w(TAG, "Cannot connect to keystore", e); 297 return false; 298 } 299 } 300 contains(String key)301 public boolean contains(String key) { 302 return contains(key, UID_SELF); 303 } 304 305 /** 306 * List all entries in the keystore for {@code uid} starting with {@code prefix}. 307 */ list(String prefix, int uid)308 public String[] list(String prefix, int uid) { 309 try { 310 return mBinder.list(prefix, uid); 311 } catch (RemoteException e) { 312 Log.w(TAG, "Cannot connect to keystore", e); 313 return null; 314 } catch (android.os.ServiceSpecificException e) { 315 Log.w(TAG, "KeyStore exception", e); 316 return null; 317 } 318 } 319 320 /** 321 * List uids of all keys that are auth bound to the current user. 322 * Only system is allowed to call this method. 323 */ 324 @UnsupportedAppUsage listUidsOfAuthBoundKeys()325 public int[] listUidsOfAuthBoundKeys() { 326 // uids are returned as a list of strings because list of integers 327 // as an output parameter is not supported by aidl-cpp. 328 List<String> uidsOut = new ArrayList<>(); 329 try { 330 int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut); 331 if (rc != NO_ERROR) { 332 Log.w(TAG, String.format("listUidsOfAuthBoundKeys failed with error code %d", rc)); 333 return null; 334 } 335 } catch (RemoteException e) { 336 Log.w(TAG, "Cannot connect to keystore", e); 337 return null; 338 } catch (android.os.ServiceSpecificException e) { 339 Log.w(TAG, "KeyStore exception", e); 340 return null; 341 } 342 // Turn list of strings into an array of uid integers. 343 return uidsOut.stream().mapToInt(Integer::parseInt).toArray(); 344 } 345 list(String prefix)346 public String[] list(String prefix) { 347 return list(prefix, UID_SELF); 348 } 349 350 /** 351 * Attempt to lock the keystore for {@code user}. 352 * 353 * @param userId Android user to lock. 354 * @return whether {@code user}'s keystore was locked. 355 */ lock(int userId)356 public boolean lock(int userId) { 357 try { 358 return mBinder.lock(userId) == NO_ERROR; 359 } catch (RemoteException e) { 360 Log.w(TAG, "Cannot connect to keystore", e); 361 return false; 362 } 363 } 364 lock()365 public boolean lock() { 366 return lock(UserHandle.myUserId()); 367 } 368 369 /** 370 * Attempt to unlock the keystore for {@code user} with the password {@code password}. 371 * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or 372 * created. 373 * 374 * @param userId Android user ID to operate on 375 * @param password user's keystore password. Should be the most recent value passed to 376 * {@link #onUserPasswordChanged} for the user. 377 * 378 * @return whether the keystore was unlocked. 379 */ unlock(int userId, String password)380 public boolean unlock(int userId, String password) { 381 try { 382 password = password != null ? password : ""; 383 mError = mBinder.unlock(userId, password); 384 return mError == NO_ERROR; 385 } catch (RemoteException e) { 386 Log.w(TAG, "Cannot connect to keystore", e); 387 return false; 388 } 389 } 390 391 @UnsupportedAppUsage unlock(String password)392 public boolean unlock(String password) { 393 return unlock(UserHandle.getUserId(Process.myUid()), password); 394 } 395 396 /** 397 * Check if the keystore for {@code userId} is empty. 398 */ isEmpty(int userId)399 public boolean isEmpty(int userId) { 400 try { 401 return mBinder.isEmpty(userId) != 0; 402 } catch (RemoteException e) { 403 Log.w(TAG, "Cannot connect to keystore", e); 404 return false; 405 } 406 } 407 408 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) isEmpty()409 public boolean isEmpty() { 410 return isEmpty(UserHandle.myUserId()); 411 } 412 grant(String key, int uid)413 public String grant(String key, int uid) { 414 try { 415 String grantAlias = mBinder.grant(key, uid); 416 if (grantAlias == "") return null; 417 return grantAlias; 418 } catch (RemoteException e) { 419 Log.w(TAG, "Cannot connect to keystore", e); 420 return null; 421 } 422 } 423 ungrant(String key, int uid)424 public boolean ungrant(String key, int uid) { 425 try { 426 return mBinder.ungrant(key, uid) == NO_ERROR; 427 } catch (RemoteException e) { 428 Log.w(TAG, "Cannot connect to keystore", e); 429 return false; 430 } 431 } 432 433 /** 434 * Returns the last modification time of the key in milliseconds since the 435 * epoch. Will return -1L if the key could not be found or other error. 436 */ getmtime(String key, int uid)437 public long getmtime(String key, int uid) { 438 try { 439 final long millis = mBinder.getmtime(key, uid); 440 if (millis == -1L) { 441 return -1L; 442 } 443 444 return millis * 1000L; 445 } catch (RemoteException e) { 446 Log.w(TAG, "Cannot connect to keystore", e); 447 return -1L; 448 } 449 } 450 getmtime(String key)451 public long getmtime(String key) { 452 return getmtime(key, UID_SELF); 453 } 454 455 // TODO: remove this when it's removed from Settings isHardwareBacked()456 public boolean isHardwareBacked() { 457 return isHardwareBacked("RSA"); 458 } 459 isHardwareBacked(String keyType)460 public boolean isHardwareBacked(String keyType) { 461 try { 462 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR; 463 } catch (RemoteException e) { 464 Log.w(TAG, "Cannot connect to keystore", e); 465 return false; 466 } 467 } 468 clearUid(int uid)469 public boolean clearUid(int uid) { 470 try { 471 return mBinder.clear_uid(uid) == NO_ERROR; 472 } catch (RemoteException e) { 473 Log.w(TAG, "Cannot connect to keystore", e); 474 return false; 475 } 476 } 477 getLastError()478 public int getLastError() { 479 return mError; 480 } 481 addRngEntropy(byte[] data, int flags)482 public boolean addRngEntropy(byte[] data, int flags) { 483 KeystoreResultPromise promise = new KeystoreResultPromise(); 484 try { 485 mBinder.asBinder().linkToDeath(promise, 0); 486 int errorCode = mBinder.addRngEntropy(promise, data, flags); 487 if (errorCode == NO_ERROR) { 488 return interruptedPreservingGet(promise.getFuture()).getErrorCode() == NO_ERROR; 489 } else { 490 return false; 491 } 492 } catch (RemoteException e) { 493 Log.w(TAG, "Cannot connect to keystore", e); 494 return false; 495 } catch (ExecutionException e) { 496 Log.e(TAG, "AddRngEntropy completed with exception", e); 497 return false; 498 } finally { 499 mBinder.asBinder().unlinkToDeath(promise, 0); 500 } 501 } 502 503 private class KeyCharacteristicsCallbackResult { 504 private KeystoreResponse keystoreResponse; 505 private KeyCharacteristics keyCharacteristics; 506 KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse, KeyCharacteristics keyCharacteristics)507 public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse, 508 KeyCharacteristics keyCharacteristics) { 509 this.keystoreResponse = keystoreResponse; 510 this.keyCharacteristics = keyCharacteristics; 511 } 512 getKeystoreResponse()513 public KeystoreResponse getKeystoreResponse() { 514 return keystoreResponse; 515 } 516 setKeystoreResponse(KeystoreResponse keystoreResponse)517 public void setKeystoreResponse(KeystoreResponse keystoreResponse) { 518 this.keystoreResponse = keystoreResponse; 519 } 520 getKeyCharacteristics()521 public KeyCharacteristics getKeyCharacteristics() { 522 return keyCharacteristics; 523 } 524 setKeyCharacteristics(KeyCharacteristics keyCharacteristics)525 public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) { 526 this.keyCharacteristics = keyCharacteristics; 527 } 528 } 529 530 private class KeyCharacteristicsPromise 531 extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub 532 implements IBinder.DeathRecipient { 533 final private CompletableFuture<KeyCharacteristicsCallbackResult> future = 534 new CompletableFuture<KeyCharacteristicsCallbackResult>(); 535 @Override onFinished(KeystoreResponse keystoreResponse, KeyCharacteristics keyCharacteristics)536 public void onFinished(KeystoreResponse keystoreResponse, 537 KeyCharacteristics keyCharacteristics) 538 throws android.os.RemoteException { 539 future.complete( 540 new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics)); 541 } getFuture()542 public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() { 543 return future; 544 } 545 @Override binderDied()546 public void binderDied() { 547 future.completeExceptionally(new RemoteException("Keystore died")); 548 } 549 }; 550 generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid, int flags, KeyCharacteristics outCharacteristics)551 private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid, 552 int flags, KeyCharacteristics outCharacteristics) 553 throws RemoteException, ExecutionException { 554 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise(); 555 int error = NO_ERROR; 556 KeyCharacteristicsCallbackResult result = null; 557 try { 558 mBinder.asBinder().linkToDeath(promise, 0); 559 error = mBinder.generateKey(promise, alias, args, entropy, uid, flags); 560 if (error != NO_ERROR) { 561 Log.e(TAG, "generateKeyInternal failed on request " + error); 562 return error; 563 } 564 result = interruptedPreservingGet(promise.getFuture()); 565 } finally { 566 mBinder.asBinder().unlinkToDeath(promise, 0); 567 } 568 569 error = result.getKeystoreResponse().getErrorCode(); 570 if (error != NO_ERROR) { 571 Log.e(TAG, "generateKeyInternal failed on response " + error); 572 return error; 573 } 574 KeyCharacteristics characteristics = result.getKeyCharacteristics(); 575 if (characteristics == null) { 576 Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error); 577 return SYSTEM_ERROR; 578 } 579 outCharacteristics.shallowCopyFrom(characteristics); 580 return NO_ERROR; 581 } 582 generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid, int flags, KeyCharacteristics outCharacteristics)583 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid, 584 int flags, KeyCharacteristics outCharacteristics) { 585 try { 586 entropy = entropy != null ? entropy : new byte[0]; 587 args = args != null ? args : new KeymasterArguments(); 588 int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics); 589 if (error == KEY_ALREADY_EXISTS) { 590 mBinder.del(alias, uid); 591 error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics); 592 } 593 return error; 594 } catch (RemoteException e) { 595 Log.w(TAG, "Cannot connect to keystore", e); 596 return SYSTEM_ERROR; 597 } catch (ExecutionException e) { 598 Log.e(TAG, "generateKey completed with exception", e); 599 return SYSTEM_ERROR; 600 } 601 } 602 generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags, KeyCharacteristics outCharacteristics)603 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags, 604 KeyCharacteristics outCharacteristics) { 605 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics); 606 } 607 getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, int uid, KeyCharacteristics outCharacteristics)608 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, 609 int uid, KeyCharacteristics outCharacteristics) { 610 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise(); 611 try { 612 mBinder.asBinder().linkToDeath(promise, 0); 613 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]); 614 appId = appId != null ? appId : new KeymasterBlob(new byte[0]); 615 616 int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid); 617 if (error != NO_ERROR) return error; 618 619 KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture()); 620 error = result.getKeystoreResponse().getErrorCode(); 621 if (error != NO_ERROR) return error; 622 623 KeyCharacteristics characteristics = result.getKeyCharacteristics(); 624 if (characteristics == null) return SYSTEM_ERROR; 625 outCharacteristics.shallowCopyFrom(characteristics); 626 return NO_ERROR; 627 } catch (RemoteException e) { 628 Log.w(TAG, "Cannot connect to keystore", e); 629 return SYSTEM_ERROR; 630 } catch (ExecutionException e) { 631 Log.e(TAG, "GetKeyCharacteristics completed with exception", e); 632 return SYSTEM_ERROR; 633 } finally { 634 mBinder.asBinder().unlinkToDeath(promise, 0); 635 } 636 } 637 getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, KeyCharacteristics outCharacteristics)638 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, 639 KeyCharacteristics outCharacteristics) { 640 return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics); 641 } 642 importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData, int uid, int flags, KeyCharacteristics outCharacteristics)643 private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData, 644 int uid, int flags, KeyCharacteristics outCharacteristics) 645 throws RemoteException, ExecutionException { 646 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise(); 647 mBinder.asBinder().linkToDeath(promise, 0); 648 try { 649 int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags); 650 if (error != NO_ERROR) return error; 651 652 KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture()); 653 654 error = result.getKeystoreResponse().getErrorCode(); 655 if (error != NO_ERROR) return error; 656 657 KeyCharacteristics characteristics = result.getKeyCharacteristics(); 658 if (characteristics == null) return SYSTEM_ERROR; 659 outCharacteristics.shallowCopyFrom(characteristics); 660 return NO_ERROR; 661 } finally { 662 mBinder.asBinder().unlinkToDeath(promise, 0); 663 } 664 } 665 importKey(String alias, KeymasterArguments args, int format, byte[] keyData, int uid, int flags, KeyCharacteristics outCharacteristics)666 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 667 int uid, int flags, KeyCharacteristics outCharacteristics) { 668 try { 669 int error = importKeyInternal(alias, args, format, keyData, uid, flags, 670 outCharacteristics); 671 if (error == KEY_ALREADY_EXISTS) { 672 mBinder.del(alias, uid); 673 error = importKeyInternal(alias, args, format, keyData, uid, flags, 674 outCharacteristics); 675 } 676 return error; 677 } catch (RemoteException e) { 678 Log.w(TAG, "Cannot connect to keystore", e); 679 return SYSTEM_ERROR; 680 } catch (ExecutionException e) { 681 Log.e(TAG, "ImportKey completed with exception", e); 682 return SYSTEM_ERROR; 683 } 684 } 685 importKey(String alias, KeymasterArguments args, int format, byte[] keyData, int flags, KeyCharacteristics outCharacteristics)686 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 687 int flags, KeyCharacteristics outCharacteristics) { 688 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics); 689 } 690 getAlgorithmFromPKCS8(byte[] keyData)691 private String getAlgorithmFromPKCS8(byte[] keyData) { 692 try { 693 final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData)); 694 final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject()); 695 final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId(); 696 return new AlgorithmId(new ObjectIdentifier(algOid)).getName(); 697 } catch (IOException e) { 698 Log.e(TAG, "getAlgorithmFromPKCS8 Failed to parse key data"); 699 Log.e(TAG, Log.getStackTraceString(e)); 700 return null; 701 } 702 } 703 makeLegacyArguments(String algorithm)704 private KeymasterArguments makeLegacyArguments(String algorithm) { 705 KeymasterArguments args = new KeymasterArguments(); 706 args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, 707 KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(algorithm)); 708 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN); 709 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_VERIFY); 710 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT); 711 args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT); 712 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE); 713 if (algorithm.equalsIgnoreCase(KeyProperties.KEY_ALGORITHM_RSA)) { 714 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP); 715 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT); 716 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN); 717 args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PSS); 718 } 719 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE); 720 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5); 721 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1); 722 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224); 723 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256); 724 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384); 725 args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512); 726 args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); 727 args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, new Date(Long.MAX_VALUE)); 728 args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, new Date(Long.MAX_VALUE)); 729 args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, new Date(0)); 730 return args; 731 } 732 importKey(String alias, byte[] keyData, int uid, int flags)733 public boolean importKey(String alias, byte[] keyData, int uid, int flags) { 734 String algorithm = getAlgorithmFromPKCS8(keyData); 735 if (algorithm == null) return false; 736 KeymasterArguments args = makeLegacyArguments(algorithm); 737 KeyCharacteristics out = new KeyCharacteristics(); 738 int result = importKey(alias, args, KeymasterDefs.KM_KEY_FORMAT_PKCS8, keyData, uid, 739 flags, out); 740 if (result != NO_ERROR) { 741 Log.e(TAG, Log.getStackTraceString( 742 new KeyStoreException(result, "legacy key import failed"))); 743 return false; 744 } 745 return true; 746 } 747 importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey, String wrappingKeyAlias, byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, KeyCharacteristics outCharacteristics)748 private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey, 749 String wrappingKeyAlias, 750 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, 751 KeyCharacteristics outCharacteristics) 752 throws RemoteException, ExecutionException { 753 KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise(); 754 mBinder.asBinder().linkToDeath(promise, 0); 755 try { 756 int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, 757 wrappingKeyAlias, maskingKey, args, rootSid, fingerprintSid); 758 if (error != NO_ERROR) return error; 759 760 KeyCharacteristicsCallbackResult result = interruptedPreservingGet(promise.getFuture()); 761 762 error = result.getKeystoreResponse().getErrorCode(); 763 if (error != NO_ERROR) return error; 764 765 KeyCharacteristics characteristics = result.getKeyCharacteristics(); 766 if (characteristics == null) return SYSTEM_ERROR; 767 outCharacteristics.shallowCopyFrom(characteristics); 768 return NO_ERROR; 769 } finally { 770 mBinder.asBinder().unlinkToDeath(promise, 0); 771 } 772 } 773 importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey, String wrappingKeyAlias, byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid, KeyCharacteristics outCharacteristics)774 public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey, 775 String wrappingKeyAlias, 776 byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid, 777 KeyCharacteristics outCharacteristics) { 778 // TODO b/119217337 uid parameter gets silently ignored. 779 try { 780 int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias, 781 maskingKey, args, rootSid, fingerprintSid, outCharacteristics); 782 if (error == KEY_ALREADY_EXISTS) { 783 mBinder.del(wrappedKeyAlias, UID_SELF); 784 error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias, 785 maskingKey, args, rootSid, fingerprintSid, outCharacteristics); 786 } 787 return error; 788 } catch (RemoteException e) { 789 Log.w(TAG, "Cannot connect to keystore", e); 790 return SYSTEM_ERROR; 791 } catch (ExecutionException e) { 792 Log.e(TAG, "ImportWrappedKey completed with exception", e); 793 return SYSTEM_ERROR; 794 } 795 } 796 797 private class ExportKeyPromise 798 extends android.security.keystore.IKeystoreExportKeyCallback.Stub 799 implements IBinder.DeathRecipient { 800 final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>(); 801 @Override onFinished(ExportResult exportKeyResult)802 public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException { 803 future.complete(exportKeyResult); 804 } getFuture()805 public final CompletableFuture<ExportResult> getFuture() { 806 return future; 807 } 808 @Override binderDied()809 public void binderDied() { 810 future.completeExceptionally(new RemoteException("Keystore died")); 811 } 812 }; 813 exportKey(String alias, int format, KeymasterBlob clientId, KeymasterBlob appId, int uid)814 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId, 815 KeymasterBlob appId, int uid) { 816 ExportKeyPromise promise = new ExportKeyPromise(); 817 try { 818 mBinder.asBinder().linkToDeath(promise, 0); 819 clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]); 820 appId = appId != null ? appId : new KeymasterBlob(new byte[0]); 821 int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid); 822 if (error == NO_ERROR) { 823 return interruptedPreservingGet(promise.getFuture()); 824 } else { 825 return new ExportResult(error); 826 } 827 } catch (RemoteException e) { 828 Log.w(TAG, "Cannot connect to keystore", e); 829 return null; 830 } catch (ExecutionException e) { 831 Log.e(TAG, "ExportKey completed with exception", e); 832 return null; 833 } finally { 834 mBinder.asBinder().unlinkToDeath(promise, 0); 835 } 836 } exportKey(String alias, int format, KeymasterBlob clientId, KeymasterBlob appId)837 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId, 838 KeymasterBlob appId) { 839 return exportKey(alias, format, clientId, appId, UID_SELF); 840 } 841 842 private class OperationPromise 843 extends android.security.keystore.IKeystoreOperationResultCallback.Stub 844 implements IBinder.DeathRecipient { 845 final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>(); 846 @Override onFinished(OperationResult operationResult)847 public void onFinished(OperationResult operationResult) throws android.os.RemoteException { 848 future.complete(operationResult); 849 } getFuture()850 public final CompletableFuture<OperationResult> getFuture() { 851 return future; 852 } 853 @Override binderDied()854 public void binderDied() { 855 future.completeExceptionally(new RemoteException("Keystore died")); 856 } 857 }; 858 begin(String alias, int purpose, boolean pruneable, KeymasterArguments args, byte[] entropy, int uid)859 public OperationResult begin(String alias, int purpose, boolean pruneable, 860 KeymasterArguments args, byte[] entropy, int uid) { 861 OperationPromise promise = new OperationPromise(); 862 try { 863 mBinder.asBinder().linkToDeath(promise, 0); 864 args = args != null ? args : new KeymasterArguments(); 865 entropy = entropy != null ? entropy : new byte[0]; 866 int errorCode = mBinder.begin(promise, getToken(), alias, purpose, pruneable, args, 867 entropy, uid); 868 if (errorCode == NO_ERROR) { 869 return interruptedPreservingGet(promise.getFuture()); 870 } else { 871 return new OperationResult(errorCode); 872 } 873 } catch (RemoteException e) { 874 Log.w(TAG, "Cannot connect to keystore", e); 875 return null; 876 } catch (ExecutionException e) { 877 Log.e(TAG, "Begin completed with exception", e); 878 return null; 879 } finally { 880 mBinder.asBinder().unlinkToDeath(promise, 0); 881 } 882 } 883 begin(String alias, int purpose, boolean pruneable, KeymasterArguments args, byte[] entropy)884 public OperationResult begin(String alias, int purpose, boolean pruneable, 885 KeymasterArguments args, byte[] entropy) { 886 entropy = entropy != null ? entropy : new byte[0]; 887 args = args != null ? args : new KeymasterArguments(); 888 return begin(alias, purpose, pruneable, args, entropy, UID_SELF); 889 } 890 update(IBinder token, KeymasterArguments arguments, byte[] input)891 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) { 892 OperationPromise promise = new OperationPromise(); 893 try { 894 mBinder.asBinder().linkToDeath(promise, 0); 895 arguments = arguments != null ? arguments : new KeymasterArguments(); 896 input = input != null ? input : new byte[0]; 897 int errorCode = mBinder.update(promise, token, arguments, input); 898 if (errorCode == NO_ERROR) { 899 return interruptedPreservingGet(promise.getFuture()); 900 } else { 901 return new OperationResult(errorCode); 902 } 903 } catch (RemoteException e) { 904 Log.w(TAG, "Cannot connect to keystore", e); 905 return null; 906 } catch (ExecutionException e) { 907 Log.e(TAG, "Update completed with exception", e); 908 return null; 909 } finally { 910 mBinder.asBinder().unlinkToDeath(promise, 0); 911 } 912 } 913 914 /** 915 * Android KeyStore finish operation. 916 * 917 * @param token Authentication token. 918 * @param arguments Keymaster arguments 919 * @param input Optional additional input data. 920 * @param signature Optional signature to be verified. 921 * @param entropy Optional additional entropy 922 * @return OperationResult that will indicate success or error of the operation. 923 */ finish(IBinder token, KeymasterArguments arguments, byte[] input, byte[] signature, byte[] entropy)924 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] input, 925 byte[] signature, byte[] entropy) { 926 OperationPromise promise = new OperationPromise(); 927 try { 928 mBinder.asBinder().linkToDeath(promise, 0); 929 arguments = arguments != null ? arguments : new KeymasterArguments(); 930 entropy = entropy != null ? entropy : new byte[0]; 931 input = input != null ? input : new byte[0]; 932 signature = signature != null ? signature : new byte[0]; 933 int errorCode = mBinder.finish(promise, token, arguments, input, signature, entropy); 934 if (errorCode == NO_ERROR) { 935 return interruptedPreservingGet(promise.getFuture()); 936 } else { 937 return new OperationResult(errorCode); 938 } 939 } catch (RemoteException e) { 940 Log.w(TAG, "Cannot connect to keystore", e); 941 return null; 942 } catch (ExecutionException e) { 943 Log.e(TAG, "Finish completed with exception", e); 944 return null; 945 } finally { 946 mBinder.asBinder().unlinkToDeath(promise, 0); 947 } 948 } 949 finish(IBinder token, KeymasterArguments arguments, byte[] signature)950 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) { 951 return finish(token, arguments, null, signature, null); 952 } 953 954 private class KeystoreResultPromise 955 extends android.security.keystore.IKeystoreResponseCallback.Stub 956 implements IBinder.DeathRecipient { 957 final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>(); 958 @Override onFinished(KeystoreResponse keystoreResponse)959 public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException { 960 future.complete(keystoreResponse); 961 } getFuture()962 public final CompletableFuture<KeystoreResponse> getFuture() { 963 return future; 964 } 965 @Override binderDied()966 public void binderDied() { 967 future.completeExceptionally(new RemoteException("Keystore died")); 968 } 969 }; 970 abort(IBinder token)971 public int abort(IBinder token) { 972 KeystoreResultPromise promise = new KeystoreResultPromise(); 973 try { 974 mBinder.asBinder().linkToDeath(promise, 0); 975 int errorCode = mBinder.abort(promise, token); 976 if (errorCode == NO_ERROR) { 977 return interruptedPreservingGet(promise.getFuture()).getErrorCode(); 978 } else { 979 return errorCode; 980 } 981 } catch (RemoteException e) { 982 Log.w(TAG, "Cannot connect to keystore", e); 983 return SYSTEM_ERROR; 984 } catch (ExecutionException e) { 985 Log.e(TAG, "Abort completed with exception", e); 986 return SYSTEM_ERROR; 987 } finally { 988 mBinder.asBinder().unlinkToDeath(promise, 0); 989 } 990 } 991 992 /** 993 * Add an authentication record to the keystore authorization table. 994 * 995 * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster. 996 * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to 997 * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode. 998 */ addAuthToken(byte[] authToken)999 public int addAuthToken(byte[] authToken) { 1000 try { 1001 return mBinder.addAuthToken(authToken); 1002 } catch (RemoteException e) { 1003 Log.w(TAG, "Cannot connect to keystore", e); 1004 return SYSTEM_ERROR; 1005 } 1006 } 1007 1008 /** 1009 * Notify keystore that a user's password has changed. 1010 * 1011 * @param userId the user whose password changed. 1012 * @param newPassword the new password or "" if the password was removed. 1013 */ onUserPasswordChanged(int userId, String newPassword)1014 public boolean onUserPasswordChanged(int userId, String newPassword) { 1015 // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that 1016 // explicit here. 1017 if (newPassword == null) { 1018 newPassword = ""; 1019 } 1020 try { 1021 return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR; 1022 } catch (RemoteException e) { 1023 Log.w(TAG, "Cannot connect to keystore", e); 1024 return false; 1025 } 1026 } 1027 1028 /** 1029 * Notify keystore that a user was added. 1030 * 1031 * @param userId the new user. 1032 * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is 1033 * specified then the new user's keystore will be intialized with the same secure lockscreen 1034 * password as the parent. 1035 */ onUserAdded(int userId, int parentId)1036 public void onUserAdded(int userId, int parentId) { 1037 try { 1038 mBinder.onUserAdded(userId, parentId); 1039 } catch (RemoteException e) { 1040 Log.w(TAG, "Cannot connect to keystore", e); 1041 } 1042 } 1043 1044 /** 1045 * Notify keystore that a user was added. 1046 * 1047 * @param userId the new user. 1048 */ onUserAdded(int userId)1049 public void onUserAdded(int userId) { 1050 onUserAdded(userId, -1); 1051 } 1052 1053 /** 1054 * Notify keystore that a user was removed. 1055 * 1056 * @param userId the removed user. 1057 */ onUserRemoved(int userId)1058 public void onUserRemoved(int userId) { 1059 try { 1060 mBinder.onUserRemoved(userId); 1061 } catch (RemoteException e) { 1062 Log.w(TAG, "Cannot connect to keystore", e); 1063 } 1064 } 1065 onUserPasswordChanged(String newPassword)1066 public boolean onUserPasswordChanged(String newPassword) { 1067 return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword); 1068 } 1069 1070 /** 1071 * Notify keystore about the latest user locked state. This is to support keyguard-bound key. 1072 */ onUserLockedStateChanged(int userHandle, boolean locked)1073 public void onUserLockedStateChanged(int userHandle, boolean locked) { 1074 try { 1075 mBinder.onKeyguardVisibilityChanged(locked, userHandle); 1076 } catch (RemoteException e) { 1077 Log.w(TAG, "Failed to update user locked state " + userHandle, e); 1078 } 1079 } 1080 1081 private class KeyAttestationCallbackResult { 1082 private KeystoreResponse keystoreResponse; 1083 private KeymasterCertificateChain certificateChain; 1084 KeyAttestationCallbackResult(KeystoreResponse keystoreResponse, KeymasterCertificateChain certificateChain)1085 public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse, 1086 KeymasterCertificateChain certificateChain) { 1087 this.keystoreResponse = keystoreResponse; 1088 this.certificateChain = certificateChain; 1089 } 1090 getKeystoreResponse()1091 public KeystoreResponse getKeystoreResponse() { 1092 return keystoreResponse; 1093 } 1094 setKeystoreResponse(KeystoreResponse keystoreResponse)1095 public void setKeystoreResponse(KeystoreResponse keystoreResponse) { 1096 this.keystoreResponse = keystoreResponse; 1097 } 1098 getCertificateChain()1099 public KeymasterCertificateChain getCertificateChain() { 1100 return certificateChain; 1101 } 1102 setCertificateChain(KeymasterCertificateChain certificateChain)1103 public void setCertificateChain(KeymasterCertificateChain certificateChain) { 1104 this.certificateChain = certificateChain; 1105 } 1106 } 1107 1108 private class CertificateChainPromise 1109 extends android.security.keystore.IKeystoreCertificateChainCallback.Stub 1110 implements IBinder.DeathRecipient { 1111 final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>(); 1112 @Override onFinished(KeystoreResponse keystoreResponse, KeymasterCertificateChain certificateChain)1113 public void onFinished(KeystoreResponse keystoreResponse, 1114 KeymasterCertificateChain certificateChain) throws android.os.RemoteException { 1115 future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain)); 1116 } getFuture()1117 public final CompletableFuture<KeyAttestationCallbackResult> getFuture() { 1118 return future; 1119 } 1120 @Override binderDied()1121 public void binderDied() { 1122 future.completeExceptionally(new RemoteException("Keystore died")); 1123 } 1124 }; 1125 1126 attestKey( String alias, KeymasterArguments params, KeymasterCertificateChain outChain)1127 public int attestKey( 1128 String alias, KeymasterArguments params, KeymasterCertificateChain outChain) { 1129 CertificateChainPromise promise = new CertificateChainPromise(); 1130 try { 1131 mBinder.asBinder().linkToDeath(promise, 0); 1132 if (params == null) { 1133 params = new KeymasterArguments(); 1134 } 1135 if (outChain == null) { 1136 outChain = new KeymasterCertificateChain(); 1137 } 1138 int error = mBinder.attestKey(promise, alias, params); 1139 if (error != NO_ERROR) return error; 1140 KeyAttestationCallbackResult result = interruptedPreservingGet(promise.getFuture()); 1141 error = result.getKeystoreResponse().getErrorCode(); 1142 if (error == NO_ERROR) { 1143 outChain.shallowCopyFrom(result.getCertificateChain()); 1144 } 1145 return error; 1146 } catch (RemoteException e) { 1147 Log.w(TAG, "Cannot connect to keystore", e); 1148 return SYSTEM_ERROR; 1149 } catch (ExecutionException e) { 1150 Log.e(TAG, "AttestKey completed with exception", e); 1151 return SYSTEM_ERROR; 1152 } finally { 1153 mBinder.asBinder().unlinkToDeath(promise, 0); 1154 } 1155 } 1156 attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain)1157 public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) { 1158 CertificateChainPromise promise = new CertificateChainPromise(); 1159 try { 1160 mBinder.asBinder().linkToDeath(promise, 0); 1161 if (params == null) { 1162 params = new KeymasterArguments(); 1163 } 1164 if (outChain == null) { 1165 outChain = new KeymasterCertificateChain(); 1166 } 1167 int error = mBinder.attestDeviceIds(promise, params); 1168 if (error != NO_ERROR) return error; 1169 KeyAttestationCallbackResult result = interruptedPreservingGet(promise.getFuture()); 1170 error = result.getKeystoreResponse().getErrorCode(); 1171 if (error == NO_ERROR) { 1172 outChain.shallowCopyFrom(result.getCertificateChain()); 1173 } 1174 return error; 1175 } catch (RemoteException e) { 1176 Log.w(TAG, "Cannot connect to keystore", e); 1177 return SYSTEM_ERROR; 1178 } catch (ExecutionException e) { 1179 Log.e(TAG, "AttestDevicdeIds completed with exception", e); 1180 return SYSTEM_ERROR; 1181 } finally { 1182 mBinder.asBinder().unlinkToDeath(promise, 0); 1183 } 1184 } 1185 1186 /** 1187 * Notify keystore that the device went off-body. 1188 */ onDeviceOffBody()1189 public void onDeviceOffBody() { 1190 try { 1191 mBinder.onDeviceOffBody(); 1192 } catch (RemoteException e) { 1193 Log.w(TAG, "Cannot connect to keystore", e); 1194 } 1195 } 1196 1197 // Keep in sync with confirmationui/1.0/types.hal. 1198 public static final int CONFIRMATIONUI_OK = 0; 1199 public static final int CONFIRMATIONUI_CANCELED = 1; 1200 public static final int CONFIRMATIONUI_ABORTED = 2; 1201 public static final int CONFIRMATIONUI_OPERATION_PENDING = 3; 1202 public static final int CONFIRMATIONUI_IGNORED = 4; 1203 public static final int CONFIRMATIONUI_SYSTEM_ERROR = 5; 1204 public static final int CONFIRMATIONUI_UNIMPLEMENTED = 6; 1205 public static final int CONFIRMATIONUI_UNEXPECTED = 7; 1206 public static final int CONFIRMATIONUI_UIERROR = 0x10000; 1207 public static final int CONFIRMATIONUI_UIERROR_MISSING_GLYPH = 0x10001; 1208 public static final int CONFIRMATIONUI_UIERROR_MESSAGE_TOO_LONG = 0x10002; 1209 public static final int CONFIRMATIONUI_UIERROR_MALFORMED_UTF8_ENCODING = 0x10003; 1210 1211 /** 1212 * Requests keystore call into the confirmationui HAL to display a prompt. 1213 * 1214 * @param listener the binder to use for callbacks. 1215 * @param promptText the prompt to display. 1216 * @param extraData extra data / nonce from application. 1217 * @param locale the locale as a BCP 47 langauge tag. 1218 * @param uiOptionsAsFlags the UI options to use, as flags. 1219 * @return one of the {@code CONFIRMATIONUI_*} constants, for 1220 * example {@code KeyStore.CONFIRMATIONUI_OK}. 1221 */ presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData, String locale, int uiOptionsAsFlags)1222 public int presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData, 1223 String locale, int uiOptionsAsFlags) { 1224 try { 1225 return mBinder.presentConfirmationPrompt(listener, promptText, extraData, locale, 1226 uiOptionsAsFlags); 1227 } catch (RemoteException e) { 1228 Log.w(TAG, "Cannot connect to keystore", e); 1229 return CONFIRMATIONUI_SYSTEM_ERROR; 1230 } 1231 } 1232 1233 /** 1234 * Requests keystore call into the confirmationui HAL to cancel displaying a prompt. 1235 * 1236 * @param listener the binder passed to the {@link #presentConfirmationPrompt} method. 1237 * @return one of the {@code CONFIRMATIONUI_*} constants, for 1238 * example {@code KeyStore.CONFIRMATIONUI_OK}. 1239 */ cancelConfirmationPrompt(IBinder listener)1240 public int cancelConfirmationPrompt(IBinder listener) { 1241 try { 1242 return mBinder.cancelConfirmationPrompt(listener); 1243 } catch (RemoteException e) { 1244 Log.w(TAG, "Cannot connect to keystore", e); 1245 return CONFIRMATIONUI_SYSTEM_ERROR; 1246 } 1247 } 1248 1249 /** 1250 * Requests keystore to check if the confirmationui HAL is available. 1251 * 1252 * @return whether the confirmationUI HAL is available. 1253 */ isConfirmationPromptSupported()1254 public boolean isConfirmationPromptSupported() { 1255 try { 1256 return mBinder.isConfirmationPromptSupported(); 1257 } catch (RemoteException e) { 1258 Log.w(TAG, "Cannot connect to keystore", e); 1259 return false; 1260 } 1261 } 1262 1263 /** 1264 * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error 1265 * code. 1266 */ 1267 @UnsupportedAppUsage getKeyStoreException(int errorCode)1268 public static KeyStoreException getKeyStoreException(int errorCode) { 1269 if (errorCode > 0) { 1270 // KeyStore layer error 1271 switch (errorCode) { 1272 case NO_ERROR: 1273 return new KeyStoreException(errorCode, "OK"); 1274 case LOCKED: 1275 return new KeyStoreException(errorCode, "User authentication required"); 1276 case UNINITIALIZED: 1277 return new KeyStoreException(errorCode, "Keystore not initialized"); 1278 case SYSTEM_ERROR: 1279 return new KeyStoreException(errorCode, "System error"); 1280 case PERMISSION_DENIED: 1281 return new KeyStoreException(errorCode, "Permission denied"); 1282 case KEY_NOT_FOUND: 1283 return new KeyStoreException(errorCode, "Key not found"); 1284 case VALUE_CORRUPTED: 1285 return new KeyStoreException(errorCode, "Key blob corrupted"); 1286 case OP_AUTH_NEEDED: 1287 return new KeyStoreException(errorCode, "Operation requires authorization"); 1288 case KEY_PERMANENTLY_INVALIDATED: 1289 return new KeyStoreException(errorCode, "Key permanently invalidated"); 1290 default: 1291 return new KeyStoreException(errorCode, String.valueOf(errorCode)); 1292 } 1293 } else { 1294 // Keymaster layer error 1295 switch (errorCode) { 1296 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT: 1297 // The name of this parameter significantly differs between Keymaster and 1298 // framework APIs. Use the framework wording to make life easier for developers. 1299 return new KeyStoreException(errorCode, 1300 "Invalid user authentication validity duration"); 1301 default: 1302 return new KeyStoreException(errorCode, 1303 KeymasterDefs.getErrorMessage(errorCode)); 1304 } 1305 } 1306 } 1307 1308 /** 1309 * Returns an {@link InvalidKeyException} corresponding to the provided 1310 * {@link KeyStoreException}. 1311 */ getInvalidKeyException( String keystoreKeyAlias, int uid, KeyStoreException e)1312 public InvalidKeyException getInvalidKeyException( 1313 String keystoreKeyAlias, int uid, KeyStoreException e) { 1314 switch (e.getErrorCode()) { 1315 case LOCKED: 1316 return new UserNotAuthenticatedException(); 1317 case KeymasterDefs.KM_ERROR_KEY_EXPIRED: 1318 return new KeyExpiredException(); 1319 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: 1320 return new KeyNotYetValidException(); 1321 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: 1322 case OP_AUTH_NEEDED: 1323 { 1324 // We now need to determine whether the key/operation can become usable if user 1325 // authentication is performed, or whether it can never become usable again. 1326 // User authentication requirements are contained in the key's characteristics. We 1327 // need to check whether these requirements can be be satisfied by asking the user 1328 // to authenticate. 1329 KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); 1330 int getKeyCharacteristicsErrorCode = 1331 getKeyCharacteristics(keystoreKeyAlias, null, null, uid, 1332 keyCharacteristics); 1333 if (getKeyCharacteristicsErrorCode != NO_ERROR) { 1334 return new InvalidKeyException( 1335 "Failed to obtained key characteristics", 1336 getKeyStoreException(getKeyCharacteristicsErrorCode)); 1337 } 1338 List<BigInteger> keySids = 1339 keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID); 1340 if (keySids.isEmpty()) { 1341 // Key is not bound to any SIDs -- no amount of authentication will help here. 1342 return new KeyPermanentlyInvalidatedException(); 1343 } 1344 long rootSid = GateKeeper.getSecureUserId(); 1345 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) { 1346 // One of the key's SIDs is the current root SID -- user can be authenticated 1347 // against that SID. 1348 return new UserNotAuthenticatedException(); 1349 } 1350 1351 final long fingerprintOnlySid = getFingerprintOnlySid(); 1352 if ((fingerprintOnlySid != 0) 1353 && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) { 1354 // One of the key's SIDs is the current fingerprint SID -- user can be 1355 // authenticated against that SID. 1356 return new UserNotAuthenticatedException(); 1357 } 1358 1359 final long faceOnlySid = getFaceOnlySid(); 1360 if ((faceOnlySid != 0) 1361 && (keySids.contains(KeymasterArguments.toUint64(faceOnlySid)))) { 1362 // One of the key's SIDs is the current face SID -- user can be 1363 // authenticated against that SID. 1364 return new UserNotAuthenticatedException(); 1365 } 1366 1367 // None of the key's SIDs can ever be authenticated 1368 return new KeyPermanentlyInvalidatedException(); 1369 } 1370 case UNINITIALIZED: 1371 return new KeyPermanentlyInvalidatedException(); 1372 default: 1373 return new InvalidKeyException("Keystore operation failed", e); 1374 } 1375 } 1376 getFaceOnlySid()1377 private long getFaceOnlySid() { 1378 final PackageManager packageManager = mContext.getPackageManager(); 1379 if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) { 1380 return 0; 1381 } 1382 FaceManager faceManager = mContext.getSystemService(FaceManager.class); 1383 if (faceManager == null) { 1384 return 0; 1385 } 1386 1387 // TODO: Restore USE_BIOMETRIC or USE_BIOMETRIC_INTERNAL permission check in 1388 // FaceManager.getAuthenticatorId once the ID is no longer needed here. 1389 return faceManager.getAuthenticatorId(); 1390 } 1391 getFingerprintOnlySid()1392 private long getFingerprintOnlySid() { 1393 final PackageManager packageManager = mContext.getPackageManager(); 1394 if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 1395 return 0; 1396 } 1397 FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class); 1398 if (fingerprintManager == null) { 1399 return 0; 1400 } 1401 1402 // TODO: Restore USE_FINGERPRINT permission check in 1403 // FingerprintManager.getAuthenticatorId once the ID is no longer needed here. 1404 return fingerprintManager.getAuthenticatorId(); 1405 } 1406 1407 /** 1408 * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error 1409 * code. 1410 */ getInvalidKeyException(String keystoreKeyAlias, int uid, int errorCode)1411 public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid, 1412 int errorCode) { 1413 return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode)); 1414 } 1415 interruptedPreservingGet(CompletableFuture<R> future)1416 private static <R> R interruptedPreservingGet(CompletableFuture<R> future) 1417 throws ExecutionException { 1418 boolean wasInterrupted = false; 1419 while (true) { 1420 try { 1421 R result = future.get(); 1422 if (wasInterrupted) { 1423 Thread.currentThread().interrupt(); 1424 } 1425 return result; 1426 } catch (InterruptedException e) { 1427 wasInterrupted = true; 1428 } 1429 } 1430 } 1431 } 1432