diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 22 | ||||
| -rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 1 | ||||
| -rw-r--r-- | keystore/java/android/security/IKeyChainService.aidl | 1 | ||||
| -rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 66 |
6 files changed, 72 insertions, 20 deletions
diff --git a/api/current.txt b/api/current.txt index 007ed134d9ab..2e2a604c5dff 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5802,6 +5802,7 @@ package android.app.admin { method public void lockNow(); method public void removeActiveAdmin(android.content.ComponentName); method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); + method public boolean removeKeyPair(android.content.ComponentName, java.lang.String); method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean resetPassword(java.lang.String, int); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); diff --git a/api/system-current.txt b/api/system-current.txt index 1a05551a3fe9..30be4c714868 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5935,6 +5935,7 @@ package android.app.admin { method public void notifyPendingSystemUpdate(long); method public void removeActiveAdmin(android.content.ComponentName); method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); + method public boolean removeKeyPair(android.content.ComponentName, java.lang.String); method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean resetPassword(java.lang.String, int); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 471750eda0cf..6b900a8ab36d 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2325,8 +2325,8 @@ public class DevicePolicyManager { * with that alias already exists, it will be overwritten. * @return {@code true} if the keys were installed, {@code false} otherwise. */ - public boolean installKeyPair(@Nullable ComponentName admin, PrivateKey privKey, Certificate cert, - String alias) { + public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey, + @NonNull Certificate cert, @NonNull String alias) { try { final byte[] pemCert = Credentials.convertToPem(cert); final byte[] pkcs8Key = KeyFactory.getInstance(privKey.getAlgorithm()) @@ -2343,6 +2343,24 @@ public class DevicePolicyManager { } /** + * Called by a device or profile owner to remove all user credentials installed under a given + * alias. + * + * @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 keys were both removed, {@code false} otherwise. + */ + public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) { + try { + return mService.removeKeyPair(admin, alias); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + return false; + } + + /** * @return the alias of a given CA certificate in the certificate store, or {@code null} if it * doesn't exist. */ diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 6b4567c297c5..1708ee3c73e3 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -135,6 +135,7 @@ interface IDevicePolicyManager { void enforceCanManageCaCerts(in ComponentName admin); boolean installKeyPair(in ComponentName who, in byte[] privKeyBuffer, in byte[] certBuffer, String alias); + boolean removeKeyPair(in ComponentName who, String alias); void choosePrivateKeyAlias(int uid, in Uri uri, in String alias, IBinder aliasCallback); void setCertInstallerPackage(in ComponentName who, String installerPackage); diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index 20c94c5946d7..cfcb4e0c16e1 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -33,6 +33,7 @@ interface IKeyChainService { // APIs used by DevicePolicyManager boolean installKeyPair(in byte[] privateKey, in byte[] userCert, String alias); + boolean removeKeyPair(String alias); // APIs used by Settings boolean deleteCaCertificate(String alias); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index eed5419218ad..5cf8ac0e2c8d 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3541,6 +3541,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void enforceCanManageInstalledKeys(ComponentName who) { + if (who == null) { + if (!isCallerDelegatedCertInstaller()) { + throw new SecurityException("who == null, but caller is not cert installer"); + } + } else { + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } + } + } + private boolean isCallerDelegatedCertInstaller() { final int callingUid = mInjector.binderGetCallingUid(); final int userHandle = UserHandle.getUserId(callingUid); @@ -3630,27 +3642,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias) { - if (who == null) { - if (!isCallerDelegatedCertInstaller()) { - throw new SecurityException("who == null, but caller is not cert installer"); - } - } else { - synchronized (this) { - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - } - } + enforceCanManageInstalledKeys(who); + final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); final long id = mInjector.binderClearCallingIdentity(); try { - final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); - try { - IKeyChainService keyChain = keyChainConnection.getService(); - return keyChain.installKeyPair(privKey, cert, alias); - } catch (RemoteException e) { - Log.e(LOG_TAG, "Installing certificate", e); - } finally { - keyChainConnection.close(); - } + final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); + try { + IKeyChainService keyChain = keyChainConnection.getService(); + return keyChain.installKeyPair(privKey, cert, alias); + } catch (RemoteException e) { + Log.e(LOG_TAG, "Installing certificate", e); + } finally { + keyChainConnection.close(); + } } catch (InterruptedException e) { Log.w(LOG_TAG, "Interrupted while installing certificate", e); Thread.currentThread().interrupt(); @@ -3661,6 +3666,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override + public boolean removeKeyPair(ComponentName who, String alias) { + enforceCanManageInstalledKeys(who); + + final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + final long id = Binder.clearCallingIdentity(); + try { + final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); + try { + IKeyChainService keyChain = keyChainConnection.getService(); + return keyChain.removeKeyPair(alias); + } catch (RemoteException e) { + Log.e(LOG_TAG, "Removing keypair", e); + } finally { + keyChainConnection.close(); + } + } catch (InterruptedException e) { + Log.w(LOG_TAG, "Interrupted while removing keypair", e); + Thread.currentThread().interrupt(); + } finally { + Binder.restoreCallingIdentity(id); + } + return false; + } + + @Override public void choosePrivateKeyAlias(final int uid, final Uri uri, final String alias, final IBinder response) { // Caller UID needs to be trusted, so we restrict this method to SYSTEM_UID callers. |