Loading services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +29 −18 Original line number Diff line number Diff line Loading @@ -158,10 +158,18 @@ public class KeySyncTask implements Runnable { } private void syncKeysForAgent(int recoveryAgentUid) { boolean recreateCurrentVersion = false; if (!shoudCreateSnapshot(recoveryAgentUid)) { recreateCurrentVersion = (mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid) != null) && (mRecoverySnapshotStorage.get(recoveryAgentUid) == null); if (recreateCurrentVersion) { Log.d(TAG, "Recreating most recent snapshot"); } else { Log.d(TAG, "Key sync not needed."); return; } } if (!mSnapshotListenersStorage.hasListener(recoveryAgentUid)) { Log.w(TAG, "No pending intent registered for recovery agent " + recoveryAgentUid); Loading Loading @@ -253,23 +261,21 @@ public class KeySyncTask implements Runnable { Log.e(TAG,"Could not encrypt with recovery key", e); return; } // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later // TODO: use Builder. KeyChainProtectionParams metadata = new KeyChainProtectionParams( /*userSecretType=*/ TYPE_LOCKSCREEN, /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential), /*keyDerivationParams=*/ KeyDerivationParams.createSha256Params(salt), /*secret=*/ new byte[0]); KeyChainProtectionParams metadata = new KeyChainProtectionParams.Builder() .setUserSecretType(TYPE_LOCKSCREEN) .setLockScreenUiFormat(getUiFormat(mCredentialType, mCredential)) .setKeyDerivationParams(KeyDerivationParams.createSha256Params(salt)) .setSecret(new byte[0]) .build(); ArrayList<KeyChainProtectionParams> metadataList = new ArrayList<>(); metadataList.add(metadata); int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid); // If application keys are not updated, snapshot will not be created on next unlock. mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false); mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyChainSnapshot.Builder() .setSnapshotVersion(snapshotVersion) .setSnapshotVersion(getSnapshotVersion(recoveryAgentUid, recreateCurrentVersion)) .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS) .setCounterId(counterId) .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey)) Loading @@ -283,9 +289,14 @@ public class KeySyncTask implements Runnable { } @VisibleForTesting int incrementSnapshotVersion(int recoveryAgentUid) { int getSnapshotVersion(int recoveryAgentUid, boolean recreateCurrentVersion) { Long snapshotVersion = mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid); if (recreateCurrentVersion) { // version shouldn't be null at this moment. snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion; } else { snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion + 1; } mRecoverableKeyStoreDb.setSnapshotVersion(mUserId, recoveryAgentUid, snapshotVersion); return snapshotVersion.intValue(); Loading Loading @@ -413,10 +424,10 @@ public class KeySyncTask implements Runnable { Map<String, byte[]> encryptedApplicationKeys) { ArrayList<WrappedApplicationKey> keyEntries = new ArrayList<>(); for (String alias : encryptedApplicationKeys.keySet()) { keyEntries.add( new WrappedApplicationKey( alias, encryptedApplicationKeys.get(alias))); keyEntries.add(new WrappedApplicationKey.Builder() .setAlias(alias) .setEncryptedKeyMaterial(encryptedApplicationKeys.get(alias)) .build()); } return keyEntries; } Loading services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +21 −2 Original line number Diff line number Diff line Loading @@ -327,7 +327,6 @@ public class KeySyncTaskTest { 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(); Loading @@ -342,6 +341,26 @@ public class KeySyncTaskTest { assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(2); // Updated } @Test public void run_recreatesMissingSnapshot() throws Exception { mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value; mRecoverySnapshotStorage.remove(TEST_RECOVERY_AGENT_UID); // corrupt snapshot. mKeySyncTask.run(); keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // Same version } @Test public void run_setsCorrectTypeForPassword() throws Exception { mKeySyncTask = new KeySyncTask( Loading Loading
services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +29 −18 Original line number Diff line number Diff line Loading @@ -158,10 +158,18 @@ public class KeySyncTask implements Runnable { } private void syncKeysForAgent(int recoveryAgentUid) { boolean recreateCurrentVersion = false; if (!shoudCreateSnapshot(recoveryAgentUid)) { recreateCurrentVersion = (mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid) != null) && (mRecoverySnapshotStorage.get(recoveryAgentUid) == null); if (recreateCurrentVersion) { Log.d(TAG, "Recreating most recent snapshot"); } else { Log.d(TAG, "Key sync not needed."); return; } } if (!mSnapshotListenersStorage.hasListener(recoveryAgentUid)) { Log.w(TAG, "No pending intent registered for recovery agent " + recoveryAgentUid); Loading Loading @@ -253,23 +261,21 @@ public class KeySyncTask implements Runnable { Log.e(TAG,"Could not encrypt with recovery key", e); return; } // TODO: store raw data in RecoveryServiceMetadataEntry and generate Parcelables later // TODO: use Builder. KeyChainProtectionParams metadata = new KeyChainProtectionParams( /*userSecretType=*/ TYPE_LOCKSCREEN, /*lockScreenUiFormat=*/ getUiFormat(mCredentialType, mCredential), /*keyDerivationParams=*/ KeyDerivationParams.createSha256Params(salt), /*secret=*/ new byte[0]); KeyChainProtectionParams metadata = new KeyChainProtectionParams.Builder() .setUserSecretType(TYPE_LOCKSCREEN) .setLockScreenUiFormat(getUiFormat(mCredentialType, mCredential)) .setKeyDerivationParams(KeyDerivationParams.createSha256Params(salt)) .setSecret(new byte[0]) .build(); ArrayList<KeyChainProtectionParams> metadataList = new ArrayList<>(); metadataList.add(metadata); int snapshotVersion = incrementSnapshotVersion(recoveryAgentUid); // If application keys are not updated, snapshot will not be created on next unlock. mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false); mRecoverySnapshotStorage.put(recoveryAgentUid, new KeyChainSnapshot.Builder() .setSnapshotVersion(snapshotVersion) .setSnapshotVersion(getSnapshotVersion(recoveryAgentUid, recreateCurrentVersion)) .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS) .setCounterId(counterId) .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey)) Loading @@ -283,9 +289,14 @@ public class KeySyncTask implements Runnable { } @VisibleForTesting int incrementSnapshotVersion(int recoveryAgentUid) { int getSnapshotVersion(int recoveryAgentUid, boolean recreateCurrentVersion) { Long snapshotVersion = mRecoverableKeyStoreDb.getSnapshotVersion(mUserId, recoveryAgentUid); if (recreateCurrentVersion) { // version shouldn't be null at this moment. snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion; } else { snapshotVersion = snapshotVersion == null ? 1 : snapshotVersion + 1; } mRecoverableKeyStoreDb.setSnapshotVersion(mUserId, recoveryAgentUid, snapshotVersion); return snapshotVersion.intValue(); Loading Loading @@ -413,10 +424,10 @@ public class KeySyncTask implements Runnable { Map<String, byte[]> encryptedApplicationKeys) { ArrayList<WrappedApplicationKey> keyEntries = new ArrayList<>(); for (String alias : encryptedApplicationKeys.keySet()) { keyEntries.add( new WrappedApplicationKey( alias, encryptedApplicationKeys.get(alias))); keyEntries.add(new WrappedApplicationKey.Builder() .setAlias(alias) .setEncryptedKeyMaterial(encryptedApplicationKeys.get(alias)) .build()); } return keyEntries; } Loading
services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +21 −2 Original line number Diff line number Diff line Loading @@ -327,7 +327,6 @@ public class KeySyncTaskTest { 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(); Loading @@ -342,6 +341,26 @@ public class KeySyncTaskTest { assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(2); // Updated } @Test public void run_recreatesMissingSnapshot() throws Exception { mRecoverableKeyStoreDb.setRecoveryServicePublicKey( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic()); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); mKeySyncTask.run(); KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // default value; mRecoverySnapshotStorage.remove(TEST_RECOVERY_AGENT_UID); // corrupt snapshot. mKeySyncTask.run(); keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); assertThat(keyChainSnapshot.getSnapshotVersion()).isEqualTo(1); // Same version } @Test public void run_setsCorrectTypeForPassword() throws Exception { mKeySyncTask = new KeySyncTask( Loading