Loading services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +17 −4 Original line number Original line Diff line number Diff line Loading @@ -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); Loading @@ -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 Loading Loading @@ -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 Loading services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +21 −6 Original line number Original line Diff line number Diff line Loading @@ -101,7 +101,8 @@ public class SyntheticPasswordManager { private static final byte WEAVER_VERSION = 1; private static final byte WEAVER_VERSION = 1; private static final int INVALID_WEAVER_SLOT = -1; private static final int INVALID_WEAVER_SLOT = -1; 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; Loading Loading @@ -792,6 +793,7 @@ public class SyntheticPasswordManager { byte[] pwdToken = computePasswordToken(credential, pwd); byte[] pwdToken = computePasswordToken(credential, pwd); final byte[] applicationId; final byte[] applicationId; final long sid; int weaverSlot = loadWeaverSlot(handle, userId); int weaverSlot = loadWeaverSlot(handle, userId); if (weaverSlot != INVALID_WEAVER_SLOT) { if (weaverSlot != INVALID_WEAVER_SLOT) { // Weaver based user password // Weaver based user password Loading @@ -804,6 +806,7 @@ public class SyntheticPasswordManager { if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { return result; return result; } } sid = GateKeeper.INVALID_SECURE_USER_ID; applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload()); applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload()); } else { } else { byte[] gkPwdToken = passwordTokenToGkInput(pwdToken); byte[] gkPwdToken = passwordTokenToGkInput(pwdToken); Loading Loading @@ -836,12 +839,13 @@ public class SyntheticPasswordManager { result.gkResponse = VerifyCredentialResponse.ERROR; result.gkResponse = VerifyCredentialResponse.ERROR; return result; return result; } } sid = sidFromPasswordHandle(pwd.passwordHandle); applicationId = transformUnderSecdiscardable(pwdToken, 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); Loading Loading @@ -877,7 +881,7 @@ public class SyntheticPasswordManager { } } byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable); byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable); 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) { Loading @@ -892,19 +896,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; Loading @@ -919,6 +930,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; } } Loading Loading
services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java +17 −4 Original line number Original line Diff line number Diff line Loading @@ -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); Loading @@ -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 Loading Loading @@ -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 Loading
services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +21 −6 Original line number Original line Diff line number Diff line Loading @@ -101,7 +101,8 @@ public class SyntheticPasswordManager { private static final byte WEAVER_VERSION = 1; private static final byte WEAVER_VERSION = 1; private static final int INVALID_WEAVER_SLOT = -1; private static final int INVALID_WEAVER_SLOT = -1; 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; Loading Loading @@ -792,6 +793,7 @@ public class SyntheticPasswordManager { byte[] pwdToken = computePasswordToken(credential, pwd); byte[] pwdToken = computePasswordToken(credential, pwd); final byte[] applicationId; final byte[] applicationId; final long sid; int weaverSlot = loadWeaverSlot(handle, userId); int weaverSlot = loadWeaverSlot(handle, userId); if (weaverSlot != INVALID_WEAVER_SLOT) { if (weaverSlot != INVALID_WEAVER_SLOT) { // Weaver based user password // Weaver based user password Loading @@ -804,6 +806,7 @@ public class SyntheticPasswordManager { if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { return result; return result; } } sid = GateKeeper.INVALID_SECURE_USER_ID; applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload()); applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload()); } else { } else { byte[] gkPwdToken = passwordTokenToGkInput(pwdToken); byte[] gkPwdToken = passwordTokenToGkInput(pwdToken); Loading Loading @@ -836,12 +839,13 @@ public class SyntheticPasswordManager { result.gkResponse = VerifyCredentialResponse.ERROR; result.gkResponse = VerifyCredentialResponse.ERROR; return result; return result; } } sid = sidFromPasswordHandle(pwd.passwordHandle); applicationId = transformUnderSecdiscardable(pwdToken, 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); Loading Loading @@ -877,7 +881,7 @@ public class SyntheticPasswordManager { } } byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable); byte[] applicationId = transformUnderSecdiscardable(token, secdiscardable); 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) { Loading @@ -892,19 +896,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; Loading @@ -919,6 +930,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; } } Loading