Merge "Try to check the platform decryption key is still accessible before using the platform encryption key"

This commit is contained in:
Bo Zhu
2018-02-06 20:13:14 +00:00
committed by Android (Google) Code Review
2 changed files with 139 additions and 18 deletions

View File

@@ -194,6 +194,9 @@ public class PlatformKeyManager {
UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
init(userId);
try {
// Try to see if the decryption key is still accessible before using the encryption key.
// The auth-bound decryption will be unrecoverable if the screen lock is disabled.
getDecryptKeyInternal(userId);
return getEncryptKeyInternal(userId);
} catch (UnrecoverableKeyException e) {
Log.i(TAG, String.format(Locale.US,
@@ -219,7 +222,7 @@ public class PlatformKeyManager {
UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
int generationId = getGenerationId(userId);
String alias = getEncryptAlias(userId, generationId);
if (!mKeyStore.containsAlias(alias)) {
if (!isKeyLoaded(userId, generationId)) {
throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
}
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
@@ -268,7 +271,7 @@ public class PlatformKeyManager {
UnrecoverableKeyException, NoSuchAlgorithmException, InsecureUserException {
int generationId = getGenerationId(userId);
String alias = getDecryptAlias(userId, generationId);
if (!mKeyStore.containsAlias(alias)) {
if (!isKeyLoaded(userId, generationId)) {
throw new UnrecoverableKeyException("KeyStore doesn't contain key " + alias);
}
AndroidKeyStoreSecretKey key = (AndroidKeyStoreSecretKey) mKeyStore.getKey(
@@ -300,12 +303,12 @@ public class PlatformKeyManager {
return;
}
if (generationId == -1) {
Log.i(TAG, "Generating initial platform ID.");
Log.i(TAG, "Generating initial platform key generation ID.");
generationId = 1;
} else {
Log.w(TAG, String.format(Locale.US, "Platform generation ID was %d but no "
+ "entry was present in AndroidKeyStore. Generating fresh key.", generationId));
// Had to generate a fresh key, bump the generation id
// Have to generate a fresh key, so bump the generation id
generationId++;
}
@@ -374,7 +377,7 @@ public class PlatformKeyManager {
String decryptAlias = getDecryptAlias(userId, generationId);
SecretKey secretKey = generateAesKey();
// Store Since decryption key first since it is more likely to fail.
// Store decryption key first since it is more likely to fail.
mKeyStore.setEntry(
decryptAlias,
new KeyStore.SecretKeyEntry(secretKey),
@@ -386,7 +389,6 @@ public class PlatformKeyManager {
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setBoundToSpecificSecureUserId(userId)
.build());
mKeyStore.setEntry(
encryptAlias,
new KeyStore.SecretKeyEntry(secretKey),
@@ -397,11 +399,7 @@ public class PlatformKeyManager {
setGenerationId(userId, generationId);
try {
secretKey.destroy();
} catch (DestroyFailedException e) {
Log.w(TAG, "Failed to destroy in-memory platform key.", e);
}
// TODO: Use a reliable way to destroy the temporary secretKey in memory.
}
/**

View File

@@ -255,6 +255,9 @@ public class PlatformKeyManagerTest {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(true);
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
@@ -263,6 +266,56 @@ public class PlatformKeyManagerTest {
any());
}
@Test
public void getDecryptKey_generatesNewKeyIfOldDecryptKeyWasRemoved() throws Exception {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(false); // was removed
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/encrypt")).thenReturn(true); // new version is available
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).containsAlias(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"));
// Attempt to get regenerated key.
verify(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
any());
}
@Test
public void getDecryptKey_generatesNewKeyIfOldEncryptKeyWasRemoved() throws Exception {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(false); // was removed
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).containsAlias(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
// Attempt to get regenerated key.
verify(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/decrypt"),
any());
}
@Test
public void getEncryptKey_generatesNewKeyIfOldOneIsInvalid() throws Exception {
doThrow(new UnrecoverableKeyException()).when(mKeyStoreProxy).getKey(
@@ -272,9 +325,15 @@ public class PlatformKeyManagerTest {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
@@ -295,11 +354,16 @@ public class PlatformKeyManagerTest {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(false); // was removed.
+ "platform/42/1/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true); // new version is available
+ "platform/42/1/decrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE);
@@ -312,14 +376,45 @@ public class PlatformKeyManagerTest {
}
@Test
public void getEncryptKey_generatesNewKeyIfOldWasRemoved() throws Exception {
public void getEncryptKey_generatesNewKeyIfDecryptKeyIsUnrecoverable() throws Exception {
doThrow(new UnrecoverableKeyException()).when(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/decrypt"),
any());
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(false); // was removed.
+ "platform/42/1/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(false); // was removed
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/encrypt")).thenReturn(true); // new version is available
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
// Attempt to get regenerated key.
verify(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"),
any());
}
@Test
public void getEncryptKey_generatesNewKeyIfOldDecryptKeyWasRemoved() throws Exception {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(false); // was removed
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/encrypt")).thenReturn(true); // new version is available
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
@@ -332,10 +427,38 @@ public class PlatformKeyManagerTest {
}
@Test
public void getEncryptKey_getsEndryptKeyWithCorrectAlias() throws Exception {
public void getEncryptKey_generatesNewKeyIfOldEncryptKeyWasRemoved() throws Exception {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(false); // was removed
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/2/decrypt")).thenReturn(true);
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);
verify(mKeyStoreProxy).containsAlias(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"));
// Attempt to get regenerated key.
verify(mKeyStoreProxy).getKey(
eq("com.android.server.locksettings.recoverablekeystore/platform/42/2/encrypt"),
any());
}
@Test
public void getEncryptKey_getsEncryptKeyWithCorrectAlias() throws Exception {
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/encrypt")).thenReturn(true);
when(mKeyStoreProxy
.containsAlias("com.android.server.locksettings.recoverablekeystore/"
+ "platform/42/1/decrypt")).thenReturn(true);
mPlatformKeyManager.getEncryptKey(USER_ID_FIXTURE);