Skip to content

Commit cdb1b2d

Browse files
committed
Cleanup ASN1 decoding routines
1 parent f84cfec commit cdb1b2d

7 files changed

Lines changed: 63 additions & 73 deletions

File tree

u2f-ref-code/java/src/com/google/u2f/server/impl/U2FServerReferenceImpl.java

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import com.google.u2f.server.data.SecurityKeyData;
4747
import com.google.u2f.server.data.SecurityKeyData.Transports;
4848
import com.google.u2f.server.data.SignSessionData;
49+
import com.google.u2f.server.impl.attestation.X509ExtentionParsingUtil;
4950
import com.google.u2f.server.messages.RegisteredKey;
5051
import com.google.u2f.server.messages.RegistrationRequest;
5152
import com.google.u2f.server.messages.RegistrationResponse;
@@ -325,36 +326,12 @@ public SecurityKeyData processSignResponse(SignResponse signResponse) throws U2F
325326
*/
326327
public static List<Transports> parseTransportsExtension(X509Certificate cert)
327328
throws CertificateParsingException{
328-
byte[] extValue = cert.getExtensionValue(TRANSPORT_EXTENSION_OID);
329329
LinkedList<Transports> transportsList = new LinkedList<Transports>();
330-
if (extValue == null) {
331-
// No transports extension found.
332-
return null;
333-
}
334-
335-
ASN1InputStream ais = new ASN1InputStream(extValue);
336-
ASN1Object asn1Object;
337-
// Read out the OctetString
338-
try {
339-
asn1Object = ais.readObject();
340-
ais.close();
341-
} catch (IOException e) {
342-
throw new CertificateParsingException("Not able to read object in transports extenion", e);
343-
}
344-
345-
if (asn1Object == null || !(asn1Object instanceof DEROctetString)) {
346-
throw new CertificateParsingException("No Octet String found in transports extension");
347-
}
348-
DEROctetString octet = (DEROctetString) asn1Object;
330+
DEROctetString extValue =
331+
X509ExtentionParsingUtil.extractExtensionValue(cert, TRANSPORT_EXTENSION_OID);
349332

350333
// Read out the BitString
351-
ais = new ASN1InputStream(octet.getOctets());
352-
try {
353-
asn1Object = ais.readObject();
354-
ais.close();
355-
} catch (IOException e) {
356-
throw new CertificateParsingException("Not able to read object in transports extension", e);
357-
}
334+
ASN1Object asn1Object = X509ExtentionParsingUtil.getAsn1Object(extValue.getOctets());
358335
if (asn1Object == null || !(asn1Object instanceof DERBitString)) {
359336
throw new CertificateParsingException("No BitString found in transports extension");
360337
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.google.u2f.server.impl.attestation;
2+
3+
import org.bouncycastle.asn1.ASN1InputStream;
4+
import org.bouncycastle.asn1.ASN1Object;
5+
import org.bouncycastle.asn1.DEROctetString;
6+
7+
import java.io.IOException;
8+
import java.security.cert.CertificateParsingException;
9+
import java.security.cert.X509Certificate;
10+
11+
/**
12+
* A set of utilities for parsing X509 Extensions
13+
*/
14+
public class X509ExtentionParsingUtil {
15+
public static DEROctetString extractExtensionValue(X509Certificate cert, String Oid)
16+
throws CertificateParsingException {
17+
byte[] extensionValue = cert.getExtensionValue(Oid);
18+
19+
if (extensionValue == null || extensionValue.length == 0) {
20+
throw new CertificateParsingException("Did not find extension with OID " + Oid);
21+
}
22+
23+
ASN1Object asn1Object = getAsn1Object(extensionValue);
24+
if (asn1Object == null || !(asn1Object instanceof DEROctetString)) {
25+
throw new CertificateParsingException("Expected DEROctetString.");
26+
}
27+
28+
return (DEROctetString) asn1Object;
29+
}
30+
31+
public static ASN1Object getAsn1Object(byte[] octets) throws CertificateParsingException {
32+
ASN1InputStream ais = new ASN1InputStream(octets);
33+
// Read the key description octet string
34+
try {
35+
return ais.readObject();
36+
} catch (IOException e) {
37+
throw new CertificateParsingException("Not able to read ASN.1 object", e);
38+
} finally {
39+
try {
40+
ais.close();
41+
} catch (IOException e) {
42+
throw new CertificateParsingException("Not able to close ASN.1 stream", e);
43+
}
44+
}
45+
}
46+
}

u2f-ref-code/java/src/com/google/u2f/server/impl/androidattestation/Algorithm.java renamed to u2f-ref-code/java/src/com/google/u2f/server/impl/attestation/android/Algorithm.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.google.u2f.server.impl.androidattestation;
1+
package com.google.u2f.server.impl.attestation.android;
22

33
import java.security.cert.CertificateParsingException;
44

u2f-ref-code/java/src/com/google/u2f/server/impl/androidattestation/AndroidKeyStoreAttestation.java renamed to u2f-ref-code/java/src/com/google/u2f/server/impl/attestation/android/AndroidKeyStoreAttestation.java

Lines changed: 9 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
package com.google.u2f.server.impl.androidattestation;
1+
package com.google.u2f.server.impl.attestation.android;
2+
3+
import com.google.u2f.server.impl.attestation.X509ExtentionParsingUtil;
24

35
import org.bouncycastle.asn1.ASN1Encodable;
4-
import org.bouncycastle.asn1.ASN1InputStream;
56
import org.bouncycastle.asn1.ASN1Integer;
67
import org.bouncycastle.asn1.ASN1Object;
78
import org.bouncycastle.asn1.ASN1Primitive;
8-
import org.bouncycastle.asn1.ASN1Sequence;
99
import org.bouncycastle.asn1.DEROctetString;
1010
import org.bouncycastle.asn1.DERSet;
1111
import org.bouncycastle.asn1.DERTaggedObject;
1212
import org.bouncycastle.asn1.DLSequence;
1313

14-
import java.io.IOException;
1514
import java.math.BigInteger;
1615
import java.security.cert.CertificateParsingException;
1716
import java.security.cert.X509Certificate;
@@ -136,7 +135,8 @@ private AndroidKeyStoreAttestation(Integer keymasterVersion, byte[] attestationC
136135
public static AndroidKeyStoreAttestation Parse(X509Certificate cert)
137136
throws CertificateParsingException {
138137
// Extract the extension from the certificate
139-
byte[] extensionValue = extractExtensionValue(cert);
138+
DEROctetString extensionValue =
139+
X509ExtentionParsingUtil.extractExtensionValue(cert, KEY_DESCRIPTION_OID);
140140

141141
// Get the KeyDescription sequence
142142
DLSequence keyDescriptionSequence = getKeyDescriptionSequence(extensionValue);
@@ -151,8 +151,8 @@ public static AndroidKeyStoreAttestation Parse(X509Certificate cert)
151151
DLSequence softwareEnforcedSequence = getSoftwareEncodedSequence(keyDescriptionSequence);
152152
AuthorizationList softwareAuthorizationList =
153153
extractAuthorizationList(softwareEnforcedSequence);
154-
155-
// TODO(aczeskis) Extract the tee authorization list
154+
155+
// TODO(aczeskis) Extract the TEE authorization list
156156

157157
return new AndroidKeyStoreAttestation(keymasterVersion, challenge, softwareAuthorizationList);
158158
}
@@ -178,43 +178,10 @@ public byte[] getAttestationChallenge() {
178178
return attestationChallenge;
179179
}
180180

181-
private static byte[] extractExtensionValue(X509Certificate cert)
182-
throws CertificateParsingException {
183-
byte[] extensionValue = cert.getExtensionValue(KEY_DESCRIPTION_OID);
184-
185-
if (extensionValue == null || extensionValue.length == 0) {
186-
throw new CertificateParsingException(
187-
"Did not find KeyDescription extension with OID " + KEY_DESCRIPTION_OID);
188-
}
189-
190-
return extensionValue;
191-
}
192-
193-
private static DLSequence getKeyDescriptionSequence(byte[] extensionValue)
181+
private static DLSequence getKeyDescriptionSequence(DEROctetString octet)
194182
throws CertificateParsingException {
195-
ASN1InputStream ais = new ASN1InputStream(extensionValue);
196-
ASN1Object asn1Object;
197-
198-
// Read the key description octet string
199-
try {
200-
asn1Object = ais.readObject();
201-
ais.close();
202-
} catch (IOException e) {
203-
throw new CertificateParsingException("Not able to read KeyDescription ASN.1 object", e);
204-
}
205-
if (asn1Object == null || !(asn1Object instanceof DEROctetString)) {
206-
throw new CertificateParsingException("Expected KeyDescription Octet String.");
207-
}
208-
DEROctetString octet = (DEROctetString) asn1Object;
209-
210183
// Read out the Sequence
211-
ais = new ASN1InputStream(octet.getOctets());
212-
try {
213-
asn1Object = ais.readObject();
214-
ais.close();
215-
} catch (IOException e) {
216-
throw new CertificateParsingException("Not able to read KeyDescription Octet String.", e);
217-
}
184+
ASN1Object asn1Object = X509ExtentionParsingUtil.getAsn1Object(octet.getOctets());
218185
if (asn1Object == null || !(asn1Object instanceof DLSequence)) {
219186
throw new CertificateParsingException("Expected KeyDescription Sequence.");
220187
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.google.u2f.server.impl.androidattestation;
1+
package com.google.u2f.server.impl.attestation.android;
22

33
import java.util.List;
44

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.google.u2f.server.impl.androidattestation;
1+
package com.google.u2f.server.impl.attestation.android;
22

33
import java.security.cert.CertificateParsingException;
44

u2f-ref-code/java/tests/com/google/u2f/server/impl/androidattestation/AndroidKeyStoreAttestationTest.java renamed to u2f-ref-code/java/tests/com/google/u2f/server/impl/attestation/android/AndroidKeyStoreAttestationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.google.u2f.server.impl.androidattestation;
1+
package com.google.u2f.server.impl.attestation.android;
22

33
import static org.junit.Assert.assertArrayEquals;
44
import static org.junit.Assert.assertEquals;

0 commit comments

Comments
 (0)