Loading services/core/java/com/android/server/locksettings/LockSettingsService.java +3 −2 Original line number Diff line number Diff line Loading @@ -1348,11 +1348,11 @@ public class LockSettingsService extends ILockSettings.Stub { .verifyChallenge(userId, 0, willStore.hash, credential.getBytes()); setUserKeyProtection(userId, credential, convertResponse(gkResponse)); fixateNewestUserKeyAuth(userId); mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); // Refresh the auth token doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */); synchronizeUnifiedWorkChallengeForProfiles(userId, null); mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); } else { throw new RemoteException("Failed to enroll " + (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password" Loading Loading @@ -2494,6 +2494,7 @@ public class LockSettingsService extends ILockSettings.Stub { (response != null ? "rate limit exceeded" : "failed")); return; } mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); } @Override Loading services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +8 −9 Original line number Diff line number Diff line Loading @@ -72,7 +72,7 @@ public class KeySyncTask implements Runnable { private final int mCredentialType; private final String mCredential; private final boolean mCredentialUpdated; private final PlatformKeyManager.Factory mPlatformKeyManagerFactory; private final PlatformKeyManager mPlatformKeyManager; private final RecoverySnapshotStorage mRecoverySnapshotStorage; private final RecoverySnapshotListenersStorage mSnapshotListenersStorage; Loading @@ -94,7 +94,7 @@ public class KeySyncTask implements Runnable { credentialType, credential, credentialUpdated, () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb)); PlatformKeyManager.getInstance(context, recoverableKeyStoreDb)); } /** Loading @@ -105,9 +105,7 @@ public class KeySyncTask implements Runnable { * @param credentialType The type of credential as defined in {@code LockPatternUtils} * @param credential The credential, encoded as a {@link String}. * @param credentialUpdated signals weather credentials were updated. * @param platformKeyManagerFactory Instantiates a {@link PlatformKeyManager} for the user. * This is a factory to enable unit testing, as otherwise it would be impossible to test * without a screen unlock occurring! * @param platformKeyManager platform key manager */ @VisibleForTesting KeySyncTask( Loading @@ -118,14 +116,14 @@ public class KeySyncTask implements Runnable { int credentialType, String credential, boolean credentialUpdated, PlatformKeyManager.Factory platformKeyManagerFactory) { PlatformKeyManager platformKeyManager) { mSnapshotListenersStorage = recoverySnapshotListenersStorage; mRecoverableKeyStoreDb = recoverableKeyStoreDb; mUserId = userId; mCredentialType = credentialType; mCredential = credential; mCredentialUpdated = credentialUpdated; mPlatformKeyManagerFactory = platformKeyManagerFactory; mPlatformKeyManager = platformKeyManager; mRecoverySnapshotStorage = snapshotStorage; } Loading @@ -145,6 +143,8 @@ public class KeySyncTask implements Runnable { if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { // Application keys for the user will not be available for sync. Log.w(TAG, "Credentials are not set for user " + mUserId); int generation = mPlatformKeyManager.getGenerationId(mUserId); mPlatformKeyManager.invalidatePlatformKey(mUserId, generation); return; } Loading Loading @@ -304,8 +304,7 @@ public class KeySyncTask implements Runnable { throws InsecureUserException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException, InvalidKeyException, InvalidAlgorithmParameterException { PlatformKeyManager platformKeyManager = mPlatformKeyManagerFactory.newInstance(); PlatformDecryptionKey decryptKey = platformKeyManager.getDecryptKey(mUserId);; PlatformDecryptionKey decryptKey = mPlatformKeyManager.getDecryptKey(mUserId);; Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys( mUserId, recoveryAgentUid, decryptKey.getGenerationId()); return WrappedKey.unwrapKeys(decryptKey, wrappedKeys); Loading services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java +31 −14 Original line number Diff line number Diff line Loading @@ -128,6 +128,26 @@ public class PlatformKeyManager { return mContext.getSystemService(KeyguardManager.class).isDeviceSecure(userId); } /** * Removes the platform key from Android KeyStore. * It is triggered when user disables lock screen. * * @param userId The ID of the user to whose lock screen the platform key must be bound. * @param generationId Generation id. * * @hide */ public void invalidatePlatformKey(int userId, int generationId) { if (generationId != -1) { try { mKeyStore.deleteEntry(getEncryptAlias(userId, generationId)); mKeyStore.deleteEntry(getDecryptAlias(userId, generationId)); } catch (KeyStoreException e) { // Ignore failed attempt to delete key. } } } /** * Generates a new key and increments the generation ID. Should be invoked if the platform key * is corrupted and needs to be rotated. Loading @@ -152,6 +172,7 @@ public class PlatformKeyManager { if (generationId == -1) { nextId = 1; } else { invalidatePlatformKey(userId, generationId); nextId = generationId + 1; } generateAndLoadKey(userId, nextId); Loading Loading @@ -197,8 +218,12 @@ public class PlatformKeyManager { private PlatformEncryptionKey getEncryptKeyInternal(int userId) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException { int generationId = getGenerationId(userId); String alias = getEncryptAlias(userId, generationId); if (!mKeyStore.containsAlias(alias)) { throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias); } AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey( getEncryptAlias(userId, generationId), /*password=*/ null); alias, /*password=*/ null); return new PlatformEncryptionKey(generationId, key); } Loading Loading @@ -242,8 +267,12 @@ public class PlatformKeyManager { private PlatformDecryptionKey getDecryptKeyInternal(int userId) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException { int generationId = getGenerationId(userId); String alias = getDecryptAlias(userId, generationId); if (!mKeyStore.containsAlias(alias)) { throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias); } AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey( getDecryptAlias(userId, generationId), /*password=*/ null); alias, /*password=*/ null); return new PlatformDecryptionKey(generationId, key); } Loading Loading @@ -405,16 +434,4 @@ public class PlatformKeyManager { return keyStore; } /** * @hide */ public interface Factory { /** * New PlatformKeyManager instance. * * @hide */ PlatformKeyManager newInstance() throws NoSuchAlgorithmException, InsecureUserException, KeyStoreException; } } services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -579,6 +579,7 @@ public class RecoverableKeyStoreManager { /** * This function can only be used inside LockSettingsService. * * @param storedHashType from {@code CredentialHash} * @param credential - unencrypted String * @param userId for the user whose lock screen credentials were changed. Loading @@ -604,7 +605,7 @@ public class RecoverableKeyStoreManager { } catch (KeyStoreException e) { Log.e(TAG, "Key store error encountered during recoverable key sync", e); } catch (InsecureUserException e) { Log.wtf(TAG, "Impossible - insecure user, but user just entered lock screen", e); Log.e(TAG, "InsecureUserException during lock screen secret update", e); } } Loading services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ public class KeySyncTaskTest { TEST_CREDENTIAL_TYPE, TEST_CREDENTIAL, /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mWrappingKey = generateAndroidKeyStoreKey(); mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey); Loading Loading @@ -352,7 +352,7 @@ public class KeySyncTaskTest { CREDENTIAL_TYPE_PASSWORD, "password", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading @@ -378,7 +378,7 @@ public class KeySyncTaskTest { CREDENTIAL_TYPE_PASSWORD, /*credential=*/ "1234", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading @@ -405,7 +405,7 @@ public class KeySyncTaskTest { CREDENTIAL_TYPE_PATTERN, "12345", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading Loading
services/core/java/com/android/server/locksettings/LockSettingsService.java +3 −2 Original line number Diff line number Diff line Loading @@ -1348,11 +1348,11 @@ public class LockSettingsService extends ILockSettings.Stub { .verifyChallenge(userId, 0, willStore.hash, credential.getBytes()); setUserKeyProtection(userId, credential, convertResponse(gkResponse)); fixateNewestUserKeyAuth(userId); mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); // Refresh the auth token doVerifyCredential(credential, credentialType, true, 0, userId, null /* progressCallback */); synchronizeUnifiedWorkChallengeForProfiles(userId, null); mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); } else { throw new RemoteException("Failed to enroll " + (credentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD ? "password" Loading Loading @@ -2494,6 +2494,7 @@ public class LockSettingsService extends ILockSettings.Stub { (response != null ? "rate limit exceeded" : "failed")); return; } mRecoverableKeyStoreManager.lockScreenSecretChanged(credentialType, credential, userId); } @Override Loading
services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +8 −9 Original line number Diff line number Diff line Loading @@ -72,7 +72,7 @@ public class KeySyncTask implements Runnable { private final int mCredentialType; private final String mCredential; private final boolean mCredentialUpdated; private final PlatformKeyManager.Factory mPlatformKeyManagerFactory; private final PlatformKeyManager mPlatformKeyManager; private final RecoverySnapshotStorage mRecoverySnapshotStorage; private final RecoverySnapshotListenersStorage mSnapshotListenersStorage; Loading @@ -94,7 +94,7 @@ public class KeySyncTask implements Runnable { credentialType, credential, credentialUpdated, () -> PlatformKeyManager.getInstance(context, recoverableKeyStoreDb)); PlatformKeyManager.getInstance(context, recoverableKeyStoreDb)); } /** Loading @@ -105,9 +105,7 @@ public class KeySyncTask implements Runnable { * @param credentialType The type of credential as defined in {@code LockPatternUtils} * @param credential The credential, encoded as a {@link String}. * @param credentialUpdated signals weather credentials were updated. * @param platformKeyManagerFactory Instantiates a {@link PlatformKeyManager} for the user. * This is a factory to enable unit testing, as otherwise it would be impossible to test * without a screen unlock occurring! * @param platformKeyManager platform key manager */ @VisibleForTesting KeySyncTask( Loading @@ -118,14 +116,14 @@ public class KeySyncTask implements Runnable { int credentialType, String credential, boolean credentialUpdated, PlatformKeyManager.Factory platformKeyManagerFactory) { PlatformKeyManager platformKeyManager) { mSnapshotListenersStorage = recoverySnapshotListenersStorage; mRecoverableKeyStoreDb = recoverableKeyStoreDb; mUserId = userId; mCredentialType = credentialType; mCredential = credential; mCredentialUpdated = credentialUpdated; mPlatformKeyManagerFactory = platformKeyManagerFactory; mPlatformKeyManager = platformKeyManager; mRecoverySnapshotStorage = snapshotStorage; } Loading @@ -145,6 +143,8 @@ public class KeySyncTask implements Runnable { if (mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) { // Application keys for the user will not be available for sync. Log.w(TAG, "Credentials are not set for user " + mUserId); int generation = mPlatformKeyManager.getGenerationId(mUserId); mPlatformKeyManager.invalidatePlatformKey(mUserId, generation); return; } Loading Loading @@ -304,8 +304,7 @@ public class KeySyncTask implements Runnable { throws InsecureUserException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException, InvalidKeyException, InvalidAlgorithmParameterException { PlatformKeyManager platformKeyManager = mPlatformKeyManagerFactory.newInstance(); PlatformDecryptionKey decryptKey = platformKeyManager.getDecryptKey(mUserId);; PlatformDecryptionKey decryptKey = mPlatformKeyManager.getDecryptKey(mUserId);; Map<String, WrappedKey> wrappedKeys = mRecoverableKeyStoreDb.getAllKeys( mUserId, recoveryAgentUid, decryptKey.getGenerationId()); return WrappedKey.unwrapKeys(decryptKey, wrappedKeys); Loading
services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java +31 −14 Original line number Diff line number Diff line Loading @@ -128,6 +128,26 @@ public class PlatformKeyManager { return mContext.getSystemService(KeyguardManager.class).isDeviceSecure(userId); } /** * Removes the platform key from Android KeyStore. * It is triggered when user disables lock screen. * * @param userId The ID of the user to whose lock screen the platform key must be bound. * @param generationId Generation id. * * @hide */ public void invalidatePlatformKey(int userId, int generationId) { if (generationId != -1) { try { mKeyStore.deleteEntry(getEncryptAlias(userId, generationId)); mKeyStore.deleteEntry(getDecryptAlias(userId, generationId)); } catch (KeyStoreException e) { // Ignore failed attempt to delete key. } } } /** * Generates a new key and increments the generation ID. Should be invoked if the platform key * is corrupted and needs to be rotated. Loading @@ -152,6 +172,7 @@ public class PlatformKeyManager { if (generationId == -1) { nextId = 1; } else { invalidatePlatformKey(userId, generationId); nextId = generationId + 1; } generateAndLoadKey(userId, nextId); Loading Loading @@ -197,8 +218,12 @@ public class PlatformKeyManager { private PlatformEncryptionKey getEncryptKeyInternal(int userId) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException { int generationId = getGenerationId(userId); String alias = getEncryptAlias(userId, generationId); if (!mKeyStore.containsAlias(alias)) { throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias); } AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey( getEncryptAlias(userId, generationId), /*password=*/ null); alias, /*password=*/ null); return new PlatformEncryptionKey(generationId, key); } Loading Loading @@ -242,8 +267,12 @@ public class PlatformKeyManager { private PlatformDecryptionKey getDecryptKeyInternal(int userId) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException { int generationId = getGenerationId(userId); String alias = getDecryptAlias(userId, generationId); if (!mKeyStore.containsAlias(alias)) { throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias); } AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey( getDecryptAlias(userId, generationId), /*password=*/ null); alias, /*password=*/ null); return new PlatformDecryptionKey(generationId, key); } Loading Loading @@ -405,16 +434,4 @@ public class PlatformKeyManager { return keyStore; } /** * @hide */ public interface Factory { /** * New PlatformKeyManager instance. * * @hide */ PlatformKeyManager newInstance() throws NoSuchAlgorithmException, InsecureUserException, KeyStoreException; } }
services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -579,6 +579,7 @@ public class RecoverableKeyStoreManager { /** * This function can only be used inside LockSettingsService. * * @param storedHashType from {@code CredentialHash} * @param credential - unencrypted String * @param userId for the user whose lock screen credentials were changed. Loading @@ -604,7 +605,7 @@ public class RecoverableKeyStoreManager { } catch (KeyStoreException e) { Log.e(TAG, "Key store error encountered during recoverable key sync", e); } catch (InsecureUserException e) { Log.wtf(TAG, "Impossible - insecure user, but user just entered lock screen", e); Log.e(TAG, "InsecureUserException during lock screen secret update", e); } } Loading
services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +4 −4 Original line number Diff line number Diff line Loading @@ -121,7 +121,7 @@ public class KeySyncTaskTest { TEST_CREDENTIAL_TYPE, TEST_CREDENTIAL, /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mWrappingKey = generateAndroidKeyStoreKey(); mEncryptKey = new PlatformEncryptionKey(TEST_GENERATION_ID, mWrappingKey); Loading Loading @@ -352,7 +352,7 @@ public class KeySyncTaskTest { CREDENTIAL_TYPE_PASSWORD, "password", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading @@ -378,7 +378,7 @@ public class KeySyncTaskTest { CREDENTIAL_TYPE_PASSWORD, /*credential=*/ "1234", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading @@ -405,7 +405,7 @@ public class KeySyncTaskTest { CREDENTIAL_TYPE_PATTERN, "12345", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading