Merge "Add a method which allows storing PIN length on disk from cache" into udc-dev

This commit is contained in:
Treehugger Robot
2023-04-14 20:46:49 +00:00
committed by Android (Google) Code Review
9 changed files with 114 additions and 24 deletions

View File

@@ -57,6 +57,7 @@ interface ILockSettings {
void removeGatekeeperPasswordHandle(long gatekeeperPasswordHandle);
int getCredentialType(int userId);
int getPinLength(int userId);
boolean refreshStoredPinLength(int userId);
byte[] getHashFactor(in LockscreenCredential currentCredential, int userId);
void setSeparateProfileChallengeEnabled(int userId, boolean enabled, in LockscreenCredential managedUserPassword);
boolean getSeparateProfileChallengeEnabled(int userId);

View File

@@ -622,6 +622,24 @@ public class LockPatternUtils {
return PIN_LENGTH_UNAVAILABLE;
}
}
/**
* This method saves the pin length value to disk based on the user's auto pin
* confirmation flag setting. If the auto pin confirmation flag is disabled, or if the
* user does not have a PIN setup, or if length of PIN is less than minimum storable PIN length
* value, the pin length value is set to PIN_LENGTH_UNAVAILABLE. Otherwise, if the
* flag is enabled, the pin length value is set to the actual length of the user's PIN.
* @param userId user id of the user whose pin length we want to save
* @return true/false depending on whether PIN length has been saved or not
*/
public boolean refreshStoredPinLength(int userId) {
try {
return getLockSettings().refreshStoredPinLength(userId);
} catch (RemoteException e) {
Log.e(TAG, "Could not store PIN length on disk " + e);
return false;
}
}
/**
* Records that the user has chosen a pattern at some time, even if the pattern is
* currently cleared.

View File

@@ -116,6 +116,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -1228,6 +1229,26 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
/**
* {@link LockPatternUtils#refreshStoredPinLength(int)}
* @param userId user id of the user whose pin length we want to save
* @return true/false depending on whether PIN length has been saved or not
*/
@Override
public boolean refreshStoredPinLength(int userId) {
checkPasswordHavePermission();
synchronized (mSpManager) {
PasswordMetrics passwordMetrics = getUserPasswordMetrics(userId);
if (passwordMetrics != null) {
final long protectorId = getCurrentLskfBasedProtectorId(userId);
return mSpManager.refreshPinLengthOnDisk(passwordMetrics, protectorId, userId);
} else {
Log.w(TAG, "PasswordMetrics is not available");
return false;
}
}
}
/**
* This API is cached; whenever the result would change,
* {@link com.android.internal.widget.LockPatternUtils#invalidateCredentialTypeCache}

View File

@@ -120,6 +120,11 @@ class LockSettingsStorage {
writeKeyValue(mOpenHelper.getWritableDatabase(), key, value, userId);
}
@VisibleForTesting
public boolean isAutoPinConfirmSettingEnabled(int userId) {
return getBoolean(LockPatternUtils.AUTO_PIN_CONFIRM, false, userId);
}
@VisibleForTesting
public void writeKeyValue(SQLiteDatabase db, String key, String value, int userId) {
ContentValues cv = new ContentValues();

View File

@@ -16,6 +16,7 @@
package com.android.server.locksettings;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PIN;
import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
import static com.android.internal.widget.LockPatternUtils.PIN_LENGTH_UNAVAILABLE;
@@ -545,6 +546,11 @@ class SyntheticPasswordManager {
return null;
}
@VisibleForTesting
public boolean isAutoPinConfirmationFeatureAvailable() {
return LockPatternUtils.isAutoPinConfirmFeatureAvailable();
}
private synchronized boolean isWeaverAvailable() {
if (mWeaver != null) {
return true;
@@ -901,8 +907,8 @@ class SyntheticPasswordManager {
LockscreenCredential credential, SyntheticPassword sp, int userId) {
long protectorId = generateProtectorId();
int pinLength = PIN_LENGTH_UNAVAILABLE;
if (LockPatternUtils.isAutoPinConfirmFeatureAvailable()) {
pinLength = derivePinLength(credential, userId);
if (isAutoPinConfirmationFeatureAvailable()) {
pinLength = derivePinLength(credential.size(), credential.isPin(), userId);
}
// There's no need to store password data about an empty LSKF.
PasswordData pwd = credential.isNone() ? null :
@@ -978,13 +984,13 @@ class SyntheticPasswordManager {
return protectorId;
}
private int derivePinLength(LockscreenCredential credential, int userId) {
if (!credential.isPin()
|| !mStorage.getBoolean(LockPatternUtils.AUTO_PIN_CONFIRM, false, userId)
|| credential.size() < LockPatternUtils.MIN_AUTO_PIN_REQUIREMENT_LENGTH) {
private int derivePinLength(int sizeOfCredential, boolean isPinCredential, int userId) {
if (!isPinCredential
|| !mStorage.isAutoPinConfirmSettingEnabled(userId)
|| sizeOfCredential < LockPatternUtils.MIN_AUTO_PIN_REQUIREMENT_LENGTH) {
return PIN_LENGTH_UNAVAILABLE;
}
return credential.size();
return sizeOfCredential;
}
public VerifyCredentialResponse verifyFrpCredential(IGateKeeperService gatekeeper,
@@ -1347,18 +1353,38 @@ class SyntheticPasswordManager {
savePasswordMetrics(credential, result.syntheticPassword, protectorId, userId);
syncState(userId); // Not strictly needed as the upgrade can be re-done, but be safe.
}
if (LockPatternUtils.isAutoPinConfirmFeatureAvailable()
&& result.syntheticPassword != null && pwd != null) {
int expectedPinLength = derivePinLength(credential, userId);
if (pwd.pinLength != expectedPinLength) {
pwd.pinLength = expectedPinLength;
saveState(PASSWORD_DATA_NAME, pwd.toBytes(), protectorId, userId);
syncState(userId);
}
}
return result;
}
/**
* {@link LockPatternUtils#refreshStoredPinLength(int)}
* @param passwordMetrics passwordMetrics object containing the cached pin length
* @param userId userId of the user whose pin length we want to store on disk
* @param protectorId current LSKF based protectorId
* @return true/false depending on whether PIN length has been saved on disk
*/
public boolean refreshPinLengthOnDisk(PasswordMetrics passwordMetrics,
long protectorId, int userId) {
if (!isAutoPinConfirmationFeatureAvailable()) {
return false;
}
byte[] pwdDataBytes = loadState(PASSWORD_DATA_NAME, protectorId, userId);
if (pwdDataBytes == null) {
return false;
}
PasswordData pwd = PasswordData.fromBytes(pwdDataBytes);
int pinLength = derivePinLength(passwordMetrics.length,
passwordMetrics.credType == CREDENTIAL_TYPE_PIN, userId);
if (pwd.pinLength != pinLength) {
pwd.pinLength = pinLength;
saveState(PASSWORD_DATA_NAME, pwd.toBytes(), protectorId, userId);
syncState(userId);
}
return true;
}
/**
* Tries to unlock a token-based SP protector (weak or strong), given its ID and the claimed
* token. On success, returns the user's synthetic password, and also does a Gatekeeper

View File

@@ -16,9 +16,6 @@
package com.android.server.locksettings;
import static android.app.admin.DevicePolicyManager.DEPRECATE_USERMANAGERINTERNAL_DEVICEPOLICY_FLAG;
import static android.provider.DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -50,7 +47,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.security.KeyStore;
@@ -235,9 +231,6 @@ public abstract class BaseLockSettingsServiceTests {
// Adding a fake Device Owner app which will enable escrow token support in LSS.
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(
new ComponentName("com.dummy.package", ".FakeDeviceOwner"));
// TODO(b/258213147): Remove
DeviceConfig.setProperty(NAMESPACE_DEVICE_POLICY_MANAGER,
DEPRECATE_USERMANAGERINTERNAL_DEVICEPOLICY_FLAG, "true", /* makeDefault= */ false);
when(mUserManagerInternal.isDeviceManaged()).thenReturn(true);
when(mDeviceStateCache.isUserOrganizationManaged(anyInt())).thenReturn(true);
when(mDeviceStateCache.isDeviceProvisioned()).thenReturn(true);

