Merge "Swap the order of synthetic password wrapping" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2ff6320d77
@@ -112,7 +112,7 @@ public class SyntheticPasswordCrypto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) {
|
public static byte[] decryptBlobV1(String keyAlias, byte[] blob, byte[] applicationId) {
|
||||||
try {
|
try {
|
||||||
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||||
keyStore.load(null);
|
keyStore.load(null);
|
||||||
@@ -120,6 +120,20 @@ public class SyntheticPasswordCrypto {
|
|||||||
SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
|
SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
|
||||||
byte[] intermediate = decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, blob);
|
byte[] intermediate = decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, blob);
|
||||||
return decrypt(decryptionKey, intermediate);
|
return decrypt(decryptionKey, intermediate);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException("Failed to decrypt blob", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] decryptBlob(String keyAlias, byte[] blob, byte[] applicationId) {
|
||||||
|
try {
|
||||||
|
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||||
|
keyStore.load(null);
|
||||||
|
|
||||||
|
SecretKey decryptionKey = (SecretKey) keyStore.getKey(keyAlias, null);
|
||||||
|
byte[] intermediate = decrypt(decryptionKey, blob);
|
||||||
|
return decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, intermediate);
|
||||||
} catch (CertificateException | IOException | BadPaddingException
|
} catch (CertificateException | IOException | BadPaddingException
|
||||||
| IllegalBlockSizeException
|
| IllegalBlockSizeException
|
||||||
| KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
|
| KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
|
||||||
@@ -150,9 +164,8 @@ public class SyntheticPasswordCrypto {
|
|||||||
keyStore.setEntry(keyAlias,
|
keyStore.setEntry(keyAlias,
|
||||||
new KeyStore.SecretKeyEntry(secretKey),
|
new KeyStore.SecretKeyEntry(secretKey),
|
||||||
builder.build());
|
builder.build());
|
||||||
byte[] intermediate = encrypt(secretKey, data);
|
byte[] intermediate = encrypt(applicationId, APPLICATION_ID_PERSONALIZATION, data);
|
||||||
return encrypt(applicationId, APPLICATION_ID_PERSONALIZATION, intermediate);
|
return encrypt(secretKey, intermediate);
|
||||||
|
|
||||||
} catch (CertificateException | IOException | BadPaddingException
|
} catch (CertificateException | IOException | BadPaddingException
|
||||||
| IllegalBlockSizeException
|
| IllegalBlockSizeException
|
||||||
| KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
|
| KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ public class SyntheticPasswordManager {
|
|||||||
public static final long DEFAULT_HANDLE = 0;
|
public static final long DEFAULT_HANDLE = 0;
|
||||||
private static final String DEFAULT_PASSWORD = "default-password";
|
private static final String DEFAULT_PASSWORD = "default-password";
|
||||||
|
|
||||||
private static final byte SYNTHETIC_PASSWORD_VERSION = 1;
|
private static final byte SYNTHETIC_PASSWORD_VERSION_V1 = 1;
|
||||||
|
private static final byte SYNTHETIC_PASSWORD_VERSION = 2;
|
||||||
private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0;
|
private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0;
|
||||||
private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1;
|
private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1;
|
||||||
|
|
||||||
@@ -468,10 +469,11 @@ public class SyntheticPasswordManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final long sid = sidFromPasswordHandle(pwd.passwordHandle);
|
||||||
byte[] applicationId = transformUnderSecdiscardable(pwdToken,
|
byte[] applicationId = transformUnderSecdiscardable(pwdToken,
|
||||||
loadSecdiscardable(handle, userId));
|
loadSecdiscardable(handle, userId));
|
||||||
result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED,
|
result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED,
|
||||||
applicationId, userId);
|
applicationId, sid, userId);
|
||||||
|
|
||||||
// Perform verifyChallenge to refresh auth tokens for GK if user password exists.
|
// Perform verifyChallenge to refresh auth tokens for GK if user password exists.
|
||||||
result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
|
result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
|
||||||
@@ -490,7 +492,7 @@ public class SyntheticPasswordManager {
|
|||||||
byte[] applicationId = transformUnderSecdiscardable(token,
|
byte[] applicationId = transformUnderSecdiscardable(token,
|
||||||
loadSecdiscardable(handle, userId));
|
loadSecdiscardable(handle, userId));
|
||||||
result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED,
|
result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_TOKEN_BASED,
|
||||||
applicationId, userId);
|
applicationId, 0L, userId);
|
||||||
if (result.authToken != null) {
|
if (result.authToken != null) {
|
||||||
result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
|
result.gkResponse = verifyChallenge(gatekeeper, result.authToken, 0L, userId);
|
||||||
if (result.gkResponse == null) {
|
if (result.gkResponse == null) {
|
||||||
@@ -505,19 +507,26 @@ public class SyntheticPasswordManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type,
|
private AuthenticationToken unwrapSyntheticPasswordBlob(long handle, byte type,
|
||||||
byte[] applicationId, int userId) {
|
byte[] applicationId, long sid, int userId) {
|
||||||
byte[] blob = loadState(SP_BLOB_NAME, handle, userId);
|
byte[] blob = loadState(SP_BLOB_NAME, handle, userId);
|
||||||
if (blob == null) {
|
if (blob == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (blob[0] != SYNTHETIC_PASSWORD_VERSION) {
|
final byte version = blob[0];
|
||||||
|
if (version != SYNTHETIC_PASSWORD_VERSION && version != SYNTHETIC_PASSWORD_VERSION_V1) {
|
||||||
throw new RuntimeException("Unknown blob version");
|
throw new RuntimeException("Unknown blob version");
|
||||||
}
|
}
|
||||||
if (blob[1] != type) {
|
if (blob[1] != type) {
|
||||||
throw new RuntimeException("Invalid blob type");
|
throw new RuntimeException("Invalid blob type");
|
||||||
}
|
}
|
||||||
byte[] secret = decryptSPBlob(getHandleName(handle),
|
final byte[] secret;
|
||||||
|
if (version == SYNTHETIC_PASSWORD_VERSION_V1) {
|
||||||
|
secret = SyntheticPasswordCrypto.decryptBlobV1(getHandleName(handle),
|
||||||
|
Arrays.copyOfRange(blob, 2, blob.length), applicationId);
|
||||||
|
} else {
|
||||||
|
secret = decryptSPBlob(getHandleName(handle),
|
||||||
Arrays.copyOfRange(blob, 2, blob.length), applicationId);
|
Arrays.copyOfRange(blob, 2, blob.length), applicationId);
|
||||||
|
}
|
||||||
if (secret == null) {
|
if (secret == null) {
|
||||||
Log.e(TAG, "Fail to decrypt SP for user " + userId);
|
Log.e(TAG, "Fail to decrypt SP for user " + userId);
|
||||||
return null;
|
return null;
|
||||||
@@ -532,6 +541,10 @@ public class SyntheticPasswordManager {
|
|||||||
} else {
|
} else {
|
||||||
result.syntheticPassword = new String(secret);
|
result.syntheticPassword = new String(secret);
|
||||||
}
|
}
|
||||||
|
if (version == SYNTHETIC_PASSWORD_VERSION_V1) {
|
||||||
|
Log.i(TAG, "Upgrade v1 SP blob for user " + userId + ", type = " + type);
|
||||||
|
createSyntheticPasswordBlob(handle, type, result, applicationId, sid, userId);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user