diff options
| author | 2021-10-08 15:31:03 +0000 | |
|---|---|---|
| committer | 2021-10-08 15:31:03 +0000 | |
| commit | 70e7dd44b422ec4727dce5f6984692bf76a8ca85 (patch) | |
| tree | 154f29d765a7a56fd12dfa012f87ed10e32f8d27 | |
| parent | 2eef723cedbdcfdd96966a08f206c7ff901155db (diff) | |
| parent | 5fe5f2def000915e514ca8286fe39e06c52bf5eb (diff) | |
Merge changes Ic6e60752,I2b8b7e74
* changes:
Test for contract between AndroidKeyStoreKey hash and equals.
Keystore 2.0 SPI: Fix contract between equals and hashCode 2
3 files changed, 125 insertions, 5 deletions
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java index b24a22dbc0ec..16f732f63bf7 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKey.java @@ -22,6 +22,8 @@ import android.system.keystore2.Authorization; import android.system.keystore2.Domain; import android.system.keystore2.KeyDescriptor; +import com.android.internal.annotations.VisibleForTesting; + import java.security.Key; /** @@ -46,7 +48,11 @@ public class AndroidKeyStoreKey implements Key { // We do not include this member in comparisons. private final KeyStoreSecurityLevel mSecurityLevel; - AndroidKeyStoreKey(@NonNull KeyDescriptor descriptor, + /** + * @hide + */ + @VisibleForTesting + public AndroidKeyStoreKey(@NonNull KeyDescriptor descriptor, long keyId, @NonNull Authorization[] authorizations, @NonNull String algorithm, diff --git a/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java index 4842984e8c6a..0b3be327b521 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStorePublicKey.java @@ -23,7 +23,7 @@ import android.system.keystore2.KeyDescriptor; import android.system.keystore2.KeyMetadata; import java.security.PublicKey; -import java.util.Objects; +import java.util.Arrays; /** * {@link PublicKey} backed by Android Keystore. @@ -62,8 +62,8 @@ public abstract class AndroidKeyStorePublicKey extends AndroidKeyStoreKey implem int result = 1; result = prime * result + super.hashCode(); - result = prime * result + ((mCertificate == null) ? 0 : mCertificate.hashCode()); - result = prime * result + ((mCertificateChain == null) ? 0 : mCertificateChain.hashCode()); + result = prime * result + Arrays.hashCode(mCertificate); + result = prime * result + Arrays.hashCode(mCertificateChain); return result; } @@ -83,7 +83,7 @@ public abstract class AndroidKeyStorePublicKey extends AndroidKeyStoreKey implem */ final AndroidKeyStorePublicKey other = (AndroidKeyStorePublicKey) obj; - return Objects.equals(mCertificate, other.mCertificate) && Objects.equals(mCertificateChain, + return Arrays.equals(mCertificate, other.mCertificate) && Arrays.equals(mCertificateChain, other.mCertificateChain); } } diff --git a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java index 1bd3069f483a..f96c39c879fd 100644 --- a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java +++ b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java @@ -24,7 +24,13 @@ import static org.mockito.Mockito.when; import android.security.KeyStore2; import android.security.KeyStoreException; +import android.security.KeyStoreSecurityLevel; +import android.system.keystore2.Authorization; +import android.system.keystore2.Domain; +import android.system.keystore2.KeyDescriptor; +import android.system.keystore2.KeyMetadata; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -52,4 +58,112 @@ public class AndroidKeyStoreSpiTest { verify(mKeystore2).list(anyInt(), anyLong()); } + @Mock + private KeyStoreSecurityLevel mKeystoreSecurityLevel; + + private static KeyDescriptor descriptor() { + final KeyDescriptor keyDescriptor = new KeyDescriptor(); + keyDescriptor.alias = "key"; + keyDescriptor.blob = null; + keyDescriptor.domain = Domain.APP; + keyDescriptor.nspace = -1; + return keyDescriptor; + } + + private static KeyMetadata metadata(byte[] cert, byte[] certChain) { + KeyMetadata metadata = new KeyMetadata(); + metadata.authorizations = new Authorization[0]; + metadata.certificate = cert; + metadata.certificateChain = certChain; + metadata.key = descriptor(); + metadata.modificationTimeMs = 0; + metadata.keySecurityLevel = 1; + return metadata; + } + + private static byte[] bytes(String string) { + return string.getBytes(); + } + + class MyPublicKey extends AndroidKeyStorePublicKey { + MyPublicKey(String cert, String chain, KeyStoreSecurityLevel securityLevel) { + super(descriptor(), metadata(cert.getBytes(), chain.getBytes()), "N/A".getBytes(), + "RSA", securityLevel); + } + + @Override + AndroidKeyStorePrivateKey getPrivateKey() { + return null; + } + } + + private AndroidKeyStorePublicKey makePrivateKeyObject(String cert, String chain) { + return new MyPublicKey(cert, chain, mKeystoreSecurityLevel); + } + + @Test + public void testKeystoreKeysAdhereToContractBetweenEqualsAndHashCode() throws Exception { + AndroidKeyStoreKey key1 = new AndroidKeyStoreKey(descriptor(), 1, new Authorization[0], + "RSA", mKeystoreSecurityLevel); + AndroidKeyStoreKey key2 = new AndroidKeyStoreKey(descriptor(), 2, new Authorization[0], + "RSA", mKeystoreSecurityLevel); + AndroidKeyStoreKey key1_clone = new AndroidKeyStoreKey(descriptor(), 1, + new Authorization[0], "RSA", mKeystoreSecurityLevel); + + assertThat("Identity should yield true", key1.equals(key1)); + Assert.assertEquals("Identity should yield same hash codes", + key1.hashCode(), key1.hashCode()); + assertThat("Identity should yield true", key2.equals(key2)); + Assert.assertEquals("Identity should yield same hash codes", + key2.hashCode(), key2.hashCode()); + assertThat("Different keys should differ", !key1.equals(key2)); + Assert.assertNotEquals("Different keys should have different hash codes", + key1.hashCode(), key2.hashCode()); + + assertThat("Same keys should yield true", key1.equals(key1_clone)); + assertThat("Same keys should yield true", key1_clone.equals(key1)); + Assert.assertEquals("Same keys should yield same hash codes", + key1.hashCode(), key1_clone.hashCode()); + + assertThat("anything.equal(null) should yield false", !key1.equals(null)); + assertThat("anything.equal(null) should yield false", !key2.equals(null)); + assertThat("anything.equal(null) should yield false", !key1_clone.equals(null)); + } + + @Test + public void testKeystorePublicKeysAdhereToContractBetweenEqualsAndHashCode() throws Exception { + AndroidKeyStorePublicKey key1 = makePrivateKeyObject("myCert1", "myChain1"); + AndroidKeyStorePublicKey key2 = makePrivateKeyObject("myCert2", "myChain1"); + AndroidKeyStorePublicKey key3 = makePrivateKeyObject("myCert1", "myChain3"); + AndroidKeyStorePublicKey key1_clone = makePrivateKeyObject("myCert1", "myChain1"); + + assertThat("Identity should yield true", key1.equals(key1)); + Assert.assertEquals("Identity should yield same hash codes", + key1.hashCode(), key1.hashCode()); + assertThat("Identity should yield true", key2.equals(key2)); + Assert.assertEquals("Identity should yield same hash codes", + key2.hashCode(), key2.hashCode()); + assertThat("Identity should yield true", key3.equals(key3)); + Assert.assertEquals("Identity should yield same hash codes", + key3.hashCode(), key3.hashCode()); + assertThat("Different keys should differ", !key1.equals(key2)); + Assert.assertNotEquals("Different keys should have different hash codes", + key1.hashCode(), key2.hashCode()); + assertThat("Different keys should differ", !key1.equals(key3)); + Assert.assertNotEquals("Different keys should have different hash codes", + key1.hashCode(), key3.hashCode()); + assertThat("Different keys should differ", !key2.equals(key3)); + Assert.assertNotEquals("Different keys should have different hash codes", + key2.hashCode(), key3.hashCode()); + + assertThat("Same keys should yield true", key1.equals(key1_clone)); + assertThat("Same keys should yield true", key1_clone.equals(key1)); + Assert.assertEquals("Same keys should yield same hash codes", + key1.hashCode(), key1_clone.hashCode()); + + assertThat("anything.equal(null) should yield false", !key1.equals(null)); + assertThat("anything.equal(null) should yield false", !key2.equals(null)); + assertThat("anything.equal(null) should yield false", !key3.equals(null)); + assertThat("anything.equal(null) should yield false", !key1_clone.equals(null)); + } } |