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;
*
* @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.
// 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<>();
* 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))) {
}
@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 {
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
}
@Test
- public void run_doesnSendKeyToNonregisteredAgent() throws Exception {
+ public void run_doesNotSendKeyToNonregisteredAgent() throws Exception {
mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());