Skip to content

Commit c11bc8d

Browse files
committed
Be more forgiving in parsing verifier IDs
RFC 4648's Base32 is made to be forgiving for users doing manual entry of the digits. For this reason we want to be able to parse lowercase letters as uppercase and number 0 (zero) as letter O along with number 1 (one) as letter I. Cherry-pick into ics-factoryrom Change-Id: I149d8e947ff8b36305c1e61d8a1d80ff0b317cda
1 parent 4e3bee7 commit c11bc8d

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

core/java/android/content/pm/VerifierDeviceIdentity.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,15 @@ private static final long decodeBase32(byte[] input) throws IllegalArgumentExcep
153153
value = group - ('2' - 26);
154154
} else if (group == SEPARATOR) {
155155
continue;
156+
} else if ('a' <= group && group <= 'z') {
157+
/* Lowercase letters should be the same as uppercase for Base32 */
158+
value = group - 'a';
159+
} else if (group == '0') {
160+
/* Be nice to users that mistake O (letter) for 0 (zero) */
161+
value = 'O' - 'A';
162+
} else if (group == '1') {
163+
/* Be nice to users that mistake I (letter) for 1 (one) */
164+
value = 'I' - 'A';
156165
} else {
157166
throw new IllegalArgumentException("base base-32 character: " + group);
158167
}

core/tests/coretests/src/android/content/pm/VerifierDeviceIdentityTest.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase {
2525

2626
private static final String TEST_1_ENCODED = "HUXY-A75N-FLKV-F";
2727

28+
private static final String TEST_1_ENCODED_LOWERCASE = "huxy-a75n-flkv-f";
29+
2830
private static final long TEST_2 = 0x5A05FF5A05F0A555L;
2931

3032
private static final long TEST_MAXVALUE = Long.MAX_VALUE;
@@ -45,6 +47,10 @@ public class VerifierDeviceIdentityTest extends android.test.AndroidTestCase {
4547

4648
private static final String TEST_OVERFLOW_ENCODED = "QAAA-AAAA-AAAA-A";
4749

50+
private static final String TEST_SUBSTITUTION_CORRECTED = "OIIO-IIOO-IOOI-I";
51+
52+
private static final String TEST_SUBSTITUTION_UNCORRECTED = "0110-1100-1001-1";
53+
4854
public void testVerifierDeviceIdentity_Equals_Success() {
4955
VerifierDeviceIdentity id1 = new VerifierDeviceIdentity(TEST_1);
5056
VerifierDeviceIdentity id2 = new VerifierDeviceIdentity(TEST_1);
@@ -125,6 +131,7 @@ public void testVerifierDeviceIdentity_Parcel_Read_Pass() {
125131
assertEquals("Original identity and parceled identity should be the same", id1, id2);
126132
}
127133

134+
@SuppressWarnings("serial")
128135
private static class MockRandom extends Random {
129136
private long mNextLong;
130137

@@ -181,7 +188,7 @@ public void testVerifierDeviceIdentity_Parse_MaxValue() {
181188

182189
public void testVerifierDeviceIdentity_Parse_TooShort() {
183190
try {
184-
VerifierDeviceIdentity id = VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-");
191+
VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-");
185192
fail("Parsing should fail when device identifier is too short");
186193
} catch (IllegalArgumentException e) {
187194
// success
@@ -190,7 +197,7 @@ public void testVerifierDeviceIdentity_Parse_TooShort() {
190197

191198
public void testVerifierDeviceIdentity_Parse_WayTooShort() {
192199
try {
193-
VerifierDeviceIdentity id = VerifierDeviceIdentity.parse("----------------");
200+
VerifierDeviceIdentity.parse("----------------");
194201
fail("Parsing should fail when device identifier is too short");
195202
} catch (IllegalArgumentException e) {
196203
// success
@@ -199,7 +206,7 @@ public void testVerifierDeviceIdentity_Parse_WayTooShort() {
199206

200207
public void testVerifierDeviceIdentity_Parse_TooLong() {
201208
try {
202-
VerifierDeviceIdentity id = VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-AA");
209+
VerifierDeviceIdentity.parse("AAAA-AAAA-AAAA-AA");
203210
fail("Parsing should fail when device identifier is too long");
204211
} catch (IllegalArgumentException e) {
205212
// success
@@ -208,10 +215,32 @@ public void testVerifierDeviceIdentity_Parse_TooLong() {
208215

209216
public void testVerifierDeviceIdentity_Parse_Overflow() {
210217
try {
211-
VerifierDeviceIdentity id = VerifierDeviceIdentity.parse(TEST_OVERFLOW_ENCODED);
218+
VerifierDeviceIdentity.parse(TEST_OVERFLOW_ENCODED);
212219
fail("Parsing should fail when the value will overflow");
213220
} catch (IllegalArgumentException e) {
214221
// success
215222
}
216223
}
224+
225+
public void testVerifierDeviceIdentity_Parse_SquashToUppercase() {
226+
VerifierDeviceIdentity id1 = new VerifierDeviceIdentity(TEST_1);
227+
228+
VerifierDeviceIdentity id2 = VerifierDeviceIdentity.parse(TEST_1_ENCODED_LOWERCASE);
229+
230+
assertEquals("Lowercase should parse to be the same as uppercase", id1, id2);
231+
232+
assertEquals("Substituted identity should render to the same string",
233+
id1.toString(), id2.toString());
234+
}
235+
236+
public void testVerifierDeviceIdentity_Parse_1I_And_0O_Substitution() {
237+
VerifierDeviceIdentity id1 = VerifierDeviceIdentity.parse(TEST_SUBSTITUTION_CORRECTED);
238+
239+
VerifierDeviceIdentity id2 = VerifierDeviceIdentity.parse(TEST_SUBSTITUTION_UNCORRECTED);
240+
241+
assertEquals("Substitution should replace 0 with O and 1 with I", id1, id2);
242+
243+
assertEquals("Substituted identity should render to the same string",
244+
id1.toString(), id2.toString());
245+
}
217246
}

0 commit comments

Comments
 (0)