diff --git a/api/current.txt b/api/current.txt index fea1f2f4cac44..282b85ef2c804 100644 --- a/api/current.txt +++ b/api/current.txt @@ -41088,6 +41088,7 @@ package android.security { field public static final String EXTRA_KEY_ALIAS = "android.security.extra.KEY_ALIAS"; field public static final String EXTRA_NAME = "name"; field public static final String EXTRA_PKCS12 = "PKCS12"; + field public static final String KEY_ALIAS_SELECTION_DENIED = "android:alias-selection-denied"; } public interface KeyChainAliasCallback { diff --git a/core/java/android/app/admin/DelegatedAdminReceiver.java b/core/java/android/app/admin/DelegatedAdminReceiver.java index f66de8d238ed3..25b8eab452bf4 100644 --- a/core/java/android/app/admin/DelegatedAdminReceiver.java +++ b/core/java/android/app/admin/DelegatedAdminReceiver.java @@ -63,6 +63,10 @@ public class DelegatedAdminReceiver extends BroadcastReceiver { * Allows this receiver to select the alias for a private key and certificate pair for * authentication. If this method returns null, the default {@link android.app.Activity} will * be shown that lets the user pick a private key and certificate pair. + * If this method returns {@link KeyChain#KEY_ALIAS_SELECTION_DENIED}, + * the default {@link android.app.Activity} will not be shown and the user will not be allowed + * to pick anything. And the app, that called {@link KeyChain#choosePrivateKeyAlias}, will + * receive {@code null} back. * *

This callback is only applicable if the delegated app has * {@link DevicePolicyManager#DELEGATION_CERT_SELECTION} capability. Additionally, it must diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index 4771fd8a00b6c..e3a49f39bdc7d 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -791,6 +791,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * Allows this receiver to select the alias for a private key and certificate pair for * authentication. If this method returns null, the default {@link android.app.Activity} will be * shown that lets the user pick a private key and certificate pair. + * If this method returns {@link KeyChain#KEY_ALIAS_SELECTION_DENIED}, + * the default {@link android.app.Activity} will not be shown and the user will not be allowed + * to pick anything. And the app, that called {@link KeyChain#choosePrivateKeyAlias}, will + * receive {@code null} back. * * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 59797f7f4bf6c..51266de83355d 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2422,6 +2422,11 @@ enum PageId { // OS: Q SETTINGS_GESTURE_TAP = 1751; + // OPEN: Settings > Security & screen lock -> Encryption & credentials > Install a certificate + // CATEGORY: SETTINGS + // OS: R + INSTALL_CERTIFICATE_FROM_STORAGE = 1803; + // OPEN: Settings > Developer Options > Platform Compat // CATEGORY: SETTINGS // OS: R diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java index 7282bcfe44457..62194d84f4f54 100644 --- a/keystore/java/android/security/Credentials.java +++ b/keystore/java/android/security/Credentials.java @@ -74,6 +74,15 @@ public class Credentials { /** Key containing suffix of lockdown VPN profile. */ public static final String LOCKDOWN_VPN = "LOCKDOWN_VPN"; + /** Name of CA certificate usage. */ + public static final String CERTIFICATE_USAGE_CA = "ca"; + + /** Name of User certificate usage. */ + public static final String CERTIFICATE_USAGE_USER = "user"; + + /** Name of WIFI certificate usage. */ + public static final String CERTIFICATE_USAGE_WIFI = "wifi"; + /** Data type for public keys. */ public static final String EXTRA_PUBLIC_KEY = "KEY"; @@ -94,30 +103,25 @@ public class Credentials { public static final String EXTRA_INSTALL_AS_UID = "install_as_uid"; /** - * Intent extra: name for the user's private key. + * Intent extra: type of the certificate to install */ - public static final String EXTRA_USER_PRIVATE_KEY_NAME = "user_private_key_name"; + public static final String EXTRA_CERTIFICATE_USAGE = "certificate_install_usage"; + + /** + * Intent extra: name for the user's key pair. + */ + public static final String EXTRA_USER_KEY_ALIAS = "user_key_pair_name"; /** * Intent extra: data for the user's private key in PEM-encoded PKCS#8. */ public static final String EXTRA_USER_PRIVATE_KEY_DATA = "user_private_key_data"; - /** - * Intent extra: name for the user's certificate. - */ - public static final String EXTRA_USER_CERTIFICATE_NAME = "user_certificate_name"; - /** * Intent extra: data for the user's certificate in PEM-encoded X.509. */ public static final String EXTRA_USER_CERTIFICATE_DATA = "user_certificate_data"; - /** - * Intent extra: name for CA certificate chain - */ - public static final String EXTRA_CA_CERTIFICATES_NAME = "ca_certificates_name"; - /** * Intent extra: data for CA certificate chain in PEM-encoded X.509. */ diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index b3cdff7eedf71..97da3cc6f80f5 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -43,7 +43,8 @@ interface IKeyChainService { String installCaCertificate(in byte[] caCertificate); // APIs used by DevicePolicyManager - boolean installKeyPair(in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias); + boolean installKeyPair( + in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias, int uid); boolean removeKeyPair(String alias); // APIs used by Settings diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 1829d2f406b42..254456cea5364 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -342,6 +342,16 @@ public final class KeyChain { */ public static final int KEY_ATTESTATION_FAILURE = 4; + /** + * Used by DPC or delegated app in + * {@link android.app.admin.DeviceAdminReceiver#onChoosePrivateKeyAlias} or + * {@link android.app.admin.DelegatedAdminReceiver#onChoosePrivateKeyAlias} to identify that + * the requesting app is not granted access to any key, and nor will the user be able to grant + * access manually. + */ + public static final String KEY_ALIAS_SELECTION_DENIED = + "android:alias-selection-denied"; + /** * Returns an {@code Intent} that can be used for credential * installation. The intent may be used without any extras, in diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index 3ad076f60c083..0c0c558beb20a 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -40944,6 +40944,7 @@ package android.security { field public static final String EXTRA_KEY_ALIAS = "android.security.extra.KEY_ALIAS"; field public static final String EXTRA_NAME = "name"; field public static final String EXTRA_PKCS12 = "PKCS12"; + field public static final String KEY_ALIAS_SELECTION_DENIED = "android:alias-selection-denied"; } public interface KeyChainAliasCallback { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 03e71f976c5bf..a363f9ba52647 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -5672,7 +5672,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { KeyChain.bindAsUser(mContext, UserHandle.getUserHandleForUid(callingUid)); try { IKeyChainService keyChain = keyChainConnection.getService(); - if (!keyChain.installKeyPair(privKey, cert, chain, alias)) { + if (!keyChain.installKeyPair(privKey, cert, chain, alias, KeyStore.UID_SELF)) { return false; } if (requestAccess) {