Don't create recovery snapshot until it contains at least one key.

Bug: 77931409
Test: atest RecoveryControllerHostTest
Change-Id: Ibd239cbd21a756a00c33e3cd0100b389b88d38b0
This commit is contained in:
Dmitry Dementyev
2018-04-12 12:10:50 -07:00
parent 6ce8408618
commit 925f026cc1
3 changed files with 85 additions and 18 deletions

View File

@@ -232,9 +232,6 @@ public class RecoverableKeyStoreManager {
throw new ServiceSpecificException(ERROR_INVALID_CERTIFICATE, e.getMessage());
}
boolean wasInitialized = mDatabase.getRecoveryServiceCertPath(userId, uid,
rootCertificateAlias) != null;
// Save the chosen and validated certificate into database
try {
Log.d(TAG, "Saving the randomly chosen endpoint certificate to database");
@@ -242,9 +239,11 @@ public class RecoverableKeyStoreManager {
certPath) > 0) {
mDatabase.setRecoveryServiceCertSerial(userId, uid, rootCertificateAlias,
newSerial);
if (wasInitialized) {
Log.i(TAG, "This is a certificate change. Snapshot pending.");
if (mDatabase.getSnapshotVersion(userId, uid) != null) {
mDatabase.setShouldCreateSnapshot(userId, uid, true);
Log.i(TAG, "This is a certificate change. Snapshot must be updated");
} else {
Log.i(TAG, "This is a certificate change. Snapshot didn't exist");
}
mDatabase.setCounterId(userId, uid, new SecureRandom().nextLong());
}
@@ -350,8 +349,12 @@ public class RecoverableKeyStoreManager {
return;
}
Log.i(TAG, "Updated server params. Snapshot pending.");
mDatabase.setShouldCreateSnapshot(userId, uid, true);
if (mDatabase.getSnapshotVersion(userId, uid) != null) {
mDatabase.setShouldCreateSnapshot(userId, uid, true);
Log.i(TAG, "Updated server params. Snapshot must be updated");
} else {
Log.i(TAG, "Updated server params. Snapshot didn't exist");
}
}
/**
@@ -407,7 +410,12 @@ public class RecoverableKeyStoreManager {
}
Log.i(TAG, "Updated secret types. Snapshot pending.");
mDatabase.setShouldCreateSnapshot(userId, uid, true);
if (mDatabase.getSnapshotVersion(userId, uid) != null) {
mDatabase.setShouldCreateSnapshot(userId, uid, true);
Log.i(TAG, "Updated secret types. Snapshot must be updated");
} else {
Log.i(TAG, "Updated secret types. Snapshot didn't exist");
}
}
/**

View File

@@ -789,11 +789,20 @@ public class RecoverableKeyStoreDb {
}
/**
* Updates the snapshot version.
* Updates a flag indicating that a new snapshot should be created.
* It will be {@code false} until the first application key is added.
* After that, the flag will be set to true, if one of the following values is updated:
* <ul>
* <li> List of application keys
* <li> Server params.
* <li> Lock-screen secret.
* <li> Lock-screen secret type.
* <li> Trusted hardware certificate.
* </ul>
*
* @param userId The userId of the profile the application is running under.
* @param uid The uid of the application.
* @param pending The server parameters.
* @param pending Should create snapshot flag.
* @return The primary key of the inserted row, or -1 if failed.
*
* @hide
@@ -809,7 +818,7 @@ public class RecoverableKeyStoreDb {
*
* @param userId The userId of the profile the application is running under.
* @param uid The uid of the application who initialized the local recovery components.
* @return snapshot outdated flag.
* @return should create snapshot flag
*
* @hide
*/

View File

