summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Robert Berry <robertberry@google.com> 2017-12-22 11:35:14 +0000
committer Robert Berry <robertberry@google.com> 2017-12-22 11:35:14 +0000
commitbd4c43c686d2d2bb36e25f07b19aa5adfac21301 (patch)
treeca945a2acb97c4dfa6e999ce76f26e69ba43300f
parent8b2af876d341de796e6995fa72588b8d88b729ba (diff)
Update recoverKeys to return raw material
This is a temporary solution, while the KeyStore team works on adding a move API to KeyStore. (At which point this will be updated to instead return 'move tokens', allowing the user to move the key from the system's keystore to their own, without ever seeing the raw material.) Test: adb shell am instrument -w -e package com.android.server.locksettings.recoverablekeystore com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner Change-Id: I2241a6da15d50c26a7b384d4e5b6f78366fb9300
-rw-r--r--core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java8
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl2
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java6
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java16
5 files changed, 30 insertions, 22 deletions
diff --git a/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java b/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java
index f88768b184fd..8b95e4e82cfa 100644
--- a/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java
+++ b/core/java/android/security/recoverablekeystore/RecoverableKeyStoreLoader.java
@@ -423,19 +423,21 @@ public class RecoverableKeyStoreLoader {
/**
* Imports keys.
*
- * @param sessionId Id for recovery session, same as in = {@link startRecoverySession}.
+ * @param sessionId Id for recovery session, same as in
+ * {@link #startRecoverySession(String, byte[], byte[], byte[], List)} on}.
* @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
* @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
* and session. KeyStore only uses package names from the application info in {@link
* KeyEntryRecoveryData}. Caller is responsibility to perform certificates check.
+ * @return Map from alias to raw key material.
*/
- public void recoverKeys(
+ public Map<String, byte[]> recoverKeys(
@NonNull String sessionId,
@NonNull byte[] recoveryKeyBlob,
@NonNull List<KeyEntryRecoveryData> applicationKeys)
throws RecoverableKeyStoreLoaderException {
try {
- mBinder.recoverKeys(
+ return (Map<String, byte[]>) mBinder.recoverKeys(
sessionId, recoveryKeyBlob, applicationKeys, UserHandle.getCallingUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 43536a522a47..747ad141909e 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -78,6 +78,6 @@ interface ILockSettings {
byte[] startRecoverySession(in String sessionId,
in byte[] verifierPublicKey, in byte[] vaultParams, in byte[] vaultChallenge,
in List<KeyStoreRecoveryMetadata> secrets, int userId);
- void recoverKeys(in String sessionId, in byte[] recoveryKeyBlob,
+ Map/*<String, byte[]>*/ recoverKeys(in String sessionId, in byte[] recoveryKeyBlob,
in List<KeyEntryRecoveryData> applicationKeys, int userId);
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index eef4d9be4b56..d78ab1679b60 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -2021,11 +2021,11 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
- public void recoverKeys(@NonNull String sessionId, @NonNull byte[] recoveryKeyBlob,
+ public Map<String, byte[]> recoverKeys(@NonNull String sessionId, @NonNull byte[] recoveryKeyBlob,
@NonNull List<KeyEntryRecoveryData> applicationKeys, @UserIdInt int userId)
throws RemoteException {
- mRecoverableKeyStoreManager.recoverKeys(sessionId, recoveryKeyBlob, applicationKeys,
- userId);
+ return mRecoverableKeyStoreManager.recoverKeys(
+ sessionId, recoveryKeyBlob, applicationKeys, userId);
}
private static final String[] VALID_SETTINGS = new String[] {
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 bb9099a32454..2fc034e2f396 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -42,6 +42,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -308,8 +309,6 @@ public class RecoverableKeyStoreManager {
* Invoked by a recovery agent after a successful recovery claim is sent to the remote vault
* service.
*
- * <p>TODO: should also load into AndroidKeyStore.
- *
* @param sessionId The session ID used to generate the claim. See
* {@link #startRecoverySession(String, byte[], byte[], byte[], List, int)}.
* @param encryptedRecoveryKey The encrypted recovery key blob returned by the remote vault
@@ -317,9 +316,10 @@ public class RecoverableKeyStoreManager {
* @param applicationKeys The encrypted key blobs returned by the remote vault service. These
* were wrapped with the recovery key.
* @param uid The uid of the recovery agent.
+ * @return Map from alias to raw key material.
* @throws RemoteException if an error occurred recovering the keys.
*/
- public void recoverKeys(
+ public Map<String, byte[]> recoverKeys(
@NonNull String sessionId,
@NonNull byte[] encryptedRecoveryKey,
@NonNull List<KeyEntryRecoveryData> applicationKeys,
@@ -335,7 +335,7 @@ public class RecoverableKeyStoreManager {
try {
byte[] recoveryKey = decryptRecoveryKey(sessionEntry, encryptedRecoveryKey);
- recoverApplicationKeys(recoveryKey, applicationKeys);
+ return recoverApplicationKeys(recoveryKey, applicationKeys);
} finally {
sessionEntry.destroy();
mRecoverySessionStorage.remove(uid);
@@ -370,20 +370,21 @@ public class RecoverableKeyStoreManager {
/**
* Uses {@code recoveryKey} to decrypt {@code applicationKeys}.
*
- * <p>TODO: and load them into store?
- *
+ * @return Map from alias to raw key material.
* @throws RemoteException if an error occurred decrypting the keys.
*/
- private void recoverApplicationKeys(
+ private Map<String, byte[]> recoverApplicationKeys(
@NonNull byte[] recoveryKey,
@NonNull List<KeyEntryRecoveryData> applicationKeys) throws RemoteException {
+ HashMap<String, byte[]> keyMaterialByAlias = new HashMap<>();
for (KeyEntryRecoveryData applicationKey : applicationKeys) {
String alias = new String(applicationKey.getAlias(), StandardCharsets.UTF_8);
byte[] encryptedKeyMaterial = applicationKey.getEncryptedKeyMaterial();
try {
- // TODO: put decrypted key material in appropriate AndroidKeyStore
- KeySyncUtils.decryptApplicationKey(recoveryKey, encryptedKeyMaterial);
+ byte[] keyMaterial =
+ KeySyncUtils.decryptApplicationKey(recoveryKey, encryptedKeyMaterial);
+ keyMaterialByAlias.put(alias, keyMaterial);
} catch (NoSuchAlgorithmException e) {
// Should never happen: all the algorithms used are required by AOSP implementations
throw new RemoteException(
@@ -399,6 +400,7 @@ public class RecoverableKeyStoreManager {
/*writeableStackTrace=*/ true);
}
}
+ 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 953ea62d3770..4eeea4699912 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
@@ -285,7 +285,7 @@ public class RecoverableKeyStoreManagerTest {
}
@Test
- public void recoverKeys_doesNotThrowIfAllIsOk() throws Exception {
+ public void recoverKeys_returnsDecryptedKeys() throws Exception {
mRecoverableKeyStoreManager.startRecoverySession(
TEST_SESSION_ID,
TEST_PUBLIC_KEY,
@@ -302,16 +302,19 @@ public class RecoverableKeyStoreManagerTest {
SecretKey recoveryKey = randomRecoveryKey();
byte[] encryptedClaimResponse = encryptClaimResponse(
keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
+ byte[] applicationKeyBytes = randomBytes(32);
KeyEntryRecoveryData applicationKey = new KeyEntryRecoveryData(
TEST_ALIAS.getBytes(StandardCharsets.UTF_8),
- randomEncryptedApplicationKey(recoveryKey)
- );
+ encryptedApplicationKey(recoveryKey, applicationKeyBytes));
- mRecoverableKeyStoreManager.recoverKeys(
+ Map<String, byte[]> recoveredKeys = mRecoverableKeyStoreManager.recoverKeys(
TEST_SESSION_ID,
encryptedClaimResponse,
ImmutableList.of(applicationKey),
TEST_USER_ID);
+
+ assertThat(recoveredKeys).hasSize(1);
+ assertThat(recoveredKeys.get(TEST_ALIAS)).isEqualTo(applicationKeyBytes);
}
@Test
@@ -387,9 +390,10 @@ public class RecoverableKeyStoreManagerTest {
assertThat(statuses).containsEntry(alias2, status); // updated
}
- private static byte[] randomEncryptedApplicationKey(SecretKey recoveryKey) throws Exception {
+ private static byte[] encryptedApplicationKey(
+ SecretKey recoveryKey, byte[] applicationKey) throws Exception {
return KeySyncUtils.encryptKeysWithRecoveryKey(recoveryKey, ImmutableMap.of(
- "alias", new SecretKeySpec(randomBytes(32), "AES")
+ "alias", new SecretKeySpec(applicationKey, "AES")
)).get("alias");
}