Loading core/java/android/app/admin/DevicePolicyManager.java +106 −30 Original line number Diff line number Diff line Loading @@ -5240,9 +5240,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * All apps within the profile will be able to access the certificate and use the private key, * given direct user approval. * * <p>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. * * <p>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 Loading Loading @@ -5273,10 +5286,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * All apps within the profile will be able to access the certificate chain and use the private * key, given direct user approval. * * <p>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. * * <p>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 Loading Loading @@ -5314,10 +5340,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * 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). * * <p>From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app * can call this API. If called by the credential management app: * <ul> * <li>The componentName must be {@code null}r</li> * <li>The alias must exist in the credential management app's * {@link android.security.AppUriAuthenticationPolicy}</li> * <li>The key pair must not be user selectable</li> * </ul> * Note, there can only be a credential management app on an unmanaged device. * * <p>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 Loading @@ -5343,7 +5385,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 Loading Loading @@ -5376,15 +5419,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * * <p>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 */ Loading Loading @@ -5419,10 +5473,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * 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}. * * <p>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. * * <p>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. Loading @@ -5445,9 +5509,10 @@ public class DevicePolicyManager { * supports these features, refer to {@link #isDeviceIdAttestationSupported()} and * {@link #isUniqueDeviceAttestationSupported()}. * * <p>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. * <p>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, Loading Loading @@ -5482,9 +5547,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: * <p> * <ul> Loading Loading @@ -5647,10 +5714,19 @@ public class DevicePolicyManager { } /** * Called by a device or profile owner, or delegated certificate installer, to associate * certificates with a key pair that was generated using {@link #generateKeyPair}, and * set whether the key is available for the user to choose in the certificate selection * prompt. * This API can be called by the following to associate certificates with a key pair that was * generated using {@link #generateKeyPair}, and set whether the key is available for the user * to choose in the certificate selection prompt: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * * <p>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. Loading @@ -5668,7 +5744,7 @@ public class DevicePolicyManager { * successfully associated with it, {@code false} otherwise. * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile * owner, or {@code admin} is null but the calling application is not a delegated * certificate installer. * certificate installer or credential management app. */ public boolean setKeyPairCertificate(@Nullable ComponentName admin, @NonNull String alias, @NonNull List<Certificate> certs, boolean isUserSelectable) { Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +77 −4 Original line number Diff line number Diff line Loading @@ -233,6 +233,7 @@ import android.provider.ContactsInternal; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Telephony; import android.security.AppUriAuthenticationPolicy; import android.security.IKeyChainAliasCallback; import android.security.IKeyChainService; import android.security.KeyChain; Loading Loading @@ -1154,6 +1155,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return LocalServices.getService(PersistentDataBlockManagerInternal.class); } AppOpsManager getAppOpsManager() { return mContext.getSystemService(AppOpsManager.class); } LockSettingsInternal getLockSettingsInternal() { return LocalServices.getService(LockSettingsInternal.class); } Loading Loading @@ -5031,7 +5036,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who, callerPackage); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias, isUserSelectable)))); final long id = mInjector.binderClearCallingIdentity(); try { Loading Loading @@ -5071,7 +5077,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who, callerPackage); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias)))); final long id = Binder.clearCallingIdentity(); try { Loading Loading @@ -5275,7 +5282,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } else { Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias)))); } // As the caller will be granted access to the key, ensure no UID was specified, as Loading Loading @@ -5371,7 +5379,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who, callerPackage); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias)))); final long id = mInjector.binderClearCallingIdentity(); try (final KeyChainConnection keyChainConnection = Loading Loading @@ -5806,6 +5815,70 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } /** * Check whether a caller application is the credential management app, which can access * privileged APIs. * <p> * This is done by checking that the calling package is authorized to perform the app operation * {@link android.app.AppOpsManager#OP_MANAGE_CREDENTIALS}. The alias provided must be contained * in the aliases specified in the credential management app's authentication policy. The * key pair to install must not be user selectable. * * @param caller the calling identity * @return {@code true} if the calling process is the credential management app. */ private boolean isCredentialManagementApp(CallerIdentity caller, String alias, boolean isUserSelectable) { // Should not be user selectable if (isUserSelectable) { Log.e(LOG_TAG, "The credential management app is not allowed to install a " + "user selectable key pair"); return false; } return isCredentialManagementApp(caller, alias); } /** * Check whether a caller application is the credential mangement app, which can access * privileged APIs. * <p> * This is done by checking that the calling package is authorized to perform the app operation * {@link android.app.AppOpsManager#OP_MANAGE_CREDENTIALS}. The alias provided must be contained * in the aliases specified in the credential management app's authentication policy. * * @param caller the calling identity * @return {@code true} if the calling process is the credential management app. */ private boolean isCredentialManagementApp(CallerIdentity caller, String alias) { // Should include alias in authentication policy try (KeyChainConnection connection = KeyChain.bindAsUser(mContext, caller.getUserHandle())) { if (!containsAlias(connection.getService().getCredentialManagementAppPolicy(), alias)) { return false; } } catch (RemoteException | InterruptedException e) { return false; } AppOpsManager appOpsManager = mInjector.getAppOpsManager(); return appOpsManager != null ? appOpsManager.noteOpNoThrow(AppOpsManager.OP_MANAGE_CREDENTIALS, caller.getUid(), caller.getPackageName(), null, null) == AppOpsManager.MODE_ALLOWED : false; } private static boolean containsAlias(AppUriAuthenticationPolicy policy, String alias) { for (Map.Entry<String, Map<Uri, String>> appsToUris : policy.getAppAndUriMappings().entrySet()) { for (Map.Entry<Uri, String> urisToAliases : appsToUris.getValue().entrySet()) { if (urisToAliases.getValue().equals(alias)) { return true; } } } return false; } @Override public void setCertInstallerPackage(ComponentName who, String installerPackage) throws SecurityException { Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +106 −30 Original line number Diff line number Diff line Loading @@ -5240,9 +5240,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * All apps within the profile will be able to access the certificate and use the private key, * given direct user approval. * * <p>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. * * <p>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 Loading Loading @@ -5273,10 +5286,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * All apps within the profile will be able to access the certificate chain and use the private * key, given direct user approval. * * <p>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. * * <p>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 Loading Loading @@ -5314,10 +5340,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * 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). * * <p>From Android {@link android.os.Build.VERSION_CODES#S}, the credential management app * can call this API. If called by the credential management app: * <ul> * <li>The componentName must be {@code null}r</li> * <li>The alias must exist in the credential management app's * {@link android.security.AppUriAuthenticationPolicy}</li> * <li>The key pair must not be user selectable</li> * </ul> * Note, there can only be a credential management app on an unmanaged device. * * <p>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 Loading @@ -5343,7 +5385,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 Loading Loading @@ -5376,15 +5419,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * * <p>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 */ Loading Loading @@ -5419,10 +5473,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: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * 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}. * * <p>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. * * <p>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. Loading @@ -5445,9 +5509,10 @@ public class DevicePolicyManager { * supports these features, refer to {@link #isDeviceIdAttestationSupported()} and * {@link #isUniqueDeviceAttestationSupported()}. * * <p>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. * <p>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, Loading Loading @@ -5482,9 +5547,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: * <p> * <ul> Loading Loading @@ -5647,10 +5714,19 @@ public class DevicePolicyManager { } /** * Called by a device or profile owner, or delegated certificate installer, to associate * certificates with a key pair that was generated using {@link #generateKeyPair}, and * set whether the key is available for the user to choose in the certificate selection * prompt. * This API can be called by the following to associate certificates with a key pair that was * generated using {@link #generateKeyPair}, and set whether the key is available for the user * to choose in the certificate selection prompt: * <ul> * <li>Device owner</li> * <li>Profile owner</li> * <li>Delegated certificate installer</li> * <li>Credential management app</li> * </ul> * * <p>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. Loading @@ -5668,7 +5744,7 @@ public class DevicePolicyManager { * successfully associated with it, {@code false} otherwise. * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile * owner, or {@code admin} is null but the calling application is not a delegated * certificate installer. * certificate installer or credential management app. */ public boolean setKeyPairCertificate(@Nullable ComponentName admin, @NonNull String alias, @NonNull List<Certificate> certs, boolean isUserSelectable) { Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +77 −4 Original line number Diff line number Diff line Loading @@ -233,6 +233,7 @@ import android.provider.ContactsInternal; import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Telephony; import android.security.AppUriAuthenticationPolicy; import android.security.IKeyChainAliasCallback; import android.security.IKeyChainService; import android.security.KeyChain; Loading Loading @@ -1154,6 +1155,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return LocalServices.getService(PersistentDataBlockManagerInternal.class); } AppOpsManager getAppOpsManager() { return mContext.getSystemService(AppOpsManager.class); } LockSettingsInternal getLockSettingsInternal() { return LocalServices.getService(LockSettingsInternal.class); } Loading Loading @@ -5031,7 +5036,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who, callerPackage); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias, isUserSelectable)))); final long id = mInjector.binderClearCallingIdentity(); try { Loading Loading @@ -5071,7 +5077,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who, callerPackage); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias)))); final long id = Binder.clearCallingIdentity(); try { Loading Loading @@ -5275,7 +5282,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } else { Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias)))); } // As the caller will be granted access to the key, ensure no UID was specified, as Loading Loading @@ -5371,7 +5379,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(who, callerPackage); Preconditions.checkCallAuthorization((caller.hasAdminComponent() && (isProfileOwner(caller) || isDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))); || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL) || isCredentialManagementApp(caller, alias)))); final long id = mInjector.binderClearCallingIdentity(); try (final KeyChainConnection keyChainConnection = Loading Loading @@ -5806,6 +5815,70 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } /** * Check whether a caller application is the credential management app, which can access * privileged APIs. * <p> * This is done by checking that the calling package is authorized to perform the app operation * {@link android.app.AppOpsManager#OP_MANAGE_CREDENTIALS}. The alias provided must be contained * in the aliases specified in the credential management app's authentication policy. The * key pair to install must not be user selectable. * * @param caller the calling identity * @return {@code true} if the calling process is the credential management app. */ private boolean isCredentialManagementApp(CallerIdentity caller, String alias, boolean isUserSelectable) { // Should not be user selectable if (isUserSelectable) { Log.e(LOG_TAG, "The credential management app is not allowed to install a " + "user selectable key pair"); return false; } return isCredentialManagementApp(caller, alias); } /** * Check whether a caller application is the credential mangement app, which can access * privileged APIs. * <p> * This is done by checking that the calling package is authorized to perform the app operation * {@link android.app.AppOpsManager#OP_MANAGE_CREDENTIALS}. The alias provided must be contained * in the aliases specified in the credential management app's authentication policy. * * @param caller the calling identity * @return {@code true} if the calling process is the credential management app. */ private boolean isCredentialManagementApp(CallerIdentity caller, String alias) { // Should include alias in authentication policy try (KeyChainConnection connection = KeyChain.bindAsUser(mContext, caller.getUserHandle())) { if (!containsAlias(connection.getService().getCredentialManagementAppPolicy(), alias)) { return false; } } catch (RemoteException | InterruptedException e) { return false; } AppOpsManager appOpsManager = mInjector.getAppOpsManager(); return appOpsManager != null ? appOpsManager.noteOpNoThrow(AppOpsManager.OP_MANAGE_CREDENTIALS, caller.getUid(), caller.getPackageName(), null, null) == AppOpsManager.MODE_ALLOWED : false; } private static boolean containsAlias(AppUriAuthenticationPolicy policy, String alias) { for (Map.Entry<String, Map<Uri, String>> appsToUris : policy.getAppAndUriMappings().entrySet()) { for (Map.Entry<Uri, String> urisToAliases : appsToUris.getValue().entrySet()) { if (urisToAliases.getValue().equals(alias)) { return true; } } } return false; } @Override public void setCertInstallerPackage(ComponentName who, String installerPackage) throws SecurityException { Loading