@@ -301,6 +301,33 @@ public class RecoverableKeyStoreManagerTest {
assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
}
@Test
public void initRecoveryService_updatesShouldCreatesnapshotOnCertUpdate() throws Exception {
int uid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
long certSerial = 1000L;
mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial));
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial + 1));
// Since there were no recoverable keys, new snapshot will not be created.
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
generateKeyAndSimulateSync(userId, uid, 10);
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial + 2));
// Since there were a recoverable key, new serial number triggers snapshot creation
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
}
@Test
public void initRecoveryService_triesToFilterRootAlias() throws Exception {
int uid = Binder.getCallingUid();
@@ -405,7 +432,8 @@ public class RecoverableKeyStoreManagerTest {
assertThat(mRecoverableKeyStoreDb.getRecoveryServiceCertSerial(userId, uid,
DEFAULT_ROOT_CERT_ALIAS)).isEqualTo(certSerial + 1);
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
// There were no keys.
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
}
@Test
@@ -479,10 +507,12 @@ public class RecoverableKeyStoreManagerTest {
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial));
generateKeyAndSimulateSync(userId, uid, 10);
mRecoverableKeyStoreManager.initRecoveryService(ROOT_CERTIFICATE_ALIAS,
TestData.getCertXmlWithSerial(certSerial));
// If the second update succeeds, getShouldCreateSnapshot() will return true.
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
}
@@ -935,7 +965,6 @@ public class RecoverableKeyStoreManagerTest {
assertThat(recoveredKeys).hasSize(1);
assertThat(recoveredKeys).containsKey(TEST_ALIAS);
// TODO(76083050) Test the grant mechanism for the keys.
}
@Test
@@ -974,7 +1003,6 @@ public class RecoverableKeyStoreManagerTest {
assertThat(recoveredKeys).hasSize(1);
assertThat(recoveredKeys).containsKey(TEST_ALIAS2);
// TODO(76083050) Test the grant mechanism for the keys.
}
@Test
@@ -1016,6 +1044,9 @@ public class RecoverableKeyStoreManagerTest {
byte[] serverParams = new byte[] { 1 };
mRecoverableKeyStoreManager.setServerParams(serverParams);
generateKeyAndSimulateSync(userId, uid, 10);
mRecoverableKeyStoreManager.setServerParams(serverParams);
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
@@ -1027,6 +1058,9 @@ public class RecoverableKeyStoreManagerTest {
int userId = UserHandle.getCallingUserId();
mRecoverableKeyStoreManager.setServerParams(new byte[] { 1 });
generateKeyAndSimulateSync(userId, uid, 10);
mRecoverableKeyStoreManager.setServerParams(new byte[] { 2 });
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
@@ -1059,6 +1093,7 @@ public class RecoverableKeyStoreManagerTest {
mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
// There were no keys.
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
}
@@ -1070,6 +1105,9 @@ public class RecoverableKeyStoreManagerTest {
int[] secretTypes = new int[] { 101 };
mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
generateKeyAndSimulateSync(userId, uid, 10);
mRecoverableKeyStoreManager.setRecoverySecretTypes(secretTypes);
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
@@ -1081,6 +1119,11 @@ public class RecoverableKeyStoreManagerTest {
int userId = UserHandle.getCallingUserId();
mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 101 });
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
generateKeyAndSimulateSync(userId, uid, 10);
mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 102 });
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
@@ -1102,9 +1145,8 @@ public class RecoverableKeyStoreManagerTest {
int userId = UserHandle.getCallingUserId();
mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 1 });
mRecoverableKeyStoreManager.generateKey(TEST_ALIAS);
// Pretend that key was synced
mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
generateKeyAndSimulateSync(userId, uid, 10);
mRecoverableKeyStoreManager.setRecoverySecretTypes(new int[] { 2 });
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
@@ -1175,6 +1217,14 @@ public class RecoverableKeyStoreManagerTest {
return bytes;
}
private void generateKeyAndSimulateSync(int userId, int uid, int snapshotVersion)
throws Exception{
mRecoverableKeyStoreManager.generateKey(TEST_ALIAS);
// Simulate key sync.
mRecoverableKeyStoreDb.setSnapshotVersion(userId, uid, snapshotVersion);
mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false);
}
private AndroidKeyStoreSecretKey generateAndroidKeyStoreKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KEY_ALGORITHM,