From ad53ef61e7d183a2600b1e69edd0eb7c18bd5144 Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Mon, 11 Jan 2021 10:13:54 +0000 Subject: [PATCH] Add KeyChain Test API for the credential manager * Add setCredentialManagementApp and removeCredentialManagementApp to KeyChain * Add permission to manage credential management app, which is to be used in CTS tests Bug: 165641221 Test: atest android.devicepolicy.cts.CredentialManagementAppTest Change-Id: I8487ebc13758a31639d55c8e380faa51d1cfd843 --- core/api/test-current.txt | 5 ++ core/res/AndroidManifest.xml | 5 ++ keystore/java/android/security/KeyChain.java | 58 ++++++++++++++++++++ packages/Shell/AndroidManifest.xml | 1 + 4 files changed, 69 insertions(+) diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 1086577b0a391..23897bba4c1f2 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1585,6 +1585,11 @@ package android.provider { package android.security { + public final class KeyChain { + method @RequiresPermission("android.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP") public static boolean removeCredentialManagementApp(@NonNull android.content.Context); + method @RequiresPermission("android.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP") public static boolean setCredentialManagementApp(@NonNull android.content.Context, @NonNull String, @NonNull android.security.AppUriAuthenticationPolicy); + } + public class KeyStoreException extends java.lang.Exception { ctor public KeyStoreException(int, String); method public int getErrorCode(); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 8682fea1f8dc6..c1e93e7b9f3cc 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3147,6 +3147,11 @@ + + + diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 2f444b34ce819..97819c56fd5ac 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -17,10 +17,13 @@ package android.security; import static android.security.Credentials.ACTION_MANAGE_CREDENTIALS; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.TestApi; import android.annotation.WorkerThread; import android.app.Activity; import android.app.PendingIntent; @@ -41,6 +44,7 @@ import android.os.UserManager; import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; +import android.util.Log; import com.android.org.conscrypt.TrustedCertificateStore; @@ -104,6 +108,11 @@ import javax.security.auth.x500.X500Principal; // TODO reference intent for credential installation when public public final class KeyChain { + /** + * @hide + */ + public static final String LOG = "KeyChain"; + /** * @hide Also used by KeyChainService implementation */ @@ -579,6 +588,55 @@ public final class KeyChain { activity.startActivity(intent); } + /** + * Set a credential management app. The credential management app has the ability to manage + * the user's KeyChain credentials on unmanaged devices. + * + *

There can only be one credential management on the device. If another app requests to + * become the credential management app, then the existing credential management app will + * no longer be able to manage credentials. + * + * @param packageName The package name of the credential management app + * @param authenticationPolicy The authentication policy of the credential management app. This + * policy determines which alias for a private key and certificate + * pair should be used for authentication. + * @return {@code true} if the credential management app was successfully added. + * @hide + */ + @TestApi + @RequiresPermission(Manifest.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP) + public static boolean setCredentialManagementApp(@NonNull Context context, + @NonNull String packageName, @NonNull AppUriAuthenticationPolicy authenticationPolicy) { + try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) { + keyChainConnection.getService() + .setCredentialManagementApp(packageName, authenticationPolicy); + return true; + } catch (RemoteException | InterruptedException e) { + Log.w(LOG, "Set credential management app failed", e); + Thread.currentThread().interrupt(); + return false; + } + } + + /** + * Remove the user's KeyChain credentials on unmanaged devices. + * + * @return {@code true} if the credential management app was successfully removed. + * @hide + */ + @TestApi + @RequiresPermission(Manifest.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP) + public static boolean removeCredentialManagementApp(@NonNull Context context) { + try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) { + keyChainConnection.getService().removeCredentialManagementApp(); + return true; + } catch (RemoteException | InterruptedException e) { + Log.w(LOG, "Remove credential management app failed", e); + Thread.currentThread().interrupt(); + return false; + } + } + private static class AliasResponse extends IKeyChainAliasCallback.Stub { private final KeyChainAliasCallback keyChainAliasResponse; private AliasResponse(KeyChainAliasCallback keyChainAliasResponse) { diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index f83f6706d55b9..d221819963993 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -119,6 +119,7 @@ +