diff options
| author | 2021-02-01 10:58:20 +0000 | |
|---|---|---|
| committer | 2021-02-23 09:32:47 +0000 | |
| commit | 42112e1e75b61cfbf27469025c39b6018cafb888 (patch) | |
| tree | c4bace7c15be4abc4f97293d45c55252ded65357 | |
| parent | 94bfa64f014711f79e04882d9deba545e2a11e96 (diff) | |
Credential management app follow ups
* KeyChain API to check if the caller is the
credential management app.
* KeyChain API to get the authentication policy
if the caller is the credential management app.
* KeyChain createManageCredentialsIntent docs
mention startActivityForResult should be used
Bug: 177979648
Test: atest android.devicepolicy.cts.CredentialManagementAppTest
Change-Id: Ia5125adb677ec103a9d5a5318edf95050e74916e
| -rw-r--r-- | core/api/current.txt | 2 | ||||
| -rw-r--r-- | keystore/java/android/security/IKeyChainService.aidl | 1 | ||||
| -rw-r--r-- | keystore/java/android/security/KeyChain.java | 58 |
3 files changed, 61 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 8fe79e6ee999..d98c9b06b44b 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -36783,8 +36783,10 @@ package android.security { method @NonNull public static android.content.Intent createInstallIntent(); method @NonNull public static android.content.Intent createManageCredentialsIntent(@NonNull android.security.AppUriAuthenticationPolicy); method @Nullable @WorkerThread public static java.security.cert.X509Certificate[] getCertificateChain(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException; + method @NonNull public static android.security.AppUriAuthenticationPolicy getCredentialManagementAppPolicy(@NonNull android.content.Context) throws java.lang.SecurityException; method @Nullable @WorkerThread public static java.security.PrivateKey getPrivateKey(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException; method @Deprecated public static boolean isBoundKeyAlgorithm(@NonNull String); + method public static boolean isCredentialManagementApp(@NonNull android.content.Context); method public static boolean isKeyAlgorithmSupported(@NonNull String); field public static final String ACTION_KEYCHAIN_CHANGED = "android.security.action.KEYCHAIN_CHANGED"; field public static final String ACTION_KEY_ACCESS_CHANGED = "android.security.action.KEY_ACCESS_CHANGED"; diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index f708298a2cbd..a6eab4f5ebe0 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -65,6 +65,7 @@ interface IKeyChainService { AppUriAuthenticationPolicy getCredentialManagementAppPolicy(); String getPredefinedAliasForPackageAndUri(String packageName, in Uri uri); void removeCredentialManagementApp(); + boolean isCredentialManagementApp(String packageName); // APIs used by KeyChainActivity void setGrant(int uid, String alias, boolean value); diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 97819c56fd5a..8362b114baeb 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -421,6 +421,15 @@ public final class KeyChain { * credentials. This is limited to unmanaged devices. The authentication policy must be * provided to be able to make this request successfully. * + * <p> This intent should be started using {@link Activity#startActivityForResult(Intent, int)} + * to verify whether the request was successful and whether the user accepted or denied the + * request. If the user successfully receives and accepts the request, the result code will be + * {@link Activity#RESULT_OK}, otherwise the result code will be + * {@link Activity#RESULT_CANCELED}. + * + * <p> {@link KeyChain#isCredentialManagementApp(Context)} should be used to determine whether + * an app is already the credential management app. + * * @param policy The authentication policy determines which alias for a private key and * certificate pair should be used for authentication. */ @@ -589,6 +598,55 @@ public final class KeyChain { } /** + * Check whether the caller is the credential management app {@link CredentialManagementApp}. + * The credential management app has the ability to manage the user's KeyChain credentials + * on unmanaged devices. + * + * <p> {@link KeyChain#createManageCredentialsIntent} should be used by an app to request to + * become the credential management app. The user must approve this request before the app can + * manage the user's credentials. There can only be one credential management on the device. + * + * @return {@code true} if the caller is the credential management app. + */ + public static boolean isCredentialManagementApp(@NonNull Context context) { + boolean isCredentialManagementApp = false; + try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) { + isCredentialManagementApp = keyChainConnection.getService() + .isCredentialManagementApp(context.getPackageName()); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted while checking whether the caller is the " + + "credential management app.", e); + } catch (SecurityException e) { + isCredentialManagementApp = false; + } + return isCredentialManagementApp; + } + + /** + * Called by the credential management app to get the authentication policy + * {@link AppUriAuthenticationPolicy}. + * + * @return the credential management app's authentication policy. + * @throws SecurityException if the caller is not the credential management app. + */ + @NonNull + public static AppUriAuthenticationPolicy getCredentialManagementAppPolicy( + @NonNull Context context) throws SecurityException { + AppUriAuthenticationPolicy policy = null; + try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) { + policy = keyChainConnection.getService().getCredentialManagementAppPolicy(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } catch (InterruptedException e) { + throw new RuntimeException( + "Interrupted while getting credential management app policy.", e); + } + return policy; + } + + /** * Set a credential management app. The credential management app has the ability to manage * the user's KeyChain credentials on unmanaged devices. * |