Skip to content

Commit 1c2a141

Browse files
authored
Simplify reading lengths. (#318)
Limits the maximum TLV length to 65535. Idea stolen from ring.
1 parent b6c8e5a commit 1c2a141

File tree

1 file changed

+35
-30
lines changed

1 file changed

+35
-30
lines changed

src/parser.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ pub enum ParseErrorKind {
99
/// Something about the tag was invalid. This refers to a syntax error,
1010
/// not a tag's value being unexpected.
1111
InvalidTag,
12+
/// Something about the length was invalid. This can mean either a invalid
13+
/// encoding, or that a TLV was longer than 65535, which is the maximum
14+
/// length that rust-asn1 supports.
15+
InvalidLength,
1216
/// An unexpected tag was encountered.
1317
UnexpectedTag { actual: Tag },
1418
/// There was not enough data available to complete parsing.
@@ -112,6 +116,7 @@ impl fmt::Display for ParseError {
112116
match self.kind {
113117
ParseErrorKind::InvalidValue => write!(f, "invalid value"),
114118
ParseErrorKind::InvalidTag => write!(f, "invalid tag"),
119+
ParseErrorKind::InvalidLength => write!(f, "invalid length"),
115120
ParseErrorKind::UnexpectedTag { actual } => {
116121
write!(f, "unexpected tag (got {:?})", actual)
117122
}
@@ -201,34 +206,29 @@ impl<'a> Parser<'a> {
201206
}
202207

203208
fn read_length(&mut self) -> ParseResult<usize> {
204-
let b = self.read_u8()?;
205-
if b & 0x80 == 0 {
206-
return Ok(b as usize);
207-
}
208-
let num_bytes = b & 0x7f;
209-
// Indefinite length form is not valid DER
210-
if num_bytes == 0 {
211-
return Err(ParseError::new(ParseErrorKind::InvalidValue));
212-
}
213-
214-
let mut length = 0;
215-
for _ in 0..num_bytes {
216-
let b = self.read_u8()?;
217-
if length > (usize::max_value() >> 8) {
218-
return Err(ParseError::new(ParseErrorKind::IntegerOverflow));
209+
match self.read_u8()? {
210+
n if (n & 0x80) == 0 => Ok(usize::from(n)),
211+
0x81 => {
212+
let length = usize::from(self.read_u8()?);
213+
// Do not allow values <0x80 to be encoded using the long form
214+
if length < 0x80 {
215+
return Err(ParseError::new(ParseErrorKind::InvalidLength));
216+
}
217+
Ok(length)
219218
}
220-
length <<= 8;
221-
length |= b as usize;
222-
// Disallow leading 0s
223-
if length == 0 {
224-
return Err(ParseError::new(ParseErrorKind::InvalidValue));
219+
0x82 => {
220+
let length = usize::from(self.read_u8()?) << 8 | usize::from(self.read_u8()?);
221+
// Enforce that we're not using long form for values <0x80,
222+
// and that the first byte of the length is not zero (i.e.
223+
// that we're minimally encoded)
224+
if length < 0x100 {
225+
return Err(ParseError::new(ParseErrorKind::InvalidLength));
226+
}
227+
Ok(length)
225228
}
229+
// We only support two-byte lengths
230+
_ => Err(ParseError::new(ParseErrorKind::InvalidLength)),
226231
}
227-
// Do not allow values <0x80 to be encoded using the long form
228-
if length < 0x80 {
229-
return Err(ParseError::new(ParseErrorKind::InvalidValue));
230-
}
231-
Ok(length)
232232
}
233233

234234
#[inline]
@@ -404,6 +404,10 @@ mod tests {
404404
ParseError::new(ParseErrorKind::InvalidTag),
405405
"ASN.1 parsing error: invalid tag"
406406
),
407+
(
408+
ParseError::new(ParseErrorKind::InvalidLength),
409+
"ASN.1 parsing error: invalid length"
410+
),
407411
(
408412
ParseError::new(ParseErrorKind::IntegerOverflow),
409413
"ASN.1 parsing error: integer overflow"
@@ -619,15 +623,16 @@ mod tests {
619623
Ok(b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
620624
b"\x04\x81\x81aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
621625
),
622-
(Err(ParseError::new(ParseErrorKind::InvalidValue)), b"\x04\x80"),
623-
(Err(ParseError::new(ParseErrorKind::InvalidValue)), b"\x04\x81\x00"),
624-
(Err(ParseError::new(ParseErrorKind::InvalidValue)), b"\x04\x81\x01\x09"),
626+
(Err(ParseError::new(ParseErrorKind::InvalidLength)), b"\x04\x80"),
627+
(Err(ParseError::new(ParseErrorKind::InvalidLength)), b"\x04\x81\x00"),
628+
(Err(ParseError::new(ParseErrorKind::InvalidLength)), b"\x04\x81\x01\x09"),
629+
(Err(ParseError::new(ParseErrorKind::InvalidLength)), b"\x04\x82\x00\x80"),
625630
(
626-
Err(ParseError::new(ParseErrorKind::IntegerOverflow)),
631+
Err(ParseError::new(ParseErrorKind::InvalidLength)),
627632
b"\x04\x89\x01\x01\x01\x01\x01\x01\x01\x01\x01"
628633
),
629634
(Err(ParseError::new(ParseErrorKind::ShortData)), b"\x04\x03\x01\x02"),
630-
(Err(ParseError::new(ParseErrorKind::ShortData)), b"\x04\x83\xff\xff\xff\xff\xff\xff"),
635+
(Err(ParseError::new(ParseErrorKind::ShortData)), b"\x04\x82\xff\xff\xff\xff\xff\xff"),
631636
]);
632637
}
633638

0 commit comments

Comments
 (0)