summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java21
-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/BaseIDevicePolicyManager.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java28
6 files changed, 54 insertions, 3 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index ef397b72e612..714f59ec13be 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6968,6 +6968,7 @@ package android.app.admin {
method public boolean grantKeyPairToApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
method public boolean hasCaCertInstalled(@Nullable android.content.ComponentName, byte[]);
method public boolean hasGrantedPolicy(@NonNull android.content.ComponentName, int);
+ method public boolean hasKeyPair(@NonNull String);
method public boolean hasLockdownAdminConfiguredNetworks(@NonNull android.content.ComponentName);
method public boolean installCaCert(@Nullable android.content.ComponentName, byte[]);
method public boolean installExistingPackage(@NonNull android.content.ComponentName, String);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 247d6f0de831..26784f2c247e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5370,6 +5370,27 @@ public class DevicePolicyManager {
}
}
+ // STOPSHIP(b/174298501): clarify the expected return value following generateKeyPair call.
+ /**
+ * Called by a device or profile owner, or delegated certificate installer, to query whether a
+ * certificate and private key are installed under a given alias.
+ *
+ * @param alias The alias under which the key pair is installed.
+ * @return {@code true} if a key pair with this alias exists, {@code false} otherwise.
+ * @throws SecurityException if the caller is not a device or profile owner or a delegated
+ * certificate installer.
+ * @see #setDelegatedScopes
+ * @see #DELEGATION_CERT_INSTALL
+ */
+ public boolean hasKeyPair(@NonNull String alias) {
+ throwIfParentInstance("hasKeyPair");
+ try {
+ return mService.hasKeyPair(mContext.getPackageName(), alias);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* 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,
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 37d34511902d..8be3cdc1296a 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -185,6 +185,7 @@ interface IDevicePolicyManager {
in byte[] certBuffer, in byte[] certChainBuffer, String alias, boolean requestAccess,
boolean isUserSelectable);
boolean removeKeyPair(in ComponentName who, in String callerPackage, String alias);
+ boolean hasKeyPair(in String callerPackage, in String alias);
boolean generateKeyPair(in ComponentName who, in String callerPackage, in String algorithm,
in ParcelableKeyGenParameterSpec keySpec,
in int idAttestationFlags, out KeymasterCertificateChain attestationChain);
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 97da3cc6f80f..1ae6a631dbcb 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -46,6 +46,7 @@ interface IKeyChainService {
boolean installKeyPair(
in byte[] privateKey, in byte[] userCert, in byte[] certChain, String alias, int uid);
boolean removeKeyPair(String alias);
+ boolean containsKeyPair(String alias);
// APIs used by Settings
boolean deleteCaCertificate(String alias);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index ce61d50df1d9..05b1e4253bc0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -101,4 +101,9 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
public boolean canProfileOwnerResetPasswordWhenLocked(int userId) {
return false;
}
+
+ public boolean hasKeyPair(String callerPackage, String alias) {
+ // STOPSHIP: implement delegation code in ArcDevicePolicyManagerWrapperService & nuke this.
+ return false;
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2f477afecf12..38381d2d74f8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5101,6 +5101,30 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
+ public boolean hasKeyPair(String callerPackage, String alias) {
+ final CallerIdentity caller = getCallerIdentity(callerPackage);
+ Preconditions.checkCallAuthorization(canManageCertificates(caller));
+
+ return mInjector.binderWithCleanCallingIdentity(() -> {
+ try (KeyChainConnection keyChainConnection =
+ KeyChain.bindAsUser(mContext, caller.getUserHandle())) {
+ return keyChainConnection.getService().containsKeyPair(alias);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Querying keypair", e);
+ } catch (InterruptedException e) {
+ Log.w(LOG_TAG, "Interrupted while querying keypair", e);
+ Thread.currentThread().interrupt();
+ }
+ return false;
+ });
+ }
+
+ private boolean canManageCertificates(CallerIdentity caller) {
+ return isProfileOwner(caller) || isDeviceOwner(caller)
+ || isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+ }
+
+ @Override
public boolean setKeyGrantForApp(ComponentName who, String callerPackage, String alias,
String packageName, boolean hasGrant) {
Preconditions.checkStringNotEmpty(alias, "Alias to grant cannot be empty");
@@ -5178,9 +5202,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
*/
if (hasProfileOwner(caller.getUserId())) {
// Make sure that the caller is the profile owner or delegate.
- Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwner(caller) || isCallerDelegate(
- caller, DELEGATION_CERT_INSTALL));
+ Preconditions.checkCallAuthorization(canManageCertificates(caller));
// Verify that the managed profile is on an organization-owned device and as such
// the profile owner can access Device IDs.
if (isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId())) {