1616
1717package com .linecorp .line .auth .fido .fido2 .server .attestation .tpm ;
1818
19+ import com .linecorp .line .auth .fido .fido2 .server .error .InternalErrorCode ;
20+ import com .linecorp .line .auth .fido .fido2 .server .exception .FIDO2ServerRuntimeException ;
21+ import com .linecorp .line .auth .fido .fido2 .server .util .UnsignedUtil ;
22+
1923import java .io .ByteArrayInputStream ;
2024import java .io .IOException ;
21-
22- import com .linecorp .line .auth .fido .fido2 .server .util .UnsignedUtil ;
25+ import java .nio .ByteBuffer ;
2326
2427public class TpmParser {
2528 public static CertInfo parseCertInfo (byte [] certInfo ) throws IOException {
@@ -89,27 +92,48 @@ public static CertInfo parseCertInfo(byte[] certInfo) throws IOException {
8992 }
9093
9194 public static PubArea parsePubArea (byte [] pubArea ) throws IOException {
95+ ByteArrayInputStream pubAreaInputStream = new ByteArrayInputStream (pubArea );
96+ switch (TpmKeyAlgorithm .fromValue (extractTpmKeyAlgType (pubAreaInputStream ))) {
97+ case RSA : {
98+ return createPubAreaForRSA (pubAreaInputStream );
99+ }
100+ case ECC : {
101+ return createPubAreaForECC (pubAreaInputStream );
102+ }
103+ }
104+ throw new FIDO2ServerRuntimeException (InternalErrorCode .TPM_ATTESTATION_DATA_INVALID );
105+ }
106+
107+ private static int extractTpmKeyAlgType (ByteArrayInputStream inputStream ) throws IOException {
92108 byte [] typeBytes = new byte [2 ];
109+ inputStream .read (typeBytes );
110+ return UnsignedUtil .readUINT16BE (typeBytes );
111+ }
112+
113+ private static PubArea createPubAreaForRSA (ByteArrayInputStream inputStream ) throws IOException {
114+ return createPubAreaBuilder (TpmKeyAlgorithm .RSA , inputStream )
115+ .parameters (extractParametersForRSA (inputStream ))
116+ .unique (extractUniqueBytesForRSA (inputStream ))
117+ .build ();
118+ }
119+
120+ private static PubArea createPubAreaForECC (ByteArrayInputStream inputStream ) throws IOException {
121+ return createPubAreaBuilder (TpmKeyAlgorithm .ECC , inputStream )
122+ .parameters (extractParametersForECC (inputStream ))
123+ .unique (extractUniqueBytesForECC (inputStream ))
124+ .build ();
125+ }
126+
127+ private static PubArea .PubAreaBuilder createPubAreaBuilder (TpmKeyAlgorithm tpmKeyAlgType , ByteArrayInputStream inputStream ) throws IOException {
93128 byte [] nameAlgBytes = new byte [2 ];
94129 byte [] objectAttributesBytes = new byte [4 ];
95130 byte [] authPolicyLengthBytes = new byte [2 ];
96- byte [] symmetricBytes = new byte [2 ];
97- byte [] schemeBytes = new byte [2 ];
98- byte [] keyBitsBytes ; // rsa key
99- byte [] exponentBytes ; // rsa key
100- byte [] curveIdBytes ; // ecc key
101- byte [] kdfBytes ; //ecc key
102- byte [] uniqueLengthBytes = new byte [2 ];
103- byte [] uniqueBytes ;
104131
105- ByteArrayInputStream inputStream = new ByteArrayInputStream (pubArea );
106-
107- inputStream .read (typeBytes ); // type
108- int type = UnsignedUtil .readUINT16BE (typeBytes );
109- inputStream .read (nameAlgBytes ); // name alg
132+ inputStream .read (nameAlgBytes );
110133 TpmHashAlgorithm nameAlg =
111134 TpmHashAlgorithm .fromValue (UnsignedUtil .readUINT16BE (nameAlgBytes ));
112- inputStream .read (objectAttributesBytes ); // object attributes
135+
136+ inputStream .read (objectAttributesBytes );
113137 int objectAttributesFlags = (int ) UnsignedUtil .readUINT32BE (objectAttributesBytes );
114138 ObjectAttributes objectAttributes = parseObjectAttributes (objectAttributesFlags );
115139 // skip auth policy
@@ -119,50 +143,77 @@ public static PubArea parsePubArea(byte[] pubArea) throws IOException {
119143 inputStream .skip (authPolicyLength );
120144 }
121145
122- // read parameters depending on the key type
123- Parameters parameters = null ;
124- if (type == TpmKeyAlgorithm .RSA .getValue ()) {
125- keyBitsBytes = new byte [2 ];
126- exponentBytes = new byte [4 ];
127- inputStream .read (symmetricBytes );
128- inputStream .read (schemeBytes );
129- inputStream .read (keyBitsBytes );
130- inputStream .read (exponentBytes );
131- parameters = new RsaParameters ();
132- parameters .setSymmetric (symmetricBytes );
133- parameters .setScheme (TpmSignatureAlgorithm .fromValue (UnsignedUtil .readUINT16BE (schemeBytes )));
134- ((RsaParameters ) parameters ).setKeyBits (keyBitsBytes );
135- ((RsaParameters ) parameters ).setExponent (exponentBytes );
136- } else if (type == TpmKeyAlgorithm .ECC .getValue ()) {
137- curveIdBytes = new byte [2 ];
138- kdfBytes = new byte [2 ];
139- inputStream .read (symmetricBytes );
140- inputStream .read (schemeBytes );
141- inputStream .read (curveIdBytes );
142- inputStream .read (kdfBytes );
143- parameters = new EccParameters ();
144- parameters .setSymmetric (symmetricBytes );
145- parameters .setScheme (TpmSignatureAlgorithm .fromValue (UnsignedUtil .readUINT16BE (schemeBytes )));
146- ((EccParameters ) parameters ).setCurveId (TpmEccCurve .fromValue (UnsignedUtil .readUINT16BE (curveIdBytes )));
147- ((EccParameters ) parameters ).setKdf (kdfBytes );
148- } else {
149- // invalid
150- }
146+ return PubArea
147+ .builder ()
148+ .type (tpmKeyAlgType )
149+ .nameAlg (nameAlg )
150+ .objectAttributes (objectAttributes );
151+ }
152+
153+ private static Parameters extractParametersForRSA (ByteArrayInputStream inputStream ) throws IOException {
154+ byte [] symmetricBytes = new byte [2 ];
155+ byte [] schemeBytes = new byte [2 ];
156+ byte [] keyBitsBytes = new byte [2 ];
157+ byte [] exponentBytes = new byte [4 ];
158+
159+ inputStream .read (symmetricBytes );
160+ inputStream .read (schemeBytes );
161+ inputStream .read (keyBitsBytes );
162+ inputStream .read (exponentBytes );
151163
152- // read unique (key value)
164+ Parameters parameters = new RsaParameters ();
165+ parameters .setSymmetric (symmetricBytes );
166+ parameters .setScheme (TpmSignatureAlgorithm .fromValue (UnsignedUtil .readUINT16BE (schemeBytes )));
167+ ((RsaParameters ) parameters ).setKeyBits (keyBitsBytes );
168+ ((RsaParameters ) parameters ).setExponent (exponentBytes );
169+ return parameters ;
170+ }
171+
172+ private static byte [] extractUniqueBytesForRSA (ByteArrayInputStream inputStream ) throws IOException {
173+ byte [] uniqueLengthBytes = new byte [2 ];
153174 inputStream .read (uniqueLengthBytes );
154175 int uniqueLength = UnsignedUtil .readUINT16BE (uniqueLengthBytes );
155- uniqueBytes = new byte [uniqueLength ];
176+ byte [] uniqueBytes = new byte [uniqueLength ];
156177 inputStream .read (uniqueBytes );
178+ return uniqueBytes ;
179+ }
157180
158- return PubArea
159- .builder ()
160- .type (TpmKeyAlgorithm .fromValue (type ))
161- .nameAlg (nameAlg )
162- .objectAttributes (objectAttributes )
163- .parameters (parameters )
164- .unique (uniqueBytes )
165- .build ();
181+ private static Parameters extractParametersForECC (ByteArrayInputStream inputStream ) throws IOException {
182+ byte [] symmetricBytes = new byte [2 ];
183+ byte [] schemeBytes = new byte [2 ];
184+ byte [] curveIdBytes = new byte [2 ];
185+ byte [] kdfBytes = new byte [2 ];
186+
187+ inputStream .read (symmetricBytes );
188+ inputStream .read (schemeBytes );
189+ inputStream .read (curveIdBytes );
190+ inputStream .read (kdfBytes );
191+
192+ Parameters parameters = new EccParameters ();
193+ parameters .setSymmetric (symmetricBytes );
194+ parameters .setScheme (TpmSignatureAlgorithm .fromValue (UnsignedUtil .readUINT16BE (schemeBytes )));
195+ ((EccParameters ) parameters ).setCurveId (TpmEccCurve .fromValue (UnsignedUtil .readUINT16BE (curveIdBytes )));
196+ ((EccParameters ) parameters ).setKdf (kdfBytes );
197+ return parameters ;
198+ }
199+
200+ private static byte [] extractUniqueBytesForECC (ByteArrayInputStream inputStream ) throws IOException {
201+ byte [] xLengthBytes = new byte [2 ];
202+ inputStream .read (xLengthBytes );
203+ int xLength = UnsignedUtil .readUINT16BE (xLengthBytes );
204+ byte [] xBytes = new byte [xLength ];
205+ inputStream .read (xBytes );
206+
207+ byte [] yLengthBytes = new byte [2 ];
208+ inputStream .read (yLengthBytes );
209+ int yLength = UnsignedUtil .readUINT16BE (yLengthBytes );
210+ byte [] yBytes = new byte [yLength ];
211+ inputStream .read (yBytes );
212+
213+ return ByteBuffer .allocate (xLength + yLength )
214+ .put (xBytes )
215+ .put (yBytes )
216+ .array ();
166217 }
167218
168219 public static ClockInfo parseClockInfo (byte [] clockInfo ) throws IOException {
0 commit comments