Loading services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +7 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.locksettings.recoverablekeystore; import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.security.recoverablekeystore.KeyDerivationParameters; import android.security.recoverablekeystore.KeyEntryRecoveryData; Loading Loading @@ -100,7 +101,7 @@ public class KeySyncTask implements Runnable { * * @param recoverableKeyStoreDb Database where the keys are stored. * @param userId The uid of the user whose profile has been unlocked. * @param credentialType The type of credential - i.e., pattern or password. * @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. Loading Loading @@ -250,7 +251,7 @@ public class KeySyncTask implements Runnable { // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later KeyStoreRecoveryMetadata metadata = new KeyStoreRecoveryMetadata( /*userSecretType=*/ TYPE_LOCKSCREEN, /*lockScreenUiFormat=*/ mCredentialType, /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential), /*keyDerivationParameters=*/ KeyDerivationParameters.createSha256Parameters(salt), /*secret=*/ new byte[0]); ArrayList<KeyStoreRecoveryMetadata> metadataList = new ArrayList<>(); Loading Loading @@ -347,7 +348,10 @@ public class KeySyncTask implements Runnable { * Returns {@code true} if {@code credential} looks like a pin. */ @VisibleForTesting static boolean isPin(@NonNull String credential) { static boolean isPin(@Nullable String credential) { if (credential == null) { return false; } int length = credential.length(); for (int i = 0; i < length; i++) { if (!Character.isDigit(credential.charAt(i))) { Loading services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +81 −1 Original line number Diff line number Diff line Loading @@ -327,6 +327,86 @@ public class KeySyncTaskTest { assertThat(recoveryData.getSnapshotVersion()).isEqualTo(2); // Updated } @Test public void run_setsCorrectTypeForPassword() throws Exception { mKeySyncTask = new KeySyncTask( mRecoverableKeyStoreDb, mRecoverySnapshotStorage, mSnapshotListenersStorage, TEST_USER_ID, CREDENTIAL_TYPE_PASSWORD, "password", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); SecretKey applicationKey = addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(recoveryData.getRecoveryMetadata()).hasSize(1); assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()). isEqualTo(TYPE_PASSWORD); } @Test public void run_setsCorrectTypeForPin() throws Exception { mKeySyncTask = new KeySyncTask( mRecoverableKeyStoreDb, mRecoverySnapshotStorage, mSnapshotListenersStorage, TEST_USER_ID, CREDENTIAL_TYPE_PASSWORD, /*credential=*/ "1234", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); SecretKey applicationKey = addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(recoveryData.getRecoveryMetadata()).hasSize(1); // Password with only digits is changed to pin. assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()). isEqualTo(TYPE_PIN); } @Test public void run_setsCorrectTypeForPattern() throws Exception { mKeySyncTask = new KeySyncTask( mRecoverableKeyStoreDb, mRecoverySnapshotStorage, mSnapshotListenersStorage, TEST_USER_ID, CREDENTIAL_TYPE_PATTERN, "12345", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); SecretKey applicationKey = addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(recoveryData.getRecoveryMetadata()).hasSize(1); assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()). isEqualTo(TYPE_PATTERN); } @Test public void run_sendsEncryptedKeysWithTwoRegisteredAgents() throws Exception { Loading @@ -345,7 +425,7 @@ public class KeySyncTaskTest { } @Test public void run_doesnSendKeyToNonregisteredAgent() throws Exception { public void run_doesNotSendKeyToNonregisteredAgent() throws Exception { mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading Loading
services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +7 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.locksettings.recoverablekeystore; import static android.security.recoverablekeystore.KeyStoreRecoveryMetadata.TYPE_LOCKSCREEN; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.security.recoverablekeystore.KeyDerivationParameters; import android.security.recoverablekeystore.KeyEntryRecoveryData; Loading Loading @@ -100,7 +101,7 @@ public class KeySyncTask implements Runnable { * * @param recoverableKeyStoreDb Database where the keys are stored. * @param userId The uid of the user whose profile has been unlocked. * @param credentialType The type of credential - i.e., pattern or password. * @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. Loading Loading @@ -250,7 +251,7 @@ public class KeySyncTask implements Runnable { // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later KeyStoreRecoveryMetadata metadata = new KeyStoreRecoveryMetadata( /*userSecretType=*/ TYPE_LOCKSCREEN, /*lockScreenUiFormat=*/ mCredentialType, /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential), /*keyDerivationParameters=*/ KeyDerivationParameters.createSha256Parameters(salt), /*secret=*/ new byte[0]); ArrayList<KeyStoreRecoveryMetadata> metadataList = new ArrayList<>(); Loading Loading @@ -347,7 +348,10 @@ public class KeySyncTask implements Runnable { * Returns {@code true} if {@code credential} looks like a pin. */ @VisibleForTesting static boolean isPin(@NonNull String credential) { static boolean isPin(@Nullable String credential) { if (credential == null) { return false; } int length = credential.length(); for (int i = 0; i < length; i++) { if (!Character.isDigit(credential.charAt(i))) { Loading
services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +81 −1 Original line number Diff line number Diff line Loading @@ -327,6 +327,86 @@ public class KeySyncTaskTest { assertThat(recoveryData.getSnapshotVersion()).isEqualTo(2); // Updated } @Test public void run_setsCorrectTypeForPassword() throws Exception { mKeySyncTask = new KeySyncTask( mRecoverableKeyStoreDb, mRecoverySnapshotStorage, mSnapshotListenersStorage, TEST_USER_ID, CREDENTIAL_TYPE_PASSWORD, "password", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); SecretKey applicationKey = addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(recoveryData.getRecoveryMetadata()).hasSize(1); assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()). isEqualTo(TYPE_PASSWORD); } @Test public void run_setsCorrectTypeForPin() throws Exception { mKeySyncTask = new KeySyncTask( mRecoverableKeyStoreDb, mRecoverySnapshotStorage, mSnapshotListenersStorage, TEST_USER_ID, CREDENTIAL_TYPE_PASSWORD, /*credential=*/ "1234", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); SecretKey applicationKey = addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(recoveryData.getRecoveryMetadata()).hasSize(1); // Password with only digits is changed to pin. assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()). isEqualTo(TYPE_PIN); } @Test public void run_setsCorrectTypeForPattern() throws Exception { mKeySyncTask = new KeySyncTask( mRecoverableKeyStoreDb, mRecoverySnapshotStorage, mSnapshotListenersStorage, TEST_USER_ID, CREDENTIAL_TYPE_PATTERN, "12345", /*credentialUpdated=*/ false, () -> mPlatformKeyManager); mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); SecretKey applicationKey = addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyStoreRecoveryData recoveryData = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(recoveryData.getRecoveryMetadata()).hasSize(1); assertThat(recoveryData.getRecoveryMetadata().get(1).getLockScreenUiFormat()). isEqualTo(TYPE_PATTERN); } @Test public void run_sendsEncryptedKeysWithTwoRegisteredAgents() throws Exception { Loading @@ -345,7 +425,7 @@ public class KeySyncTaskTest { } @Test public void run_doesnSendKeyToNonregisteredAgent() throws Exception { public void run_doesNotSendKeyToNonregisteredAgent() throws Exception { mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); Loading