Merge changes from topics "wifi-dpm-grant", "wifi-keychain" into sc-dev
* changes: Allow WiFi module to request grants from KeyChain DPM API to grant keys to Wifi
This commit is contained in:
@@ -7121,6 +7121,7 @@ package android.app.admin {
|
|||||||
method @NonNull public android.os.Bundle getUserRestrictions(@NonNull android.content.ComponentName);
|
method @NonNull public android.os.Bundle getUserRestrictions(@NonNull android.content.ComponentName);
|
||||||
method @Nullable public String getWifiMacAddress(@NonNull android.content.ComponentName);
|
method @Nullable public String getWifiMacAddress(@NonNull android.content.ComponentName);
|
||||||
method public boolean grantKeyPairToApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
|
method public boolean grantKeyPairToApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
|
||||||
|
method public boolean grantKeyPairToWifiAuth(@NonNull String);
|
||||||
method public boolean hasCaCertInstalled(@Nullable android.content.ComponentName, byte[]);
|
method public boolean hasCaCertInstalled(@Nullable android.content.ComponentName, byte[]);
|
||||||
method public boolean hasGrantedPolicy(@NonNull android.content.ComponentName, int);
|
method public boolean hasGrantedPolicy(@NonNull android.content.ComponentName, int);
|
||||||
method public boolean hasKeyPair(@NonNull String);
|
method public boolean hasKeyPair(@NonNull String);
|
||||||
@@ -7143,6 +7144,7 @@ package android.app.admin {
|
|||||||
method public boolean isDeviceIdAttestationSupported();
|
method public boolean isDeviceIdAttestationSupported();
|
||||||
method public boolean isDeviceOwnerApp(String);
|
method public boolean isDeviceOwnerApp(String);
|
||||||
method public boolean isEphemeralUser(@NonNull android.content.ComponentName);
|
method public boolean isEphemeralUser(@NonNull android.content.ComponentName);
|
||||||
|
method public boolean isKeyPairGrantedToWifiAuth(@NonNull String);
|
||||||
method public boolean isLockTaskPermitted(String);
|
method public boolean isLockTaskPermitted(String);
|
||||||
method public boolean isLogoutEnabled();
|
method public boolean isLogoutEnabled();
|
||||||
method public boolean isManagedProfile(@NonNull android.content.ComponentName);
|
method public boolean isManagedProfile(@NonNull android.content.ComponentName);
|
||||||
@@ -7178,6 +7180,7 @@ package android.app.admin {
|
|||||||
method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(@NonNull android.content.ComponentName);
|
method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(@NonNull android.content.ComponentName);
|
||||||
method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(@NonNull android.content.ComponentName);
|
method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(@NonNull android.content.ComponentName);
|
||||||
method public boolean revokeKeyPairFromApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
|
method public boolean revokeKeyPairFromApp(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
|
||||||
|
method public boolean revokeKeyPairFromWifiAuth(@NonNull String);
|
||||||
method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean);
|
method public void setAccountManagementDisabled(@NonNull android.content.ComponentName, String, boolean);
|
||||||
method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
|
method public void setAffiliationIds(@NonNull android.content.ComponentName, @NonNull java.util.Set<java.lang.String>);
|
||||||
method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
|
method public void setAlwaysOnVpnPackage(@NonNull android.content.ComponentName, @Nullable String, boolean) throws android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
|||||||
@@ -9198,6 +9198,15 @@ package android.se.omapi {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
package android.security {
|
||||||
|
|
||||||
|
public final class KeyChain {
|
||||||
|
method @Nullable @WorkerThread public static String getWifiKeyGrantAsUser(@NonNull android.content.Context, @NonNull android.os.UserHandle, @NonNull String);
|
||||||
|
method @WorkerThread public static boolean hasWifiKeyGrantAsUser(@NonNull android.content.Context, @NonNull android.os.UserHandle, @NonNull String);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
package android.security.keystore {
|
package android.security.keystore {
|
||||||
|
|
||||||
public class AndroidKeyStoreProvider extends java.security.Provider {
|
public class AndroidKeyStoreProvider extends java.security.Provider {
|
||||||
|
|||||||
@@ -6437,6 +6437,74 @@ public class DevicePolicyManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by a device or profile owner, or delegated certificate chooser (an app that has been
|
||||||
|
* delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to allow using a KeyChain key
|
||||||
|
* pair for authentication to Wifi networks. The key can then be used in configurations passed
|
||||||
|
* to {@link android.net.wifi.WifiManager#addNetwork}.
|
||||||
|
*
|
||||||
|
* @param alias The alias of the key pair.
|
||||||
|
* @return {@code true} if the operation was set successfully, {@code false} otherwise.
|
||||||
|
*
|
||||||
|
* @throws SecurityException if the caller is not a device owner, a profile owner or
|
||||||
|
* delegated certificate chooser.
|
||||||
|
* @see #revokeKeyPairFromWifiAuth
|
||||||
|
*/
|
||||||
|
public boolean grantKeyPairToWifiAuth(@NonNull String alias) {
|
||||||
|
throwIfParentInstance("grantKeyPairToWifiAuth");
|
||||||
|
try {
|
||||||
|
return mService.setKeyGrantToWifiAuth(mContext.getPackageName(), alias, true);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by a device or profile owner, or delegated certificate chooser (an app that has been
|
||||||
|
* delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to deny using a KeyChain key
|
||||||
|
* pair for authentication to Wifi networks. Configured networks using this key won't be able to
|
||||||
|
* authenticate.
|
||||||
|
*
|
||||||
|
* @param alias The alias of the key pair.
|
||||||
|
* @return {@code true} if the operation was set successfully, {@code false} otherwise.
|
||||||
|
*
|
||||||
|
* @throws SecurityException if the caller is not a device owner, a profile owner or
|
||||||
|
* delegated certificate chooser.
|
||||||
|
* @see #grantKeyPairToWifiAuth
|
||||||
|
*/
|
||||||
|
public boolean revokeKeyPairFromWifiAuth(@NonNull String alias) {
|
||||||
|
throwIfParentInstance("revokeKeyPairFromWifiAuth");
|
||||||
|
try {
|
||||||
|
return mService.setKeyGrantToWifiAuth(mContext.getPackageName(), alias, false);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by a device or profile owner, or delegated certificate chooser (an app that has been
|
||||||
|
* delegated the {@link #DELEGATION_CERT_SELECTION} privilege), to query whether a KeyChain key
|
||||||
|
* pair can be used for authentication to Wifi networks.
|
||||||
|
*
|
||||||
|
* @param alias The alias of the key pair.
|
||||||
|
* @return {@code true} if the key pair can be used, {@code false} otherwise.
|
||||||
|
*
|
||||||
|
* @throws SecurityException if the caller is not a device owner, a profile owner or
|
||||||
|
* delegated certificate chooser.
|
||||||
|
* @see #grantKeyPairToWifiAuth
|
||||||
|
*/
|
||||||
|
public boolean isKeyPairGrantedToWifiAuth(@NonNull String alias) {
|
||||||
|
throwIfParentInstance("isKeyPairGrantedToWifiAuth");
|
||||||
|
try {
|
||||||
|
return mService.isKeyPairGrantedToWifiAuth(mContext.getPackageName(), alias);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if the device supports attestation of device identifiers in addition
|
* Returns {@code true} if the device supports attestation of device identifiers in addition
|
||||||
* to key attestation. See
|
* to key attestation. See
|
||||||
|
|||||||
@@ -479,6 +479,8 @@ interface IDevicePolicyManager {
|
|||||||
|
|
||||||
boolean setKeyGrantForApp(in ComponentName admin, String callerPackage, String alias, String packageName, boolean hasGrant);
|
boolean setKeyGrantForApp(in ComponentName admin, String callerPackage, String alias, String packageName, boolean hasGrant);
|
||||||
List<String> getKeyPairGrants(in String callerPackage, in String alias);
|
List<String> getKeyPairGrants(in String callerPackage, in String alias);
|
||||||
|
boolean setKeyGrantToWifiAuth(String callerPackage, String alias, boolean hasGrant);
|
||||||
|
boolean isKeyPairGrantedToWifiAuth(String callerPackage, String alias);
|
||||||
|
|
||||||
void setUserControlDisabledPackages(in ComponentName admin, in List<String> packages);
|
void setUserControlDisabledPackages(in ComponentName admin, in List<String> packages);
|
||||||
|
|
||||||
|
|||||||
@@ -68,4 +68,7 @@ interface IKeyChainService {
|
|||||||
// APIs used by KeyChainActivity
|
// APIs used by KeyChainActivity
|
||||||
void setGrant(int uid, String alias, boolean value);
|
void setGrant(int uid, String alias, boolean value);
|
||||||
boolean hasGrant(int uid, String alias);
|
boolean hasGrant(int uid, String alias);
|
||||||
|
|
||||||
|
// API used by Wifi
|
||||||
|
String getWifiKeyGrantAsUser(String alias);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
|
|||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.SdkConstant;
|
import android.annotation.SdkConstant;
|
||||||
import android.annotation.SdkConstant.SdkConstantType;
|
import android.annotation.SdkConstant.SdkConstantType;
|
||||||
|
import android.annotation.SystemApi;
|
||||||
import android.annotation.TestApi;
|
import android.annotation.TestApi;
|
||||||
import android.annotation.WorkerThread;
|
import android.annotation.WorkerThread;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -1012,6 +1013,54 @@ public final class KeyChain {
|
|||||||
return bindAsUser(context, null, user);
|
return bindAsUser(context, null, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a persistable grant string that allows WiFi stack to access the key using Keystore
|
||||||
|
* SSL engine.
|
||||||
|
*
|
||||||
|
* @return grant string or null if key is not granted or doesn't exist.
|
||||||
|
*
|
||||||
|
* The key should be granted to Process.WIFI_UID.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
@Nullable
|
||||||
|
@WorkerThread
|
||||||
|
public static String getWifiKeyGrantAsUser(
|
||||||
|
@NonNull Context context, @NonNull UserHandle user, @NonNull String alias) {
|
||||||
|
try (KeyChainConnection keyChainConnection =
|
||||||
|
bindAsUser(context.getApplicationContext(), user)) {
|
||||||
|
return keyChainConnection.getService().getWifiKeyGrantAsUser(alias);
|
||||||
|
} catch (RemoteException | RuntimeException e) {
|
||||||
|
Log.i(LOG, "Couldn't get grant for wifi", e);
|
||||||
|
return null;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
Log.i(LOG, "Interrupted while getting grant for wifi", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the key is granted to WiFi stack.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi
|
||||||
|
@WorkerThread
|
||||||
|
public static boolean hasWifiKeyGrantAsUser(
|
||||||
|
@NonNull Context context, @NonNull UserHandle user, @NonNull String alias) {
|
||||||
|
try (KeyChainConnection keyChainConnection =
|
||||||
|
bindAsUser(context.getApplicationContext(), user)) {
|
||||||
|
return keyChainConnection.getService().hasGrant(Process.WIFI_UID, alias);
|
||||||
|
} catch (RemoteException | RuntimeException e) {
|
||||||
|
Log.i(LOG, "Couldn't query grant for wifi", e);
|
||||||
|
return false;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
Log.i(LOG, "Interrupted while querying grant for wifi", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind to KeyChainService in the target user.
|
* Bind to KeyChainService in the target user.
|
||||||
* Caller should call unbindService on the result when finished.
|
* Caller should call unbindService on the result when finished.
|
||||||
|
|||||||
@@ -143,4 +143,14 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
|
|||||||
public boolean canAdminGrantSensorsPermissionsForUser(int userId) {
|
public boolean canAdminGrantSensorsPermissionsForUser(int userId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setKeyGrantToWifiAuth(String callerPackage, String alias, boolean hasGrant) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKeyPairGrantedToWifiAuth(String callerPackage, String alias) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5460,6 +5460,42 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
|| isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
|
|| isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setKeyGrantToWifiAuth(String callerPackage, String alias, boolean hasGrant) {
|
||||||
|
Preconditions.checkStringNotEmpty(alias, "Alias to grant cannot be empty");
|
||||||
|
|
||||||
|
final CallerIdentity caller = getCallerIdentity(callerPackage);
|
||||||
|
Preconditions.checkCallAuthorization(canManageCertificates(caller));
|
||||||
|
|
||||||
|
return setKeyChainGrantInternal(alias, hasGrant, Process.WIFI_UID, caller.getUserHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKeyPairGrantedToWifiAuth(String callerPackage, String alias) {
|
||||||
|
Preconditions.checkStringNotEmpty(alias, "Alias to check cannot be empty");
|
||||||
|
|
||||||
|
final CallerIdentity caller = getCallerIdentity(callerPackage);
|
||||||
|
Preconditions.checkCallAuthorization(canManageCertificates(caller));
|
||||||
|
|
||||||
|
return mInjector.binderWithCleanCallingIdentity(() -> {
|
||||||
|
try (KeyChainConnection keyChainConnection =
|
||||||
|
KeyChain.bindAsUser(mContext, caller.getUserHandle())) {
|
||||||
|
final List<String> result = new ArrayList<>();
|
||||||
|
final int[] granteeUids = keyChainConnection.getService().getGrants(alias);
|
||||||
|
|
||||||
|
for (final int uid : granteeUids) {
|
||||||
|
if (uid == Process.WIFI_UID) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(LOG_TAG, "Querying grant to wifi auth. ", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setKeyGrantForApp(ComponentName who, String callerPackage, String alias,
|
public boolean setKeyGrantForApp(ComponentName who, String callerPackage, String alias,
|
||||||
String packageName, boolean hasGrant) {
|
String packageName, boolean hasGrant) {
|
||||||
@@ -5482,19 +5518,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
|||||||
throw new IllegalStateException("Failure getting grantee uid", e);
|
throw new IllegalStateException("Failure getting grantee uid", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return setKeyChainGrantInternal(alias, hasGrant, granteeUid, caller.getUserHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean setKeyChainGrantInternal(String alias, boolean hasGrant, int granteeUid,
|
||||||
|
UserHandle userHandle) {
|
||||||
final long id = mInjector.binderClearCallingIdentity();
|
final long id = mInjector.binderClearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
final KeyChainConnection keyChainConnection =
|
try (KeyChainConnection keyChainConnection =
|
||||||
KeyChain.bindAsUser(mContext, caller.getUserHandle());
|
KeyChain.bindAsUser(mContext, userHandle)) {
|
||||||
try {
|
|
||||||
IKeyChainService keyChain = keyChainConnection.getService();
|
IKeyChainService keyChain = keyChainConnection.getService();
|
||||||
keyChain.setGrant(granteeUid, alias, hasGrant);
|
keyChain.setGrant(granteeUid, alias, hasGrant);
|
||||||
return true;
|
return true;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(LOG_TAG, "Setting grant for package.", e);
|
Log.e(LOG_TAG, "Setting grant for package.", e);
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
|
||||||
keyChainConnection.close();
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.w(LOG_TAG, "Interrupted while setting key grant", e);
|
Log.w(LOG_TAG, "Interrupted while setting key grant", e);
|
||||||
|
|||||||
Reference in New Issue
Block a user