Merge changes Ic6e60752,I2b8b7e74

* changes:
  Test for contract between AndroidKeyStoreKey hash and equals.
  Keystore 2.0 SPI: Fix contract between equals and hashCode 2
This commit is contained in:
Treehugger Robot
2021-10-08 15:31:03 +00:00
committed by Gerrit Code Review
3 changed files with 125 additions and 5 deletions

View File

@@ -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,

View File

@@ -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);
}
}

View File

@@ -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));
}
}