diff --git a/server/src/main/java/com/google/android/attestation/AttestationApplicationId.java b/server/src/main/java/com/google/android/attestation/AttestationApplicationId.java index d5bfe71..ead446d 100644 --- a/server/src/main/java/com/google/android/attestation/AttestationApplicationId.java +++ b/server/src/main/java/com/google/android/attestation/AttestationApplicationId.java @@ -19,10 +19,13 @@ import static com.google.android.attestation.Constants.ATTESTATION_APPLICATION_ID_SIGNATURE_DIGESTS_INDEX; import static com.google.android.attestation.Constants.ATTESTATION_PACKAGE_INFO_PACKAGE_NAME_INDEX; import static com.google.android.attestation.Constants.ATTESTATION_PACKAGE_INFO_VERSION_INDEX; +import static java.nio.charset.StandardCharsets.UTF_8; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Objects; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1OctetString; @@ -111,6 +114,11 @@ public boolean equals(Object o) { && (compareTo((AttestationApplicationId) o) == 0); } + @Override + public int hashCode() { + return Objects.hash(packageInfos, Arrays.deepHashCode(signatureDigests.toArray())); + } + /** Provides package's name and version number. */ public static class AttestationPackageInfo implements Comparable { public final String packageName; @@ -121,7 +129,8 @@ private AttestationPackageInfo(ASN1Sequence packageInfo) { new String( ((ASN1OctetString) packageInfo.getObjectAt(ATTESTATION_PACKAGE_INFO_PACKAGE_NAME_INDEX)) - .getOctets()); + .getOctets(), + UTF_8); this.version = ((ASN1Integer) packageInfo.getObjectAt(ATTESTATION_PACKAGE_INFO_VERSION_INDEX)) .getValue() @@ -148,11 +157,16 @@ public int compareTo(AttestationPackageInfo other) { @Override public boolean equals(Object o) { - return (o instanceof AttestationPackageInfo) && (0 == compareTo((AttestationPackageInfo) o)); + return (o instanceof AttestationPackageInfo) && (compareTo((AttestationPackageInfo) o) == 0); + } + + @Override + public int hashCode() { + return Objects.hash(packageName, version); } } - private class ByteArrayComparator implements java.util.Comparator { + private static class ByteArrayComparator implements java.util.Comparator { @Override public int compare(byte[] a, byte[] b) { int res = Integer.compare(a.length, b.length); diff --git a/server/src/main/java/com/google/android/attestation/RootOfTrust.java b/server/src/main/java/com/google/android/attestation/RootOfTrust.java index f56477d..50a1e86 100644 --- a/server/src/main/java/com/google/android/attestation/RootOfTrust.java +++ b/server/src/main/java/com/google/android/attestation/RootOfTrust.java @@ -42,7 +42,7 @@ private RootOfTrust(ASN1Sequence rootOfTrust, int attestationVersion) { this.deviceLocked = ASN1Parsing.getBooleanFromAsn1(rootOfTrust.getObjectAt(ROOT_OF_TRUST_DEVICE_LOCKED_INDEX)); this.verifiedBootState = - rootOfTrustToEnum( + verifiedBootStateToEnum( ASN1Parsing.getIntegerFromAsn1( rootOfTrust.getObjectAt(ROOT_OF_TRUST_VERIFIED_BOOT_STATE_INDEX))); if (attestationVersion >= 3) { @@ -61,12 +61,12 @@ static RootOfTrust createRootOfTrust(ASN1Sequence rootOfTrust, int attestationVe return new RootOfTrust(rootOfTrust, attestationVersion); } - private static VerifiedBootState rootOfTrustToEnum(int securityLevel) { + private static VerifiedBootState verifiedBootStateToEnum(int securityLevel) { switch (securityLevel) { case KM_VERIFIED_BOOT_STATE_VERIFIED: return VerifiedBootState.VERIFIED; case KM_VERIFIED_BOOT_STATE_SELF_SIGNED: - return VerifiedBootState.SELFSIGNED; + return VerifiedBootState.SELF_SIGNED; case KM_VERIFIED_BOOT_STATE_UNVERIFIED: return VerifiedBootState.UNVERIFIED; case KM_VERIFIED_BOOT_STATE_FAILED: @@ -82,7 +82,7 @@ private static VerifiedBootState rootOfTrustToEnum(int securityLevel) { */ public enum VerifiedBootState { VERIFIED, - SELFSIGNED, + SELF_SIGNED, UNVERIFIED, FAILED } diff --git a/server/src/test/java/com/google/android/attestation/AttestationApplicationIdTest.java b/server/src/test/java/com/google/android/attestation/AttestationApplicationIdTest.java index cbaa47b..a1a4b21 100644 --- a/server/src/test/java/com/google/android/attestation/AttestationApplicationIdTest.java +++ b/server/src/test/java/com/google/android/attestation/AttestationApplicationIdTest.java @@ -31,16 +31,17 @@ public class AttestationApplicationIdTest { // Generated from certificate with RSA Algorithm and StrongBox Security Level - private static final String ATTESTATION_APPLICATION_ID = - "MIIBszGCAYswDAQHYW5kcm9pZAIBHTAZBBRjb20uYW5kcm9pZC5rZXljaGFpbgIBHTAZBBRjb20uYW5kcm9pZC5zZXR0" - + "aW5ncwIBHTAZBBRjb20ucXRpLmRpYWdzZXJ2aWNlcwIBHTAaBBVjb20uYW5kcm9pZC5keW5zeXN0ZW0CAR0wHQ" - + "QYY29tLmFuZHJvaWQuaW5wdXRkZXZpY2VzAgEdMB8EGmNvbS5hbmRyb2lkLmxvY2FsdHJhbnNwb3J0AgEdMB8E" - + "GmNvbS5hbmRyb2lkLmxvY2F0aW9uLmZ1c2VkAgEdMB8EGmNvbS5hbmRyb2lkLnNlcnZlci50ZWxlY29tAgEdMC" - + "AEG2NvbS5hbmRyb2lkLndhbGxwYXBlcmJhY2t1cAIBHTAhBBxjb20uZ29vZ2xlLlNTUmVzdGFydERldGVjdG9y" - + "AgEdMCIEHWNvbS5nb29nbGUuYW5kcm9pZC5oaWRkZW5tZW51AgEBMCMEHmNvbS5hbmRyb2lkLnByb3ZpZGVycy" - + "5zZXR0aW5ncwIBHTEiBCAwGqPLCBE0UBxF8UIqvGbCQiT9Xe1f3I8X5pcXb9hmqg=="; - private static final DEROctetString ATTESTATION_APPLICATION_ID_OCTETS = - new DEROctetString(Base64.decode(ATTESTATION_APPLICATION_ID)); + private static final DEROctetString ATTESTATION_APPLICATION_ID = + new DEROctetString( + Base64.decode( + "MIIBszGCAYswDAQHYW5kcm9pZAIBHTAZBBRjb20uYW5kcm9pZC5rZXljaGFpbgIBHTAZBBRjb20uYW5kcm9p" + + "ZC5zZXR0aW5ncwIBHTAZBBRjb20ucXRpLmRpYWdzZXJ2aWNlcwIBHTAaBBVjb20uYW5kcm9pZC5keW" + + "5zeXN0ZW0CAR0wHQQYY29tLmFuZHJvaWQuaW5wdXRkZXZpY2VzAgEdMB8EGmNvbS5hbmRyb2lkLmxv" + + "Y2FsdHJhbnNwb3J0AgEdMB8EGmNvbS5hbmRyb2lkLmxvY2F0aW9uLmZ1c2VkAgEdMB8EGmNvbS5hbm" + + "Ryb2lkLnNlcnZlci50ZWxlY29tAgEdMCAEG2NvbS5hbmRyb2lkLndhbGxwYXBlcmJhY2t1cAIBHTAh" + + "BBxjb20uZ29vZ2xlLlNTUmVzdGFydERldGVjdG9yAgEdMCIEHWNvbS5nb29nbGUuYW5kcm9pZC5oaW" + + "RkZW5tZW51AgEBMCMEHmNvbS5hbmRyb2lkLnByb3ZpZGVycy5zZXR0aW5ncwIBHTEiBCAwGqPLCBE0" + + "UBxF8UIqvGbCQiT9Xe1f3I8X5pcXb9hmqg==")); private static final List EXPECTED_PACKAGE_INFOS = ImmutableList.of( @@ -66,7 +67,7 @@ public class AttestationApplicationIdTest { @Test public void testCreateAttestationApplicationId() { AttestationApplicationId attestationApplicationId = - AttestationApplicationId.createAttestationApplicationId(ATTESTATION_APPLICATION_ID_OCTETS); + AttestationApplicationId.createAttestationApplicationId(ATTESTATION_APPLICATION_ID); assertThat(attestationApplicationId).isEqualTo(EXPECTED_ATTESTATION_APPLICATION_ID); } @@ -75,7 +76,31 @@ public void testCreateEmptyAttestationApplicationIdFromEmptyOrInvalidInput() { assertThat(AttestationApplicationId.createAttestationApplicationId(null)).isNull(); assertThat( AttestationApplicationId.createAttestationApplicationId( - new DEROctetString(Base64.decode("Invalid DEROcetet String")))) + new DEROctetString(Base64.decode("Invalid DEROctet String")))) .isNull(); } + + @Test + public void testEquals() { + AttestationApplicationId attestationApplicationId = + AttestationApplicationId.createAttestationApplicationId(ATTESTATION_APPLICATION_ID); + AttestationApplicationId emptyAttestationApplicationId = + new AttestationApplicationId(ImmutableList.of(), ImmutableList.of()); + + assertThat(attestationApplicationId.equals(EXPECTED_ATTESTATION_APPLICATION_ID)).isTrue(); + assertThat(EXPECTED_ATTESTATION_APPLICATION_ID.equals(attestationApplicationId)).isTrue(); + + assertThat(attestationApplicationId.equals(emptyAttestationApplicationId)).isFalse(); + assertThat(emptyAttestationApplicationId.equals(attestationApplicationId)).isFalse(); + } + + @Test + public void testEqualObjectsHaveEqualHashCodes() { + AttestationApplicationId attestationApplicationId = + AttestationApplicationId.createAttestationApplicationId(ATTESTATION_APPLICATION_ID); + + assertThat(attestationApplicationId.equals(EXPECTED_ATTESTATION_APPLICATION_ID)).isTrue(); + assertThat(attestationApplicationId.hashCode()) + .isEqualTo(EXPECTED_ATTESTATION_APPLICATION_ID.hashCode()); + } }