Merge changes from topics "async-challenge", "lss-sp"
* changes: Remove GenerateChallengeBlocking from FingerprintManager Change GenerateChallengeCallback from abstract class to interface 3/n: Remove challenge from verifyCredential 2/n: Remove unnecessary RequestThrottledException for verify paths 1/n: Allow LockSettingsService to return Gatekeeper Password
This commit is contained in:
@@ -1073,12 +1073,12 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public abstract static class GenerateChallengeCallback {
|
||||
public abstract void onGenerateChallengeResult(long challenge);
|
||||
public interface GenerateChallengeCallback {
|
||||
void onGenerateChallengeResult(long challenge);
|
||||
}
|
||||
|
||||
private abstract static class InternalGenerateChallengeCallback
|
||||
extends GenerateChallengeCallback {}
|
||||
implements GenerateChallengeCallback {}
|
||||
|
||||
private class OnEnrollCancelListener implements OnCancelListener {
|
||||
@Override
|
||||
|
||||
@@ -377,12 +377,12 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public abstract static class GenerateChallengeCallback {
|
||||
public abstract void onChallengeGenerated(long challenge);
|
||||
public interface GenerateChallengeCallback {
|
||||
void onChallengeGenerated(long challenge);
|
||||
}
|
||||
|
||||
private abstract static class InternalGenerateChallengeCallback
|
||||
extends GenerateChallengeCallback {}
|
||||
implements GenerateChallengeCallback {}
|
||||
|
||||
/**
|
||||
* Request authentication of a crypto object. This call warms up the fingerprint hardware
|
||||
@@ -580,37 +580,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #generateChallenge(GenerateChallengeCallback)}, except blocks until the
|
||||
* TEE/hardware operation is complete.
|
||||
* @return challenge generated in the TEE/hardware
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(MANAGE_FINGERPRINT)
|
||||
public long generateChallengeBlocking() {
|
||||
final AtomicReference<Long> result = new AtomicReference<>();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final GenerateChallengeCallback callback = new InternalGenerateChallengeCallback() {
|
||||
@Override
|
||||
public void onChallengeGenerated(long challenge) {
|
||||
result.set(challenge);
|
||||
latch.countDown();
|
||||
}
|
||||
};
|
||||
|
||||
generateChallenge(callback);
|
||||
|
||||
try {
|
||||
latch.await(1, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Slog.e(TAG, "Interrupted while generatingChallenge", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return result.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a unique random challenge in the TEE. A typical use case is to have it wrapped in a
|
||||
* HardwareAuthenticationToken, minted by Gatekeeper upon PIN/Pattern/Password verification.
|
||||
|
||||
@@ -47,8 +47,9 @@ interface ILockSettings {
|
||||
void resetKeyStore(int userId);
|
||||
VerifyCredentialResponse checkCredential(in LockscreenCredential credential, int userId,
|
||||
in ICheckCredentialProgressCallback progressCallback);
|
||||
VerifyCredentialResponse verifyCredential(in LockscreenCredential credential, long challenge, int userId);
|
||||
VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, long challenge, int userId);
|
||||
VerifyCredentialResponse verifyCredential(in LockscreenCredential credential, int userId, int flags);
|
||||
VerifyCredentialResponse verifyTiedProfileChallenge(in LockscreenCredential credential, int userId, int flags);
|
||||
VerifyCredentialResponse verifyGatekeeperPassword(in byte[] gatekeeperPassword, long challenge, int userId);
|
||||
boolean checkVoldPassword(int userId);
|
||||
int getCredentialType(int userId);
|
||||
byte[] getHashFactor(in LockscreenCredential currentCredential, int userId);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.android.internal.widget;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
|
||||
@@ -41,11 +42,11 @@ public final class LockPatternChecker {
|
||||
/**
|
||||
* Invoked when a security verification is finished.
|
||||
*
|
||||
* @param attestation The attestation that the challenge was verified, or null.
|
||||
* @param response The response, optionally containing Gatekeeper HAT or Gatekeeper Password
|
||||
* @param throttleTimeoutMs The amount of time in ms to wait before reattempting
|
||||
* the call. Only non-0 if attestation is null.
|
||||
* the call. Only non-0 if the response is {@link VerifyCredentialResponse#RESPONSE_RETRY}.
|
||||
*/
|
||||
void onVerified(byte[] attestation, int throttleTimeoutMs);
|
||||
void onVerified(@NonNull VerifyCredentialResponse response, int throttleTimeoutMs);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,33 +54,27 @@ public final class LockPatternChecker {
|
||||
*
|
||||
* @param utils The LockPatternUtils instance to use.
|
||||
* @param credential The credential to check.
|
||||
* @param challenge The challenge to verify against the credential.
|
||||
* @param userId The user to check against the credential.
|
||||
* @param flags See {@link LockPatternUtils.VerifyFlag}
|
||||
* @param callback The callback to be invoked with the verification result.
|
||||
*/
|
||||
public static AsyncTask<?, ?, ?> verifyCredential(final LockPatternUtils utils,
|
||||
final LockscreenCredential credential,
|
||||
final long challenge,
|
||||
final int userId,
|
||||
final @LockPatternUtils.VerifyFlag int flags,
|
||||
final OnVerifyCallback callback) {
|
||||
// Create a copy of the credential since checking credential is asynchrounous.
|
||||
final LockscreenCredential credentialCopy = credential.duplicate();
|
||||
AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
|
||||
private int mThrottleTimeout;
|
||||
|
||||
AsyncTask<Void, Void, VerifyCredentialResponse> task =
|
||||
new AsyncTask<Void, Void, VerifyCredentialResponse>() {
|
||||
@Override
|
||||
protected byte[] doInBackground(Void... args) {
|
||||
try {
|
||||
return utils.verifyCredential(credentialCopy, challenge, userId);
|
||||
} catch (RequestThrottledException ex) {
|
||||
mThrottleTimeout = ex.getTimeoutMs();
|
||||
return null;
|
||||
}
|
||||
protected VerifyCredentialResponse doInBackground(Void... args) {
|
||||
return utils.verifyCredential(credentialCopy, userId, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(byte[] result) {
|
||||
callback.onVerified(result, mThrottleTimeout);
|
||||
protected void onPostExecute(@NonNull VerifyCredentialResponse result) {
|
||||
callback.onVerified(result, result.getTimeout());
|
||||
credentialCopy.zeroize();
|
||||
}
|
||||
|
||||
@@ -141,33 +136,27 @@ public final class LockPatternChecker {
|
||||
*
|
||||
* @param utils The LockPatternUtils instance to use.
|
||||
* @param credential The credential to check.
|
||||
* @param challenge The challenge to verify against the credential.
|
||||
* @param userId The user to check against the credential.
|
||||
* @param flags See {@link LockPatternUtils.VerifyFlag}
|
||||
* @param callback The callback to be invoked with the verification result.
|
||||
*/
|
||||
public static AsyncTask<?, ?, ?> verifyTiedProfileChallenge(final LockPatternUtils utils,
|
||||
final LockscreenCredential credential,
|
||||
final long challenge,
|
||||
final int userId,
|
||||
final @LockPatternUtils.VerifyFlag int flags,
|
||||
final OnVerifyCallback callback) {
|
||||
// Create a copy of the credential since checking credential is asynchrounous.
|
||||
// Create a copy of the credential since checking credential is asynchronous.
|
||||
final LockscreenCredential credentialCopy = credential.duplicate();
|
||||
AsyncTask<Void, Void, byte[]> task = new AsyncTask<Void, Void, byte[]>() {
|
||||
private int mThrottleTimeout;
|
||||
|
||||
AsyncTask<Void, Void, VerifyCredentialResponse> task =
|
||||
new AsyncTask<Void, Void, VerifyCredentialResponse>() {
|
||||
@Override
|
||||
protected byte[] doInBackground(Void... args) {
|
||||
try {
|
||||
return utils.verifyTiedProfileChallenge(credentialCopy, challenge, userId);
|
||||
} catch (RequestThrottledException ex) {
|
||||
mThrottleTimeout = ex.getTimeoutMs();
|
||||
return null;
|
||||
}
|
||||
protected VerifyCredentialResponse doInBackground(Void... args) {
|
||||
return utils.verifyTiedProfileChallenge(credentialCopy, userId, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(byte[] result) {
|
||||
callback.onVerified(result, mThrottleTimeout);
|
||||
protected void onPostExecute(@NonNull VerifyCredentialResponse response) {
|
||||
callback.onVerified(response, response.getTimeout());
|
||||
credentialCopy.zeroize();
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,18 @@ public class LockPatternUtils {
|
||||
})
|
||||
public @interface CredentialType {}
|
||||
|
||||
/**
|
||||
* Flag provided to {@link #verifyCredential(LockscreenCredential, long, int, int)} . If set,
|
||||
* the method will return the Gatekeeper Password in the {@link VerifyCredentialResponse}.
|
||||
*/
|
||||
public static final int VERIFY_FLAG_RETURN_GK_PW = 1 << 0;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = true, value = {
|
||||
VERIFY_FLAG_RETURN_GK_PW
|
||||
})
|
||||
public @interface VerifyFlag {}
|
||||
|
||||
/**
|
||||
* Special user id for triggering the FRP verification flow.
|
||||
*/
|
||||
@@ -374,29 +386,46 @@ public class LockPatternUtils {
|
||||
* If credential matches, return an opaque attestation that the challenge was verified.
|
||||
*
|
||||
* @param credential The credential to check.
|
||||
* @param challenge The challenge to verify against the credential
|
||||
* @param userId The user whose credential is being verified
|
||||
* @return the attestation that the challenge was verified, or null
|
||||
* @throws RequestThrottledException if credential verification is being throttled due to
|
||||
* to many incorrect attempts.
|
||||
* @param flags See {@link VerifyFlag}
|
||||
* @throws IllegalStateException if called on the main thread.
|
||||
*/
|
||||
public byte[] verifyCredential(@NonNull LockscreenCredential credential, long challenge,
|
||||
int userId) throws RequestThrottledException {
|
||||
@NonNull
|
||||
public VerifyCredentialResponse verifyCredential(@NonNull LockscreenCredential credential,
|
||||
int userId, @VerifyFlag int flags) {
|
||||
throwIfCalledOnMainThread();
|
||||
try {
|
||||
VerifyCredentialResponse response = getLockSettings().verifyCredential(
|
||||
credential, challenge, userId);
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
return response.getPayload();
|
||||
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
|
||||
throw new RequestThrottledException(response.getTimeout());
|
||||
final VerifyCredentialResponse response = getLockSettings().verifyCredential(
|
||||
credential, userId, flags);
|
||||
if (response == null) {
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
} else {
|
||||
return null;
|
||||
return response;
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Log.e(TAG, "failed to verify credential", re);
|
||||
return null;
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* With the Gatekeeper Password returned via {@link #verifyCredential(LockscreenCredential,
|
||||
* int, int)}, request Gatekeeper to create a HardwareAuthToken wrapping the given
|
||||
* challenge.
|
||||
*/
|
||||
@NonNull
|
||||
public VerifyCredentialResponse verifyGatekeeperPassword(@NonNull byte[] gatekeeperPassword,
|
||||
long challenge, int userId) {
|
||||
try {
|
||||
final VerifyCredentialResponse response = getLockSettings().verifyGatekeeperPassword(
|
||||
gatekeeperPassword, challenge, userId);
|
||||
if (response == null) {
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
}
|
||||
return response;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "failed to verify gatekeeper password", e);
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,8 +447,9 @@ public class LockPatternUtils {
|
||||
try {
|
||||
VerifyCredentialResponse response = getLockSettings().checkCredential(
|
||||
credential, userId, wrapCallback(progressCallback));
|
||||
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
if (response == null) {
|
||||
return false;
|
||||
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
return true;
|
||||
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
|
||||
throw new RequestThrottledException(response.getTimeout());
|
||||
@@ -439,30 +469,26 @@ public class LockPatternUtils {
|
||||
* verified.
|
||||
*
|
||||
* @param credential The parent user's credential to check.
|
||||
* @param challenge The challenge to verify against the credential
|
||||
* @return the attestation that the challenge was verified, or null
|
||||
* @param userId The managed profile user id
|
||||
* @throws RequestThrottledException if credential verification is being throttled due to
|
||||
* to many incorrect attempts.
|
||||
* @param flags See {@link VerifyFlag}
|
||||
* @throws IllegalStateException if called on the main thread.
|
||||
*/
|
||||
public byte[] verifyTiedProfileChallenge(@NonNull LockscreenCredential credential,
|
||||
long challenge, int userId) throws RequestThrottledException {
|
||||
@NonNull
|
||||
public VerifyCredentialResponse verifyTiedProfileChallenge(
|
||||
@NonNull LockscreenCredential credential, int userId, @VerifyFlag int flags) {
|
||||
throwIfCalledOnMainThread();
|
||||
try {
|
||||
VerifyCredentialResponse response =
|
||||
getLockSettings().verifyTiedProfileChallenge(credential, challenge, userId);
|
||||
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
return response.getPayload();
|
||||
} else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
|
||||
throw new RequestThrottledException(response.getTimeout());
|
||||
final VerifyCredentialResponse response = getLockSettings()
|
||||
.verifyTiedProfileChallenge(credential, userId, flags);
|
||||
if (response == null) {
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
} else {
|
||||
return null;
|
||||
return response;
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Log.e(TAG, "failed to verify tied profile credential", re);
|
||||
return null;
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ import java.util.Objects;
|
||||
* // Process the credential in some way
|
||||
* }
|
||||
* </pre>
|
||||
* With this construct, we can garantee that there will be no copies of the password left in
|
||||
* With this construct, we can guarantee that there will be no copies of the password left in
|
||||
* memory when the credential goes out of scope. This should help mitigate certain class of
|
||||
* attacks where the attcker gains read-only access to full device memory (cold boot attack,
|
||||
* unsecured software/hardware memory dumping interfaces such as JTAG).
|
||||
|
||||
@@ -16,11 +16,16 @@
|
||||
|
||||
package com.android.internal.widget;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.service.gatekeeper.GateKeeperResponse;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Response object for a ILockSettings credential verification request.
|
||||
* @hide
|
||||
@@ -30,78 +35,114 @@ public final class VerifyCredentialResponse implements Parcelable {
|
||||
public static final int RESPONSE_ERROR = -1;
|
||||
public static final int RESPONSE_OK = 0;
|
||||
public static final int RESPONSE_RETRY = 1;
|
||||
@IntDef({RESPONSE_ERROR,
|
||||
RESPONSE_OK,
|
||||
RESPONSE_RETRY})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface ResponseCode {}
|
||||
|
||||
public static final VerifyCredentialResponse OK = new VerifyCredentialResponse();
|
||||
public static final VerifyCredentialResponse ERROR
|
||||
= new VerifyCredentialResponse(RESPONSE_ERROR, 0, null);
|
||||
public static final VerifyCredentialResponse OK = new VerifyCredentialResponse.Builder()
|
||||
.build();
|
||||
public static final VerifyCredentialResponse ERROR = fromError();
|
||||
private static final String TAG = "VerifyCredentialResponse";
|
||||
|
||||
private int mResponseCode;
|
||||
private byte[] mPayload;
|
||||
private int mTimeout;
|
||||
private final @ResponseCode int mResponseCode;
|
||||
private final int mTimeout;
|
||||
@Nullable private final byte[] mGatekeeperHAT;
|
||||
@Nullable private final byte[] mGatekeeperPw;
|
||||
|
||||
public static final Parcelable.Creator<VerifyCredentialResponse> CREATOR
|
||||
= new Parcelable.Creator<VerifyCredentialResponse>() {
|
||||
@Override
|
||||
public VerifyCredentialResponse createFromParcel(Parcel source) {
|
||||
int responseCode = source.readInt();
|
||||
VerifyCredentialResponse response = new VerifyCredentialResponse(responseCode, 0, null);
|
||||
if (responseCode == RESPONSE_RETRY) {
|
||||
response.setTimeout(source.readInt());
|
||||
} else if (responseCode == RESPONSE_OK) {
|
||||
int size = source.readInt();
|
||||
if (size > 0) {
|
||||
byte[] payload = new byte[size];
|
||||
source.readByteArray(payload);
|
||||
response.setPayload(payload);
|
||||
}
|
||||
}
|
||||
return response;
|
||||
final @ResponseCode int responseCode = source.readInt();
|
||||
final int timeout = source.readInt();
|
||||
final byte[] gatekeeperHAT = source.createByteArray();
|
||||
final byte[] gatekeeperPassword = source.createByteArray();
|
||||
|
||||
return new VerifyCredentialResponse(responseCode, timeout, gatekeeperHAT,
|
||||
gatekeeperPassword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifyCredentialResponse[] newArray(int size) {
|
||||
return new VerifyCredentialResponse[size];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public VerifyCredentialResponse() {
|
||||
mResponseCode = RESPONSE_OK;
|
||||
mPayload = null;
|
||||
public static class Builder {
|
||||
@Nullable private byte[] mGatekeeperHAT;
|
||||
@Nullable private byte[] mGatekeeperPassword;
|
||||
|
||||
/**
|
||||
* @param gatekeeperHAT Gatekeeper HardwareAuthToken, minted upon successful authentication.
|
||||
*/
|
||||
public Builder setGatekeeperHAT(byte[] gatekeeperHAT) {
|
||||
mGatekeeperHAT = gatekeeperHAT;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setGatekeeperPassword(byte[] gatekeeperPassword) {
|
||||
mGatekeeperPassword = gatekeeperPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a VerifyCredentialResponse with {@link #RESPONSE_OK} and any other parameters
|
||||
* that were preveiously set.
|
||||
* @return
|
||||
*/
|
||||
public VerifyCredentialResponse build() {
|
||||
return new VerifyCredentialResponse(RESPONSE_OK,
|
||||
0 /* timeout */,
|
||||
mGatekeeperHAT,
|
||||
mGatekeeperPassword);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public VerifyCredentialResponse(byte[] payload) {
|
||||
mPayload = payload;
|
||||
mResponseCode = RESPONSE_OK;
|
||||
/**
|
||||
* Since timeouts are always an error, provide a way to create the VerifyCredentialResponse
|
||||
* object directly. None of the other fields (Gatekeeper HAT, Gatekeeper Password, etc)
|
||||
* are valid in this case. Similarly, the response code will always be
|
||||
* {@link #RESPONSE_RETRY}.
|
||||
*/
|
||||
public static VerifyCredentialResponse fromTimeout(int timeout) {
|
||||
return new VerifyCredentialResponse(RESPONSE_RETRY,
|
||||
timeout,
|
||||
null /* gatekeeperHAT */,
|
||||
null /* gatekeeperPassword */);
|
||||
}
|
||||
|
||||
public VerifyCredentialResponse(int timeout) {
|
||||
mTimeout = timeout;
|
||||
mResponseCode = RESPONSE_RETRY;
|
||||
mPayload = null;
|
||||
/**
|
||||
* Since error (incorrect password) should never result in any of the other fields from
|
||||
* being populated, provide a default method to return a VerifyCredentialResponse.
|
||||
*/
|
||||
public static VerifyCredentialResponse fromError() {
|
||||
return new VerifyCredentialResponse(RESPONSE_ERROR,
|
||||
0 /* timeout */,
|
||||
null /* gatekeeperHAT */,
|
||||
null /* gatekeeperPassword */);
|
||||
}
|
||||
|
||||
private VerifyCredentialResponse(int responseCode, int timeout, byte[] payload) {
|
||||
private VerifyCredentialResponse(@ResponseCode int responseCode, int timeout,
|
||||
@Nullable byte[] gatekeeperHAT, @Nullable byte[] gatekeeperPassword) {
|
||||
mResponseCode = responseCode;
|
||||
mTimeout = timeout;
|
||||
mPayload = payload;
|
||||
mGatekeeperHAT = gatekeeperHAT;
|
||||
mGatekeeperPw = gatekeeperPassword;
|
||||
}
|
||||
|
||||
public VerifyCredentialResponse stripPayload() {
|
||||
return new VerifyCredentialResponse(mResponseCode, mTimeout,
|
||||
null /* gatekeeperHAT */, null /* gatekeeperPassword */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mResponseCode);
|
||||
if (mResponseCode == RESPONSE_RETRY) {
|
||||
dest.writeInt(mTimeout);
|
||||
} else if (mResponseCode == RESPONSE_OK) {
|
||||
if (mPayload != null) {
|
||||
dest.writeInt(mPayload.length);
|
||||
dest.writeByteArray(mPayload);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
}
|
||||
dest.writeInt(mTimeout);
|
||||
dest.writeByteArray(mGatekeeperHAT);
|
||||
dest.writeByteArray(mGatekeeperPw);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,48 +150,51 @@ public final class VerifyCredentialResponse implements Parcelable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
return mPayload;
|
||||
@Nullable
|
||||
public byte[] getGatekeeperHAT() {
|
||||
return mGatekeeperHAT;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public byte[] getGatekeeperPw() {
|
||||
return mGatekeeperPw;
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return mTimeout;
|
||||
}
|
||||
|
||||
public int getResponseCode() {
|
||||
public @ResponseCode int getResponseCode() {
|
||||
return mResponseCode;
|
||||
}
|
||||
|
||||
private void setTimeout(int timeout) {
|
||||
mTimeout = timeout;
|
||||
public boolean isMatched() {
|
||||
return mResponseCode == RESPONSE_OK;
|
||||
}
|
||||
|
||||
private void setPayload(byte[] payload) {
|
||||
mPayload = payload;
|
||||
}
|
||||
|
||||
public VerifyCredentialResponse stripPayload() {
|
||||
return new VerifyCredentialResponse(mResponseCode, mTimeout, new byte[0]);
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Response: " + mResponseCode
|
||||
+ ", GK HAT: " + (mGatekeeperHAT != null)
|
||||
+ ", GK PW: " + (mGatekeeperPw != null);
|
||||
}
|
||||
|
||||
public static VerifyCredentialResponse fromGateKeeperResponse(
|
||||
GateKeeperResponse gateKeeperResponse) {
|
||||
VerifyCredentialResponse response;
|
||||
int responseCode = gateKeeperResponse.getResponseCode();
|
||||
if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
|
||||
response = new VerifyCredentialResponse(gateKeeperResponse.getTimeout());
|
||||
return fromTimeout(gateKeeperResponse.getTimeout());
|
||||
} else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
|
||||
byte[] token = gateKeeperResponse.getPayload();
|
||||
if (token == null) {
|
||||
// something's wrong if there's no payload with a challenge
|
||||
Slog.e(TAG, "verifyChallenge response had no associated payload");
|
||||
response = VerifyCredentialResponse.ERROR;
|
||||
return fromError();
|
||||
} else {
|
||||
response = new VerifyCredentialResponse(token);
|
||||
return new VerifyCredentialResponse.Builder().setGatekeeperHAT(token).build();
|
||||
}
|
||||
} else {
|
||||
response = VerifyCredentialResponse.ERROR;
|
||||
return fromError();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.text.InputType;
|
||||
@@ -27,7 +28,9 @@ import android.widget.ImeAwareEditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.systemui.R;
|
||||
|
||||
/**
|
||||
@@ -104,18 +107,21 @@ public class AuthCredentialPasswordView extends AuthCredentialView
|
||||
return;
|
||||
}
|
||||
|
||||
// Request LockSettingsService to return the Gatekeeper Password in the
|
||||
// VerifyCredentialResponse so that we can request a Gatekeeper HAT with the
|
||||
// Gatekeeper Password and operationId.
|
||||
mPendingLockCheck = LockPatternChecker.verifyCredential(mLockPatternUtils,
|
||||
password, mOperationId, mEffectiveUserId, this::onCredentialVerified);
|
||||
password, mEffectiveUserId, LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW,
|
||||
this::onCredentialVerified);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCredentialVerified(byte[] attestation, int timeoutMs) {
|
||||
super.onCredentialVerified(attestation, timeoutMs);
|
||||
protected void onCredentialVerified(@NonNull VerifyCredentialResponse response,
|
||||
int timeoutMs) {
|
||||
super.onCredentialVerified(response, timeoutMs);
|
||||
|
||||
final boolean matched = attestation != null;
|
||||
|
||||
if (matched) {
|
||||
if (response.isMatched()) {
|
||||
mImm.hideSoftInputFromWindow(getWindowToken(), 0 /* flags */);
|
||||
} else {
|
||||
mPasswordField.setText("");
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
@@ -23,6 +24,7 @@ import com.android.internal.widget.LockPatternChecker;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LockscreenCredential;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.util.List;
|
||||
@@ -61,22 +63,25 @@ public class AuthCredentialPatternView extends AuthCredentialView {
|
||||
|
||||
if (pattern.size() < LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
|
||||
// Pattern size is less than the minimum, do not count it as a failed attempt.
|
||||
onPatternVerified(null /* attestation */, 0 /* timeoutMs */);
|
||||
onPatternVerified(VerifyCredentialResponse.ERROR, 0 /* timeoutMs */);
|
||||
return;
|
||||
}
|
||||
|
||||
try (LockscreenCredential credential = LockscreenCredential.createPattern(pattern)) {
|
||||
// Request LockSettingsService to return the Gatekeeper Password in the
|
||||
// VerifyCredentialResponse so that we can request a Gatekeeper HAT with the
|
||||
// Gatekeeper Password and operationId.
|
||||
mPendingLockCheck = LockPatternChecker.verifyCredential(
|
||||
mLockPatternUtils,
|
||||
credential,
|
||||
mOperationId,
|
||||
mEffectiveUserId,
|
||||
LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW,
|
||||
this::onPatternVerified);
|
||||
}
|
||||
}
|
||||
|
||||
private void onPatternVerified(byte[] attestation, int timeoutMs) {
|
||||
AuthCredentialPatternView.this.onCredentialVerified(attestation, timeoutMs);
|
||||
private void onPatternVerified(@NonNull VerifyCredentialResponse response, int timeoutMs) {
|
||||
AuthCredentialPatternView.this.onCredentialVerified(response, timeoutMs);
|
||||
if (timeoutMs > 0) {
|
||||
mLockPatternView.setEnabled(false);
|
||||
} else {
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.systemui.biometrics;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
@@ -38,12 +41,10 @@ import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.VerifyCredentialResponse;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
|
||||
@@ -283,14 +284,18 @@ public abstract class AuthCredentialView extends LinearLayout {
|
||||
|
||||
protected void onErrorTimeoutFinish() {}
|
||||
|
||||
protected void onCredentialVerified(byte[] attestation, int timeoutMs) {
|
||||
|
||||
final boolean matched = attestation != null;
|
||||
|
||||
if (matched) {
|
||||
protected void onCredentialVerified(@NonNull VerifyCredentialResponse response, int timeoutMs) {
|
||||
if (response.isMatched()) {
|
||||
mClearErrorRunnable.run();
|
||||
mLockPatternUtils.userPresent(mEffectiveUserId);
|
||||
mCallback.onCredentialMatched(attestation);
|
||||
|
||||
// The response passed into this method contains the Gatekeeper Password. We still
|
||||
// have to request Gatekeeper to create a Hardware Auth Token with the
|
||||
// Gatekeeper Password and Challenge (keystore operationId in this case)
|
||||
final VerifyCredentialResponse gkResponse = mLockPatternUtils.verifyGatekeeperPassword(
|
||||
response.getGatekeeperPw(), mOperationId, mEffectiveUserId);
|
||||
|
||||
mCallback.onCredentialMatched(gkResponse.getGatekeeperHAT());
|
||||
} else {
|
||||
if (timeoutMs > 0) {
|
||||
mHandler.removeCallbacks(mClearErrorRunnable);
|
||||
|
||||
@@ -33,6 +33,7 @@ import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HA
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
|
||||
import static com.android.internal.widget.LockPatternUtils.USER_FRP;
|
||||
import static com.android.internal.widget.LockPatternUtils.VERIFY_FLAG_RETURN_GK_PW;
|
||||
import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled;
|
||||
import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential;
|
||||
|
||||
@@ -186,6 +187,9 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
private static final String SYNTHETIC_PASSWORD_UPDATE_TIME_KEY = "sp-handle-ts";
|
||||
private static final String USER_SERIAL_NUMBER_KEY = "serial-number";
|
||||
|
||||
// TODO (b/145978626) LockSettingsService no longer accepts challenges in the verifyCredential
|
||||
// paths. These are temporarily left around to ensure that resetLockout works. It will be
|
||||
// removed once resetLockout is compartmentalized.
|
||||
// No challenge provided
|
||||
private static final int CHALLENGE_NONE = 0;
|
||||
// Challenge was provided from the external caller (non-LockSettingsService)
|
||||
@@ -1308,7 +1312,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
try {
|
||||
doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
|
||||
challengeType, challenge, profileHandle, null /* progressCallback */,
|
||||
resetLockouts);
|
||||
resetLockouts, 0 /* flags */);
|
||||
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
|
||||
| NoSuchAlgorithmException | NoSuchPaddingException
|
||||
| InvalidAlgorithmParameterException | IllegalBlockSizeException
|
||||
@@ -1608,8 +1612,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
// Verify the parent credential again, to make sure we have a fresh enough
|
||||
// auth token such that getDecryptedPasswordForTiedProfile() inside
|
||||
// setLockCredentialInternal() can function correctly.
|
||||
verifyCredential(savedCredential, /* challenge */ 0,
|
||||
mUserManager.getProfileParent(userId).id);
|
||||
verifyCredential(savedCredential, mUserManager.getProfileParent(userId).id,
|
||||
0 /* flags */);
|
||||
savedCredential.zeroize();
|
||||
savedCredential = LockscreenCredential.createNone();
|
||||
}
|
||||
@@ -1724,7 +1728,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
fixateNewestUserKeyAuth(userId);
|
||||
// Refresh the auth token
|
||||
doVerifyCredential(credential, CHALLENGE_FROM_CALLER, 0, userId,
|
||||
null /* progressCallback */);
|
||||
null /* progressCallback */, 0 /* flags */);
|
||||
synchronizeUnifiedWorkChallengeForProfiles(userId, null);
|
||||
sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
|
||||
return true;
|
||||
@@ -1835,7 +1839,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
throw new IllegalArgumentException("Non-OK response verifying a credential we just set "
|
||||
+ vcr.getResponseCode());
|
||||
}
|
||||
byte[] token = vcr.getPayload();
|
||||
byte[] token = vcr.getGatekeeperHAT();
|
||||
if (token == null) {
|
||||
throw new IllegalArgumentException("Empty payload verifying a credential we just set");
|
||||
}
|
||||
@@ -1968,35 +1972,56 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
ICheckCredentialProgressCallback progressCallback) {
|
||||
checkPasswordReadPermission(userId);
|
||||
try {
|
||||
return doVerifyCredential(credential, CHALLENGE_NONE, 0, userId, progressCallback);
|
||||
return doVerifyCredential(credential, CHALLENGE_NONE, 0L, userId, progressCallback,
|
||||
0 /* flags */);
|
||||
} finally {
|
||||
scheduleGc();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public VerifyCredentialResponse verifyCredential(LockscreenCredential credential,
|
||||
long challenge, int userId) {
|
||||
int userId, int flags) {
|
||||
checkPasswordReadPermission(userId);
|
||||
@ChallengeType int challengeType = CHALLENGE_FROM_CALLER;
|
||||
if (challenge == 0) {
|
||||
Slog.w(TAG, "VerifyCredential called with challenge=0");
|
||||
challengeType = CHALLENGE_NONE;
|
||||
|
||||
}
|
||||
try {
|
||||
return doVerifyCredential(credential, challengeType, challenge, userId,
|
||||
null /* progressCallback */);
|
||||
return doVerifyCredential(credential, CHALLENGE_NONE, 0L, userId,
|
||||
null /* progressCallback */, flags);
|
||||
} finally {
|
||||
scheduleGc();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VerifyCredentialResponse verifyGatekeeperPassword(byte[] gatekeeperPassword,
|
||||
long challenge, int userId) {
|
||||
checkPasswordReadPermission(userId);
|
||||
|
||||
VerifyCredentialResponse response;
|
||||
synchronized (mSpManager) {
|
||||
response = mSpManager.verifyChallengeInternal(getGateKeeperService(),
|
||||
gatekeeperPassword, challenge, userId);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param credential User's lockscreen credential
|
||||
* @param challengeType Owner of the challenge
|
||||
* @param challenge Challenge to be wrapped within Gatekeeper's HAT, if the credential is
|
||||
* verified
|
||||
* @param userId User to verify the credential for
|
||||
* @param progressCallback Receive progress callbacks
|
||||
* @param flags See {@link LockPatternUtils.VerifyFlag}
|
||||
* @return See {@link VerifyCredentialResponse}
|
||||
*/
|
||||
private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
|
||||
@ChallengeType int challengeType, long challenge, int userId,
|
||||
ICheckCredentialProgressCallback progressCallback) {
|
||||
ICheckCredentialProgressCallback progressCallback,
|
||||
@LockPatternUtils.VerifyFlag int flags) {
|
||||
return doVerifyCredential(credential, challengeType, challenge, userId,
|
||||
progressCallback, null /* resetLockouts */);
|
||||
progressCallback, null /* resetLockouts */, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2006,7 +2031,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
private VerifyCredentialResponse doVerifyCredential(LockscreenCredential credential,
|
||||
@ChallengeType int challengeType, long challenge, int userId,
|
||||
ICheckCredentialProgressCallback progressCallback,
|
||||
@Nullable ArrayList<PendingResetLockout> resetLockouts) {
|
||||
@Nullable ArrayList<PendingResetLockout> resetLockouts,
|
||||
@LockPatternUtils.VerifyFlag int flags) {
|
||||
if (credential == null || credential.isNone()) {
|
||||
throw new IllegalArgumentException("Credential can't be null or empty");
|
||||
}
|
||||
@@ -2017,7 +2043,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
VerifyCredentialResponse response = null;
|
||||
response = spBasedDoVerifyCredential(credential, challengeType, challenge,
|
||||
userId, progressCallback, resetLockouts);
|
||||
userId, progressCallback, resetLockouts, flags);
|
||||
// The user employs synthetic password based credential.
|
||||
if (response != null) {
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
@@ -2050,7 +2076,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
|
||||
@Override
|
||||
public VerifyCredentialResponse verifyTiedProfileChallenge(LockscreenCredential credential,
|
||||
long challenge, int userId) {
|
||||
int userId, @LockPatternUtils.VerifyFlag int flags) {
|
||||
checkPasswordReadPermission(userId);
|
||||
if (!isManagedProfileWithUnifiedLock(userId)) {
|
||||
throw new IllegalArgumentException("User id must be managed profile with unified lock");
|
||||
@@ -2059,10 +2085,11 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
// Unlock parent by using parent's challenge
|
||||
final VerifyCredentialResponse parentResponse = doVerifyCredential(
|
||||
credential,
|
||||
CHALLENGE_FROM_CALLER,
|
||||
challenge,
|
||||
CHALLENGE_NONE,
|
||||
0L,
|
||||
parentProfileId,
|
||||
null /* progressCallback */);
|
||||
null /* progressCallback */,
|
||||
flags);
|
||||
if (parentResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
|
||||
// Failed, just return parent's response
|
||||
return parentResponse;
|
||||
@@ -2071,9 +2098,10 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
try {
|
||||
// Unlock work profile, and work profile with unified lock must use password only
|
||||
return doVerifyCredential(getDecryptedPasswordForTiedProfile(userId),
|
||||
CHALLENGE_FROM_CALLER,
|
||||
challenge,
|
||||
userId, null /* progressCallback */);
|
||||
CHALLENGE_NONE,
|
||||
0L,
|
||||
userId, null /* progressCallback */,
|
||||
flags);
|
||||
} catch (UnrecoverableKeyException | InvalidKeyException | KeyStoreException
|
||||
| NoSuchAlgorithmException | NoSuchPaddingException
|
||||
| InvalidAlgorithmParameterException | IllegalBlockSizeException
|
||||
@@ -2132,8 +2160,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
unlockKeystore(credential.getCredential(), userId);
|
||||
|
||||
Slog.i(TAG, "Unlocking user " + userId + " with token length "
|
||||
+ response.getPayload().length);
|
||||
unlockUser(userId, response.getPayload(), secretFromCredential(credential));
|
||||
+ response.getGatekeeperHAT().length);
|
||||
unlockUser(userId, response.getGatekeeperHAT(), secretFromCredential(credential));
|
||||
|
||||
if (isManagedProfileWithSeparatedLock(userId)) {
|
||||
setDeviceUnlockedForUser(userId);
|
||||
@@ -2684,7 +2712,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
private VerifyCredentialResponse spBasedDoVerifyCredential(LockscreenCredential userCredential,
|
||||
@ChallengeType int challengeType, long challenge,
|
||||
int userId, ICheckCredentialProgressCallback progressCallback,
|
||||
@Nullable ArrayList<PendingResetLockout> resetLockouts) {
|
||||
@Nullable ArrayList<PendingResetLockout> resetLockouts,
|
||||
@LockPatternUtils.VerifyFlag int flags) {
|
||||
|
||||
final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId);
|
||||
|
||||
@@ -2705,6 +2734,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
|
||||
final AuthenticationResult authResult;
|
||||
VerifyCredentialResponse response;
|
||||
final boolean returnGkPw = (flags & VERIFY_FLAG_RETURN_GK_PW) != 0;
|
||||
|
||||
synchronized (mSpManager) {
|
||||
if (!isSyntheticPasswordBasedCredentialLocked(userId)) {
|
||||
return null;
|
||||
@@ -2717,8 +2748,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
long handle = getSyntheticPasswordHandleLocked(userId);
|
||||
authResult = mSpManager.unwrapPasswordBasedSyntheticPassword(
|
||||
getGateKeeperService(), handle, userCredential, userId, progressCallback);
|
||||
|
||||
response = authResult.gkResponse;
|
||||
|
||||
// credential has matched
|
||||
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
|
||||
// perform verifyChallenge with synthetic password which generates the real GK auth
|
||||
@@ -2739,7 +2770,7 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
if (resetLockouts == null) {
|
||||
resetLockouts = new ArrayList<>();
|
||||
}
|
||||
resetLockouts.add(new PendingResetLockout(userId, response.getPayload()));
|
||||
resetLockouts.add(new PendingResetLockout(userId, response.getGatekeeperHAT()));
|
||||
}
|
||||
|
||||
onCredentialVerified(authResult.authToken, challengeType, challenge, resetLockouts,
|
||||
@@ -2750,7 +2781,12 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
if (response.isMatched() && returnGkPw) {
|
||||
return new VerifyCredentialResponse.Builder()
|
||||
.setGatekeeperPassword(authResult.authToken.deriveGkPassword()).build();
|
||||
} else {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
private void onCredentialVerified(AuthenticationToken authToken,
|
||||
@@ -3172,7 +3208,8 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
if (cred == null) {
|
||||
return false;
|
||||
}
|
||||
return doVerifyCredential(cred, CHALLENGE_NONE, 0, userId, null /* progressCallback */)
|
||||
return doVerifyCredential(cred, CHALLENGE_NONE, 0, userId,
|
||||
null /* progressCallback */, 0 /* flags */)
|
||||
.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,11 +482,12 @@ public class SyntheticPasswordManager {
|
||||
(int status, WeaverReadResponse readResponse) -> {
|
||||
switch (status) {
|
||||
case WeaverReadStatus.OK:
|
||||
response[0] = new VerifyCredentialResponse(
|
||||
fromByteArrayList(readResponse.value));
|
||||
response[0] = new VerifyCredentialResponse.Builder().setGatekeeperHAT(
|
||||
fromByteArrayList(readResponse.value)).build();
|
||||
break;
|
||||
case WeaverReadStatus.THROTTLE:
|
||||
response[0] = new VerifyCredentialResponse(readResponse.timeout);
|
||||
response[0] = VerifyCredentialResponse
|
||||
.fromTimeout(readResponse.timeout);
|
||||
Slog.e(TAG, "weaver read failed (THROTTLE), slot: " + slot);
|
||||
break;
|
||||
case WeaverReadStatus.INCORRECT_KEY:
|
||||
@@ -494,7 +495,8 @@ public class SyntheticPasswordManager {
|
||||
response[0] = VerifyCredentialResponse.ERROR;
|
||||
Slog.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot);
|
||||
} else {
|
||||
response[0] = new VerifyCredentialResponse(readResponse.timeout);
|
||||
response[0] = VerifyCredentialResponse
|
||||
.fromTimeout(readResponse.timeout);
|
||||
Slog.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: "
|
||||
+ slot);
|
||||
}
|
||||
@@ -1007,7 +1009,8 @@ public class SyntheticPasswordManager {
|
||||
return result;
|
||||
}
|
||||
sid = GateKeeper.INVALID_SECURE_USER_ID;
|
||||
applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload());
|
||||
applicationId = transformUnderWeaverSecret(pwdToken,
|
||||
result.gkResponse.getGatekeeperHAT());
|
||||
} else {
|
||||
byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
|
||||
GateKeeperResponse response;
|
||||
@@ -1045,7 +1048,7 @@ public class SyntheticPasswordManager {
|
||||
}
|
||||
}
|
||||
} else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
|
||||
result.gkResponse = new VerifyCredentialResponse(response.getTimeout());
|
||||
result.gkResponse = VerifyCredentialResponse.fromTimeout(response.getTimeout());
|
||||
return result;
|
||||
} else {
|
||||
result.gkResponse = VerifyCredentialResponse.ERROR;
|
||||
@@ -1096,12 +1099,12 @@ public class SyntheticPasswordManager {
|
||||
}
|
||||
VerifyCredentialResponse response = weaverVerify(slotId, null);
|
||||
if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK ||
|
||||
response.getPayload() == null) {
|
||||
response.getGatekeeperHAT() == null) {
|
||||
Slog.e(TAG, "Failed to retrieve weaver secret when unwrapping token");
|
||||
result.gkResponse = VerifyCredentialResponse.ERROR;
|
||||
return result;
|
||||
}
|
||||
secdiscardable = SyntheticPasswordCrypto.decrypt(response.getPayload(),
|
||||
secdiscardable = SyntheticPasswordCrypto.decrypt(response.getGatekeeperHAT(),
|
||||
PERSONALISATION_WEAVER_TOKEN, secdiscardable);
|
||||
}
|
||||
byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable);
|
||||
@@ -1174,6 +1177,12 @@ public class SyntheticPasswordManager {
|
||||
*/
|
||||
public @Nullable VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper,
|
||||
@NonNull AuthenticationToken auth, long challenge, int userId) {
|
||||
return verifyChallengeInternal(gatekeeper, auth.deriveGkPassword(), challenge, userId);
|
||||
}
|
||||
|
||||
protected @Nullable VerifyCredentialResponse verifyChallengeInternal(
|
||||
IGateKeeperService gatekeeper, @NonNull byte[] gatekeeperPassword, long challenge,
|
||||
int userId) {
|
||||
byte[] spHandle = loadSyntheticPasswordHandle(userId);
|
||||
if (spHandle == null) {
|
||||
// There is no password handle associated with the given user, i.e. the user is not
|
||||
@@ -1183,18 +1192,19 @@ public class SyntheticPasswordManager {
|
||||
GateKeeperResponse response;
|
||||
try {
|
||||
response = gatekeeper.verifyChallenge(userId, challenge,
|
||||
spHandle, auth.deriveGkPassword());
|
||||
spHandle, gatekeeperPassword);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Fail to verify with gatekeeper " + userId, e);
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
}
|
||||
int responseCode = response.getResponseCode();
|
||||
if (responseCode == GateKeeperResponse.RESPONSE_OK) {
|
||||
VerifyCredentialResponse result = new VerifyCredentialResponse(response.getPayload());
|
||||
VerifyCredentialResponse result = new VerifyCredentialResponse.Builder()
|
||||
.setGatekeeperHAT(response.getPayload()).build();
|
||||
if (response.getShouldReEnroll()) {
|
||||
try {
|
||||
response = gatekeeper.enroll(userId, spHandle, spHandle,
|
||||
auth.deriveGkPassword());
|
||||
gatekeeperPassword);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to invoke gatekeeper.enroll", e);
|
||||
response = GateKeeperResponse.ERROR;
|
||||
@@ -1203,7 +1213,8 @@ public class SyntheticPasswordManager {
|
||||
spHandle = response.getPayload();
|
||||
saveSyntheticPasswordHandle(spHandle, userId);
|
||||
// Call self again to re-verify with updated handle
|
||||
return verifyChallenge(gatekeeper, auth, challenge, userId);
|
||||
return verifyChallengeInternal(gatekeeper, gatekeeperPassword, challenge,
|
||||
userId);
|
||||
} else {
|
||||
// Fall through, return result from the previous verification attempt.
|
||||
Slog.w(TAG, "Fail to re-enroll SP handle for user " + userId);
|
||||
@@ -1211,7 +1222,7 @@ public class SyntheticPasswordManager {
|
||||
}
|
||||
return result;
|
||||
} else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
|
||||
return new VerifyCredentialResponse(response.getTimeout());
|
||||
return VerifyCredentialResponse.fromTimeout(response.getTimeout());
|
||||
} else {
|
||||
return VerifyCredentialResponse.ERROR;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
mGateKeeperService.clearAuthToken(TURNED_OFF_PROFILE_USER_ID);
|
||||
// verify credential
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
firstUnifiedPassword, 0, PRIMARY_USER_ID)
|
||||
firstUnifiedPassword, PRIMARY_USER_ID, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
|
||||
// Verify that we have a new auth token for the profile
|
||||
@@ -186,13 +186,13 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
mGateKeeperService.clearAuthToken(MANAGED_PROFILE_USER_ID);
|
||||
// verify primary credential
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
primaryPassword, 0, PRIMARY_USER_ID)
|
||||
primaryPassword, PRIMARY_USER_ID, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
assertNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
|
||||
|
||||
// verify profile credential
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
profilePassword, 0, MANAGED_PROFILE_USER_ID)
|
||||
profilePassword, MANAGED_PROFILE_USER_ID, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
assertNotNull(mGateKeeperService.getAuthToken(MANAGED_PROFILE_USER_ID));
|
||||
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
|
||||
@@ -203,7 +203,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
newPassword("pwd"), primaryPassword, PRIMARY_USER_ID));
|
||||
mStorageManager.setIgnoreBadUnlock(false);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
profilePassword, 0, MANAGED_PROFILE_USER_ID)
|
||||
profilePassword, MANAGED_PROFILE_USER_ID, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
|
||||
}
|
||||
@@ -389,7 +389,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
initializeStorageWithCredential(PRIMARY_USER_ID, password, 1234);
|
||||
reset(mRecoverableKeyStoreManager);
|
||||
|
||||
mService.verifyCredential(password, 1, PRIMARY_USER_ID);
|
||||
mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */);
|
||||
|
||||
verify(mRecoverableKeyStoreManager)
|
||||
.lockScreenSecretAvailable(
|
||||
@@ -406,7 +406,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
MANAGED_PROFILE_USER_ID));
|
||||
reset(mRecoverableKeyStoreManager);
|
||||
|
||||
mService.verifyCredential(pattern, 1, MANAGED_PROFILE_USER_ID);
|
||||
mService.verifyCredential(pattern, MANAGED_PROFILE_USER_ID, 0 /* flags */);
|
||||
|
||||
verify(mRecoverableKeyStoreManager)
|
||||
.lockScreenSecretAvailable(
|
||||
@@ -421,7 +421,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
|
||||
reset(mRecoverableKeyStoreManager);
|
||||
|
||||
mService.verifyCredential(pattern, 1, PRIMARY_USER_ID);
|
||||
mService.verifyCredential(pattern, PRIMARY_USER_ID, 0 /* flags */);
|
||||
|
||||
// Parent sends its credentials for both the parent and profile.
|
||||
verify(mRecoverableKeyStoreManager)
|
||||
@@ -484,9 +484,8 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
|
||||
private void assertVerifyCredentials(int userId, LockscreenCredential credential, long sid)
|
||||
throws RemoteException{
|
||||
final long challenge = 54321;
|
||||
VerifyCredentialResponse response = mService.verifyCredential(credential,
|
||||
challenge, userId);
|
||||
VerifyCredentialResponse response = mService.verifyCredential(credential, userId,
|
||||
0 /* flags */);
|
||||
|
||||
assertEquals(GateKeeperResponse.RESPONSE_OK, response.getResponseCode());
|
||||
if (sid != -1) assertEquals(sid, mGateKeeperService.getSecureUserId(userId));
|
||||
@@ -508,7 +507,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
|
||||
badCredential = LockscreenCredential.createPin("0");
|
||||
}
|
||||
assertEquals(GateKeeperResponse.RESPONSE_ERROR, mService.verifyCredential(
|
||||
badCredential, challenge, userId).getResponseCode());
|
||||
badCredential, userId, 0 /* flags */).getResponseCode());
|
||||
}
|
||||
|
||||
private void initializeStorageWithCredential(int userId, LockscreenCredential credential,
|
||||
|
||||
@@ -52,7 +52,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
|
||||
assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
|
||||
mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
|
||||
mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -61,7 +62,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
|
||||
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
|
||||
mService.verifyCredential(newPattern("4321"), 0, USER_FRP).getResponseCode());
|
||||
mService.verifyCredential(newPattern("4321"), USER_FRP, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -70,7 +72,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
|
||||
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
|
||||
mService.verifyCredential(newPassword("4321"), 0, USER_FRP).getResponseCode());
|
||||
mService.verifyCredential(newPassword("4321"), USER_FRP, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -80,7 +83,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
|
||||
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
|
||||
mService.verifyCredential(newPattern("5678"), 0, USER_FRP).getResponseCode());
|
||||
mService.verifyCredential(newPattern("5678"), USER_FRP, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,7 +102,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
|
||||
mSettings.setDeviceProvisioned(true);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
|
||||
mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
|
||||
mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -113,7 +118,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
|
||||
assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
|
||||
mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
|
||||
mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
|
||||
}
|
||||
|
||||
@@ -129,6 +135,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
|
||||
|
||||
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
|
||||
mService.verifyCredential(newPin("1234"), 0, USER_FRP).getResponseCode());
|
||||
mService.verifyCredential(newPin("1234"), USER_FRP, 0 /* flags */)
|
||||
.getResponseCode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,8 +119,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
|
||||
mService.setLockCredential(newPassword, password, PRIMARY_USER_ID);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
newPassword, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
newPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
|
||||
}
|
||||
|
||||
@@ -131,12 +130,10 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
|
||||
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
password, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
|
||||
badPassword, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -153,8 +150,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
// set a new password
|
||||
mService.setLockCredential(badPassword, nonePassword(), PRIMARY_USER_ID);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
badPassword, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
|
||||
}
|
||||
|
||||
@@ -166,8 +162,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
|
||||
mService.setLockCredential(badPassword, password, PRIMARY_USER_ID);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
badPassword, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
badPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
|
||||
// Check the same secret was passed each time
|
||||
ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
|
||||
@@ -183,8 +178,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
|
||||
reset(mAuthSecretService);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
password, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
|
||||
}
|
||||
|
||||
@@ -194,8 +188,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
|
||||
initializeCredentialUnderSP(password, SECONDARY_USER_ID);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
password, 0, SECONDARY_USER_ID)
|
||||
.getResponseCode());
|
||||
password, SECONDARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
|
||||
}
|
||||
|
||||
@@ -246,7 +239,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
assertTrue(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
|
||||
|
||||
mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
|
||||
mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
|
||||
.getResponseCode();
|
||||
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
assertFalse(mService.hasPendingEscrowToken(PRIMARY_USER_ID));
|
||||
|
||||
@@ -259,8 +253,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
verify(mDevicePolicyManager).reportPasswordChanged(PRIMARY_USER_ID);
|
||||
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
pattern, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
pattern, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
|
||||
}
|
||||
|
||||
@@ -275,7 +268,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
|
||||
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
|
||||
mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
|
||||
mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
|
||||
.getResponseCode();
|
||||
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
|
||||
mLocalService.setLockCredentialWithToken(nonePassword(), handle, token, PRIMARY_USER_ID);
|
||||
@@ -284,8 +278,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
PRIMARY_USER_ID);
|
||||
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
pattern, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
pattern, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
|
||||
}
|
||||
|
||||
@@ -301,7 +294,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
|
||||
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
|
||||
mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
|
||||
mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
|
||||
.getResponseCode();
|
||||
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
|
||||
mService.setLockCredential(pattern, password, PRIMARY_USER_ID);
|
||||
@@ -309,8 +303,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
mLocalService.setLockCredentialWithToken(newPassword, handle, token, PRIMARY_USER_ID);
|
||||
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
newPassword, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
newPassword, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
|
||||
}
|
||||
|
||||
@@ -357,8 +350,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
assertFalse(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
// Activate token (password gets migrated to SP at the same time)
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
password, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
// Verify token is activated
|
||||
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
}
|
||||
@@ -488,8 +480,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
|
||||
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
|
||||
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
|
||||
password, 0, PRIMARY_USER_ID)
|
||||
.getResponseCode());
|
||||
password, PRIMARY_USER_ID, 0 /* flags */).getResponseCode());
|
||||
verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
|
||||
}
|
||||
|
||||
@@ -503,7 +494,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
|
||||
reset(mDevicePolicyManager);
|
||||
|
||||
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
|
||||
mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
|
||||
mService.verifyCredential(password, PRIMARY_USER_ID, 0 /* flags */)
|
||||
.getResponseCode();
|
||||
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
|
||||
|
||||
mService.onCleanupUser(PRIMARY_USER_ID);
|
||||
|
||||
Reference in New Issue
Block a user