diff options
2 files changed, 138 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java index 3a78f950675e..e5ff5b83704f 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/PlatformKeyManager.java @@ -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. } /** diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java index f9ffccdd5d38..0f0e3f386fec 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/PlatformKeyManagerTest.java @@ -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); @@ -264,6 +267,56 @@ public class PlatformKeyManagerTest { } @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( eq("com.android.server.locksettings.recoverablekeystore/platform/42/1/encrypt"), @@ -274,7 +327,13 @@ public class PlatformKeyManagerTest { + "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/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); // new version is available + + "platform/42/2/decrypt")).thenReturn(true); mPlatformKeyManager.getDecryptKey(USER_ID_FIXTURE); @@ -312,14 +376,70 @@ 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(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/1/encrypt")).thenReturn(false); // was removed. + + "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); + + 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_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); @@ -332,10 +452,13 @@ public class PlatformKeyManagerTest { } @Test - public void getEncryptKey_getsEndryptKeyWithCorrectAlias() throws Exception { + 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); |