summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java22
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--keystore/java/android/security/IKeyChainService.aidl1
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java66
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.