View File

@@ -87,7 +87,10 @@ public class LockSettingsStorageTestable extends LockSettingsStorage {
PersistentDataBlockManagerInternal getPersistentDataBlockManager() {
return mPersistentDataBlockManager;
}
@Override
public boolean isAutoPinConfirmSettingEnabled(int userId) {
return true;
}
private File remapToStorageDir(File origPath) {
File mappedPath = new File(mStorageDir, origPath.toString());
mappedPath.getParentFile().mkdirs();

View File

@@ -112,6 +112,11 @@ public class MockSyntheticPasswordManager extends SyntheticPasswordManager {
}
}
@Override
public boolean isAutoPinConfirmationFeatureAvailable() {
return true;
}
@Override
protected IWeaver getWeaverHidlService() throws RemoteException {
return mWeaverService;

View File

@@ -606,6 +606,24 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
assertArrayEquals(PAYLOAD2, deserialized.passwordHandle);
}
@Test
public void testStorePinLengthOnDisk() {
int userId = 1;
LockscreenCredential lockscreenCredentialPin = LockscreenCredential.createPin("123456");
MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage,
mGateKeeperService, mUserManager, mPasswordSlotManager);
SyntheticPassword sp = manager.newSyntheticPassword(userId);
long protectorId = manager.createLskfBasedProtector(mGateKeeperService,
lockscreenCredentialPin, sp,
userId);
PasswordMetrics passwordMetrics =
PasswordMetrics.computeForCredential(lockscreenCredentialPin);
boolean result = manager.refreshPinLengthOnDisk(passwordMetrics, protectorId, userId);
assertEquals(manager.getPinLength(protectorId, userId), lockscreenCredentialPin.size());
assertTrue(result);
}
@Test
public void testPasswordDataV2VersionCredentialTypePin_deserialize() {
// Test that we can deserialize existing PasswordData and don't inadvertently change the