diff options
author | Eran Messeri <eranm@google.com> | 2019-09-04 15:21:34 +0100 |
---|---|---|
committer | Eran Messeri <eranm@google.com> | 2019-09-05 16:54:46 +0100 |
commit | 1d92aa06a840b4740f82c5d06702c849132d137a (patch) | |
tree | 9ba84647b5e8f71dbfef81e254f0fc48eadacd72 /tests | |
parent | 59d606855f98b283e381e8348e48cadebbdeab59 (diff) | |
download | KeyChain-1d92aa06a840b4740f82c5d06702c849132d137a.tar.gz |
Add tests for key generation & attestation
Test that generateKeyPair, attestKey and setKeyPairCertificate operate correctly:
* Test successful key generation and attestation.
* Test various error conditions (missing attestation challenge, etc).
Bug: 138375478
Test: atest KeyChainTests
Change-Id: I62673c35a6729dcc4a3f2fa7761c82cd0a2dc6e4
Diffstat (limited to 'tests')
-rw-r--r-- | tests/src/com/android/keychain/tests/BasicKeyChainServiceTest.java | 134 |
1 files changed, 133 insertions, 1 deletions
diff --git a/tests/src/com/android/keychain/tests/BasicKeyChainServiceTest.java b/tests/src/com/android/keychain/tests/BasicKeyChainServiceTest.java index 63a3a80..4144b2d 100644 --- a/tests/src/com/android/keychain/tests/BasicKeyChainServiceTest.java +++ b/tests/src/com/android/keychain/tests/BasicKeyChainServiceTest.java @@ -15,8 +15,9 @@ */ package com.android.keychain.tests; +import static android.os.Process.WIFI_UID; + import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; import android.content.ComponentName; import android.content.Context; @@ -29,6 +30,10 @@ import android.os.RemoteException; import android.platform.test.annotations.LargeTest; import android.security.Credentials; import android.security.IKeyChainService; +import android.security.KeyChain; +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; +import android.security.keystore.ParcelableKeyGenParameterSpec; import android.util.Log; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -49,6 +54,9 @@ public class BasicKeyChainServiceTest { private static final String TAG = "BasicKeyChainServiceTest"; private static final String ALIAS_1 = "client"; private static final String ALIAS_IMPORTED = "imported"; + private static final String ALIAS_GENERATED = "generated"; + public static final byte[] DUMMY_CHALLENGE = {'a', 'b', 'c'}; + private static final String ALIAS_NON_EXISTING = "nonexisting"; private Context mContext; @@ -106,6 +114,14 @@ public class BasicKeyChainServiceTest { @After public void tearDown() { + // Clean up keys that might have been left over + try { + removeKeyPair(ALIAS_IMPORTED); + removeKeyPair(ALIAS_GENERATED); + } catch (RemoteException e) { + // Nothing to do here but warn that clean-up was not successful. + Log.w(TAG, "Failed cleaning up installed keys", e); + } unbindTestSupportService(); assertThat(mIsSupportServiceBound).isFalse(); unbindKeyChainService(); @@ -175,6 +191,110 @@ public class BasicKeyChainServiceTest { assertThat(mTestSupportService.removeKeyPair(ALIAS_IMPORTED)).isTrue(); } + @Test + public void testGenerateKeyPairErrorsOnBadUid() throws RemoteException { + KeyGenParameterSpec specBadUid = + new KeyGenParameterSpec.Builder(buildRsaKeySpec(ALIAS_GENERATED)) + .setUid(WIFI_UID) + .build(); + ParcelableKeyGenParameterSpec parcelableSpec = + new ParcelableKeyGenParameterSpec(specBadUid); + assertThat(mTestSupportService.generateKeyPair("RSA", parcelableSpec)).isEqualTo( + KeyChain.KEY_GEN_MISSING_ALIAS); + } + + @Test + public void testGenerateKeyPairErrorsOnSuperflousAttestationChallenge() throws RemoteException { + KeyGenParameterSpec specWithChallenge = + new KeyGenParameterSpec.Builder(buildRsaKeySpec(ALIAS_GENERATED)) + .setAttestationChallenge(DUMMY_CHALLENGE) + .build(); + ParcelableKeyGenParameterSpec parcelableSpec = + new ParcelableKeyGenParameterSpec(specWithChallenge); + assertThat(mTestSupportService.generateKeyPair("RSA", parcelableSpec)).isEqualTo( + KeyChain.KEY_GEN_SUPERFLUOUS_ATTESTATION_CHALLENGE); + } + + @Test + public void testGenerateKeyPairErrorsOnInvalidAlgorithm() throws RemoteException { + ParcelableKeyGenParameterSpec parcelableSpec = new ParcelableKeyGenParameterSpec( + buildRsaKeySpec(ALIAS_GENERATED)); + assertThat(mTestSupportService.generateKeyPair("BADBAD", parcelableSpec)).isEqualTo( + KeyChain.KEY_GEN_NO_SUCH_ALGORITHM); + } + + @Test + public void testGenerateKeyPairErrorsOnInvalidAlgorithmParameters() throws RemoteException { + ParcelableKeyGenParameterSpec parcelableSpec = new ParcelableKeyGenParameterSpec( + buildRsaKeySpec(ALIAS_GENERATED)); + // RSA key parameters do not make sense for Elliptic Curve + assertThat(mTestSupportService.generateKeyPair("EC", parcelableSpec)).isEqualTo( + KeyChain.KEY_GEN_INVALID_ALGORITHM_PARAMETERS); + } + + @Test + public void testGenerateKeyPairSucceeds() throws RemoteException { + generateRsaKey(ALIAS_GENERATED); + // Test that there are no grants by default + assertThat(mKeyChainService.requestPrivateKey(ALIAS_GENERATED)).isNull(); + // And is not user-selectable by default + assertThat(mKeyChainService.isUserSelectable(ALIAS_GENERATED)).isFalse(); + // But after granting access, it can be used. + mTestSupportService.grantAppPermission(Process.myUid(), ALIAS_GENERATED); + assertThat(mKeyChainService.requestPrivateKey(ALIAS_GENERATED)).isNotNull(); + } + + @Test + public void testAttestKeyFailsOnMissingChallenge() throws RemoteException { + generateRsaKey(ALIAS_GENERATED); + assertThat(mTestSupportService.attestKey(ALIAS_GENERATED, null, new int[]{} + )).isEqualTo(KeyChain.KEY_ATTESTATION_MISSING_CHALLENGE); + } + + @Test + public void testAttestKeyFailsOnNonExistentKey() throws RemoteException { + assertThat(mTestSupportService.attestKey(ALIAS_NON_EXISTING, DUMMY_CHALLENGE, new int[]{} + )).isEqualTo(KeyChain.KEY_ATTESTATION_FAILURE); + } + + @Test + public void testAttestKeySucceedsOnGeneratedKey() throws RemoteException { + generateRsaKey(ALIAS_GENERATED); + assertThat(mTestSupportService.attestKey(ALIAS_GENERATED, DUMMY_CHALLENGE, + new int[]{})).isEqualTo(KeyChain.KEY_ATTESTATION_SUCCESS); + } + + @Test + public void testSetKeyPairCertificate() throws RemoteException { + generateRsaKey(ALIAS_GENERATED); + final byte[] userCert = new byte[] {'a', 'b', 'c'}; + final byte[] certChain = new byte[] {'d', 'e', 'f'}; + + assertThat(mTestSupportService.setKeyPairCertificate(ALIAS_GENERATED, userCert, + certChain)).isTrue(); + mTestSupportService.grantAppPermission(Process.myUid(), ALIAS_GENERATED); + + assertThat(mKeyChainService.getCertificate(ALIAS_GENERATED)).isEqualTo(userCert); + assertThat(mKeyChainService.getCaCertificates(ALIAS_GENERATED)).isEqualTo(certChain); + + final byte[] newUserCert = new byte[] {'x', 'y', 'z'}; + assertThat(mTestSupportService.setKeyPairCertificate(ALIAS_GENERATED, newUserCert, + null)).isTrue(); + assertThat(mKeyChainService.getCertificate(ALIAS_GENERATED)).isEqualTo(newUserCert); + assertThat(mKeyChainService.getCaCertificates(ALIAS_GENERATED)).isNull(); + } + + void generateRsaKey(String alias) throws RemoteException { + ParcelableKeyGenParameterSpec parcelableSpec = new ParcelableKeyGenParameterSpec( + buildRsaKeySpec(alias)); + assertThat(mTestSupportService.generateKeyPair("RSA", parcelableSpec)).isEqualTo( + KeyChain.KEY_GEN_SUCCESS); + } + + void removeKeyPair(String alias) throws RemoteException { + assertThat(mTestSupportService.removeKeyPair(alias)).isTrue(); + } + void bindTestSupportService() { Intent serviceIntent = new Intent(mContext, IKeyChainServiceTestSupport.class); serviceIntent.setComponent( @@ -259,4 +379,16 @@ public class BasicKeyChainServiceTest { assertThat(mKeyChainAvailable.block(10000)).isTrue();; assertThat(mKeyChainService).isNotNull(); } + + private KeyGenParameterSpec buildRsaKeySpec(String alias) { + return new KeyGenParameterSpec.Builder( + alias, + KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) + .setKeySize(2048) + .setDigests(KeyProperties.DIGEST_SHA256) + .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS, + KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) + .setIsStrongBoxBacked(false) + .build(); + } } |