@@ -14,6 +14,13 @@ const MAX_DER_OCTETS: usize = 5;
14
14
/// Maximum length as a `u32` (256 MiB).
15
15
const MAX_U32 : u32 = 0xfff_ffff ;
16
16
17
+ /// Octet identifying an indefinite length as described in X.690 Section
18
+ /// 8.1.3.6.1:
19
+ ///
20
+ /// > The single octet shall have bit 8 set to one, and bits 7 to
21
+ /// > 1 set to zero.
22
+ const INDEFINITE_LENGTH_OCTET : u8 = 0b10000000 ; // 0x80
23
+
17
24
/// ASN.1-encoded length.
18
25
///
19
26
/// Maximum length is defined by the [`Length::MAX`] constant (256 MiB).
@@ -204,7 +211,8 @@ impl<'a> Decode<'a> for Length {
204
211
match reader. read_byte ( ) ? {
205
212
// Note: per X.690 Section 8.1.3.6.1 the byte 0x80 encodes indefinite
206
213
// lengths, which are not allowed in DER, so disallow that byte.
207
- len if len < 0x80 => Ok ( len. into ( ) ) ,
214
+ len if len < INDEFINITE_LENGTH_OCTET => Ok ( len. into ( ) ) ,
215
+ INDEFINITE_LENGTH_OCTET => Err ( ErrorKind :: IndefiniteLength . into ( ) ) ,
208
216
// 1-4 byte variable-sized length prefix
209
217
tag @ 0x81 ..=0x84 => {
210
218
let nbytes = tag. checked_sub ( 0x80 ) . ok_or ( ErrorKind :: Overlength ) ? as usize ;
@@ -299,9 +307,95 @@ impl<'a> arbitrary::Arbitrary<'a> for Length {
299
307
}
300
308
}
301
309
310
+ /// Length type with support for indefinite lengths as used by ASN.1 BER,
311
+ /// as described in X.690 Section 8.1.3.6:
312
+ ///
313
+ /// > 8.1.3.6 For the indefinite form, the length octets indicate that the
314
+ /// > contents octets are terminated by end-of-contents
315
+ /// > octets (see 8.1.5), and shall consist of a single octet.
316
+ /// >
317
+ /// > 8.1.3.6.1 The single octet shall have bit 8 set to one, and bits 7 to
318
+ /// > 1 set to zero.
319
+ /// >
320
+ /// > 8.1.3.6.2 If this form of length is used, then end-of-contents octets
321
+ /// > (see 8.1.5) shall be present in the encoding following the contents
322
+ /// > octets.
323
+ ///
324
+ /// Indefinite lengths are non-canonical and therefore invalid DER, however
325
+ /// there are interoperability corner cases where we have little choice but to
326
+ /// tolerate some BER productions where this is helpful.
327
+ #[ derive( Copy , Clone , Debug , Eq , PartialEq , PartialOrd , Ord ) ]
328
+ pub struct IndefiniteLength ( Option < Length > ) ;
329
+
330
+ impl IndefiniteLength {
331
+ /// Length of `0`.
332
+ pub const ZERO : Self = Self ( Some ( Length :: ZERO ) ) ;
333
+
334
+ /// Length of `1`.
335
+ pub const ONE : Self = Self ( Some ( Length :: ONE ) ) ;
336
+
337
+ /// Indefinite length.
338
+ pub const INDEFINITE : Self = Self ( None ) ;
339
+ }
340
+
341
+ impl IndefiniteLength {
342
+ /// Is this length definite?
343
+ pub fn is_definite ( self ) -> bool {
344
+ self . 0 . is_some ( )
345
+ }
346
+ /// Is this length indefinite?
347
+ pub fn is_indefinite ( self ) -> bool {
348
+ self . 0 . is_none ( )
349
+ }
350
+ }
351
+
352
+ impl < ' a > Decode < ' a > for IndefiniteLength {
353
+ fn decode < R : Reader < ' a > > ( reader : & mut R ) -> Result < IndefiniteLength > {
354
+ if reader. peek_byte ( ) == Some ( INDEFINITE_LENGTH_OCTET ) {
355
+ // Consume the byte we already peeked at.
356
+ let byte = reader. read_byte ( ) ?;
357
+ debug_assert_eq ! ( byte, INDEFINITE_LENGTH_OCTET ) ;
358
+
359
+ Ok ( Self :: INDEFINITE )
360
+ } else {
361
+ Length :: decode ( reader) . map ( Into :: into)
362
+ }
363
+ }
364
+ }
365
+
366
+ impl Encode for IndefiniteLength {
367
+ fn encoded_len ( & self ) -> Result < Length > {
368
+ match self . 0 {
369
+ Some ( length) => length. encoded_len ( ) ,
370
+ None => Ok ( Length :: ONE ) ,
371
+ }
372
+ }
373
+
374
+ fn encode ( & self , writer : & mut impl Writer ) -> Result < ( ) > {
375
+ match self . 0 {
376
+ Some ( length) => length. encode ( writer) ,
377
+ None => writer. write_byte ( INDEFINITE_LENGTH_OCTET ) ,
378
+ }
379
+ }
380
+ }
381
+
382
+ impl From < Length > for IndefiniteLength {
383
+ fn from ( length : Length ) -> IndefiniteLength {
384
+ Self ( Some ( length) )
385
+ }
386
+ }
387
+
388
+ impl TryFrom < IndefiniteLength > for Length {
389
+ type Error = Error ;
390
+
391
+ fn try_from ( length : IndefiniteLength ) -> Result < Length > {
392
+ length. 0 . ok_or_else ( || ErrorKind :: IndefiniteLength . into ( ) )
393
+ }
394
+ }
395
+
302
396
#[ cfg( test) ]
303
397
mod tests {
304
- use super :: Length ;
398
+ use super :: { IndefiniteLength , Length } ;
305
399
use crate :: { Decode , DerOrd , Encode , ErrorKind } ;
306
400
use core:: cmp:: Ordering ;
307
401
@@ -368,8 +462,22 @@ mod tests {
368
462
}
369
463
370
464
#[ test]
371
- fn reject_indefinite_lengths ( ) {
465
+ fn indefinite_lengths ( ) {
466
+ // DER disallows indefinite lengths
372
467
assert ! ( Length :: from_der( & [ 0x80 ] ) . is_err( ) ) ;
468
+
469
+ // The `IndefiniteLength` type supports them
470
+ let indefinite_length = IndefiniteLength :: from_der ( & [ 0x80 ] ) . unwrap ( ) ;
471
+ assert ! ( indefinite_length. is_indefinite( ) ) ;
472
+ assert_eq ! ( indefinite_length, IndefiniteLength :: INDEFINITE ) ;
473
+
474
+ // It also supports definite lengths.
475
+ let length = IndefiniteLength :: from_der ( & [ 0x83 , 0x01 , 0x00 , 0x00 ] ) . unwrap ( ) ;
476
+ assert ! ( length. is_definite( ) ) ;
477
+ assert_eq ! (
478
+ Length :: try_from( 0x10000u32 ) . unwrap( ) ,
479
+ length. try_into( ) . unwrap( )
480
+ ) ;
373
481
}
374
482
375
483
#[ test]
0 commit comments