From dfdbd2e905308d4345d9a53d86257453713c0583 Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Sun, 29 Nov 2020 21:41:23 +0000 Subject: [PATCH] Add credential management app access control DPM Background * This is part of the work to support a credential management app on unmanaged devices. Changes * Add isCredentialManagementApp access control check to the following DPM API methods: - installKeyPair - removeKeyPair - generateKeyPair - setKeyPairCertificate Bug: 165641221 Test: Manual testing with TestDPC Change-Id: Ib88f077ee1f26c08e648ab8b4bb3544b42078d57 --- .../app/admin/DevicePolicyManager.java | 136 ++++++++++++++---- .../DevicePolicyManagerService.java | 81 ++++++++++- 2 files changed, 183 insertions(+), 34 deletions(-) diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 26784f2c247e4..646b7b36dabf7 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -5213,9 +5213,22 @@ public class DevicePolicyManager { } /** - * Called by a device or profile owner, or delegated certificate installer, to install a - * certificate and corresponding private key. All apps within the profile will be able to access - * the certificate and use the private key, given direct user approval. + * This API can be called by the following to install a certificate and corresponding + * private key: + * + * All apps within the profile will be able to access the certificate and use the private key, + * given direct user approval. + * + *

From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app + * can call this API. However, this API sets the key pair as user selectable by default, + * which is not permitted when called by the credential management app. Instead, + * {@link #installKeyPair(ComponentName, PrivateKey, Certificate[], String, int)} should be + * called with {@link #INSTALLKEY_SET_USER_SELECTABLE} not set as a flag. * *

Access to the installed credentials will not be granted to the caller of this API without * direct user approval. This is for security - should a certificate installer become @@ -5246,10 +5259,23 @@ public class DevicePolicyManager { } /** - * Called by a device or profile owner, or delegated certificate installer, to install a - * certificate chain and corresponding private key for the leaf certificate. All apps within the - * profile will be able to access the certificate chain and use the private key, given direct - * user approval. + * This API can be called by the following to install a certificate chain and corresponding + * private key for the leaf certificate: + *

+ * All apps within the profile will be able to access the certificate chain and use the private + * key, given direct user approval. + * + *

From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app + * can call this API. However, this API sets the key pair as user selectable by default, + * which is not permitted when called by the credential management app. Instead, + * {@link #installKeyPair(ComponentName, PrivateKey, Certificate[], String, int)} should be + * called with {@link #INSTALLKEY_SET_USER_SELECTABLE} not set as a flag. + * Note, there can only be a credential management app on an unmanaged device. * *

The caller of this API may grant itself access to the certificate and private key * immediately, without user approval. It is a best practice not to request this unless strictly @@ -5287,10 +5313,26 @@ public class DevicePolicyManager { } /** - * Called by a device or profile owner, or delegated certificate installer, to install a - * certificate chain and corresponding private key for the leaf certificate. All apps within the - * profile will be able to access the certificate chain and use the private key, given direct - * user approval (if the user is allowed to select the private key). + * This API can be called by the following to install a certificate chain and corresponding + * private key for the leaf certificate: + *

+ * All apps within the profile will be able to access the certificate chain and use the + * private key, given direct user approval (if the user is allowed to select the private key). + * + *

From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app + * can call this API. If called by the credential management app: + *

+ * Note, there can only be a credential management app on an unmanaged device. * *

The caller of this API may grant itself access to the certificate and private key * immediately, without user approval. It is a best practice not to request this unless strictly @@ -5316,7 +5358,8 @@ public class DevicePolicyManager { * {@link #INSTALLKEY_REQUEST_CREDENTIALS_ACCESS}. * @return {@code true} if the keys were installed, {@code false} otherwise. * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile - * owner. + * owner, or {@code admin} is null but the calling application is not a delegated + * certificate installer or credential management app. * @see android.security.KeyChain#getCertificateChain * @see #setDelegatedScopes * @see #DELEGATION_CERT_INSTALL @@ -5349,15 +5392,26 @@ public class DevicePolicyManager { } /** - * Called by a device or profile owner, or delegated certificate installer, to remove a - * certificate and private key pair installed under a given alias. + * This API can be called by the following to remove a certificate and private key pair + * installed under a given alias: + *

+ * + *

From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app + * can call this API. If called by the credential management app, the componentName must be + * {@code null}. Note, there can only be a credential management app on an unmanaged device. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. * @param alias The private key alias under which the certificate is installed. * @return {@code true} if the private key alias no longer exists, {@code false} otherwise. * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile - * owner. + * owner, or {@code admin} is null but the calling application is not a delegated + * certificate installer or credential management app. * @see #setDelegatedScopes * @see #DELEGATION_CERT_INSTALL */ @@ -5392,10 +5446,20 @@ public class DevicePolicyManager { } /** - * Called by a device or profile owner, or delegated certificate installer, to generate a - * new private/public key pair. If the device supports key generation via secure hardware, - * this method is useful for creating a key in KeyChain that never left the secure hardware. - * Access to the key is controlled the same way as in {@link #installKeyPair}. + * This API can be called by the following to generate a new private/public key pair: + *

+ * If the device supports key generation via secure hardware, this method is useful for + * creating a key in KeyChain that never left the secure hardware. Access to the key is + * controlled the same way as in {@link #installKeyPair}. + * + *

From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app + * can call this API. If called by the credential management app, the componentName must be + * {@code null}. Note, there can only be a credential management app on an unmanaged device. * *

Because this method might take several seconds to complete, it should only be called from * a worker thread. This method returns {@code null} when called from the main thread. @@ -5418,9 +5482,10 @@ public class DevicePolicyManager { * supports these features, refer to {@link #isDeviceIdAttestationSupported()} and * {@link #isUniqueDeviceAttestationSupported()}. * - *

Device owner, profile owner and their delegated certificate installer can use - * {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device information - * including manufacturer, model, brand, device and product in the attestation record. + *

Device owner, profile owner, their delegated certificate installer and the credential + * management app can use {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device + * information including manufacturer, model, brand, device and product in the attestation + * record. * Only device owner, profile owner on an organization-owned device and their delegated * certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and * {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial number, @@ -5455,9 +5520,11 @@ public class DevicePolicyManager { * {@code keySpec}. * @return A non-null {@code AttestedKeyPair} if the key generation succeeded, null otherwise. * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile - * owner. If Device ID attestation is requested (using {@link #ID_TYPE_SERIAL}, - * {@link #ID_TYPE_IMEI} or {@link #ID_TYPE_MEID}), the caller must be the Device Owner - * or the Certificate Installer delegate. + * owner, or {@code admin} is null but the calling application is not a delegated + * certificate installer or credential management app. If Device ID attestation is + * requested (using {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} or + * {@link #ID_TYPE_MEID}), the caller must be the Device Owner or the Certificate + * Installer delegate. * @throws IllegalArgumentException in the following cases: *

*