Skip to content

Commit

Permalink
Make value classes immutable
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonweeks committed Nov 21, 2023
1 parent add07bd commit 4079f7d
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 119 deletions.
1 change: 1 addition & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ maven_install(
"com.google.code.gson:gson:2.10.1",
"com.google.errorprone:error_prone_annotations:2.3.1",
"com.google.guava:guava:32.0.1-jre",
"com.google.protobuf:protobuf-javalite:3.25.1",
"com.squareup.okhttp3:okhttp:4.10.0",
"org.bouncycastle:bcpkix-jdk18on:1.73",
"org.bouncycastle:bcprov-jdk18on:1.73",
Expand Down
1 change: 1 addition & 0 deletions server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies {
compile 'com.google.code.gson:gson:2.10.1'
compile 'com.google.errorprone:error_prone_annotations:2.3.1'
compile 'com.google.guava:guava:32.0.1-jre'
compile 'com.google.protobuf:protobuf-javalite:3.25.1'
compile 'com.squareup.okhttp3:okhttp:4.10.0'
compile 'org.bouncycastle:bcpkix-jdk18on:1.73'
compile 'org.jspecify:jspecify:0.2.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import static com.google.android.attestation.ParsedAttestationRecord.createParsedAttestationRecord;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.android.attestation.AttestationApplicationId;
import com.google.android.attestation.AttestationApplicationId.AttestationPackageInfo;
Expand All @@ -28,6 +27,7 @@
import com.google.android.attestation.ParsedAttestationRecord;
import com.google.android.attestation.RootOfTrust;
import com.google.common.collect.ImmutableList;
import com.google.protobuf.ByteString;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Files;
Expand Down Expand Up @@ -98,9 +98,9 @@ public static void main(String[] args)
"Keymaster Security Level: " + parsedAttestationRecord.keymasterSecurityLevel.name());

System.out.println(
"Attestation Challenge: "
+ new String(parsedAttestationRecord.attestationChallenge, UTF_8));
System.out.println("Unique ID: " + Arrays.toString(parsedAttestationRecord.uniqueId));
"Attestation Challenge: " + parsedAttestationRecord.attestationChallenge.toStringUtf8());
System.out.println(
"Unique ID: " + Arrays.toString(parsedAttestationRecord.uniqueId.toByteArray()));

System.out.println("Software Enforced Authorization List:");
AuthorizationList softwareEnforced = parsedAttestationRecord.softwareEnforced;
Expand Down Expand Up @@ -174,13 +174,17 @@ private static void printAuthorizationList(AuthorizationList authorizationList,

private static void print(RootOfTrust rootOfTrust, String indent) {
System.out.println(
indent + "Verified Boot Key: " + Base64.toBase64String(rootOfTrust.verifiedBootKey));
indent
+ "Verified Boot Key: "
+ Base64.toBase64String(rootOfTrust.verifiedBootKey.toByteArray()));
System.out.println(indent + "Device Locked: " + rootOfTrust.deviceLocked);
System.out.println(indent + "Verified Boot State: " + rootOfTrust.verifiedBootState.name());
rootOfTrust.verifiedBootHash.ifPresent(
verifiedBootHash ->
System.out.println(
indent + "Verified Boot Hash: " + Base64.toBase64String(verifiedBootHash)));
indent
+ "Verified Boot Hash: "
+ Base64.toBase64String(verifiedBootHash.toByteArray())));
}

