106
106
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
107
107
import com .oracle .graal .python .nodes .ErrorMessages ;
108
108
import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
109
- import com .oracle .graal .python .util .BiConsumer ;
110
109
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
111
110
import com .oracle .truffle .api .TruffleFile ;
112
111
import com .oracle .truffle .api .nodes .Node ;
@@ -151,7 +150,7 @@ static boolean isCrl(boolean[] keyUsage) {
151
150
* _ssl.c#_decode_certificate
152
151
*/
153
152
@ TruffleBoundary
154
- public static PDict decodeCertificate (Node node , X509Certificate cert ) throws IOException , CertificateParsingException {
153
+ public static PDict decodeCertificate (Node node , X509Certificate cert ) throws CertificateParsingException {
155
154
PythonObjectFactory factory = PythonObjectFactory .getUncached ();
156
155
PDict dict = factory .createDict ();
157
156
HashingStorage storage = dict .getDictStorage ();
@@ -289,77 +288,92 @@ private static final class DerValue {
289
288
private static final byte OBJECT_IDENTIFIER = 0x06 ;
290
289
private static final byte SEQUENCE = 0x10 ;
291
290
291
+ private static final String ERROR_MESSAGE = "Invalid DER encoded data" ;
292
+
292
293
final byte [] data ;
293
- final int end ;
294
294
final boolean isContextTag ;
295
295
final int contentLen ;
296
296
final int contentStart ;
297
297
int contentTag ;
298
298
299
- DerValue (byte [] data ) {
299
+ DerValue (byte [] data ) throws CertificateParsingException {
300
300
this (data , 0 , data .length );
301
301
}
302
302
303
- DerValue (byte [] data , int offset , int end ) {
304
- this .data = data ;
305
- this .end = end ;
306
-
307
- this .contentTag = data [offset ] & 0b11111;
308
- this .isContextTag = (data [offset ] & 0b11000000) == 0b10000000;
309
- int [] lenAndOffset = readLength (data , offset );
310
- this .contentStart = lenAndOffset [0 ];
311
- this .contentLen = lenAndOffset [1 ];
312
-
313
- assert this .contentTag != 0b11111 : "extended tag range not supported" ;
314
- assert contentStart + contentLen <= end ;
303
+ DerValue (byte [] data , int offset , int end ) throws CertificateParsingException {
304
+ if (offset == data .length ) {
305
+ // this is a 0-length value at the end of the data
306
+ this .data = data ;
307
+ this .contentTag = 0 ;
308
+ this .isContextTag = false ;
309
+ this .contentStart = offset ;
310
+ this .contentLen = 0 ;
311
+ } else if (offset < data .length ) {
312
+ this .data = data ;
313
+
314
+ this .contentTag = data [offset ] & 0b11111;
315
+ this .isContextTag = (data [offset ] & 0b11000000) == 0b10000000;
316
+ int [] lenAndOffset = readLength (data , offset );
317
+ this .contentStart = lenAndOffset [0 ];
318
+ this .contentLen = lenAndOffset [1 ];
319
+
320
+ assert this .contentTag != 0b11111 : "extended tag range not supported" ;
321
+ assert contentStart + contentLen <= end ;
322
+ } else {
323
+ throw new CertificateParsingException (ERROR_MESSAGE );
324
+ }
315
325
}
316
326
317
- private static int [] readLength (byte [] data , int offset ) {
318
- int lenBase = data [offset + 1 ] & 0xff ;
319
- if (lenBase < 128 ) {
320
- return new int []{offset + 2 , lenBase };
321
- } else {
322
- int lengthOfLength = lenBase - 128 ;
323
- if (lengthOfLength > 4 ) {
324
- throw new IllegalArgumentException ("longer than int-range DER values not supported" );
325
- }
326
- int fullLength = 0 ;
327
- for (int i = 0 ; i < lengthOfLength ; i ++) {
328
- fullLength = (fullLength << 8 ) | data [offset + 2 + i ];
327
+ private static int [] readLength (byte [] data , int offset ) throws CertificateParsingException {
328
+ try {
329
+ int lenBase = data [offset + 1 ] & 0xff ;
330
+ if (lenBase < 128 ) {
331
+ return new int []{offset + 2 , lenBase };
332
+ } else {
333
+ int lengthOfLength = lenBase - 128 ;
334
+ if (lengthOfLength > 4 ) {
335
+ throw new IllegalArgumentException ("longer than int-range DER values not supported" );
336
+ }
337
+ int fullLength = 0 ;
338
+ for (int i = 0 ; i < lengthOfLength ; i ++) {
339
+ fullLength = (fullLength << 8 ) | data [offset + 2 + i ];
340
+ }
341
+ return new int []{offset + 2 + lengthOfLength , fullLength };
329
342
}
330
- return new int []{offset + 2 + lengthOfLength , fullLength };
343
+ } catch (ArrayIndexOutOfBoundsException e ) {
344
+ throw new CertificateParsingException (ERROR_MESSAGE );
331
345
}
332
346
}
333
347
334
348
byte [] getRawData () {
335
349
return Arrays .copyOfRange (data , contentStart , contentStart + contentLen );
336
350
}
337
351
338
- DerValue getObjectIdentifier () {
352
+ DerValue getObjectIdentifier () throws CertificateParsingException {
339
353
if (contentTag != OBJECT_IDENTIFIER ) {
340
354
return null ;
341
355
} else {
342
356
return new DerValue (data , contentStart , contentStart + contentLen );
343
357
}
344
358
}
345
359
346
- DerValue getContextTag (int tag ) {
360
+ DerValue getContextTag (int tag ) throws CertificateParsingException {
347
361
if (contentTag != tag || !isContextTag ) {
348
362
return null ;
349
363
} else {
350
364
return new DerValue (data , contentStart , contentStart + contentLen );
351
365
}
352
366
}
353
367
354
- DerValue getOctetString () {
368
+ DerValue getOctetString () throws CertificateParsingException {
355
369
if (contentTag != OCTET_STRING ) {
356
370
return null ;
357
371
} else {
358
372
return new DerValue (data , contentStart , contentStart + contentLen );
359
373
}
360
374
}
361
375
362
- DerValue getSequence () {
376
+ DerValue getSequence () throws CertificateParsingException {
363
377
if (contentTag != SEQUENCE ) {
364
378
return null ;
365
379
} else {
@@ -386,15 +400,20 @@ String getGeneralNameURI() {
386
400
}
387
401
}
388
402
389
- List <DerValue > getSequenceElements () {
403
+ List <DerValue > getSequenceElements () throws CertificateParsingException {
390
404
List <DerValue > result = new ArrayList <>();
391
405
iterateSequence ((e , r ) -> {
392
406
result .add (e );
393
407
}, result );
394
408
return result ;
395
409
}
396
410
397
- <T > void iterateSequence (BiConsumer <DerValue , T > consumer , T value ) {
411
+ @ FunctionalInterface
412
+ private interface DerSequenceConsumer <A , B > {
413
+ abstract void accept (A a , B b ) throws CertificateParsingException ;
414
+ }
415
+
416
+ <T > void iterateSequence (DerSequenceConsumer <DerValue , T > consumer , T value ) throws CertificateParsingException {
398
417
int sequenceStart = contentStart ;
399
418
int sequenceEnd = contentStart + contentLen ;
400
419
DerValue sequenceData = getSequence ();
@@ -411,7 +430,7 @@ <T> void iterateSequence(BiConsumer<DerValue, T> consumer, T value) {
411
430
}
412
431
413
432
@ TruffleBoundary
414
- private static PTuple parseCRLPoints (X509Certificate cert , PythonObjectFactory factory ) throws IOException {
433
+ private static PTuple parseCRLPoints (X509Certificate cert , PythonObjectFactory factory ) throws CertificateParsingException {
415
434
List <String > result = new ArrayList <>();
416
435
byte [] bytes = cert .getExtensionValue (OID_CRL_DISTRIBUTION_POINTS );
417
436
if (bytes == null ) {
@@ -452,7 +471,7 @@ private static PTuple parseCRLPoints(X509Certificate cert, PythonObjectFactory f
452
471
}
453
472
454
473
@ TruffleBoundary
455
- private static PTuple parseCAIssuers (X509Certificate cert , PythonObjectFactory factory ) throws IOException {
474
+ private static PTuple parseCAIssuers (X509Certificate cert , PythonObjectFactory factory ) throws CertificateParsingException {
456
475
List <String > result = new ArrayList <>();
457
476
byte [] bytes = cert .getExtensionValue (OID_AUTHORITY_INFO_ACCESS );
458
477
if (bytes == null ) {
@@ -484,7 +503,7 @@ private static PTuple parseCAIssuers(X509Certificate cert, PythonObjectFactory f
484
503
}
485
504
486
505
@ TruffleBoundary
487
- private static PTuple parseOCSP (X509Certificate cert , PythonObjectFactory factory ) {
506
+ private static PTuple parseOCSP (X509Certificate cert , PythonObjectFactory factory ) throws CertificateParsingException {
488
507
List <String > result = new ArrayList <>();
489
508
byte [] bytes = cert .getExtensionValue (OID_AUTHORITY_INFO_ACCESS );
490
509
if (bytes == null ) {
0 commit comments