aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2021-08-11 16:13:31 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-08-11 16:13:31 +0000
commit8a9d08102c0bfecc31490086c638aed5aec660c7 (patch)
treeaf1fe68b60da42b29f3da153cc234358a765fc17
parentdbab207c1943ec31e6a08fa561337eac4b6c5bbe (diff)
parentb83de0384b622c77d95b5675b92a7725df4352ba (diff)
downloadder-parser-8a9d08102c0bfecc31490086c638aed5aec660c7.tar.gz
Merge "Revert "Upgrade rust/crates/der-parser to 5.1.2"" am: b83de0384b
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/der-parser/+/1792934 Change-Id: I01d7f60394dda1e6854e56edc9337249af781a29
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp1
-rw-r--r--CHANGELOG.md16
-rw-r--r--Cargo.toml88
-rw-r--r--Cargo.toml.orig52
-rw-r--r--METADATA9
-rw-r--r--README.md24
-rw-r--r--benches/bench.rs101
-rw-r--r--cargo2android.json2
-rw-r--r--der-oid-macro/Cargo.toml18
-rw-r--r--der-oid-macro/src/lib.rs139
-rw-r--r--fuzz/.gitignore5
-rw-r--r--fuzz/Cargo.toml30
-rw-r--r--fuzz/fuzz_targets/fuzz_parse_ber.rs8
-rw-r--r--fuzz/fuzz_targets/fuzz_parse_der.rs8
-rw-r--r--patches/bitvec_dep.patch8
-rw-r--r--src/ber/ber.rs218
-rw-r--r--src/ber/integer.rs130
-rw-r--r--src/ber/mod.rs6
-rw-r--r--src/ber/parser.rs70
-rw-r--r--src/ber/print.rs13
-rw-r--r--src/ber/serialize.rs8
-rw-r--r--src/der/mod.rs4
-rw-r--r--src/der/parser.rs68
-rw-r--r--src/error.rs14
-rw-r--r--src/lib.rs31
-rw-r--r--src/oid.rs30
-rw-r--r--tests/ber_parser.rs83
-rw-r--r--tests/der_parser.rs28
-rw-r--r--tests/macros.rs1
-rw-r--r--tests/oid.rs1
-rw-r--r--tests/primitive.rs1
32 files changed, 540 insertions, 677 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index d5c766e..3c083e8 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "c8adf28076c11651618bcf414a20ecd0bd896315"
+ "sha1": "ebbea4bd6d42ad878ca2b9cdc53291f4ae19481a"
}
}
diff --git a/Android.bp b/Android.bp
index bd24618..c0d3541 100644
--- a/Android.bp
+++ b/Android.bp
@@ -48,6 +48,7 @@ rust_library {
features: [
"bigint",
"num-bigint",
+ "std",
],
rustlibs: [
"libnom",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4bc3295..3f676f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,22 +8,6 @@
### Thanks
-## 5.1.2
-
-### Changed/Fixed
-
-- Make `BerError` Copy + Clone
-- Fix clippy warnings (rustc 1.54)
-
-## 5.1.1
-
-### Changed/Fixed
-
-- BER: raise error if using Indefinite length and not constructed
-- Fix `INTEGER` signed/unsigned parsing (#49)
-- Fix INTEGER signed/unsigned parsing for bigint/biguint (#49)
-- Doc: clarify documentation for parsing integers (#49)
-
## 5.1.0
### Changed/Fixed
diff --git a/Cargo.toml b/Cargo.toml
index 9715d20..a0a1bcd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,61 +1,53 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
[package]
-edition = "2018"
-name = "der-parser"
-version = "5.1.2"
-authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"]
-include = ["LICENSE-*", "CHANGELOG.md", "README.md", "UPGRADING.md", ".gitignore", "Cargo.toml", "bench/*.rs", "src/*.rs", "src/ber/*.rs", "src/der/*.rs", "tests/*.rs", "der-oid-macro/Cargo.toml", "der-oid-macro/src/*.rs"]
description = "Parser/encoder for ASN.1 BER/DER data"
-homepage = "https://github.com/rusticata/der-parser"
-readme = "README.md"
-keywords = ["BER", "DER", "ASN1", "parser", "nom"]
-categories = ["parser-implementations"]
license = "MIT/Apache-2.0"
+keywords = ["BER","DER","ASN1","parser","nom"]
+homepage = "https://github.com/rusticata/der-parser"
repository = "https://github.com/rusticata/der-parser.git"
+name = "der-parser"
+version = "5.1.0"
+authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"]
+categories = ["parser-implementations"]
+readme = "README.md"
+edition = "2018"
+
+include = [
+ "LICENSE-*",
+ "CHANGELOG.md",
+ "README.md",
+ "UPGRADING.md",
+ ".gitignore",
+ "Cargo.toml",
+ "bench/*.rs",
+ "src/*.rs",
+ "src/ber/*.rs",
+ "src/der/*.rs",
+ "tests/*.rs",
+ "der-oid-macro/Cargo.toml",
+ "der-oid-macro/src/*.rs",
+]
+
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
-[dependencies.cookie-factory]
-version = "0.3.0"
-optional = true
-
-[dependencies.der-oid-macro]
-version = "0.4"
-[dependencies.nom]
-version = "6.0"
+[dependencies]
+cookie-factory = { version="0.3.0", optional=true }
+nom = "6.0"
+rusticata-macros = "3.1"
+num-traits = "0.2"
+num-bigint = { version = "0.4", optional = true }
-[dependencies.num-bigint]
-version = "0.4"
-optional = true
-
-[dependencies.num-traits]
-version = "0.2"
-
-[dependencies.rusticata-macros]
-version = "3.0.1"
-[dev-dependencies.hex-literal]
-version = "0.3"
-
-[dev-dependencies.pretty_assertions]
-version = "0.7"
-
-[dev-dependencies.test-case]
-version = "1.0"
+der-oid-macro = { version = "0.4", path = "./der-oid-macro" }
[features]
+default = ["std"]
bigint = ["num-bigint"]
-default = []
-serialize = ["cookie-factory"]
+serialize = ["std", "cookie-factory"]
unstable = []
+std = []
+
+[dev-dependencies]
+hex-literal = "0.3"
+pretty_assertions = "0.7"
+test-case = "1.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
deleted file mode 100644
index e2a6c3f..0000000
--- a/Cargo.toml.orig
+++ /dev/null
@@ -1,52 +0,0 @@
-[package]
-description = "Parser/encoder for ASN.1 BER/DER data"
-license = "MIT/Apache-2.0"
-keywords = ["BER","DER","ASN1","parser","nom"]
-homepage = "https://github.com/rusticata/der-parser"
-repository = "https://github.com/rusticata/der-parser.git"
-name = "der-parser"
-version = "5.1.2"
-authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"]
-categories = ["parser-implementations"]
-readme = "README.md"
-edition = "2018"
-
-include = [
- "LICENSE-*",
- "CHANGELOG.md",
- "README.md",
- "UPGRADING.md",
- ".gitignore",
- "Cargo.toml",
- "bench/*.rs",
- "src/*.rs",
- "src/ber/*.rs",
- "src/der/*.rs",
- "tests/*.rs",
- "der-oid-macro/Cargo.toml",
- "der-oid-macro/src/*.rs",
-]
-
-[package.metadata.docs.rs]
-all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
-
-[dependencies]
-cookie-factory = { version="0.3.0", optional=true }
-nom = "6.0"
-rusticata-macros = "3.0.1"
-num-traits = "0.2"
-num-bigint = { version = "0.4", optional = true }
-
-der-oid-macro = { version = "0.4", path = "./der-oid-macro" }
-
-[features]
-default = []
-bigint = ["num-bigint"]
-serialize = ["cookie-factory"]
-unstable = []
-
-[dev-dependencies]
-hex-literal = "0.3"
-pretty_assertions = "0.7"
-test-case = "1.0"
diff --git a/METADATA b/METADATA
index c3a9cdb..33a289f 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,14 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/der-parser/der-parser-5.1.2.crate"
+ value: "https://static.crates.io/crates/der-parser/der-parser-5.1.0.crate"
}
- version: "5.1.2"
+ version: "5.1.0"
+ # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same.
license_type: NOTICE
last_upgrade_date {
year: 2021
- month: 8
- day: 9
+ month: 7
+ day: 20
}
}
diff --git a/README.md b/README.md
index 03f33bc..739c96f 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[![docs.rs](https://docs.rs/der-parser/badge.svg)](https://docs.rs/der-parser)
[![crates.io](https://img.shields.io/crates/v/der-parser.svg)](https://crates.io/crates/der-parser)
[![Download numbers](https://img.shields.io/crates/d/der-parser.svg)](https://crates.io/crates/der-parser)
-[![dependency status](https://deps.rs/crate/der-parser/5.1.2/status.svg)](https://deps.rs/crate/der-parser/5.1.2)
+[![dependency status](https://deps.rs/crate/der-parser/5.0.0/status.svg)](https://deps.rs/crate/der-parser/5.0.1)
[![Github CI](https://github.com/rusticata/der-parser/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/der-parser/actions)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.44.0+-lightgray.svg)](#rust-version-requirements)
@@ -47,7 +47,7 @@ See the related modules for object definitions, functions, and example:
## Examples
-Parse two BER integers (see [BER/DER Integers](#berder-integers)):
+Parse two BER integers:
```rust
use der_parser::ber::parse_ber_integer;
@@ -151,19 +151,10 @@ Note that this type is also a `Result`, so usual functions (`map`, `unwrap` etc.
DER integers can be of any size, so it is not possible to store them as simple integers (they
are stored as raw bytes).
-Note that, by default, BER/DER integers are signed. Functions are provided to request reading
-unsigned values, but they will fail if the integer value is negative.
-
-To get the integer value for all possible integer sign and size, use
-[`BerObject::as_bigint`](https://docs.rs/der-parser/latest/der_parser/ber/struct.BerObject.html#method.as_bigint)) (requires the `bigint` feature).
-
-To get a simple value expected to be in a known range, use methods like
-[`BerObject::as_i32`](ber/struct.BerObject.html#method.as_i32)) and
-[`BerObject::as_i64`](ber/struct.BerObject.html#method.as_i64) (or the unsigned versions
-[`BerObject::as_u32`](ber/struct.BerObject.html#method.as_u32) and
-[`BerObject::as_u64`](ber/struct.BerObject.html#method.as_u64)
-),
-which will return the value, or an error if the integer is too large (or is negative).
+To get a simple value, use [`BerObject::as_u32`](ber/struct.BerObject.html#method.as_u32)
+(knowning that this method will return an error if the integer is too large),
+[`BerObject::as_u64`](ber/struct.BerObject.html#method.as_u64), or use the `bigint` feature of
+this crate and use [`BerObject::as_bigint`](https://docs.rs/der-parser/latest/der_parser/ber/struct.BerObject.html#method.as_bigint).
```rust
use der_parser::ber::*;
@@ -172,9 +163,6 @@ let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
let (_, object) = parse_ber_integer(data).expect("parsing failed");
assert_eq!(object.as_u64(), Ok(65537));
-
-#[cfg(feature = "bigint")]
-assert_eq!(object.as_bigint(), Some(65537.into()))
```
Access to the raw value is possible using the `as_slice` method.
diff --git a/benches/bench.rs b/benches/bench.rs
new file mode 100644
index 0000000..5a0616e
--- /dev/null
+++ b/benches/bench.rs
@@ -0,0 +1,101 @@
+#![cfg(feature = "unstable")]
+#![cfg(all(feature = "unstable", test))]
+#![feature(test)]
+
+extern crate test;
+use test::Bencher;
+
+use der_parser::ber::{BerClass, BerObjectHeader, BerTag};
+use der_parser::der::{
+ der_read_element_header, parse_der, parse_der_integer, parse_der_u32, DerObject,
+};
+use der_parser::error::DerResult;
+use der_parser::*;
+use hex_literal::hex;
+use nom::{map, map_res};
+
+#[bench]
+fn bench_der_read_element_header(b: &mut Bencher) {
+ let bytes = hex!("0c 0a 53 6f 6d 65 2d 53 74 61 74 65");
+ b.iter(|| {
+ let res = der_read_element_header(&bytes);
+ match res {
+ Ok((_rem, hdr)) => {
+ assert_eq!(
+ hdr,
+ BerObjectHeader::new(BerClass::Universal, 0, BerTag(12), 10)
+ .with_raw_tag(Some(&[0xc]))
+ );
+ }
+ _ => assert!(false),
+ }
+ });
+}
+
+#[bench]
+fn bench_der_map_res_integer_u32(b: &mut Bencher) {
+ let bytes = hex!("02 04 01 23 45 67");
+ b.iter(|| {
+ let res = map_res!(&bytes as &[u8], parse_der_integer, |x: DerObject| x
+ .as_u32());
+ match res {
+ Ok((_rem, i)) => {
+ assert_eq!(i, 0x0123_4567);
+ }
+ _ => assert!(false),
+ }
+ });
+}
+
+#[bench]
+fn bench_parse_der_u32(b: &mut Bencher) {
+ let bytes = hex!("02 04 01 23 45 67");
+ b.iter(|| {
+ let res = parse_der_u32(&bytes);
+ match res {
+ Ok((_rem, i)) => {
+ assert_eq!(i, 0x0123_4567);
+ }
+ _ => assert!(false),
+ }
+ });
+}
+
+#[bench]
+fn bench_parse_der_seq(b: &mut Bencher) {
+ let bytes = hex!("30 0a 02 03 01 00 01 02 03 01 00 00");
+ b.iter(|| {
+ let res = parse_der(&bytes);
+ let expected = DerObject::from_seq(vec![
+ DerObject::from_int_slice(b"\x01\x00\x01"),
+ DerObject::from_int_slice(b"\x01\x00\x00"),
+ ]);
+ match res {
+ Ok((_rem, i)) => {
+ assert_eq!(i, expected);
+ }
+ _ => assert!(false),
+ }
+ });
+}
+
+#[bench]
+fn bench_parse_der_seq_macros(b: &mut Bencher) {
+ fn localparse_seq(i: &[u8]) -> DerResult {
+ parse_der_sequence_defined!(i, parse_der_integer >> parse_der_integer)
+ }
+ let bytes = hex!("30 0a 02 03 01 00 01 02 03 01 00 00");
+ b.iter(|| {
+ let res = localparse_seq(&bytes);
+ let expected = DerObject::from_seq(vec![
+ DerObject::from_int_slice(b"\x01\x00\x01"),
+ DerObject::from_int_slice(b"\x01\x00\x00"),
+ ]);
+ match res {
+ Ok((_rem, i)) => {
+ assert_eq!(i, expected);
+ }
+ _ => assert!(false),
+ }
+ });
+}
diff --git a/cargo2android.json b/cargo2android.json
index fd3c228..323332c 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,6 +1,6 @@
{
"device": true,
- "features": "bigint",
+ "features": "std,bigint",
"run": true
}
diff --git a/der-oid-macro/Cargo.toml b/der-oid-macro/Cargo.toml
new file mode 100644
index 0000000..fbf8a6f
--- /dev/null
+++ b/der-oid-macro/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "der-oid-macro"
+description = "Macro to encode DER oids at compile time"
+version = "0.4.0"
+edition = "2018"
+license = "MIT/Apache-2.0"
+homepage = "https://github.com/rusticata/der-parser"
+repository = "https://github.com/rusticata/der-parser.git"
+authors = ["Pierre Chifflier <chifflier@wzdftpd.net>", "Jannik Schürg <schuerg@ins.uni-bonn.de>"]
+
+[lib]
+proc-macro = true
+
+[dependencies]
+nom = "6.0"
+num-bigint = "0.4"
+num-traits = "0.2"
+syn = "1.0"
diff --git a/der-oid-macro/src/lib.rs b/der-oid-macro/src/lib.rs
new file mode 100644
index 0000000..e12a16b
--- /dev/null
+++ b/der-oid-macro/src/lib.rs
@@ -0,0 +1,139 @@
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+fn parse_arg(arg: &str) -> (bool, bool, Vec<&str>) {
+ use nom::{
+ bytes::complete::{tag, take_while},
+ call,
+ character::complete::{char, digit1},
+ combinator::{map, opt, recognize, verify},
+ error::{ErrorKind, ParseError},
+ exact,
+ multi::separated_list1,
+ sequence::{delimited, terminated, tuple},
+ IResult,
+ };
+
+ fn uint<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
+ verify(recognize(separated_list1(char('_'), digit1)), |s: &str| {
+ s.len() == 1 || !s.starts_with('0')
+ })(i)
+ }
+
+ fn ws<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
+ take_while(|c| c == ' ')(i)
+ }
+
+ fn ws_dot_ws<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, char, E> {
+ delimited(ws, char('.'), ws)(i)
+ }
+
+ fn root<'a, E: ParseError<&'a str>>(
+ i: &'a str,
+ ) -> IResult<&'a str, (bool, bool, Vec<&'a str>), E> {
+ tuple((
+ map(opt(terminated(tag("raw "), ws)), |x| x.is_some()),
+ map(opt(terminated(tag("rel "), ws)), |x| x.is_some()),
+ separated_list1(ws_dot_ws, uint),
+ ))(i)
+ }
+
+ exact!(arg.trim(), call!(root::<(&str, ErrorKind)>))
+ .expect("could not parse oid")
+ .1
+}
+
+fn encode_components(components: &[num_bigint::BigUint], relative: bool) -> Vec<u8> {
+ use num_traits::cast::ToPrimitive;
+
+ let mut enc = Vec::new();
+ let mut dec = components;
+ if !relative {
+ if dec.len() < 2 {
+ if dec.len() == 1 && dec[0] == 0u8.into() {
+ return vec![0];
+ }
+ panic!("Need at least two components for non-relative oid");
+ }
+ if dec[0] >= 7u8.into() || dec[1] >= 40u8.into() {
+ panic!("First components are too big");
+ }
+ enc.push(dec[0].to_u8().unwrap() * 40 + dec[1].to_u8().unwrap());
+ dec = &dec[2..];
+ }
+
+ for int in dec.iter() {
+ let mut bytes = int.to_bytes_be();
+ if bytes[0] == 0 {
+ enc.push(0u8);
+ continue;
+ }
+ let total_bits = (8 - bytes[0].leading_zeros()) as usize + (bytes.len() - 1) * 8;
+ let octects_needed = ((total_bits + 6) / 7).max(1);
+ enc.resize_with(enc.len() + octects_needed, Default::default);
+
+ let mut pos = enc.len() - 1;
+ let mut extra = 0u8;
+ let mut extra_size = 0u8;
+ bytes.reverse();
+ let mut bytes_stored = 0;
+ for byte in bytes.into_iter() {
+ if extra_size == 7 {
+ // there a seven bits in extra
+ enc[pos] = extra | (1 << 7);
+ bytes_stored += 1;
+ pos -= 1;
+ extra = 0;
+ extra_size = 0;
+ }
+ // make space for the extra bits
+ enc[pos] = (byte << extra_size) | extra | (1 << 7);
+ bytes_stored += 1;
+ if pos > 0 {
+ pos -= 1;
+ extra_size += 1;
+ extra = byte >> (8 - extra_size);
+ }
+ }
+ let last = enc.len() - 1;
+ if bytes_stored != octects_needed {
+ let first = last + 1 - octects_needed;
+ enc[first] = extra | (1 << 7);
+ }
+ enc[last] ^= 1 << 7;
+ }
+ enc
+}
+
+#[proc_macro]
+pub fn oid(item: TokenStream) -> TokenStream {
+ let arg = item.to_string();
+ let (raw, relative, int_strings) = parse_arg(&arg);
+ let ints: Vec<num_bigint::BigUint> = int_strings
+ .into_iter()
+ .map(|s| s.parse().unwrap())
+ .collect();
+ let enc = encode_components(&ints, relative);
+
+ let mut s = String::with_capacity(2 + 6 * enc.len());
+ s.push('[');
+ for byte in enc.iter() {
+ s.insert_str(s.len(), &format!("0x{:02x}, ", byte));
+ }
+ s.push(']');
+
+ let code = if raw {
+ format!("{{extern crate alloc; {}}}", s)
+ } else if relative {
+ format!(
+ "{{extern crate alloc; der_parser::oid::Oid::new_relative(alloc::borrow::Cow::Borrowed(&{}))}}",
+ s
+ )
+ } else {
+ format!(
+ "{{extern crate alloc; der_parser::oid::Oid::new(alloc::borrow::Cow::Borrowed(&{}))}}",
+ s
+ )
+ };
+ code.parse().unwrap()
+}
diff --git a/fuzz/.gitignore b/fuzz/.gitignore
new file mode 100644
index 0000000..dfeb7db
--- /dev/null
+++ b/fuzz/.gitignore
@@ -0,0 +1,5 @@
+
+target
+libfuzzer
+corpus
+artifacts
diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml
new file mode 100644
index 0000000..f85b6c9
--- /dev/null
+++ b/fuzz/Cargo.toml
@@ -0,0 +1,30 @@
+
+[package]
+name = "der-parser-fuzz"
+version = "0.0.1"
+authors = ["Automatically generated"]
+publish = false
+
+[package.metadata]
+cargo-fuzz = true
+
+[dependencies.der-parser]
+path = ".."
+[dependencies.libfuzzer-sys]
+git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
+
+# Prevent this from interfering with workspaces
+[workspace]
+members = ["."]
+
+[[bin]]
+name = "fuzz_parse_der"
+path = "fuzz_targets/fuzz_parse_der.rs"
+test = false
+doc = false
+
+[[bin]]
+name = "fuzz_parse_ber"
+path = "fuzz_targets/fuzz_parse_ber.rs"
+test = false
+doc = false
diff --git a/fuzz/fuzz_targets/fuzz_parse_ber.rs b/fuzz/fuzz_targets/fuzz_parse_ber.rs
new file mode 100644
index 0000000..bd4c55c
--- /dev/null
+++ b/fuzz/fuzz_targets/fuzz_parse_ber.rs
@@ -0,0 +1,8 @@
+#![no_main]
+extern crate libfuzzer_sys;
+use libfuzzer_sys::fuzz_target;
+
+fuzz_target!(|data: &[u8]| {
+ // fuzzed code goes here
+ let _ = der_parser::parse_ber(data);
+});
diff --git a/fuzz/fuzz_targets/fuzz_parse_der.rs b/fuzz/fuzz_targets/fuzz_parse_der.rs
new file mode 100644
index 0000000..267baa5
--- /dev/null
+++ b/fuzz/fuzz_targets/fuzz_parse_der.rs
@@ -0,0 +1,8 @@
+#![no_main]
+extern crate libfuzzer_sys;
+extern crate der_parser;
+#[export_name="rust_fuzzer_test_input"]
+pub extern fn go(data: &[u8]) {
+ // fuzzed code goes here
+ let _ = der_parser::parse_der(data);
+}
diff --git a/patches/bitvec_dep.patch b/patches/bitvec_dep.patch
index 40bad0b..d38d8aa 100644
--- a/patches/bitvec_dep.patch
+++ b/patches/bitvec_dep.patch
@@ -3,13 +3,13 @@ index 6f6741d..e89b6c8 100644
--- a/src/ber/ber.rs
+++ b/src/ber/ber.rs
@@ -9,6 +9,7 @@ use core::convert::From;
- use crate::ber::integer::*;
- use crate::error::BerError;
- use crate::oid::Oid;
+ use core::convert::TryFrom;
+ use core::fmt;
+ use core::ops::Index;
+#[cfg(not(any(target_os = "android", target_os = "linux")))]
use nom::bitvec::{order::Msb0, slice::BitSlice};
use rusticata_macros::newtype_enum;
- use std::convert::AsRef;
+
@@ -479,6 +480,7 @@ impl<'a> BerObject<'a> {
}
diff --git a/src/ber/ber.rs b/src/ber/ber.rs
index e7bd384..e89b6c8 100644
--- a/src/ber/ber.rs
+++ b/src/ber/ber.rs
@@ -1,16 +1,17 @@
-use crate::ber::bitstring_to_u64;
-use crate::ber::integer::*;
+use crate::ber::{bitstring_to_u64, bytes_to_u64};
use crate::error::BerError;
use crate::oid::Oid;
+use alloc::borrow::ToOwned;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::convert::AsRef;
+use core::convert::From;
+use core::convert::TryFrom;
+use core::fmt;
+use core::ops::Index;
#[cfg(not(any(target_os = "android", target_os = "linux")))]
use nom::bitvec::{order::Msb0, slice::BitSlice};
use rusticata_macros::newtype_enum;
-use std::convert::AsRef;
-use std::convert::From;
-use std::convert::TryFrom;
-use std::fmt;
-use std::ops::Index;
-use std::vec::Vec;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct BerClassFromIntError(pub(crate) ());
@@ -183,6 +184,8 @@ pub enum BerObjectContent<'a> {
Optional(Option<Box<BerObject<'a>>>),
/// Tagged object (EXPLICIT): class, tag and content of inner object
Tagged(BerClass, BerTag, Box<BerObject<'a>>),
+ /// Private
+ Private(BerObjectHeader<'a>, &'a [u8]),
/// Unknown object: object tag (copied from header), and raw content
Unknown(BerTag, &'a [u8]),
@@ -400,47 +403,8 @@ impl<'a> BerObject<'a> {
self.header.clone()
}
- /// Attempt to read a signed integer value from DER object.
- ///
- /// This can fail if the object is not an integer, or if it is too large.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use der_parser::ber::BerObject;
- /// let der_int = BerObject::from_int_slice(b"\x80");
- /// assert_eq!(
- /// der_int.as_i64(),
- /// Ok(-128)
- /// );
- /// ```
- pub fn as_i64(&self) -> Result<i64, BerError> {
- self.content.as_i64()
- }
-
- /// Attempt to read a signed integer value from DER object.
- ///
- /// This can fail if the object is not an integer, or if it is too large.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use der_parser::ber::BerObject;
- /// let der_int = BerObject::from_int_slice(b"\x80");
- /// assert_eq!(
- /// der_int.as_i32(),
- /// Ok(-128)
- /// );
- /// ```
- pub fn as_i32(&self) -> Result<i32, BerError> {
- self.content.as_i32()
- }
-
/// Attempt to read integer value from DER object.
- ///
- /// This can fail if the object is not an unsigned integer, or if it is too large.
- ///
- /// # Examples
+ /// This can fail if the object is not an integer, or if it is too large.
///
/// ```rust
/// # use der_parser::ber::BerObject;
@@ -455,10 +419,7 @@ impl<'a> BerObject<'a> {
}
/// Attempt to read integer value from DER object.
- ///
- /// This can fail if the object is not an unsigned integer, or if it is too large.
- ///
- /// # Examples
+ /// This can fail if the object is not an integer, or if it is too large.
///
/// ```rust
/// # extern crate der_parser;
@@ -630,80 +591,9 @@ impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> {
}
impl<'a> BerObjectContent<'a> {
- /// Attempt to read a signed integer value from this object.
- ///
- /// This can fail if the object is not an integer, or if it is too large.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use der_parser::ber::BerObject;
- /// let der_int = BerObject::from_int_slice(b"\x80");
- /// assert_eq!(
- /// der_int.as_i64(),
- /// Ok(-128)
- /// );
- /// ```
- pub fn as_i64(&self) -> Result<i64, BerError> {
- if let BerObjectContent::Integer(bytes) = self {
- let result = if is_highest_bit_set(bytes) {
- <i64>::from_be_bytes(decode_array_int8(bytes)?)
- } else {
- <u64>::from_be_bytes(decode_array_uint8(bytes)?) as i64
- };
- Ok(result)
- } else {
- Err(BerError::InvalidTag)
- }
- }
-
- /// Attempt to read a signed integer value from this object.
- ///
- /// This can fail if the object is not an integer, or if it is too large.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use der_parser::ber::BerObject;
- /// let der_int = BerObject::from_int_slice(b"\x80");
- /// assert_eq!(
- /// der_int.as_i32(),
- /// Ok(-128)
- /// );
- /// ```
- pub fn as_i32(&self) -> Result<i32, BerError> {
- if let BerObjectContent::Integer(bytes) = self {
- let result = if is_highest_bit_set(bytes) {
- <i32>::from_be_bytes(decode_array_int4(bytes)?)
- } else {
- <u32>::from_be_bytes(decode_array_uint4(bytes)?) as i32
- };
- Ok(result)
- } else {
- Err(BerError::InvalidTag)
- }
- }
-
- /// Attempt to read integer value from this object.
- ///
- /// This can fail if the object is not an unsigned integer, or if it is too large.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # use der_parser::ber::BerObject;
- /// let der_int = BerObject::from_int_slice(b"\x01\x00\x01");
- /// assert_eq!(
- /// der_int.as_u64(),
- /// Ok(0x10001)
- /// );
- /// ```
pub fn as_u64(&self) -> Result<u64, BerError> {
match self {
- BerObjectContent::Integer(i) => {
- let result = <u64>::from_be_bytes(decode_array_uint8(i)?);
- Ok(result)
- }
+ BerObjectContent::Integer(i) => bytes_to_u64(i),
BerObjectContent::BitString(ignored_bits, data) => {
bitstring_to_u64(*ignored_bits as usize, data)
}
@@ -712,30 +602,18 @@ impl<'a> BerObjectContent<'a> {
}
}
- /// Attempt to read integer value from this object.
- ///
- /// This can fail if the object is not an unsigned integer, or if it is too large.
- ///
- /// # Examples
- ///
- /// ```rust
- /// # extern crate der_parser;
- /// # use der_parser::ber::{BerObject,BerObjectContent};
- /// let der_int = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
- /// assert_eq!(
- /// der_int.as_u32(),
- /// Ok(0x10001)
- /// );
- /// ```
pub fn as_u32(&self) -> Result<u32, BerError> {
match self {
- BerObjectContent::Integer(i) => {
- let result = <u32>::from_be_bytes(decode_array_uint4(i)?);
- Ok(result)
- }
+ BerObjectContent::Integer(i) => bytes_to_u64(i).and_then(|x| {
+ if x > u64::from(core::u32::MAX) {
+ Err(BerError::IntegerTooLarge)
+ } else {
+ Ok(x as u32)
+ }
+ }),
BerObjectContent::BitString(ignored_bits, data) => {
bitstring_to_u64(*ignored_bits as usize, data).and_then(|x| {
- if x > u64::from(std::u32::MAX) {
+ if x > u64::from(core::u32::MAX) {
Err(BerError::IntegerTooLarge)
} else {
Ok(x as u32)
@@ -743,7 +621,7 @@ impl<'a> BerObjectContent<'a> {
})
}
BerObjectContent::Enum(i) => {
- if *i > u64::from(std::u32::MAX) {
+ if *i > u64::from(core::u32::MAX) {
Err(BerError::IntegerTooLarge)
} else {
Ok(*i as u32)
@@ -774,7 +652,7 @@ impl<'a> BerObjectContent<'a> {
pub fn as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError> {
match *self {
- BerObjectContent::Optional(Some(ref o)) => Ok(Some(o)),
+ BerObjectContent::Optional(Some(ref o)) => Ok(Some(&o)),
BerObjectContent::Optional(None) => Ok(None),
_ => Err(BerError::BerTypeError),
}
@@ -842,7 +720,8 @@ impl<'a> BerObjectContent<'a> {
BerObjectContent::ObjectDescriptor(s) |
BerObjectContent::GraphicString(s) |
BerObjectContent::GeneralString(s) |
- BerObjectContent::Unknown(_,s) => Ok(s),
+ BerObjectContent::Unknown(_,s) |
+ BerObjectContent::Private(_,s) => Ok(s),
_ => Err(BerError::BerTypeError),
}
}
@@ -891,6 +770,7 @@ impl<'a> BerObjectContent<'a> {
BerObjectContent::GeneralString(_) => BerTag::GeneralString,
BerObjectContent::Tagged(_,x,_) |
BerObjectContent::Unknown(x,_) => *x,
+ &BerObjectContent::Private(ref hdr, _) => hdr.tag,
BerObjectContent::Optional(Some(obj)) => obj.content.tag(),
BerObjectContent::Optional(None) => BerTag(0x00), // XXX invalid !
}
@@ -899,56 +779,21 @@ impl<'a> BerObjectContent<'a> {
#[cfg(feature = "bigint")]
#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
-use num_bigint::{BigInt, BigUint};
+use num_bigint::{BigInt, BigUint, Sign};
#[cfg(feature = "bigint")]
#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
impl<'a> BerObject<'a> {
- /// Attempt to read an integer value from this object.
- ///
- /// This can fail if the object is not an integer.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use der_parser::ber::*;
- ///
- /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
- ///
- /// let (_, object) = parse_ber_integer(data).expect("parsing failed");
- /// # #[cfg(feature = "bigint")]
- /// assert_eq!(object.as_bigint(), Some(65537.into()))
- /// ```
pub fn as_bigint(&self) -> Option<BigInt> {
match self.content {
- BerObjectContent::Integer(s) => Some(BigInt::from_signed_bytes_be(s)),
+ BerObjectContent::Integer(s) => Some(BigInt::from_bytes_be(Sign::Plus, s)),
_ => None,
}
}
- /// Attempt to read a positive integer value from this object.
- ///
- /// This can fail if the object is not an integer, or is negative.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use der_parser::ber::*;
- ///
- /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01];
- ///
- /// let (_, object) = parse_ber_integer(data).expect("parsing failed");
- /// # #[cfg(feature = "bigint")]
- /// assert_eq!(object.as_biguint(), Some(65537_u32.into()))
- /// ```
pub fn as_biguint(&self) -> Option<BigUint> {
match self.content {
- BerObjectContent::Integer(s) => {
- if is_highest_bit_set(s) {
- return None;
- }
- Some(BigUint::from_bytes_be(s))
- }
+ BerObjectContent::Integer(s) => Some(BigUint::from_bytes_be(s)),
_ => None,
}
}
@@ -1068,7 +913,7 @@ impl<'a> BitStringObject<'a> {
/// Constructs a shared `&BitSlice` reference over the object data.
#[cfg(not(any(target_os = "android", target_os = "linux")))]
pub fn as_bitslice(&self) -> Option<&BitSlice<Msb0, u8>> {
- BitSlice::<Msb0, _>::from_slice(self.data)
+ BitSlice::<Msb0, _>::from_slice(&self.data)
}
}
@@ -1082,6 +927,7 @@ impl<'a> AsRef<[u8]> for BitStringObject<'a> {
mod tests {
use crate::ber::*;
use crate::oid::*;
+ use std::string::String;
#[test]
fn test_der_as_u64() {
diff --git a/src/ber/integer.rs b/src/ber/integer.rs
deleted file mode 100644
index 1c05bec..0000000
--- a/src/ber/integer.rs
+++ /dev/null
@@ -1,130 +0,0 @@
-use crate::error::*;
-
-/// Decode an unsigned integer into a big endian byte slice with all leading
-/// zeroes removed.
-///
-/// Returns a byte array of the requested size containing a big endian integer.
-fn remove_zeroes(bytes: &[u8]) -> Result<&[u8], BerError> {
- // skip leading 0s
- match bytes {
- // [] => Err(BerError::DerConstraintFailed),
- [0] => Ok(bytes),
- // [0, byte, ..] if *byte < 0x80 => Err(BerError::DerConstraintFailed),
- // [0, rest @ ..] => Ok(&rest),
- [0, rest @ ..] => remove_zeroes(rest),
- // [byte, ..] if *byte >= 0x80 => Err(BerError::IntegerTooLarge),
- _ => Ok(bytes),
- }
-}
-
-// XXX const generics require rustc >= 1.51
-// /// Decode an unsigned integer into a byte array of the requested size
-// /// containing a big endian integer.
-// pub(crate) fn decode_array_uint<const N: usize>(bytes: &[u8]) -> Result<[u8; N], BerError> {
-// // Check if MSB is set *before* leading zeroes
-// if is_highest_bit_set(bytes) {
-// return Err(BerError::IntegerNegative);
-// }
-// let input = remove_zeroes(bytes)?;
-
-// if input.len() > N {
-// return Err(BerError::IntegerTooLarge);
-// }
-
-// // Input has leading zeroes removed, so we need to add them back
-// let mut output = [0u8; N];
-// assert!(input.len() <= N);
-// output[N.saturating_sub(input.len())..].copy_from_slice(input);
-// Ok(output)
-// }
-
-pub(crate) fn decode_array_uint8(bytes: &[u8]) -> Result<[u8; 8], BerError> {
- // Check if MSB is set *before* leading zeroes
- if is_highest_bit_set(bytes) {
- return Err(BerError::IntegerNegative);
- }
- let input = remove_zeroes(bytes)?;
-
- if input.len() > 8 {
- return Err(BerError::IntegerTooLarge);
- }
-
- // Input has leading zeroes removed, so we need to add them back
- let mut output = [0u8; 8];
- assert!(input.len() <= 8);
- output[8_usize.saturating_sub(input.len())..].copy_from_slice(input);
- Ok(output)
-}
-
-pub(crate) fn decode_array_uint4(bytes: &[u8]) -> Result<[u8; 4], BerError> {
- // Check if MSB is set *before* leading zeroes
- if is_highest_bit_set(bytes) {
- return Err(BerError::IntegerNegative);
- }
- let input = remove_zeroes(bytes)?;
-
- if input.len() > 4 {
- return Err(BerError::IntegerTooLarge);
- }
-
- // Input has leading zeroes removed, so we need to add them back
- let mut output = [0u8; 4];
- assert!(input.len() <= 4);
- output[4_usize.saturating_sub(input.len())..].copy_from_slice(input);
- Ok(output)
-}
-
-// XXX const generics require rustc >= 1.51
-// /// Decode an unsigned integer of the specified size.
-// ///
-// /// Returns a byte array of the requested size containing a big endian integer.
-// pub(crate) fn decode_array_int<const N: usize>(input: &[u8]) -> Result<[u8; N], BerError> {
-// let input = remove_zeroes(input)?;
-
-// if input.len() > N {
-// return Err(BerError::IntegerTooLarge);
-// }
-
-// // any.tag().assert_eq(Tag::Integer)?;
-// let mut output = [0xFFu8; N];
-// let offset = N.saturating_sub(input.len());
-// output[offset..].copy_from_slice(input);
-// Ok(output)
-// }
-
-pub(crate) fn decode_array_int8(input: &[u8]) -> Result<[u8; 8], BerError> {
- let input = remove_zeroes(input)?;
-
- if input.len() > 8 {
- return Err(BerError::IntegerTooLarge);
- }
-
- // any.tag().assert_eq(Tag::Integer)?;
- let mut output = [0xFFu8; 8];
- let offset = 8_usize.saturating_sub(input.len());
- output[offset..].copy_from_slice(input);
- Ok(output)
-}
-
-pub(crate) fn decode_array_int4(input: &[u8]) -> Result<[u8; 4], BerError> {
- let input = remove_zeroes(input)?;
-
- if input.len() > 4 {
- return Err(BerError::IntegerTooLarge);
- }
-
- // any.tag().assert_eq(Tag::Integer)?;
- let mut output = [0xFFu8; 4];
- let offset = 4_usize.saturating_sub(input.len());
- output[offset..].copy_from_slice(input);
- Ok(output)
-}
-
-/// Is the highest bit of the first byte in the slice 1? (if present)
-#[inline]
-pub(crate) fn is_highest_bit_set(bytes: &[u8]) -> bool {
- bytes
- .get(0)
- .map(|byte| byte & 0b10000000 != 0)
- .unwrap_or(false)
-}
diff --git a/src/ber/mod.rs b/src/ber/mod.rs
index f2fa5f9..e479e47 100644
--- a/src/ber/mod.rs
+++ b/src/ber/mod.rs
@@ -47,7 +47,6 @@
//! ```
mod ber;
-mod integer;
mod multi;
mod parser;
mod print;
@@ -62,3 +61,8 @@ pub use crate::ber::print::*;
#[cfg(feature = "serialize")]
pub use crate::ber::serialize::*;
pub use crate::ber::tagged::*;
+
+use alloc::borrow::Cow;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::convert::{Into, TryFrom};
diff --git a/src/ber/parser.rs b/src/ber/parser.rs
index ace4937..d5e7198 100644
--- a/src/ber/parser.rs
+++ b/src/ber/parser.rs
@@ -7,8 +7,6 @@ use nom::multi::{many0, many_till};
use nom::number::streaming::be_u8;
use nom::{Err, Needed, Offset};
use rusticata_macros::{combinator::parse_hex_to_u64, custom_check};
-use std::borrow::Cow;
-use std::convert::{Into, TryFrom};
/// Default maximum recursion limit
pub const MAX_RECURSION: usize = 50;
@@ -280,7 +278,7 @@ fn ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
fn ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
let (i, bytes) = take(len)(i)?;
- let s = std::str::from_utf8(bytes)
+ let s = core::str::from_utf8(bytes)
.map_err(|_| Err::Error(BerError::StringInvalidCharset))
.map(|s| BerObjectContent::UTF8String(s))?;
Ok((i, s))
@@ -345,7 +343,7 @@ fn ber_read_content_numericstring<'a>(i: &'a [u8], len: usize) -> BerResult<BerO
if !bytes.iter().all(is_numeric) {
return Err(Err::Error(BerError::StringInvalidCharset));
}
- let s = std::str::from_utf8(bytes)
+ let s = core::str::from_utf8(bytes)
.map_err(|_| Err::Error(BerError::StringInvalidCharset))
.map(|s| BerObjectContent::NumericString(s))?;
Ok((i, s))
@@ -361,7 +359,7 @@ fn ber_read_content_visiblestring<'a>(i: &'a [u8], len: usize) -> BerResult<BerO
if !bytes.iter().all(is_visible) {
return Err(Err::Error(BerError::StringInvalidCharset));
}
- let s = std::str::from_utf8(bytes)
+ let s = core::str::from_utf8(bytes)
.map_err(|_| Err::Error(BerError::StringInvalidCharset))
.map(|s| BerObjectContent::VisibleString(s))?;
Ok((i, s))
@@ -395,7 +393,7 @@ fn ber_read_content_printablestring<'a>(
if !bytes.iter().all(is_printable) {
return Err(Err::Error(BerError::StringInvalidCharset));
}
- let s = std::str::from_utf8(bytes)
+ let s = core::str::from_utf8(bytes)
.map_err(|_| Err::Error(BerError::StringInvalidCharset))
.map(|s| BerObjectContent::PrintableString(s))?;
Ok((i, s))
@@ -416,7 +414,7 @@ fn ber_read_content_ia5string<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjec
if !bytes.iter().all(u8::is_ascii) {
return Err(Err::Error(BerError::StringInvalidCharset));
}
- let s = std::str::from_utf8(bytes)
+ let s = core::str::from_utf8(bytes)
.map_err(|_| Err::Error(BerError::StringInvalidCharset))
.map(|s| BerObjectContent::IA5String(s))?;
Ok((i, s))
@@ -432,7 +430,7 @@ fn ber_read_content_utctime<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectC
if !bytes.iter().all(is_visible) {
return Err(Err::Error(BerError::StringInvalidCharset));
}
- let s = std::str::from_utf8(bytes)
+ let s = core::str::from_utf8(bytes)
.map_err(|_| Err::Error(BerError::StringInvalidCharset))
.map(|s| BerObjectContent::UTCTime(s))?;
Ok((i, s))
@@ -451,7 +449,7 @@ fn ber_read_content_generalizedtime<'a>(
if !bytes.iter().all(is_visible) {
return Err(Err::Error(BerError::StringInvalidCharset));
}
- let s = std::str::from_utf8(bytes)
+ let s = core::str::from_utf8(bytes)
.map_err(|_| Err::Error(BerError::StringInvalidCharset))
.map(|s| BerObjectContent::GeneralizedTime(s))?;
Ok((i, s))
@@ -1101,37 +1099,23 @@ where
}
}
-/// Parse BER object and try to decode it as a 32-bits signed integer
-///
-/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
-/// integer type.
-#[inline]
-pub fn parse_ber_i32(i: &[u8]) -> BerResult<i32> {
- let (rem, ber) = parse_ber_integer(i)?;
- let int = ber.as_i32().map_err(nom::Err::Error)?;
- Ok((rem, int))
-}
-
-/// Parse BER object and try to decode it as a 64-bits signed integer
-///
-/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
-/// integer type.
-#[inline]
-pub fn parse_ber_i64(i: &[u8]) -> BerResult<i64> {
- let (rem, ber) = parse_ber_integer(i)?;
- let int = ber.as_i64().map_err(nom::Err::Error)?;
- Ok((rem, int))
-}
-
/// Parse BER object and try to decode it as a 32-bits unsigned integer
///
/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
/// integer type.
#[inline]
pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> {
- let (rem, ber) = parse_ber_integer(i)?;
- let int = ber.as_u32().map_err(nom::Err::Error)?;
- Ok((rem, int))
+ parse_ber_container(|content, hdr| {
+ if hdr.tag != BerTag::Integer {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ let l = bytes_to_u64(content)?;
+ if l > 0xffff_ffff {
+ Err(Err::Error(BerError::IntegerTooLarge))
+ } else {
+ Ok((&b""[..], l as u32))
+ }
+ })(i)
}
/// Parse BER object and try to decode it as a 64-bits unsigned integer
@@ -1140,9 +1124,13 @@ pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> {
/// integer type.
#[inline]
pub fn parse_ber_u64(i: &[u8]) -> BerResult<u64> {
- let (rem, ber) = parse_ber_integer(i)?;
- let int = ber.as_u64().map_err(nom::Err::Error)?;
- Ok((rem, int))
+ parse_ber_container(|content, hdr| {
+ if hdr.tag != BerTag::Integer {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ let l = bytes_to_u64(content)?;
+ Ok((&b""[..], l))
+ })(i)
}
/// Parse BER object and get content as slice
@@ -1184,7 +1172,13 @@ pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult {
custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
}
match hdr.class {
- BerClass::Universal | BerClass::Private => (),
+ BerClass::Universal => (),
+ BerClass::Private => {
+ let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
+ let content = BerObjectContent::Private(hdr.clone(), content);
+ let obj = BerObject::from_header_and_content(hdr, content);
+ return Ok((rem, obj));
+ }
_ => {
let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
let content = BerObjectContent::Unknown(hdr.tag, content);
diff --git a/src/ber/print.rs b/src/ber/print.rs
index b3ae221..2459d19 100644
--- a/src/ber/print.rs
+++ b/src/ber/print.rs
@@ -1,8 +1,10 @@
use crate::ber::BitStringObject;
use crate::ber::{BerObject, BerObjectContent, BerTag};
-use std::fmt;
-use std::iter::FromIterator;
-use std::str;
+use alloc::string::String;
+use alloc::vec::Vec;
+use core::fmt;
+use core::iter::FromIterator;
+use core::str;
use rusticata_macros::debug;
@@ -77,7 +79,7 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
fn print_utf32_string_with_type(f: &mut fmt::Formatter, s: &[u8], ty: &str) -> fmt::Result {
let chars: Option<Vec<char>> = s
.chunks_exact(4)
- .map(|a| std::char::from_u32(u32::from_be_bytes([a[0], a[1], a[2], a[3]])))
+ .map(|a| core::char::from_u32(u32::from_be_bytes([a[0], a[1], a[2], a[3]])))
.collect();
match chars {
@@ -116,6 +118,9 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
None => writeln!(f, "NONE"),
}
}
+ BerObjectContent::Private(ref hdr, bytes) => {
+ writeln!(f, "Private(c:{} s:{} t:{}): {:?}", hdr.class, hdr.structured, hdr.tag.0, debug::HexSlice(bytes))
+ },
BerObjectContent::Tagged(class, tag, ref obj) => {
writeln!(f, "ContextSpecific [{} {}] {{", class, tag)?;
write!(f, "{:?}", self.next_indent(obj))?;
diff --git a/src/ber/serialize.rs b/src/ber/serialize.rs
index 7ffedc2..be7c187 100644
--- a/src/ber/serialize.rs
+++ b/src/ber/serialize.rs
@@ -1,3 +1,4 @@
+#![cfg(feature = "std")]
use crate::ber::*;
use crate::oid::Oid;
use cookie_factory::bytes::be_u8;
@@ -79,7 +80,7 @@ pub fn ber_encode_tagged_explicit<'a, W: Write + Default + AsRef<[u8]> + 'a>(
) -> impl SerializeFn<W> + 'a {
move |out| {
// encode inner object
- let v = gen_simple(ber_encode_object(obj), W::default())?;
+ let v = gen_simple(ber_encode_object(&obj), W::default())?;
let len = v.as_ref().len();
// encode the application header, using the tag
let hdr = BerObjectHeader::new(class, 1 /* X.690 8.14.2 */, tag, len);
@@ -149,7 +150,7 @@ fn ber_encode_object_content<'a, W: Write + Default + AsRef<[u8]> + 'a>(
| BerObjectContent::ObjectDescriptor(s)
| BerObjectContent::GraphicString(s)
| BerObjectContent::GeneralString(s) => slice(s)(out),
- BerObjectContent::Sequence(v) | BerObjectContent::Set(v) => ber_encode_sequence(v)(out),
+ BerObjectContent::Sequence(v) | BerObjectContent::Set(v) => ber_encode_sequence(&v)(out),
// best we can do is tagged-explicit, but we don't know
BerObjectContent::Optional(inner) => {
// directly encode inner object
@@ -158,6 +159,7 @@ fn ber_encode_object_content<'a, W: Write + Default + AsRef<[u8]> + 'a>(
None => slice(&[])(out), // XXX encode NOP ?
}
}
+ BerObjectContent::Private(_hdr, bytes) => slice(bytes)(out),
BerObjectContent::Tagged(_class, _tag, inner) => {
// directly encode inner object
// XXX wrong, we should wrap it!
@@ -178,7 +180,7 @@ pub fn ber_encode_object_raw<'a, 'b: 'a, 'c: 'a, W: Write + Default + AsRef<[u8]
hdr: &'b BerObjectHeader,
content: &'c BerObjectContent,
) -> impl SerializeFn<W> + 'a {
- tuple((ber_encode_header(hdr), ber_encode_object_content(content)))
+ tuple((ber_encode_header(&hdr), ber_encode_object_content(&content)))
}
/// Encode object as BER
diff --git a/src/der/mod.rs b/src/der/mod.rs
index aaa64c5..bad3f23 100644
--- a/src/der/mod.rs
+++ b/src/der/mod.rs
@@ -62,6 +62,10 @@ pub use crate::der::multi::*;
pub use crate::der::parser::*;
pub use crate::der::tagged::*;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::convert::{Into, TryFrom};
+
/// DER Object class of tag (same as `BerClass`)
pub type DerClass = BerClass;
diff --git a/src/der/parser.rs b/src/der/parser.rs
index bb5ea0f..68e1a7f 100644
--- a/src/der/parser.rs
+++ b/src/der/parser.rs
@@ -5,7 +5,8 @@ use nom::bytes::streaming::take;
use nom::number::streaming::be_u8;
use nom::{Err, Needed};
use rusticata_macros::custom_check;
-use std::convert::{Into, TryFrom};
+
+use crate::ber::MAX_RECURSION;
/// Parse DER object recursively
///
@@ -381,36 +382,22 @@ where
parse_ber_implicit(i, tag, f)
}
-/// Parse DER object and try to decode it as a 32-bits signed integer
-///
-/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
-/// integer type.
-#[inline]
-pub fn parse_der_i32(i: &[u8]) -> BerResult<i32> {
- let (rem, der) = parse_der_integer(i)?;
- let int = der.as_i32().map_err(nom::Err::Error)?;
- Ok((rem, int))
-}
-
-/// Parse DER object and try to decode it as a 64-bits signed integer
-///
-/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
-/// integer type.
-#[inline]
-pub fn parse_der_i64(i: &[u8]) -> BerResult<i64> {
- let (rem, der) = parse_der_integer(i)?;
- let int = der.as_i64().map_err(nom::Err::Error)?;
- Ok((rem, int))
-}
-
/// Parse DER object and try to decode it as a 32-bits unsigned integer
///
/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
/// integer type.
pub fn parse_der_u32(i: &[u8]) -> BerResult<u32> {
- let (rem, der) = parse_der_integer(i)?;
- let int = der.as_u32().map_err(nom::Err::Error)?;
- Ok((rem, int))
+ parse_der_container(|content, hdr| {
+ if hdr.tag != DerTag::Integer {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ let l = bytes_to_u64(content)?;
+ if l > 0xffff_ffff {
+ Err(Err::Error(BerError::IntegerTooLarge))
+ } else {
+ Ok((&b""[..], l as u32))
+ }
+ })(i)
}
/// Parse DER object and try to decode it as a 64-bits unsigned integer
@@ -418,9 +405,13 @@ pub fn parse_der_u32(i: &[u8]) -> BerResult<u32> {
/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
/// integer type.
pub fn parse_der_u64(i: &[u8]) -> BerResult<u64> {
- let (rem, der) = parse_der_integer(i)?;
- let int = der.as_u64().map_err(nom::Err::Error)?;
- Ok((rem, int))
+ parse_der_container(|content, hdr| {
+ if hdr.tag != DerTag::Integer {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ let l = bytes_to_u64(content)?;
+ Ok((&b""[..], l))
+ })(i)
}
/// Parse DER object and get content as slice
@@ -527,17 +518,6 @@ pub fn der_read_element_content_as(
// exception: read and verify padding bits
return der_read_content_bitstring(i, l);
}
- DerTag::Integer => {
- // verify leading zeros
- match i[..l] {
- [] => return Err(nom::Err::Error(BerError::DerConstraintFailed)),
- [0, 0, ..] => return Err(nom::Err::Error(BerError::DerConstraintFailed)),
- [0, byte, ..] if byte < 0x80 => {
- return Err(nom::Err::Error(BerError::DerConstraintFailed));
- }
- _ => (),
- }
- }
DerTag::NumericString
| DerTag::VisibleString
| DerTag::PrintableString
@@ -575,7 +555,13 @@ fn der_read_element_content_recursive<'a>(
max_depth: usize,
) -> DerResult<'a> {
match hdr.class {
- DerClass::Universal | DerClass::Private => (),
+ BerClass::Universal => (),
+ BerClass::Private => {
+ let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?;
+ let content = BerObjectContent::Private(hdr.clone(), content);
+ let obj = BerObject::from_header_and_content(hdr, content);
+ return Ok((rem, obj));
+ }
_ => {
let (i, content) = ber_get_object_content(i, &hdr, max_depth)?;
let content = DerObjectContent::Unknown(hdr.tag, content);
diff --git a/src/error.rs b/src/error.rs
index 803bdee..958236b 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -2,10 +2,9 @@
use crate::ber::BerObject;
use crate::der::DerObject;
+use alloc::fmt;
use nom::error::{ErrorKind, FromExternalError, ParseError};
use nom::IResult;
-use std::error::Error;
-use std::fmt;
/// Holds the result of parsing functions
///
@@ -22,7 +21,7 @@ pub type BerResult<'a, O = BerObject<'a>> = IResult<&'a [u8], O, BerError>;
pub type DerResult<'a> = BerResult<'a, DerObject<'a>>;
/// Error for BER/DER parsers
-#[derive(Debug, PartialEq, Copy, Clone)]
+#[derive(Debug, PartialEq)]
pub enum BerError {
/// BER object does not have the expected type
BerTypeError,
@@ -45,8 +44,6 @@ pub enum BerError {
/// BER integer is too large to fit in a native type. Use `as_bigint()`
IntegerTooLarge,
- /// BER integer is negative, while an unsigned integer was requested
- IntegerNegative,
/// BER recursive parsing reached maximum depth (See
/// [MAX_RECURSION](../ber/constant.MAX_RECURSION.html))
@@ -97,11 +94,14 @@ impl fmt::Display for BerError {
}
}
-impl Error for BerError {}
+#[cfg(feature = "std")]
+impl std::error::Error for BerError {}
-#[cfg(test)]
+#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
+ use std::boxed::Box;
+ use std::error::Error;
#[test]
fn test_unwrap_bererror() {
diff --git a/src/lib.rs b/src/lib.rs
index 926a036..dbcccfc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,7 +3,7 @@
//! [![docs.rs](https://docs.rs/der-parser/badge.svg)](https://docs.rs/der-parser)
//! [![crates.io](https://img.shields.io/crates/v/der-parser.svg)](https://crates.io/crates/der-parser)
//! [![Download numbers](https://img.shields.io/crates/d/der-parser.svg)](https://crates.io/crates/der-parser)
-//! [![dependency status](https://deps.rs/crate/der-parser/5.1.2/status.svg)](https://deps.rs/crate/der-parser/5.1.2)
+//! [![dependency status](https://deps.rs/crate/der-parser/5.0.0/status.svg)](https://deps.rs/crate/der-parser/5.0.1)
//! [![Github CI](https://github.com/rusticata/der-parser/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/der-parser/actions)
//! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.44.0+-lightgray.svg)](#rust-version-requirements)
//!
@@ -45,7 +45,7 @@
//!
//! ## Examples
//!
-//! Parse two BER integers (see [BER/DER Integers](#berder-integers)):
+//! Parse two BER integers:
//!
//! ```rust
//! use der_parser::ber::parse_ber_integer;
@@ -149,19 +149,10 @@
//! DER integers can be of any size, so it is not possible to store them as simple integers (they
//! are stored as raw bytes).
//!
-//! Note that, by default, BER/DER integers are signed. Functions are provided to request reading
-//! unsigned values, but they will fail if the integer value is negative.
-//!
-//! To get the integer value for all possible integer sign and size, use
-//! [`BerObject::as_bigint`](ber/struct.BerObject.html#method.as_bigint)) (requires the `bigint` feature).
-//!
-//! To get a simple value expected to be in a known range, use methods like
-//! [`BerObject::as_i32`](ber/struct.BerObject.html#method.as_i32)) and
-//! [`BerObject::as_i64`](ber/struct.BerObject.html#method.as_i64) (or the unsigned versions
-//! [`BerObject::as_u32`](ber/struct.BerObject.html#method.as_u32) and
-//! [`BerObject::as_u64`](ber/struct.BerObject.html#method.as_u64)
-//!),
-//! which will return the value, or an error if the integer is too large (or is negative).
+//! To get a simple value, use [`BerObject::as_u32`](ber/struct.BerObject.html#method.as_u32)
+//! (knowning that this method will return an error if the integer is too large),
+//! [`BerObject::as_u64`](ber/struct.BerObject.html#method.as_u64), or use the `bigint` feature of
+//! this crate and use [`BerObject::as_bigint`](ber/struct.BerObject.html#method.as_bigint).
//!
//! ```rust
//! use der_parser::ber::*;
@@ -170,9 +161,6 @@
//!
//! let (_, object) = parse_ber_integer(data).expect("parsing failed");
//! assert_eq!(object.as_u64(), Ok(65537));
-//!
-//! #[cfg(feature = "bigint")]
-//! assert_eq!(object.as_bigint(), Some(65537.into()))
//! ```
//!
//! Access to the raw value is possible using the `as_slice` method.
@@ -237,6 +225,13 @@
no_crate_inject,
attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables))
))]
+#![no_std]
+
+#[cfg(any(test, feature = "std"))]
+#[macro_use]
+extern crate std;
+
+extern crate alloc;
#[macro_use]
mod macros;
diff --git a/src/oid.rs b/src/oid.rs
index fdb17b3..17b64a6 100644
--- a/src/oid.rs
+++ b/src/oid.rs
@@ -47,17 +47,22 @@
//! ```
//! *Attention*, be aware that the latter version might not handle the case of a relative oid correctly. An
//! extra check might be necessary.
-use std::borrow::Cow;
-use std::convert::From;
-use std::fmt;
-use std::iter::{ExactSizeIterator, FusedIterator, Iterator};
-use std::ops::Shl;
-use std::str::FromStr;
+use alloc::borrow::Cow;
+use alloc::fmt;
+use alloc::str::FromStr;
+use alloc::string::{String, ToString};
+use alloc::vec::Vec;
+use core::convert::From;
+use core::iter::{ExactSizeIterator, FusedIterator, Iterator};
+use core::ops::Shl;
#[cfg(feature = "bigint")]
use num_bigint::BigUint;
use num_traits::Num;
+#[cfg(not(feature = "std"))]
+use alloc::format;
+
#[derive(Debug)]
pub enum ParseError {
TooShort,
@@ -209,10 +214,10 @@ impl<'a> Oid<'a> {
&'_ self,
) -> impl Iterator<Item = BigUint> + FusedIterator + ExactSizeIterator + '_ {
SubIdentifierIterator {
- oid: self,
+ oid: &self,
pos: 0,
first: false,
- n: std::marker::PhantomData,
+ n: core::marker::PhantomData,
}
}
@@ -245,10 +250,10 @@ impl<'a> Oid<'a> {
}
Some(SubIdentifierIterator {
- oid: self,
+ oid: &self,
pos: 0,
first: false,
- n: std::marker::PhantomData,
+ n: core::marker::PhantomData,
})
}
}
@@ -260,7 +265,7 @@ struct SubIdentifierIterator<'a, N: Repr> {
oid: &'a Oid<'a>,
pos: usize,
first: bool,
- n: std::marker::PhantomData<&'a N>,
+ n: core::marker::PhantomData<&'a N>,
}
impl<'a, N: Repr> Iterator for SubIdentifierIterator<'a, N> {
@@ -358,6 +363,7 @@ impl<'a> FromStr for Oid<'a> {
mod tests {
use crate::oid::Oid;
use std::borrow::Cow;
+ use std::borrow::ToOwned;
use std::str::FromStr;
#[test]
@@ -437,6 +443,7 @@ mod tests {
{
use num_bigint::BigUint;
use num_traits::FromPrimitive;
+ use std::vec::Vec;
let oid_raw = Oid::new(Cow::Borrowed(&[0]));
let ids: Vec<BigUint> = oid_raw.iter_bigint().collect();
@@ -444,6 +451,7 @@ mod tests {
assert_eq!(oid_raw.iter_bigint().len(), 1);
}
{
+ use std::vec::Vec;
let oid_raw = Oid::new(Cow::Borrowed(&[0]));
let ids: Vec<u64> = oid_raw.iter().unwrap().collect();
assert_eq!(vec![0], ids);
diff --git a/tests/ber_parser.rs b/tests/ber_parser.rs
index 488a0c1..e5906d7 100644
--- a/tests/ber_parser.rs
+++ b/tests/ber_parser.rs
@@ -6,9 +6,6 @@ use nom::Err;
// use pretty_assertions::assert_eq;
use test_case::test_case;
-#[cfg(feature = "bigint")]
-use num_bigint::{BigInt, BigUint, Sign};
-
#[test_case(&hex!("01 01 00"), Some(false) ; "val true")]
#[test_case(&hex!("01 01 ff"), Some(true) ; "val false")]
#[test_case(&hex!("01 01 7f"), Some(true) ; "true not ff")]
@@ -140,10 +137,10 @@ fn test_ber_int() {
}
#[test_case(&hex!("02 01 01"), Ok(1) ; "u32-1")]
-#[test_case(&hex!("02 02 00 ff"), Ok(255) ; "u32-255")]
+#[test_case(&hex!("02 01 ff"), Ok(255) ; "u32-255")]
#[test_case(&hex!("02 02 01 23"), Ok(0x123) ; "u32-0x123")]
#[test_case(&hex!("02 04 01 23 45 67"), Ok(0x0123_4567) ; "u32-long-ok")]
-#[test_case(&hex!("02 05 00 ff ff ff ff"), Ok(0xffff_ffff) ; "u32-long2-ok")]
+#[test_case(&hex!("02 04 ff ff ff ff"), Ok(0xffff_ffff) ; "u32-long2-ok")]
#[test_case(&hex!("02 06 00 00 01 23 45 67"), Ok(0x0123_4567) ; "u32-long-leading-zeros-ok")]
#[test_case(&hex!("02 05 01 23 45 67 01"), Err(BerError::IntegerTooLarge) ; "u32 too large")]
#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Err(BerError::IntegerTooLarge) ; "u32 too large 2")]
@@ -161,10 +158,10 @@ fn tc_ber_u32(i: &[u8], out: Result<u32, BerError>) {
}
#[test_case(&hex!("02 01 01"), Ok(1) ; "u64-1")]
-#[test_case(&hex!("02 02 00 ff"), Ok(255) ; "u64-255")]
+#[test_case(&hex!("02 01 ff"), Ok(255) ; "u64-255")]
#[test_case(&hex!("02 02 01 23"), Ok(0x123) ; "u64-0x123")]
#[test_case(&hex!("02 08 01 23 45 67 01 23 45 67"), Ok(0x0123_4567_0123_4567) ; "u64-long-ok")]
-#[test_case(&hex!("02 09 00 ff ff ff ff ff ff ff ff"), Ok(0xffff_ffff_ffff_ffff) ; "u64-long2-ok")]
+#[test_case(&hex!("02 08 ff ff ff ff ff ff ff ff"), Ok(0xffff_ffff_ffff_ffff) ; "u64-long2-ok")]
#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Err(BerError::IntegerTooLarge) ; "u64 too large")]
#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
fn tc_ber_u64(i: &[u8], out: Result<u64, BerError>) {
@@ -179,70 +176,6 @@ fn tc_ber_u64(i: &[u8], out: Result<u64, BerError>) {
}
}
-#[test_case(&hex!("02 01 01"), Ok(1) ; "i64-1")]
-#[test_case(&hex!("02 01 ff"), Ok(-1) ; "i64-neg1")]
-#[test_case(&hex!("02 01 80"), Ok(-128) ; "i64-neg128")]
-#[test_case(&hex!("02 02 ff 7f"), Ok(-129) ; "i64-neg129")]
-#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
-fn tc_ber_i64(i: &[u8], out: Result<i64, BerError>) {
- let res = parse_ber_i64(i);
- match out {
- Ok(expected) => {
- pretty_assertions::assert_eq!(res, Ok((&b""[..], expected)));
- }
- Err(e) => {
- pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
- }
- }
-}
-
-#[cfg(feature = "bigint")]
-#[test_case(&hex!("02 01 01"), Ok(BigInt::from(1)) ; "bigint-1")]
-#[test_case(&hex!("02 02 00 ff"), Ok(BigInt::from(255)) ; "bigint-255")]
-#[test_case(&hex!("02 01 ff"), Ok(BigInt::from(-1)) ; "bigint-neg1")]
-#[test_case(&hex!("02 01 80"), Ok(BigInt::from(-128)) ; "bigint-neg128")]
-#[test_case(&hex!("02 02 ff 7f"), Ok(BigInt::from(-129)) ; "bigint-neg129")]
-#[test_case(&hex!("02 09 00 ff ff ff ff ff ff ff ff"), Ok(BigInt::from(0xffff_ffff_ffff_ffff_u64)) ; "bigint-long2-ok")]
-#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Ok(BigInt::from_bytes_be(Sign::Plus, &hex!("01 23 45 67 01 23 45 67 ab"))) ; "bigint-longer1")]
-fn tc_ber_bigint(i: &[u8], out: Result<BigInt, BerError>) {
- let res = parse_ber_integer(i);
- match out {
- Ok(expected) => {
- let (rem, ber) = res.expect("parsing failed");
- assert!(rem.is_empty());
- let int = ber.as_bigint().expect("failed to convert to bigint");
- pretty_assertions::assert_eq!(int, expected);
- }
- Err(e) => {
- pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
- }
- }
-}
-
-#[cfg(feature = "bigint")]
-#[test_case(&hex!("02 01 01"), Ok(Some(BigUint::from(1_u8))) ; "biguint-1")]
-#[test_case(&hex!("02 02 00 ff"), Ok(Some(BigUint::from(255_u8))) ; "biguint-255")]
-#[test_case(&hex!("02 01 ff"), Ok(None) ; "biguint-neg1")]
-#[test_case(&hex!("02 01 80"), Ok(None) ; "biguint-neg128")]
-#[test_case(&hex!("02 02 ff 7f"), Ok(None) ; "biguint-neg129")]
-#[test_case(&hex!("02 09 00 ff ff ff ff ff ff ff ff"), Ok(Some(BigUint::from(0xffff_ffff_ffff_ffff_u64))) ; "biguint-long2-ok")]
-#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Ok(Some(BigUint::from_bytes_be(&hex!("01 23 45 67 01 23 45 67 ab")))) ; "biguint-longer1")]
-#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
-fn tc_ber_biguint(i: &[u8], out: Result<Option<BigUint>, BerError>) {
- let res = parse_ber_integer(i);
- match out {
- Ok(expected) => {
- let (rem, ber) = res.expect("parsing failed");
- assert!(rem.is_empty());
- let uint = ber.as_biguint();
- pretty_assertions::assert_eq!(uint, expected);
- }
- Err(e) => {
- pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
- }
- }
-}
-
#[test_case(&hex!("02 01 01"), Ok(&[1]) ; "slice 1")]
#[test_case(&hex!("02 01 ff"), Ok(&[255]) ; "slice 2")]
#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Ok(&hex!("01 23 45 67 01 23 45 67 ab")) ; "slice 3")]
@@ -543,3 +476,11 @@ fn test_parse_ber_content2() {
assert_eq!(tag, BerTag::Integer);
assert_eq!(content.as_u32(), Ok(0x10001));
}
+
+#[test]
+fn parse_ber_private() {
+ let bytes = &hex!("c0 03 01 00 01");
+ let (rem, res) = parse_ber(bytes).expect("parsing failed");
+ assert!(rem.is_empty());
+ assert!(matches!(res.content, BerObjectContent::Private(_, _)));
+}
diff --git a/tests/der_parser.rs b/tests/der_parser.rs
index 9a31e5c..3d604b0 100644
--- a/tests/der_parser.rs
+++ b/tests/der_parser.rs
@@ -519,12 +519,11 @@ fn test_der_defined_set_macros() {
}
#[test_case(&hex!("02 01 01"), Ok(1) ; "u32-1")]
-#[test_case(&hex!("02 01 ff"), Err(BerError::IntegerNegative) ; "negative integer")]
-#[test_case(&hex!("02 02 00 ff"), Ok(255) ; "u32-255")]
+#[test_case(&hex!("02 01 ff"), Ok(255) ; "u32-255")]
#[test_case(&hex!("02 02 01 23"), Ok(0x123) ; "u32-0x123")]
#[test_case(&hex!("02 04 01 23 45 67"), Ok(0x0123_4567) ; "u32-long-ok")]
-#[test_case(&hex!("02 04 ff ff ff ff"), Err(BerError::IntegerNegative) ; "u32-long2-neg")]
-#[test_case(&hex!("02 06 00 00 01 23 45 67"), Err(BerError::DerConstraintFailed) ; "u32-long-leading-zeros")]
+#[test_case(&hex!("02 04 ff ff ff ff"), Ok(0xffff_ffff) ; "u32-long2-ok")]
+#[test_case(&hex!("02 06 00 00 01 23 45 67"), Ok(0x0123_4567) ; "u32-long-leading-zeros-ok")]
#[test_case(&hex!("02 05 01 23 45 67 01"), Err(BerError::IntegerTooLarge) ; "u32 too large")]
#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Err(BerError::IntegerTooLarge) ; "u32 too large 2")]
#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
@@ -540,28 +539,11 @@ fn tc_der_u32(i: &[u8], out: Result<u32, BerError>) {
}
}
-#[test_case(&hex!("02 01 01"), Ok(1) ; "i32-1")]
-#[test_case(&hex!("02 01 ff"), Ok(-1) ; "i32-neg1")]
-#[test_case(&hex!("02 01 80"), Ok(-128) ; "i32-neg128")]
-#[test_case(&hex!("02 02 ff 7f"), Ok(-129) ; "i32-neg129")]
-#[test_case(&hex!("02 02 00 ff"), Ok(255) ; "i32-255")]
-fn tc_der_i32(i: &[u8], out: Result<i32, BerError>) {
- let res = parse_der_i32(i);
- match out {
- Ok(expected) => {
- pretty_assertions::assert_eq!(res, Ok((&b""[..], expected)));
- }
- Err(e) => {
- pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
- }
- }
-}
-
#[test_case(&hex!("02 01 01"), Ok(1) ; "u64-1")]
-#[test_case(&hex!("02 02 00 ff"), Ok(255) ; "u64-255")]
+#[test_case(&hex!("02 01 ff"), Ok(255) ; "u64-255")]
#[test_case(&hex!("02 02 01 23"), Ok(0x123) ; "u64-0x123")]
#[test_case(&hex!("02 08 01 23 45 67 01 23 45 67"), Ok(0x0123_4567_0123_4567) ; "u64-long-ok")]
-#[test_case(&hex!("02 09 00 ff ff ff ff ff ff ff ff"), Ok(0xffff_ffff_ffff_ffff) ; "u64-long2-ok")]
+#[test_case(&hex!("02 08 ff ff ff ff ff ff ff ff"), Ok(0xffff_ffff_ffff_ffff) ; "u64-long2-ok")]
#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Err(BerError::IntegerTooLarge) ; "u64 too large")]
#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
fn tc_der_u64(i: &[u8], out: Result<u64, BerError>) {
diff --git a/tests/macros.rs b/tests/macros.rs
index 361fee9..f22c6a9 100644
--- a/tests/macros.rs
+++ b/tests/macros.rs
@@ -1,5 +1,6 @@
#![allow(deprecated)]
+extern crate alloc;
use der_parser::ber::{parse_ber_integer, BerObject};
use der_parser::der::{parse_der_enum, parse_der_integer};
use der_parser::error::{BerResult, DerResult};
diff --git a/tests/oid.rs b/tests/oid.rs
index 7f04b53..5cffad4 100644
--- a/tests/oid.rs
+++ b/tests/oid.rs
@@ -1,5 +1,6 @@
//! Test the API provided to compare OIDs
+extern crate alloc;
use der_parser::oid;
use der_parser::oid::Oid;
diff --git a/tests/primitive.rs b/tests/primitive.rs
index ae40317..b18cf4f 100644
--- a/tests/primitive.rs
+++ b/tests/primitive.rs
@@ -1,3 +1,4 @@
+extern crate alloc;
use der_parser::ber::*;
use der_parser::der::*;
use der_parser::error::*;