aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2021-10-14 18:23:12 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-10-14 18:23:12 +0000
commit2335e55250a1697d3cfe3f5250b3a23bbd3431ce (patch)
tree0c456b741b024344a572c19e339051b558380ecd
parenta4951681b23b361be74e2e9fbd49134d0b9ca947 (diff)
parentbb3ba3621595ddacd4e4efe0bca88d5ffd0a907d (diff)
downloadder-parser-2335e55250a1697d3cfe3f5250b3a23bbd3431ce.tar.gz
Merge "Upgrade rust/crates/der-parser to 6.0.0" am: bb3ba36215
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/der-parser/+/1833332 Change-Id: Idd3bb9e4d407deef170d1044705a6582188a586e
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp5
-rw-r--r--CHANGELOG.md36
-rw-r--r--Cargo.toml26
-rw-r--r--Cargo.toml.orig14
-rw-r--r--METADATA8
-rw-r--r--README.md8
-rw-r--r--cargo2android.json2
-rw-r--r--patches/bitvec_dep.patch44
-rw-r--r--src/ber/ber.rs96
-rw-r--r--src/ber/mod.rs5
-rw-r--r--src/ber/parser.rs44
-rw-r--r--src/ber/print.rs15
-rw-r--r--src/ber/serialize.rs12
-rw-r--r--src/der/mod.rs4
-rw-r--r--src/der/parser.rs29
-rw-r--r--src/error.rs10
-rw-r--r--src/lib.rs43
-rw-r--r--src/macros.rs668
-rw-r--r--src/oid.rs26
-rw-r--r--tests/ber_parser.rs31
-rw-r--r--tests/constructed.rs137
-rw-r--r--tests/der_parser.rs106
-rw-r--r--tests/macros.rs129
-rw-r--r--tests/oid.rs1
-rw-r--r--tests/primitive.rs27
26 files changed, 364 insertions, 1164 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index d5c766e..4eaee56 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "c8adf28076c11651618bcf414a20ecd0bd896315"
+ "sha1": "7b9b5b84387d7c4707b1abc7a13faba515b7c08e"
}
}
diff --git a/Android.bp b/Android.bp
index bd24618..55296a0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,8 +1,6 @@
// This file is generated by cargo2android.py --config cargo2android.json.
// Do not modify this file as changes will be overridden on upgrade.
-
-
package {
default_applicable_licenses: ["external_rust_crates_der-parser_license"],
}
@@ -43,11 +41,14 @@ rust_library {
name: "libder_parser",
host_supported: true,
crate_name: "der_parser",
+ cargo_env_compat: true,
+ cargo_pkg_version: "6.0.0",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
"bigint",
"num-bigint",
+ "std",
],
rustlibs: [
"libnom",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4bc3295..2fa3705 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,21 +8,39 @@
### Thanks
-## 5.1.2
+## 6.0.0
-### Changed/Fixed
-
-- Make `BerError` Copy + Clone
-- Fix clippy warnings (rustc 1.54)
-
-## 5.1.1
+This release has several major changes:
+- upgrade to nom 7
+- add support for `no_std`
+- remove all macros
+- update MSRV to 1.48
### Changed/Fixed
+- Do not attempt to parse PRIVATE object contents (closes #48)
- BER: raise error if using Indefinite length and not constructed
+- Fix `oid!` macro to be independant of `der_parser` crate name and path (#46)
+- Simplify `der-oid-macro`, do not depend on `nom`
- Fix `INTEGER` signed/unsigned parsing (#49)
-- Fix INTEGER signed/unsigned parsing for bigint/biguint (#49)
-- Doc: clarify documentation for parsing integers (#49)
+- Change `as_bigint()` and `as_uint()` to return a `Result`
+- Remove deprecated functions
+
+### Added
+
+- Added support for `no_std` (#50)
+- Make `BerError` Copy + Clone (#51)
+- Add feature 'bitvec' for `.as_bitslice()` methods
+
+### Removed
+
+- Remove all macros
+
+### Thanks
+
+- @yoguorui for `no_std` support
+- @SergioBenitez for `BerError` traits
+- @lilyball for `INTEGER` parsing
## 5.1.0
diff --git a/Cargo.toml b/Cargo.toml
index 9715d20..55418dc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
# 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
+# 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)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "der-parser"
-version = "5.1.2"
+version = "6.0.0"
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"
@@ -26,15 +25,19 @@ repository = "https://github.com/rusticata/der-parser.git"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
+[dependencies.bitvec]
+version = "0.22"
+optional = true
+
[dependencies.cookie-factory]
version = "0.3.0"
optional = true
[dependencies.der-oid-macro]
-version = "0.4"
+version = "0.5"
[dependencies.nom]
-version = "6.0"
+version = "7.0"
[dependencies.num-bigint]
version = "0.4"
@@ -44,7 +47,7 @@ optional = true
version = "0.2"
[dependencies.rusticata-macros]
-version = "3.0.1"
+version = "4.0"
[dev-dependencies.hex-literal]
version = "0.3"
@@ -56,6 +59,7 @@ version = "1.0"
[features]
bigint = ["num-bigint"]
-default = []
-serialize = ["cookie-factory"]
+default = ["std"]
+serialize = ["std", "cookie-factory"]
+std = []
unstable = []
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index e2a6c3f..69f5242 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -5,7 +5,7 @@ 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"
+version = "6.0.0"
authors = ["Pierre Chifflier <chifflier@wzdftpd.net>"]
categories = ["parser-implementations"]
readme = "README.md"
@@ -32,19 +32,21 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
+bitvec = { version="0.22", optional=true }
cookie-factory = { version="0.3.0", optional=true }
-nom = "6.0"
-rusticata-macros = "3.0.1"
+nom = "7.0"
+rusticata-macros = "4.0"
num-traits = "0.2"
num-bigint = { version = "0.4", optional = true }
-der-oid-macro = { version = "0.4", path = "./der-oid-macro" }
+der-oid-macro = { version = "0.5", path = "./der-oid-macro" }
[features]
-default = []
+default = ["std"]
bigint = ["num-bigint"]
-serialize = ["cookie-factory"]
+serialize = ["std", "cookie-factory"]
unstable = []
+std = []
[dev-dependencies]
hex-literal = "0.3"
diff --git a/METADATA b/METADATA
index c3a9cdb..c30f813 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ 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-6.0.0.crate"
}
- version: "5.1.2"
+ version: "6.0.0"
license_type: NOTICE
last_upgrade_date {
year: 2021
- month: 8
- day: 9
+ month: 9
+ day: 27
}
}
diff --git a/README.md b/README.md
index 03f33bc..42f3ee4 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,9 @@
[![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)
+[![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.0+-lightgray.svg)](#rust-version-requirements)
# BER/DER Parser
@@ -174,7 +174,7 @@ 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()))
+assert_eq!(object.as_bigint(), Ok(65537.into()))
```
Access to the raw value is possible using the `as_slice` method.
@@ -198,7 +198,7 @@ Some parsing tools (for ex for tagged objects) are available in different forms:
## Rust version requirements
-The 5.0 series of `der-parser` requires **Rustc version 1.44 or greater**, based on nom 6
+The 6.0 series of `der-parser` requires **Rustc version 1.48 or greater**, based on nom 7
dependencies.
# Serialization
diff --git a/cargo2android.json b/cargo2android.json
index fd3c228..1a78574 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,6 +1,6 @@
{
"device": true,
- "features": "bigint",
+ "features": "bigint,std",
"run": true
}
diff --git a/patches/bitvec_dep.patch b/patches/bitvec_dep.patch
deleted file mode 100644
index 40bad0b..0000000
--- a/patches/bitvec_dep.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-diff --git a/src/ber/ber.rs b/src/ber/ber.rs
-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;
-+#[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> {
- }
-
- /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
-+ #[cfg(not(any(target_os = "android", target_os = "linux")))]
- pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
- self.content.as_bitslice()
- }
-@@ -678,6 +680,7 @@ impl<'a> BerObjectContent<'a> {
- }
-
- /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
-+ #[cfg(not(any(target_os = "android", target_os = "linux")))]
- pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
- self.as_slice()
- .and_then(|s| BitSlice::<Msb0, _>::from_slice(s).ok_or(BerError::BerValueError))
-@@ -908,6 +911,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)
- }
-@@ -981,6 +985,7 @@ mod tests {
- }
-
- #[test]
-+ #[cfg(not(any(target_os = "android", target_os = "linux")))]
- fn test_der_bitslice() {
- let obj = BitStringObject {
- data: &[0x0f, 0x00, 0x40],
diff --git a/src/ber/ber.rs b/src/ber/ber.rs
index e7bd384..47d5069 100644
--- a/src/ber/ber.rs
+++ b/src/ber/ber.rs
@@ -2,15 +2,17 @@ use crate::ber::bitstring_to_u64;
use crate::ber::integer::*;
use crate::error::BerError;
use crate::oid::Oid;
-#[cfg(not(any(target_os = "android", target_os = "linux")))]
-use nom::bitvec::{order::Msb0, slice::BitSlice};
+use alloc::borrow::ToOwned;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+#[cfg(feature = "bitvec")]
+use bitvec::{order::Msb0, slice::BitSlice};
+use core::convert::AsRef;
+use core::convert::From;
+use core::convert::TryFrom;
+use core::fmt;
+use core::ops::Index;
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,9 +185,11 @@ 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]),
+ Unknown(BerClass, BerTag, &'a [u8]),
}
impl fmt::Display for BerClass {
@@ -391,15 +395,6 @@ impl<'a> BerObject<'a> {
BerObject::from_obj(BerObjectContent::Set(l))
}
- /// Build a BER header from this object content
- #[deprecated(
- since = "0.5.0",
- note = "please use `obj.header` or `obj.header.clone()` instead"
- )]
- pub fn to_header(&self) -> BerObjectHeader {
- 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.
@@ -519,7 +514,7 @@ impl<'a> BerObject<'a> {
}
/// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
- #[cfg(not(any(target_os = "android", target_os = "linux")))]
+ #[cfg(feature = "bitvec")]
pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
self.content.as_bitslice()
}
@@ -595,16 +590,6 @@ impl<'a> From<BerObjectContent<'a>> for BerObject<'a> {
}
}
-/// Replacement function for Option.xor (>= 1.37)
-#[inline]
-pub(crate) fn xor_option<T>(opta: Option<T>, optb: Option<T>) -> Option<T> {
- match (opta, optb) {
- (Some(a), None) => Some(a),
- (None, Some(b)) => Some(b),
- _ => None,
- }
-}
-
/// Compare two BER headers. `len` fields are compared only if both objects have it set (same for `raw_tag`)
impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> {
fn eq(&self, other: &BerObjectHeader) -> bool {
@@ -620,7 +605,7 @@ impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> {
}
&& {
// it tag is present for both, compare it
- if xor_option(self.raw_tag, other.raw_tag).is_none() {
+ if self.raw_tag.xor(other.raw_tag).is_none() {
self.raw_tag == other.raw_tag
} else {
true
@@ -735,7 +720,7 @@ impl<'a> BerObjectContent<'a> {
}
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 +728,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)
@@ -802,10 +787,10 @@ impl<'a> BerObjectContent<'a> {
}
/// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
- #[cfg(not(any(target_os = "android", target_os = "linux")))]
+ #[cfg(feature = "bitvec")]
pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
self.as_slice()
- .and_then(|s| BitSlice::<Msb0, _>::from_slice(s).ok_or(BerError::BerValueError))
+ .and_then(|s| BitSlice::<Msb0, _>::from_slice(s).map_err(|_| BerError::BerValueError))
}
pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
@@ -842,7 +827,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),
}
}
@@ -890,7 +876,8 @@ impl<'a> BerObjectContent<'a> {
BerObjectContent::GraphicString(_) => BerTag::GraphicString,
BerObjectContent::GeneralString(_) => BerTag::GeneralString,
BerObjectContent::Tagged(_,x,_) |
- BerObjectContent::Unknown(x,_) => *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 !
}
@@ -917,12 +904,12 @@ impl<'a> BerObject<'a> {
///
/// let (_, object) = parse_ber_integer(data).expect("parsing failed");
/// # #[cfg(feature = "bigint")]
- /// assert_eq!(object.as_bigint(), Some(65537.into()))
+ /// assert_eq!(object.as_bigint(), Ok(65537.into()))
/// ```
- pub fn as_bigint(&self) -> Option<BigInt> {
+ pub fn as_bigint(&self) -> Result<BigInt, BerError> {
match self.content {
- BerObjectContent::Integer(s) => Some(BigInt::from_signed_bytes_be(s)),
- _ => None,
+ BerObjectContent::Integer(s) => Ok(BigInt::from_signed_bytes_be(s)),
+ _ => Err(BerError::InvalidTag),
}
}
@@ -939,17 +926,17 @@ impl<'a> BerObject<'a> {
///
/// let (_, object) = parse_ber_integer(data).expect("parsing failed");
/// # #[cfg(feature = "bigint")]
- /// assert_eq!(object.as_biguint(), Some(65537_u32.into()))
+ /// assert_eq!(object.as_biguint(), Ok(65537_u32.into()))
/// ```
- pub fn as_biguint(&self) -> Option<BigUint> {
+ pub fn as_biguint(&self) -> Result<BigUint, BerError> {
match self.content {
BerObjectContent::Integer(s) => {
if is_highest_bit_set(s) {
- return None;
+ return Err(BerError::IntegerNegative);
}
- Some(BigUint::from_bytes_be(s))
+ Ok(BigUint::from_bytes_be(s))
}
- _ => None,
+ _ => Err(BerError::InvalidTag),
}
}
}
@@ -1066,9 +1053,9 @@ impl<'a> BitStringObject<'a> {
}
/// Constructs a shared `&BitSlice` reference over the object data.
- #[cfg(not(any(target_os = "android", target_os = "linux")))]
+ #[cfg(feature = "bitvec")]
pub fn as_bitslice(&self) -> Option<&BitSlice<Msb0, u8>> {
- BitSlice::<Msb0, _>::from_slice(self.data)
+ BitSlice::<Msb0, _>::from_slice(self.data).ok()
}
}
@@ -1138,17 +1125,18 @@ mod tests {
assert!(obj.is_set(17));
}
+ #[cfg(feature = "bitvec")]
#[test]
- #[cfg(not(any(target_os = "android", target_os = "linux")))]
fn test_der_bitslice() {
+ use std::string::String;
let obj = BitStringObject {
data: &[0x0f, 0x00, 0x40],
};
let slice = obj.as_bitslice().expect("as_bitslice");
- assert_eq!(slice.get(0), Some(&false));
- assert_eq!(slice.get(7), Some(&true));
- assert_eq!(slice.get(9), Some(&false));
- assert_eq!(slice.get(17), Some(&true));
+ assert_eq!(slice.get(0).as_deref(), Some(&false));
+ assert_eq!(slice.get(7).as_deref(), Some(&true));
+ assert_eq!(slice.get(9).as_deref(), Some(&false));
+ assert_eq!(slice.get(17).as_deref(), Some(&true));
let s = slice.iter().fold(String::with_capacity(24), |mut acc, b| {
acc += if *b { "1" } else { "0" };
acc
@@ -1172,7 +1160,7 @@ mod tests {
let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
let expected = ::num_bigint::BigInt::from(0x10001);
- assert_eq!(obj.as_bigint(), Some(expected));
+ assert_eq!(obj.as_bigint(), Ok(expected));
}
#[cfg(feature = "bigint")]
@@ -1181,6 +1169,6 @@ mod tests {
let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
let expected = ::num_bigint::BigUint::from(0x10001_u32);
- assert_eq!(obj.as_biguint(), Some(expected));
+ assert_eq!(obj.as_biguint(), Ok(expected));
}
}
diff --git a/src/ber/mod.rs b/src/ber/mod.rs
index f2fa5f9..c674d93 100644
--- a/src/ber/mod.rs
+++ b/src/ber/mod.rs
@@ -62,3 +62,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..81ccef8 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))
@@ -995,22 +993,6 @@ where
}))(i)
}
-/// Parse an optional tagged object, applying function to get content
-///
-/// This function is deprecated, use
-/// [parse_ber_explicit_optional](fn.parse_ber_explicit_optional.html) instead.
-#[deprecated(
- since = "5.0.0",
- note = "Please use `parse_ber_explicit_optional` instead"
-)]
-#[inline]
-pub fn parse_ber_explicit<F>(i: &[u8], tag: BerTag, f: F) -> BerResult
-where
- F: Fn(&[u8]) -> BerResult,
-{
- parse_ber_explicit_optional(i, tag, f)
-}
-
/// Parse an implicit tagged object, applying function to read content
///
/// Note: unlike explicit tagged functions, the callback must be a *content* parsing function,
@@ -1184,10 +1166,16 @@ 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);
+ let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
let obj = BerObject::from_header_and_content(hdr, content);
return Ok((rem, obj));
}
@@ -1196,7 +1184,7 @@ pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult {
Ok((rem, content)) => Ok((rem, BerObject::from_header_and_content(hdr, content))),
Err(Err::Error(BerError::UnknownTag)) => {
let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
- let content = BerObjectContent::Unknown(hdr.tag, content);
+ let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
let obj = BerObject::from_header_and_content(hdr, content);
Ok((rem, obj))
}
diff --git a/src/ber/print.rs b/src/ber/print.rs
index b3ae221..e80eb5e 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))?;
@@ -138,7 +143,7 @@ impl<'a> fmt::Debug for PrettyBer<'a> {
writeln!(f, "]")?;
Ok(())
},
- BerObjectContent::Unknown(tag,o) => writeln!(f, "Unknown({:?},{:x?})", tag, o),
+ BerObjectContent::Unknown(class, tag,o) => writeln!(f, "Unknown({:?},{:?},{:x?})", class, tag, o),
}
}
}
diff --git a/src/ber/serialize.rs b/src/ber/serialize.rs
index 7ffedc2..8c82e29 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;
@@ -8,8 +9,6 @@ use cookie_factory::sequence::tuple;
use cookie_factory::{GenError, SerializeFn};
use std::io::Write;
-// we do not use .copied() for compatibility with 1.34
-#[allow(clippy::map_clone)]
fn encode_length<'a, W: Write + 'a, Len: Into<BerSize>>(len: Len) -> impl SerializeFn<W> + 'a {
let l = len.into();
move |out| {
@@ -23,7 +22,7 @@ fn encode_length<'a, W: Write + 'a, Len: Into<BerSize>>(len: Len) -> impl Serial
let v: Vec<u8> = sz
.to_be_bytes()
.iter()
- .map(|&x| x)
+ .cloned()
.skip_while(|&b| b == 0)
.collect();
let b0 = 0b1000_0000 | (v.len() as u8);
@@ -108,8 +107,6 @@ pub fn ber_encode_tagged_implicit<'a, W: Write + Default + AsRef<[u8]> + 'a>(
}
}
-// we do not use .copied() for compatibility with 1.34
-#[allow(clippy::map_clone)]
fn ber_encode_object_content<'a, W: Write + Default + AsRef<[u8]> + 'a>(
c: &'a BerObjectContent,
) -> impl SerializeFn<W> + 'a {
@@ -129,7 +126,7 @@ fn ber_encode_object_content<'a, W: Write + Default + AsRef<[u8]> + 'a>(
let v: Vec<u8> = i
.to_be_bytes()
.iter()
- .map(|&x| x)
+ .cloned()
.skip_while(|&b| b == 0)
.collect();
slice(v)(out)
@@ -158,12 +155,13 @@ 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!
ber_encode_object(inner)(out)
}
- BerObjectContent::Unknown(_tag, s) => slice(s)(out),
+ BerObjectContent::Unknown(_, _, s) => slice(s)(out),
}
}
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..04b4b23 100644
--- a/src/der/parser.rs
+++ b/src/der/parser.rs
@@ -5,7 +5,6 @@ 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};
/// Parse DER object recursively
///
@@ -317,22 +316,6 @@ where
parse_ber_explicit_optional(i, tag, f)
}
-/// Parse an optional tagged object, applying function to get content
-///
-/// This function is deprecated, use
-/// [parse_der_explicit_optional](fn.parse_der_explicit_optional.html) instead.
-#[deprecated(
- since = "4.1.0",
- note = "Please use `parse_der_explicit_optional` instead"
-)]
-#[inline]
-pub fn parse_der_explicit<F>(i: &[u8], tag: DerTag, f: F) -> BerResult
-where
- F: Fn(&[u8]) -> BerResult,
-{
- parse_der_explicit_optional(i, tag, f)
-}
-
/// Parse an implicit tagged object, applying function to read content
///
/// Note: unlike explicit tagged functions, the callback must be a *content* parsing function,
@@ -575,10 +558,16 @@ 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);
+ let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content);
let obj = DerObject::from_header_and_content(hdr, content);
return Ok((i, obj));
}
@@ -587,7 +576,7 @@ fn der_read_element_content_recursive<'a>(
Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))),
Err(Err::Error(BerError::UnknownTag)) => {
let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?;
- let content = DerObjectContent::Unknown(hdr.tag, content);
+ let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content);
let obj = DerObject::from_header_and_content(hdr, content);
Ok((rem, obj))
}
diff --git a/src/error.rs b/src/error.rs
index 803bdee..8a496a8 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
///
@@ -97,11 +96,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..a5f6e2e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,9 +3,9 @@
//! [![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)
+//! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.0+-lightgray.svg)](#rust-version-requirements)
//!
//! # BER/DER Parser
//!
@@ -172,7 +172,7 @@
//! assert_eq!(object.as_u64(), Ok(65537));
//!
//! #[cfg(feature = "bigint")]
-//! assert_eq!(object.as_bigint(), Some(65537.into()))
+//! assert_eq!(object.as_bigint(), Ok(65537.into()))
//! ```
//!
//! Access to the raw value is possible using the `as_slice` method.
@@ -196,7 +196,7 @@
//!
//! ## Rust version requirements
//!
-//! The 5.0 series of `der-parser` requires **Rustc version 1.44 or greater**, based on nom 6
+//! The 6.0 series of `der-parser` requires **Rustc version 1.48 or greater**, based on nom 7
//! dependencies.
//!
//! # Serialization
@@ -237,9 +237,13 @@
no_crate_inject,
attr(deny(warnings/*, rust_2018_idioms*/), allow(dead_code, unused_variables))
))]
+#![no_std]
+#[cfg(any(test, feature = "std"))]
#[macro_use]
-mod macros;
+extern crate std;
+
+extern crate alloc;
#[allow(clippy::module_inception)]
pub mod ber;
@@ -259,7 +263,32 @@ pub use num_bigint;
// re-exports nom macros, so this crate's macros can be used without importing nom
pub use nom::IResult;
#[doc(hidden)]
-pub use rusticata_macros::{custom_check, flat_take};
+pub use rusticata_macros::custom_check;
+
+#[doc(hidden)]
+pub mod exports {
+ pub use alloc::borrow;
+ pub use der_oid_macro;
+}
/// Procedural macro to get encoded oids, see the [oid module](oid/index.html).
-pub use der_oid_macro::oid;
+#[macro_export]
+macro_rules! oid {
+ (raw $($args:tt)*) => {{
+ $crate::exports::der_oid_macro::encode_oid!($($args)*)
+ }};
+ (rel $($args:tt)*) => {{
+ $crate::oid::Oid::new_relative(
+ $crate::exports::borrow::Cow::Borrowed(&
+ $crate::exports::der_oid_macro::encode_oid!(rel $($args)*)
+ )
+ )
+ }};
+ ($($args:tt)*) => {{
+ $crate::oid::Oid::new(
+ $crate::exports::borrow::Cow::Borrowed(&
+ $crate::exports::der_oid_macro::encode_oid!($($args)*)
+ )
+ )
+ }};
+}
diff --git a/src/macros.rs b/src/macros.rs
deleted file mode 100644
index 24ad59b..0000000
--- a/src/macros.rs
+++ /dev/null
@@ -1,668 +0,0 @@
-/// Internal parser, do not use directly
-#[doc(hidden)]
-#[macro_export]
-macro_rules! fold_der_defined_m(
- (__impl $i:expr, $acc:ident, $f:ident) => ( {
- match $f($i) {
- Ok((rem,res)) => { $acc.push(res); Ok((rem,$acc)) },
- Err(e) => Err(e)
- }
- });
- (__impl $i:expr, $acc:ident, $submac:ident!( $($args:tt)* ) ) => ( {
- match $submac!($i, $($args)*) {
- Ok((rem,res)) => { $acc.push(res); Ok((rem,$acc)) },
- Err(e) => Err(e)
- }
- });
- (__impl $i:expr, $acc:ident, $f:ident >> $($rest:tt)*) => (
- {
- match $f($i) {
- Ok((rem,res)) => {
- $acc.push(res);
- fold_der_defined_m!(__impl rem, $acc, $($rest)* )
- },
- Err(e) => Err(e)
- }
- }
- );
- (__impl $i:expr, $acc:ident, $submac:ident!( $($args:tt)* ) >> $($rest:tt)*) => (
- {
- match $submac!($i, $($args)*) {
- Ok((rem,res)) => {
- $acc.push(res);
- fold_der_defined_m!(__impl rem, $acc, $($rest)* )
- },
- Err(e) => Err(e)
- }
- }
- );
-
- ($i:expr, $($rest:tt)* ) => (
- {
- let mut v = Vec::new();
- fold_der_defined_m!(__impl $i, v, $($rest)*)
- }
- );
-);
-
-/// Internal parser, do not use directly
-#[doc(hidden)]
-#[macro_export]
-macro_rules! parse_ber_defined_m(
- ($i:expr, $tag:expr, $($args:tt)*) => (
- {
- use $crate::ber::parse_ber_container;
- use $crate::error::BerError;
- parse_ber_container(|content, hdr| {
- if !hdr.is_constructed() {
- return Err(nom::Err::Error(BerError::ConstructExpected.into()));
- }
- if hdr.tag != $tag {
- return Err(nom::Err::Error(BerError::InvalidTag.into()));
- }
- let (rem, content) = fold_der_defined_m!(content, $($args)* )?;
- Ok((rem, (hdr, content)))
- })($i)
- }
- );
-);
-
-/// Parse a defined sequence of DER elements (deprecated)
-///
-/// Given a list of expected parsers, apply them to build a DER sequence.
-///
-/// Deprecated, use [`parse_der_sequence_defined`](macro.parse_der_sequence_defined.html) instead.
-#[macro_export]
-#[deprecated(since = "3.0.0", note = "Use parse_der_sequence_defined")]
-macro_rules! parse_der_sequence_defined_m(
- ($i:expr, $($args:tt)*) => ({
- parse_der_sequence_defined!($i, $($args)*)
- });
-);
-
-/// Parse a defined set of DER elements (deprecated)
-///
-/// Given a list of expected parsers, apply them to build a DER set.
-///
-/// Deprecated, use [`parse_der_set_defined`](macro.parse_der_set_defined.html) instead.
-#[macro_export]
-#[deprecated(since = "3.0.0", note = "Use parse_der_set_defined")]
-macro_rules! parse_der_set_defined_m(
- ($i:expr, $($args:tt)*) => ({
- parse_der_set_defined!($i, $($args)*)
- });
-);
-
-/// Internal parser, do not use directly
-#[doc(hidden)]
-#[macro_export]
-macro_rules! fold_parsers(
- ($i:expr, $($args:tt)*) => (
- {
- let parsers = [ $($args)* ];
- parsers.iter().fold(
- (Ok(($i,vec![]))),
- |r, f| {
- match r {
- Ok((rem,mut v)) => {
- map!(rem, f, |x| { v.push(x); v })
- }
- Err(e) => Err(e)
- }
- }
- )
- }
- );
-);
-
-/// Internal parser, do not use directly
-#[doc(hidden)]
-#[macro_export]
-macro_rules! parse_der_defined(
- ($i:expr, $tag:expr, $($args:tt)*) => (
- {
- use $crate::ber::ber_read_element_header;
- let res =
- do_parse!(
- $i,
- hdr: ber_read_element_header >>
- custom_check!(hdr.class != $crate::ber::BerClass::Universal, $crate::error::BerError::InvalidClass) >>
- custom_check!(hdr.structured != 0b1, $crate::error::BerError::ConstructExpected) >>
- custom_check!(hdr.tag != $tag, $crate::error::BerError::InvalidTag) >>
- content: take!(hdr.len) >>
- (hdr,content)
- );
- match res {
- Ok((_rem,o)) => {
- match fold_parsers!(o.1, $($args)* ) {
- Ok((rem,v)) => {
- if rem.len() != 0 { Err(::nom::Err::Error($crate::error::BerError::ObjectTooShort)) }
- else { Ok((_rem,(o.0,v))) }
- },
- Err(e) => Err(e)
- }
- },
- Err(e) => Err(e)
- }
- }
- );
-);
-
-/// Parse a defined sequence of DER elements
-///
-/// Given a list of expected parsers, apply them to build a DER sequence.
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::{parse_ber_integer, BerObject};
-/// # use der_parser::error::BerResult;
-/// #
-/// # fn main() {
-/// fn localparse_seq(i:&[u8]) -> BerResult {
-/// parse_der_sequence_defined!(i,
-/// parse_ber_integer >>
-/// parse_ber_integer
-/// )
-/// }
-///
-/// let empty = &b""[..];
-/// let bytes = [ 0x30, 0x0a,
-/// 0x02, 0x03, 0x01, 0x00, 0x01,
-/// 0x02, 0x03, 0x01, 0x00, 0x00,
-/// ];
-/// let expected = BerObject::from_seq(vec![
-/// BerObject::from_int_slice(b"\x01\x00\x01"),
-/// BerObject::from_int_slice(b"\x01\x00\x00"),
-/// ]);
-/// assert_eq!(localparse_seq(&bytes), Ok((empty, expected)));
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_sequence_defined(
- ($i:expr, $($args:tt)*) => ({
- use nom::map;
- map!(
- $i,
- parse_ber_defined_m!($crate::ber::BerTag::Sequence, $($args)*),
- |(hdr,o)| $crate::ber::BerObject::from_header_and_content(hdr,$crate::ber::BerObjectContent::Sequence(o))
- )
- });
-);
-
-/// Parse a defined set of DER elements
-///
-/// Given a list of expected parsers, apply them to build a DER set.
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::{parse_ber_integer, BerObject};
-/// # use der_parser::error::BerResult;
-/// #
-/// # fn main() {
-/// fn localparse_set(i:&[u8]) -> BerResult {
-/// parse_der_set_defined!(i,
-/// parse_ber_integer >>
-/// parse_ber_integer
-/// )
-/// }
-///
-/// let empty = &b""[..];
-/// let bytes = [ 0x31, 0x0a,
-/// 0x02, 0x03, 0x01, 0x00, 0x01,
-/// 0x02, 0x03, 0x01, 0x00, 0x00,
-/// ];
-/// let expected = BerObject::from_set(vec![
-/// BerObject::from_int_slice(b"\x01\x00\x01").set_raw_tag(Some(&[0x2])),
-/// BerObject::from_int_slice(b"\x01\x00\x00").set_raw_tag(Some(&[0x2])),
-/// ]).set_raw_tag(Some(&[0x31]));
-/// assert_eq!(localparse_set(&bytes), Ok((empty, expected)));
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_set_defined(
- ($i:expr, $($args:tt)*) => ({
- use nom::map;
- map!(
- $i,
- parse_ber_defined_m!($crate::ber::BerTag::Set, $($args)*),
- |(hdr,o)| $crate::ber::BerObject::from_header_and_content(hdr,$crate::ber::BerObjectContent::Set(o))
- )
- });
-);
-
-/// Parse a sequence of identical DER elements
-///
-/// Given a subparser for a DER type, parse a sequence of identical objects.
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::{parse_ber_integer, BerObject};
-/// # use der_parser::error::BerResult;
-/// #
-/// # fn main() {
-/// fn parser(i:&[u8]) -> BerResult {
-/// parse_der_sequence_of!(i, parse_ber_integer)
-/// }
-///
-/// let empty = &b""[..];
-/// let bytes = [ 0x30, 0x0a,
-/// 0x02, 0x03, 0x01, 0x00, 0x01,
-/// 0x02, 0x03, 0x01, 0x00, 0x00,
-/// ];
-/// let expected = BerObject::from_seq(vec![
-/// BerObject::from_int_slice(b"\x01\x00\x01"),
-/// BerObject::from_int_slice(b"\x01\x00\x00"),
-/// ]);
-/// assert_eq!(parser(&bytes), Ok((empty, expected)));
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_sequence_of(
- ($i:expr, $f:ident) => ({
- use $crate::ber::parse_ber_sequence_of;
- parse_ber_sequence_of($f)($i)
- })
-);
-
-/// Parse a set of identical DER elements
-///
-/// Given a subparser for a DER type, parse a set of identical objects.
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::{parse_ber_integer, BerObject};
-/// # use der_parser::error::BerResult;
-/// #
-/// # fn main() {
-/// fn parser(i:&[u8]) -> BerResult {
-/// parse_der_set_of!(i, parse_ber_integer)
-/// }
-///
-/// let empty = &b""[..];
-/// let bytes = [ 0x31, 0x0a,
-/// 0x02, 0x03, 0x01, 0x00, 0x01,
-/// 0x02, 0x03, 0x01, 0x00, 0x00,
-/// ];
-/// let expected = BerObject::from_set(vec![
-/// BerObject::from_int_slice(b"\x01\x00\x01"),
-/// BerObject::from_int_slice(b"\x01\x00\x00"),
-/// ]);
-/// assert_eq!(parser(&bytes), Ok((empty, expected)));
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_set_of(
- ($i:expr, $f:ident) => ({
- use $crate::ber::parse_ber_set_of;
- parse_ber_set_of($f)($i)
- })
-);
-
-/// Parse an optional DER element
-///
-/// Try to parse an optional DER element, and return it as a `ContextSpecific` item with tag 0.
-/// If the parsing failed, the `ContextSpecific` object has value `None`.
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::*;
-/// # use der_parser::error::BerResult;
-/// #
-/// # fn main() {
-/// let empty = &b""[..];
-/// let bytes1 = [ 0x30, 0x0a,
-/// 0x0a, 0x03, 0x00, 0x00, 0x01,
-/// 0x02, 0x03, 0x01, 0x00, 0x01];
-/// let bytes2 = [ 0x30, 0x05,
-/// 0x02, 0x03, 0x01, 0x00, 0x01];
-/// let expected1 = BerObject::from_seq(vec![
-/// BerObject::from_obj(BerObjectContent::Optional(Some(Box::new(
-/// BerObject::from_obj(BerObjectContent::Enum(1)),
-/// )))),
-/// BerObject::from_int_slice(b"\x01\x00\x01"),
-/// ]);
-/// let expected2 = BerObject::from_seq(vec![
-/// BerObject::from_obj(
-/// BerObjectContent::Optional(None),
-/// ),
-/// BerObject::from_int_slice(b"\x01\x00\x01"),
-/// ]);
-///
-/// fn parse_optional_enum(i:&[u8]) -> BerResult {
-/// parse_der_optional!(i, parse_ber_enum)
-/// }
-/// fn parser(i:&[u8]) -> BerResult {
-/// parse_der_sequence_defined!(i,
-/// parse_optional_enum >>
-/// parse_ber_integer
-/// )
-/// }
-///
-/// assert_eq!(parser(&bytes1), Ok((empty, expected1)));
-/// assert_eq!(parser(&bytes2), Ok((empty, expected2)));
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_optional(
- ($i:expr, $f:ident) => (
- match $f($i) {
- Ok((rem, obj)) => {
- let opt =
- $crate::ber::BerObject::from_header_and_content(
- obj.header.clone(),
- $crate::ber::BerObjectContent::Optional(Some(Box::new(obj)))
- );
- Ok((rem, opt))
- }
- Err(_) => {
- let opt = $crate::ber::BerObject::from_obj(
- $crate::ber::BerObjectContent::Optional(None)
- );
- Ok(($i, opt))
- }
- }
- // alt!(
- // $i,
- // complete!(do_parse!(
- // content: call!($f) >>
- // (
- // $crate::ber::BerObject::from_obj(
- // $crate::ber::BerObjectContent::ContextSpecific($crate::ber::BerTag(0) /* XXX */,Some(Box::new(content)))
- // )
- // )
- // )) |
- // complete!(call!($crate::ber::parse_ber_explicit_failed,$crate::ber::BerTag(0) /* XXX */))
- // )
- )
-);
-
-/// Parse a constructed DER element
-///
-/// Read a constructed DER element (sequence or set, typically) using the provided functions.
-/// This is generally used to build a struct from a DER sequence.
-///
-/// The returned object is a tuple containing a [`BerObjectHeader`](struct.BerObjectHeader.html)
-/// and the object returned by the subparser.
-///
-/// To ensure the subparser consumes all bytes from the constructed object, add the `eof!()`
-/// subparser as the last parsing item.
-///
-/// To verify the tag of the constructed element, use the `TAG` version, for ex
-/// `parse_der_struct!(i, TAG DerTag::Sequence, parse_der_integer)`
-///
-/// Similar to [`parse_der_sequence_defined`](macro.parse_der_sequence_defined.html), but using the
-/// `do_parse` macro from nom.
-/// This allows declaring variables, and running code at the end.
-///
-/// # Examples
-///
-/// Basic struct parsing (ignoring tag):
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::*;
-/// # use der_parser::error::BerResult;
-/// # use nom::eof;
-/// #
-/// # fn main() {
-/// #[derive(Debug, PartialEq)]
-/// struct MyStruct<'a>{
-/// a: BerObject<'a>,
-/// b: BerObject<'a>,
-/// }
-///
-/// fn parse_struct01(i: &[u8]) -> BerResult<MyStruct> {
-/// parse_der_struct!(
-/// i,
-/// a: parse_ber_integer >>
-/// b: parse_ber_integer >>
-/// eof!() >>
-/// ( MyStruct{ a: a, b: b } )
-/// )
-/// }
-///
-/// let bytes = [ 0x30, 0x0a,
-/// 0x02, 0x03, 0x01, 0x00, 0x01,
-/// 0x02, 0x03, 0x01, 0x00, 0x00,
-/// ];
-/// let empty = &b""[..];
-/// let expected = MyStruct {
-/// a: BerObject::from_int_slice(b"\x01\x00\x01"),
-/// b: BerObject::from_int_slice(b"\x01\x00\x00"),
-/// };
-/// let res = parse_struct01(&bytes);
-/// assert_eq!(res, Ok((empty, expected)));
-/// # }
-/// ```
-///
-/// To check the expected tag, use the `TAG <tagname>` variant:
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::*;
-/// # use der_parser::error::BerResult;
-/// # use nom::eof;
-/// #
-/// # fn main() {
-/// struct MyStruct<'a>{
-/// a: BerObject<'a>,
-/// b: BerObject<'a>,
-/// }
-///
-/// fn parse_struct_with_tag(i: &[u8]) -> BerResult<MyStruct> {
-/// parse_der_struct!(
-/// i,
-/// TAG BerTag::Sequence,
-/// a: parse_ber_integer >>
-/// b: parse_ber_integer >>
-/// eof!() >>
-/// ( MyStruct{ a, b } )
-/// )
-/// }
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_struct(
- ($i:expr, TAG $tag:expr, $($rest:tt)*) => ({
- use $crate::ber::parse_ber_container;
- use $crate::error::BerError;
- use nom::do_parse;
- parse_ber_container(
- |i, hdr| {
- if !hdr.is_constructed() {
- return Err(nom::Err::Error(BerError::ConstructExpected.into()));
- }
- if hdr.tag != $tag {
- return Err(nom::Err::Error(BerError::InvalidTag.into()));
- }
- do_parse!(i, $($rest)*)
- }
- )($i)
- });
- ($i:expr, $($rest:tt)*) => ({
- use $crate::ber::parse_ber_container;
- use $crate::error::BerError;
- use nom::do_parse;
- parse_ber_container(
- |i, hdr| {
- if !hdr.is_constructed() {
- return Err(nom::Err::Error(BerError::ConstructExpected.into()));
- }
- do_parse!(i, $($rest)*)
- }
- )($i)
- });
-);
-
-/// Parse a tagged DER element
-///
-/// Read a tagged DER element using the provided function.
-///
-/// The returned object is either the object returned by the subparser, or a nom error.
-/// Unlike [`parse_der_explicit`](fn.parse_der_explicit.html) or
-/// [`parse_der_implicit`](fn.parse_der_implicit.html), the returned values are *not* encapsulated
-/// in a `BerObject` (they are directly returned, without the tag).
-///
-/// To specify the kind of tag, use the EXPLICIT or IMPLICIT keyword. If no keyword is specified,
-/// the parsing is EXPLICIT by default.
-///
-/// When parsing IMPLICIT values, the third argument is a [`DerTag`](enum.DerTag.html) defining the
-/// subtype of the object.
-///
-/// # Examples
-///
-/// The following parses `[2] INTEGER`:
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::{parse_ber_integer, BerObject};
-/// # use nom::map_res;
-/// # use der_parser::error::BerResult;
-/// #
-/// # fn main() {
-/// fn parse_int_explicit(i:&[u8]) -> BerResult<u32> {
-/// map_res!(
-/// i,
-/// parse_der_tagged!(EXPLICIT 2, parse_ber_integer),
-/// |x: BerObject| x.as_tagged()?.2.as_u32()
-/// )
-/// }
-///
-/// let bytes = &[0xa2, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01];
-/// let res = parse_int_explicit(bytes);
-/// match res {
-/// Ok((rem,val)) => {
-/// assert!(rem.is_empty());
-/// assert_eq!(val, 0x10001);
-/// },
-/// Err(e) => panic!("parse_int_explicit failed: {:?}", e),
-/// }
-/// # }
-/// ```
-///
-/// The following parses `[2] IMPLICIT INTEGER`:
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::{BerObject, BerTag};
-/// # use der_parser::error::BerResult;
-/// # use nom::map_res;
-/// #
-/// # fn main() {
-/// fn parse_int_implicit(i:&[u8]) -> BerResult<u32> {
-/// map_res!(
-/// i,
-/// parse_der_tagged!(IMPLICIT 2, BerTag::Integer),
-/// |x: BerObject| x.as_u32()
-/// )
-/// }
-///
-/// let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01];
-/// let res = parse_int_implicit(bytes);
-/// match res {
-/// Ok((rem,val)) => {
-/// assert!(rem.is_empty());
-/// assert_eq!(val, 0x10001);
-/// },
-/// _ => assert!(false)
-/// }
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_tagged(
- ($i:expr, EXPLICIT $tag:expr, $f:ident) => ({
- use $crate::ber::parse_ber_tagged_explicit;
- parse_ber_tagged_explicit(
- $tag,
- $f
- )($i)
- });
- ($i:expr, EXPLICIT $tag:expr, $submac:ident!( $($args:tt)*)) => ({
- use $crate::ber::parse_ber_tagged_explicit;
- parse_ber_tagged_explicit(
- $tag,
- |content| {
- $submac!(content, $($args)*)
- }
- )($i)
- });
- ($i:expr, IMPLICIT $tag:expr, $type:expr) => ({
- use $crate::ber::{ber_read_element_content_as, parse_ber_tagged_implicit};
- parse_ber_tagged_implicit(
- $tag,
- |content, hdr, max_size| {
- ber_read_element_content_as(content, $type, hdr.len, hdr.is_constructed(), max_size)
- }
- )($i)
- });
- ($i:expr, $tag:expr, $f:ident) => ( parse_der_tagged!($i, EXPLICIT $tag, $f) );
-);
-
-/// Parse an application DER element
-///
-/// Read an application DER element using the provided functions.
-/// This is generally used to build a struct from a DER sequence.
-///
-/// The returned object is a tuple containing a [`BerObjectHeader`](struct.BerObjectHeader.html)
-/// and the object returned by the subparser.
-///
-/// To ensure the subparser consumes all bytes from the constructed object, add the `eof!()`
-/// subparser as the last parsing item.
-///
-/// # Examples
-///
-/// The following parses `[APPLICATION 2] INTEGER`:
-///
-/// ```rust
-/// # #[macro_use] extern crate der_parser;
-/// # use der_parser::ber::*;
-/// # use der_parser::error::BerResult;
-/// # use nom::{eof, map_res};
-/// #
-/// # fn main() {
-/// #[derive(Debug, PartialEq)]
-/// struct SimpleStruct {
-/// a: u32,
-/// }
-///
-/// fn parse_app01(i:&[u8]) -> BerResult<SimpleStruct> {
-/// parse_der_application!(
-/// i,
-/// APPLICATION 2,
-/// a: map_res!(parse_ber_integer,|x: BerObject| x.as_u32()) >>
-/// eof!() >>
-/// ( SimpleStruct{ a:a } )
-/// )
-/// }
-///
-/// let bytes = &[0x62, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01];
-/// let res = parse_app01(bytes);
-/// match res {
-/// Ok((rem, app)) => {
-/// assert!(rem.is_empty());
-/// assert_eq!(app, SimpleStruct{ a:0x10001 });
-/// },
-/// _ => assert!(false)
-/// }
-/// # }
-/// ```
-#[macro_export]
-macro_rules! parse_der_application(
- ($i:expr, APPLICATION $tag:expr, $($rest:tt)*) => ({
- use $crate::ber::{parse_ber_container, BerClass, BerTag};
- use $crate::error::BerError;
- use nom::do_parse;
- parse_ber_container(
- |content, hdr| {
- if hdr.class != BerClass::Application {
- return Err(nom::Err::Error(BerError::InvalidClass.into()));
- }
- if hdr.tag != BerTag($tag) {
- return Err(nom::Err::Error(BerError::BerTypeError.into()));
- }
- do_parse!(content, $($rest)* )
- }
- )($i)
- });
- ($i:expr, $tag:expr, $($rest:tt)*) => ( parse_der_application!($i, APPLICATION $tag, $($rest)*) );
-);
diff --git a/src/oid.rs b/src/oid.rs
index fdb17b3..618988d 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,
@@ -212,7 +217,7 @@ impl<'a> Oid<'a> {
oid: self,
pos: 0,
first: false,
- n: std::marker::PhantomData,
+ n: core::marker::PhantomData,
}
}
@@ -248,7 +253,7 @@ impl<'a> Oid<'a> {
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..6f020e3 100644
--- a/tests/ber_parser.rs
+++ b/tests/ber_parser.rs
@@ -220,22 +220,19 @@ fn tc_ber_bigint(i: &[u8], out: Result<BigInt, BerError>) {
}
#[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!("02 01 01"), Ok(BigUint::from(1_u8)) ; "biguint-1")]
+#[test_case(&hex!("02 02 00 ff"), Ok(BigUint::from(255_u8)) ; "biguint-255")]
+#[test_case(&hex!("02 01 ff"), Err(BerError::IntegerNegative) ; "biguint-neg1")]
+#[test_case(&hex!("02 01 80"), Err(BerError::IntegerNegative) ; "biguint-neg128")]
+#[test_case(&hex!("02 02 ff 7f"), Err(BerError::IntegerNegative) ; "biguint-neg129")]
+#[test_case(&hex!("02 09 00 ff ff ff ff ff ff ff ff"), Ok(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(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);
+fn tc_ber_biguint(i: &[u8], out: Result<BigUint, BerError>) {
+ let res = parse_ber_integer(i).and_then(|(rem, ber)| Ok((rem, ber.as_biguint()?)));
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);
+ pretty_assertions::assert_eq!(res, Ok((&b""[..], expected)));
}
Err(e) => {
pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
@@ -543,3 +540,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/constructed.rs b/tests/constructed.rs
index 49bc0c6..20a83a0 100644
--- a/tests/constructed.rs
+++ b/tests/constructed.rs
@@ -1,9 +1,12 @@
use der_parser::ber::*;
+use der_parser::der::*;
use der_parser::error::*;
use der_parser::*;
use hex_literal::hex;
-use nom::combinator::map;
+use nom::branch::alt;
+use nom::combinator::{complete, eof, map, map_res};
use nom::error::ErrorKind;
+use nom::multi::many0;
use nom::sequence::tuple;
use nom::*;
use oid::Oid;
@@ -17,44 +20,33 @@ struct MyStruct<'a> {
}
fn parse_struct01(i: &[u8]) -> BerResult<MyStruct> {
- parse_der_struct!(
- i,
- a: parse_ber_integer >> b: parse_ber_integer >> (MyStruct { a, b })
- )
+ parse_der_sequence_defined_g(|i: &[u8], _| {
+ let (i, a) = parse_ber_integer(i)?;
+ let (i, b) = parse_ber_integer(i)?;
+ Ok((i, MyStruct { a, b }))
+ })(i)
}
fn parse_struct01_complete(i: &[u8]) -> BerResult<MyStruct> {
- parse_der_struct!(
- i,
- a: parse_ber_integer >> b: parse_ber_integer >> eof!() >> (MyStruct { a, b })
- )
-}
-
-// calling user function
-#[allow(dead_code)]
-fn parse_struct02(i: &[u8]) -> BerResult<()> {
- parse_der_struct!(i, _a: parse_ber_integer >> _b: parse_struct01 >> (()))
-}
-
-// embedded DER structs
-#[allow(dead_code)]
-fn parse_struct03(i: &[u8]) -> BerResult<()> {
- parse_der_struct!(
- i,
- _a: parse_ber_integer >> _b: parse_der_struct!(parse_ber_integer >> (())) >> (())
- )
+ parse_der_sequence_defined_g(|i: &[u8], _| {
+ let (i, a) = parse_ber_integer(i)?;
+ let (i, b) = parse_ber_integer(i)?;
+ eof(i)?;
+ Ok((i, MyStruct { a, b }))
+ })(i)
}
// verifying tag
fn parse_struct04(i: &[u8], tag: BerTag) -> BerResult<MyStruct> {
- parse_der_struct!(
- i,
- TAG tag,
- a: parse_ber_integer >>
- b: parse_ber_integer >>
- eof!() >>
- ( MyStruct{ a, b } )
- )
+ parse_der_container(|i: &[u8], hdr| {
+ if hdr.tag != tag {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ let (i, a) = parse_ber_integer(i)?;
+ let (i, b) = parse_ber_integer(i)?;
+ eof(i)?;
+ Ok((i, MyStruct { a, b }))
+ })(i)
}
#[test_case(&hex!("30 00"), Ok(&[]) ; "empty seq")]
@@ -247,27 +239,33 @@ fn struct02() {
],
};
fn parse_directory_string(i: &[u8]) -> BerResult {
- alt!(
- i,
- parse_ber_utf8string | parse_ber_printablestring | parse_ber_ia5string
- )
+ alt((
+ parse_ber_utf8string,
+ parse_ber_printablestring,
+ parse_ber_ia5string,
+ ))(i)
}
fn parse_attr_type_and_value(i: &[u8]) -> BerResult<Attr> {
fn clone_oid(x: BerObject) -> Result<Oid, BerError> {
x.as_oid().map(|o| o.clone())
}
- parse_der_struct!(
- i,
- o: map_res!(parse_ber_oid, clone_oid)
- >> s: parse_directory_string
- >> (Attr { oid: o, val: s })
- )
+ parse_der_sequence_defined_g(|i: &[u8], _| {
+ let (i, o) = map_res(parse_ber_oid, clone_oid)(i)?;
+ let (i, s) = parse_directory_string(i)?;
+ Ok((i, Attr { oid: o, val: s }))
+ })(i)
}
fn parse_rdn(i: &[u8]) -> BerResult<Rdn> {
- parse_der_struct!(i, a: parse_attr_type_and_value >> (Rdn { a }))
+ parse_der_set_defined_g(|i: &[u8], _| {
+ let (i, a) = parse_attr_type_and_value(i)?;
+ Ok((i, Rdn { a }))
+ })(i)
}
fn parse_name(i: &[u8]) -> BerResult<Name> {
- parse_der_struct!(i, l: many0!(complete!(parse_rdn)) >> (Name { l }))
+ parse_der_sequence_defined_g(|i: &[u8], _| {
+ let (i, l) = many0(complete(parse_rdn))(i)?;
+ Ok((i, Name { l }))
+ })(i)
}
let parsed = parse_name(&bytes).unwrap();
assert_eq!(parsed, (empty, expected));
@@ -337,36 +335,24 @@ fn tc_ber_tagged_explicit_g(i: &[u8], out: Result<u32, BerError>) {
#[test]
fn tagged_explicit() {
fn parse_int_explicit(i: &[u8]) -> BerResult<u32> {
- map_res!(
- i,
- parse_der_tagged!(EXPLICIT 2, parse_ber_integer),
- |x: BerObject| x.as_tagged()?.2.as_u32()
- )
- }
- fn parse_int_noexplicit(i: &[u8]) -> BerResult<u32> {
- map_res!(
- i,
- parse_der_tagged!(2, parse_ber_integer),
- |x: BerObject| x.as_tagged()?.2.as_u32()
- )
+ map_res(
+ parse_der_tagged_explicit(2, parse_der_integer),
+ |x: BerObject| x.as_tagged()?.2.as_u32(),
+ )(i)
}
let bytes = &[0xa2, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01];
// EXPLICIT tagged value parsing
let (rem, val) = parse_int_explicit(bytes).expect("Could not parse explicit int");
assert!(rem.is_empty());
assert_eq!(val, 0x10001);
- // omitting EXPLICIT keyword
- let a = parse_int_explicit(bytes);
- let b = parse_int_noexplicit(bytes);
- assert_eq!(a, b);
// wrong tag
assert_eq!(
- parse_der_tagged!(bytes as &[u8], 3, parse_ber_integer),
+ parse_der_tagged_explicit(3, parse_der_integer)(bytes as &[u8]),
Err(Err::Error(BerError::InvalidTag))
);
// wrong type
assert_eq!(
- parse_der_tagged!(bytes as &[u8], 2, parse_ber_bool),
+ parse_der_tagged_explicit(2, parse_der_bool)(bytes as &[u8]),
Err(Err::Error(BerError::InvalidTag))
);
}
@@ -395,11 +381,10 @@ fn tc_ber_tagged_implicit_g(i: &[u8], out: Result<u32, BerError>) {
#[test]
fn tagged_implicit() {
fn parse_int_implicit(i: &[u8]) -> BerResult<u32> {
- map_res!(
- i,
- parse_der_tagged!(IMPLICIT 2, BerTag::Integer),
- |x: BerObject| x.as_u32()
- )
+ map_res(
+ parse_der_tagged_implicit(2, parse_der_content(DerTag::Integer)),
+ |x: BerObject| x.as_u32(),
+ )(i)
}
let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01];
// IMPLICIT tagged value parsing
@@ -408,7 +393,7 @@ fn tagged_implicit() {
assert_eq!(val, 0x10001);
// wrong tag
assert_eq!(
- parse_der_tagged!(bytes as &[u8], IMPLICIT 3, BerTag::Integer),
+ parse_der_tagged_implicit(3, parse_der_content(DerTag::Integer))(bytes as &[u8]),
Err(Err::Error(BerError::InvalidTag))
);
}
@@ -420,12 +405,16 @@ fn application() {
a: u32,
}
fn parse_app01(i: &[u8]) -> BerResult<SimpleStruct> {
- parse_der_application!(
- i,
- APPLICATION 2,
- a: map_res!(parse_ber_integer,|x: BerObject| x.as_u32()) >>
- ( SimpleStruct{ a } )
- )
+ parse_der_container(|i, hdr| {
+ if hdr.class != BerClass::Application {
+ return Err(Err::Error(BerError::InvalidClass));
+ }
+ if hdr.tag != BerTag(2) {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ let (i, a) = map_res(parse_ber_integer, |x: BerObject| x.as_u32())(i)?;
+ Ok((i, SimpleStruct { a }))
+ })(i)
}
let bytes = &[0x62, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01];
let (rem, app) = parse_app01(bytes).expect("could not parse application");
diff --git a/tests/der_parser.rs b/tests/der_parser.rs
index 9a31e5c..33665f3 100644
--- a/tests/der_parser.rs
+++ b/tests/der_parser.rs
@@ -6,8 +6,11 @@ use der_parser::error::*;
use der_parser::oid::*;
use der_parser::*;
use hex_literal::hex;
+use nom::branch::alt;
+use nom::combinator::map;
use nom::error::ErrorKind;
-use nom::{alt, call, Err};
+use nom::sequence::tuple;
+use nom::Err;
use pretty_assertions::assert_eq;
use test_case::test_case;
@@ -175,7 +178,13 @@ fn test_der_seq_defined() {
DerObject::from_int_slice(b"\x01\x00\x00"),
]);
fn parser(i: &[u8]) -> DerResult {
- parse_der_sequence_defined!(i, parse_der_integer >> parse_der_integer)
+ parse_der_sequence_defined(
+ // the nom `tuple` combinator returns a tuple, so we have to map it
+ // to a list
+ map(tuple((parse_der_integer, parse_der_integer)), |(a, b)| {
+ vec![a, b]
+ }),
+ )(i)
}
assert_eq!(parser(&bytes), Ok((empty, expected)));
}
@@ -191,7 +200,13 @@ fn test_der_set_defined() {
DerObject::from_int_slice(b"\x01\x00\x00"),
]);
fn parser(i: &[u8]) -> DerResult {
- parse_der_set_defined!(i, parse_der_integer >> parse_der_integer)
+ parse_der_set_defined(
+ // the nom `tuple` combinator returns a tuple, so we have to map it
+ // to a list
+ map(tuple((parse_der_integer, parse_der_integer)), |(a, b)| {
+ vec![a, b]
+ }),
+ )(i)
}
assert_eq!(parser(&bytes), Ok((empty, expected)));
}
@@ -207,7 +222,7 @@ fn test_der_seq_of() {
DerObject::from_int_slice(b"\x01\x00\x00"),
]);
fn parser(i: &[u8]) -> DerResult {
- parse_der_sequence_of!(i, parse_der_integer)
+ parse_der_sequence_of(parse_der_integer)(i)
}
assert_eq!(parser(&bytes), Ok((empty, expected.clone())));
//
@@ -222,7 +237,7 @@ fn test_der_seq_of() {
fn test_der_seq_of_incomplete() {
let bytes = [0x30, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00];
fn parser(i: &[u8]) -> DerResult {
- parse_der_sequence_of!(i, parse_der_integer)
+ parse_der_sequence_of(parse_der_integer)(i)
}
assert_eq!(parser(&bytes), Err(Err::Failure(BerError::InvalidTag)));
//
@@ -250,7 +265,7 @@ fn test_der_set_of() {
DerObject::from_int_slice(b"\x01\x00\x00"),
]);
fn parser(i: &[u8]) -> DerResult {
- parse_der_set_of!(i, parse_der_integer)
+ parse_der_set_of(parse_der_integer)(i)
}
assert_eq!(parser(&bytes), Ok((empty, expected)));
}
@@ -293,13 +308,13 @@ fn test_der_contextspecific() {
let expected = DerObject {
header: BerObjectHeader::new(BerClass::ContextSpecific, 1, BerTag(0), 3)
.with_raw_tag(Some(&[0xa0])),
- content: BerObjectContent::Unknown(BerTag(0), &bytes[2..]),
+ content: BerObjectContent::Unknown(BerClass::ContextSpecific, BerTag(0), &bytes[2..]),
};
assert_eq!(parse_der(&bytes), Ok((empty, expected)));
}
#[test]
-fn test_der_explicit() {
+fn test_der_explicit_optional() {
let empty = &b""[..];
let bytes = [0xa0, 0x03, 0x02, 0x01, 0x02];
let header = BerObjectHeader::new(BerClass::ContextSpecific, 1, BerTag(0), 3)
@@ -316,12 +331,12 @@ fn test_der_explicit() {
)))),
};
assert_eq!(
- parse_der_explicit(&bytes, BerTag(0), parse_der_integer),
+ parse_der_explicit_optional(&bytes, BerTag(0), parse_der_integer),
Ok((empty, expected))
);
let expected2 = DerObject::from_obj(BerObjectContent::Optional(None));
assert_eq!(
- parse_der_explicit(&bytes, BerTag(1), parse_der_integer),
+ parse_der_explicit_optional(&bytes, BerTag(1), parse_der_integer),
Ok((&bytes[..], expected2))
);
}
@@ -396,10 +411,16 @@ fn test_der_optional() {
DerObject::from_int_slice(b"\x01\x00\x01"),
]);
fn parse_optional_enum(i: &[u8]) -> DerResult {
- parse_der_optional!(i, parse_der_enum)
+ parse_ber_optional(parse_der_enum)(i)
}
fn parser(i: &[u8]) -> DerResult {
- parse_der_sequence_defined!(i, parse_optional_enum >> parse_der_integer)
+ parse_der_sequence_defined(
+ // the nom `tuple` combinator returns a tuple, so we have to map it
+ // to a list
+ map(tuple((parse_optional_enum, parse_der_integer)), |(a, b)| {
+ vec![a, b]
+ }),
+ )(i)
}
assert_eq!(parser(&bytes1), Ok((empty, expected1)));
assert_eq!(parser(&bytes2), Ok((empty, expected2)));
@@ -458,66 +479,33 @@ fn test_der_seq_dn_defined() {
]);
#[inline]
fn parse_directory_string(i: &[u8]) -> DerResult {
- alt!(
- i,
- parse_der_utf8string | parse_der_printablestring | parse_der_ia5string
- )
+ alt((
+ parse_der_utf8string,
+ parse_der_printablestring,
+ parse_der_ia5string,
+ ))(i)
}
#[inline]
fn parse_attr_type_and_value(i: &[u8]) -> DerResult {
- parse_der_sequence_defined!(i, parse_der_oid >> parse_directory_string)
+ parse_der_sequence_defined(
+ // the nom `tuple` combinator returns a tuple, so we have to map it
+ // to a list
+ map(tuple((parse_der_oid, parse_directory_string)), |(a, b)| {
+ vec![a, b]
+ }),
+ )(i)
}
#[inline]
fn parse_rdn(i: &[u8]) -> DerResult {
- parse_der_set_defined!(i, parse_attr_type_and_value)
+ parse_der_set_of(parse_attr_type_and_value)(i)
}
#[inline]
fn parse_name(i: &[u8]) -> DerResult {
- parse_der_sequence_defined!(i, parse_rdn >> parse_rdn >> parse_rdn)
+ parse_der_sequence_of(parse_rdn)(i)
}
assert_eq!(parse_name(&bytes), Ok((empty, expected)));
}
-#[test]
-fn test_der_defined_seq_macros() {
- fn localparse_seq(i: &[u8]) -> DerResult {
- parse_der_sequence_defined_m! {
- i,
- parse_der_integer >>
- call!(parse_der_integer)
- }
- }
- let empty = &b""[..];
- let bytes = [
- 0x30, 0x0a, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00,
- ];
- let expected = DerObject::from_seq(vec![
- DerObject::from_int_slice(b"\x01\x00\x01"),
- DerObject::from_int_slice(b"\x01\x00\x00"),
- ]);
- assert_eq!(localparse_seq(&bytes), Ok((empty, expected)));
-}
-
-#[test]
-fn test_der_defined_set_macros() {
- fn localparse_set(i: &[u8]) -> DerResult {
- parse_der_set_defined_m! {
- i,
- parse_der_integer >>
- call!(parse_der_integer)
- }
- }
- let empty = &b""[..];
- let bytes = [
- 0x31, 0x0a, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00,
- ];
- let expected = DerObject::from_set(vec![
- DerObject::from_int_slice(b"\x01\x00\x01"),
- DerObject::from_int_slice(b"\x01\x00\x00"),
- ]);
- assert_eq!(localparse_set(&bytes), Ok((empty, expected)));
-}
-
#[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")]
diff --git a/tests/macros.rs b/tests/macros.rs
deleted file mode 100644
index 361fee9..0000000
--- a/tests/macros.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-#![allow(deprecated)]
-
-use der_parser::ber::{parse_ber_integer, BerObject};
-use der_parser::der::{parse_der_enum, parse_der_integer};
-use der_parser::error::{BerResult, DerResult};
-use der_parser::*;
-use nom::map_res;
-
-// Do not import nom, to check types and re-exports
-
-// all following functions are declared to check if macros from
-// der-parser can be used without importing nom or rusticata_macros
-
-#[derive(Debug, PartialEq)]
-struct MyStruct<'a> {
- a: BerObject<'a>,
- b: BerObject<'a>,
-}
-
-#[allow(dead_code)]
-fn parse_seq_m(i: &[u8]) -> DerResult {
- parse_der_sequence_defined_m! {
- i,
- parse_der_integer >>
- parse_der_integer
- }
-}
-
-#[allow(dead_code)]
-fn parse_set_m(i: &[u8]) -> DerResult {
- parse_der_set_defined_m! {
- i,
- parse_der_integer >>
- parse_der_integer
- }
-}
-
-#[allow(dead_code)]
-fn parse_seq(i: &[u8]) -> DerResult {
- parse_der_sequence_defined! {
- i,
- parse_der_integer >>
- parse_der_integer
- }
-}
-
-#[allow(dead_code)]
-fn parse_set(i: &[u8]) -> DerResult {
- parse_der_set_defined! {
- i,
- parse_der_integer >>
- parse_der_integer
- }
-}
-
-#[allow(dead_code)]
-fn parse_seq_of_int(i: &[u8]) -> DerResult {
- parse_der_sequence_of!(i, parse_der_integer)
-}
-
-#[allow(dead_code)]
-fn parse_set_of_int(i: &[u8]) -> DerResult {
- parse_der_set_of!(i, parse_der_integer)
-}
-
-#[allow(dead_code)]
-fn parse_optional_enum(i: &[u8]) -> BerResult {
- parse_der_optional!(i, parse_der_enum)
-}
-
-#[allow(dead_code)]
-fn parse_struct01(i: &[u8]) -> BerResult<MyStruct> {
- parse_der_struct!(
- i,
- a: parse_ber_integer >> b: parse_ber_integer >> (MyStruct { a, b })
- )
-}
-
-#[allow(dead_code)]
-fn parse_tagged_int(i: &[u8]) -> BerResult {
- parse_der_tagged!(i, EXPLICIT 2, parse_ber_integer)
-}
-
-#[derive(Debug, PartialEq)]
-struct SimpleStruct {
- a: u32,
-}
-
-#[allow(dead_code)]
-fn parse_app_int(i: &[u8]) -> BerResult<SimpleStruct> {
- parse_der_application!(
- i,
- APPLICATION 2,
- a: map_res!(parse_ber_integer,|x: BerObject| x.as_u32()) >>
- ( SimpleStruct{ a } )
- )
-}
-
-#[rustfmt::skip::macros(oid)]
-#[test]
-fn oid_macro() {
- let abs = oid!(1.2.44.233.0.124_982_9_348248912829838230928);
- assert!(!abs.relative);
- if cfg!(feature = "bigint") {
- assert_eq!(abs.to_string(), "1.2.44.233.0.1249829348248912829838230928");
- } else {
- assert_eq!(
- abs.to_string(),
- "2a 2c 81 69 00 c0 ce d6 d1 ba fd 8e c7 e5 dc ee 8b 10"
- );
- }
-
- let rel = oid!(rel 1.2.44.233);
- assert!(rel.relative);
- assert_eq!(rel.to_id_string(), "1.2.44.233");
- assert_eq!(format!("{:?}", &rel), "OID(rel. 1.2.44.233)")
-}
-
-#[test]
-fn oid_macro_edge_cases() {
- let undef = oid!(0);
- assert_eq!(undef.bytes(), [0].as_ref());
-
- let two = oid!(1.2);
- assert_eq!(two.bytes(), [40 + 2].as_ref());
-
- let spacing = oid!(5.2);
- assert_eq!(spacing.bytes(), [5 * 40 + 2].as_ref());
-}
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..4c07b0a 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::*;
@@ -88,13 +89,21 @@ fn test_unknown_tag() {
assert!(res.0.is_empty());
assert_eq!(
res.1,
- BerObject::from_obj(BerObjectContent::Unknown(BerTag(0x1d), &bytes[2..]))
+ BerObject::from_obj(BerObjectContent::Unknown(
+ BerClass::Universal,
+ BerTag(0x1d),
+ &bytes[2..]
+ ))
);
let res = parse_der(&bytes).expect("parsing failed");
assert!(res.0.is_empty());
assert_eq!(
res.1,
- BerObject::from_obj(BerObjectContent::Unknown(BerTag(0x1d), &bytes[2..]))
+ BerObject::from_obj(BerObjectContent::Unknown(
+ BerClass::Universal,
+ BerTag(0x1d),
+ &bytes[2..]
+ ))
);
}
@@ -108,7 +117,7 @@ fn test_unknown_context_specific() {
BerObject {
header: BerObjectHeader::new(BerClass::ContextSpecific, 0, BerTag(0), 1)
.with_raw_tag(Some(&[0x80])),
- content: BerObjectContent::Unknown(BerTag(0x0), &bytes[2..]),
+ content: BerObjectContent::Unknown(BerClass::ContextSpecific, BerTag(0x0), &bytes[2..]),
}
);
}
@@ -123,7 +132,11 @@ fn test_unknown_long_tag() {
BerObject {
header: BerObjectHeader::new(BerClass::ContextSpecific, 0, BerTag(0x22), 1)
.with_raw_tag(Some(&[0x9f, 0x22])),
- content: BerObjectContent::Unknown(BerTag(0x22), &bytes[3..]),
+ content: BerObjectContent::Unknown(
+ BerClass::ContextSpecific,
+ BerTag(0x22),
+ &bytes[3..]
+ ),
}
);
}
@@ -138,7 +151,11 @@ fn test_unknown_longer_tag() {
BerObject {
header: BerObjectHeader::new(BerClass::ContextSpecific, 0, BerTag(0x1122), 1)
.with_raw_tag(Some(&[0x9f, 0xa2, 0x22])),
- content: BerObjectContent::Unknown(BerTag(0x1122), &bytes[4..]),
+ content: BerObjectContent::Unknown(
+ BerClass::ContextSpecific,
+ BerTag(0x1122),
+ &bytes[4..]
+ ),
}
);
}