Skip to content

Commit 54bb5d9

Browse files
authored
Merge pull request #10 from Devolutions/fuzzer
Add fuzzer + fix issues found using it
2 parents 9a1160e + ea01b4e commit 54bb5d9

33 files changed

+465
-187
lines changed

Cargo.lock

Lines changed: 17 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

picky-asn1-der/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Changelog
2+
3+
## [0.2.0] 2019-12-23
4+
5+
### Added
6+
7+
- Add `from_reader_with_max_len` deserialization function to limit how many bytes can be read at most.
8+
9+
### Changed
10+
11+
- `from_reader` function has a default limit of 10240 bytes before returning a truncated data error. Uses `from_reader_with_max_len` to change the limit.
12+
13+
### Fixed
14+
15+
- Fix various crash found by fuzzing.
16+

picky-asn1-der/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "picky-asn1-der"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
edition = "2018"
55
authors = [
66
"KizzyCode Software Labs./Keziah Biermann <[email protected]>",

picky-asn1-der/src/de/mod.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use picky_asn1::{tag::Tag, wrapper::*, Asn1Type};
1313
use serde::{de::Visitor, Deserialize};
1414
use std::io::{Cursor, Read};
1515

16+
const DEFAULT_MAX_LEN: usize = 10240;
17+
1618
/// Deserializes `T` from `bytes`
1719
pub fn from_bytes<'a, T: Deserialize<'a>>(bytes: &'a [u8]) -> Result<T> {
1820
debug_log!("deserialization using `from_bytes`");
@@ -22,8 +24,16 @@ pub fn from_bytes<'a, T: Deserialize<'a>>(bytes: &'a [u8]) -> Result<T> {
2224

2325
/// Deserializes `T` from `reader`
2426
pub fn from_reader<'a, T: Deserialize<'a>>(reader: impl Read + 'a) -> Result<T> {
25-
debug_log!("deserialization using `from_reader`");
26-
let mut deserializer = Deserializer::new_from_reader(reader);
27+
from_reader_with_max_len(reader, DEFAULT_MAX_LEN)
28+
}
29+
30+
/// Deserializes `T` from `reader` reading at most n bytes.
31+
pub fn from_reader_with_max_len<'a, T: Deserialize<'a>>(reader: impl Read + 'a, max_len: usize) -> Result<T> {
32+
debug_log!(
33+
"deserialization using `from_reader_with_max_len`, max_len = {}",
34+
max_len
35+
);
36+
let mut deserializer = Deserializer::new_from_reader(reader, max_len);
2737
T::deserialize(&mut deserializer)
2838
}
2939

@@ -33,20 +43,22 @@ pub struct Deserializer<'de> {
3343
buf: Vec<u8>,
3444
encapsulator_tag_stack: Vec<Tag>,
3545
header_only: bool,
46+
max_len: usize,
3647
}
3748

3849
impl<'de> Deserializer<'de> {
3950
/// Creates a new deserializer over `bytes`
4051
pub fn new_from_bytes(bytes: &'de [u8]) -> Self {
41-
Self::new_from_reader(Cursor::new(bytes))
52+
Self::new_from_reader(Cursor::new(bytes), bytes.len())
4253
}
4354
/// Creates a new deserializer for `reader`
44-
pub fn new_from_reader(reader: impl Read + 'de) -> Self {
55+
pub fn new_from_reader(reader: impl Read + 'de, max_len: usize) -> Self {
4556
Self {
4657
reader: PeekableReader::new(Box::new(reader)),
4758
buf: Vec::new(),
4859
encapsulator_tag_stack: Vec::with_capacity(3),
4960
header_only: false,
61+
max_len,
5062
}
5163
}
5264

@@ -74,8 +86,13 @@ impl<'de> Deserializer<'de> {
7486
(tag, len)
7587
};
7688

89+
if len > self.max_len {
90+
debug_log!("TRUNCATED DATA (invalid len: found {}, max is {})", len, self.max_len);
91+
return Err(Asn1DerError::TruncatedData);
92+
}
93+
7794
self.buf.resize(len, 0);
78-
self.reader.read_exact(&mut self.buf)?;
95+
self.reader.read_exact(self.buf.as_mut_slice())?;
7996

8097
Ok(tag)
8198
}
@@ -122,7 +139,7 @@ impl<'de> Deserializer<'de> {
122139
};
123140
}
124141

125-
if peeked.len() < cursor {
142+
if peeked.len() <= cursor {
126143
debug_log!("peek_object: TRUNCATED DATA (couldn't read object tag)");
127144
return Err(Asn1DerError::TruncatedData);
128145
}

picky-asn1-der/src/de/sequence.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ pub struct Sequence<'a, 'de> {
66
de: &'a mut Deserializer<'de>,
77
len: usize,
88
}
9+
910
impl<'a, 'de> Sequence<'a, 'de> {
1011
/// Creates a lazy deserializer that can walk through the sequence's sub-elements
1112
pub fn deserialize_lazy(de: &'a mut Deserializer<'de>, len: usize) -> Self {
1213
Self { de, len }
1314
}
1415
}
16+
1517
impl<'a, 'de> SeqAccess<'de> for Sequence<'a, 'de> {
1618
type Error = Asn1DerError;
1719

@@ -24,7 +26,13 @@ impl<'a, 'de> SeqAccess<'de> for Sequence<'a, 'de> {
2426
// Deserialize the element
2527
let pos = self.de.reader.pos();
2628
let element = seed.deserialize(&mut *self.de)?;
27-
self.len -= self.de.reader.pos() - pos;
29+
30+
let read = self.de.reader.pos() - pos;
31+
if self.len < read {
32+
debug_log!("TRUNCATED DATA (read more than necessary??)");
33+
return Err(Asn1DerError::TruncatedData);
34+
}
35+
self.len -= read;
2836

2937
Ok(Some(element))
3038
}

picky-asn1-der/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ mod misc;
7777
mod ser;
7878

7979
pub use crate::{
80-
de::{from_bytes, from_reader, Deserializer},
80+
de::{from_bytes, from_reader, from_reader_with_max_len, Deserializer},
8181
ser::{to_byte_buf, to_bytes, to_vec, to_writer, Serializer},
8282
};
8383

picky-asn1-der/src/ser/sequence.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub struct Sequence<'a, 'se> {
1313
buf: Cursor<Vec<u8>>,
1414
tag: Tag,
1515
}
16+
1617
impl<'a, 'se> Sequence<'a, 'se> {
1718
/// Creates a lazy serializer that will serialize the sequence's sub-elements to `writer`
1819
pub fn serialize_lazy(ser: &'a mut Serializer<'se>, tag: Tag) -> Self {
@@ -28,6 +29,7 @@ impl<'a, 'se> Sequence<'a, 'se> {
2829
to_writer(value, &mut self.buf)?;
2930
Ok(())
3031
}
32+
3133
/// Finalizes the sequence
3234
fn finalize(self) -> Result<usize> {
3335
// Reclaim buffer
@@ -39,6 +41,7 @@ impl<'a, 'se> Sequence<'a, 'se> {
3941
Ok(written)
4042
}
4143
}
44+
4245
impl<'a, 'se> serde::ser::SerializeSeq for Sequence<'a, 'se> {
4346
type Ok = usize;
4447
type Error = Asn1DerError;
@@ -50,6 +53,7 @@ impl<'a, 'se> serde::ser::SerializeSeq for Sequence<'a, 'se> {
5053
self.finalize()
5154
}
5255
}
56+
5357
impl<'a, 'se> serde::ser::SerializeTuple for Sequence<'a, 'se> {
5458
type Ok = usize;
5559
type Error = Asn1DerError;
@@ -61,6 +65,7 @@ impl<'a, 'se> serde::ser::SerializeTuple for Sequence<'a, 'se> {
6165
self.finalize()
6266
}
6367
}
68+
6469
impl<'a, 'se> serde::ser::SerializeStruct for Sequence<'a, 'se> {
6570
type Ok = usize;
6671
type Error = Asn1DerError;
@@ -72,6 +77,7 @@ impl<'a, 'se> serde::ser::SerializeStruct for Sequence<'a, 'se> {
7277
self.finalize()
7378
}
7479
}
80+
7581
impl<'a, 'se> serde::ser::SerializeTupleStruct for Sequence<'a, 'se> {
7682
type Ok = usize;
7783
type Error = Asn1DerError;

picky-server/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "picky-server"
3-
version = "4.2.0"
3+
version = "4.2.1"
44
authors = [
55
"jtrepanier-devolutions <[email protected]>",
66
"Benoît CORTIER <[email protected]>",
@@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0"
1111
repository = "https://github.com/Devolutions/picky-rs"
1212

1313
[dependencies]
14-
picky = { version = "4.2", default-features = false, features = ["x509", "chrono_conversion"] }
14+
picky = { version = "4.5", default-features = false, features = ["x509", "chrono_conversion"] }
1515
picky-asn1 = "0.1"
1616
mongodb = { package = "mongodb_cwal", version = "0.6", features = ["ssl"] }
1717
curl = { git = "https://github.com/Devolutions/curl-rust", branch = "wayk" }

picky-server/src/picky_controller.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use picky::{
2-
key::{KeyError, OwnedPublicKey, PrivateKey},
2+
key::{KeyError, PrivateKey, PublicKey},
33
oids,
44
pem::PemError,
55
signature::SignatureHashType,
@@ -83,7 +83,7 @@ impl Picky {
8383

8484
pub fn generate_intermediate(
8585
intermediate_name: &str,
86-
intermediate_key: OwnedPublicKey,
86+
intermediate_key: PublicKey,
8787
issuer_cert: &Cert,
8888
issuer_key: &PrivateKey,
8989
signature_hash_type: SignatureHashType,

picky/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "picky"
3-
version = "4.4.2"
3+
version = "4.5.0"
44
authors = [
55
"jtrepanier-devolutions <[email protected]>",
66
"Benoît CORTIER <[email protected]>",
@@ -12,7 +12,7 @@ repository = "https://github.com/Devolutions/picky-rs"
1212

1313
[dependencies]
1414
picky-asn1 = "0.1"
15-
picky-asn1-der = "0.1"
15+
picky-asn1-der = "0.2"
1616
serde = { version = "1.0", features = ["derive"] }
1717
oid = { version = "^0.1.1", features = ["serde_support"] }
1818
base64 = "0.10"

0 commit comments

Comments
 (0)