Add DPM.hasKeyPair()

The method returns true if a private key and a user certifiate are
present in KeyChain under this alias.

Bug: 160457441
Test: atest com.android.cts.devicepolicy.MixedManagedProfileOwnerTest#testKeyManagement
Test: atest com.android.cts.devicepolicy.MixedDeviceOwnerTest#testDelegatedCertInstallerDirectly
Test: atest android.admin.cts.DevicePolicyManagerTest
Change-Id: I15ca6190db1ef4dbf0caabe9d46008d92f758df5
This commit is contained in:
Pavel Grafov
2020-11-12 21:17:47 +00:00
parent 3a9b54f704
commit b73e15249b
6 changed files with 54 additions and 3 deletions

View File

@@ -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);

View File

@@ -5349,6 +5349,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,

View File

@@ -184,6 +184,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);

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -5045,6 +5045,30 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
@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) {
@@ -5123,9 +5147,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())) {