diff options
2 files changed, 55 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java index fda6cdf33e0c..33e767fe1a8f 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java @@ -519,11 +519,11 @@ public class RecoverableKeyStoreManager { byte[] locallyEncryptedKey; try { // TODO: Remove the extraneous logging here - Log.e(TAG, constructLoggingMessage("sessionEntry.getKeyClaimant()", + Log.d(TAG, constructLoggingMessage("sessionEntry.getKeyClaimant()", sessionEntry.getKeyClaimant())); - Log.e(TAG, constructLoggingMessage("sessionEntry.getVaultParams()", + Log.d(TAG, constructLoggingMessage("sessionEntry.getVaultParams()", sessionEntry.getVaultParams())); - Log.e(TAG, constructLoggingMessage("encryptedClaimResponse", encryptedClaimResponse)); + Log.d(TAG, constructLoggingMessage("encryptedClaimResponse", encryptedClaimResponse)); locallyEncryptedKey = KeySyncUtils.decryptRecoveryClaimResponse( sessionEntry.getKeyClaimant(), sessionEntry.getVaultParams(), @@ -543,9 +543,9 @@ public class RecoverableKeyStoreManager { try { // TODO: Remove the extraneous logging here - Log.e(TAG, constructLoggingMessage("sessionEntry.getLskfHash()", + Log.d(TAG, constructLoggingMessage("sessionEntry.getLskfHash()", sessionEntry.getLskfHash())); - Log.e(TAG, constructLoggingMessage("locallyEncryptedKey", locallyEncryptedKey)); + Log.d(TAG, constructLoggingMessage("locallyEncryptedKey", locallyEncryptedKey)); return KeySyncUtils.decryptRecoveryKey(sessionEntry.getLskfHash(), locallyEncryptedKey); } catch (InvalidKeyException e) { Log.e(TAG, "Got InvalidKeyException during decrypting recovery key", e); @@ -585,8 +585,8 @@ public class RecoverableKeyStoreManager { try { // TODO: Remove the extraneous logging here - Log.e(TAG, constructLoggingMessage("recoveryKey", recoveryKey)); - Log.e(TAG, constructLoggingMessage("encryptedKeyMaterial", encryptedKeyMaterial)); + Log.d(TAG, constructLoggingMessage("recoveryKey", recoveryKey)); + Log.d(TAG, constructLoggingMessage("encryptedKeyMaterial", encryptedKeyMaterial)); byte[] keyMaterial = KeySyncUtils.decryptApplicationKey(recoveryKey, encryptedKeyMaterial); keyMaterialByAlias.put(alias, keyMaterial); @@ -600,13 +600,16 @@ public class RecoverableKeyStoreManager { throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED, "Failed to recover key with alias '" + alias + "': " + e.getMessage()); } catch (AEADBadTagException e) { - // TODO: Remove the extraneous logging here Log.e(TAG, "Got AEADBadTagException during decrypting application key with alias: " + alias, e); - throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED, - "Failed to recover key with alias '" + alias + "': " + e.getMessage()); + // Ignore the exception to continue to recover the other application keys. } } + if (keyMaterialByAlias.isEmpty()) { + Log.e(TAG, "Failed to recover any of the application keys."); + throw new ServiceSpecificException(ERROR_DECRYPTION_FAILED, + "Failed to recover any of the application keys."); + } return keyMaterialByAlias; } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index 473a813c3838..2343deec020b 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -125,6 +125,7 @@ public class RecoverableKeyStoreManagerTest { private static final byte[] RECOVERY_RESPONSE_HEADER = "V1 reencrypted_recovery_key".getBytes(StandardCharsets.UTF_8); private static final String TEST_ALIAS = "nick"; + private static final String TEST_ALIAS2 = "bob"; private static final int RECOVERABLE_KEY_SIZE_BYTES = 32; private static final int GENERATION_ID = 1; private static final byte[] NONCE = getUtf8Bytes("nonce"); @@ -424,7 +425,7 @@ public class RecoverableKeyStoreManagerTest { } @Test - public void recoverKeys_throwsIfFailedToDecryptAnApplicationKey() throws Exception { + public void recoverKeys_throwsIfFailedToDecryptAllApplicationKeys() throws Exception { mRecoverableKeyStoreManager.startRecoverySession( TEST_SESSION_ID, TEST_PUBLIC_KEY, @@ -442,7 +443,7 @@ public class RecoverableKeyStoreManagerTest { keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey); WrappedApplicationKey badApplicationKey = new WrappedApplicationKey( TEST_ALIAS, - randomBytes(32)); + encryptedApplicationKey(randomRecoveryKey(), randomBytes(32))); try { mRecoverableKeyStoreManager.recoverKeys( @@ -451,7 +452,7 @@ public class RecoverableKeyStoreManagerTest { /*applicationKeys=*/ ImmutableList.of(badApplicationKey)); fail("should have thrown"); } catch (ServiceSpecificException e) { - assertThat(e.getMessage()).startsWith("Failed to recover key with alias 'nick'"); + assertThat(e.getMessage()).startsWith("Failed to recover any of the application keys"); } } @@ -487,6 +488,44 @@ public class RecoverableKeyStoreManagerTest { } @Test + public void recoverKeys_worksOnOtherApplicationKeysIfOneDecryptionFails() throws Exception { + mRecoverableKeyStoreManager.startRecoverySession( + TEST_SESSION_ID, + TEST_PUBLIC_KEY, + TEST_VAULT_PARAMS, + TEST_VAULT_CHALLENGE, + ImmutableList.of(new KeyChainProtectionParams( + TYPE_LOCKSCREEN, + UI_FORMAT_PASSWORD, + KeyDerivationParams.createSha256Params(TEST_SALT), + TEST_SECRET))); + byte[] keyClaimant = mRecoverySessionStorage.get(Binder.getCallingUid(), TEST_SESSION_ID) + .getKeyClaimant(); + SecretKey recoveryKey = randomRecoveryKey(); + byte[] encryptedClaimResponse = encryptClaimResponse( + keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey); + + byte[] applicationKeyBytes1 = randomBytes(32); + byte[] applicationKeyBytes2 = randomBytes(32); + + WrappedApplicationKey applicationKey1 = new WrappedApplicationKey( + TEST_ALIAS, + // Use a different recovery key here, so the decryption will fail + encryptedApplicationKey(randomRecoveryKey(), applicationKeyBytes1)); + WrappedApplicationKey applicationKey2 = new WrappedApplicationKey( + TEST_ALIAS2, + encryptedApplicationKey(recoveryKey, applicationKeyBytes2)); + + Map<String, byte[]> recoveredKeys = mRecoverableKeyStoreManager.recoverKeys( + TEST_SESSION_ID, + encryptedClaimResponse, + ImmutableList.of(applicationKey1, applicationKey2)); + + assertThat(recoveredKeys).hasSize(1); + assertThat(recoveredKeys.get(TEST_ALIAS2)).isEqualTo(applicationKeyBytes2); + } + + @Test public void setSnapshotCreatedPendingIntent() throws Exception { int uid = Binder.getCallingUid(); PendingIntent intent = PendingIntent.getBroadcast( |