private static void print(AttestationApplicationId attestationApplicationId, String indent) {
Expand All @@ -189,8 +193,8 @@ private static void print(AttestationApplicationId attestationApplicationId, Str
System.out.println(indent + "\t" + info.packageName + ", " + info.version);
}
System.out.println(indent + "Signature Digests:");
for (byte[] digest : attestationApplicationId.signatureDigests) {
System.out.println(indent + "\t" + Base64.toBase64String(digest));
for (ByteString digest : attestationApplicationId.signatureDigests) {
System.out.println(indent + "\t" + Base64.toBase64String(digest.toByteArray()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@
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 com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Streams.stream;
import static java.nio.charset.StandardCharsets.UTF_8;

import java.util.ArrayList;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
import com.google.protobuf.ByteString;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
Expand All @@ -43,9 +46,10 @@
*
* <p>The Attestation Application ID data from KeyMint will not exceed 1K bytes.
*/
@Immutable
public class AttestationApplicationId {
public final List<AttestationPackageInfo> packageInfos;
public final List<byte[]> signatureDigests;
public final ImmutableList<AttestationPackageInfo> packageInfos;
public final ImmutableList<ByteString> signatureDigests;

private AttestationApplicationId(byte[] attestationApplicationId) {
ASN1Sequence attestationApplicationIdSequence =
Expand All @@ -54,25 +58,28 @@ private AttestationApplicationId(byte[] attestationApplicationId) {
(ASN1Set)
attestationApplicationIdSequence.getObjectAt(
ATTESTATION_APPLICATION_ID_PACKAGE_INFOS_INDEX);
packageInfos = new ArrayList<>();
for (ASN1Encodable packageInfo : attestationPackageInfos) {
packageInfos.add(new AttestationPackageInfo((ASN1Sequence) packageInfo));
}
packageInfos =
stream(attestationPackageInfos.iterator())
.map(ASN1Sequence.class::cast)
.map(AttestationPackageInfo::new)
.collect(toImmutableList());

ASN1Set digests =
(ASN1Set)
attestationApplicationIdSequence.getObjectAt(
ATTESTATION_APPLICATION_ID_SIGNATURE_DIGESTS_INDEX);
signatureDigests = new ArrayList<>();
for (ASN1Encodable digest : digests) {
signatureDigests.add(((ASN1OctetString) digest).getOctets());
}
signatureDigests =
stream(digests.iterator())
.map(ASN1OctetString.class::cast)
.map(ASN1OctetString::getOctets)
.map(ByteString::copyFrom)
.collect(toImmutableList());
}

public AttestationApplicationId(
List<AttestationPackageInfo> packageInfos, List<byte[]> signatureDigests) {
this.packageInfos = packageInfos;
this.signatureDigests = signatureDigests;
List<AttestationPackageInfo> packageInfos, List<ByteString> signatureDigests) {
this.packageInfos = ImmutableList.copyOf(packageInfos);
this.signatureDigests = ImmutableList.copyOf(signatureDigests);
}

static AttestationApplicationId createAttestationApplicationId(byte[] attestationApplicationId) {
Expand All @@ -81,15 +88,17 @@ static AttestationApplicationId createAttestationApplicationId(byte[] attestatio

ASN1Sequence toAsn1Sequence() {
ASN1Encodable[] applicationIdAsn1Array = new ASN1Encodable[2];
ASN1EncodableVector tmpPackageInfos = new ASN1EncodableVector();
packageInfos.forEach(packageInfo -> tmpPackageInfos.add(packageInfo.toAsn1Sequence()));
applicationIdAsn1Array[ATTESTATION_APPLICATION_ID_PACKAGE_INFOS_INDEX] =
new DERSet(tmpPackageInfos);

ASN1EncodableVector tmpSignatureDigests = new ASN1EncodableVector();
signatureDigests.forEach(digest -> tmpSignatureDigests.add(new DEROctetString(digest)));
new DERSet(
packageInfos.stream()
.map(AttestationPackageInfo::toAsn1Sequence)
.toArray(ASN1Sequence[]::new));
applicationIdAsn1Array[ATTESTATION_APPLICATION_ID_SIGNATURE_DIGESTS_INDEX] =
new DERSet(tmpSignatureDigests);
new DERSet(
signatureDigests.stream()
.map(ByteString::toByteArray)
.map(DEROctetString::new)
.toArray(DEROctetString[]::new));

return new DERSequence(applicationIdAsn1Array);
}
Expand All @@ -110,6 +119,7 @@ public int hashCode() {
}

/** Provides package's name and version number. */
@Immutable
public static class AttestationPackageInfo {
public final String packageName;
public final long version;
Expand Down
Loading

0 comments on commit 4079f7d

Please sign in to comment.