Rename pwdToken to stretchedLskf

stretchedLskf is a much more self-explanatory name for what this value
is: it's the result of passing the LSKF through a key stretching
function (scrypt).  The words "password" and "token" are already
overloaded in this code, so this should reduce confusion.  As usual I'll
be updating http://go/android-locksettings-design accordingly.

Test: atest com.android.server.locksettings
Change-Id: Id57de2d1f9246b3aed09554841ecfb54c947582f
This commit is contained in:
Eric Biggers
2022-08-03 01:49:56 +00:00
parent 4fdb5d00fa
commit 174d8dffa9

View File

@@ -144,7 +144,7 @@ public class SyntheticPasswordManager {
private static final int PASSWORD_SCRYPT_LOG_R = 3;
private static final int PASSWORD_SCRYPT_LOG_P = 1;
private static final int PASSWORD_SALT_LENGTH = 16;
private static final int PASSWORD_TOKEN_LENGTH = 32;
private static final int STRETCHED_LSKF_LENGTH = 32;
private static final String TAG = "SyntheticPasswordManager";
private static final byte[] PERSONALIZATION_SECDISCARDABLE = "secdiscardable-transform".getBytes();
@@ -772,7 +772,7 @@ public class SyntheticPasswordManager {
LockscreenCredential credential, SyntheticPassword sp, int userId) {
long protectorId = generateProtectorId();
PasswordData pwd = PasswordData.create(credential.getType());
byte[] pwdToken = computePasswordToken(credential, pwd);
byte[] stretchedLskf = stretchLskf(credential, pwd);
final long sid;
final byte[] protectorSecret;
@@ -780,7 +780,7 @@ public class SyntheticPasswordManager {
// Protector uses Weaver to verify the LSKF
int weaverSlot = getNextAvailableWeaverSlot();
Slog.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
byte[] weaverSecret = weaverEnroll(weaverSlot, passwordTokenToWeaverKey(pwdToken),
byte[] weaverSecret = weaverEnroll(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf),
null);
if (weaverSecret == null) {
throw new IllegalStateException(
@@ -793,7 +793,7 @@ public class SyntheticPasswordManager {
pwd.passwordHandle = null;
sid = GateKeeper.INVALID_SECURE_USER_ID;
protectorSecret = transformUnderWeaverSecret(pwdToken, weaverSecret);
protectorSecret = transformUnderWeaverSecret(stretchedLskf, weaverSecret);
} else {
// Protector uses Gatekeeper to verify the LSKF
@@ -807,7 +807,7 @@ public class SyntheticPasswordManager {
GateKeeperResponse response;
try {
response = gatekeeper.enroll(fakeUid(userId), null, null,
passwordTokenToGkInput(pwdToken));
stretchedLskfToGkPassword(stretchedLskf));
} catch (RemoteException e) {
throw new IllegalStateException("Failed to enroll LSKF for new SP protector for "
+ "user " + userId, e);
@@ -818,7 +818,7 @@ public class SyntheticPasswordManager {
}
pwd.passwordHandle = response.getPayload();
sid = sidFromPasswordHandle(pwd.passwordHandle);
protectorSecret = transformUnderSecdiscardable(pwdToken,
protectorSecret = transformUnderSecdiscardable(stretchedLskf,
createSecdiscardable(protectorId, userId));
// No need to pass in quality since the credential type already encodes sufficient info
synchronizeFrpPassword(pwd, 0, userId);
@@ -836,12 +836,13 @@ public class SyntheticPasswordManager {
PersistentData persistentData = mStorage.readPersistentDataBlock();
if (persistentData.type == PersistentData.TYPE_SP) {
PasswordData pwd = PasswordData.fromBytes(persistentData.payload);
byte[] pwdToken = computePasswordToken(userCredential, pwd);
byte[] stretchedLskf = stretchLskf(userCredential, pwd);
GateKeeperResponse response;
try {
response = gatekeeper.verifyChallenge(fakeUid(persistentData.userId),
0 /* challenge */, pwd.passwordHandle, passwordTokenToGkInput(pwdToken));
0 /* challenge */, pwd.passwordHandle,
stretchedLskfToGkPassword(stretchedLskf));
} catch (RemoteException e) {
Slog.e(TAG, "FRP verifyChallenge failed", e);
return VerifyCredentialResponse.ERROR;
@@ -853,10 +854,10 @@ public class SyntheticPasswordManager {
return VerifyCredentialResponse.ERROR;
}
PasswordData pwd = PasswordData.fromBytes(persistentData.payload);
byte[] pwdToken = computePasswordToken(userCredential, pwd);
byte[] stretchedLskf = stretchLskf(userCredential, pwd);
int weaverSlot = persistentData.userId;
return weaverVerify(weaverSlot, passwordTokenToWeaverKey(pwdToken)).stripPayload();
return weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf)).stripPayload();
} else {
Slog.e(TAG, "persistentData.type must be TYPE_SP or TYPE_SP_WEAVER, but is "
+ persistentData.type);
@@ -1034,7 +1035,7 @@ public class SyntheticPasswordManager {
return result;
}
byte[] pwdToken = computePasswordToken(credential, pwd);
byte[] stretchedLskf = stretchLskf(credential, pwd);
final byte[] protectorSecret;
final long sid;
@@ -1046,20 +1047,20 @@ public class SyntheticPasswordManager {
result.gkResponse = VerifyCredentialResponse.ERROR;
return result;
}
result.gkResponse = weaverVerify(weaverSlot, passwordTokenToWeaverKey(pwdToken));
result.gkResponse = weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf));
if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
return result;
}
sid = GateKeeper.INVALID_SECURE_USER_ID;
protectorSecret = transformUnderWeaverSecret(pwdToken,
protectorSecret = transformUnderWeaverSecret(stretchedLskf,
result.gkResponse.getGatekeeperHAT());
} else {
// Protector uses Gatekeeper to verify the LSKF
byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
byte[] gkPassword = stretchedLskfToGkPassword(stretchedLskf);
GateKeeperResponse response;
try {
response = gatekeeper.verifyChallenge(fakeUid(userId), 0L,
pwd.passwordHandle, gkPwdToken);
pwd.passwordHandle, gkPassword);
} catch (RemoteException e) {
Slog.e(TAG, "gatekeeper verify failed", e);
result.gkResponse = VerifyCredentialResponse.ERROR;
@@ -1072,7 +1073,7 @@ public class SyntheticPasswordManager {
GateKeeperResponse reenrollResponse;
try {
reenrollResponse = gatekeeper.enroll(fakeUid(userId),
pwd.passwordHandle, gkPwdToken, gkPwdToken);
pwd.passwordHandle, gkPassword, gkPassword);
} catch (RemoteException e) {
Slog.w(TAG, "Fail to invoke gatekeeper.enroll", e);
reenrollResponse = GateKeeperResponse.ERROR;
@@ -1098,7 +1099,7 @@ public class SyntheticPasswordManager {
return result;
}
sid = sidFromPasswordHandle(pwd.passwordHandle);
protectorSecret = transformUnderSecdiscardable(pwdToken,
protectorSecret = transformUnderSecdiscardable(stretchedLskf,
loadSecdiscardable(protectorId, userId));
}
// Supplied credential passes first stage weaver/gatekeeper check so it should be correct.
@@ -1468,18 +1469,20 @@ public class SyntheticPasswordManager {
return String.format("%s%x", PROTECTOR_KEY_ALIAS_PREFIX, protectorId);
}
private byte[] computePasswordToken(LockscreenCredential credential, PasswordData data) {
private byte[] stretchLskf(LockscreenCredential credential, PasswordData data) {
final byte[] password = credential.isNone() ? DEFAULT_PASSWORD : credential.getCredential();
return scrypt(password, data.salt, 1 << data.scryptLogN, 1 << data.scryptLogR,
1 << data.scryptLogP, PASSWORD_TOKEN_LENGTH);
1 << data.scryptLogP, STRETCHED_LSKF_LENGTH);
}
private byte[] passwordTokenToGkInput(byte[] token) {
return SyntheticPasswordCrypto.personalizedHash(PERSONALIZATION_USER_GK_AUTH, token);
private byte[] stretchedLskfToGkPassword(byte[] stretchedLskf) {
return SyntheticPasswordCrypto.personalizedHash(PERSONALIZATION_USER_GK_AUTH,
stretchedLskf);
}
private byte[] passwordTokenToWeaverKey(byte[] token) {
byte[] key = SyntheticPasswordCrypto.personalizedHash(PERSONALIZATION_WEAVER_KEY, token);
private byte[] stretchedLskfToWeaverKey(byte[] stretchedLskf) {
byte[] key = SyntheticPasswordCrypto.personalizedHash(PERSONALIZATION_WEAVER_KEY,
stretchedLskf);
if (key.length < mWeaverConfig.keySize) {
throw new IllegalArgumentException("weaver key length too small");
}