Skip to content

Commit a53db46

Browse files
committed
Makes the software enforced section more pretty
Splits up the various software enforced properties into their own items instead of just displaying the JSON strigified representation.
1 parent abfa519 commit a53db46

5 files changed

Lines changed: 140 additions & 13 deletions

File tree

u2f-gae-demo/src/soy/card.soy

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@
2929
<li><span class="label">Keymaster Version: </span><span class="keymasterVersion"></span><br/>
3030
<li><span class="label">Attestation Challenge: </span><span class="challenge"></span><br/>
3131
<li><span class="label">Software Enforced: </span>
32-
<span class="softwareEnforced"></span><br/>
32+
<div class="softwareEnforced">
33+
<ul>
34+
<li><span class="label">Purpose: </span> <span class="purpose"></span>
35+
<li><span class="label">Algorithm: </span> <span class="algorithm"></span>
36+
</ul>
37+
</div>
3338
<li><span class="label">TEE Enforced: </span>
3439
<span class="teeEnforced"></span>
3540
</ul>

u2f-gae-demo/war/js/u2fdemo.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,14 @@ function tokenToDom(token) {
3333
= token.android_attestation.keymaster_version;
3434
card.querySelector('.challenge').textContent
3535
= token.android_attestation.attestation_challenge;
36-
card.querySelector('.softwareEnforced').textContent
37-
= JSON.stringify(token.android_attestation.software_encoded, null, 2);
36+
37+
card.querySelector('.softwareEnforced .algorithm').textContent
38+
= token.android_attestation.software_encoded.algorithm;
39+
if (token.android_attestation.software_encoded.purpose) {
40+
card.querySelector('.softwareEnforced .purpose').textContent
41+
= token.android_attestation.software_encoded.purpose.join(', ');
42+
}
43+
3844
card.querySelector('.teeEnforced').textContent
3945
= JSON.stringify(token.android_attestation.tee_encoded, null, 2);
4046
}

u2f-ref-code/java/src/com/google/u2f/server/impl/attestation/android/AuthorizationList.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.google.u2f.server.impl.attestation.android;
22

3+
import com.google.common.annotations.VisibleForTesting;
4+
import com.google.gson.JsonArray;
35
import com.google.gson.JsonObject;
6+
import com.google.gson.JsonPrimitive;
47

