Merge "Add RecoverySession importKeyChainSnapshot method" into pi-dev
This commit is contained in:
@@ -547,10 +547,7 @@ public class RecoveryController {
|
||||
if (grantAlias == null) {
|
||||
throw new InternalRecoveryServiceException("null grant alias");
|
||||
}
|
||||
return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
|
||||
mKeyStore,
|
||||
grantAlias,
|
||||
KeyStore.UID_SELF);
|
||||
return getKeyFromGrant(grantAlias);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
@@ -581,10 +578,7 @@ public class RecoveryController {
|
||||
if (grantAlias == null) {
|
||||
throw new InternalRecoveryServiceException("Null grant alias");
|
||||
}
|
||||
return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
|
||||
mKeyStore,
|
||||
grantAlias,
|
||||
KeyStore.UID_SELF);
|
||||
return getKeyFromGrant(alias);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
@@ -614,10 +608,7 @@ public class RecoveryController {
|
||||
if (grantAlias == null) {
|
||||
return null;
|
||||
}
|
||||
return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
|
||||
mKeyStore,
|
||||
grantAlias,
|
||||
KeyStore.UID_SELF);
|
||||
return getKeyFromGrant(grantAlias);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
} catch (ServiceSpecificException e) {
|
||||
@@ -625,6 +616,16 @@ public class RecoveryController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key with the given {@code grantAlias}.
|
||||
*/
|
||||
Key getKeyFromGrant(String grantAlias) throws UnrecoverableKeyException {
|
||||
return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
|
||||
mKeyStore,
|
||||
grantAlias,
|
||||
KeyStore.UID_SELF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a key called {@code alias} from the recoverable key store.
|
||||
*
|
||||
|
||||
@@ -16,17 +16,22 @@
|
||||
|
||||
package android.security.keystore.recovery;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -243,6 +248,63 @@ public class RecoverySession implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports key chain snapshot recovered from a remote vault.
|
||||
*
|
||||
* @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.
|
||||
* @throws SessionExpiredException if {@code session} has since been closed.
|
||||
* @throws DecryptionFailedException if unable to decrypt the snapshot.
|
||||
* @throws InternalRecoveryServiceException if an error occurs internal to the recovery service.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.RECOVER_KEYSTORE)
|
||||
public Map<String, Key> recoverKeyChainSnapshot(
|
||||
@NonNull byte[] recoveryKeyBlob,
|
||||
@NonNull List<WrappedApplicationKey> applicationKeys
|
||||
) throws SessionExpiredException, DecryptionFailedException, InternalRecoveryServiceException {
|
||||
try {
|
||||
Map<String, String> grantAliases = mRecoveryController
|
||||
.getBinder()
|
||||
.recoverKeyChainSnapshot(mSessionId, recoveryKeyBlob, applicationKeys);
|
||||
return getKeysFromGrants(grantAliases);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
} catch (ServiceSpecificException e) {
|
||||
if (e.errorCode == RecoveryController.ERROR_DECRYPTION_FAILED) {
|
||||
throw new DecryptionFailedException(e.getMessage());
|
||||
}
|
||||
if (e.errorCode == RecoveryController.ERROR_SESSION_EXPIRED) {
|
||||
throw new SessionExpiredException(e.getMessage());
|
||||
}
|
||||
throw mRecoveryController.wrapUnexpectedServiceSpecificException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Given a map from alias to grant alias, returns a map from alias to a {@link Key} handle. */
|
||||
private Map<String, Key> getKeysFromGrants(Map<String, String> grantAliases)
|
||||
throws InternalRecoveryServiceException {
|
||||
ArrayMap<String, Key> keysByAlias = new ArrayMap<>(grantAliases.size());
|
||||
for (String alias : grantAliases.keySet()) {
|
||||
String grantAlias = grantAliases.get(alias);
|
||||
Key key;
|
||||
try {
|
||||
key = mRecoveryController.getKeyFromGrant(grantAlias);
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
throw new InternalRecoveryServiceException(
|
||||
String.format(
|
||||
Locale.US,
|
||||
"Failed to get key '%s' from grant '%s'",
|
||||
alias,
|
||||
grantAlias), e);
|
||||
}
|
||||
keysByAlias.put(alias, key);
|
||||
}
|
||||
return keysByAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal session ID, used by the framework to match recovery claims to snapshot responses.
|
||||
*
|
||||
|
||||
@@ -83,5 +83,9 @@ interface ILockSettings {
|
||||
in List<KeyChainProtectionParams> secrets);
|
||||
Map/*<String, byte[]>*/ recoverKeys(in String sessionId, in byte[] recoveryKeyBlob,
|
||||
in List<WrappedApplicationKey> applicationKeys);
|
||||
Map/*<String, String>*/ recoverKeyChainSnapshot(
|
||||
in String sessionId,
|
||||
in byte[] recoveryKeyBlob,
|
||||
in List<WrappedApplicationKey> applicationKeys);
|
||||
void closeSession(in String sessionId);
|
||||
}
|
||||
|
||||
@@ -2064,12 +2064,20 @@ public class LockSettingsService extends ILockSettings.Stub {
|
||||
mRecoverableKeyStoreManager.closeSession(sessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> recoverKeyChainSnapshot(
|
||||
@NonNull String sessionId,
|
||||
@NonNull byte[] recoveryKeyBlob,
|
||||
@NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException {
|
||||
return mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
|
||||
sessionId, recoveryKeyBlob, applicationKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, byte[]> recoverKeys(@NonNull String sessionId,
|
||||
@NonNull byte[] recoveryKeyBlob, @NonNull List<WrappedApplicationKey> applicationKeys)
|
||||
throws RemoteException {
|
||||
return mRecoverableKeyStoreManager.recoverKeys(
|
||||
sessionId, recoveryKeyBlob, applicationKeys);
|
||||
return mRecoverableKeyStoreManager.recoverKeys(sessionId, recoveryKeyBlob, applicationKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.annotation.Nullable;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.os.UserHandle;
|
||||
@@ -41,6 +42,7 @@ import android.security.keystore.recovery.RecoveryController;
|
||||
import android.security.keystore.recovery.TrustedRootCertificates;
|
||||
import android.security.keystore.recovery.WrappedApplicationKey;
|
||||
import android.security.KeyStore;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -555,6 +557,78 @@ public class RecoverableKeyStoreManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by a recovery agent after a successful recovery claim is sent to the remote vault
|
||||
* service.
|
||||
*
|
||||
* @param sessionId The session ID used to generate the claim. See
|
||||
* {@link #startRecoverySession(String, byte[], byte[], byte[], List)}.
|
||||
* @param encryptedRecoveryKey The encrypted recovery key blob returned by the remote vault
|
||||
* service.
|
||||
* @param applicationKeys The encrypted key blobs returned by the remote vault service. These
|
||||
* were wrapped with the recovery key.
|
||||
* @throws RemoteException if an error occurred recovering the keys.
|
||||
*/
|
||||
public Map<String, String> recoverKeyChainSnapshot(
|
||||
@NonNull String sessionId,
|
||||
@NonNull byte[] encryptedRecoveryKey,
|
||||
@NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException {
|
||||
checkRecoverKeyStorePermission();
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
int uid = Binder.getCallingUid();
|
||||
RecoverySessionStorage.Entry sessionEntry = mRecoverySessionStorage.get(uid, sessionId);
|
||||
if (sessionEntry == null) {
|
||||
throw new ServiceSpecificException(ERROR_SESSION_EXPIRED,
|
||||
String.format(Locale.US,
|
||||
"Application uid=%d does not have pending session '%s'",
|
||||
uid,
|
||||
sessionId));
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] recoveryKey = decryptRecoveryKey(sessionEntry, encryptedRecoveryKey);
|
||||
Map<String, byte[]> keysByAlias = recoverApplicationKeys(recoveryKey, applicationKeys);
|
||||
return importKeyMaterials(userId, uid, keysByAlias);
|
||||
} catch (KeyStoreException e) {
|
||||
throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
|
||||
} finally {
|
||||
sessionEntry.destroy();
|
||||
mRecoverySessionStorage.remove(uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports the key materials, returning a map from alias to grant alias for the calling user.
|
||||
*
|
||||
* @param userId The calling user ID.
|
||||
* @param uid The calling uid.
|
||||
* @param keysByAlias The key materials, keyed by alias.
|
||||
* @throws KeyStoreException if an error occurs importing the key or getting the grant.
|
||||
*/
|
||||
private Map<String, String> importKeyMaterials(
|
||||
int userId, int uid, Map<String, byte[]> keysByAlias) throws KeyStoreException {
|
||||
ArrayMap<String, String> grantAliasesByAlias = new ArrayMap<>(keysByAlias.size());
|
||||
for (String alias : keysByAlias.keySet()) {
|
||||
mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, keysByAlias.get(alias));
|
||||
String grantAlias = getAlias(userId, uid, alias);
|
||||
Log.i(TAG, String.format(Locale.US, "Import %s -> %s", alias, grantAlias));
|
||||
grantAliasesByAlias.put(alias, grantAlias);
|
||||
}
|
||||
return grantAliasesByAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an alias for the key.
|
||||
*
|
||||
* @param userId The user ID of the calling process.
|
||||
* @param uid The uid of the calling process.
|
||||
* @param alias The alias of the key.
|
||||
* @return The alias in the calling process's keystore.
|
||||
*/
|
||||
private String getAlias(int userId, int uid, String alias) {
|
||||
return mApplicationKeyStorage.getGrantAlias(userId, uid, alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
* Generates a key named {@code alias} in the recoverable store for the calling uid. Then
|
||||
@@ -632,7 +706,7 @@ public class RecoverableKeyStoreManager {
|
||||
byte[] secretKey =
|
||||
mRecoverableKeyGenerator.generateAndStoreKey(encryptionKey, userId, uid, alias);
|
||||
mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, secretKey);
|
||||
return mApplicationKeyStorage.getGrantAlias(userId, uid, alias);
|
||||
return getAlias(userId, uid, alias);
|
||||
} catch (KeyStoreException | InvalidKeyException | RecoverableKeyStorageException e) {
|
||||
throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
@@ -683,7 +757,7 @@ public class RecoverableKeyStoreManager {
|
||||
|
||||
// Import the key to Android KeyStore and get grant
|
||||
mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, keyBytes);
|
||||
return mApplicationKeyStorage.getGrantAlias(userId, uid, alias);
|
||||
return getAlias(userId, uid, alias);
|
||||
} catch (KeyStoreException | InvalidKeyException | RecoverableKeyStorageException e) {
|
||||
throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage());
|
||||
}
|
||||
@@ -697,8 +771,7 @@ public class RecoverableKeyStoreManager {
|
||||
public String getKey(@NonNull String alias) throws RemoteException {
|
||||
int uid = Binder.getCallingUid();
|
||||
int userId = UserHandle.getCallingUserId();
|
||||
String grantAlias = mApplicationKeyStorage.getGrantAlias(userId, uid, alias);
|
||||
return grantAlias;
|
||||
return getAlias(userId, uid, alias);
|
||||
}
|
||||
|
||||
private byte[] decryptRecoveryKey(
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.security.Credentials;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.security.keystore.KeyProtection;
|
||||
import android.security.KeyStore;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.locksettings.recoverablekeystore.KeyStoreProxy;
|
||||
@@ -31,6 +32,8 @@ import com.android.server.locksettings.recoverablekeystore.KeyStoreProxyImpl;
|
||||
|
||||
import java.security.KeyStore.SecretKeyEntry;
|
||||
import java.security.KeyStoreException;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
@@ -40,11 +43,13 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
* revealing key material
|
||||
*/
|
||||
public class ApplicationKeyStorage {
|
||||
private static final String TAG = "RecoverableAppKeyStore";
|
||||
|
||||
private static final String APPLICATION_KEY_ALIAS_PREFIX =
|
||||
"com.android.server.locksettings.recoverablekeystore/application/";
|
||||
|
||||
KeyStoreProxy mKeyStore;
|
||||
KeyStore mKeystoreService;
|
||||
private final KeyStoreProxy mKeyStore;
|
||||
private final KeyStore mKeystoreService;
|
||||
|
||||
public static ApplicationKeyStorage getInstance(KeyStore keystoreService)
|
||||
throws KeyStoreException {
|
||||
@@ -65,12 +70,15 @@ public class ApplicationKeyStorage {
|
||||
public @Nullable String getGrantAlias(int userId, int uid, String alias) {
|
||||
// Aliases used by {@link KeyStore} are different than used by public API.
|
||||
// {@code USER_PRIVATE_KEY} prefix is used secret keys.
|
||||
Log.i(TAG, String.format(Locale.US, "Get %d/%d/%s", userId, uid, alias));
|
||||
String keystoreAlias = Credentials.USER_PRIVATE_KEY + getInternalAlias(userId, uid, alias);
|
||||
return mKeystoreService.grant(keystoreAlias, uid);
|
||||
}
|
||||
|
||||
public void setSymmetricKeyEntry(int userId, int uid, String alias, byte[] secretKey)
|
||||
throws KeyStoreException {
|
||||
Log.i(TAG, String.format(Locale.US, "Set %d/%d/%s: %d bytes of key material",
|
||||
userId, uid, alias, secretKey.length));
|
||||
try {
|
||||
mKeyStore.setEntry(
|
||||
getInternalAlias(userId, uid, alias),
|
||||
@@ -87,6 +95,7 @@ public class ApplicationKeyStorage {
|
||||
}
|
||||
|
||||
public void deleteEntry(int userId, int uid, String alias) {
|
||||
Log.i(TAG, String.format(Locale.US, "Del %d/%d/%s", userId, uid, alias));
|
||||
try {
|
||||
mKeyStore.deleteEntry(getInternalAlias(userId, uid, alias));
|
||||
} catch (KeyStoreException e) {
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.os.Binder;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.os.UserHandle;
|
||||
import android.security.KeyStore;
|
||||
import android.security.keystore.AndroidKeyStoreProvider;
|
||||
import android.security.keystore.AndroidKeyStoreSecretKey;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyProperties;
|
||||
@@ -68,6 +69,7 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
@@ -76,8 +78,10 @@ import java.util.concurrent.Executors;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
@SmallTest
|
||||
@@ -145,7 +149,6 @@ public class RecoverableKeyStoreManagerTest {
|
||||
@Mock private RecoverySnapshotListenersStorage mMockListenersStorage;
|
||||
@Mock private KeyguardManager mKeyguardManager;
|
||||
@Mock private PlatformKeyManager mPlatformKeyManager;
|
||||
@Mock private KeyStore mKeyStore;
|
||||
@Mock private ApplicationKeyStorage mApplicationKeyStorage;
|
||||
|
||||
private RecoverableKeyStoreDb mRecoverableKeyStoreDb;
|
||||
@@ -176,7 +179,7 @@ public class RecoverableKeyStoreManagerTest {
|
||||
|
||||
mRecoverableKeyStoreManager = new RecoverableKeyStoreManager(
|
||||
mMockContext,
|
||||
mKeyStore,
|
||||
KeyStore.getInstance(),
|
||||
mRecoverableKeyStoreDb,
|
||||
mRecoverySessionStorage,
|
||||
Executors.newSingleThreadExecutor(),
|
||||
@@ -220,6 +223,7 @@ public class RecoverableKeyStoreManagerTest {
|
||||
|
||||
assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNotNull();
|
||||
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
|
||||
// TODO(76083050) Test the grant mechanism for the keys.
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -680,9 +684,9 @@ public class RecoverableKeyStoreManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recoverKeys_throwsIfNoSessionIsPresent() throws Exception {
|
||||
public void recoverKeyChainSnapshot_throwsIfNoSessionIsPresent() throws Exception {
|
||||
try {
|
||||
mRecoverableKeyStoreManager.recoverKeys(
|
||||
mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
|
||||
TEST_SESSION_ID,
|
||||
/*recoveryKeyBlob=*/ randomBytes(32),
|
||||
/*applicationKeys=*/ ImmutableList.of(
|
||||
@@ -695,7 +699,7 @@ public class RecoverableKeyStoreManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recoverKeys_throwsIfRecoveryClaimCannotBeDecrypted() throws Exception {
|
||||
public void recoverKeyChainSnapshot_throwsIfRecoveryClaimCannotBeDecrypted() throws Exception {
|
||||
mRecoverableKeyStoreManager.startRecoverySession(
|
||||
TEST_SESSION_ID,
|
||||
TEST_PUBLIC_KEY,
|
||||
@@ -708,7 +712,7 @@ public class RecoverableKeyStoreManagerTest {
|
||||
TEST_SECRET)));
|
||||
|
||||
try {
|
||||
mRecoverableKeyStoreManager.recoverKeys(
|
||||
mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
|
||||
TEST_SESSION_ID,
|
||||
/*encryptedRecoveryKey=*/ randomBytes(60),
|
||||
/*applicationKeys=*/ ImmutableList.of());
|
||||
@@ -719,7 +723,7 @@ public class RecoverableKeyStoreManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recoverKeys_throwsIfFailedToDecryptAllApplicationKeys() throws Exception {
|
||||
public void recoverKeyChainSnapshot_throwsIfFailedToDecryptAllApplicationKeys() throws Exception {
|
||||
mRecoverableKeyStoreManager.startRecoverySession(
|
||||
TEST_SESSION_ID,
|
||||
TEST_PUBLIC_KEY,
|
||||
@@ -740,7 +744,7 @@ public class RecoverableKeyStoreManagerTest {
|
||||
encryptedApplicationKey(randomRecoveryKey(), randomBytes(32)));
|
||||
|
||||
try {
|
||||
mRecoverableKeyStoreManager.recoverKeys(
|
||||
mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
|
||||
TEST_SESSION_ID,
|
||||
/*encryptedRecoveryKey=*/ encryptedClaimResponse,
|
||||
/*applicationKeys=*/ ImmutableList.of(badApplicationKey));
|
||||
@@ -751,7 +755,8 @@ public class RecoverableKeyStoreManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recoverKeys_doesNotThrowIfNoApplicationKeysToBeDecrypted() throws Exception {
|
||||
public void recoverKeyChainSnapshot_doesNotThrowIfNoApplicationKeysToBeDecrypted()
|
||||
throws Exception {
|
||||
mRecoverableKeyStoreManager.startRecoverySession(
|
||||
TEST_SESSION_ID,
|
||||
TEST_PUBLIC_KEY,
|
||||
@@ -768,14 +773,14 @@ public class RecoverableKeyStoreManagerTest {
|
||||
byte[] encryptedClaimResponse = encryptClaimResponse(
|
||||
keyClaimant, TEST_SECRET, TEST_VAULT_PARAMS, recoveryKey);
|
||||
|
||||
mRecoverableKeyStoreManager.recoverKeys(
|
||||
mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
|
||||
TEST_SESSION_ID,
|
||||
/*encryptedRecoveryKey=*/ encryptedClaimResponse,
|
||||
/*applicationKeys=*/ ImmutableList.of());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recoverKeys_returnsDecryptedKeys() throws Exception {
|
||||
public void recoverKeyChainSnapshot_returnsDecryptedKeys() throws Exception {
|
||||
mRecoverableKeyStoreManager.startRecoverySession(
|
||||
TEST_SESSION_ID,
|
||||
TEST_PUBLIC_KEY,
|
||||
@@ -796,17 +801,18 @@ public class RecoverableKeyStoreManagerTest {
|
||||
TEST_ALIAS,
|
||||
encryptedApplicationKey(recoveryKey, applicationKeyBytes));
|
||||
|
||||
Map<String, byte[]> recoveredKeys = mRecoverableKeyStoreManager.recoverKeys(
|
||||
Map<String, String> recoveredKeys = mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
|
||||
TEST_SESSION_ID,
|
||||
encryptedClaimResponse,
|
||||
ImmutableList.of(applicationKey));
|
||||
|
||||
assertThat(recoveredKeys).hasSize(1);
|
||||
assertThat(recoveredKeys.get(TEST_ALIAS)).isEqualTo(applicationKeyBytes);
|
||||
assertThat(recoveredKeys).containsKey(TEST_ALIAS);
|
||||
// TODO(76083050) Test the grant mechanism for the keys.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void recoverKeys_worksOnOtherApplicationKeysIfOneDecryptionFails() throws Exception {
|
||||
public void recoverKeyChainSnapshot_worksOnOtherApplicationKeysIfOneDecryptionFails() throws Exception {
|
||||
mRecoverableKeyStoreManager.startRecoverySession(
|
||||
TEST_SESSION_ID,
|
||||
TEST_PUBLIC_KEY,
|
||||
@@ -834,13 +840,14 @@ public class RecoverableKeyStoreManagerTest {
|
||||
TEST_ALIAS2,
|
||||
encryptedApplicationKey(recoveryKey, applicationKeyBytes2));
|
||||
|
||||
Map<String, byte[]> recoveredKeys = mRecoverableKeyStoreManager.recoverKeys(
|
||||
Map<String, String> recoveredKeys = mRecoverableKeyStoreManager.recoverKeyChainSnapshot(
|
||||
TEST_SESSION_ID,
|
||||
encryptedClaimResponse,
|
||||
ImmutableList.of(applicationKey1, applicationKey2));
|
||||
|
||||
assertThat(recoveredKeys).hasSize(1);
|
||||
assertThat(recoveredKeys.get(TEST_ALIAS2)).isEqualTo(applicationKeyBytes2);
|
||||
assertThat(recoveredKeys).containsKey(TEST_ALIAS2);
|
||||
// TODO(76083050) Test the grant mechanism for the keys.
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user