Import RestoreKeyFetcher
Bug: 111386661 Test: atest BackupEncryptionRoboTests Change-Id: I4163ebda82f588c624255f2a090e4ddab55e998f
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.backup.encryption.keys;
|
||||
|
||||
import android.security.keystore.recovery.InternalRecoveryServiceException;
|
||||
|
||||
import com.android.server.backup.encryption.keys.RecoverableKeyStoreSecondaryKeyManager.RecoverableKeyStoreSecondaryKeyManagerProvider;
|
||||
import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.KeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
/** Fetches the secondary key and uses it to unwrap the tertiary key during restore. */
|
||||
public class RestoreKeyFetcher {
|
||||
|
||||
/**
|
||||
* Retrieves the secondary key with the given alias and uses it to unwrap the given wrapped
|
||||
* tertiary key.
|
||||
*
|
||||
* @param secondaryKeyManagerProvider Provider which creates {@link
|
||||
* RecoverableKeyStoreSecondaryKeyManager}
|
||||
* @param secondaryKeyAlias Alias of the secondary key used to wrap the tertiary key
|
||||
* @param wrappedTertiaryKey Tertiary key wrapped with the secondary key above
|
||||
* @return The unwrapped tertiary key
|
||||
*/
|
||||
public static SecretKey unwrapTertiaryKey(
|
||||
RecoverableKeyStoreSecondaryKeyManagerProvider secondaryKeyManagerProvider,
|
||||
String secondaryKeyAlias,
|
||||
WrappedKeyProto.WrappedKey wrappedTertiaryKey)
|
||||
throws KeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
|
||||
NoSuchPaddingException {
|
||||
Optional<RecoverableKeyStoreSecondaryKey> secondaryKey =
|
||||
getSecondaryKey(secondaryKeyManagerProvider, secondaryKeyAlias);
|
||||
if (!secondaryKey.isPresent()) {
|
||||
throw new KeyException("No key:" + secondaryKeyAlias);
|
||||
}
|
||||
|
||||
return KeyWrapUtils.unwrap(secondaryKey.get().getSecretKey(), wrappedTertiaryKey);
|
||||
}
|
||||
|
||||
private static Optional<RecoverableKeyStoreSecondaryKey> getSecondaryKey(
|
||||
RecoverableKeyStoreSecondaryKeyManagerProvider secondaryKeyManagerProvider,
|
||||
String secondaryKeyAlias)
|
||||
throws KeyException {
|
||||
try {
|
||||
return secondaryKeyManagerProvider.get().get(secondaryKeyAlias);
|
||||
} catch (InternalRecoveryServiceException | UnrecoverableKeyException e) {
|
||||
throw new KeyException("Could not retrieve key:" + secondaryKeyAlias, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ android_robolectric_test {
|
||||
"backup-encryption-protos",
|
||||
"platform-test-annotations",
|
||||
"testng",
|
||||
"truth-prebuilt",
|
||||
],
|
||||
instrumentation_for: "BackupEncryption",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.backup.encryption.keys;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import com.android.server.backup.encryption.protos.nano.WrappedKeyProto;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/** Test the restore key fetcher */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Presubmit
|
||||
public class RestoreKeyFetcherTest {
|
||||
|
||||
private static final String KEY_GENERATOR_ALGORITHM = "AES";
|
||||
|
||||
private static final String TEST_SECONDARY_KEY_ALIAS = "test_2ndary_key";
|
||||
private static final byte[] TEST_SECONDARY_KEY_BYTES = new byte[256 / Byte.SIZE];
|
||||
|
||||
@Mock private RecoverableKeyStoreSecondaryKeyManager mSecondaryKeyManager;
|
||||
|
||||
/** Initialise the mocks **/
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
/** Ensure the unwrap method works as expected */
|
||||
@Test
|
||||
public void unwrapTertiaryKey_returnsUnwrappedKey() throws Exception {
|
||||
RecoverableKeyStoreSecondaryKey secondaryKey = createSecondaryKey();
|
||||
SecretKey tertiaryKey = createTertiaryKey();
|
||||
WrappedKeyProto.WrappedKey wrappedTertiaryKey =
|
||||
KeyWrapUtils.wrap(secondaryKey.getSecretKey(), tertiaryKey);
|
||||
when(mSecondaryKeyManager.get(TEST_SECONDARY_KEY_ALIAS))
|
||||
.thenReturn(Optional.of(secondaryKey));
|
||||
|
||||
SecretKey actualTertiaryKey =
|
||||
RestoreKeyFetcher.unwrapTertiaryKey(
|
||||
() -> mSecondaryKeyManager,
|
||||
TEST_SECONDARY_KEY_ALIAS,
|
||||
wrappedTertiaryKey);
|
||||
|
||||
assertThat(actualTertiaryKey).isEqualTo(tertiaryKey);
|
||||
}
|
||||
|
||||
/** Ensure that missing secondary keys are detected and an appropriate exception is thrown */
|
||||
@Test
|
||||
public void unwrapTertiaryKey_missingSecondaryKey_throwsSpecificException() throws Exception {
|
||||
WrappedKeyProto.WrappedKey wrappedTertiaryKey =
|
||||
KeyWrapUtils.wrap(createSecondaryKey().getSecretKey(), createTertiaryKey());
|
||||
when(mSecondaryKeyManager.get(TEST_SECONDARY_KEY_ALIAS)).thenReturn(Optional.empty());
|
||||
|
||||
assertThrows(
|
||||
KeyException.class,
|
||||
() ->
|
||||
RestoreKeyFetcher.unwrapTertiaryKey(
|
||||
() -> mSecondaryKeyManager,
|
||||
TEST_SECONDARY_KEY_ALIAS,
|
||||
wrappedTertiaryKey));
|
||||
}
|
||||
|
||||
/** Ensure that invalid secondary keys are detected and an appropriate exception is thrown */
|
||||
@Test
|
||||
public void unwrapTertiaryKey_badSecondaryKey_throws() throws Exception {
|
||||
RecoverableKeyStoreSecondaryKey badSecondaryKey =
|
||||
new RecoverableKeyStoreSecondaryKey(
|
||||
TEST_SECONDARY_KEY_ALIAS,
|
||||
new SecretKeySpec(new byte[] {0, 1}, KEY_GENERATOR_ALGORITHM));
|
||||
|
||||
WrappedKeyProto.WrappedKey wrappedTertiaryKey =
|
||||
KeyWrapUtils.wrap(createSecondaryKey().getSecretKey(), createTertiaryKey());
|
||||
when(mSecondaryKeyManager.get(TEST_SECONDARY_KEY_ALIAS))
|
||||
.thenReturn(Optional.of(badSecondaryKey));
|
||||
|
||||
assertThrows(
|
||||
InvalidKeyException.class,
|
||||
() ->
|
||||
RestoreKeyFetcher.unwrapTertiaryKey(
|
||||
() -> mSecondaryKeyManager,
|
||||
TEST_SECONDARY_KEY_ALIAS,
|
||||
wrappedTertiaryKey));
|
||||
}
|
||||
|
||||
private static RecoverableKeyStoreSecondaryKey createSecondaryKey() {
|
||||
return new RecoverableKeyStoreSecondaryKey(
|
||||
TEST_SECONDARY_KEY_ALIAS,
|
||||
new SecretKeySpec(TEST_SECONDARY_KEY_BYTES, KEY_GENERATOR_ALGORITHM));
|
||||
}
|
||||
|
||||
private static SecretKey createTertiaryKey() {
|
||||
return new TertiaryKeyGenerator(new SecureRandom(new byte[] {0})).generate();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user