Merge "Try to check the platform decryption key is still accessible before using the platform encryption key"
This commit is contained in:
@@ -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.
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user