58
import java.util.List;
69
import java.util.Objects;
@@ -9,16 +12,22 @@
912
* Authorization List that describes a Keymaster key
1013
*/
1114
public class AuthorizationList {
12-
private final List<Purpose> purpose;
15+
private final List<Purpose> purposeList;
1316
private final Algorithm algorithm;
1417

18+
@VisibleForTesting
19+
public static final String JSON_ALGORITHM_KEY = "algorithm";
20+
21+
@VisibleForTesting
22+
public static final String JSON_PURPOSE_KEY = "purpose";
23+
1524
protected AuthorizationList(List<Purpose> purpose, Algorithm algorithm) {
16-
this.purpose = purpose;
25+
this.purposeList = purpose;
1726
this.algorithm = algorithm;
1827
}
1928

2029
public List<Purpose> getPurpose() {
21-
return purpose;
30+
return purposeList;
2231
}
2332

2433
public Algorithm getAlgorithm() {
@@ -27,7 +36,7 @@ public Algorithm getAlgorithm() {
2736

2837
@Override
2938
public int hashCode() {
30-
return Objects.hash(purpose, algorithm);
39+
return Objects.hash(purposeList, algorithm);
3140
}
3241

3342
@Override
@@ -40,17 +49,18 @@ public boolean equals(Object obj) {
4049
return false;
4150

4251
AuthorizationList other = (AuthorizationList) obj;
43-
return Objects.equals(algorithm, other.algorithm) && Objects.equals(purpose, other.purpose);
52+
return Objects.equals(algorithm, other.algorithm)
53+
&& Objects.equals(purposeList, other.purposeList);
4454
}
4555

4656
@Override
4757
public String toString() {
4858
StringBuilder stringRepresentation = new StringBuilder();
4959
stringRepresentation.append("[");
5060

51-
if (purpose != null) {
61+
if (purposeList != null) {
5262
stringRepresentation.append("\n purpose: ");
53-
stringRepresentation.append(purpose);
63+
stringRepresentation.append(purposeList);
5464
}
5565

5666
if (algorithm != null) {
@@ -65,11 +75,15 @@ public String toString() {
6575

6676
public JsonObject toJson() {
6777
JsonObject json = new JsonObject();
68-
if (purpose != null) {
69-
json.addProperty("purpose", purpose.toString());
78+
if (purposeList != null) {
79+
JsonArray purposeJsonArray = new JsonArray();
80+
for (Purpose p : purposeList) {
81+
purposeJsonArray.add(new JsonPrimitive(p.toString()));
82+
}
83+
json.add(JSON_PURPOSE_KEY, purposeJsonArray);
7084
}
7185
if (algorithm != null) {
72-
json.addProperty("algorithm", algorithm.toString());
86+
json.addProperty(JSON_ALGORITHM_KEY, algorithm.toString());
7387
}
7488
return json;
7589
}

u2f-ref-code/java/src/com/google/u2f/server/impl/attestation/android/Purpose.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ public static Purpose fromValue(int value) throws CertificateParsingException {
2424
throw new CertificateParsingException("Invalid purpose value: " + value);
2525
}
2626

27+
public static Purpose fromString(String string) throws CertificateParsingException {
28+
for (Purpose purpose : Purpose.values()) {
29+
if (purpose.toString().equals(string)) {
30+
return purpose;
31+
}
32+
}
33+
34+
throw new CertificateParsingException("Invalid purpose value: " + string);
35+
}
36+
2737
private Purpose(int value, String description) {
2838
this.value = value;
2939
this.description = description;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.google.u2f.server.impl.attestation.android;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
import static org.junit.Assert.assertTrue;
6+
7+
import com.google.gson.JsonArray;
8+
import com.google.gson.JsonElement;
9+
import com.google.gson.JsonObject;
10+
11+
import org.junit.Test;
12+
import org.junit.runner.RunWith;
13+
import org.junit.runners.JUnit4;
14+
15+
import java.util.ArrayList;
16+
import java.util.Arrays;
17+
import java.util.Iterator;
18+
import java.util.List;
19+
20+
/**
21+
* Unit tests for {@link AuthorizationList}
22+
*/
23+
@RunWith(JUnit4.class)
24+
public class AuthorizationListTest {
25+
private static final List<Purpose> EMPTY_PURPOSE = new ArrayList<Purpose>();
26+
private static final List<Purpose> ONE_PURPOSE = Arrays.asList(Purpose.KM_PURPOSE_SIGN);
27+
private static final List<Purpose> TWO_PURPOSES =
28+
Arrays.asList(Purpose.KM_PURPOSE_SIGN, Purpose.KM_PURPOSE_VERIFY);
29+
30+
@Test
31+
public void toJson_nullValues() throws Exception {
32+
JsonObject json = new AuthorizationList(null, null).toJson();
33+
34+
assertFalse(json.has(AuthorizationList.JSON_ALGORITHM_KEY));
35+
assertFalse(json.has(AuthorizationList.JSON_PURPOSE_KEY));
36+
}
37+
38+
@Test
39+
public void toJson_emptyPurpose() throws Exception {
40+
AuthorizationList authorizationList =
41+
new AuthorizationList(EMPTY_PURPOSE, Algorithm.KM_ALGORITHM_EC);
42+
JsonObject json = authorizationList.toJson();
43+
44+
assertEquals(
45+
Algorithm.KM_ALGORITHM_EC.toString(),
46+
json.get(AuthorizationList.JSON_ALGORITHM_KEY).getAsString());
47+
List<Purpose> extractedPurpose = extractPurposeListFromJsonArray(
48+
json.get(AuthorizationList.JSON_PURPOSE_KEY).getAsJsonArray());
49+
50+
assertTrue(EMPTY_PURPOSE.containsAll(extractedPurpose));
51+
assertTrue(extractedPurpose.containsAll(EMPTY_PURPOSE));
52+
}
53+
54+
@Test
55+
public void toJson_onePurpose() throws Exception {
56+
AuthorizationList authorizationList =
57+
new AuthorizationList(ONE_PURPOSE, Algorithm.KM_ALGORITHM_HMAC);
58+
JsonObject json = authorizationList.toJson();
59+
60+
assertEquals(
61+
Algorithm.KM_ALGORITHM_HMAC.toString(),
62+
json.get(AuthorizationList.JSON_ALGORITHM_KEY).getAsString());
63+
List<Purpose> extractedPurpose = extractPurposeListFromJsonArray(
64+
json.get(AuthorizationList.JSON_PURPOSE_KEY).getAsJsonArray());
65+
66+
assertTrue(ONE_PURPOSE.containsAll(extractedPurpose));
67+
assertTrue(extractedPurpose.containsAll(ONE_PURPOSE));
68+
}
69+
70+
@Test
71+
public void toJson_twoPurposes() throws Exception {
72+
JsonObject json = new AuthorizationList(TWO_PURPOSES, Algorithm.KM_ALGORITHM_RSA).toJson();
73+
74+
assertEquals(
75+
Algorithm.KM_ALGORITHM_RSA.toString(),
76+
json.get(AuthorizationList.JSON_ALGORITHM_KEY).getAsString());
77+
List<Purpose> extractedPurpose = extractPurposeListFromJsonArray(
78+
json.get(AuthorizationList.JSON_PURPOSE_KEY).getAsJsonArray());
79+
80+
assertTrue(TWO_PURPOSES.containsAll(extractedPurpose));
81+
assertTrue(extractedPurpose.containsAll(TWO_PURPOSES));
82+
}
83+
84+
private List<Purpose> extractPurposeListFromJsonArray(JsonArray array) throws Exception {
85+
Iterator<JsonElement> iterator = array.iterator();
86+
List<Purpose> result = new ArrayList<Purpose>();
87+
while (iterator.hasNext()) {
88+
result.add(Purpose.fromString(iterator.next().getAsString()));
89+
}
90+
return result;
91+
}
92+
}

0 commit comments

Comments
 (0)