Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bc6f2e4 authored by Bo Zhu's avatar Bo Zhu Committed by Android (Google) Code Review
Browse files

Merge "Use Scrypt to hash all passwords in RecoverableKeyStore" into pi-dev

parents eb914118 c3aefbd7
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -70,8 +70,6 @@ public class KeySyncTask implements Runnable {
    private static final String LOCK_SCREEN_HASH_ALGORITHM = "SHA-256";
    private static final int TRUSTED_HARDWARE_MAX_ATTEMPTS = 10;

    // TODO: Reduce the minimal length once all other components are updated
    private static final int MIN_CREDENTIAL_LEN_TO_USE_SCRYPT = 24;
    @VisibleForTesting
    static final int SCRYPT_PARAM_N = 4096;
    @VisibleForTesting
@@ -246,7 +244,7 @@ public class KeySyncTask implements Runnable {
            }
        }

        boolean useScryptToHashCredential = shouldUseScryptToHashCredential(rootCertAlias);
        boolean useScryptToHashCredential = shouldUseScryptToHashCredential();
        byte[] salt = generateSalt();
        byte[] localLskfHash;
        if (useScryptToHashCredential) {
@@ -514,10 +512,7 @@ public class KeySyncTask implements Runnable {
        return keyEntries;
    }

    private boolean shouldUseScryptToHashCredential(String rootCertAlias) {
        return mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD
                && mCredential.length() >= MIN_CREDENTIAL_LEN_TO_USE_SCRYPT
                // TODO: Remove the test cert check once all other components are updated
                && mTestOnlyInsecureCertificateHelper.isTestOnlyCertificateAlias(rootCertAlias);
    private boolean shouldUseScryptToHashCredential() {
        return mCredentialType == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
    }
}
+29 −61
Original line number Diff line number Diff line
@@ -92,8 +92,8 @@ public class KeySyncTaskTest {
            new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
    private static final String TEST_APP_KEY_ALIAS = "rcleaver";
    private static final int TEST_GENERATION_ID = 2;
    private static final int TEST_CREDENTIAL_TYPE = CREDENTIAL_TYPE_PASSWORD;
    private static final String TEST_CREDENTIAL = "password1234";
    private static final int TEST_CREDENTIAL_TYPE = CREDENTIAL_TYPE_PATTERN;
    private static final String TEST_CREDENTIAL = "pas123";
    private static final byte[] THM_ENCRYPTED_RECOVERY_KEY_HEADER =
            "V1 THM_encrypted_recovery_key".getBytes(StandardCharsets.UTF_8);

@@ -278,8 +278,8 @@ public class KeySyncTaskTest {
    }

    @Test
    public void run_useScryptToHashLongPasswordInTestMode() throws Exception {
        String longPassword = TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "0123456789";
    public void run_useScryptToHashPasswordInTestMode() throws Exception {
        String password = TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "";  // The shortest
        String appKeyAlias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX + "alias";
        mKeySyncTask = new KeySyncTask(
                mRecoverableKeyStoreDb,
@@ -287,7 +287,7 @@ public class KeySyncTaskTest {
                mSnapshotListenersStorage,
                TEST_USER_ID,
                CREDENTIAL_TYPE_PASSWORD,
                /*credential=*/ longPassword,
                /*credential=*/ password,
                /*credentialUpdated=*/ false,
                mPlatformKeyManager,
                mTestOnlyInsecureCertificateHelper,
@@ -309,7 +309,7 @@ public class KeySyncTaskTest {
        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
                isEqualTo(UI_FORMAT_PASSWORD);
        verify(mMockScrypt).scrypt(eq(longPassword.getBytes()), any(),
        verify(mMockScrypt).scrypt(eq(password.getBytes()), any(),
                eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
                eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
        KeyDerivationParams keyDerivationParams =
@@ -320,54 +320,15 @@ public class KeySyncTaskTest {
    }

    @Test
    public void run_useSha256ToHashShortPasswordInTestMode() throws Exception {
        String shortPassword = TrustedRootCertificates.INSECURE_PASSWORD_PREFIX + "012345678";
        String appKeyAlias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX + "alias";
    public void run_useSha256ToHashPatternInProdMode() throws Exception {
        String pattern = "123456";
        mKeySyncTask = new KeySyncTask(
                mRecoverableKeyStoreDb,
                mRecoverySnapshotStorage,
                mSnapshotListenersStorage,
                TEST_USER_ID,
                CREDENTIAL_TYPE_PASSWORD,
                /*credential=*/ shortPassword,
                /*credentialUpdated=*/ false,
                mPlatformKeyManager,
                mTestOnlyInsecureCertificateHelper,
                mMockScrypt);
        mRecoverableKeyStoreDb.setServerParams(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
        mRecoverableKeyStoreDb.setPlatformKeyGenerationId(TEST_USER_ID, TEST_GENERATION_ID);
        mRecoverableKeyStoreDb.setActiveRootOfTrust(TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
                TrustedRootCertificates.TEST_ONLY_INSECURE_CERTIFICATE_ALIAS);
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID,
                TrustedRootCertificates.TEST_ONLY_INSECURE_CERTIFICATE_ALIAS,
                TestData.getInsecureCertPathForEndpoint1());
        addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, appKeyAlias);

        mKeySyncTask.run();

        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
                isEqualTo(UI_FORMAT_PASSWORD);
        verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
        KeyDerivationParams keyDerivationParams =
                keyChainSnapshot.getKeyChainProtectionParams().get(0).getKeyDerivationParams();
        assertThat(keyDerivationParams.getAlgorithm()).isEqualTo(
                KeyDerivationParams.ALGORITHM_SHA256);
    }

    @Test
    public void run_useSha256ToHashShortPasswordInProdMode() throws Exception {
        String shortPassword = "01234567890123456789abc";  // 23 chars
        mKeySyncTask = new KeySyncTask(
                mRecoverableKeyStoreDb,
                mRecoverySnapshotStorage,
                mSnapshotListenersStorage,
                TEST_USER_ID,
                CREDENTIAL_TYPE_PASSWORD,
                /*credential=*/ shortPassword,
                CREDENTIAL_TYPE_PATTERN,
                /*credential=*/ pattern,
                /*credentialUpdated=*/ false,
                mPlatformKeyManager,
                mTestOnlyInsecureCertificateHelper,
@@ -384,7 +345,7 @@ public class KeySyncTaskTest {
        KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
                isEqualTo(UI_FORMAT_PASSWORD);
                isEqualTo(UI_FORMAT_PATTERN);
        verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
        KeyDerivationParams keyDerivationParams =
                keyChainSnapshot.getKeyChainProtectionParams().get(0).getKeyDerivationParams();
@@ -393,15 +354,15 @@ public class KeySyncTaskTest {
    }

    @Test
    public void run_useSha256ToHashLongPasswordInProdMode() throws Exception {
        String longPassword = "01234567890123456789abcd";  // 24 chars
    public void run_useScryptToHashPasswordInProdMode() throws Exception {
        String shortPassword = "abc";
        mKeySyncTask = new KeySyncTask(
                mRecoverableKeyStoreDb,
                mRecoverySnapshotStorage,
                mSnapshotListenersStorage,
                TEST_USER_ID,
                CREDENTIAL_TYPE_PASSWORD,
                /*credential=*/ longPassword,
                /*credential=*/ shortPassword,
                /*credentialUpdated=*/ false,
                mPlatformKeyManager,
                mTestOnlyInsecureCertificateHelper,
@@ -419,11 +380,13 @@ public class KeySyncTaskTest {
        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
                isEqualTo(UI_FORMAT_PASSWORD);
        verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
        verify(mMockScrypt).scrypt(eq(shortPassword.getBytes()), any(),
                eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
                eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
        KeyDerivationParams keyDerivationParams =
                keyChainSnapshot.getKeyChainProtectionParams().get(0).getKeyDerivationParams();
        assertThat(keyDerivationParams.getAlgorithm()).isEqualTo(
                KeyDerivationParams.ALGORITHM_SHA256);
                KeyDerivationParams.ALGORITHM_SCRYPT);
    }

    @Test
@@ -644,13 +607,14 @@ public class KeySyncTaskTest {

    @Test
    public void run_setsCorrectTypeForPassword() throws Exception {
        String password = "password";
        mKeySyncTask = new KeySyncTask(
                mRecoverableKeyStoreDb,
                mRecoverySnapshotStorage,
                mSnapshotListenersStorage,
                TEST_USER_ID,
                CREDENTIAL_TYPE_PASSWORD,
                "password",
                password,
                /*credentialUpdated=*/ false,
                mPlatformKeyManager,
                mTestOnlyInsecureCertificateHelper,
@@ -659,7 +623,6 @@ public class KeySyncTaskTest {
        mRecoverableKeyStoreDb.setRecoveryServiceCertPath(
                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1);
        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();
@@ -668,18 +631,21 @@ public class KeySyncTaskTest {
        assertThat(keyChainSnapshot.getKeyChainProtectionParams()).hasSize(1);
        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
                isEqualTo(UI_FORMAT_PASSWORD);
        verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
        verify(mMockScrypt).scrypt(eq(password.getBytes()), any(),
                eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
                eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
    }

    @Test
    public void run_setsCorrectTypeForPin() throws Exception {
        String pin = "1234";
        mKeySyncTask = new KeySyncTask(
                mRecoverableKeyStoreDb,
                mRecoverySnapshotStorage,
                mSnapshotListenersStorage,
                TEST_USER_ID,
                CREDENTIAL_TYPE_PASSWORD,
                /*credential=*/ "1234",
                /*credential=*/ pin,
                /*credentialUpdated=*/ false,
                mPlatformKeyManager,
                mTestOnlyInsecureCertificateHelper,
@@ -698,7 +664,9 @@ public class KeySyncTaskTest {
        // Password with only digits is changed to pin.
        assertThat(keyChainSnapshot.getKeyChainProtectionParams().get(0).getLockScreenUiFormat()).
                isEqualTo(UI_FORMAT_PIN);
        verify(mMockScrypt, never()).scrypt(any(), any(), anyInt(), anyInt(), anyInt(), anyInt());
        verify(mMockScrypt).scrypt(eq(pin.getBytes()), any(),
                eq(KeySyncTask.SCRYPT_PARAM_N), eq(KeySyncTask.SCRYPT_PARAM_R),
                eq(KeySyncTask.SCRYPT_PARAM_P), eq(KeySyncTask.SCRYPT_PARAM_OUTLEN_BYTES));
    }

    @Test