Merge "Refactor remote lockscreen verification API." into udc-dev

This commit is contained in:
Dmitry Dementyev
2023-03-09 22:15:43 +00:00
committed by Android (Google) Code Review
10 changed files with 88 additions and 84 deletions

View File

@@ -925,7 +925,7 @@ package android.app {
public class KeyguardManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public long addWeakEscrowToken(@NonNull byte[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.WeakEscrowTokenActivatedListener);
method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.content.Intent createConfirmDeviceCredentialForRemoteValidationIntent(@NonNull android.app.StartLockscreenValidationRequest, @NonNull android.content.ComponentName, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence);
method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.content.Intent createConfirmDeviceCredentialForRemoteValidationIntent(@NonNull android.app.RemoteLockscreenValidationSession, @NonNull android.content.ComponentName, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence, @Nullable CharSequence);
method public android.content.Intent createConfirmFactoryResetCredentialIntent(CharSequence, CharSequence, CharSequence);
method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public int getMinLockLength(boolean, int);
method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public boolean getPrivateNotificationsAllowed();
@@ -937,7 +937,7 @@ package android.app {
method @RequiresPermission(android.Manifest.permission.SHOW_KEYGUARD_MESSAGE) public void requestDismissKeyguard(@NonNull android.app.Activity, @Nullable CharSequence, @Nullable android.app.KeyguardManager.KeyguardDismissCallback);
method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public boolean setLock(int, @NonNull byte[], int);
method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public void setPrivateNotificationsAllowed(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.app.StartLockscreenValidationRequest startRemoteLockscreenValidation();
method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.app.RemoteLockscreenValidationSession startRemoteLockscreenValidation();
method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public boolean unregisterWeakEscrowTokenRemovedListener(@NonNull android.app.KeyguardManager.WeakEscrowTokenRemovedListener);
method @NonNull @RequiresPermission(android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN) public android.app.RemoteLockscreenValidationResult validateRemoteLockscreen(@NonNull byte[]);
field public static final int PASSWORD = 0; // 0x0
@@ -1026,6 +1026,7 @@ package android.app {
field public static final int RESULT_GUESS_VALID = 1; // 0x1
field public static final int RESULT_LOCKOUT = 3; // 0x3
field public static final int RESULT_NO_REMAINING_ATTEMPTS = 4; // 0x4
field public static final int RESULT_SESSION_EXPIRED = 5; // 0x5
}
public static final class RemoteLockscreenValidationResult.Builder {
@@ -1035,6 +1036,23 @@ package android.app {
method @NonNull public android.app.RemoteLockscreenValidationResult.Builder setTimeoutMillis(long);
}
public final class RemoteLockscreenValidationSession implements android.os.Parcelable {
method public int describeContents();
method public int getLockType();
method public int getRemainingAttempts();
method @NonNull public byte[] getSourcePublicKey();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.RemoteLockscreenValidationSession> CREATOR;
}
public static final class RemoteLockscreenValidationSession.Builder {
ctor public RemoteLockscreenValidationSession.Builder();
method @NonNull public android.app.RemoteLockscreenValidationSession build();
method @NonNull public android.app.RemoteLockscreenValidationSession.Builder setLockType(int);
method @NonNull public android.app.RemoteLockscreenValidationSession.Builder setRemainingAttempts(int);
method @NonNull public android.app.RemoteLockscreenValidationSession.Builder setSourcePublicKey(@NonNull byte[]);
}
public final class RuntimeAppOpAccessMessage implements android.os.Parcelable {
ctor public RuntimeAppOpAccessMessage(@IntRange(from=0L) int, @IntRange(from=0L) int, @NonNull String, @Nullable String, @NonNull String, int);
method public int describeContents();
@@ -1052,23 +1070,6 @@ package android.app {
method public void launchAssist(@Nullable android.os.Bundle);
}
public final class StartLockscreenValidationRequest implements android.os.Parcelable {
method public int describeContents();
method public int getLockscreenUiType();
method public int getRemainingAttempts();
method @NonNull public byte[] getSourcePublicKey();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.StartLockscreenValidationRequest> CREATOR;
}
public static final class StartLockscreenValidationRequest.Builder {
ctor public StartLockscreenValidationRequest.Builder();
method @NonNull public android.app.StartLockscreenValidationRequest build();
method @NonNull public android.app.StartLockscreenValidationRequest.Builder setLockscreenUiType(int);
method @NonNull public android.app.StartLockscreenValidationRequest.Builder setRemainingAttempts(int);
method @NonNull public android.app.StartLockscreenValidationRequest.Builder setSourcePublicKey(@NonNull byte[]);
}
public class StatusBarManager {
method @NonNull @RequiresPermission(android.Manifest.permission.STATUS_BAR) public android.app.StatusBarManager.DisableInfo getDisableInfo();
method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public int getNavBarMode();

View File

@@ -146,13 +146,13 @@ public class KeyguardManager {
public static final String EXTRA_CHECKBOX_LABEL = "android.app.extra.CHECKBOX_LABEL";
/**
* A {@link StartLockscreenValidationRequest} extra to be sent along with
* A {@link RemoteLockscreenValidationSession} extra to be sent along with
* {@link #ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL} containing the data needed to prompt for
* a remote device's lock screen.
* @hide
*/
public static final String EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST =
"android.app.extra.START_LOCKSCREEN_VALIDATION_REQUEST";
public static final String EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION =
"android.app.extra.REMOTE_LOCKSCREEN_VALIDATION_SESSION";
/**
* Result code returned by the activity started by
@@ -359,8 +359,7 @@ public class KeyguardManager {
/**
* Get an Intent to launch an activity to prompt the user to confirm the
* credentials (pin, pattern or password) of a remote device.
* @param startLockscreenValidationRequest contains information necessary to start remote device
* credential validation.
* @param session contains information necessary to start remote device credential validation.
* @param remoteLockscreenValidationServiceComponent
* the {@link ComponentName} of the implementation of
* {@link android.service.remotelockscreenvalidation.RemoteLockscreenValidationService}
@@ -376,15 +375,14 @@ public class KeyguardManager {
@RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN)
@NonNull
public Intent createConfirmDeviceCredentialForRemoteValidationIntent(
@NonNull StartLockscreenValidationRequest startLockscreenValidationRequest,
@NonNull RemoteLockscreenValidationSession session,
@NonNull ComponentName remoteLockscreenValidationServiceComponent,
@Nullable CharSequence title,
@Nullable CharSequence description,
@Nullable CharSequence checkboxLabel,
@Nullable CharSequence alternateButtonLabel) {
Intent intent = new Intent(ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL)
.putExtra(
EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST, startLockscreenValidationRequest)
.putExtra(EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION, session)
.putExtra(Intent.EXTRA_COMPONENT_NAME, remoteLockscreenValidationServiceComponent)
.putExtra(EXTRA_TITLE, title)
.putExtra(EXTRA_DESCRIPTION, description)
@@ -1157,7 +1155,7 @@ public class KeyguardManager {
@SystemApi
@RequiresPermission(Manifest.permission.CHECK_REMOTE_LOCKSCREEN)
@NonNull
public StartLockscreenValidationRequest startRemoteLockscreenValidation() {
public RemoteLockscreenValidationSession startRemoteLockscreenValidation() {
return mLockPatternUtils.startRemoteLockscreenValidation();
}
@@ -1165,11 +1163,10 @@ public class KeyguardManager {
* Verifies credentials guess from a remote device.
*
* <p>Secret must be encrypted using {@code SecureBox} library
* with public key from {@code StartLockscreenValidationRequest}
* with public key from {@code RemoteLockscreenValidationSession}
* and header set to {@code "encrypted_remote_credentials"} in UTF-8 encoding.
*
* @throws IllegalStateException if there is no active lock screen validation session or
* there was a decryption error.
* @throws IllegalStateException if there was a decryption error.
*
* @hide
*/

View File

@@ -55,10 +55,16 @@ public final class RemoteLockscreenValidationResult implements Parcelable {
*/
public static final int RESULT_NO_REMAINING_ATTEMPTS = 4;
/**
* New lockscreen validation session is required to verify guess.
*/
public static final int RESULT_SESSION_EXPIRED = 5;
@IntDef({RESULT_GUESS_VALID,
RESULT_GUESS_INVALID,
RESULT_LOCKOUT,
RESULT_NO_REMAINING_ATTEMPTS})
RESULT_NO_REMAINING_ATTEMPTS,
RESULT_SESSION_EXPIRED})
@Retention(RetentionPolicy.SOURCE)
@interface ResultCode {}

View File

@@ -17,4 +17,4 @@
package android.app;
/** {@hide} */
parcelable StartLockscreenValidationRequest;
parcelable RemoteLockscreenValidationSession;

View File

@@ -30,44 +30,45 @@ import java.util.Objects;
* @hide
*/
@SystemApi
public final class StartLockscreenValidationRequest implements Parcelable {
public final class RemoteLockscreenValidationSession implements Parcelable {
@LockTypes
private int mLockscreenUiType;
private int mLockType;
private byte[] mSourcePublicKey;
private int mRemainingAttempts;
public static final @NonNull Parcelable.Creator<StartLockscreenValidationRequest> CREATOR = new
Parcelable.Creator<StartLockscreenValidationRequest>() {
public static final @NonNull Parcelable.Creator<RemoteLockscreenValidationSession> CREATOR = new
Parcelable.Creator<RemoteLockscreenValidationSession>() {
@Override
public StartLockscreenValidationRequest createFromParcel(Parcel source) {
return new StartLockscreenValidationRequest(source);
public RemoteLockscreenValidationSession createFromParcel(Parcel source) {
return new RemoteLockscreenValidationSession(source);
}
@Override
public StartLockscreenValidationRequest[] newArray(int size) {
return new StartLockscreenValidationRequest[size];
public RemoteLockscreenValidationSession[] newArray(int size) {
return new RemoteLockscreenValidationSession[size];
}
};
/**
* Builder for {@code StartLockscreenValidationRequest}
* Builder for {@code RemoteLockscreenValidationSession}
*/
public static final class Builder {
private StartLockscreenValidationRequest mInstance = new StartLockscreenValidationRequest();
private RemoteLockscreenValidationSession mInstance =
new RemoteLockscreenValidationSession();
/**
* Sets UI type.
* Default value is {@code LockTypes.PASSWORD}
*
* @param lockscreenUiType The UI format
* @param lockType The UI format
* @return This builder.
*/
public @NonNull Builder setLockscreenUiType(@LockTypes int lockscreenUiType) {
mInstance.mLockscreenUiType = lockscreenUiType;
public @NonNull Builder setLockType(@LockTypes int lockType) {
mInstance.mLockType = lockType;
return this;
}
@@ -92,11 +93,11 @@ public final class StartLockscreenValidationRequest implements Parcelable {
}
/**
* Creates {@code StartLockscreenValidationRequest}
* Creates {@code RemoteLockscreenValidationSession}
*
* @throws NullPointerException if required fields are not set.
*/
public @NonNull StartLockscreenValidationRequest build() {
public @NonNull RemoteLockscreenValidationSession build() {
Objects.requireNonNull(mInstance.mSourcePublicKey);
return mInstance;
}
@@ -105,8 +106,8 @@ public final class StartLockscreenValidationRequest implements Parcelable {
/**
* Specifies lock screen credential type.
*/
public @LockTypes int getLockscreenUiType() {
return mLockscreenUiType;
public @LockTypes int getLockType() {
return mLockType;
}
/**
@@ -127,16 +128,16 @@ public final class StartLockscreenValidationRequest implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(mLockscreenUiType);
out.writeInt(mLockType);
out.writeByteArray(mSourcePublicKey);
out.writeInt(mRemainingAttempts);
}
private StartLockscreenValidationRequest() {
private RemoteLockscreenValidationSession() {
}
private StartLockscreenValidationRequest(Parcel in) {
mLockscreenUiType = in.readInt();
private RemoteLockscreenValidationSession(Parcel in) {
mLockType = in.readInt();
mSourcePublicKey = in.createByteArray();
mRemainingAttempts = in.readInt();
}

View File

@@ -18,7 +18,7 @@ package com.android.internal.widget;
import android.app.PendingIntent;
import android.app.RemoteLockscreenValidationResult;
import android.app.StartLockscreenValidationRequest;
import android.app.RemoteLockscreenValidationSession;
import android.app.trust.IStrongAuthTracker;
import android.os.Bundle;
import android.security.keystore.recovery.WrappedApplicationKey;
@@ -95,7 +95,7 @@ interface ILockSettings {
in byte[] recoveryKeyBlob,
in List<WrappedApplicationKey> applicationKeys);
void closeSession(in String sessionId);
StartLockscreenValidationRequest startRemoteLockscreenValidation();
RemoteLockscreenValidationSession startRemoteLockscreenValidation();
RemoteLockscreenValidationResult validateRemoteLockscreen(in byte[] encryptedCredential);
boolean hasSecureLockScreen();
boolean tryUnlockWithCachedUnifiedChallenge(int userId);

View File

@@ -29,7 +29,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.PropertyInvalidatedCache;
import android.app.RemoteLockscreenValidationResult;
import android.app.StartLockscreenValidationRequest;
import android.app.RemoteLockscreenValidationSession;
import android.app.admin.DevicePolicyManager;
import android.app.admin.PasswordMetrics;
import android.app.trust.IStrongAuthTracker;
@@ -1875,7 +1875,7 @@ public class LockPatternUtils {
* Starts a session to verify lockscreen credentials provided by a remote device.
*/
@NonNull
public StartLockscreenValidationRequest startRemoteLockscreenValidation() {
public RemoteLockscreenValidationSession startRemoteLockscreenValidation() {
try {
return getLockSettings().startRemoteLockscreenValidation();
} catch (RemoteException e) {

View File

@@ -56,7 +56,7 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.RemoteLockscreenValidationResult;
import android.app.StartLockscreenValidationRequest;
import android.app.RemoteLockscreenValidationSession;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DeviceStateCache;
@@ -2514,7 +2514,7 @@ public class LockSettingsService extends ILockSettings.Stub {
* Starts a session to verify lock screen credentials provided by a remote device.
*/
@NonNull
public StartLockscreenValidationRequest startRemoteLockscreenValidation() {
public RemoteLockscreenValidationSession startRemoteLockscreenValidation() {
return mRecoverableKeyStoreManager.startRemoteLockscreenValidation(this);
}

View File

@@ -31,7 +31,7 @@ import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.RemoteLockscreenValidationResult;
import android.app.StartLockscreenValidationRequest;
import android.app.RemoteLockscreenValidationSession;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
@@ -999,7 +999,7 @@ public class RecoverableKeyStoreManager {
/**
* Starts a session to verify lock screen credentials provided by a remote device.
*/
public StartLockscreenValidationRequest startRemoteLockscreenValidation(
public RemoteLockscreenValidationSession startRemoteLockscreenValidation(
LockSettingsService lockSettingsService) {
if (mRemoteLockscreenValidationSessionStorage == null) {
throw new UnsupportedOperationException("Under development");
@@ -1021,8 +1021,8 @@ public class RecoverableKeyStoreManager {
int badGuesses = mDatabase.getBadRemoteGuessCounter(userId);
int remainingAttempts = Math.max(INVALID_REMOTE_GUESS_LIMIT - badGuesses, 0);
// TODO(b/254335492): Schedule task to remove inactive session
return new StartLockscreenValidationRequest.Builder()
.setLockscreenUiType(keyguardCredentialsType)
return new RemoteLockscreenValidationSession.Builder()
.setLockType(keyguardCredentialsType)
.setRemainingAttempts(remainingAttempts)
.setSourcePublicKey(encodedPublicKey)
.build();
@@ -1046,7 +1046,9 @@ public class RecoverableKeyStoreManager {
.build();
}
if (session == null) {
throw new IllegalStateException("There is no active lock screen check session");
return new RemoteLockscreenValidationResult.Builder()
.setResultCode(RemoteLockscreenValidationResult.RESULT_SESSION_EXPIRED)
.build();
}
byte[] decryptedCredentials;
try {

View File

@@ -41,7 +41,7 @@ import android.Manifest;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.RemoteLockscreenValidationResult;
import android.app.StartLockscreenValidationRequest;
import android.app.RemoteLockscreenValidationSession;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
@@ -1326,11 +1326,10 @@ public class RecoverableKeyStoreManagerTest {
when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
LockPatternUtils.CREDENTIAL_TYPE_PIN);
StartLockscreenValidationRequest request =
RemoteLockscreenValidationSession request =
mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
int credetialsType = request.getLockscreenUiType();
assertThat(credetialsType).isEqualTo(KeyguardManager.PIN);
assertThat(request.getLockType()).isEqualTo(KeyguardManager.PIN);
assertThat(request.getRemainingAttempts()).isEqualTo(5);
verify(mLockSettingsService).getCredentialType(anyInt());
}
@@ -1340,11 +1339,10 @@ public class RecoverableKeyStoreManagerTest {
LockPatternUtils.CREDENTIAL_TYPE_PATTERN);
mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 3);
StartLockscreenValidationRequest request =
RemoteLockscreenValidationSession request =
mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
int credetialsType = request.getLockscreenUiType();
assertThat(credetialsType).isEqualTo(KeyguardManager.PATTERN);
assertThat(request.getLockType()).isEqualTo(KeyguardManager.PATTERN);
assertThat(request.getRemainingAttempts()).isEqualTo(2);
}
@Test
@@ -1353,24 +1351,23 @@ public class RecoverableKeyStoreManagerTest {
LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
mRecoverableKeyStoreDb.setBadRemoteGuessCounter(mUserId, 7);
StartLockscreenValidationRequest request =
RemoteLockscreenValidationSession request =
mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
int credetialsType = request.getLockscreenUiType();
assertThat(request.getRemainingAttempts()).isEqualTo(0);
assertThat(credetialsType).isEqualTo(KeyguardManager.PASSWORD);
assertThat(request.getLockType()).isEqualTo(KeyguardManager.PASSWORD);
}
@Test
public void validateRemoteLockscreen_noActiveSession() throws Exception {
when(mLockSettingsService.getCredentialType(anyInt())).thenReturn(
LockPatternUtils.CREDENTIAL_TYPE_NONE);
try {
mRecoverableKeyStoreManager.validateRemoteLockscreen(INVALID_GUESS,
mLockSettingsService);
fail("should have thrown");
} catch (IllegalStateException e) {
assertThat(e.getMessage()).contains("session");
}
LockPatternUtils.CREDENTIAL_TYPE_PASSWORD);
RemoteLockscreenValidationResult result =
mRecoverableKeyStoreManager.validateRemoteLockscreen(INVALID_GUESS,
mLockSettingsService);
assertThat(result.getResultCode()).isEqualTo(
RemoteLockscreenValidationResult.RESULT_SESSION_EXPIRED);
}
@Test
public void validateRemoteLockscreen_decryptionError() throws Exception {
@@ -1456,7 +1453,7 @@ public class RecoverableKeyStoreManagerTest {
}
private byte[] encryptCredentialsForNewSession(byte[] credentials) throws Exception {
StartLockscreenValidationRequest request =
RemoteLockscreenValidationSession request =
mRecoverableKeyStoreManager.startRemoteLockscreenValidation(mLockSettingsService);
PublicKey publicKey = SecureBox.decodePublicKey(request.getSourcePublicKey());
return SecureBox.encrypt(