summaryrefslogtreecommitdiffstats
path: root/rust/vendor/der-parser
diff options
context:
space:
mode:
Diffstat (limited to 'rust/vendor/der-parser')
-rw-r--r--rust/vendor/der-parser/.cargo-checksum.json1
-rw-r--r--rust/vendor/der-parser/CHANGELOG.md388
-rw-r--r--rust/vendor/der-parser/Cargo.toml94
-rw-r--r--rust/vendor/der-parser/LICENSE-APACHE201
-rw-r--r--rust/vendor/der-parser/LICENSE-MIT25
-rw-r--r--rust/vendor/der-parser/README.md244
-rw-r--r--rust/vendor/der-parser/UPGRADING.md128
-rw-r--r--rust/vendor/der-parser/src/ber/ber.rs950
-rw-r--r--rust/vendor/der-parser/src/ber/compat.rs9
-rw-r--r--rust/vendor/der-parser/src/ber/integer.rs130
-rw-r--r--rust/vendor/der-parser/src/ber/mod.rs78
-rw-r--r--rust/vendor/der-parser/src/ber/multi.rs531
-rw-r--r--rust/vendor/der-parser/src/ber/parser.rs661
-rw-r--r--rust/vendor/der-parser/src/ber/print.rs209
-rw-r--r--rust/vendor/der-parser/src/ber/serialize.rs419
-rw-r--r--rust/vendor/der-parser/src/ber/tagged.rs260
-rw-r--r--rust/vendor/der-parser/src/ber/visit.rs192
-rw-r--r--rust/vendor/der-parser/src/ber/visit_mut.rs206
-rw-r--r--rust/vendor/der-parser/src/ber/wrap_any.rs213
-rw-r--r--rust/vendor/der-parser/src/der/mod.rs93
-rw-r--r--rust/vendor/der-parser/src/der/multi.rs534
-rw-r--r--rust/vendor/der-parser/src/der/parser.rs632
-rw-r--r--rust/vendor/der-parser/src/der/tagged.rs261
-rw-r--r--rust/vendor/der-parser/src/error.rs39
-rw-r--r--rust/vendor/der-parser/src/lib.rs278
-rw-r--r--rust/vendor/der-parser/src/oid.rs1
-rw-r--r--rust/vendor/der-parser/tests/ber_parser.rs556
-rw-r--r--rust/vendor/der-parser/tests/constructed.rs441
-rw-r--r--rust/vendor/der-parser/tests/custom_error.rs53
-rw-r--r--rust/vendor/der-parser/tests/der_constructed.rs177
-rw-r--r--rust/vendor/der-parser/tests/der_parser.rs628
-rw-r--r--rust/vendor/der-parser/tests/fuzz01.rs5
-rw-r--r--rust/vendor/der-parser/tests/fuzz02.rs22
-rw-r--r--rust/vendor/der-parser/tests/oid.rs25
-rw-r--r--rust/vendor/der-parser/tests/primitive.rs236
35 files changed, 8920 insertions, 0 deletions
diff --git a/rust/vendor/der-parser/.cargo-checksum.json b/rust/vendor/der-parser/.cargo-checksum.json
new file mode 100644
index 0000000..5c8cb9c
--- /dev/null
+++ b/rust/vendor/der-parser/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"0dd2ab03c45afe5db35191ec398b5ae56fdd252aabd1fa1b669033ff010f87f8","Cargo.toml":"213b0dfa900619e433c3999b5b2de2ce54effe7d8161a8ae3abf972196ea81b4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a5c61b93b6ee1d104af9920cf020ff3c7efe818e31fe562c72261847a728f513","README.md":"4cb96f25c1a2b876e75e98f528a0a51dbdaa97f210e270a2f8b07f1da18ccc22","UPGRADING.md":"ec1f026903fda2de7adda9090863b519c9732266460dadf0eaece9bf1c00289c","src/ber/ber.rs":"f03f71f653cbfd3e1903d989d0b49b4fd16604e8923444b02aa4851b7f013479","src/ber/compat.rs":"a220f947321d91431673d54b56f05c03b502e05c80b644ef0163d31ca83cf922","src/ber/integer.rs":"d87b78dabd3b455764b36bcd62f6dceb2fcbe4e381b2e32a71585b25967a29ed","src/ber/mod.rs":"8d208e2574dca87fbc1b65b66bad7c679fd32d60c688856a590d31b08d051ce0","src/ber/multi.rs":"7ec726d0c320496f7093c701b1f64296a5f4f391f0fae59c2d3cb17b2e8fa23b","src/ber/parser.rs":"68b320e05527fcb06681a21e0e072aab912db9cefac2c65e66ef2dbe9e6dcb8c","src/ber/print.rs":"f5e6839e765709d6634773282b1be0e1d9513b69dc5756379d4c923afd26951b","src/ber/serialize.rs":"ec32664e1e4ebbd0468c202448ed1fed2ee8f694c690617187fd4ea536aded99","src/ber/tagged.rs":"81d05ceb46f308fb766e2f7df6cec7c2c8479b928f2be9ce7e5cc30e126815fb","src/ber/visit.rs":"20a2cddb9263943de03b2e8abc054030baab64a9a739d590dd52c32599a838e9","src/ber/visit_mut.rs":"cf2c936173c3d077113f0421edab0a6e609587ab4ad984ee2128dde89dafe5be","src/ber/wrap_any.rs":"8db018f8141cd0497aa3ae08a3a76528851585c88c22275af2be8a69887fb01b","src/der/mod.rs":"70d80fc8eefaf6d15fb87e3b159796ec4e43d4b8e2854db74d715d10b36b0025","src/der/multi.rs":"b69e1bae25f6a57b821a35f4ddf9400feedf4c0303f1087254d01a856a8a5284","src/der/parser.rs":"10a33f70973c358a7e10c1e3ecf3f6470a86c61541e91136374c0d1d1be96e7e","src/der/tagged.rs":"66bf6b755bb41cd059a31021a631462985e76732a34c2df06ad805d4d19c2a1b","src/error.rs":"0d83caef79ea673a5814b7068bda0f2a558f05d57661e2ca24d819c650244937","src/lib.rs":"1ea83ce2d6582f9b8122062cf8813119abac7cb043f09e339beceec3d9e85559","src/oid.rs":"f6ff7343c47e7d554a1bfd6f07fc17996a8f58b2153336d624cfd076c0192bf1","tests/ber_parser.rs":"bf2401c7b06b7724d81b93e696f2403c947a51b1c360dfc731c7f392b0005d08","tests/constructed.rs":"532f1fda98bc9f22da0dd905f2314be5195e9442bb3acb1584e80037101a013f","tests/custom_error.rs":"8f92380a8b71df6033e15806c162bc502c6beea086ebed7c3106c76da71ec95b","tests/der_constructed.rs":"49f8f8d97659410ac0752a2fb9c2aec97930c6efb8cccd989946912afa0f1a6d","tests/der_parser.rs":"e00691edef8a5f83f5ea746835c061c08c47c5aad74aecae71833c9b3205fe64","tests/fuzz01.rs":"b1929c8183fdba11ea73618ef48b23d4d3d39df79ac70e1c46787c3dcfcf9ec9","tests/fuzz02.rs":"b1e4ae20a40bb74887b7d62e9bbec5919f7c963b3f699e01888755e3637877a5","tests/oid.rs":"901a1a929653eef5f1753479dc742f1e9fefca960523958d4e50b8376ac06524","tests/primitive.rs":"95e6da515e34df3d4682341319bf580e51304d2c3b14e9645b2c49f0f6e41f49"},"package":"dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e"} \ No newline at end of file
diff --git a/rust/vendor/der-parser/CHANGELOG.md b/rust/vendor/der-parser/CHANGELOG.md
new file mode 100644
index 0000000..9f0ee32
--- /dev/null
+++ b/rust/vendor/der-parser/CHANGELOG.md
@@ -0,0 +1,388 @@
+# Change Log
+
+## [Unreleased][unreleased]
+
+### Changed/Fixed
+
+### Added
+
+### Thanks
+
+## 8.2.0
+
+### Changed/Fixed
+
+- Fix parser name to `parse_der_visiblestring` for `VisibleString` (Closes #64).
+ Keep previous function for compatibility (mark it as deprecated).
+- Fix clippy warnings (rustc 1.67.1)
+- Update test-case from 2.0 to 3.0
+
+## 8.1.0
+
+### Changed/Fixed
+
+- Upgrade `asn1-rs` to 0.5.0 (new features only: only increment minor number)
+
+## 8.0.0
+
+### Changed/Fixed
+
+- Upgrade `asn1-rs` to 0.4.0
+ This causes an increment of the major number, because `asn1-rs` is re-exported
+
+## 7.0.0
+
+This release marks the beginning of the merge with the `asn1-rs` crate. **This will break things.**
+
+However, this is necessary, because the `asn1-rs` crate is much cleaner and supports more types
+and features (like serialization, custom derive, etc.).
+Ultimately, this crate will become a frontend to `asn1-rs`, that will be optional: crate users can
+switch to `asn1-rs` and use it directly.
+
+### Changed/Fixed
+
+MSRV: The minimum supported rust version is now *1.53*.
+
+`BerObjectHeader`:
+
+- `BerSize` has been renamed to `Length`
+- `BerClass` has been renamed to `Class`
+- `BerTag` has been renamed to `Tag`
+- Header fields are now private. Getters/setters have been added, and must be used to access/modify fields
+
+`BerObjectContent`:
+- `Unknown` variant now contains an `Any` object, with both the header and object content
+- `Private` variant has been merged into `Unknown`
+- `BmpString`, `GeneralString`, `GraphicString`, `T61String`, `VideotexString` and `ObjectDescriptor` are now decoded
+- `GeneralizedTime` and `UtcTime` are now decoded
+
+`BerError`:
+
+- Add error types `UnexpectedClass` and `UnexpectedTag`
+- Store expected and found item in error to help debugging
+- Keep `InvalidTag` for tags with invalid form (length/encoding/etc.)
+- Use `displaydoc` for `BerError`
+- Parsing an indefinite length in DER now raises `IndefiniteLengthUnexpected`
+- Error: when a DER constraint fails, store constraint identifier
+
+`DER`:
+- `DerClass` and `DerTag` have been deprecated. Use `Class` and `Tag` instead.
+- `DerObjectHeader` has been deprecated. Use `Header` instead.
+
+`Oid`:
+- The `Oid` object is now the same as `asn1_rs::Oid` (simply reexported)
+- Remove dependency on crate `der-oid-macro`
+
+Misc:
+- `ber_read_element_content_as` now requires a non-zero `depth`, or it
+ will raise a `BerMaxDepth` error (previously, 0 allowed one level of parsing)
+- crate `rusticata-macros` is now re-exported (#55)
+
+### Thanks
+
+- @lilyball
+- @erikmarkmartin
+
+## 6.0.0
+
+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)
+- 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
+
+### Changed/Fixed
+
+- Remove dependency on proc-macro-hack (attempt to fix #36)
+- Update pretty_assertions requirement from 0.6 to 0.7
+- Update num-bigint to 0.4 (Closes #42)
+
+## 5.0.1
+
+### Changed/Fixed
+
+- Fix typos in the `parse_[ber|der]_[u32|u64]` doc comments
+- Add documentation for BerObjectContent variants (#41)
+- Fixes for clippy
+
+### Added
+
+## 5.0.0
+
+See changelog entries for 5.0.0-beta1 and -beta2 for changes since 4.1
+
+### Changed/Fixed
+
+The following changes applies since 5.0.0-beta1, and do not affect 4.x
+
+- Fix potential integer underflow in `bytes_to_u64`
+- Fix potential stack recursion overflow for indefinite length objects
+ (Add maximum depth).
+- Fix potential UB in bitstring_to_u64 with large input and many ignored bits
+- Fix constructed objects parsing with indefinite length (do not include EOC)
+- Constructed objects: use `InvalidTag` everywhere if tag is not expected
+- Integer parsing functions now all return `IntegerTooLarge` instead of `MapRes`
+- Ensure Indefinite length form is only used in BER constructed objects
+
+### Added
+
+- Add new error `StringInvalidCharset` and update string parsing methods
+- Add methods `parse_ber_slice` and `parse_der_slice` to parse an expected Tag and get content as slice
+
+## 5.0.0-beta2
+
+### Changed/Fixed
+
+- Consistency: reorder arguments or function callbacks, always set input slice as first argument
+ (`parse_ber_sequence_defined_g`, `parse_ber_container`, `parse_ber_tagged_explicit_g`, ...)
+- Make functions `parse_ber_sequence_of_v` and `parse_ber_set_of_v` accept generic error types
+
+### Added
+
+- Add `parse_ber_content2`, owned version of `parse_ber_content`, which can directly be combined
+ with `parse_ber_tagged_implicit_g`
+- Add methods to parse DER tagged values and containers (with constraints)
+
+## 5.0.0-beta1
+
+### Changed/Fixed
+
+- Upgrade to nom 6
+- Switch all parsers to function-based parsers
+- Change representation of size (new type `BerSize`) to support BER indefinite lengths
+- Rewrite BER/DER parsing macros to use functional parsing combinators
+- The constructed bit is now tested for explicit tagged structures
+- Some checks (for ex. tags in constructed objects) now return specific errors (`InvalidTag`)
+ instead of generic errors (`Verify`)
+- Refactor BerObject for parsing of tagged and optional values
+- Add method `as_bitslice()` to BerObject
+- Remove Copy trait from BerObjectHeader, copy is non-trivial and should be explicit
+- Fix the bug that caused OIDs longer than two subidentifiers which started by subidentifiers "0.0" ("itu-t recommenation") not to be decoded correctly
+- Implement the `as_u64` and `as_u32` methods for BerObjects with contents of type `BerObjectContent::BitString`.
+- Implement the `VideotexString`, `ObjectDescriptor` `GraphicString`, and `VisibleString` string types. (Non-breaking changes)
+- Correctly decode `BMPString` as UTF-16 instead of UTF-8 when printing. (Non-breaking change)
+- Turn `UTCTime` and `GeneralizedTime` into a `&str` instead of `&[u8]`, as they inherit from `VisibleString` which is a subset of ASCII. (Breaking change)
+
+### Added
+
+- Add combinator `parse_ber_optional`
+
+### Thanks
+
+By alphabetic order of handle:
+
+- `@cccs-sadugas`
+- `@nickelc`
+- `@p1-mmr`
+
+## 4.1.0
+
+### Added/Changed
+
+- Re-export num-bigint so crate users do not have to import it
+- Add function versions to parse BER sequences/sets (#20)
+- Add function versions to parse BER tagged objects (#20)
+- Add generic error type to structured parsing functions
+- Add function to parse a generic BER container object
+- Document that trailing bytes from SEQUENCE/SET are ignored
+- Deprecate functions `parse_{ber,der}_explicit` (use `_optional`)
+
+## 4.0.2
+
+### Changed/Fixed
+
+- Upgrade dependencies on num-bigint and der-oid-macro
+
+## 4.0.1
+
+### Changed/Fixed
+
+- Add workaround to fix parsing of empty sequence or set
+
+## 4.0.0
+
+**Attention** This is a major release, with several API-breaking changes. See `UPGRADING.md` for instructions.
+
+### Thanks
+
+- Jannik Schürg (oid, string verifications)
+
+### Added
+
+- Add functions `parse_ber_recursive` and `parse_der_recursive`, allowing to specify maximum
+ recursion depth when parsing
+- The string types `IA5String`, `NumericString`, `PrintableString` and `UTF8String`
+ do now only parse if the characters are valid.
+- `as_str()` was added to `BerObjectContent` to obtain a `&str` for the types above.
+ `as_slice()` works as before.
+- Implement `Error` trait for `BerError`
+- Add method to extract raw tag from header
+ - `BerObjectHeader` now has a lifetime and a `raw_tag` field
+ - `BerObject` now has a `raw_tag` field
+ - Implement `PartialEq` manually for `BerObject`: `raw_tag` is compared only if both fields provide it
+- Add type `BerClass`
+- Start adding serialization support (experimental) using the `serialize` feature
+
+### Changed/Fixed
+
+- Make header part of `BerObject`, remove duplicate fields
+- Maximum recursion logic has changed. Instead of providing the current depth, the argument is
+ now the maximum possible depth.
+- Change the api around `Oid` to achieve zero-copy. The following changed:
+ - The `Oid` struct now has a lifetime and uses `Cow` internally.
+ - The procedural macro `oid!` was added.
+ - `Oid::from` returns a `Result` now.
+ - The `Oid` struct now encodes whether the oid is relative or not.
+ - The `Debug` implementation now shows whether the oid is relative
+ and uses the bigint feature if available.
+ - The `Oid::iter` method now returns an `Option`. `Oid::iter_bigint` was
+ added.
+ - `Hash` is now derived for `Oid`.
+- Minimum rust version is now 1.34
+
+## 3.0.3
+
+- Make the pretty-printer function public
+- Fix DER datestring sanity check
+- CI
+ - add rusfmt check
+ - add cargo clippy
+
+## 3.0.2
+
+- Add `parse_ber_u32` and `parse_ber_u64` functions
+- Fix typo in description
+
+## 3.0.1
+
+- Add crate `BerResult` and `DerResult` types
+- Use crate result types, remove uneeded imports
+ - Crates using `der-parser` do not need to import `nom` or `rusticata-macros` anymore
+ - Result types are aliases, so API is unchanged
+
+## 3.0.0
+
+- Upgrade to nom 5 (breaks API)
+- New error types, now all functions use `BerError`
+
+## 2.1.0
+
+- Handle BER/DER tags that are longer than one byte.
+- Set edition to 2018
+
+## 2.0.2
+
+- Revert 2.0.1 release, breaks API
+
+## 2.0.1
+
+- Handle BER/DER tags that are longer than one byte.
+
+## 2.0.0
+
+- Refactor code, split BER and DER, check DER constraints
+- Add recursion limit for sequences and sets
+- Rustfmt
+- Documentation
+- Remove unused function `ber_read_element_content`
+
+## 1.1.1
+
+- Fix OID parsing, and add support for relative OIDs
+- Add FromStr trait for Oid
+
+## 1.1.0
+
+- Use num-bigint over num and upgrade to 0.2
+
+## 1.0.0
+
+- Upgrade to nom 4
+
+## 0.5.5
+
+- Add functions `parse_der_u32` and `parse_der_u64` to quickly parse integers
+- Remove `Oid::from_vec`, `Oid::from` does the same
+- Enforce constraints on DER booleans
+
+## 0.5.4
+
+- Add `BitStringObject` to wrap BitString objects
+- Mark constructed BitStrings as unsupported
+- Do not try to parse application-specific data in `parse_der`
+
+## 0.5.3
+
+- Add function `DerObject::as_u64`
+- Add function `DerObject::as_oid_val`
+- Add `parse_der_struct!` variant to check tag
+
+## 0.5.2
+
+- Add functions to test object class and primitive/constructed state
+- Add macro `parse_der_application!`
+- Add macro `parse_der_tagged!` to parse `[x] EXPLICIT` or `[x] IMPLICIT` tagged values
+
+## 0.5.1
+
+- Add type GeneralString
+- Add macro `parse_der_struct!`
+
+## 0.5.0
+
+- Allow use of crate without extra use statements
+- Use constants for u32 errors instead of magical numbers
+- Rename `tag_of_der_content()` to `DerObjectContent::tag`
+- Rename DerElementxxx structs to have a consistent naming scheme
+- Add documentation for parsing DER sequences and sets, and fix wrong return type for sets
+- Fix a lot of clippy warnings
+- QA: add pragma rules (disable unsafe code, unstable features etc.)
+- More documentation
+- Switch license to MIT + APLv2
+
+## 0.4.4
+
+- Add macro parse_der_defined_m, to parse a defined sequence or set
+ This macro differs from `parse_der_defined` because it allows using macros
+- Rename `DerObject::new_int` to `DerObject::from_int_slice`
+- Rename `Oid::to_hex` to `Oid::to_string`
+- Document more functions
+
+## 0.4.1
+
+- Add new feature 'bigint' to export DER integers
+- OID is now a specific type
+- Add new types T61String and BmpString
+- Fix wrong expected tag in parse_der_set_of
+
+## 0.4.0
+
+- Der Integers are now represented as slices (byte arrays) since they can be larger than u64.
diff --git a/rust/vendor/der-parser/Cargo.toml b/rust/vendor/der-parser/Cargo.toml
new file mode 100644
index 0000000..bf192be
--- /dev/null
+++ b/rust/vendor/der-parser/Cargo.toml
@@ -0,0 +1,94 @@
+# 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 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 = "8.2.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"
+homepage = "https://github.com/rusticata/der-parser"
+readme = "README.md"
+keywords = [
+ "BER",
+ "DER",
+ "ASN1",
+ "parser",
+ "nom",
+]
+categories = ["parser-implementations"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/rusticata/der-parser.git"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[dependencies.asn1-rs]
+version = "0.5"
+
+[dependencies.cookie-factory]
+version = "0.3.0"
+optional = true
+
+[dependencies.displaydoc]
+version = "0.2"
+default-features = false
+
+[dependencies.nom]
+version = "7.0"
+
+[dependencies.num-bigint]
+version = "0.4"
+optional = true
+
+[dependencies.num-traits]
+version = "0.2"
+
+[dependencies.rusticata-macros]
+version = "4.0"
+
+[dev-dependencies.hex-literal]
+version = "0.3"
+
+[dev-dependencies.pretty_assertions]
+version = "1.0"
+
+[dev-dependencies.test-case]
+version = "3.0"
+
+[features]
+bigint = ["num-bigint"]
+default = ["std"]
+serialize = [
+ "std",
+ "cookie-factory",
+]
+std = []
+unstable = []
diff --git a/rust/vendor/der-parser/LICENSE-APACHE b/rust/vendor/der-parser/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/rust/vendor/der-parser/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/rust/vendor/der-parser/LICENSE-MIT b/rust/vendor/der-parser/LICENSE-MIT
new file mode 100644
index 0000000..290e7b9
--- /dev/null
+++ b/rust/vendor/der-parser/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2017 Pierre Chifflier
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/rust/vendor/der-parser/README.md b/rust/vendor/der-parser/README.md
new file mode 100644
index 0000000..780e258
--- /dev/null
+++ b/rust/vendor/der-parser/README.md
@@ -0,0 +1,244 @@
+<!-- cargo-sync-readme start -->
+
+[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT)
+[![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE)
+[![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/8.2.0/status.svg)](https://deps.rs/crate/der-parser/8.2.0)
+[![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.53.0+-lightgray.svg)](#rust-version-requirements)
+
+# BER/DER Parser
+
+A parser for Basic Encoding Rules (BER [[X.690]]) and Distinguished Encoding Rules(DER
+[[X.690]]), implemented with the [nom](https://github.com/Geal/nom) parser combinator
+framework.
+
+It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken
+to ensure security and safety of this crate, including design (recursion limit, defensive
+programming), tests, and fuzzing. It also aims to be panic-free.
+
+Historically, this parser was intended for DER only, and BER support was added later. This may
+still reflect on some naming schemes, but has no other consequence: the `BerObject` and
+`DerObject` used in this crate are type aliases, so all functions are compatible.
+
+DER parsing functions have additional constraints verification, however.
+
+Serialization has also been added (see [Serialization](#serialization) )
+
+The code is available on [Github](https://github.com/rusticata/der-parser)
+and is part of the [Rusticata](https://github.com/rusticata) project.
+
+# BER/DER parsers
+
+BER stands for Basic Encoding Rules, and is defined in [X.690]. It defines a set of rules to
+encode and decode ASN.1 objects in binary.
+
+[X.690] also defines Distinguished Encoding Rules (DER), which is BER with added rules to
+ensure canonical and unequivocal binary representation of objects.
+
+The choice of which one to use is usually guided by the speficication of the data format based
+on BER or DER: for example, X.509 uses DER as encoding representation.
+
+See the related modules for object definitions, functions, and example:
+- [`ber`]: Basic Encoding Rules
+- [`der`]: Distinguished Encoding Rules
+
+## Examples
+
+Parse two BER integers (see [BER/DER Integers](#berder-integers)):
+
+```rust
+use der_parser::ber::parse_ber_integer;
+
+let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x02, 0x03, 0x01, 0x00, 0x00,
+];
+
+let (rem, obj1) = parse_ber_integer(&bytes).expect("parsing failed");
+let (rem, obj2) = parse_ber_integer(&bytes).expect("parsing failed");
+```
+
+Parse a DER sequence of integers:
+
+```rust
+use der_parser::der::{parse_der_integer, parse_der_sequence_of};
+
+let bytes = [ 0x30, 0x0a,
+ 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x02, 0x03, 0x01, 0x00, 0x00,
+];
+
+let (rem, seq) = parse_der_sequence_of(parse_der_integer)(&bytes)
+ .expect("parsing failed");
+```
+
+Note: all parsing functions return the remaining (unparsed) bytes and the parsed object, or an
+error.
+
+# DER parser design
+
+Parsing functions are inspired from `nom`, and follow the same interface. The most common
+return type is [`BerResult`](https://docs.rs/der-parser/latest/der_parser/error/type.BerResult.html), that stores the remaining bytes and
+parsed [`BerObject`](https://docs.rs/der-parser/latest/der_parser/ber/struct.BerObject.html), or an error. Reading the nom documentation may
+help understanding how to write parsers and use the output.
+
+There are two different approaches for parsing DER objects: reading the objects recursively as
+long as the tags are known, or specifying a description of the expected objects (generally from
+the [ASN.1][X.680] description).
+
+The first parsing method can be done using the [`parse_ber`](https://docs.rs/der-parser/latest/der_parser/ber/fn.parse_ber.html) and
+[`parse_der`](https://docs.rs/der-parser/latest/der_parser/der/fn.parse_der.html) methods.
+It is useful when decoding an arbitrary DER object.
+However, it cannot fully parse all objects, especially those containing IMPLICIT, OPTIONAL, or
+DEFINED BY items.
+
+```rust
+use der_parser::parse_der;
+
+let bytes = [ 0x30, 0x0a,
+ 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x02, 0x03, 0x01, 0x00, 0x00,
+];
+
+let parsed = parse_der(&bytes);
+```
+
+The second (and preferred) parsing method is to specify the expected objects recursively. The
+following functions can be used:
+- [`parse_ber_sequence_defined`](https://docs.rs/der-parser/latest/der_parser/ber/fn.parse_ber_sequence_defined.html) and similar functions
+for sequences and sets variants
+- [`parse_ber_tagged_explicit`](https://docs.rs/der-parser/latest/der_parser/ber/fn.parse_ber_tagged_explicit.html) for tagged explicit
+- [`parse_ber_tagged_implicit`](https://docs.rs/der-parser/latest/der_parser/ber/fn.parse_ber_tagged_implicit.html) for tagged implicit
+- [`parse_ber_container`](https://docs.rs/der-parser/latest/der_parser/ber/fn.parse_ber_container.html) for generic parsing, etc.
+- DER objects use the `_der_` variants
+
+For example, to read a BER sequence containing two integers:
+
+```rust
+use der_parser::ber::*;
+use der_parser::error::BerResult;
+
+fn localparse_seq(i:&[u8]) -> BerResult {
+ parse_ber_sequence_defined(|data| {
+ let (rem, a) = parse_ber_integer(data)?;
+ let (rem, b) = parse_ber_integer(rem)?;
+ Ok((rem, vec![a, b]))
+ })(i)
+}
+
+let bytes = [ 0x30, 0x0a,
+ 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x02, 0x03, 0x01, 0x00, 0x00,
+];
+
+let (_, parsed) = localparse_seq(&bytes).expect("parsing failed");
+
+assert_eq!(parsed[0].as_u64(), Ok(65537));
+assert_eq!(parsed[1].as_u64(), Ok(65536));
+```
+
+All functions return a [`BerResult`](https://docs.rs/der-parser/latest/der_parser/error/type.BerResult.html) object: the parsed
+[`BerObject`](https://docs.rs/der-parser/latest/der_parser/ber/struct.BerObject.html), an `Incomplete` value, or an error.
+
+Note that this type is also a `Result`, so usual functions (`map`, `unwrap` etc.) are available.
+
+# Notes
+
+## BER/DER Integers
+
+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).
+
+```rust
+use der_parser::ber::*;
+
+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(), Ok(65537.into()))
+```
+
+Access to the raw value is possible using the `as_slice` method.
+
+## Parsers, combinators, macros
+
+Some parsing tools (for ex for tagged objects) are available in different forms:
+- parsers: (regular) functions that takes input and create an object
+- combinators: functions that takes parsers (or combinators) as input, and return a function
+ (usually, the parser). They are used (combined) as building blocks to create more complex
+ parsers.
+- macros: these are generally previous (historic) versions of parsers, kept for compatibility.
+ They can sometime reduce the amount of code to write, but are hard to debug.
+ Parsers should be preferred when possible.
+
+## Misc Notes
+
+- The DER constraints are verified if using `parse_der`.
+- `BerObject` and `DerObject` are the same objects (type alias). The only difference is the
+ verification of constraints *during parsing*.
+
+## Rust version requirements
+
+The 7.0 series of `der-parser` requires **Rustc version 1.53 or greater**, based on `asn1-rs`
+and `nom` 7 dependencies.
+
+# Serialization
+
+Support for encoding BER/DER objects is currently being tested and can be used by activating the `serialize` feature.
+Note that current status is **experimental**.
+
+See the `ber_encode_*` functions in the [`ber`](https://docs.rs/der-parser/latest/der_parser/ber/index.html) module, and
+[`BerObject::to_vec`](https://docs.rs/der-parser/latest/der_parser/ber/struct.BerObject.html#method.to_vec)
+
+# References
+
+- [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation.
+- [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical
+ Encoding Rules (CER) and Distinguished Encoding Rules (DER).
+
+[X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1):
+ Specification of basic notation."
+[X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of
+ Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules
+ (DER)."
+<!-- cargo-sync-readme end -->
+
+## Changes
+
+See `CHANGELOG.md`, and `UPGRADING.md` for instructions for upgrading major versions.
+
+## License
+
+Licensed under either of
+
+ * Apache License, Version 2.0
+ ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
+ * MIT license
+ ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+## Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
+dual licensed as above, without any additional terms or conditions.
diff --git a/rust/vendor/der-parser/UPGRADING.md b/rust/vendor/der-parser/UPGRADING.md
new file mode 100644
index 0000000..3df0ed2
--- /dev/null
+++ b/rust/vendor/der-parser/UPGRADING.md
@@ -0,0 +1,128 @@
+## Upgrading from 6.x to 7.0
+
+### Header refactor
+
+Header names have changed:
+- `BerClass` is now `Class`
+- `BerSize` is now `Length`
+- `BerTag` is now `Tag`
+- `BerObjectHeader` is now `Header`
+
+Changing the names should be enough for upgrades.
+
+To eventually ease upgrades, a new module (`der_parser::ber::compat`) has been added, to provide aliases for these types. It must be imported explicitely.
+
+Header fields are now private. Getters/setters have been added, and must be used to access/modify fields. Replace:
+- `hdr.len` by `hdr.length()`
+- `hdr.class` by `hdr.class()`
+- `hdr.tag` by `hdr.tag()`
+
+`structured` has been renamed to `constructed` to match RFC. Since this field is now private, methods `constructed()`/`set_constructed()` must be used instead of raw access.
+
+### DER
+
+`DerClass` and `DerTag` have been deprecated. Use `Class` and `Tag` instead.
+
+`DerObjectHeader` has been deprecated. Use `Header` instead.
+
+## Upgrading from 4.x to 5.0
+
+### BER variants: ContextSpecific, Optional, Tagged
+
+The variant `ContextSpecific` has been removed from `BerObject`, and 2 new variants have been added:
+- `Tagged` for explicit tagged objects,
+- `Optional` to simplify writing subparsers with only `BerObject`
+
+This is also used to clarify parsing of tagged values, and the API now clearly says if trying to parse an
+optional value or not.
+
+### Ber Size
+
+The `len` field of `BerObjectHeader` is now an enum, to represent definite and indefinite lengths.
+To get the value, either match the type, or use `try_from` (which will fail if indefinite).
+
+### Struct parsing Macros
+
+Functions and combinators are now the preferred way of parsing constructed objects.
+
+Macros have been upgrading and use the combinators internally. As a consequence, they do not return
+a tuple `(BerObjectHeader, T)` but only the built object `T`. The header should be removed from function
+signatures, for ex:
+```
+-fn parse_struct01(i: &[u8]) -> BerResult<(BerObjectHeader,MyStruct)> {
++fn parse_struct01(i: &[u8]) -> BerResult<MyStruct> {
+```
+
+The header was usually ignored, so this should simplify most uses of this macro. To get the header,
+use `parse_ber_container` directly.
+
+## Upgrading from 3.x to 4.0
+
+### Ber Object and Header
+
+The `class`, `structured` and `tag` fields were duplicated in `BerObject` and the header.
+Now, a header is always created and embedded in the BER object, with the following changes:
+
+- To access these fields, use the header: `obj.tag` becomes `obj.header.tag`, etc.
+- `BerObject::to_header()` is now deprecated
+- The `len` field is now public. However, in some cases it can be 0 (when creating an object, 0 means that serialization will calculate the length)
+- As a consequence, `PartialEq` on BER objects and headers compare `len` only if set in both objects
+
+### BER String types verification
+
+Some BER String types (`IA5String`, `NumericString`, `PrintableString` and `UTF8String`) are now
+verified, and will now only parse if the characters are valid.
+
+Their types have change from slice to `str` in the `BerObjectContent` enum.
+
+### BerClass
+
+The `class` field of `BerObject` struct now uses the newtype `BerClass`. Use the provided constants
+(for ex `BerClass:Universal`). To access the value, just use `class.0`.
+
+### Maximum depth
+
+The `depth` argument of functions (for ex. `ber_read_element_content_as`) has changed, and is now the maximum possible depth while parsing.
+Change it (usually from `0`) to a possible limit, for ex `der_parser::ber::MAX_RECURSION`.
+
+### Oid
+
+This is probably the most impacting change.
+
+OID objects have been refactored, and are now zero-copy. This has several consequences:
+
+- `Oid` struct now has a lifetime, which must be propagated to objects using them
+ - This makes having globally static structs difficult. Obtaining a `'static` object is possible
+ using the `oid` macro. For ex:
+
+```rust
+const SOME_STATIC_OID: Oid<'static> = oid!(1.2.456);
+```
+
+- Due to limitations of procedural macros ([rust
+ issue](https://github.com/rust-lang/rust/issues/54727)) and constants used in patterns ([rust issue](https://github.com/rust-lang/rust/issues/31434)), the `oid` macro can not directly be used in patterns, also not through constants.
+You can do this, though:
+
+```rust
+# use der_parser::{oid, oid::Oid};
+# let some_oid: Oid<'static> = oid!(1.2.456);
+const SOME_OID: Oid<'static> = oid!(1.2.456);
+if some_oid == SOME_OID || some_oid == oid!(1.2.456) {
+ println!("match");
+}
+
+// Alternatively, compare the DER encoded form directly:
+const SOME_OID_RAW: &[u8] = &oid!(raw 1.2.456);
+match some_oid.bytes() {
+ SOME_OID_RAW => println!("match"),
+ _ => panic!("no match"),
+}
+```
+*Attention*, be aware that the latter version might not handle the case of a relative oid correctly. An
+extra check might be necessary.
+
+- To build an `Oid`, the `from`, `new` or `new_relative` methods can be used.
+- The `from` method now returns a `Result` (failure can happen if the first components are too
+ large, for ex)
+- An `oid` macro has also been added in the `der-oid-macro` crate to easily build an `Oid` (see
+ above).
diff --git a/rust/vendor/der-parser/src/ber/ber.rs b/rust/vendor/der-parser/src/ber/ber.rs
new file mode 100644
index 0000000..3063ff2
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/ber.rs
@@ -0,0 +1,950 @@
+use super::{Class, Header, Length, Tag};
+use crate::ber::bitstring_to_u64;
+use crate::ber::integer::*;
+use crate::error::BerError;
+use crate::oid::Oid;
+use alloc::borrow::ToOwned;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use asn1_rs::ASN1DateTime;
+use asn1_rs::Any;
+#[cfg(feature = "bitvec")]
+use bitvec::{order::Msb0, slice::BitSlice};
+use core::convert::AsRef;
+use core::convert::From;
+use core::ops::Index;
+
+/// Representation of a BER-encoded (X.690) object
+///
+/// A BER object is composed of a header describing the object class, type and length,
+/// and the content.
+///
+/// Note that the content may sometimes not match the header tag (for ex when parsing IMPLICIT
+/// tagged values).
+#[derive(Debug, Clone, PartialEq)]
+pub struct BerObject<'a> {
+ pub header: Header<'a>,
+ pub content: BerObjectContent<'a>,
+}
+
+/// BER object content
+#[derive(Debug, Clone, PartialEq)]
+#[allow(clippy::upper_case_acronyms)]
+pub enum BerObjectContent<'a> {
+ /// EOC (no content)
+ EndOfContent,
+ /// BOOLEAN: decoded value
+ Boolean(bool),
+ /// INTEGER: raw bytes
+ ///
+ /// Note: the reason to store the raw bytes is that integers have non-finite length in the
+ /// spec, and also that the raw encoding is also important for some applications.
+ ///
+ /// To extract the number, see the `as_u64`, `as_u32`, `as_bigint` and `as_biguint` methods.
+ Integer(&'a [u8]),
+ /// BIT STRING: number of unused bits, and object
+ BitString(u8, BitStringObject<'a>),
+ /// OCTET STRING: slice
+ OctetString(&'a [u8]),
+ /// NULL (no content)
+ Null,
+ /// ENUMERATED: decoded enum number
+ Enum(u64),
+ /// OID
+ OID(Oid<'a>),
+ /// RELATIVE OID
+ RelativeOID(Oid<'a>),
+ /// NumericString: decoded string
+ NumericString(&'a str),
+ /// VisibleString: decoded string
+ VisibleString(&'a str),
+ /// PrintableString: decoded string
+ PrintableString(&'a str),
+ /// IA5String: decoded string
+ IA5String(&'a str),
+ /// UTF8String: decoded string
+ UTF8String(&'a str),
+ /// T61String: decoded string
+ T61String(&'a str),
+ /// VideotexString: decoded string
+ VideotexString(&'a str),
+
+ /// BmpString: decoded string
+ BmpString(&'a str),
+ /// UniversalString: raw object bytes
+ UniversalString(&'a [u8]),
+
+ /// SEQUENCE: list of objects
+ Sequence(Vec<BerObject<'a>>),
+ /// SET: list of objects
+ Set(Vec<BerObject<'a>>),
+
+ /// UTCTime: decoded string
+ UTCTime(ASN1DateTime),
+ /// GeneralizedTime: decoded string
+ GeneralizedTime(ASN1DateTime),
+
+ /// Object descriptor: decoded string
+ ObjectDescriptor(&'a str),
+ /// GraphicString: decoded string
+ GraphicString(&'a str),
+ /// GeneralString: decoded string
+ GeneralString(&'a str),
+
+ /// Optional object
+ Optional(Option<Box<BerObject<'a>>>),
+ /// Tagged object (EXPLICIT): class, tag and content of inner object
+ Tagged(Class, Tag, Box<BerObject<'a>>),
+
+ /// Private or Unknown (for ex. unknown tag) object
+ Unknown(Any<'a>),
+}
+
+impl<'a> BerObject<'a> {
+ /// Build a BerObject from a header and content.
+ ///
+ /// Note: values are not checked, so the tag can be different from the real content, or flags
+ /// can be invalid.
+ #[inline]
+ pub const fn from_header_and_content<'o>(
+ header: Header<'o>,
+ content: BerObjectContent<'o>,
+ ) -> BerObject<'o> {
+ BerObject { header, content }
+ }
+
+ /// Build a BerObject from its content, using default flags (no class, correct tag,
+ /// and constructed flag set only for Set and Sequence)
+ pub const fn from_obj(c: BerObjectContent) -> BerObject {
+ let class = Class::Universal;
+ let tag = c.tag();
+ let constructed = matches!(tag, Tag::Sequence | Tag::Set);
+ let header = Header::new(class, constructed, tag, Length::Definite(0));
+ BerObject { header, content: c }
+ }
+
+ /// Build a DER integer object from a slice containing an encoded integer
+ pub const fn from_int_slice(i: &'a [u8]) -> BerObject<'a> {
+ let header = Header::new(Class::Universal, false, Tag::Integer, Length::Definite(0));
+ BerObject {
+ header,
+ content: BerObjectContent::Integer(i),
+ }
+ }
+
+ /// Set a tag for the BER object
+ pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject {
+ let header = self.header.with_raw_tag(raw_tag.map(|x| x.into()));
+ BerObject { header, ..self }
+ }
+
+ /// Build a DER sequence object from a vector of DER objects
+ pub const fn from_seq(l: Vec<BerObject>) -> BerObject {
+ BerObject::from_obj(BerObjectContent::Sequence(l))
+ }
+
+ /// Build a DER set object from a vector of DER objects
+ pub const fn from_set(l: Vec<BerObject>) -> BerObject {
+ BerObject::from_obj(BerObjectContent::Set(l))
+ }
+
+ /// 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
+ ///
+ /// ```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> {
+ self.content.as_u64()
+ }
+
+ /// 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
+ ///
+ /// ```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> {
+ self.content.as_u32()
+ }
+
+ /// Attempt to read integer value from DER object.
+ /// This can fail if the object is not a boolean.
+ pub fn as_bool(&self) -> Result<bool, BerError> {
+ self.content.as_bool()
+ }
+
+ /// Attempt to read an OID value from DER object.
+ /// This can fail if the object is not an OID.
+ pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
+ self.content.as_oid()
+ }
+
+ /// Attempt to read an OID value from DER object.
+ /// This can fail if the object is not an OID.
+ pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
+ self.content.as_oid_val()
+ }
+
+ /// Attempt to get a reference on the content from an optional object.
+ /// This can fail if the object is not optional.
+ pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
+ self.content.as_optional()
+ }
+
+ /// Attempt to get a reference on the content from a tagged object.
+ /// This can fail if the object is not tagged.
+ pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
+ self.content.as_tagged()
+ }
+
+ /// Attempt to read a reference to a BitString value from DER object.
+ /// This can fail if the object is not an BitString.
+ ///
+ /// Note that this function returns a reference to the BitString. To get an owned value,
+ /// use [`as_bitstring`](struct.BerObject.html#method.as_bitstring)
+ pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
+ self.content.as_bitstring_ref()
+ }
+
+ /// Attempt to read a BitString value from DER object.
+ /// This can fail if the object is not an BitString.
+ pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
+ self.content.as_bitstring()
+ }
+
+ /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
+ #[cfg(feature = "bitvec")]
+ pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
+ self.content.as_bitslice()
+ }
+
+ /// Attempt to extract the list of objects from a DER sequence.
+ /// This can fail if the object is not a sequence.
+ pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
+ self.content.as_sequence()
+ }
+
+ /// Attempt to extract the list of objects from a DER set.
+ /// This can fail if the object is not a set.
+ pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
+ self.content.as_set()
+ }
+
+ /// Attempt to get the content from a DER object, as a slice.
+ /// This can fail if the object does not contain a type directly equivalent to a slice (e.g a
+ /// sequence).
+ /// This function mostly concerns string types, integers, or unknown DER objects.
+ pub fn as_slice(&self) -> Result<&'a [u8], BerError> {
+ self.content.as_slice()
+ }
+
+ /// Attempt to get the content from a DER object, as a str.
+ /// This can fail if the object does not contain a string type.
+ ///
+ /// Only some string types are considered here. Other
+ /// string types can be read using `as_slice`.
+ pub fn as_str(&self) -> Result<&'a str, BerError> {
+ self.content.as_str()
+ }
+
+ /// Get the BER object header's class.
+ #[inline]
+ pub const fn class(&self) -> Class {
+ self.header.class()
+ }
+
+ /// Get the BER object header's tag.
+ #[inline]
+ pub const fn tag(&self) -> Tag {
+ self.header.tag()
+ }
+
+ /// Get the BER object header's length.
+ #[inline]
+ pub const fn length(&self) -> Length {
+ self.header.length()
+ }
+
+ /// Test if object class is Universal
+ #[inline]
+ pub const fn is_universal(&self) -> bool {
+ self.header.is_universal()
+ }
+ /// Test if object class is Application
+ #[inline]
+ pub const fn is_application(&self) -> bool {
+ self.header.is_application()
+ }
+ /// Test if object class is Context-specific
+ #[inline]
+ pub const fn is_contextspecific(&self) -> bool {
+ self.header.is_contextspecific()
+ }
+ /// Test if object class is Private
+ #[inline]
+ pub fn is_private(&self) -> bool {
+ self.header.is_private()
+ }
+
+ /// Test if object is primitive
+ #[inline]
+ pub const fn is_primitive(&self) -> bool {
+ self.header.is_primitive()
+ }
+ /// Test if object is constructed
+ #[inline]
+ pub const fn is_constructed(&self) -> bool {
+ self.header.is_constructed()
+ }
+
+ /// Return error if `class` is not the expected class
+ #[inline]
+ pub const fn assert_class(&self, class: Class) -> Result<(), BerError> {
+ self.header.assert_class(class)
+ }
+
+ /// Return error if `tag` is not the expected tag
+ #[inline]
+ pub const fn assert_tag(&self, tag: Tag) -> Result<(), BerError> {
+ self.header.assert_tag(tag)
+ }
+
+ /// Return error if object is not constructed
+ #[inline]
+ pub const fn assert_constructed(&self) -> Result<(), BerError> {
+ self.header.assert_constructed()
+ }
+
+ /// Return error if object is not primitive
+ #[inline]
+ pub const fn assert_primitive(&self) -> Result<(), BerError> {
+ self.header.assert_primitive()
+ }
+}
+
+/// Build a DER object from an OID.
+impl<'a> From<Oid<'a>> for BerObject<'a> {
+ fn from(oid: Oid<'a>) -> BerObject<'a> {
+ BerObject::from_obj(BerObjectContent::OID(oid))
+ }
+}
+
+/// Build a DER object from a BerObjectContent.
+impl<'a> From<BerObjectContent<'a>> for BerObject<'a> {
+ fn from(obj: BerObjectContent<'a>) -> BerObject<'a> {
+ BerObject::from_obj(obj)
+ }
+}
+
+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::BerValueError)
+ }
+ }
+
+ /// 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::BerValueError)
+ }
+ }
+
+ /// 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::BitString(ignored_bits, data) => {
+ bitstring_to_u64(*ignored_bits as usize, data)
+ }
+ BerObjectContent::Enum(i) => Ok(*i),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ /// 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::BitString(ignored_bits, data) => {
+ bitstring_to_u64(*ignored_bits as usize, data).and_then(|x| {
+ if x > u64::from(core::u32::MAX) {
+ Err(BerError::IntegerTooLarge)
+ } else {
+ Ok(x as u32)
+ }
+ })
+ }
+ BerObjectContent::Enum(i) => {
+ if *i > u64::from(core::u32::MAX) {
+ Err(BerError::IntegerTooLarge)
+ } else {
+ Ok(*i as u32)
+ }
+ }
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ pub fn as_bool(&self) -> Result<bool, BerError> {
+ match *self {
+ BerObjectContent::Boolean(b) => Ok(b),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> {
+ match *self {
+ BerObjectContent::OID(ref o) => Ok(o),
+ BerObjectContent::RelativeOID(ref o) => Ok(o),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> {
+ self.as_oid().map(|o| o.clone())
+ }
+
+ pub fn as_optional(&self) -> Result<Option<&BerObject<'a>>, BerError> {
+ match *self {
+ BerObjectContent::Optional(Some(ref o)) => Ok(Some(o)),
+ BerObjectContent::Optional(None) => Ok(None),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ pub fn as_tagged(&self) -> Result<(Class, Tag, &BerObject<'a>), BerError> {
+ match *self {
+ BerObjectContent::Tagged(class, tag, ref o) => Ok((class, tag, o.as_ref())),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> {
+ match *self {
+ BerObjectContent::BitString(_, ref b) => Ok(b),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ pub fn as_bitstring(&self) -> Result<BitStringObject<'a>, BerError> {
+ match *self {
+ BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ /// Constructs a shared `&BitSlice` reference over the object data, if available as slice.
+ #[cfg(feature = "bitvec")]
+ pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> {
+ self.as_slice()
+ .and_then(|s| BitSlice::<Msb0, _>::from_slice(s).map_err(|_| BerError::BerValueError))
+ }
+
+ pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
+ match *self {
+ BerObjectContent::Sequence(ref s) => Ok(s),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> {
+ match *self {
+ BerObjectContent::Set(ref s) => Ok(s),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ #[rustfmt::skip]
+ pub fn as_slice(&self) -> Result<&'a [u8],BerError> {
+ match *self {
+ BerObjectContent::NumericString(s) |
+ BerObjectContent::BmpString(s) |
+ BerObjectContent::VisibleString(s) |
+ BerObjectContent::PrintableString(s) |
+ BerObjectContent::GeneralString(s) |
+ BerObjectContent::ObjectDescriptor(s) |
+ BerObjectContent::GraphicString(s) |
+ BerObjectContent::T61String(s) |
+ BerObjectContent::VideotexString(s) |
+ BerObjectContent::UTF8String(s) |
+ BerObjectContent::IA5String(s) => Ok(s.as_ref()),
+ BerObjectContent::Integer(s) |
+ BerObjectContent::BitString(_,BitStringObject{data:s}) |
+ BerObjectContent::OctetString(s) |
+ BerObjectContent::UniversalString(s) => Ok(s),
+ BerObjectContent::Unknown(ref any) => Ok(any.data),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ #[rustfmt::skip]
+ pub fn as_str(&self) -> Result<&'a str,BerError> {
+ match *self {
+ BerObjectContent::NumericString(s) |
+ BerObjectContent::BmpString(s) |
+ BerObjectContent::VisibleString(s) |
+ BerObjectContent::PrintableString(s) |
+ BerObjectContent::GeneralString(s) |
+ BerObjectContent::ObjectDescriptor(s) |
+ BerObjectContent::GraphicString(s) |
+ BerObjectContent::T61String(s) |
+ BerObjectContent::VideotexString(s) |
+ BerObjectContent::UTF8String(s) |
+ BerObjectContent::IA5String(s) => Ok(s),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ #[rustfmt::skip]
+ const fn tag(&self) -> Tag {
+ match self {
+ BerObjectContent::EndOfContent => Tag::EndOfContent,
+ BerObjectContent::Boolean(_) => Tag::Boolean,
+ BerObjectContent::Integer(_) => Tag::Integer,
+ BerObjectContent::BitString(_,_) => Tag::BitString,
+ BerObjectContent::OctetString(_) => Tag::OctetString,
+ BerObjectContent::Null => Tag::Null,
+ BerObjectContent::Enum(_) => Tag::Enumerated,
+ BerObjectContent::OID(_) => Tag::Oid,
+ BerObjectContent::NumericString(_) => Tag::NumericString,
+ BerObjectContent::VisibleString(_) => Tag::VisibleString,
+ BerObjectContent::PrintableString(_) => Tag::PrintableString,
+ BerObjectContent::IA5String(_) => Tag::Ia5String,
+ BerObjectContent::UTF8String(_) => Tag::Utf8String,
+ BerObjectContent::RelativeOID(_) => Tag::RelativeOid,
+ BerObjectContent::T61String(_) => Tag::T61String,
+ BerObjectContent::VideotexString(_) => Tag::VideotexString,
+ BerObjectContent::BmpString(_) => Tag::BmpString,
+ BerObjectContent::UniversalString(_) => Tag::UniversalString,
+ BerObjectContent::Sequence(_) => Tag::Sequence,
+ BerObjectContent::Set(_) => Tag::Set,
+ BerObjectContent::UTCTime(_) => Tag::UtcTime,
+ BerObjectContent::GeneralizedTime(_) => Tag::GeneralizedTime,
+ BerObjectContent::ObjectDescriptor(_) => Tag::ObjectDescriptor,
+ BerObjectContent::GraphicString(_) => Tag::GraphicString,
+ BerObjectContent::GeneralString(_) => Tag::GeneralString,
+ BerObjectContent::Tagged(_,x,_) => *x,
+ BerObjectContent::Unknown(any) => any.tag(),
+ BerObjectContent::Optional(Some(obj)) => obj.content.tag(),
+ BerObjectContent::Optional(None) => Tag(0x00), // XXX invalid !
+ }
+ }
+}
+
+#[cfg(feature = "bigint")]
+#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
+use num_bigint::{BigInt, BigUint};
+
+#[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(), Ok(65537.into()))
+ /// ```
+ pub fn as_bigint(&self) -> Result<BigInt, BerError> {
+ match self.content {
+ BerObjectContent::Integer(s) => Ok(BigInt::from_signed_bytes_be(s)),
+ _ => Err(BerError::BerValueError),
+ }
+ }
+
+ /// 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(), Ok(65537_u32.into()))
+ /// ```
+ pub fn as_biguint(&self) -> Result<BigUint, BerError> {
+ match self.content {
+ BerObjectContent::Integer(s) => {
+ if is_highest_bit_set(s) {
+ return Err(BerError::IntegerNegative);
+ }
+ Ok(BigUint::from_bytes_be(s))
+ }
+ _ => Err(BerError::BerValueError),
+ }
+ }
+}
+
+// This is a consuming iterator
+impl<'a> IntoIterator for BerObject<'a> {
+ type Item = BerObject<'a>;
+ type IntoIter = BerObjectIntoIterator<'a>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ // match self {
+ // BerObjectContent::Sequence(ref v) => (),
+ // _ => (),
+ // };
+ BerObjectIntoIterator { val: self, idx: 0 }
+ }
+}
+
+#[derive(Debug)]
+pub struct BerObjectIntoIterator<'a> {
+ val: BerObject<'a>,
+ idx: usize,
+}
+
+impl<'a> Iterator for BerObjectIntoIterator<'a> {
+ type Item = BerObject<'a>;
+ fn next(&mut self) -> Option<BerObject<'a>> {
+ // let result = if self.idx < self.vec.len() {
+ // Some(self.vec[self.idx].clone())
+ // } else {
+ // None
+ // };
+ let res = match self.val.content {
+ BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
+ BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()),
+ _ => {
+ if self.idx == 0 {
+ Some(self.val.clone())
+ } else {
+ None
+ }
+ }
+ };
+ self.idx += 1;
+ res
+ }
+}
+
+// impl<'a> Iterator for BerObjectContent<'a> {
+// type Item = BerObjectContent<'a>;
+//
+// fn next(&mut self) -> Option<BerObjectContent<'a>> {
+// None
+// }
+// }
+
+#[derive(Debug)]
+pub struct BerObjectRefIterator<'a> {
+ obj: &'a BerObject<'a>,
+ idx: usize,
+}
+
+impl<'a> Iterator for BerObjectRefIterator<'a> {
+ type Item = &'a BerObject<'a>;
+ fn next(&mut self) -> Option<&'a BerObject<'a>> {
+ let res = match (self.obj).content {
+ BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]),
+ BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]),
+ _ => None,
+ };
+ self.idx += 1;
+ res
+ }
+}
+
+impl<'a> BerObject<'a> {
+ pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> {
+ BerObjectRefIterator { obj: self, idx: 0 }
+ }
+}
+
+impl<'a> Index<usize> for BerObject<'a> {
+ type Output = BerObject<'a>;
+
+ fn index(&self, idx: usize) -> &BerObject<'a> {
+ match (self).content {
+ BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx],
+ BerObjectContent::Set(ref v) if idx < v.len() => &v[idx],
+ _ => panic!("Try to index BerObjectContent which is not constructed"),
+ }
+ // XXX the following
+ // self.ref_iter().nth(idx).unwrap()
+ // fails with:
+ // error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
+ // self.ref_iter().nth(idx).unwrap()
+ }
+}
+
+/// BitString wrapper
+#[derive(Clone, Debug, PartialEq)]
+pub struct BitStringObject<'a> {
+ pub data: &'a [u8],
+}
+
+impl<'a> BitStringObject<'a> {
+ /// Test if bit `bitnum` is set
+ pub fn is_set(&self, bitnum: usize) -> bool {
+ let byte_pos = bitnum / 8;
+ if byte_pos >= self.data.len() {
+ return false;
+ }
+ let b = 7 - (bitnum % 8);
+ (self.data[byte_pos] & (1 << b)) != 0
+ }
+
+ /// Constructs a shared `&BitSlice` reference over the object data.
+ #[cfg(feature = "bitvec")]
+ pub fn as_bitslice(&self) -> Option<&BitSlice<Msb0, u8>> {
+ BitSlice::<Msb0, _>::from_slice(self.data).ok()
+ }
+}
+
+impl<'a> AsRef<[u8]> for BitStringObject<'a> {
+ fn as_ref(&self) -> &[u8] {
+ self.data
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::ber::*;
+ use crate::oid::*;
+
+ #[test]
+ fn test_der_as_u64() {
+ let der_obj = BerObject::from_int_slice(b"\x01\x00\x02");
+ assert_eq!(der_obj.as_u64(), Ok(0x10002));
+ }
+
+ #[test]
+ fn test_ber_as_u64_bitstring() {
+ let (_, ber_obj) = parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xc0").unwrap();
+ assert_eq!(ber_obj.as_u64(), Ok(0b011011100101110111));
+
+ let (_, ber_obj_with_nonzero_padding) =
+ parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xe0").unwrap();
+ assert_eq!(
+ ber_obj_with_nonzero_padding.as_u64(),
+ Ok(0b011011100101110111)
+ );
+ }
+
+ #[test]
+ fn test_der_seq_iter() {
+ let der_obj = BerObject::from_obj(BerObjectContent::Sequence(vec![
+ BerObject::from_int_slice(b"\x01\x00\x01"),
+ BerObject::from_int_slice(b"\x01\x00\x00"),
+ ]));
+ let expected_values = vec![
+ BerObject::from_int_slice(b"\x01\x00\x01"),
+ BerObject::from_int_slice(b"\x01\x00\x00"),
+ ];
+
+ for (idx, v) in der_obj.ref_iter().enumerate() {
+ // println!("v: {:?}", v);
+ assert_eq!((*v), expected_values[idx]);
+ }
+ }
+
+ #[test]
+ fn test_der_from_oid() {
+ let obj: BerObject = Oid::from(&[1, 2]).unwrap().into();
+ let expected = BerObject::from_obj(BerObjectContent::OID(Oid::from(&[1, 2]).unwrap()));
+
+ assert_eq!(obj, expected);
+ }
+
+ #[test]
+ fn test_der_bitstringobject() {
+ let obj = BitStringObject {
+ data: &[0x0f, 0x00, 0x40],
+ };
+ assert!(!obj.is_set(0));
+ assert!(obj.is_set(7));
+ assert!(!obj.is_set(9));
+ assert!(obj.is_set(17));
+ }
+
+ #[cfg(feature = "bitvec")]
+ #[test]
+ 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).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
+ });
+ assert_eq!(&s, "000011110000000001000000");
+ }
+
+ #[test]
+ fn test_der_bistringobject_asref() {
+ fn assert_equal<T: AsRef<[u8]>>(s: T, b: &[u8]) {
+ assert_eq!(s.as_ref(), b);
+ }
+ let b: &[u8] = &[0x0f, 0x00, 0x40];
+ let obj = BitStringObject { data: b };
+ assert_equal(obj, b);
+ }
+
+ #[cfg(feature = "bigint")]
+ #[test]
+ fn test_der_to_bigint() {
+ let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
+ let expected = ::num_bigint::BigInt::from(0x10001);
+
+ assert_eq!(obj.as_bigint(), Ok(expected));
+ }
+
+ #[cfg(feature = "bigint")]
+ #[test]
+ fn test_der_to_biguint() {
+ let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
+ let expected = ::num_bigint::BigUint::from(0x10001_u32);
+
+ assert_eq!(obj.as_biguint(), Ok(expected));
+ }
+}
diff --git a/rust/vendor/der-parser/src/ber/compat.rs b/rust/vendor/der-parser/src/ber/compat.rs
new file mode 100644
index 0000000..ce52bb7
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/compat.rs
@@ -0,0 +1,9 @@
+//! Compatibility module for old (pre-7.0) types
+
+use super::{Class, Header, Length};
+pub use asn1_rs::Tag;
+
+pub type BerClass = Class;
+pub type BerSize = Length;
+pub type BerTag = Tag;
+pub type BerObjectHeader<'a> = Header<'a>;
diff --git a/rust/vendor/der-parser/src/ber/integer.rs b/rust/vendor/der-parser/src/ber/integer.rs
new file mode 100644
index 0000000..2ddb2a0
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/integer.rs
@@ -0,0 +1,130 @@
+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
+ .first()
+ .map(|byte| byte & 0b10000000 != 0)
+ .unwrap_or(false)
+}
diff --git a/rust/vendor/der-parser/src/ber/mod.rs b/rust/vendor/der-parser/src/ber/mod.rs
new file mode 100644
index 0000000..342743c
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/mod.rs
@@ -0,0 +1,78 @@
+//! Basic Encoding Rules (BER) objects and parser
+//!
+//! # BER Objects
+//!
+//! The main object of this crate is [`BerObject`]. It contains a header (ber tag, class, and size)
+//! and content.
+//!
+//! To parse primitive objects (for ex. integers or strings), use the `parse_ber_` set of
+//! functions.
+//!
+//! Constructed objects (like sequences, sets or tagged objects) require to use a combinator. This
+//! combinator takes a function or closure as input, and returns a new, specialized parser.
+//! See the [nom](https://github.com/geal/nom) parser combinator library for more details on
+//! combinators.
+//!
+//! # Examples
+//!
+//! Parse two BER integers:
+//!
+//! ```rust
+//! use der_parser::ber::parse_ber_integer;
+//!
+//! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x02, 0x03, 0x01, 0x00, 0x00,
+//! ];
+//!
+//! let (rem, obj1) = parse_ber_integer(&bytes).expect("parsing failed");
+//! let (rem, obj2) = parse_ber_integer(&bytes).expect("parsing failed");
+//! ```
+//!
+//! Parse a BER sequence containing one integer and an octetstring:
+//!
+//! ```rust
+//! use der_parser::ber::*;
+//!
+//! let bytes = [ 0x30, 0x0a,
+//! 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x04, 0x03, 0x62, 0x61, 0x64,
+//! ];
+//!
+//! let (rem, seq) = parse_ber_sequence_defined(|content| {
+//! let (rem, obj1) = parse_ber_integer(content)?;
+//! let (rem, obj2) = parse_ber_octetstring(rem)?;
+//! Ok((rem, vec![obj1, obj2]))
+//! })(&bytes)
+//! .expect("parsing failed");
+//! ```
+
+mod ber;
+mod integer;
+mod multi;
+mod parser;
+mod print;
+#[cfg(feature = "serialize")]
+mod serialize;
+mod tagged;
+mod visit;
+mod visit_mut;
+mod wrap_any;
+
+pub use crate::ber::ber::*;
+pub use crate::ber::multi::*;
+pub use crate::ber::parser::*;
+pub use crate::ber::print::*;
+#[cfg(feature = "serialize")]
+pub use crate::ber::serialize::*;
+pub use crate::ber::tagged::*;
+pub use crate::ber::visit::*;
+pub use crate::ber::visit_mut::*;
+pub use crate::ber::wrap_any::*;
+
+pub mod compat;
+
+pub use asn1_rs::{Class, Header, Length, Tag};
+
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::convert::Into;
diff --git a/rust/vendor/der-parser/src/ber/multi.rs b/rust/vendor/der-parser/src/ber/multi.rs
new file mode 100644
index 0000000..6168bc9
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/multi.rs
@@ -0,0 +1,531 @@
+use crate::ber::*;
+use crate::error::*;
+use asn1_rs::Tag;
+use nom::bytes::complete::take;
+use nom::combinator::{all_consuming, complete, cut, map};
+use nom::error::ParseError;
+use nom::multi::many0;
+use nom::{Err, IResult};
+
+/// Parse a SEQUENCE OF object
+///
+/// Given a subparser for a BER type, parse a sequence of identical objects.
+///
+/// ```rust
+/// # use der_parser::ber::{parse_ber_integer, parse_ber_sequence_of, BerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SEQUENCE OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<BerObject> {
+/// parse_ber_sequence_of(parse_ber_integer)(i)
+/// }
+///
+/// # 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)));
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_ber_sequence_of<'a, F>(f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult,
+{
+ map(parse_ber_sequence_of_v(f), BerObject::from_seq)
+}
+
+/// Parse a SEQUENCE OF object (returning a vec)
+///
+/// Given a subparser for a BER type, parse a sequence of identical objects.
+///
+/// This differs from `parse_ber_sequence_of` in the parse function and return type.
+///
+/// ```rust
+/// # use der_parser::ber::{parse_ber_integer, parse_ber_sequence_of_v, BerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SEQUENCE OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<Vec<BerObject>> {
+/// parse_ber_sequence_of_v(parse_ber_integer)(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x02, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = vec![
+/// # BerObject::from_int_slice(b"\x01\x00\x01"),
+/// # BerObject::from_int_slice(b"\x01\x00\x00"),
+/// # ];
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// # assert_eq!(v, expected);
+/// ```
+pub fn parse_ber_sequence_of_v<'a, T, F, E>(
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Vec<T>, E>
+where
+ F: FnMut(&'a [u8]) -> IResult<&'a [u8], T, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ let mut subparser = all_consuming(many0(complete(cut(f))));
+ parse_ber_sequence_defined_g(move |data, _| subparser(data))
+}
+
+/// Parse a defined sequence of DER elements (function version)
+///
+/// Given a list of expected parsers, apply them to build a DER sequence and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the sequence: any bytes that are part of the sequence but not
+/// parsed are ignored.
+///
+/// The object header is not available to the parsing function, and the returned type is always a
+/// `BerObject`.
+/// For a generic version, see
+/// [`parse_ber_sequence_defined_g`](fn.parse_ber_sequence_defined_g.html).
+///
+/// # Examples
+///
+/// Parsing a sequence of identical types (same as `parse_ber_sequence_of`):
+///
+/// ```rust
+/// # use der_parser::ber::{parse_ber_integer, parse_ber_sequence_defined, BerObject};
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::complete;
+/// use nom::multi::many1;
+///
+/// fn localparse_seq(i:&[u8]) -> BerResult {
+/// parse_ber_sequence_defined(
+/// many1(complete(parse_ber_integer))
+/// )(i)
+/// }
+///
+/// # 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)));
+/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed");
+/// ```
+///
+/// Parsing a defined sequence with different types:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map;
+/// use nom::sequence::tuple;
+///
+/// /// Read a DER-encoded object:
+/// /// SEQUENCE {
+/// /// a INTEGER,
+/// /// b OCTETSTRING
+/// /// }
+/// fn localparse_seq(i:&[u8]) -> BerResult {
+/// parse_ber_sequence_defined(
+/// // the nom `tuple` combinator returns a tuple, so we have to map it
+/// // to a list
+/// map(
+/// tuple((parse_ber_integer, parse_ber_octetstring)),
+/// |(a, b)| vec![a, b]
+/// )
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = BerObject::from_seq(vec![
+/// # BerObject::from_int_slice(b"\x01\x00\x01"),
+/// # BerObject::from_obj(BerObjectContent::OctetString(b"\x01\x00\x00")),
+/// # ]);
+/// # assert_eq!(localparse_seq(&bytes), Ok((empty, expected)));
+/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_ber_sequence_defined<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: FnMut(&'a [u8]) -> BerResult<Vec<BerObject>>,
+{
+ map(
+ parse_ber_sequence_defined_g(move |data, _| f(data)),
+ BerObject::from_seq,
+ )
+}
+
+/// Parse a defined SEQUENCE object (generic function)
+///
+/// Given a parser for sequence content, apply it to build a DER sequence and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the sequence: any bytes that are part of the sequence but not
+/// parsed are ignored.
+///
+/// Unlike `parse_ber_sequence_defined`, this function allows returning any object or error type,
+/// and also passes the object header to the callback.
+///
+/// # Examples
+///
+/// Parsing a defined sequence with different types:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// # #[derive(Debug, PartialEq)]
+/// pub struct MyObject<'a> {
+/// a: u32,
+/// b: &'a [u8],
+/// }
+///
+/// /// Read a DER-encoded object:
+/// /// SEQUENCE {
+/// /// a INTEGER (0..4294967295),
+/// /// b OCTETSTRING
+/// /// }
+/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> {
+/// parse_ber_sequence_defined_g(
+/// |i:&[u8], _| {
+/// let (i, a) = parse_ber_u32(i)?;
+/// let (i, obj) = parse_ber_octetstring(i)?;
+/// let b = obj.as_slice().unwrap();
+/// Ok((i, MyObject{ a, b }))
+/// }
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = MyObject {
+/// # a: 0x010001,
+/// # b: &[01, 00, 00]
+/// # };
+/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_ber_sequence_defined_g<'a, O, F, E>(
+ mut f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
+where
+ F: FnMut(&'a [u8], Header<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_ber_container(move |i, hdr| {
+ hdr.assert_tag(Tag::Sequence)
+ .map_err(|e| Err::Error(e.into()))?;
+ f(i, hdr)
+ })
+}
+
+/// Parse a SET OF object
+///
+/// Given a subparser for a BER type, parse a set of identical objects.
+///
+/// ```rust
+/// # use der_parser::ber::{parse_ber_integer, parse_ber_set_of, BerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SET OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<BerObject> {
+/// parse_ber_set_of(parse_ber_integer)(i)
+/// }
+///
+/// # 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)));
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_ber_set_of<'a, F>(f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult,
+{
+ map(parse_ber_set_of_v(f), BerObject::from_set)
+}
+
+/// Parse a SET OF object (returning a vec)
+///
+/// Given a subparser for a BER type, parse a set of identical objects.
+///
+/// This differs from `parse_ber_set_of` in the parse function and return type.
+///
+/// ```rust
+/// # use der_parser::ber::{parse_ber_integer, parse_ber_set_of_v, BerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SET OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<Vec<BerObject>> {
+/// parse_ber_set_of_v(parse_ber_integer)(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x31, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x02, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = vec![
+/// # BerObject::from_int_slice(b"\x01\x00\x01"),
+/// # BerObject::from_int_slice(b"\x01\x00\x00"),
+/// # ];
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// # assert_eq!(v, expected);
+/// ```
+pub fn parse_ber_set_of_v<'a, T, F, E>(f: F) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Vec<T>, E>
+where
+ F: FnMut(&'a [u8]) -> IResult<&'a [u8], T, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ let mut subparser = all_consuming(many0(complete(cut(f))));
+ parse_ber_set_defined_g(move |data, _| subparser(data))
+}
+
+/// Parse a defined set of DER elements (function version)
+///
+/// Given a list of expected parsers, apply them to build a DER set and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the set: any bytes that are part of the sequence but not
+/// parsed are ignored.
+/// The nom combinator `all_consuming` can be used to ensure all the content is parsed.
+///
+/// The object header is not available to the parsing function, and the returned type is always a
+/// `BerObject`.
+/// For a generic version, see [`parse_ber_set_defined_g`](fn.parse_ber_set_defined_g.html).
+///
+/// # Examples
+///
+/// Parsing a set of identical types (same as `parse_ber_set_of`):
+///
+/// ```rust
+/// # use der_parser::ber::{parse_ber_integer, parse_ber_set_defined, BerObject};
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::complete;
+/// use nom::multi::many1;
+///
+/// fn localparse_seq(i:&[u8]) -> BerResult {
+/// parse_ber_set_defined(
+/// many1(complete(parse_ber_integer))
+/// )(i)
+/// }
+///
+/// # 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!(localparse_seq(&bytes), Ok((empty, expected)));
+/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed");
+/// ```
+///
+/// Parsing a defined set with different types:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map;
+/// use nom::sequence::tuple;
+///
+/// /// Read a DER-encoded object:
+/// /// SET {
+/// /// a INTEGER,
+/// /// b OCTETSTRING
+/// /// }
+/// fn localparse_set(i:&[u8]) -> BerResult {
+/// parse_ber_set_defined(
+/// // the nom `tuple` combinator returns a tuple, so we have to map it
+/// // to a list
+/// map(
+/// tuple((parse_ber_integer, parse_ber_octetstring)),
+/// |(a, b)| vec![a, b]
+/// )
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x31, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = BerObject::from_set(vec![
+/// # BerObject::from_int_slice(b"\x01\x00\x01"),
+/// # BerObject::from_obj(BerObjectContent::OctetString(b"\x01\x00\x00")),
+/// # ]);
+/// # assert_eq!(localparse_set(&bytes), Ok((empty, expected)));
+/// let (rem, v) = localparse_set(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_ber_set_defined<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: FnMut(&'a [u8]) -> BerResult<Vec<BerObject>>,
+{
+ map(
+ parse_ber_set_defined_g(move |data, _| f(data)),
+ BerObject::from_set,
+ )
+}
+
+/// Parse a defined SET object (generic version)
+///
+/// Given a parser for set content, apply it to build a DER set and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the set: any bytes that are part of the sequence but not
+/// parsed are ignored.
+/// The nom combinator `all_consuming` can be used to ensure all the content is parsed.
+///
+/// Unlike `parse_ber_set_defined`, this function allows returning any object or error type,
+/// and also passes the object header to the callback.
+///
+/// # Examples
+///
+/// Parsing a defined set with different types:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// # #[derive(Debug, PartialEq)]
+/// pub struct MyObject<'a> {
+/// a: u32,
+/// b: &'a [u8],
+/// }
+///
+/// /// Read a DER-encoded object:
+/// /// SET {
+/// /// a INTEGER (0..4294967295),
+/// /// b OCTETSTRING
+/// /// }
+/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> {
+/// parse_ber_set_defined_g(
+/// |i:&[u8], _| {
+/// let (i, a) = parse_ber_u32(i)?;
+/// let (i, obj) = parse_ber_octetstring(i)?;
+/// let b = obj.as_slice().unwrap();
+/// Ok((i, MyObject{ a, b }))
+/// }
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x31, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = MyObject {
+/// # a: 0x010001,
+/// # b: &[01, 00, 00]
+/// # };
+/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_ber_set_defined_g<'a, O, F, E>(
+ mut f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
+where
+ F: FnMut(&'a [u8], Header<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_ber_container(move |i, hdr| {
+ hdr.assert_tag(Tag::Set).map_err(|e| Err::Error(e.into()))?;
+ f(i, hdr)
+ })
+}
+
+/// Parse a BER object and apply provided function to content
+///
+/// Given a parser for content, read BER object header and apply parser to
+/// return the remaining bytes and the parser result.
+///
+/// The remaining bytes point *after* the content: any bytes that are part of the content but not
+/// parsed are ignored.
+/// The nom combinator `all_consuming` can be used to ensure all the content is parsed.
+///
+/// This function is mostly intended for constructed objects, but can be used for any valid BER
+/// object.
+///
+/// # Examples
+///
+/// Parsing a defined sequence with different types:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::{BerError, BerResult};
+/// #
+/// # #[derive(Debug, PartialEq)]
+/// pub struct MyObject<'a> {
+/// a: u32,
+/// b: &'a [u8],
+/// }
+///
+/// /// Read a DER-encoded object:
+/// /// SEQUENCE {
+/// /// a INTEGER (0..4294967295),
+/// /// b OCTETSTRING
+/// /// }
+/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> {
+/// parse_ber_container(
+/// |i: &[u8], hdr: Header| {
+/// if hdr.tag() != Tag::Sequence {
+/// return Err(nom::Err::Error(BerError::BerTypeError.into()));
+/// }
+/// let (i, a) = parse_ber_u32(i)?;
+/// let (i, obj) = parse_ber_octetstring(i)?;
+/// let b = obj.as_slice().unwrap();
+/// Ok((i, MyObject{ a, b }))
+/// }
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = MyObject {
+/// # a: 0x010001,
+/// # b: &[01, 00, 00]
+/// # };
+/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_ber_container<'a, O, F, E>(mut f: F) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
+where
+ F: FnMut(&'a [u8], Header<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ move |i: &[u8]| {
+ let (i, hdr) = ber_read_element_header(i).map_err(nom::Err::convert)?;
+ let (i, data) = match hdr.length() {
+ Length::Definite(len) => take(len)(i)?,
+ Length::Indefinite => {
+ ber_get_object_content(i, &hdr, MAX_RECURSION).map_err(nom::Err::convert)?
+ }
+ };
+ let (_rest, v) = f(data, hdr)?;
+ Ok((i, v))
+ }
+}
diff --git a/rust/vendor/der-parser/src/ber/parser.rs b/rust/vendor/der-parser/src/ber/parser.rs
new file mode 100644
index 0000000..f951402
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/parser.rs
@@ -0,0 +1,661 @@
+use crate::ber::wrap_any::parse_ber_any_r;
+use crate::ber::*;
+use crate::error::*;
+use asn1_rs::{FromBer, Tag};
+use nom::bytes::streaming::take;
+use nom::{Err, Offset};
+
+/// Default maximum recursion limit
+pub const MAX_RECURSION: usize = 50;
+
+/// Default maximum object size (2^32)
+pub const MAX_OBJECT_SIZE: usize = 4_294_967_295;
+
+/// Skip object content, and return true if object was End-Of-Content
+pub(crate) fn ber_skip_object_content<'a>(
+ i: &'a [u8],
+ hdr: &Header,
+ max_depth: usize,
+) -> BerResult<'a, bool> {
+ if max_depth == 0 {
+ return Err(Err::Error(BerError::BerMaxDepth));
+ }
+ match hdr.length() {
+ Length::Definite(l) => {
+ if l == 0 && hdr.tag() == Tag::EndOfContent {
+ return Ok((i, true));
+ }
+ let (i, _) = take(l)(i)?;
+ Ok((i, false))
+ }
+ Length::Indefinite => {
+ if hdr.is_primitive() {
+ return Err(Err::Error(BerError::ConstructExpected));
+ }
+ // read objects until EndOfContent (00 00)
+ // this is recursive
+ let mut i = i;
+ loop {
+ let (i2, header2) = ber_read_element_header(i)?;
+ let (i3, eoc) = ber_skip_object_content(i2, &header2, max_depth - 1)?;
+ if eoc {
+ // return false, since top object was not EndOfContent
+ return Ok((i3, false));
+ }
+ i = i3;
+ }
+ }
+ }
+}
+
+/// Read object raw content (bytes)
+pub(crate) fn ber_get_object_content<'a>(
+ i: &'a [u8],
+ hdr: &Header,
+ max_depth: usize,
+) -> BerResult<'a, &'a [u8]> {
+ let start_i = i;
+ let (i, _) = ber_skip_object_content(i, hdr, max_depth)?;
+ let len = start_i.offset(i);
+ let (content, i) = start_i.split_at(len);
+ // if len is indefinite, there are 2 extra bytes for EOC
+ if hdr.length() == Length::Indefinite {
+ let len = content.len();
+ assert!(len >= 2);
+ Ok((i, &content[..len - 2]))
+ } else {
+ Ok((i, content))
+ }
+}
+
+/// Try to parse an input bit string as u64.
+///
+/// Note: this is for the primitive BER/DER encoding only, the
+/// constructed BER encoding for BIT STRING does not seem to be
+/// supported at all by the library currently.
+#[inline]
+pub(crate) fn bitstring_to_u64(
+ padding_bits: usize,
+ data: &BitStringObject,
+) -> Result<u64, BerError> {
+ let raw_bytes = data.data;
+ let bit_size = (raw_bytes.len() * 8)
+ .checked_sub(padding_bits)
+ .ok_or(BerError::InvalidLength)?;
+ if bit_size > 64 {
+ return Err(BerError::IntegerTooLarge);
+ }
+ let padding_bits = padding_bits % 8;
+ let num_bytes = if bit_size % 8 > 0 {
+ (bit_size / 8) + 1
+ } else {
+ bit_size / 8
+ };
+ let mut resulting_integer: u64 = 0;
+ for &c in &raw_bytes[..num_bytes] {
+ resulting_integer <<= 8;
+ resulting_integer |= c as u64;
+ }
+ Ok(resulting_integer >> padding_bits)
+}
+
+/// Read an object header
+///
+/// ### Example
+///
+/// ```
+/// # use der_parser::ber::{ber_read_element_header, Class, Length, Tag};
+/// #
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header");
+///
+/// assert_eq!(hdr.class(), Class::Universal);
+/// assert_eq!(hdr.tag(), Tag::Integer);
+/// assert_eq!(hdr.length(), Length::Definite(3));
+/// ```
+#[inline]
+pub fn ber_read_element_header(i: &[u8]) -> BerResult<Header> {
+ Header::from_ber(i)
+}
+
+/// Parse the next bytes as the *content* of a BER object.
+///
+/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
+///
+/// This function is mostly used when parsing implicit tagged objects, when reading primitive
+/// types.
+///
+/// `max_depth` is the maximum allowed recursion for objects.
+///
+/// ### Example
+///
+/// ```
+/// # use der_parser::ber::{ber_read_element_content_as, ber_read_element_header, Tag};
+/// #
+/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header");
+/// let (_, content) = ber_read_element_content_as(
+/// i, hdr.tag(), hdr.length(), hdr.is_constructed(), 5
+/// ).expect("parsing failed");
+/// #
+/// # assert_eq!(hdr.tag(), Tag::Integer);
+/// # assert_eq!(content.as_u32(), Ok(0x10001));
+/// ```
+#[inline]
+pub fn ber_read_element_content_as(
+ i: &[u8],
+ tag: Tag,
+ length: Length,
+ constructed: bool,
+ max_depth: usize,
+) -> BerResult<BerObjectContent> {
+ try_read_berobjectcontent_as(i, tag, length, constructed, max_depth)
+}
+
+/// Parse the next bytes as the content of a BER object (combinator, header reference)
+///
+/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
+///
+/// Caller is also responsible to check if parsing function consumed the expected number of
+/// bytes (`header.len`).
+///
+/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
+///
+/// This function differs from [`parse_ber_content2`](fn.parse_ber_content2.html) because it passes
+/// the BER object header by reference (required for ex. by `parse_ber_implicit`).
+///
+/// Example: manually parsing header and content
+///
+/// ```
+/// # use der_parser::ber::*;
+/// #
+/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (i, header) = ber_read_element_header(bytes).expect("parsing failed");
+/// let (rem, content) = parse_ber_content(header.tag())(i, &header, MAX_RECURSION)
+/// .expect("parsing failed");
+/// #
+/// # assert_eq!(header.tag(), Tag::Integer);
+/// ```
+pub fn parse_ber_content<'a>(
+ tag: Tag,
+) -> impl Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, BerObjectContent<'a>> {
+ move |i: &[u8], hdr: &Header, max_recursion: usize| {
+ ber_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion)
+ }
+}
+
+/// Parse the next bytes as the content of a BER object (combinator, owned header)
+///
+/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
+///
+/// Caller is also responsible to check if parsing function consumed the expected number of
+/// bytes (`header.len`).
+///
+/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
+///
+/// This function differs from [`parse_ber_content`](fn.parse_ber_content.html) because it passes
+/// an owned BER object header (required for ex. by `parse_ber_tagged_implicit_g`).
+///
+/// Example: manually parsing header and content
+///
+/// ```
+/// # use der_parser::ber::*;
+/// #
+/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (i, header) = ber_read_element_header(bytes).expect("parsing failed");
+/// let (rem, content) = parse_ber_content(header.tag())(i, &header, MAX_RECURSION)
+/// .expect("parsing failed");
+/// #
+/// # assert_eq!(header.tag(), Tag::Integer);
+/// ```
+pub fn parse_ber_content2<'a>(
+ tag: Tag,
+) -> impl Fn(&'a [u8], Header<'a>, usize) -> BerResult<'a, BerObjectContent<'a>> {
+ move |i: &[u8], hdr: Header, max_recursion: usize| {
+ ber_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion)
+ }
+}
+
+/// Parse a BER object, expecting a value with specified tag
+///
+/// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`.
+///
+/// ### Example
+///
+/// ```
+/// use der_parser::ber::Tag;
+/// use der_parser::ber::parse_ber_with_tag;
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_ber_with_tag(bytes, Tag::Integer).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag(), Tag::Integer);
+/// ```
+pub fn parse_ber_with_tag<T: Into<Tag>>(i: &[u8], tag: T) -> BerResult {
+ let tag = tag.into();
+ let (i, hdr) = ber_read_element_header(i)?;
+ hdr.assert_tag(tag)?;
+ let (i, content) = ber_read_element_content_as(
+ i,
+ hdr.tag(),
+ hdr.length(),
+ hdr.is_constructed(),
+ MAX_RECURSION,
+ )?;
+ Ok((i, BerObject::from_header_and_content(hdr, content)))
+}
+
+/// Read end of content marker
+#[inline]
+pub fn parse_ber_endofcontent(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::EndOfContent)
+}
+
+/// Read a boolean value
+///
+/// The encoding of a boolean value shall be primitive. The contents octets shall consist of a
+/// single octet.
+///
+/// If the boolean value is FALSE, the octet shall be zero.
+/// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff).
+#[inline]
+pub fn parse_ber_bool(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Boolean)
+}
+
+/// Read an integer value
+///
+/// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or
+/// more octets.
+///
+/// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64),
+/// [`as_u32`](struct.BerObject.html#method.as_u32),
+/// [`as_biguint`](struct.BerObject.html#method.as_biguint) or
+/// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods.
+/// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option`
+/// objects.
+///
+/// # Examples
+///
+/// ```rust
+/// # extern crate nom;
+/// # use der_parser::ber::parse_ber_integer;
+/// # use der_parser::ber::{BerObject,BerObjectContent};
+/// let empty = &b""[..];
+/// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01];
+/// let expected = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
+/// assert_eq!(
+/// parse_ber_integer(&bytes),
+/// Ok((empty, expected))
+/// );
+/// ```
+#[inline]
+pub fn parse_ber_integer(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Integer)
+}
+
+/// Read an bitstring value
+#[inline]
+pub fn parse_ber_bitstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::BitString)
+}
+
+/// Read an octetstring value
+#[inline]
+pub fn parse_ber_octetstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::OctetString)
+}
+
+/// Read a null value
+#[inline]
+pub fn parse_ber_null(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Null)
+}
+
+/// Read an object identifier value
+#[inline]
+pub fn parse_ber_oid(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Oid)
+}
+
+/// Read an enumerated value
+#[inline]
+pub fn parse_ber_enum(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Enumerated)
+}
+
+/// Read a UTF-8 string value. The encoding is checked.
+#[inline]
+pub fn parse_ber_utf8string(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Utf8String)
+}
+
+/// Read a relative object identifier value
+#[inline]
+pub fn parse_ber_relative_oid(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::RelativeOid)
+}
+
+/// Parse a sequence of BER elements
+///
+/// Read a sequence of BER objects, without any constraint on the types.
+/// Sequence is parsed recursively, so if constructed elements are found, they are parsed using the
+/// same function.
+///
+/// To read a specific sequence of objects (giving the expected types), use the
+/// [`parse_ber_sequence_defined`](macro.parse_ber_sequence_defined.html) macro.
+#[inline]
+pub fn parse_ber_sequence(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Sequence)
+}
+
+/// Parse a set of BER elements
+///
+/// Read a set of BER objects, without any constraint on the types.
+/// Set is parsed recursively, so if constructed elements are found, they are parsed using the
+/// same function.
+///
+/// To read a specific set of objects (giving the expected types), use the
+/// [`parse_ber_set_defined`](macro.parse_ber_set_defined.html) macro.
+#[inline]
+pub fn parse_ber_set(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Set)
+}
+
+/// Read a numeric string value. The content is verified to
+/// contain only digits and spaces.
+#[inline]
+pub fn parse_ber_numericstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::NumericString)
+}
+
+/// Read a visible string value. The content is verified to
+/// contain only the allowed characters.
+#[inline]
+pub fn parse_ber_visiblestring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::VisibleString)
+}
+
+/// Read a printable string value. The content is verified to
+/// contain only the allowed characters.
+#[inline]
+pub fn parse_ber_printablestring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::PrintableString)
+}
+
+/// Read a T61 string value
+#[inline]
+pub fn parse_ber_t61string(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::T61String)
+}
+
+/// Read a Videotex string value
+#[inline]
+pub fn parse_ber_videotexstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::VideotexString)
+}
+
+/// Read an IA5 string value. The content is verified to be ASCII.
+#[inline]
+pub fn parse_ber_ia5string(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::Ia5String)
+}
+
+/// Read an UTC time value
+#[inline]
+pub fn parse_ber_utctime(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::UtcTime)
+}
+
+/// Read a Generalized time value
+#[inline]
+pub fn parse_ber_generalizedtime(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::GeneralizedTime)
+}
+
+/// Read an ObjectDescriptor value
+#[inline]
+pub fn parse_ber_objectdescriptor(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::ObjectDescriptor)
+}
+
+/// Read a GraphicString value
+#[inline]
+pub fn parse_ber_graphicstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::GraphicString)
+}
+
+/// Read a GeneralString value
+#[inline]
+pub fn parse_ber_generalstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::GeneralString)
+}
+
+/// Read a BmpString value
+#[inline]
+pub fn parse_ber_bmpstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::BmpString)
+}
+
+/// Read a UniversalString value
+#[inline]
+pub fn parse_ber_universalstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, Tag::UniversalString)
+}
+
+/// Parse an optional tagged object, applying function to get content
+///
+/// This function returns a `BerObject`, trying to read content as generic BER objects.
+/// If parsing failed, return an optional object containing `None`.
+///
+/// To support other return or error types, use
+/// [parse_ber_tagged_explicit_g](fn.parse_ber_tagged_explicit_g.html)
+///
+/// This function will never fail: if parsing content failed, the BER value `Optional(None)` is
+/// returned.
+pub fn parse_ber_explicit_optional<F>(i: &[u8], tag: Tag, f: F) -> BerResult
+where
+ F: Fn(&[u8]) -> BerResult,
+{
+ parse_ber_optional(parse_ber_tagged_explicit_g(tag, |content, hdr| {
+ let (rem, obj) = f(content)?;
+ let content = BerObjectContent::Tagged(hdr.class(), hdr.tag(), Box::new(obj));
+ let tagged = BerObject::from_header_and_content(hdr, content);
+ Ok((rem, tagged))
+ }))(i)
+}
+
+/// Parse an implicit tagged object, applying function to read content
+///
+/// Note: unlike explicit tagged functions, the callback must be a *content* parsing function,
+/// often based on the [`parse_ber_content`](fn.parse_ber_content.html) combinator.
+///
+/// The built object will use the original header (and tag), so the content may not match the tag
+/// value.
+///
+/// For a combinator version, see [parse_ber_tagged_implicit](fn.parse_ber_tagged_implicit.html).
+///
+/// For a generic version (different output and error types), see
+/// [parse_ber_tagged_implicit_g](fn.parse_ber_tagged_implicit_g.html).
+///
+/// # Examples
+///
+/// The following parses `[3] IMPLICIT INTEGER` into a `BerObject`:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> BerResult<BerObject> {
+/// parse_ber_implicit(
+/// i,
+/// 3,
+/// parse_ber_content(Tag::Integer),
+/// )
+/// }
+///
+/// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01];
+/// let res = parse_int_implicit(bytes);
+/// # match res {
+/// # Ok((rem, content)) => {
+/// # assert!(rem.is_empty());
+/// # assert_eq!(content.as_u32(), Ok(0x10001));
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+#[inline]
+pub fn parse_ber_implicit<'a, T, F>(i: &'a [u8], tag: T, f: F) -> BerResult<'a>
+where
+ F: Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, BerObjectContent<'a>>,
+ T: Into<Tag>,
+{
+ parse_ber_tagged_implicit(tag, f)(i)
+}
+
+/// Combinator for building optional BER values
+///
+/// To read optional BER values, it is to use the nom `opt()` combinator. However, this results in
+/// a `Option<BerObject>` and prevents using some functions from this crate (the generic functions
+/// can still be used).
+///
+/// This combinator is used when parsing BER values, while keeping `BerObject` output only.
+///
+/// This function will never fail: if parsing content failed, the BER value `Optional(None)` is
+/// returned.
+///
+/// ### Example
+///
+/// ```
+/// # use der_parser::ber::*;
+/// #
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let mut parser = parse_ber_optional(parse_ber_integer);
+/// let (_, obj) = parser(bytes).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag(), Tag::Integer);
+/// assert!(obj.as_optional().is_ok());
+/// ```
+pub fn parse_ber_optional<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult<'a>
+where
+ F: FnMut(&'a [u8]) -> BerResult<'a>,
+{
+ move |i: &[u8]| {
+ let res = f(i);
+ match res {
+ Ok((rem, inner)) => {
+ let opt = BerObject::from_header_and_content(
+ inner.header.clone(),
+ BerObjectContent::Optional(Some(Box::new(inner))),
+ );
+ Ok((rem, opt))
+ }
+ Err(_) => Ok((i, BerObject::from_obj(BerObjectContent::Optional(None)))),
+ }
+ }
+}
+
+/// 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> {
+ <i32>::from_ber(i)
+}
+
+/// 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> {
+ <i64>::from_ber(i)
+}
+
+/// 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> {
+ <u32>::from_ber(i)
+}
+
+/// Parse BER object and try to decode it as a 64-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_u64(i: &[u8]) -> BerResult<u64> {
+ <u64>::from_ber(i)
+}
+
+/// Parse BER object and get content as slice
+#[inline]
+pub fn parse_ber_slice<T: Into<Tag>>(i: &[u8], tag: T) -> BerResult<&[u8]> {
+ let tag = tag.into();
+ parse_ber_container(move |content, hdr| {
+ hdr.assert_tag(tag)?;
+ Ok((&b""[..], content))
+ })(i)
+}
+
+/// Parse BER object recursively, specifying the maximum recursion depth
+///
+/// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error.
+///
+/// ### Example
+///
+/// ```
+/// use der_parser::ber::{parse_ber_recursive, Tag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_ber_recursive(bytes, 1).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag(), Tag::Integer);
+/// ```
+#[inline]
+pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult {
+ parse_ber_any_r(i, max_depth)
+}
+
+/// Parse BER object recursively
+///
+/// Return a tuple containing the remaining (unparsed) bytes and the BER Object, or an error.
+///
+/// *Note*: this is the same as calling `parse_ber_recursive` with `MAX_RECURSION`.
+///
+/// ### Example
+///
+/// ```
+/// use der_parser::ber::{parse_ber, Tag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_ber(bytes).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag(), Tag::Integer);
+/// ```
+#[inline]
+pub fn parse_ber(i: &[u8]) -> BerResult {
+ parse_ber_recursive(i, MAX_RECURSION)
+}
+
+#[test]
+fn test_bitstring_to_u64() {
+ // ignored bits modulo 8 to 0
+ let data = &hex_literal::hex!("0d 71 82");
+ let r = bitstring_to_u64(8, &BitStringObject { data });
+ assert_eq!(r, Ok(0x0d71));
+
+ // input too large to fit a 64-bits integer
+ let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31");
+ let r = bitstring_to_u64(0, &BitStringObject { data });
+ assert!(r.is_err());
+
+ // test large number but with many ignored bits
+ let data = &hex_literal::hex!("0d 71 82 0e 73 72 76 6e 67 6e 62 6c 6e 2d 65 78 30 31");
+ let r = bitstring_to_u64(130, &BitStringObject { data });
+ // 2 = 130 % 8
+ assert_eq!(r, Ok(0x0d71 >> 2));
+}
diff --git a/rust/vendor/der-parser/src/ber/print.rs b/rust/vendor/der-parser/src/ber/print.rs
new file mode 100644
index 0000000..ce15523
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/print.rs
@@ -0,0 +1,209 @@
+use crate::ber::BitStringObject;
+use crate::ber::{BerObject, BerObjectContent};
+use alloc::string::{String, ToString};
+use alloc::vec;
+use alloc::vec::Vec;
+use asn1_rs::{Class, Header, Length, Tag};
+use core::fmt;
+use core::iter::FromIterator;
+use core::str;
+use debug::HexSlice;
+
+use rusticata_macros::debug;
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum PrettyPrinterFlag {
+ Recursive,
+ ShowHeader,
+}
+
+/// Pretty-print BER object
+///
+/// This method is recursive by default. To prevent that, unset the `Recursive` flag.
+pub struct PrettyBer<'a> {
+ obj: &'a BerObject<'a>,
+ indent: usize,
+ inc: usize,
+
+ flags: Vec<PrettyPrinterFlag>,
+}
+
+impl<'a> BerObject<'a> {
+ pub fn as_pretty(&'a self, indent: usize, increment: usize) -> PrettyBer<'a> {
+ PrettyBer::new(self, vec![PrettyPrinterFlag::Recursive], indent, increment)
+ }
+}
+
+impl<'a> PrettyBer<'a> {
+ pub const fn new(
+ obj: &'a BerObject<'a>,
+ flags: Vec<PrettyPrinterFlag>,
+ indent: usize,
+ increment: usize,
+ ) -> Self {
+ Self {
+ obj,
+ indent,
+ inc: increment,
+ flags,
+ }
+ }
+
+ pub fn set_flag(&mut self, flag: PrettyPrinterFlag) {
+ if !self.flags.contains(&flag) {
+ self.flags.push(flag);
+ }
+ }
+
+ pub fn unset_flag(&mut self, flag: PrettyPrinterFlag) {
+ self.flags.retain(|&f| f != flag);
+ }
+
+ pub fn is_flag_set(&self, flag: PrettyPrinterFlag) -> bool {
+ self.flags.contains(&flag)
+ }
+
+ pub fn next_indent<'b>(&self, obj: &'b BerObject) -> PrettyBer<'b> {
+ PrettyBer {
+ obj,
+ indent: self.indent + self.inc,
+ inc: self.inc,
+ flags: self.flags.to_vec(),
+ }
+ }
+
+ #[inline]
+ fn is_recursive(&self) -> bool {
+ self.is_flag_set(PrettyPrinterFlag::Recursive)
+ }
+}
+
+fn dbg_header(header: &Header, f: &mut fmt::Formatter) -> fmt::Result {
+ let s_constructed = if header.is_constructed() { "+" } else { "" };
+ let l = match header.length() {
+ Length::Definite(sz) => sz.to_string(),
+ Length::Indefinite => "Indefinite".to_string(),
+ };
+ match header.class() {
+ Class::Universal => {
+ write!(f, "[{}]{} {}", header.tag(), s_constructed, l)?;
+ }
+ Class::ContextSpecific => {
+ write!(f, "[{}]{} {}", header.tag().0, s_constructed, l)?;
+ }
+
+ class => {
+ write!(f, "[{} {}]{} {}", class, header.tag().0, s_constructed, l)?;
+ }
+ }
+ Ok(())
+}
+
+impl<'a> fmt::Debug for PrettyBer<'a> {
+ #[rustfmt::skip]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.indent > 0 {
+ write!(f, "{:1$}", " ", self.indent)?;
+ };
+ if self.flags.contains(&PrettyPrinterFlag::ShowHeader) {
+ dbg_header(&self.obj.header, f)?;
+ write!(f, " ")?;
+ };
+ 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| core::char::from_u32(u32::from_be_bytes([a[0], a[1], a[2], a[3]])))
+ .collect();
+
+ match chars {
+ Some(b) => writeln!(f, "{}(\"{}\")", ty, String::from_iter(b)),
+ None => writeln!(f, "{}({:?}) <error decoding utf32 string>", ty, s),
+ }
+ }
+ match self.obj.content {
+ BerObjectContent::EndOfContent => write!(f, "EndOfContent"),
+ BerObjectContent::Boolean(b) => write!(f, "Boolean({:?})", b),
+ BerObjectContent::Integer(i) => write!(f, "Integer({:?})", HexSlice(i)),
+ BerObjectContent::Enum(i) => write!(f, "Enum({})", i),
+ BerObjectContent::OID(ref v) => write!(f, "OID({:?})", v),
+ BerObjectContent::RelativeOID(ref v) => write!(f, "RelativeOID({:?})", v),
+ BerObjectContent::Null => write!(f, "Null"),
+ BerObjectContent::OctetString(v) => write!(f, "OctetString({:?})", HexSlice(v)),
+ BerObjectContent::BitString(u,BitStringObject{data:v})
+ => write!(f, "BitString({},{:?})", u, HexSlice(v)),
+ BerObjectContent::GeneralizedTime(ref time) => write!(f, "GeneralizedTime(\"{}\")", time),
+ BerObjectContent::UTCTime(ref time) => write!(f, "UTCTime(\"{}\")", time),
+ BerObjectContent::VisibleString(s) => write!(f, "VisibleString(\"{}\")", s),
+ BerObjectContent::GeneralString(s) => write!(f, "GeneralString(\"{}\")", s),
+ BerObjectContent::GraphicString(s) => write!(f, "GraphicString(\"{}\")", s),
+ BerObjectContent::PrintableString(s) => write!(f, "PrintableString(\"{}\")", s),
+ BerObjectContent::NumericString(s) => write!(f, "NumericString(\"{}\")", s),
+ BerObjectContent::UTF8String(s) => write!(f, "UTF8String(\"{}\")", s),
+ BerObjectContent::IA5String(s) => write!(f, "IA5String(\"{}\")", s),
+ BerObjectContent::T61String(s) => write!(f, "T61String({})", s),
+ BerObjectContent::VideotexString(s) => write!(f, "VideotexString({})", s),
+ BerObjectContent::ObjectDescriptor(s) => write!(f, "ObjectDescriptor(\"{}\")", s),
+ BerObjectContent::BmpString(s) => write!(f, "BmpString(\"{}\")", s),
+ BerObjectContent::UniversalString(s) => print_utf32_string_with_type(f, s, "UniversalString"),
+ BerObjectContent::Optional(ref o) => {
+ match o {
+ Some(obj) => write!(f, "OPTION {:?}", obj),
+ None => write!(f, "NONE"),
+ }
+ }
+ BerObjectContent::Tagged(class, tag, ref obj) => {
+ writeln!(f, "ContextSpecific [{} {}] {{", class, tag.0)?;
+ write!(f, "{:?}", self.next_indent(obj))?;
+ if self.indent > 0 {
+ write!(f, "{:1$}", " ", self.indent)?;
+ };
+ write!(f, "}}")?;
+ Ok(())
+ },
+ BerObjectContent::Set(ref v) |
+ BerObjectContent::Sequence(ref v) => {
+ let ty = if self.obj.header.tag() == Tag::Sequence { "Sequence" } else { "Set" };
+ if self.is_recursive() {
+ writeln!(f, "{}[", ty)?;
+ for o in v {
+ write!(f, "{:?}", self.next_indent(o))?;
+ };
+ if self.indent > 0 {
+ write!(f, "{:1$}", " ", self.indent)?;
+ };
+ write!(f, "]")?;
+ } else {
+ write!(f, "{}", ty)?;
+ }
+ Ok(())
+ },
+ BerObjectContent::Unknown(ref any) => {
+ write!(f, "Unknown {:x?}", HexSlice(any.data))
+ },
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::PrettyPrinterFlag;
+ use crate::ber::*;
+
+ #[test]
+ fn test_pretty_print() {
+ let d = BerObject::from_obj(BerObjectContent::Sequence(vec![
+ BerObject::from_int_slice(b"\x01\x00\x01"),
+ BerObject::from_int_slice(b"\x01\x00\x01"),
+ BerObject::from_obj(BerObjectContent::Set(vec![
+ BerObject::from_int_slice(b"\x01"),
+ BerObject::from_int_slice(b"\x02"),
+ ])),
+ ]));
+
+ println!("{:?}", d.as_pretty(0, 2));
+
+ let mut pp = d.as_pretty(0, 4);
+ pp.set_flag(PrettyPrinterFlag::ShowHeader);
+ println!("{:?}", pp);
+ }
+}
diff --git a/rust/vendor/der-parser/src/ber/serialize.rs b/rust/vendor/der-parser/src/ber/serialize.rs
new file mode 100644
index 0000000..0839e02
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/serialize.rs
@@ -0,0 +1,419 @@
+#![cfg(feature = "std")]
+use crate::ber::*;
+use crate::oid::Oid;
+use asn1_rs::{ASN1DateTime, Tag};
+use cookie_factory::bytes::be_u8;
+use cookie_factory::combinator::slice;
+use cookie_factory::gen_simple;
+use cookie_factory::multi::many_ref;
+use cookie_factory::sequence::tuple;
+use cookie_factory::{GenError, SerializeFn};
+use std::io::Write;
+
+fn encode_length<'a, W: Write + 'a, Len: Into<Length>>(len: Len) -> impl SerializeFn<W> + 'a {
+ let l = len.into();
+ move |out| {
+ match l {
+ Length::Definite(sz) => {
+ if sz <= 128 {
+ // definite, short form
+ be_u8(sz as u8)(out)
+ } else {
+ // definite, long form
+ let v: Vec<u8> = sz
+ .to_be_bytes()
+ .iter()
+ .cloned()
+ .skip_while(|&b| b == 0)
+ .collect();
+ let b0 = 0b1000_0000 | (v.len() as u8);
+ tuple((be_u8(b0), slice(v)))(out)
+ }
+ }
+ Length::Indefinite => be_u8(0b1000_0000)(out),
+ }
+ }
+}
+
+/// Encode header as object
+///
+/// The `len` field must be correct
+#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
+pub fn ber_encode_header<'a, 'b: 'a, W: Write + 'a>(hdr: &'b Header) -> impl SerializeFn<W> + 'a {
+ move |out| {
+ // identifier octets (X.690 8.1.2)
+ let class_u8 = (hdr.class() as u8) << 6;
+ let pc_u8 = (if hdr.constructed() { 1 } else { 0 }) << 5;
+ if hdr.tag().0 >= 30 {
+ unimplemented!();
+ }
+ let byte_0 = class_u8 | pc_u8 | (hdr.tag().0 as u8);
+ // length octets (X.690 8.1.3)
+ tuple((be_u8(byte_0), encode_length(hdr.length())))(out)
+ }
+}
+
+fn ber_encode_oid<'a, W: Write + 'a>(oid: &'a Oid) -> impl SerializeFn<W> + 'a {
+ move |out| {
+ // check oid.relative attribute ? this should not be necessary
+ slice(oid.as_bytes())(out)
+ }
+}
+
+fn ber_encode_datetime<'a, W: Write + 'a>(time: &'a ASN1DateTime) -> impl SerializeFn<W> + 'a {
+ move |out| {
+ let s = format!("{}", time);
+ slice(s)(out)
+ }
+}
+
+fn ber_encode_sequence<'a, W: Write + Default + AsRef<[u8]> + 'a>(
+ v: &'a [BerObject],
+) -> impl SerializeFn<W> + 'a {
+ many_ref(v, ber_encode_object)
+}
+
+/// Encode the provided object in an EXPLICIT tagged value, using the provided tag ans class
+///
+/// Note: `obj` should be the object to be encapsulated, not the `ContextSpecific` variant.
+#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
+pub fn ber_encode_tagged_explicit<'a, W: Write + Default + AsRef<[u8]> + 'a>(
+ tag: Tag,
+ class: Class,
+ obj: &'a BerObject,
+) -> impl SerializeFn<W> + 'a {
+ move |out| {
+ // encode inner object
+ 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 = Header::new(class, true /* X.690 8.14.2 */, tag, len.into());
+ let v_hdr = gen_simple(ber_encode_header(&hdr), W::default())?;
+ tuple((slice(v_hdr), slice(v)))(out)
+ }
+}
+
+/// Encode the provided object in an IMPLICIT tagged value, using the provided tag and class
+///
+/// Note: `obj` should be the object to be encapsulated, not the `ContextSpecific` variant.
+#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
+pub fn ber_encode_tagged_implicit<'a, W: Write + Default + AsRef<[u8]> + 'a>(
+ tag: Tag,
+ class: Class,
+ obj: &'a BerObject,
+) -> impl SerializeFn<W> + 'a {
+ move |out| {
+ // encode inner object content
+ let v = gen_simple(ber_encode_object_content(&obj.content), W::default())?;
+ // but replace the tag (keep constructed attribute)
+ let len = v.as_ref().len();
+ let hdr = Header::new(class, obj.header.constructed(), tag, len.into());
+ let v_hdr = gen_simple(ber_encode_header(&hdr), W::default())?;
+ tuple((slice(v_hdr), slice(v)))(out)
+ }
+}
+
+fn ber_encode_object_content<'a, W: Write + Default + AsRef<[u8]> + 'a>(
+ c: &'a BerObjectContent,
+) -> impl SerializeFn<W> + 'a {
+ move |out| match c {
+ BerObjectContent::EndOfContent => be_u8(0)(out),
+ BerObjectContent::Boolean(b) => {
+ let b0 = if *b { 0xff } else { 0x00 };
+ be_u8(b0)(out)
+ }
+ BerObjectContent::Integer(s) => slice(s)(out),
+ BerObjectContent::BitString(ignored_bits, s) => {
+ tuple((be_u8(*ignored_bits), slice(s)))(out)
+ }
+ BerObjectContent::OctetString(s) => slice(s)(out),
+ BerObjectContent::Null => Ok(out),
+ BerObjectContent::Enum(i) => {
+ let v: Vec<u8> = i
+ .to_be_bytes()
+ .iter()
+ .cloned()
+ .skip_while(|&b| b == 0)
+ .collect();
+ slice(v)(out)
+ }
+ BerObjectContent::OID(oid) | BerObjectContent::RelativeOID(oid) => ber_encode_oid(oid)(out),
+ BerObjectContent::UTCTime(time) | BerObjectContent::GeneralizedTime(time) => {
+ ber_encode_datetime(time)(out)
+ }
+ BerObjectContent::NumericString(s)
+ | BerObjectContent::BmpString(s)
+ | BerObjectContent::GeneralString(s)
+ | BerObjectContent::ObjectDescriptor(s)
+ | BerObjectContent::GraphicString(s)
+ | BerObjectContent::VisibleString(s)
+ | BerObjectContent::PrintableString(s)
+ | BerObjectContent::IA5String(s)
+ | BerObjectContent::T61String(s)
+ | BerObjectContent::VideotexString(s)
+ | BerObjectContent::UTF8String(s) => slice(s)(out),
+ BerObjectContent::UniversalString(s) => slice(s)(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
+ match inner {
+ Some(obj) => ber_encode_object_content(&obj.content)(out),
+ None => slice(&[])(out), // XXX encode NOP ?
+ }
+ }
+ BerObjectContent::Tagged(_class, _tag, inner) => {
+ // directly encode inner object
+ // XXX wrong, we should wrap it!
+ ber_encode_object(inner)(out)
+ }
+ BerObjectContent::Unknown(any) => slice(any.data)(out),
+ }
+}
+
+/// Encode header and object content as BER, without any validation
+///
+/// Note that the encoding will not check *any* `field of the header (including length)
+/// This can be used to craft invalid objects.
+///
+/// *This function is only available if the `serialize` feature is enabled.*
+#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
+pub fn ber_encode_object_raw<'a, 'b: 'a, 'c: 'a, W: Write + Default + AsRef<[u8]> + 'a>(
+ hdr: &'b Header,
+ content: &'c BerObjectContent,
+) -> impl SerializeFn<W> + 'a {
+ tuple((ber_encode_header(hdr), ber_encode_object_content(content)))
+}
+
+/// Encode object as BER
+///
+/// Note that the encoding will not check that the values of the `BerObject` fields are correct.
+/// The length is automatically calculated, and the field is ignored.
+///
+/// `Tagged` objects will be encoded as EXPLICIT.
+///
+/// *This function is only available if the `serialize` feature is enabled.*
+#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
+pub fn ber_encode_object<'a, 'b: 'a, W: Write + Default + AsRef<[u8]> + 'a>(
+ obj: &'b BerObject,
+) -> impl SerializeFn<W> + 'a {
+ move |out| {
+ // XXX should we make an exception for tagged values here ?
+ let v = gen_simple(ber_encode_object_content(&obj.content), W::default())?;
+ let len = v.as_ref().len();
+ let hdr = obj.header.clone().with_length(len.into());
+ let v_hdr = gen_simple(ber_encode_header(&hdr), W::default())?;
+ tuple((slice(v_hdr), slice(v)))(out)
+ }
+}
+
+impl<'a> BerObject<'a> {
+ /// Attempt to encode object as BER
+ ///
+ /// Note that the encoding will not check that the values of the `BerObject` fields are correct.
+ /// The length is automatically calculated, and the field is ignored.
+ ///
+ /// `Tagged` objects will be encoded as EXPLICIT.
+ ///
+ /// *This function is only available if the `serialize` feature is enabled.*
+ #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
+ pub fn to_vec(&self) -> Result<Vec<u8>, GenError> {
+ gen_simple(ber_encode_object(self), Vec::new())
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use crate::error::BerResult;
+ use cookie_factory::gen_simple;
+ use hex_literal::hex;
+
+ macro_rules! encode_and_parse {
+ ($obj:ident, $encode:ident, $parse:ident) => {{
+ let v = gen_simple($encode(&$obj), Vec::new()).expect("could not encode");
+ let (_, obj2) = $parse(&v).expect("could not re-parse");
+ assert_eq!($obj, obj2);
+ v
+ }};
+ }
+
+ #[test]
+ fn test_encode_length() {
+ let l = 38;
+ let v = gen_simple(encode_length(l), Vec::new()).expect("could not serialize");
+ assert_eq!(&v[..], &[38]);
+ let l = 201;
+ let v = gen_simple(encode_length(l), Vec::new()).expect("could not serialize");
+ assert_eq!(&v[..], &[129, 201]);
+ let l = 0x1234_5678;
+ let v = gen_simple(encode_length(l), Vec::new()).expect("could not serialize");
+ assert_eq!(&v[..], &[132, 0x12, 0x34, 0x56, 0x78]);
+ }
+
+ #[test]
+ fn test_encode_header() {
+ // simple header (integer)
+ let bytes = hex!("02 03 01 00 01");
+ let (_, hdr) = ber_read_element_header(&bytes).expect("could not parse");
+ let v = encode_and_parse!(hdr, ber_encode_header, ber_read_element_header);
+ assert_eq!(&v[..], &bytes[..2]);
+ }
+
+ #[test]
+ fn test_encode_bool() {
+ let b_true = BerObject::from_obj(BerObjectContent::Boolean(true));
+ let b_false = BerObject::from_obj(BerObjectContent::Boolean(false));
+ encode_and_parse!(b_true, ber_encode_object, parse_ber_bool);
+ encode_and_parse!(b_false, ber_encode_object, parse_ber_bool);
+ }
+
+ #[test]
+ fn test_encode_integer() {
+ let i = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
+ encode_and_parse!(i, ber_encode_object, parse_ber_integer);
+ }
+
+ #[test]
+ fn test_encode_bitstring() {
+ let bytes = hex!("03 04 06 6e 5d e0");
+ let b = BerObject::from_obj(BerObjectContent::BitString(
+ 6,
+ BitStringObject { data: &bytes[3..] },
+ ));
+ let v = encode_and_parse!(b, ber_encode_object, parse_ber_bitstring);
+ assert_eq!(&v[..], bytes)
+ }
+
+ #[test]
+ fn test_encode_octetstring() {
+ let i = BerObject::from_obj(BerObjectContent::OctetString(b"AAAAA"));
+ let v = encode_and_parse!(i, ber_encode_object, parse_ber_octetstring);
+ assert_eq!(&v[..], hex!("04 05 41 41 41 41 41"))
+ }
+
+ #[test]
+ fn test_encode_enum() {
+ let i = BerObject::from_obj(BerObjectContent::Enum(2));
+ let v = encode_and_parse!(i, ber_encode_object, parse_ber_enum);
+ assert_eq!(&v[..], hex!("0a 01 02"))
+ }
+
+ #[test]
+ fn test_encode_null() {
+ let i = BerObject::from_obj(BerObjectContent::Null);
+ encode_and_parse!(i, ber_encode_object, parse_ber_null);
+ }
+
+ #[test]
+ fn test_encode_oid() {
+ let bytes = hex!("06 09 2A 86 48 86 F7 0D 01 01 05");
+ let obj = BerObject::from_obj(BerObjectContent::OID(
+ Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap(),
+ ));
+ let v = encode_and_parse!(obj, ber_encode_object, parse_ber_oid);
+ assert_eq!(&v[..], bytes);
+ }
+
+ #[test]
+ fn test_encode_relative_oid() {
+ let bytes = hex!("0d 04 c2 7b 03 02");
+ let obj = BerObject::from_obj(BerObjectContent::RelativeOID(
+ Oid::from_relative(&[8571, 3, 2]).unwrap(),
+ ));
+ let v = encode_and_parse!(obj, ber_encode_object, parse_ber_relative_oid);
+ assert_eq!(&v[..], bytes);
+ }
+
+ #[test]
+ fn test_encode_sequence() {
+ let bytes = hex!("30 0a 02 03 01 00 01 02 03 01 00 00");
+ let obj = BerObject::from_seq(vec![
+ BerObject::from_int_slice(b"\x01\x00\x01"),
+ BerObject::from_int_slice(b"\x01\x00\x00"),
+ ]);
+ let v = encode_and_parse!(obj, ber_encode_object, parse_ber_sequence);
+ assert_eq!(&v[..], bytes);
+ }
+
+ #[test]
+ fn test_encode_set() {
+ let bytes = hex!("31 0a 02 03 01 00 01 02 03 01 00 00");
+ let obj = BerObject::from_set(vec![
+ BerObject::from_int_slice(b"\x01\x00\x01"),
+ BerObject::from_int_slice(b"\x01\x00\x00"),
+ ]);
+ let v = encode_and_parse!(obj, ber_encode_object, parse_ber_set);
+ assert_eq!(&v[..], bytes);
+ }
+
+ #[test]
+ fn test_encode_tagged_explicit() {
+ fn local_parse(i: &[u8]) -> BerResult {
+ parse_ber_explicit_optional(i, Tag(0), parse_ber_integer)
+ }
+ let bytes = hex!("a0 03 02 01 02");
+ let obj = BerObject::from_int_slice(b"\x02");
+ let v = gen_simple(
+ ber_encode_tagged_explicit(Tag(0), Class::ContextSpecific, &obj),
+ Vec::new(),
+ )
+ .expect("could not encode");
+ let (_, obj2) = local_parse(&v).expect("could not re-parse");
+ let obj2 = obj2
+ .as_optional()
+ .expect("tagged object not found")
+ .expect("optional object empty");
+ let (_class, tag, inner) = obj2.as_tagged().expect("not a tagged object");
+ assert_eq!(tag, Tag(0));
+ assert_eq!(&obj, inner);
+ assert_eq!(&v[..], bytes);
+ }
+
+ #[test]
+ fn test_encode_tagged_implicit() {
+ fn der_read_integer_content<'a>(
+ i: &'a [u8],
+ hdr: &Header,
+ depth: usize,
+ ) -> BerResult<'a, BerObjectContent<'a>> {
+ ber_read_element_content_as(i, Tag::Integer, hdr.length(), false, depth)
+ }
+ fn local_parse(i: &[u8]) -> BerResult<BerObject> {
+ parse_ber_implicit(i, Tag(3), der_read_integer_content)
+ }
+ let obj = BerObject::from_int_slice(b"\x02");
+ let v = gen_simple(
+ ber_encode_tagged_implicit(Tag(3), Class::ContextSpecific, &obj),
+ Vec::new(),
+ )
+ .expect("could not encode");
+ let (_, obj2) = local_parse(&v).expect("could not re-parse");
+ assert_eq!(obj2.header.tag(), Tag(3));
+ assert_eq!(&obj.content, &obj2.content);
+ let bytes = hex!("83 01 02");
+ assert_eq!(&v[..], bytes);
+ }
+ #[test]
+ fn test_encode_tagged_application() {
+ fn local_parse(i: &[u8]) -> BerResult {
+ parse_ber_explicit_optional(i, Tag(2), parse_ber_integer)
+ }
+ let obj = BerObject::from_int_slice(b"\x02");
+ let v = gen_simple(
+ ber_encode_tagged_explicit(Tag(2), Class::Application, &obj),
+ Vec::new(),
+ )
+ .expect("could not encode");
+ let (_, obj2) = local_parse(&v).expect("could not re-parse");
+ let obj2 = obj2
+ .as_optional()
+ .expect("tagged object not found")
+ .expect("optional object empty");
+ let (_class, tag, inner) = obj2.as_tagged().expect("not a tagged object");
+ assert_eq!(tag, Tag(2));
+ assert_eq!(&obj, inner);
+ let bytes = hex!("62 03 02 01 02");
+ assert_eq!(&v[..], bytes);
+ }
+}
diff --git a/rust/vendor/der-parser/src/ber/tagged.rs b/rust/vendor/der-parser/src/ber/tagged.rs
new file mode 100644
index 0000000..e4614c5
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/tagged.rs
@@ -0,0 +1,260 @@
+use crate::ber::*;
+use crate::error::*;
+use asn1_rs::Tag;
+use nom::error::ParseError;
+use nom::{Err, IResult};
+
+/// Read a TAGGED EXPLICIT value (combinator)
+///
+/// The built object will use the outer header (and tag), and contains a `Tagged` object
+/// with class, value and content.
+///
+/// For a generic version (different output and error types), see
+/// [parse_ber_tagged_explicit_g](fn.parse_ber_tagged_explicit_g.html).
+///
+/// The following parses `[2] EXPLICIT INTEGER`:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map_res;
+/// #
+/// fn parse_int_explicit(i:&[u8]) -> BerResult<u32> {
+/// map_res(
+/// parse_ber_tagged_explicit(2, parse_ber_integer),
+/// |x: BerObject| x.as_tagged()?.2.as_u32()
+/// )(i)
+/// }
+///
+/// # 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);
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+pub fn parse_ber_tagged_explicit<'a, T, F>(tag: T, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult<BerObject>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_ber_tagged_explicit_g(tag, move |content, hdr| {
+ let (rem, obj) = f(content)?;
+ let class = hdr.class();
+ let obj2 = BerObject::from_header_and_content(
+ hdr,
+ BerObjectContent::Tagged(class, tag, Box::new(obj)),
+ );
+ Ok((rem, obj2))
+ })
+}
+
+/// Read a TAGGED EXPLICIT value (generic version)
+///
+/// The following parses `[2] EXPLICIT INTEGER`:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_int_explicit(i:&[u8]) -> BerResult<u32> {
+/// parse_ber_tagged_explicit_g(2, move |content, hdr| {
+/// let (rem, obj) = parse_ber_integer(content)?;
+/// let value = obj.as_u32()?;
+/// Ok((rem, value))
+/// })(i)
+/// }
+///
+/// # 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);
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+pub fn parse_ber_tagged_explicit_g<'a, T, Output, F, E>(
+ tag: T,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Output, E>
+where
+ F: Fn(&'a [u8], Header<'a>) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_ber_container(move |i, hdr| {
+ if hdr.class() == Class::Universal {
+ return Err(Err::Error(
+ BerError::unexpected_class(None, hdr.class()).into(),
+ ));
+ }
+ hdr.assert_tag(tag).map_err(|e| Err::Error(e.into()))?;
+ // X.690 8.14.2: if implicit tagging was not used, the encoding shall be constructed
+ hdr.assert_constructed().map_err(|e| Err::Error(e.into()))?;
+
+ f(i, hdr)
+ // trailing bytes are ignored
+ })
+}
+
+/// Read a TAGGED IMPLICIT value (combinator)
+///
+/// Parse a TAGGED IMPLICIT value, given the expected tag, and the content parsing function.
+///
+/// The built object will use the original header (and tag), so the content may not match the tag
+/// value.
+///
+/// For a generic version (different output and error types), see
+/// [parse_ber_tagged_implicit_g](fn.parse_ber_tagged_implicit_g.html).
+///
+/// # Examples
+///
+/// The following parses `[2] IMPLICIT INTEGER` into a `BerObject`:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> BerResult<BerObject> {
+/// parse_ber_tagged_implicit(
+/// 2,
+/// parse_ber_content(Tag::Integer),
+/// )(i)
+/// }
+///
+/// # let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01];
+/// let res = parse_int_implicit(bytes);
+/// # match res {
+/// # Ok((rem, content)) => {
+/// # assert!(rem.is_empty());
+/// # assert_eq!(content.as_u32(), Ok(0x10001));
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+///
+/// The following parses `[2] IMPLICIT INTEGER` into an `u32`, raising an error if the integer is
+/// too large:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map_res;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> BerResult<u32> {
+/// map_res(
+/// parse_ber_tagged_implicit(
+/// 2,
+/// parse_ber_content(Tag::Integer),
+/// ),
+/// |x: BerObject| x.as_u32()
+/// )(i)
+/// }
+///
+/// # 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)
+/// # }
+/// ```
+pub fn parse_ber_tagged_implicit<'a, T, F>(tag: T, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, BerObjectContent<'a>>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_ber_tagged_implicit_g(tag, move |i, hdr, depth| {
+ let (rem, content) = f(i, &hdr, depth)?;
+ // trailing bytes are ignored
+ let obj = BerObject::from_header_and_content(hdr, content);
+ Ok((rem, obj))
+ })
+}
+
+/// Read a TAGGED IMPLICIT value (generic version)
+///
+/// Parse a TAGGED IMPLICIT value, given the expected tag, and the content parsing function.
+///
+/// # Examples
+///
+/// The following parses `[1] IMPLICIT OCTETSTRING`, returning a `BerObject`:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_implicit_0_octetstring(i:&[u8]) -> BerResult<BerObjectContent> {
+/// parse_ber_tagged_implicit_g(
+/// 2,
+/// parse_ber_content2(Tag::OctetString)
+/// )(i)
+/// }
+///
+/// # let bytes = &[0x02, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f];
+/// let res = parse_implicit_0_octetstring(bytes);
+/// # match res {
+/// # Ok((rem, val)) => {
+/// # assert!(rem.is_empty());
+/// # let s = val.as_slice().unwrap();
+/// # assert_eq!(s, b"hello");
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+///
+/// The following parses `[2] IMPLICIT INTEGER` into an `u32`, raising an error if the integer is
+/// too large:
+///
+/// ```rust
+/// # use der_parser::ber::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> BerResult<u32> {
+/// parse_ber_tagged_implicit_g(
+/// 2,
+/// |content, hdr, depth| {
+/// let (rem, obj_content) = parse_ber_content(Tag::Integer)(content, &hdr, depth)?;
+/// let value = obj_content.as_u32()?;
+/// Ok((rem, value))
+/// }
+/// )(i)
+/// }
+///
+/// # 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)
+/// # }
+/// ```
+pub fn parse_ber_tagged_implicit_g<'a, T, Output, F, E>(
+ tag: T,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&[u8], Output, E>
+where
+ F: Fn(&'a [u8], Header<'a>, usize) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_ber_container(move |i, hdr| {
+ hdr.assert_tag(tag).map_err(|e| Err::Error(e.into()))?;
+ // XXX MAX_RECURSION should not be used, it resets the depth counter
+ f(i, hdr, MAX_RECURSION)
+ // trailing bytes are ignored
+ })
+}
diff --git a/rust/vendor/der-parser/src/ber/visit.rs b/rust/vendor/der-parser/src/ber/visit.rs
new file mode 100644
index 0000000..a2d5669
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/visit.rs
@@ -0,0 +1,192 @@
+use super::{BerObject, BerObjectContent, BitStringObject};
+use asn1_rs::{ASN1DateTime, Any, Class, Oid, Tag};
+
+/// BER object tree traversal to walk a shared borrow of a BER object
+///
+/// When implementing your own visitor, define your own `visit_ber_xxx` methods.
+///
+/// Note that `visit_ber` is called for every object, so if you implement multiple visitor methods they
+/// will be called multiple times for the same object. Generally, if `visit_ber` is implemented, then other
+/// methods are not needed.
+///
+/// For example, on a `Sequence` item, `visit_ber` is called first, then `visit_ber_sequence`, and then
+/// `visit_ber` for every sequence object (recursively).
+///
+/// Entry point: use the [`Visit::run`] or [`Visit::run_at`] methods.
+///
+/// Visitor functions
+#[allow(unused_variables)]
+pub trait Visit<'a> {
+ /// Called for every BER object
+ fn visit_ber(&mut self, ber: &'_ BerObject<'a>, depth: usize) {}
+
+ /// Called for BER bitstring objects
+ fn visit_ber_bitstring(&mut self, ignored: u8, data: &'a BitStringObject, depth: usize) {}
+
+ /// Called for BER bmpstring objects
+ fn visit_ber_bmpstring(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER boolean objects
+ fn visit_ber_boolean(&mut self, b: bool, depth: usize) {}
+
+ /// Called for BER end-of-content objects
+ fn visit_ber_endofcontent(&mut self, depth: usize) {}
+
+ /// Called for BER enum objects
+ fn visit_ber_enum(&mut self, e: u64, depth: usize) {}
+
+ /// Called for BER generalstring objects
+ fn visit_ber_generalstring(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER generalizedtime objects
+ fn visit_ber_generalizedtime(&mut self, t: &'a ASN1DateTime, depth: usize) {}
+
+ /// Called for BER graphicstring objects
+ fn visit_ber_graphicstring(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER ia5string objects
+ fn visit_ber_ia5string(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER integer objects
+ fn visit_ber_integer(&mut self, raw_bytes: &'a [u8], depth: usize) {}
+
+ /// Called for BER null objects
+ fn visit_ber_null(&mut self, depth: usize) {}
+
+ /// Called for BER numericstring objects
+ fn visit_ber_numericstring(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER OID objects
+ fn visit_ber_oid(&mut self, oid: &'a Oid, depth: usize) {}
+
+ /// Called for BER object descriptor objects
+ fn visit_ber_objectdescriptor(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER octetstring objects
+ fn visit_ber_octetstring(&mut self, b: &'a [u8], depth: usize) {}
+
+ /// Called for BER optional objects
+ fn visit_ber_optional(&mut self, obj: Option<&'a BerObject<'a>>, depth: usize) {}
+
+ /// Called for BER printablestring objects
+ fn visit_ber_printablestring(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER relative OID objects
+ fn visit_ber_relative_oid(&mut self, oid: &'a Oid, depth: usize) {}
+
+ /// Called for BER sequence objects
+ fn visit_ber_sequence(&mut self, ber: &'_ [BerObject<'a>], depth: usize) {}
+
+ /// Called for BER set objects
+ fn visit_ber_set(&mut self, ber: &'_ [BerObject<'a>], depth: usize) {}
+
+ /// Called for BER teletexstring objects
+ fn visit_ber_teletexstring(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER tagged objects
+ fn visit_ber_tagged(&mut self, class: Class, tag: Tag, obj: &'_ BerObject<'a>, depth: usize) {}
+
+ /// Called for BER generalizedtime objects
+ fn visit_ber_utctime(&mut self, t: &'a ASN1DateTime, depth: usize) {}
+
+ /// Called for BER utf8string objects
+ fn visit_ber_utf8string(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER universalstring objects
+ fn visit_ber_universalstring(&mut self, raw_bytes: &'a [u8], depth: usize) {}
+
+ /// Called for BER videotexstring objects
+ fn visit_ber_videotextstring(&mut self, raw_bytes: &'a str, depth: usize) {}
+
+ /// Called for BER visiblestring objects
+ fn visit_ber_visiblestring(&mut self, raw_bytes: &'a str, depth: usize) {}
+
+ /// Called for BER unknown objects
+ fn visit_ber_unknown(&mut self, ber: &'_ Any<'a>, depth: usize) {}
+
+ /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
+ ///
+ /// Usually, this method should not be redefined (unless implementing a custom traversal)
+ fn run(&mut self, ber: &'a BerObject<'a>) {
+ visit_ber_bfs(self, ber, 0)
+ }
+
+ /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
+ ///
+ /// Start at specified depth.
+ ///
+ /// Usually, this method should not be redefined (unless implementing a custom traversal)
+ fn run_at(&mut self, ber: &'a BerObject<'a>, depth: usize) {
+ visit_ber_bfs(self, ber, depth)
+ }
+}
+
+fn visit_ber_bfs<'a, V>(v: &mut V, ber: &'a BerObject<'a>, depth: usize)
+where
+ V: Visit<'a> + ?Sized,
+{
+ v.visit_ber(ber, depth);
+
+ match ber.content {
+ BerObjectContent::BitString(ignored, ref data) => {
+ v.visit_ber_bitstring(ignored, data, depth);
+ }
+ BerObjectContent::BmpString(s) => v.visit_ber_bmpstring(s, depth),
+ BerObjectContent::Boolean(b) => v.visit_ber_boolean(b, depth),
+ BerObjectContent::EndOfContent => v.visit_ber_endofcontent(depth),
+ BerObjectContent::Enum(val) => v.visit_ber_enum(val, depth),
+ BerObjectContent::GeneralString(s) => v.visit_ber_generalstring(s, depth),
+ BerObjectContent::GeneralizedTime(ref t) => v.visit_ber_generalizedtime(t, depth),
+ BerObjectContent::GraphicString(s) => v.visit_ber_graphicstring(s, depth),
+ BerObjectContent::IA5String(s) => v.visit_ber_ia5string(s, depth),
+ BerObjectContent::Integer(s) => v.visit_ber_integer(s, depth),
+ BerObjectContent::Null => v.visit_ber_null(depth),
+ BerObjectContent::NumericString(s) => v.visit_ber_numericstring(s, depth),
+ BerObjectContent::OID(ref oid) => v.visit_ber_oid(oid, depth),
+ BerObjectContent::ObjectDescriptor(s) => v.visit_ber_objectdescriptor(s, depth),
+ BerObjectContent::OctetString(b) => v.visit_ber_octetstring(b, depth),
+ BerObjectContent::Optional(ref obj) => {
+ let opt = obj.as_ref().map(|b| b.as_ref());
+ v.visit_ber_optional(opt, depth)
+ }
+ BerObjectContent::PrintableString(s) => v.visit_ber_printablestring(s, depth),
+ BerObjectContent::RelativeOID(ref oid) => v.visit_ber_relative_oid(oid, depth),
+ BerObjectContent::Sequence(ref l) => {
+ v.visit_ber_sequence(l, depth);
+ for item in l.iter() {
+ visit_ber_bfs(v, item, depth + 1);
+ }
+ }
+ BerObjectContent::Set(ref l) => {
+ v.visit_ber_set(l, depth);
+ for item in l.iter() {
+ visit_ber_bfs(v, item, depth + 1);
+ }
+ }
+ BerObjectContent::T61String(s) => v.visit_ber_teletexstring(s, depth),
+ BerObjectContent::Tagged(class, tag, ref obj) => {
+ v.visit_ber_tagged(class, tag, obj.as_ref(), depth)
+ }
+ BerObjectContent::UTCTime(ref t) => v.visit_ber_utctime(t, depth),
+ BerObjectContent::UTF8String(s) => v.visit_ber_utf8string(s, depth),
+ BerObjectContent::UniversalString(b) => v.visit_ber_universalstring(b, depth),
+ BerObjectContent::Unknown(ref inner) => v.visit_ber_unknown(inner, depth),
+ BerObjectContent::VideotexString(s) => v.visit_ber_videotextstring(s, depth),
+ BerObjectContent::VisibleString(s) => v.visit_ber_visiblestring(s, depth),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::Visit;
+ use crate::ber::BerObject;
+
+ #[derive(Debug)]
+ struct BerObjectVisitor {}
+
+ impl<'a> Visit<'a> for BerObjectVisitor {
+ fn visit_ber(&mut self, ber: &'_ BerObject<'a>, depth: usize) {
+ eprintln!("Depth {}: Object with tag {}", depth, ber.tag());
+ }
+ }
+}
diff --git a/rust/vendor/der-parser/src/ber/visit_mut.rs b/rust/vendor/der-parser/src/ber/visit_mut.rs
new file mode 100644
index 0000000..1ff86be
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/visit_mut.rs
@@ -0,0 +1,206 @@
+use super::{BerObject, BerObjectContent, BitStringObject};
+use alloc::vec::Vec;
+use asn1_rs::{ASN1DateTime, Any, Class, Oid, Tag};
+
+/// BER object tree traversal to walk a shared borrow of a BER object
+///
+/// When implementing your own visitor, define your own `visit_ber_xxx` methods.
+///
+/// Note that `visit_ber` is called for every object, so if you implement multiple visitor methods they
+/// will be called multiple times for the same object. Generally, if `visit_ber` is implemented, then other
+/// methods are not needed.
+///
+/// For example, on a `Sequence` item, `visit_ber` is called first, then `visit_ber_sequence`, and then
+/// `visit_ber` for every sequence object (recursively).
+///
+/// Entry point: use the [`VisitMut::run`] or [`VisitMut::run_at`] methods.
+///
+/// Visitor functions
+#[allow(unused_variables)]
+pub trait VisitMut<'a> {
+ /// Called for every BER object
+ fn visit_ber_mut(&mut self, ber: &'_ mut BerObject<'a>, depth: usize) {}
+
+ /// Called for BER bitstring objects
+ fn visit_ber_bitstring_mut(
+ &mut self,
+ ignored: &mut u8,
+ data: &'a mut BitStringObject,
+ depth: usize,
+ ) {
+ }
+
+ /// Called for BER bmpstring objects
+ fn visit_ber_bmpstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER boolean objects
+ fn visit_ber_boolean_mut(&mut self, b: &'a mut bool, depth: usize) {}
+
+ /// Called for BER end-of-content objects
+ fn visit_ber_endofcontent_mut(&mut self, depth: usize) {}
+
+ /// Called for BER enum objects
+ fn visit_ber_enum_mut(&mut self, e: &'a mut u64, depth: usize) {}
+
+ /// Called for BER generalstring objects
+ fn visit_ber_generalstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER generalizedtime objects
+ fn visit_ber_generalizedtime_mut(&mut self, t: &'a ASN1DateTime, depth: usize) {}
+
+ /// Called for BER graphicstring objects
+ fn visit_ber_graphicstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER ia5string objects
+ fn visit_ber_ia5string_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER integer objects
+ fn visit_ber_integer_mut(&mut self, raw_bytes: &'a mut &'_ [u8], depth: usize) {}
+
+ /// Called for BER null objects
+ fn visit_ber_null_mut(&mut self, depth: usize) {}
+
+ /// Called for BER numericstring objects
+ fn visit_ber_numericstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER OID objects
+ fn visit_ber_oid_mut(&mut self, oid: &'a mut Oid, depth: usize) {}
+
+ /// Called for BER object descriptor objects
+ fn visit_ber_objectdescriptor_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER octetstring objects
+ fn visit_ber_octetstring_mut(&mut self, b: &'a [u8], depth: usize) {}
+
+ /// Called for BER optional objects
+ fn visit_ber_optional_mut(&mut self, obj: Option<&'a mut BerObject<'a>>, depth: usize) {}
+
+ /// Called for BER printablestring objects
+ fn visit_ber_printablestring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER relative OID objects
+ fn visit_ber_relative_oid_mut(&mut self, oid: &'a mut Oid, depth: usize) {}
+
+ /// Called for BER sequence objects
+ fn visit_ber_sequence_mut(&mut self, l: &'_ mut Vec<BerObject<'a>>, depth: usize) {}
+
+ /// Called for BER set objects
+ fn visit_ber_set_mut(&mut self, ber: &'_ mut Vec<BerObject<'a>>, depth: usize) {}
+
+ /// Called for BER teletexstring objects
+ fn visit_ber_teletexstring_mut(&mut self, s: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER tagged objects
+ fn visit_ber_tagged_mut(
+ &mut self,
+ class: &'a mut Class,
+ tag: &'a mut Tag,
+ obj: &'a mut BerObject<'a>,
+ depth: usize,
+ ) {
+ }
+
+ /// Called for BER generalizedtime objects
+ fn visit_ber_utctime_mut(&mut self, t: &'a ASN1DateTime, depth: usize) {}
+
+ /// Called for BER utf8string objects
+ fn visit_ber_utf8string_mut(&mut self, s: &'a str, depth: usize) {}
+
+ /// Called for BER universalstring objects
+ fn visit_ber_universalstring_mut(&mut self, raw_bytes: &'a mut &'_ [u8], depth: usize) {}
+
+ /// Called for BER videotexstring objects
+ fn visit_ber_videotextstring_mut(&mut self, raw_bytes: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER visiblestring objects
+ fn visit_ber_visiblestring_mut(&mut self, raw_bytes: &'a mut &'_ str, depth: usize) {}
+
+ /// Called for BER unknown objects
+ fn visit_ber_unknown_mut(&mut self, ber: &'_ mut Any<'a>, depth: usize) {}
+
+ /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
+ ///
+ /// Usually, this method should not be redefined (unless implementing a custom traversal)
+ fn run(&mut self, ber: &'a mut BerObject<'a>) {
+ visit_ber_bfs_mut(self, ber, 0)
+ }
+
+ /// Perform a BFS traversal of the BER object, calling the visitor functions during he traversal
+ ///
+ /// Start at specified depth.
+ ///
+ /// Usually, this method should not be redefined (unless implementing a custom traversal)
+ fn run_at(&mut self, ber: &'a mut BerObject<'a>, depth: usize) {
+ visit_ber_bfs_mut(self, ber, depth)
+ }
+}
+
+fn visit_ber_bfs_mut<'a, V>(v: &mut V, ber: &'a mut BerObject<'a>, depth: usize)
+where
+ V: VisitMut<'a> + ?Sized,
+{
+ v.visit_ber_mut(ber, depth);
+
+ match ber.content {
+ BerObjectContent::BitString(ref mut ignored, ref mut data) => {
+ v.visit_ber_bitstring_mut(ignored, data, depth);
+ }
+ BerObjectContent::BmpString(ref mut s) => v.visit_ber_bmpstring_mut(s, depth),
+ BerObjectContent::Boolean(ref mut b) => v.visit_ber_boolean_mut(b, depth),
+ BerObjectContent::EndOfContent => v.visit_ber_endofcontent_mut(depth),
+ BerObjectContent::Enum(ref mut val) => v.visit_ber_enum_mut(val, depth),
+ BerObjectContent::GeneralString(ref mut s) => v.visit_ber_generalstring_mut(s, depth),
+ BerObjectContent::GeneralizedTime(ref t) => v.visit_ber_generalizedtime_mut(t, depth),
+ BerObjectContent::GraphicString(ref mut s) => v.visit_ber_graphicstring_mut(s, depth),
+ BerObjectContent::IA5String(ref mut s) => v.visit_ber_ia5string_mut(s, depth),
+ BerObjectContent::Integer(ref mut s) => v.visit_ber_integer_mut(s, depth),
+ BerObjectContent::Null => v.visit_ber_null_mut(depth),
+ BerObjectContent::NumericString(ref mut s) => v.visit_ber_numericstring_mut(s, depth),
+ BerObjectContent::OID(ref mut oid) => v.visit_ber_oid_mut(oid, depth),
+ BerObjectContent::ObjectDescriptor(ref mut s) => v.visit_ber_objectdescriptor_mut(s, depth),
+ BerObjectContent::OctetString(ref mut b) => v.visit_ber_octetstring_mut(b, depth),
+ BerObjectContent::Optional(ref mut obj) => {
+ let opt = obj.as_mut().map(|b| b.as_mut());
+ v.visit_ber_optional_mut(opt, depth)
+ }
+ BerObjectContent::PrintableString(ref mut s) => v.visit_ber_printablestring_mut(s, depth),
+ BerObjectContent::RelativeOID(ref mut oid) => v.visit_ber_relative_oid_mut(oid, depth),
+ BerObjectContent::Sequence(ref mut l) => {
+ v.visit_ber_sequence_mut(l, depth);
+ for item in l.iter_mut() {
+ visit_ber_bfs_mut(v, item, depth + 1);
+ }
+ }
+ BerObjectContent::Set(ref mut l) => {
+ v.visit_ber_set_mut(l, depth);
+ for item in l.iter_mut() {
+ visit_ber_bfs_mut(v, item, depth + 1);
+ }
+ }
+ BerObjectContent::T61String(ref mut s) => v.visit_ber_teletexstring_mut(s, depth),
+ BerObjectContent::Tagged(ref mut class, ref mut tag, ref mut obj) => {
+ v.visit_ber_tagged_mut(class, tag, obj.as_mut(), depth)
+ }
+ BerObjectContent::UTCTime(ref t) => v.visit_ber_utctime_mut(t, depth),
+ BerObjectContent::UTF8String(ref mut s) => v.visit_ber_utf8string_mut(s, depth),
+ BerObjectContent::UniversalString(ref mut b) => v.visit_ber_universalstring_mut(b, depth),
+ BerObjectContent::Unknown(ref mut inner) => v.visit_ber_unknown_mut(inner, depth),
+ BerObjectContent::VideotexString(ref mut s) => v.visit_ber_videotextstring_mut(s, depth),
+ BerObjectContent::VisibleString(ref mut s) => v.visit_ber_visiblestring_mut(s, depth),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::VisitMut;
+ use crate::ber::BerObject;
+
+ #[derive(Debug)]
+ struct BerObjectVisitor {}
+
+ impl<'a> VisitMut<'a> for BerObjectVisitor {
+ fn visit_ber_mut(&mut self, ber: &'_ mut BerObject<'a>, depth: usize) {
+ eprintln!("Depth {}: Object with tag {}", depth, ber.tag());
+ }
+ }
+}
diff --git a/rust/vendor/der-parser/src/ber/wrap_any.rs b/rust/vendor/der-parser/src/ber/wrap_any.rs
new file mode 100644
index 0000000..7543cc4
--- /dev/null
+++ b/rust/vendor/der-parser/src/ber/wrap_any.rs
@@ -0,0 +1,213 @@
+use super::{BerObject, BerObjectContent, BitStringObject};
+use crate::ber::{ber_get_object_content, MAX_OBJECT_SIZE};
+use crate::error::{BerError, BerResult};
+use alloc::vec::Vec;
+use asn1_rs::*;
+use nom::Err;
+use rusticata_macros::custom_check;
+
+/// Parse any BER object recursively, specifying the maximum recursion depth and expected tag
+///
+/// Raise an error if the maximum recursion depth was reached.
+pub fn parse_ber_any_with_tag_r(i: &[u8], tag: Tag, max_depth: usize) -> BerResult {
+ custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
+ let (rem, any) = Any::from_ber(i)?;
+ any.header.assert_tag(tag)?;
+ let obj = try_berobject_from_any(any, max_depth)?;
+ Ok((rem, obj))
+}
+
+/// Parse any BER object recursively, specifying the maximum recursion depth
+///
+/// Raise an error if the maximum recursion depth was reached.
+pub fn parse_ber_any_r(i: &[u8], max_depth: usize) -> BerResult {
+ custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
+ let (rem, any) = Any::from_ber(i)?;
+ let obj = try_berobject_from_any(any, max_depth)?;
+ Ok((rem, obj))
+}
+
+/// Parse any BER object (not recursive)
+pub fn parse_ber_any(i: &[u8]) -> BerResult<Any> {
+ Any::from_ber(i)
+}
+
+macro_rules! from_obj {
+ ($header:ident, $content:expr) => {
+ BerObject::from_header_and_content($header, $content)
+ };
+ (STRING $ty:ident, $any:ident, $header:ident) => {
+ from_obj!(STRING $ty, $ty, $any, $header)
+ };
+ // macro variant when enum variant is not the same as char type
+ (STRING $ty:ident, $variant:ident, $any:ident, $header:ident) => {{
+ custom_check!($any.data, $header.constructed(), BerError::Unsupported)?; // XXX valid in BER (8.21)
+ <$ty>::test_valid_charset($any.data)?;
+ let s = core::str::from_utf8($any.data)?;
+ Ok(BerObject::from_header_and_content(
+ $header,
+ BerObjectContent::$variant(s),
+ ))
+ }};
+}
+
+/// Read element content as Universal object, or Unknown
+// TODO implement the function for BerObjectContent (to replace ber_read_element_content_as)
+// note: we cannot implement TryFrom because of the `max_depth` argument
+pub(crate) fn try_read_berobjectcontent_as(
+ i: &[u8],
+ tag: Tag,
+ length: Length,
+ constructed: bool,
+ max_depth: usize,
+) -> BerResult<BerObjectContent> {
+ if let Length::Definite(l) = length {
+ custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
+ if i.len() < l {
+ return Err(Err::Incomplete(Needed::new(l)));
+ }
+ }
+ let header = Header::new(Class::Universal, constructed, tag, length);
+ let (rem, i) = ber_get_object_content(i, &header, max_depth)?;
+ let any = Any::new(header, i);
+ let object = try_berobject_from_any(any, max_depth)?;
+ Ok((rem, object.content))
+}
+
+// note: we cannot implement TryFrom because of the `max_depth` argument
+fn try_berobject_from_any(any: Any, max_depth: usize) -> Result<BerObject> {
+ custom_check!(any.data, max_depth == 0, BerError::BerMaxDepth)?;
+ let obj_from = BerObject::from_header_and_content;
+ let header = any.header.clone();
+ if any.class() != Class::Universal {
+ return Ok(obj_from(header, BerObjectContent::Unknown(any)));
+ }
+ match any.tag() {
+ Tag::BitString => {
+ if any.data.is_empty() {
+ return Err(BerError::BerValueError);
+ }
+ custom_check!(any.data, header.constructed(), BerError::Unsupported)?; // XXX valid in BER (8.6.3)
+ let ignored_bits = any.data[0];
+ let data = &any.data[1..];
+ Ok(obj_from(
+ header,
+ BerObjectContent::BitString(ignored_bits, BitStringObject { data }),
+ ))
+ }
+ Tag::BmpString => from_obj!(STRING BmpString, any, header),
+ Tag::Boolean => {
+ let b = any.bool()?;
+ Ok(obj_from(header, BerObjectContent::Boolean(b)))
+ }
+ Tag::EndOfContent => Ok(obj_from(header, BerObjectContent::EndOfContent)),
+ Tag::Enumerated => {
+ let obj = any.enumerated()?;
+ Ok(obj_from(header, BerObjectContent::Enum(obj.0 as u64)))
+ }
+ Tag::GeneralizedTime => {
+ let time = any.generalizedtime()?;
+ Ok(obj_from(header, BerObjectContent::GeneralizedTime(time.0)))
+ }
+ Tag::GeneralString => from_obj!(STRING GeneralString, any, header),
+ Tag::GraphicString => from_obj!(STRING GraphicString, any, header),
+ Tag::Ia5String => from_obj!(STRING Ia5String, IA5String, any, header),
+ Tag::Integer => {
+ let obj = obj_from(header, BerObjectContent::Integer(any.data));
+ Ok(obj)
+ }
+ Tag::Null => Ok(obj_from(header, BerObjectContent::Null)),
+ Tag::NumericString => from_obj!(STRING NumericString, any, header),
+ Tag::ObjectDescriptor => from_obj!(STRING ObjectDescriptor, any, header),
+ Tag::OctetString => Ok(obj_from(header, BerObjectContent::OctetString(any.data))),
+ Tag::Oid => {
+ let oid = any.oid()?;
+ Ok(obj_from(header, BerObjectContent::OID(oid)))
+ }
+ Tag::PrintableString => from_obj!(STRING PrintableString, any, header),
+ Tag::RelativeOid => {
+ let oid = any.relative_oid()?;
+ Ok(obj_from(header, BerObjectContent::RelativeOID(oid)))
+ }
+ Tag::Sequence => {
+ header.assert_constructed()?;
+ let objects: Result<Vec<_>> = SequenceIterator::<Any, BerParser>::new(any.data)
+ .map(|item| {
+ let item = item?;
+ try_berobject_from_any(item, max_depth - 1)
+ })
+ .collect();
+ let objects = objects?;
+ Ok(obj_from(header, BerObjectContent::Sequence(objects)))
+ }
+ Tag::Set => {
+ header.assert_constructed()?;
+ let objects: Result<Vec<_>> = SetIterator::<Any, BerParser>::new(any.data)
+ .map(|item| {
+ let item = item?;
+ try_berobject_from_any(item, max_depth - 1)
+ })
+ .collect();
+ let objects = objects?;
+ Ok(obj_from(header, BerObjectContent::Set(objects)))
+ }
+ Tag::TeletexString => from_obj!(STRING TeletexString, T61String, any, header),
+ Tag::UtcTime => {
+ let time = any.utctime()?;
+ Ok(obj_from(header, BerObjectContent::UTCTime(time.0)))
+ }
+ Tag::UniversalString => {
+ custom_check!(any.data, header.constructed(), BerError::Unsupported)?; // XXX valid in BER (8.21)
+
+ // as detailed in asn1-rs, UniversalString allocates memory since the UCS-4 to UTF-8 conversion requires a memory allocation.
+ // so, the charset is not checked here
+ Ok(obj_from(
+ header,
+ BerObjectContent::UniversalString(any.data),
+ ))
+ }
+ Tag::Utf8String => from_obj!(STRING Utf8String, UTF8String, any, header),
+ Tag::VideotexString => from_obj!(STRING VideotexString, any, header),
+ Tag::VisibleString => from_obj!(STRING VisibleString, any, header),
+ _ => {
+ // Note for: Tag::EmbeddedPdv | Tag::External | Tag::RealType
+ // these types have no mapping in the BerObjectContent enum,
+ // so we use the Unknown type
+ Ok(obj_from(header, BerObjectContent::Unknown(any)))
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::ber::{BerObject, BerObjectContent, MAX_RECURSION};
+ use crate::error::BerError;
+ use hex_literal::hex;
+ use test_case::test_case;
+
+ use super::parse_ber_any_r;
+
+ #[test_case(&hex!("01 01 00") => matches Ok(BerObject{header:_, content:BerObjectContent::Boolean(false)}) ; "val false")]
+ #[test_case(&hex!("01 01 ff") => matches Ok(BerObject{header:_, content:BerObjectContent::Boolean(true)}) ; "val true")]
+ #[test_case(&hex!("01 01 7f") => matches Ok(BerObject{header:_, content:BerObjectContent::Boolean(true)}) ; "true not ff")]
+ #[test_case(&hex!("02 02 00 ff") => matches Ok(BerObject{header:_, content:BerObjectContent::Integer(_)}) ; "u32-255")]
+ #[test_case(&hex!("02 02 01 23") => matches Ok(BerObject{header:_, content:BerObjectContent::Integer(_)}) ; "u32-0x123")]
+ #[test_case(&hex!("02 04 ff ff ff ff") => matches Ok(BerObject{header:_, content:BerObjectContent::Integer(_)}) ; "u32-long-neg")]
+ #[test_case(&hex!("0c 04 31 32 33 34") => matches Ok(BerObject{header:_, content:BerObjectContent::UTF8String("1234")}) ; "utf8: numeric")]
+ #[test_case(&hex!("0d 04 c2 7b 03 02") => matches Ok(BerObject{header:_, content:BerObjectContent::RelativeOID(_)}) ; "relative OID")]
+ #[test_case(&hex!("12 04 31 32 33 34") => matches Ok(BerObject{header:_, content:BerObjectContent::NumericString("1234")}) ; "numeric string")]
+ #[test_case(&hex!("12 04 01 02 03 04") => matches Err(BerError::StringInvalidCharset) ; "numeric string err")]
+ #[test_case(&hex!("13 04 31 32 33 34") => matches Ok(BerObject{header:_, content:BerObjectContent::PrintableString("1234")}) ; "printable string")]
+ #[test_case(&hex!("13 04 01 02 03 04") => matches Err(BerError::StringInvalidCharset) ; "printable string err")]
+ #[test_case(&hex!("16 04 31 32 33 34") => matches Ok(BerObject{header:_, content:BerObjectContent::IA5String("1234")}) ; "ia5: numeric")]
+ #[test_case(&hex!("1a 04 31 32 33 34") => matches Ok(BerObject{header:_, content:BerObjectContent::VisibleString("1234")}) ; "visible: numeric")]
+ #[test_case(&hex!("1e 08 00 55 00 73 00 65 00 72") => matches Ok(BerObject{header:_, content:BerObjectContent::BmpString("\x00U\x00s\x00e\x00r")}) ; "bmp")]
+ #[test_case(&hex!("30 80 04 03 56 78 90 00 00") => matches Ok(BerObject{header:_, content:BerObjectContent::Sequence(_)}) ; "indefinite length")]
+ #[test_case(&hex!("c0 03 01 00 01") => matches Ok(BerObject{header:_, content:BerObjectContent::Unknown(_)}) ; "private")]
+ fn ber_from_any(i: &[u8]) -> Result<BerObject, BerError> {
+ let (rem, res) = parse_ber_any_r(i, MAX_RECURSION)?;
+ assert!(rem.is_empty());
+ // dbg!(&res);
+ Ok(res)
+ }
+}
diff --git a/rust/vendor/der-parser/src/der/mod.rs b/rust/vendor/der-parser/src/der/mod.rs
new file mode 100644
index 0000000..558d25a
--- /dev/null
+++ b/rust/vendor/der-parser/src/der/mod.rs
@@ -0,0 +1,93 @@
+//! Distinguished Encoding Rules (DER) objects and parser
+//!
+//! All functions in this crate use BER parsing functions (see the `ber` module)
+//! internally, adding constraints verification where needed.
+//!
+//! The objects [`BerObject`] and [`DerObject`] are the same (type alias): all BER functions,
+//! combinators and macros can be used, and provide additional tools for DER parsing.
+//! However, DER parsing functions enforce DER constraints in addition of their BER counterparts.
+//!
+//! # DER Objects
+//!
+//! The main object of this crate is [`DerObject`]. It contains a header (ber tag, class, and size)
+//! and content.
+//!
+//! To parse primitive objects (for ex. integers or strings), use the `parse_der_` set of
+//! functions.
+//!
+//! Constructed objects (like sequences, sets or tagged objects) require to use a combinator. This
+//! combinator takes a function or closure as input, and returns a new, specialized parser.
+//! See the [nom](https://github.com/geal/nom) parser combinator library for more details on
+//! combinators.
+//!
+//! # Examples
+//!
+//! Parse two DER integers:
+//!
+//! ```rust
+//! use der_parser::der::parse_der_integer;
+//!
+//! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x02, 0x03, 0x01, 0x00, 0x00,
+//! ];
+//!
+//! let (rem, obj1) = parse_der_integer(&bytes).expect("parsing failed");
+//! let (rem, obj2) = parse_der_integer(&bytes).expect("parsing failed");
+//! ```
+//!
+//! Parse a BER sequence containing one integer and an octetstring:
+//!
+//! ```rust
+//! use der_parser::der::*;
+//!
+//! let bytes = [ 0x30, 0x0a,
+//! 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x04, 0x03, 0x62, 0x61, 0x64,
+//! ];
+//!
+//! let (rem, seq) = parse_der_sequence_defined(|content| {
+//! let (rem, obj1) = parse_der_integer(content)?;
+//! let (rem, obj2) = parse_der_octetstring(rem)?;
+//! Ok((rem, vec![obj1, obj2]))
+//! })(&bytes)
+//! .expect("parsing failed");
+//! ```
+
+use crate::ber::{BerObject, BerObjectContent};
+pub use crate::ber::{Class, Header};
+pub use asn1_rs::Tag;
+
+mod multi;
+mod parser;
+mod tagged;
+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;
+
+/// DER Object class of tag (same as `BerClass`)
+#[deprecated(since = "7.0.0", note = "Use `Class` instead")]
+pub type DerClass = Class;
+
+/// DER tag (same as BER tag)
+#[deprecated(since = "7.0.0", note = "Use `Tag` instead")]
+pub type DerTag = Tag;
+
+/// Representation of a DER-encoded (X.690) object
+///
+/// Note that a DER object is just a BER object, with additional constraints.
+pub type DerObject<'a> = BerObject<'a>;
+
+/// DER object header (identifier and length)
+///
+/// This is the same object as `BerObjectHeader`.
+#[deprecated(since = "7.0.0", note = "Use `Tag` instead")]
+pub type DerObjectHeader<'a> = Header<'a>;
+
+/// BER object content
+///
+/// This is the same object as `BerObjectContent`.
+pub type DerObjectContent<'a> = BerObjectContent<'a>;
diff --git a/rust/vendor/der-parser/src/der/multi.rs b/rust/vendor/der-parser/src/der/multi.rs
new file mode 100644
index 0000000..9b20eb8
--- /dev/null
+++ b/rust/vendor/der-parser/src/der/multi.rs
@@ -0,0 +1,534 @@
+use crate::ber::Length;
+use crate::der::*;
+use crate::error::*;
+use nom::bytes::complete::take;
+use nom::combinator::{all_consuming, complete, cut, map};
+use nom::error::ParseError;
+use nom::multi::many0;
+use nom::{Err, IResult};
+
+/// Parse a SEQUENCE OF object
+///
+/// Given a subparser for a DER type, parse a sequence of identical objects.
+///
+/// ```rust
+/// # use der_parser::der::{parse_der_integer, parse_der_sequence_of, DerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SEQUENCE OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<DerObject> {
+/// parse_der_sequence_of(parse_der_integer)(i)
+/// }
+///
+/// # 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!(parser(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_der_sequence_of<'a, F>(f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult,
+{
+ map(parse_der_sequence_of_v(f), DerObject::from_seq)
+}
+
+/// Parse a SEQUENCE OF object (returning a vec)
+///
+/// Given a subparser for a DER type, parse a sequence of identical objects.
+///
+/// This differs from `parse_der_sequence_of` in the parse function and return type.
+///
+/// ```rust
+/// # use der_parser::der::{parse_der_integer, parse_der_sequence_of_v, DerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SEQUENCE OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<Vec<DerObject>> {
+/// parse_der_sequence_of_v(parse_der_integer)(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x02, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = vec![
+/// # DerObject::from_int_slice(b"\x01\x00\x01"),
+/// # DerObject::from_int_slice(b"\x01\x00\x00"),
+/// # ];
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// # assert_eq!(v, expected);
+/// ```
+pub fn parse_der_sequence_of_v<'a, T, F, E>(
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Vec<T>, E>
+where
+ F: FnMut(&'a [u8]) -> IResult<&'a [u8], T, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ let mut subparser = all_consuming(many0(complete(cut(f))));
+ parse_der_sequence_defined_g(move |data, _| subparser(data))
+}
+
+/// Parse a defined sequence of DER elements (function version)
+///
+/// Given a list of expected parsers, apply them to build a DER sequence and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the sequence: any bytes that are part of the sequence but not
+/// parsed are ignored.
+///
+/// The object header is not available to the parsing function, and the returned type is always a
+/// `DerObject`.
+/// For a generic version, see
+/// [`parse_der_sequence_defined_g`](fn.parse_der_sequence_defined_g.html).
+///
+/// # Examples
+///
+/// Parsing a sequence of identical types (same as `parse_der_sequence_of`):
+///
+/// ```rust
+/// # use der_parser::der::{parse_der_integer, parse_der_sequence_defined, DerObject};
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::complete;
+/// use nom::multi::many1;
+///
+/// fn localparse_seq(i:&[u8]) -> BerResult {
+/// parse_der_sequence_defined(
+/// many1(complete(parse_der_integer))
+/// )(i)
+/// }
+///
+/// # 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)));
+/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed");
+/// ```
+///
+/// Parsing a defined sequence with different types:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map;
+/// use nom::sequence::tuple;
+///
+/// /// Read a DER-encoded object:
+/// /// SEQUENCE {
+/// /// a INTEGER,
+/// /// b OCTETSTRING
+/// /// }
+/// fn localparse_seq(i:&[u8]) -> BerResult {
+/// 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_octetstring)),
+/// |(a, b)| vec![a, b]
+/// )
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = DerObject::from_seq(vec![
+/// # DerObject::from_int_slice(b"\x01\x00\x01"),
+/// # DerObject::from_obj(DerObjectContent::OctetString(b"\x01\x00\x00")),
+/// # ]);
+/// # assert_eq!(localparse_seq(&bytes), Ok((empty, expected)));
+/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_der_sequence_defined<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: FnMut(&'a [u8]) -> BerResult<Vec<DerObject>>,
+{
+ map(
+ parse_der_sequence_defined_g(move |data, _| f(data)),
+ DerObject::from_seq,
+ )
+}
+
+/// Parse a defined SEQUENCE object (generic function)
+///
+/// Given a parser for sequence content, apply it to build a DER sequence and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the sequence: any bytes that are part of the sequence but not
+/// parsed are ignored.
+///
+/// Unlike `parse_der_sequence_defined`, this function allows returning any object or error type,
+/// and also passes the object header to the callback.
+///
+/// # Examples
+///
+/// Parsing a defined sequence with different types:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// # #[derive(Debug, PartialEq)]
+/// pub struct MyObject<'a> {
+/// a: u32,
+/// b: &'a [u8],
+/// }
+///
+/// /// Read a DER-encoded object:
+/// /// SEQUENCE {
+/// /// a INTEGER (0..4294967295),
+/// /// b OCTETSTRING
+/// /// }
+/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> {
+/// parse_der_sequence_defined_g(
+/// |i:&[u8], _| {
+/// let (i, a) = parse_der_u32(i)?;
+/// let (i, obj) = parse_der_octetstring(i)?;
+/// let b = obj.as_slice().unwrap();
+/// Ok((i, MyObject{ a, b }))
+/// }
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = MyObject {
+/// # a: 0x010001,
+/// # b: &[01, 00, 00]
+/// # };
+/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_der_sequence_defined_g<'a, O, F, E>(
+ mut f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
+where
+ F: FnMut(&'a [u8], Header<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_der_container(move |i, hdr| {
+ hdr.assert_tag(Tag::Sequence)
+ .map_err(|e| Err::Error(e.into()))?;
+ f(i, hdr)
+ })
+}
+
+/// Parse a SET OF object
+///
+/// Given a subparser for a DER type, parse a set of identical objects.
+///
+/// ```rust
+/// # use der_parser::der::{parse_der_integer, parse_der_set_of, DerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SET OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<DerObject> {
+/// parse_der_set_of(parse_der_integer)(i)
+/// }
+///
+/// # 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!(parser(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_der_set_of<'a, F>(f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult,
+{
+ map(parse_der_set_of_v(f), DerObject::from_set)
+}
+
+/// Parse a SET OF object (returning a vec)
+///
+/// Given a subparser for a DER type, parse a set of identical objects.
+///
+/// This differs from `parse_der_set_of` in the parse function and return type.
+///
+/// ```rust
+/// # use der_parser::der::{parse_der_integer, parse_der_set_of_v, DerObject};
+/// # use der_parser::error::BerResult;
+/// #
+/// /// Read a SET OF INTEGER
+/// fn parser(i:&[u8]) -> BerResult<Vec<DerObject>> {
+/// parse_der_set_of_v(parse_der_integer)(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x31, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x02, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = vec![
+/// # DerObject::from_int_slice(b"\x01\x00\x01"),
+/// # DerObject::from_int_slice(b"\x01\x00\x00"),
+/// # ];
+/// let (rem, v) = parser(&bytes).expect("parsing failed");
+/// # assert_eq!(v, expected);
+/// ```
+pub fn parse_der_set_of_v<'a, T, F, E>(f: F) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Vec<T>, E>
+where
+ F: FnMut(&'a [u8]) -> IResult<&'a [u8], T, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ let mut subparser = all_consuming(many0(complete(cut(f))));
+ parse_der_set_defined_g(move |data, _| subparser(data))
+}
+
+/// Parse a defined set of DER elements (function version)
+///
+/// Given a list of expected parsers, apply them to build a DER set and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the set: any bytes that are part of the sequence but not
+/// parsed are ignored.
+/// The nom combinator `all_consuming` can be used to ensure all the content is parsed.
+///
+/// The object header is not available to the parsing function, and the returned type is always a
+/// `DerObject`.
+/// For a generic version, see [`parse_der_set_defined_g`](fn.parse_der_set_defined_g.html).
+///
+/// # Examples
+///
+/// Parsing a set of identical types (same as `parse_der_set_of`):
+///
+/// ```rust
+/// # use der_parser::der::{parse_der_integer, parse_der_set_defined, DerObject};
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::complete;
+/// use nom::multi::many1;
+///
+/// fn localparse_seq(i:&[u8]) -> BerResult {
+/// parse_der_set_defined(
+/// many1(complete(parse_der_integer))
+/// )(i)
+/// }
+///
+/// # 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_seq(&bytes), Ok((empty, expected)));
+/// let (rem, v) = localparse_seq(&bytes).expect("parsing failed");
+/// ```
+///
+/// Parsing a defined set with different types:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map;
+/// use nom::sequence::tuple;
+///
+/// /// Read a DER-encoded object:
+/// /// SET {
+/// /// a INTEGER,
+/// /// b OCTETSTRING
+/// /// }
+/// fn localparse_set(i:&[u8]) -> BerResult {
+/// 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_octetstring)),
+/// |(a, b)| vec![a, b]
+/// )
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x31, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = DerObject::from_set(vec![
+/// # DerObject::from_int_slice(b"\x01\x00\x01"),
+/// # DerObject::from_obj(DerObjectContent::OctetString(b"\x01\x00\x00")),
+/// # ]);
+/// # assert_eq!(localparse_set(&bytes), Ok((empty, expected)));
+/// let (rem, v) = localparse_set(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_der_set_defined<'a, F>(mut f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: FnMut(&'a [u8]) -> BerResult<Vec<DerObject>>,
+{
+ map(
+ parse_der_set_defined_g(move |data, _| f(data)),
+ DerObject::from_set,
+ )
+}
+
+/// Parse a defined SET object (generic version)
+///
+/// Given a parser for set content, apply it to build a DER set and
+/// return the remaining bytes and the built object.
+///
+/// The remaining bytes point *after* the set: any bytes that are part of the sequence but not
+/// parsed are ignored.
+/// The nom combinator `all_consuming` can be used to ensure all the content is parsed.
+///
+/// Unlike `parse_der_set_defined`, this function allows returning any object or error type,
+/// and also passes the object header to the callback.
+///
+/// # Examples
+///
+/// Parsing a defined set with different types:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// # #[derive(Debug, PartialEq)]
+/// pub struct MyObject<'a> {
+/// a: u32,
+/// b: &'a [u8],
+/// }
+///
+/// /// Read a DER-encoded object:
+/// /// SET {
+/// /// a INTEGER (0..4294967295),
+/// /// b OCTETSTRING
+/// /// }
+/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> {
+/// parse_der_set_defined_g(
+/// |i:&[u8], _| {
+/// let (i, a) = parse_der_u32(i)?;
+/// let (i, obj) = parse_der_octetstring(i)?;
+/// let b = obj.as_slice().unwrap();
+/// Ok((i, MyObject{ a, b }))
+/// }
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x31, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = MyObject {
+/// # a: 0x010001,
+/// # b: &[01, 00, 00]
+/// # };
+/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_der_set_defined_g<'a, O, F, E>(
+ mut f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
+where
+ F: FnMut(&'a [u8], Header<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_der_container(move |i, hdr| {
+ hdr.assert_tag(Tag::Set).map_err(|e| Err::Error(e.into()))?;
+ f(i, hdr)
+ })
+}
+
+/// Parse a DER object and apply provided function to content
+///
+/// Given a parser for content, read DER object header and apply parser to
+/// return the remaining bytes and the parser result.
+///
+/// The remaining bytes point *after* the content: any bytes that are part of the content but not
+/// parsed are ignored.
+/// The nom combinator `all_consuming` can be used to ensure all the content is parsed.
+///
+/// This function is mostly intended for constructed objects, but can be used for any valid DER
+/// object.
+///
+/// # Examples
+///
+/// Parsing a defined sequence with different types:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::{BerError, BerResult};
+/// #
+/// # #[derive(Debug, PartialEq)]
+/// pub struct MyObject<'a> {
+/// a: u32,
+/// b: &'a [u8],
+/// }
+///
+/// /// Read a DER-encoded object:
+/// /// SEQUENCE {
+/// /// a INTEGER (0..4294967295),
+/// /// b OCTETSTRING
+/// /// }
+/// fn parse_myobject(i: &[u8]) -> BerResult<MyObject> {
+/// parse_der_container(
+/// |i: &[u8], hdr: Header| {
+/// if hdr.tag() != Tag::Sequence {
+/// return Err(nom::Err::Error(BerError::BerTypeError.into()));
+/// }
+/// let (i, a) = parse_der_u32(i)?;
+/// let (i, obj) = parse_der_octetstring(i)?;
+/// let b = obj.as_slice().unwrap();
+/// Ok((i, MyObject{ a, b }))
+/// }
+/// )(i)
+/// }
+///
+/// # let empty = &b""[..];
+/// # let bytes = [ 0x30, 0x0a,
+/// # 0x02, 0x03, 0x01, 0x00, 0x01,
+/// # 0x04, 0x03, 0x01, 0x00, 0x00,
+/// # ];
+/// # let expected = MyObject {
+/// # a: 0x010001,
+/// # b: &[01, 00, 00]
+/// # };
+/// # assert_eq!(parse_myobject(&bytes), Ok((empty, expected)));
+/// let (rem, v) = parse_myobject(&bytes).expect("parsing failed");
+/// ```
+pub fn parse_der_container<'a, O, F, E>(mut f: F) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], O, E>
+where
+ F: FnMut(&'a [u8], Header<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ move |i: &[u8]| {
+ let (i, hdr) = der_read_element_header(i).map_err(nom::Err::convert)?;
+ // X.690 10.1: the definitive form of length encoding shall be used
+ let (i, data) = match hdr.length() {
+ Length::Definite(len) => take(len)(i)?,
+ Length::Indefinite => {
+ return Err(Err::Error(
+ BerError::DerConstraintFailed(DerConstraint::IndefiniteLength).into(),
+ ));
+ }
+ };
+ let (_rest, v) = f(data, hdr)?;
+ Ok((i, v))
+ }
+}
diff --git a/rust/vendor/der-parser/src/der/parser.rs b/rust/vendor/der-parser/src/der/parser.rs
new file mode 100644
index 0000000..273ea62
--- /dev/null
+++ b/rust/vendor/der-parser/src/der/parser.rs
@@ -0,0 +1,632 @@
+use crate::ber::*;
+use crate::der::*;
+use crate::der_constraint_fail_if;
+use crate::error::*;
+use alloc::borrow::ToOwned;
+use asn1_rs::{Any, FromDer, Tag};
+use nom::bytes::streaming::take;
+use nom::number::streaming::be_u8;
+use nom::{Err, Needed};
+use rusticata_macros::custom_check;
+
+/// Parse DER object recursively
+///
+/// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error.
+///
+/// *Note: this is the same as calling `parse_der_recursive` with `MAX_RECURSION`.
+///
+/// ### Example
+///
+/// ```
+/// use der_parser::der::{parse_der, Tag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_der(bytes).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag(), Tag::Integer);
+/// ```
+#[inline]
+pub fn parse_der(i: &[u8]) -> DerResult {
+ parse_der_recursive(i, MAX_RECURSION)
+}
+
+/// Parse DER object recursively, specifying the maximum recursion depth
+///
+/// Return a tuple containing the remaining (unparsed) bytes and the DER Object, or an error.
+///
+/// ### Example
+///
+/// ```
+/// use der_parser::der::{parse_der_recursive, Tag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_der_recursive(bytes, 1).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag(), Tag::Integer);
+/// ```
+pub fn parse_der_recursive(i: &[u8], max_depth: usize) -> DerResult {
+ let (i, hdr) = der_read_element_header(i)?;
+ // safety check: length cannot be more than 2^32 bytes
+ if let Length::Definite(l) = hdr.length() {
+ custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
+ }
+ der_read_element_content_recursive(i, hdr, max_depth)
+}
+
+/// Parse a DER object, expecting a value with specified tag
+///
+/// The object is parsed recursively, with a maximum depth of `MAX_RECURSION`.
+///
+/// ### Example
+///
+/// ```
+/// use der_parser::der::{parse_der_with_tag, Tag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_der_with_tag(bytes, Tag::Integer).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag(), Tag::Integer);
+/// ```
+pub fn parse_der_with_tag<T: Into<Tag>>(i: &[u8], tag: T) -> DerResult {
+ let tag = tag.into();
+ let (i, hdr) = der_read_element_header(i)?;
+ hdr.assert_tag(tag)?;
+ let (i, content) = der_read_element_content_as(
+ i,
+ hdr.tag(),
+ hdr.length(),
+ hdr.is_constructed(),
+ MAX_RECURSION,
+ )?;
+ Ok((i, DerObject::from_header_and_content(hdr, content)))
+}
+
+/// Read end of content marker
+#[inline]
+pub fn parse_der_endofcontent(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::EndOfContent)
+}
+
+/// Read a boolean value
+///
+/// The encoding of a boolean value shall be primitive. The contents octets shall consist of a
+/// single octet.
+///
+/// If the boolean value is FALSE, the octet shall be zero.
+/// If the boolean value is TRUE, the octet shall be one byte, and have all bits set to one (0xff).
+#[inline]
+pub fn parse_der_bool(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Boolean)
+}
+
+/// Read an integer value
+///
+/// The encoding of a boolean value shall be primitive. The contents octets shall consist of one or
+/// more octets.
+///
+/// To access the content, use the [`as_u64`](struct.BerObject.html#method.as_u64),
+/// [`as_u32`](struct.BerObject.html#method.as_u32),
+/// [`as_biguint`](struct.BerObject.html#method.as_biguint) or
+/// [`as_bigint`](struct.BerObject.html#method.as_bigint) methods.
+/// Remember that a BER integer has unlimited size, so these methods return `Result` or `Option`
+/// objects.
+///
+/// # Examples
+///
+/// ```rust
+/// # use der_parser::der::{parse_der_integer, DerObject, DerObjectContent};
+/// let empty = &b""[..];
+/// let bytes = [0x02, 0x03, 0x01, 0x00, 0x01];
+/// let expected = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01"));
+/// assert_eq!(
+/// parse_der_integer(&bytes),
+/// Ok((empty, expected))
+/// );
+/// ```
+#[inline]
+pub fn parse_der_integer(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Integer)
+}
+
+/// Read an bitstring value
+///
+/// To access the content as plain bytes, you will have to
+/// interprete the resulting tuple which will contain in
+/// its first item the number of padding bits left at
+/// the end of the bit string, and in its second item
+/// a `BitStringObject` structure which will, in its sole
+/// structure field called `data`, contain a byte slice
+/// representing the value of the bit string which can
+/// be interpreted as a big-endian value with the padding
+/// bits on the right (as in ASN.1 raw BER or DER encoding).
+///
+/// To access the content as an integer, use the [`as_u64`](struct.BerObject.html#method.as_u64)
+/// or [`as_u32`](struct.BerObject.html#method.as_u32) methods.
+/// Remember that a BER bit string has unlimited size, so these methods return `Result` or `Option`
+/// objects.
+#[inline]
+pub fn parse_der_bitstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::BitString)
+}
+
+/// Read an octetstring value
+#[inline]
+pub fn parse_der_octetstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::OctetString)
+}
+
+/// Read a null value
+#[inline]
+pub fn parse_der_null(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Null)
+}
+
+/// Read an object identifier value
+#[inline]
+pub fn parse_der_oid(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Oid)
+}
+
+/// Read an enumerated value
+#[inline]
+pub fn parse_der_enum(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Enumerated)
+}
+
+/// Read a UTF-8 string value. The encoding is checked.
+#[inline]
+pub fn parse_der_utf8string(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Utf8String)
+}
+
+/// Read a relative object identifier value
+#[inline]
+pub fn parse_der_relative_oid(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::RelativeOid)
+}
+
+/// Parse a sequence of DER elements
+///
+/// Read a sequence of DER objects, without any constraint on the types.
+/// Sequence is parsed recursively, so if constructed elements are found, they are parsed using the
+/// same function.
+///
+/// To read a specific sequence of objects (giving the expected types), use the
+/// [`parse_der_sequence_defined`](macro.parse_der_sequence_defined.html) macro.
+#[inline]
+pub fn parse_der_sequence(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Sequence)
+}
+
+/// Parse a set of DER elements
+///
+/// Read a set of DER objects, without any constraint on the types.
+/// Set is parsed recursively, so if constructed elements are found, they are parsed using the
+/// same function.
+///
+/// To read a specific set of objects (giving the expected types), use the
+/// [`parse_der_set_defined`](macro.parse_der_set_defined.html) macro.
+#[inline]
+pub fn parse_der_set(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Set)
+}
+
+/// Read a numeric string value. The content is verified to
+/// contain only digits and spaces.
+#[inline]
+pub fn parse_der_numericstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::NumericString)
+}
+
+/// Read a printable string value. The content is verified to
+/// contain only the allowed characters.
+#[inline]
+pub fn parse_der_visiblestring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::VisibleString)
+}
+
+#[deprecated(since = "8.2.0", note = "Use `parse_der_visiblestring` instead")]
+#[inline]
+pub fn visiblestring(i: &[u8]) -> DerResult {
+ parse_der_visiblestring(i)
+}
+
+/// Read a printable string value. The content is verified to
+/// contain only the allowed characters.
+#[inline]
+pub fn parse_der_printablestring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::PrintableString)
+}
+
+/// Read a T61 string value
+#[inline]
+pub fn parse_der_t61string(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::T61String)
+}
+
+/// Read a Videotex string value
+#[inline]
+pub fn parse_der_videotexstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::VideotexString)
+}
+
+/// Read an IA5 string value. The content is verified to be ASCII.
+#[inline]
+pub fn parse_der_ia5string(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::Ia5String)
+}
+
+/// Read an UTC time value
+#[inline]
+pub fn parse_der_utctime(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::UtcTime)
+}
+
+/// Read a Generalized time value
+#[inline]
+pub fn parse_der_generalizedtime(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::GeneralizedTime)
+}
+
+/// Read a ObjectDescriptor value
+#[inline]
+pub fn parse_der_objectdescriptor(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::ObjectDescriptor)
+}
+
+/// Read a GraphicString value
+#[inline]
+pub fn parse_der_graphicstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::GraphicString)
+}
+
+/// Read a GeneralString value
+#[inline]
+pub fn parse_der_generalstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::GeneralString)
+}
+
+/// Read a BmpString value
+#[inline]
+pub fn parse_der_bmpstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::BmpString)
+}
+
+/// Read a UniversalString value
+#[inline]
+pub fn parse_der_universalstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, Tag::UniversalString)
+}
+
+/// Parse an optional tagged object, applying function to get content
+///
+/// This function returns a `DerObject`, trying to read content as generic DER objects.
+/// If parsing failed, return an optional object containing `None`.
+///
+/// To support other return or error types, use
+/// [parse_der_tagged_explicit_g](fn.parse_der_tagged_explicit_g.html)
+///
+/// This function will never fail: if parsing content failed, the BER value `Optional(None)` is
+/// returned.
+#[inline]
+pub fn parse_der_explicit_optional<F>(i: &[u8], tag: Tag, f: F) -> DerResult
+where
+ F: Fn(&[u8]) -> DerResult,
+{
+ 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,
+/// often based on the [`parse_der_content`](fn.parse_der_content.html) combinator.
+///
+/// The built object will use the original header (and tag), so the content may not match the tag
+/// value.
+///
+/// For a combinator version, see [parse_der_tagged_implicit](../ber/fn.parse_der_tagged_implicit.html).
+///
+/// For a generic version (different output and error types), see
+/// [parse_der_tagged_implicit_g](../ber/fn.parse_der_tagged_implicit_g.html).
+///
+/// # Examples
+///
+/// The following parses `[3] IMPLICIT INTEGER` into a `DerObject`:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::DerResult;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> DerResult {
+/// parse_der_implicit(
+/// i,
+/// 3,
+/// parse_der_content(Tag::Integer),
+/// )
+/// }
+///
+/// # let bytes = &[0x83, 0x03, 0x01, 0x00, 0x01];
+/// let res = parse_int_implicit(bytes);
+/// # match res {
+/// # Ok((rem, content)) => {
+/// # assert!(rem.is_empty());
+/// # assert_eq!(content.as_u32(), Ok(0x10001));
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+#[inline]
+pub fn parse_der_implicit<'a, T, F>(i: &'a [u8], tag: T, f: F) -> DerResult<'a>
+where
+ F: Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, DerObjectContent<'a>>,
+ T: Into<Tag>,
+{
+ 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> {
+ <i32>::from_der(i)
+}
+
+/// 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> {
+ <i64>::from_der(i)
+}
+
+/// 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> {
+ <u32>::from_der(i)
+}
+
+/// Parse DER object and try to decode it as a 64-bits unsigned integer
+///
+/// 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> {
+ <u64>::from_der(i)
+}
+
+/// Parse DER object and get content as slice
+#[inline]
+pub fn parse_der_slice<T: Into<Tag>>(i: &[u8], tag: T) -> BerResult<&[u8]> {
+ let tag = tag.into();
+ parse_der_container(move |content, hdr| {
+ hdr.assert_tag(tag)?;
+ Ok((&b""[..], content))
+ })(i)
+}
+
+/// Parse the next bytes as the content of a DER object (combinator, header reference)
+///
+/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
+///
+/// Caller is also responsible to check if parsing function consumed the expected number of
+/// bytes (`header.len`).
+///
+/// This function differs from [`parse_der_content2`](fn.parse_der_content2.html) because it passes
+/// the BER object header by reference (required for ex. by `parse_der_implicit`).
+///
+/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
+///
+/// Example: manually parsing header and content
+///
+/// ```
+/// # use der_parser::ber::MAX_RECURSION;
+/// # use der_parser::der::*;
+/// #
+/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (i, header) = der_read_element_header(bytes).expect("parsing failed");
+/// let (rem, content) = parse_der_content(header.tag())(i, &header, MAX_RECURSION)
+/// .expect("parsing failed");
+/// #
+/// # assert_eq!(header.tag(), Tag::Integer);
+/// ```
+pub fn parse_der_content<'a>(
+ tag: Tag,
+) -> impl Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, DerObjectContent<'a>> {
+ move |i: &[u8], hdr: &Header, max_recursion: usize| {
+ der_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion)
+ }
+}
+
+/// Parse the next bytes as the content of a DER object (combinator, owned header)
+///
+/// Content type is *not* checked to match tag, caller is responsible of providing the correct tag
+///
+/// Caller is also responsible to check if parsing function consumed the expected number of
+/// bytes (`header.len`).
+///
+/// The arguments of the parse function are: `(input, ber_object_header, max_recursion)`.
+///
+/// This function differs from [`parse_der_content`](fn.parse_der_content.html) because it passes
+/// an owned BER object header (required for ex. by `parse_der_tagged_implicit_g`).
+///
+/// Example: manually parsing header and content
+///
+/// ```
+/// # use der_parser::ber::MAX_RECURSION;
+/// # use der_parser::der::*;
+/// #
+/// # let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (i, header) = der_read_element_header(bytes).expect("parsing failed");
+/// # assert_eq!(header.tag(), Tag::Integer);
+/// let (rem, content) = parse_der_content2(header.tag())(i, header, MAX_RECURSION)
+/// .expect("parsing failed");
+/// ```
+pub fn parse_der_content2<'a>(
+ tag: Tag,
+) -> impl Fn(&'a [u8], Header<'a>, usize) -> BerResult<'a, DerObjectContent<'a>> {
+ move |i: &[u8], hdr: Header, max_recursion: usize| {
+ der_read_element_content_as(i, tag, hdr.length(), hdr.is_constructed(), max_recursion)
+ }
+}
+
+// --------- end of parse_der_xxx functions ----------
+
+/// Parse the next bytes as the content of a DER object.
+///
+/// Content type is *not* checked, caller is responsible of providing the correct tag
+pub fn der_read_element_content_as(
+ i: &[u8],
+ tag: Tag,
+ length: Length,
+ constructed: bool,
+ max_depth: usize,
+) -> BerResult<DerObjectContent> {
+ // Indefinite lengths are not allowed in DER (X.690 section 10.1)
+ let l = length.definite().map_err(BerError::from)?;
+ if i.len() < l {
+ return Err(Err::Incomplete(Needed::new(l)));
+ }
+ match tag {
+ Tag::Boolean => {
+ custom_check!(i, l != 1, BerError::InvalidLength)?;
+ der_constraint_fail_if!(i, i[0] != 0 && i[0] != 0xff, DerConstraint::InvalidBoolean);
+ }
+ Tag::BitString => {
+ der_constraint_fail_if!(i, constructed, DerConstraint::Constructed);
+ // exception: read and verify padding bits
+ return der_read_content_bitstring(i, l);
+ }
+ Tag::Integer => {
+ // verify leading zeros
+ match i[..l] {
+ [] => {
+ return Err(nom::Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::IntegerEmpty,
+ )))
+ }
+ [0, 0, ..] => {
+ return Err(nom::Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::IntegerLeadingZeroes,
+ )))
+ }
+ [0, byte, ..] if byte < 0x80 => {
+ return Err(nom::Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::IntegerLeadingZeroes,
+ )));
+ }
+ _ => (),
+ }
+ }
+ Tag::NumericString
+ | Tag::VisibleString
+ | Tag::PrintableString
+ | Tag::Ia5String
+ | Tag::Utf8String
+ | Tag::T61String
+ | Tag::VideotexString
+ | Tag::BmpString
+ | Tag::UniversalString
+ | Tag::ObjectDescriptor
+ | Tag::GraphicString
+ | Tag::GeneralString => {
+ der_constraint_fail_if!(i, constructed, DerConstraint::Constructed);
+ }
+ Tag::UtcTime | Tag::GeneralizedTime => {
+ if l == 0 || i.get(l - 1).cloned() != Some(b'Z') {
+ return Err(Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::MissingTimeZone,
+ )));
+ }
+ }
+ _ => (),
+ }
+ ber_read_element_content_as(i, tag, length, constructed, max_depth)
+}
+
+/// Parse DER object content recursively
+///
+/// *Note: an error is raised if recursion depth exceeds `MAX_RECURSION`.
+pub fn der_read_element_content<'a>(i: &'a [u8], hdr: Header<'a>) -> DerResult<'a> {
+ der_read_element_content_recursive(i, hdr, MAX_RECURSION)
+}
+
+fn der_read_element_content_recursive<'a>(
+ i: &'a [u8],
+ hdr: Header<'a>,
+ max_depth: usize,
+) -> DerResult<'a> {
+ match hdr.class() {
+ Class::Universal => (),
+ _ => {
+ let (i, data) = ber_get_object_content(i, &hdr, max_depth)?;
+ let any = Any::new(hdr.clone(), data);
+ let content = DerObjectContent::Unknown(any);
+ let obj = DerObject::from_header_and_content(hdr, content);
+ return Ok((i, obj));
+ }
+ }
+ match der_read_element_content_as(i, hdr.tag(), hdr.length(), hdr.is_constructed(), max_depth) {
+ Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))),
+ Err(Err::Error(BerError::UnknownTag(_))) => {
+ let (rem, data) = ber_get_object_content(i, &hdr, max_depth)?;
+ let any = Any::new(hdr.clone(), data);
+ let content = DerObjectContent::Unknown(any);
+ let obj = DerObject::from_header_and_content(hdr, content);
+ Ok((rem, obj))
+ }
+ Err(e) => Err(e),
+ }
+}
+
+fn der_read_content_bitstring(i: &[u8], len: usize) -> BerResult<DerObjectContent> {
+ let (i, ignored_bits) = be_u8(i)?;
+ if ignored_bits > 7 {
+ return Err(Err::Error(BerError::invalid_value(
+ Tag::BitString,
+ "More than 7 unused bits".to_owned(),
+ )));
+ }
+ if len == 0 {
+ return Err(Err::Error(BerError::InvalidLength));
+ }
+ let (i, data) = take(len - 1)(i)?;
+ if len > 1 {
+ let mut last_byte = data[len - 2];
+ for _ in 0..ignored_bits as usize {
+ der_constraint_fail_if!(i, last_byte & 1 != 0, DerConstraint::UnusedBitsNotZero);
+ last_byte >>= 1;
+ }
+ }
+ Ok((
+ i,
+ DerObjectContent::BitString(ignored_bits, BitStringObject { data }),
+ ))
+ // do_parse! {
+ // i,
+ // ignored_bits: be_u8 >>
+ // custom_check!(ignored_bits > 7, BerError::DerConstraintFailed) >>
+ // custom_check!(len == 0, BerError::InvalidLength) >>
+ // s: take!(len - 1) >>
+ // call!(|input| {
+ // if len > 1 {
+ // let mut last_byte = s[len-2];
+ // for _ in 0..ignored_bits as usize {
+ // der_constraint_fail_if!(i, last_byte & 1 != 0);
+ // last_byte >>= 1;
+ // }
+ // }
+ // Ok((input,()))
+ // }) >>
+ // ( DerObjectContent::BitString(ignored_bits,BitStringObject{ data:s }) )
+ // }
+}
+
+/// Read an object header (DER)
+#[inline]
+pub fn der_read_element_header(i: &[u8]) -> BerResult<Header> {
+ Header::from_der(i)
+}
diff --git a/rust/vendor/der-parser/src/der/tagged.rs b/rust/vendor/der-parser/src/der/tagged.rs
new file mode 100644
index 0000000..83b8bc7
--- /dev/null
+++ b/rust/vendor/der-parser/src/der/tagged.rs
@@ -0,0 +1,261 @@
+use crate::ber::MAX_RECURSION;
+use crate::der::*;
+use crate::error::*;
+use nom::error::ParseError;
+use nom::{Err, IResult};
+
+/// Read a TAGGED EXPLICIT value (combinator)
+///
+/// The built object will use the outer header (and tag), and contains a `Tagged` object
+/// with class, value and content.
+///
+/// For a generic version (different output and error types), see
+/// [parse_der_tagged_explicit_g](fn.parse_der_tagged_explicit_g.html).
+///
+/// The following parses `[2] EXPLICIT INTEGER`:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map_res;
+/// #
+/// fn parse_int_explicit(i:&[u8]) -> BerResult<u32> {
+/// map_res(
+/// parse_der_tagged_explicit(2, parse_der_integer),
+/// |x: DerObject| x.as_tagged()?.2.as_u32()
+/// )(i)
+/// }
+///
+/// # 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);
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+pub fn parse_der_tagged_explicit<'a, T, F>(tag: T, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult<DerObject>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_der_tagged_explicit_g(tag, move |content, hdr| {
+ let (rem, obj) = f(content)?;
+ let class = hdr.class();
+ let obj2 = DerObject::from_header_and_content(
+ hdr,
+ DerObjectContent::Tagged(class, tag, Box::new(obj)),
+ );
+ Ok((rem, obj2))
+ })
+}
+
+/// Read a TAGGED EXPLICIT value (generic version)
+///
+/// The following parses `[2] EXPLICIT INTEGER`:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_int_explicit(i:&[u8]) -> BerResult<u32> {
+/// parse_der_tagged_explicit_g(2, move |content, hdr| {
+/// let (rem, obj) = parse_der_integer(content)?;
+/// let value = obj.as_u32()?;
+/// Ok((rem, value))
+/// })(i)
+/// }
+///
+/// # 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);
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+pub fn parse_der_tagged_explicit_g<'a, T, Output, F, E>(
+ tag: T,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Output, E>
+where
+ F: Fn(&'a [u8], Header<'a>) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_der_container(move |i, hdr| {
+ if hdr.class() == Class::Universal {
+ return Err(Err::Error(
+ BerError::unexpected_class(None, hdr.class()).into(),
+ ));
+ }
+ hdr.assert_tag(tag).map_err(|e| Err::Error(e.into()))?;
+ // X.690 8.14.2: if implicit tagging was not used, the encoding shall be constructed
+ if !hdr.is_constructed() {
+ return Err(Err::Error(BerError::ConstructExpected.into()));
+ }
+ f(i, hdr)
+ // trailing bytes are ignored
+ })
+}
+
+/// Read a TAGGED IMPLICIT value (combinator)
+///
+/// Parse a TAGGED IMPLICIT value, given the expected tag, and the content parsing function.
+///
+/// The built object will use the original header (and tag), so the content may not match the tag
+/// value.
+///
+/// For a generic version (different output and error types), see
+/// [parse_der_tagged_implicit_g](fn.parse_der_tagged_implicit_g.html).
+///
+/// # Examples
+///
+/// The following parses `[2] IMPLICIT INTEGER` into a `DerObject`:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> BerResult<DerObject> {
+/// parse_der_tagged_implicit(
+/// 2,
+/// parse_der_content(Tag::Integer),
+/// )(i)
+/// }
+///
+/// # let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01];
+/// let res = parse_int_implicit(bytes);
+/// # match res {
+/// # Ok((rem, content)) => {
+/// # assert!(rem.is_empty());
+/// # assert_eq!(content.as_u32(), Ok(0x10001));
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+///
+/// The following parses `[2] IMPLICIT INTEGER` into an `u32`, raising an error if the integer is
+/// too large:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// use nom::combinator::map_res;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> BerResult<u32> {
+/// map_res(
+/// parse_der_tagged_implicit(
+/// 2,
+/// parse_der_content(Tag::Integer),
+/// ),
+/// |x: DerObject| x.as_u32()
+/// )(i)
+/// }
+///
+/// # 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)
+/// # }
+/// ```
+pub fn parse_der_tagged_implicit<'a, T, F>(tag: T, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8], &'_ Header, usize) -> BerResult<'a, DerObjectContent<'a>>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_der_tagged_implicit_g(tag, move |i, hdr, depth| {
+ let (rem, content) = f(i, &hdr, depth)?;
+ // trailing bytes are ignored
+ let obj = DerObject::from_header_and_content(hdr, content);
+ Ok((rem, obj))
+ })
+}
+
+/// Read a TAGGED IMPLICIT value (generic version)
+///
+/// Parse a TAGGED IMPLICIT value, given the expected tag, and the content parsing function.
+///
+/// # Examples
+///
+/// The following parses `[1] IMPLICIT OCTETSTRING`, returning a `DerObject`:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_implicit_0_octetstring(i:&[u8]) -> BerResult<DerObjectContent> {
+/// parse_der_tagged_implicit_g(
+/// 2,
+/// parse_der_content2(Tag::OctetString)
+/// )(i)
+/// }
+///
+/// # let bytes = &[0x02, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f];
+/// let res = parse_implicit_0_octetstring(bytes);
+/// # match res {
+/// # Ok((rem, val)) => {
+/// # assert!(rem.is_empty());
+/// # let s = val.as_slice().unwrap();
+/// # assert_eq!(s, b"hello");
+/// # },
+/// # _ => assert!(false)
+/// # }
+/// ```
+///
+/// The following parses `[2] IMPLICIT INTEGER` into an `u32`, raising an error if the integer is
+/// too large:
+///
+/// ```rust
+/// # use der_parser::der::*;
+/// # use der_parser::error::BerResult;
+/// #
+/// fn parse_int_implicit(i:&[u8]) -> BerResult<u32> {
+/// parse_der_tagged_implicit_g(
+/// 2,
+/// |content, hdr, depth| {
+/// let (rem, obj_content) = parse_der_content(Tag::Integer)(content, &hdr, depth)?;
+/// let value = obj_content.as_u32()?;
+/// Ok((rem, value))
+/// }
+/// )(i)
+/// }
+///
+/// # 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)
+/// # }
+/// ```
+pub fn parse_der_tagged_implicit_g<'a, T, Output, F, E>(
+ tag: T,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&[u8], Output, E>
+where
+ F: Fn(&'a [u8], Header<'a>, usize) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ T: Into<Tag>,
+{
+ let tag = tag.into();
+ parse_der_container(move |i, hdr| {
+ hdr.assert_tag(tag).map_err(|e| Err::Error(e.into()))?;
+ // XXX MAX_RECURSION should not be used, it resets the depth counter
+ f(i, hdr, MAX_RECURSION)
+ // trailing bytes are ignored
+ })
+}
diff --git a/rust/vendor/der-parser/src/error.rs b/rust/vendor/der-parser/src/error.rs
new file mode 100644
index 0000000..1644594
--- /dev/null
+++ b/rust/vendor/der-parser/src/error.rs
@@ -0,0 +1,39 @@
+//! Error type for BER/DER parsers
+
+use crate::ber::BerObject;
+use crate::der::DerObject;
+use nom::IResult;
+
+pub use asn1_rs::{DerConstraint, Error};
+
+pub type BerError = Error;
+
+// pub use asn1_rs::Result;
+
+/// Holds the result of parsing functions
+///
+/// `O` is the output type, and defaults to a `BerObject`.
+///
+/// Note that this type is also a `Result`, so usual functions (`map`, `unwrap` etc.) are available.
+///
+/// This type is a wrapper around nom's IResult type
+pub type BerResult<'a, O = BerObject<'a>> = IResult<&'a [u8], O, BerError>;
+
+/// Holds the result of parsing functions (DER)
+///
+/// Note that this type is also a `Result`, so usual functions (`map`, `unwrap` etc.) are available.
+pub type DerResult<'a> = BerResult<'a, DerObject<'a>>;
+
+#[cfg(all(test, feature = "std"))]
+mod tests {
+ use super::*;
+ use std::boxed::Box;
+ use std::error::Error;
+
+ #[test]
+ fn test_unwrap_bererror() {
+ let e = BerError::IntegerTooLarge;
+ // println!("{}", e);
+ let _: Result<(), Box<dyn Error>> = Err(Box::new(e));
+ }
+}
diff --git a/rust/vendor/der-parser/src/lib.rs b/rust/vendor/der-parser/src/lib.rs
new file mode 100644
index 0000000..089e2b4
--- /dev/null
+++ b/rust/vendor/der-parser/src/lib.rs
@@ -0,0 +1,278 @@
+//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE-MIT)
+//! [![Apache License 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](./LICENSE-APACHE)
+//! [![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/8.2.0/status.svg)](https://deps.rs/crate/der-parser/8.2.0)
+//! [![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.53.0+-lightgray.svg)](#rust-version-requirements)
+//!
+//! # BER/DER Parser
+//!
+//! A parser for Basic Encoding Rules (BER [[X.690]]) and Distinguished Encoding Rules(DER
+//! [[X.690]]), implemented with the [nom](https://github.com/Geal/nom) parser combinator
+//! framework.
+//!
+//! It is written in pure Rust, fast, and makes extensive use of zero-copy. A lot of care is taken
+//! to ensure security and safety of this crate, including design (recursion limit, defensive
+//! programming), tests, and fuzzing. It also aims to be panic-free.
+//!
+//! Historically, this parser was intended for DER only, and BER support was added later. This may
+//! still reflect on some naming schemes, but has no other consequence: the `BerObject` and
+//! `DerObject` used in this crate are type aliases, so all functions are compatible.
+//!
+//! DER parsing functions have additional constraints verification, however.
+//!
+//! Serialization has also been added (see [Serialization](#serialization) )
+//!
+//! The code is available on [Github](https://github.com/rusticata/der-parser)
+//! and is part of the [Rusticata](https://github.com/rusticata) project.
+//!
+//! # BER/DER parsers
+//!
+//! BER stands for Basic Encoding Rules, and is defined in [X.690]. It defines a set of rules to
+//! encode and decode ASN.1 objects in binary.
+//!
+//! [X.690] also defines Distinguished Encoding Rules (DER), which is BER with added rules to
+//! ensure canonical and unequivocal binary representation of objects.
+//!
+//! The choice of which one to use is usually guided by the speficication of the data format based
+//! on BER or DER: for example, X.509 uses DER as encoding representation.
+//!
+//! See the related modules for object definitions, functions, and example:
+//! - [`ber`]: Basic Encoding Rules
+//! - [`der`]: Distinguished Encoding Rules
+//!
+//! ## Examples
+//!
+//! Parse two BER integers (see [BER/DER Integers](#berder-integers)):
+//!
+//! ```rust
+//! use der_parser::ber::parse_ber_integer;
+//!
+//! let bytes = [ 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x02, 0x03, 0x01, 0x00, 0x00,
+//! ];
+//!
+//! let (rem, obj1) = parse_ber_integer(&bytes).expect("parsing failed");
+//! let (rem, obj2) = parse_ber_integer(&bytes).expect("parsing failed");
+//! ```
+//!
+//! Parse a DER sequence of integers:
+//!
+//! ```rust
+//! use der_parser::der::{parse_der_integer, parse_der_sequence_of};
+//!
+//! let bytes = [ 0x30, 0x0a,
+//! 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x02, 0x03, 0x01, 0x00, 0x00,
+//! ];
+//!
+//! let (rem, seq) = parse_der_sequence_of(parse_der_integer)(&bytes)
+//! .expect("parsing failed");
+//! ```
+//!
+//! Note: all parsing functions return the remaining (unparsed) bytes and the parsed object, or an
+//! error.
+//!
+//! # DER parser design
+//!
+//! Parsing functions are inspired from `nom`, and follow the same interface. The most common
+//! return type is [`BerResult`](error/type.BerResult.html), that stores the remaining bytes and
+//! parsed [`BerObject`](ber/struct.BerObject.html), or an error. Reading the nom documentation may
+//! help understanding how to write parsers and use the output.
+//!
+//! There are two different approaches for parsing DER objects: reading the objects recursively as
+//! long as the tags are known, or specifying a description of the expected objects (generally from
+//! the [ASN.1][X.680] description).
+//!
+//! The first parsing method can be done using the [`parse_ber`](ber/fn.parse_ber.html) and
+//! [`parse_der`](der/fn.parse_der.html) methods.
+//! It is useful when decoding an arbitrary DER object.
+//! However, it cannot fully parse all objects, especially those containing IMPLICIT, OPTIONAL, or
+//! DEFINED BY items.
+//!
+//! ```rust
+//! use der_parser::parse_der;
+//!
+//! let bytes = [ 0x30, 0x0a,
+//! 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x02, 0x03, 0x01, 0x00, 0x00,
+//! ];
+//!
+//! let parsed = parse_der(&bytes);
+//! ```
+//!
+//! The second (and preferred) parsing method is to specify the expected objects recursively. The
+//! following functions can be used:
+//! - [`parse_ber_sequence_defined`](ber/fn.parse_ber_sequence_defined.html) and similar functions
+//! for sequences and sets variants
+//! - [`parse_ber_tagged_explicit`](ber/fn.parse_ber_tagged_explicit.html) for tagged explicit
+//! - [`parse_ber_tagged_implicit`](ber/fn.parse_ber_tagged_implicit.html) for tagged implicit
+//! - [`parse_ber_container`](ber/fn.parse_ber_container.html) for generic parsing, etc.
+//! - DER objects use the `_der_` variants
+//!
+//! For example, to read a BER sequence containing two integers:
+//!
+//! ```rust
+//! use der_parser::ber::*;
+//! use der_parser::error::BerResult;
+//!
+//! fn localparse_seq(i:&[u8]) -> BerResult {
+//! parse_ber_sequence_defined(|data| {
+//! let (rem, a) = parse_ber_integer(data)?;
+//! let (rem, b) = parse_ber_integer(rem)?;
+//! Ok((rem, vec![a, b]))
+//! })(i)
+//! }
+//!
+//! let bytes = [ 0x30, 0x0a,
+//! 0x02, 0x03, 0x01, 0x00, 0x01,
+//! 0x02, 0x03, 0x01, 0x00, 0x00,
+//! ];
+//!
+//! let (_, parsed) = localparse_seq(&bytes).expect("parsing failed");
+//!
+//! assert_eq!(parsed[0].as_u64(), Ok(65537));
+//! assert_eq!(parsed[1].as_u64(), Ok(65536));
+//! ```
+//!
+//! All functions return a [`BerResult`](error/type.BerResult.html) object: the parsed
+//! [`BerObject`](ber/struct.BerObject.html), an `Incomplete` value, or an error.
+//!
+//! Note that this type is also a `Result`, so usual functions (`map`, `unwrap` etc.) are available.
+//!
+//! # Notes
+//!
+//! ## BER/DER Integers
+//!
+//! 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).
+//!
+//! ```rust
+//! use der_parser::ber::*;
+//!
+//! 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(), Ok(65537.into()))
+//! ```
+//!
+//! Access to the raw value is possible using the `as_slice` method.
+//!
+//! ## Parsers, combinators, macros
+//!
+//! Some parsing tools (for ex for tagged objects) are available in different forms:
+//! - parsers: (regular) functions that takes input and create an object
+//! - combinators: functions that takes parsers (or combinators) as input, and return a function
+//! (usually, the parser). They are used (combined) as building blocks to create more complex
+//! parsers.
+//! - macros: these are generally previous (historic) versions of parsers, kept for compatibility.
+//! They can sometime reduce the amount of code to write, but are hard to debug.
+//! Parsers should be preferred when possible.
+//!
+//! ## Misc Notes
+//!
+//! - The DER constraints are verified if using `parse_der`.
+//! - `BerObject` and `DerObject` are the same objects (type alias). The only difference is the
+//! verification of constraints *during parsing*.
+//!
+//! ## Rust version requirements
+//!
+//! The 7.0 series of `der-parser` requires **Rustc version 1.53 or greater**, based on `asn1-rs`
+//! and `nom` 7 dependencies.
+//!
+//! # Serialization
+//!
+//! Support for encoding BER/DER objects is currently being tested and can be used by activating the `serialize` feature.
+//! Note that current status is **experimental**.
+//!
+//! See the `ber_encode_*` functions in the [`ber`](ber/index.html) module, and
+//! [`BerObject::to_vec`](ber/struct.BerObject.html#method.to_vec)
+//!
+//! # References
+//!
+//! - [[X.680]] Abstract Syntax Notation One (ASN.1): Specification of basic notation.
+//! - [[X.690]] ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical
+//! Encoding Rules (CER) and Distinguished Encoding Rules (DER).
+//!
+//! [X.680]: http://www.itu.int/rec/T-REC-X.680/en "Abstract Syntax Notation One (ASN.1):
+//! Specification of basic notation."
+//! [X.690]: https://www.itu.int/rec/T-REC-X.690/en "ASN.1 encoding rules: Specification of
+//! Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules
+//! (DER)."
+
+#![deny(/*missing_docs,*/
+ unstable_features,
+ unused_import_braces,
+ unused_qualifications,
+ unreachable_pub)]
+#![forbid(unsafe_code)]
+#![warn(
+ /* missing_docs,
+ rust_2018_idioms,*/
+ missing_debug_implementations,
+)]
+// pragmas for doc
+#![deny(broken_intra_doc_links)]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![doc(test(
+ 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;
+
+#[allow(clippy::module_inception)]
+pub mod ber;
+pub mod der;
+pub mod error;
+pub mod oid;
+
+// compatibility: re-export at crate root
+pub use ber::parse_ber;
+pub use der::parse_der;
+
+pub use asn1_rs;
+pub use nom;
+#[cfg(feature = "bigint")]
+#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
+pub use num_bigint;
+pub use rusticata_macros;
+
+// re-exports nom macros, so this crate's macros can be used without importing nom
+pub use nom::IResult;
+
+pub(crate) use asn1_rs::der_constraint_fail_if;
+
+pub use asn1_rs::Oid;
+
+/// Procedural macro to get encoded oids, see the [oid module](oid/index.html).
+#[macro_export]
+macro_rules! oid {
+ ($($args:tt)*) => {{
+ $crate::asn1_rs::oid!($($args)*)
+ }};
+}
diff --git a/rust/vendor/der-parser/src/oid.rs b/rust/vendor/der-parser/src/oid.rs
new file mode 100644
index 0000000..f35b52b
--- /dev/null
+++ b/rust/vendor/der-parser/src/oid.rs
@@ -0,0 +1 @@
+pub use asn1_rs::Oid;
diff --git a/rust/vendor/der-parser/tests/ber_parser.rs b/rust/vendor/der-parser/tests/ber_parser.rs
new file mode 100644
index 0000000..3d61574
--- /dev/null
+++ b/rust/vendor/der-parser/tests/ber_parser.rs
@@ -0,0 +1,556 @@
+// test_case seem to generate this warning - ignore it
+#![allow(clippy::unused_unit)]
+
+use der_parser::ber::*;
+use der_parser::error::*;
+use der_parser::oid::*;
+use hex_literal::hex;
+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 false")]
+#[test_case(&hex!("01 01 ff"), Some(true) ; "val true")]
+#[test_case(&hex!("01 01 7f"), Some(true) ; "true not ff")]
+#[test_case(&hex!("01 02 00 00"), None ; "invalid length")]
+#[test_case(&hex!("01 01"), None ; "incomplete")]
+fn tc_ber_bool(i: &[u8], out: Option<bool>) {
+ let res = parse_ber_bool(i);
+ if let Some(b) = out {
+ let expected = BerObject::from_obj(BerObjectContent::Boolean(b));
+ pretty_assertions::assert_eq!(res, Ok((&b""[..], expected)));
+ } else {
+ assert!(res.is_err());
+ }
+}
+
+#[test]
+fn test_ber_bool() {
+ let empty = &b""[..];
+ let b_true = BerObject::from_obj(BerObjectContent::Boolean(true));
+ let b_false = BerObject::from_obj(BerObjectContent::Boolean(false));
+ assert_eq!(parse_ber_bool(&[0x01, 0x01, 0x00]), Ok((empty, b_false)));
+ assert_eq!(
+ parse_ber_bool(&[0x01, 0x01, 0xff]),
+ Ok((empty, b_true.clone()))
+ );
+ assert_eq!(parse_ber_bool(&[0x01, 0x01, 0x7f]), Ok((empty, b_true)));
+ assert_eq!(
+ parse_ber_bool(&[0x01, 0x02, 0x12, 0x34]),
+ Err(Err::Error(BerError::InvalidLength))
+ );
+}
+
+#[test]
+fn test_seq_indefinite_length() {
+ let data = hex!("30 80 04 03 56 78 90 00 00 02 01 01");
+ let res = parse_ber(&data);
+ assert_eq!(
+ res,
+ Ok((
+ &data[9..],
+ BerObject::from_seq(vec![BerObject::from_obj(BerObjectContent::OctetString(
+ &data[4..=6]
+ )),])
+ ))
+ );
+ let res = parse_ber_sequence(&data);
+ assert_eq!(
+ res,
+ Ok((
+ &data[9..],
+ BerObject::from_seq(vec![BerObject::from_obj(BerObjectContent::OctetString(
+ &data[4..=6]
+ )),])
+ ))
+ );
+}
+
+#[test]
+fn test_ber_set_of() {
+ 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"),
+ ]);
+ fn parser(i: &[u8]) -> BerResult {
+ parse_ber_set_of(parse_ber_integer)(i)
+ }
+ assert_eq!(parser(&bytes), Ok((empty, expected)));
+ // empty input should raise error (could not read set header)
+ assert!(parser(&[]).is_err());
+ // empty set is ok (returns empty vec)
+ assert!(parser(&[0x31, 0x00]).is_ok());
+}
+
+#[test]
+fn test_ber_set_of_v() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x31, 0x0a, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00,
+ ];
+ let expected = vec![
+ BerObject::from_int_slice(b"\x01\x00\x01"),
+ BerObject::from_int_slice(b"\x01\x00\x00"),
+ ];
+ fn parser(i: &[u8]) -> BerResult<Vec<BerObject>> {
+ parse_ber_set_of_v(parse_ber_integer)(i)
+ }
+ assert_eq!(parser(&bytes), Ok((empty, expected)));
+ // empty input should raise error (could not read set header)
+ assert!(parser(&[]).is_err());
+ // empty set is ok (returns empty vec)
+ assert_eq!(parser(&[0x31, 0x00]), Ok((empty, vec![])));
+}
+
+#[test]
+fn test_set_indefinite_length() {
+ let data = hex!("31 80 04 03 56 78 90 00 00");
+ let res = parse_ber(&data);
+ assert_eq!(
+ res,
+ Ok((
+ &data[9..],
+ BerObject::from_set(vec![BerObject::from_obj(BerObjectContent::OctetString(
+ &data[4..=6]
+ )),])
+ ))
+ );
+ let res = parse_ber_set(&data);
+ assert_eq!(
+ res,
+ Ok((
+ &data[9..],
+ BerObject::from_set(vec![BerObject::from_obj(BerObjectContent::OctetString(
+ &data[4..=6]
+ )),])
+ ))
+ );
+}
+
+#[test]
+fn test_ber_int() {
+ let empty = &b""[..];
+ let bytes = [0x02, 0x03, 0x01, 0x00, 0x01];
+ let expected = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
+ assert_eq!(parse_ber_integer(&bytes), Ok((empty, expected)));
+}
+
+#[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 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"), Err(BerError::IntegerNegative) ; "u32-long2-neg")]
+#[test_case(&hex!("02 06 ff ff ff ff ff ff"), Err(BerError::IntegerNegative) ; "u32-long3-neg")]
+#[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::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_ber_u32(i: &[u8], out: Result<u32, BerError>) {
+ let res = parse_ber_u32(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 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 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::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_ber_u64(i: &[u8], out: Result<u64, BerError>) {
+ let res = parse_ber_u64(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) ; "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!("02 04 ff ff ff ff"), Ok(-1) ; "i64-long-neg")]
+#[test_case(&hex!("03 03 01 00 01"), Err(BerError::unexpected_tag(Some(Tag(2)), Tag(3))) ; "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(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::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+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) => {
+ 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]) ; "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")]
+#[test_case(&hex!("22 80 02 01 01 00 00"), Ok(&[2, 1, 1]) ; "constructed slice")]
+#[test_case(&hex!("03 03 01 00 01"), Err(BerError::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_ber_slice(i: &[u8], out: Result<&[u8], BerError>) {
+ let res = parse_ber_slice(i, 2);
+ match out {
+ Ok(expected) => {
+ pretty_assertions::assert_eq!(res, Ok((&b""[..], expected)));
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
+ }
+ }
+}
+
+#[test]
+fn test_ber_bitstring_primitive() {
+ let empty = &b""[..];
+ let bytes = &[0x03, 0x07, 0x04, 0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0];
+ let expected = BerObject::from_obj(BerObjectContent::BitString(
+ 4,
+ BitStringObject { data: &bytes[3..] },
+ ));
+ assert_eq!(parse_ber_bitstring(bytes), Ok((empty, expected)));
+ //
+ // correct encoding, padding bits not all set to 0
+ //
+ let bytes = &[0x03, 0x04, 0x06, 0x6e, 0x5d, 0xe0];
+ let expected = BerObject::from_obj(BerObjectContent::BitString(
+ 6,
+ BitStringObject { data: &bytes[3..] },
+ ));
+ assert_eq!(parse_ber_bitstring(bytes), Ok((empty, expected)));
+ //
+ // long form of length
+ //
+ let bytes = &[0x03, 0x81, 0x04, 0x06, 0x6e, 0x5d, 0xc0];
+ let expected = BerObject::from_obj(BerObjectContent::BitString(
+ 6,
+ BitStringObject { data: &bytes[4..] },
+ ));
+ assert_eq!(parse_ber_bitstring(bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_ber_bitstring_constructed() {
+ let bytes = &[
+ 0x23, 0x80, 0x03, 0x03, 0x00, 0x0a, 0x3b, 0x03, 0x05, 0x04, 0x5f, 0x29, 0x1c, 0xd0, 0x00,
+ 0x00,
+ ];
+ assert_eq!(
+ parse_ber_bitstring(bytes),
+ Err(Err::Error(BerError::Unsupported))
+ ); // XXX valid encoding
+}
+
+#[test]
+fn test_ber_octetstring_primitive() {
+ let empty = &b""[..];
+ let bytes = [0x04, 0x05, 0x41, 0x41, 0x41, 0x41, 0x41];
+ let expected = BerObject::from_obj(BerObjectContent::OctetString(b"AAAAA"));
+ assert_eq!(parse_ber_octetstring(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_ber_null() {
+ let empty = &b""[..];
+ let expected = BerObject::from_obj(BerObjectContent::Null);
+ assert_eq!(parse_ber_null(&[0x05, 0x00]), Ok((empty, expected)));
+}
+
+#[test]
+fn test_ber_oid() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
+ ];
+ let expected = BerObject::from_obj(BerObjectContent::OID(
+ Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap(),
+ ));
+ assert_eq!(parse_ber_oid(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_ber_enum() {
+ let empty = &b""[..];
+ let expected = BerObject::from_obj(BerObjectContent::Enum(2));
+ assert_eq!(parse_ber_enum(&[0x0a, 0x01, 0x02]), Ok((empty, expected)));
+}
+
+#[test_case(&hex!("0c 04 31 32 33 34"), Ok("1234") ; "utf8: numeric")]
+#[test_case(&hex!("0c 05 68 65 6c 6c 6f"), Ok("hello") ; "utf8: string")]
+#[test_case(&hex!("0c 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64"), Ok("hello world") ; "utf8: string with spaces")]
+#[test_case(&hex!("0c 0b 68 65 6c 6c 6f 5c 77 6f 72 6c 64"), Ok("hello\\world") ; "utf8: string with backspace")]
+#[test_case(&hex!("0c 0b 68 65 6c 6c 6f 2b 77 6f 72 6c 64"), Ok("hello+world") ; "utf8: string with plus")]
+#[test_case(&hex!("0c 05 01 02 03 04 05"), Ok("\x01\x02\x03\x04\x05") ; "invalid chars")]
+#[test_case(&hex!("0c 0e d0 bf d1 80 d0 b8 d0 b2 d0 b5 cc 81 d1 82"), Ok("приве́т") ; "utf8")]
+#[test_case(&hex!("0c 04 00 9f 92 96"), Err(Err::Error(BerError::StringInvalidCharset)) ; "invalid utf8")]
+fn tc_ber_utf8_string(i: &[u8], out: Result<&str, Err<BerError>>) {
+ let res = parse_ber_utf8string(i);
+ match out {
+ Ok(b) => {
+ let (rem, res) = res.expect("could not parse utf8string");
+ assert!(rem.is_empty());
+ let r = res.as_str().expect("could not convert to string");
+ // let expected = BerObject::from_obj(BerObjectContent::Boolean(b));
+ pretty_assertions::assert_eq!(r, b);
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("12 04 31 32 33 34"), Ok("1234") ; "numeric string")]
+#[test_case(&hex!("12 05 68 65 6c 6c 6f"), Err(Err::Error(BerError::StringInvalidCharset)) ; "invalid chars")]
+#[test_case(&hex!("12 05 01 02 03 04 05"), Err(Err::Error(BerError::StringInvalidCharset)) ; "invalid chars2")]
+fn tc_ber_numeric_string(i: &[u8], out: Result<&str, Err<BerError>>) {
+ let res = parse_ber_numericstring(i);
+ match out {
+ Ok(b) => {
+ let (rem, res) = res.expect("could not parse numericstring");
+ assert!(rem.is_empty());
+ let r = res.as_str().expect("could not convert to string");
+ // let expected = BerObject::from_obj(BerObjectContent::Boolean(b));
+ pretty_assertions::assert_eq!(r, b);
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("13 04 31 32 33 34"), Ok("1234") ; "printable: numeric")]
+#[test_case(&hex!("13 05 68 65 6c 6c 6f"), Ok("hello") ; "printable: string")]
+#[test_case(&hex!("13 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64"), Ok("hello world") ; "printable: string with spaces")]
+#[test_case(&hex!("13 0b 68 65 6c 6c 6f 5c 77 6f 72 6c 64"), Err(Err::Error(BerError::StringInvalidCharset)) ; "printable: string with backspace")]
+#[test_case(&hex!("13 0b 68 65 6c 6c 6f 2b 77 6f 72 6c 64"), Ok("hello+world") ; "printable: string with plus")]
+#[test_case(&hex!("13 05 01 02 03 04 05"), Err(Err::Error(BerError::StringInvalidCharset)) ; "invalid chars")]
+fn tc_ber_printable_string(i: &[u8], out: Result<&str, Err<BerError>>) {
+ let res = parse_ber_printablestring(i);
+ match out {
+ Ok(b) => {
+ let (rem, res) = res.expect("could not parse printablestring");
+ assert!(rem.is_empty());
+ let r = res.as_str().expect("could not convert to string");
+ // let expected = BerObject::from_obj(BerObjectContent::Boolean(b));
+ pretty_assertions::assert_eq!(r, b);
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("16 04 31 32 33 34"), Ok("1234") ; "ia5: numeric")]
+#[test_case(&hex!("16 05 68 65 6c 6c 6f"), Ok("hello") ; "ia5: string")]
+#[test_case(&hex!("16 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64"), Ok("hello world") ; "ia5: string with spaces")]
+#[test_case(&hex!("16 0b 68 65 6c 6c 6f 5c 77 6f 72 6c 64"), Ok("hello\\world") ; "ia5: string with backspace")]
+#[test_case(&hex!("16 0b 68 65 6c 6c 6f 2b 77 6f 72 6c 64"), Ok("hello+world") ; "ia5: string with plus")]
+#[test_case(&hex!("16 05 01 02 03 04 05"), Ok("\x01\x02\x03\x04\x05") ; "invalid chars")]
+#[test_case(&hex!("16 0d d0 bf d1 80 d0 b8 d0 b2 d0 b5 cc 81 d1 82"), Err(Err::Error(BerError::StringInvalidCharset)) ; "utf8")]
+fn tc_ber_ia5_string(i: &[u8], out: Result<&str, Err<BerError>>) {
+ let res = parse_ber_ia5string(i);
+ match out {
+ Ok(b) => {
+ let (rem, res) = res.expect("could not parse ia5string");
+ assert!(rem.is_empty());
+ let r = res.as_str().expect("could not convert to string");
+ // let expected = BerObject::from_obj(BerObjectContent::Boolean(b));
+ pretty_assertions::assert_eq!(r, b);
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("1a 04 31 32 33 34"), Ok("1234") ; "visible: numeric")]
+#[test_case(&hex!("1a 05 68 65 6c 6c 6f"), Ok("hello") ; "visible: string")]
+#[test_case(&hex!("1a 0b 68 65 6c 6c 6f 20 77 6f 72 6c 64"), Ok("hello world") ; "visible: string with spaces")]
+#[test_case(&hex!("1a 0b 68 65 6c 6c 6f 5c 77 6f 72 6c 64"), Ok("hello\\world") ; "printable: string with backspace")]
+#[test_case(&hex!("1a 0b 68 65 6c 6c 6f 2b 77 6f 72 6c 64"), Ok("hello+world") ; "printable: string with plus")]
+#[test_case(&hex!("1a 05 01 02 03 04 05"), Err(Err::Error(BerError::StringInvalidCharset)) ; "invalid chars")]
+fn tc_ber_visible_string(i: &[u8], out: Result<&str, Err<BerError>>) {
+ let res = parse_ber_visiblestring(i);
+ match out {
+ Ok(b) => {
+ let (rem, res) = res.expect("could not parse visiblestring");
+ assert!(rem.is_empty());
+ let r = res.as_str().expect("could not convert to string");
+ // let expected = BerObject::from_obj(BerObjectContent::Boolean(b));
+ pretty_assertions::assert_eq!(r, b);
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test]
+fn test_ber_utf8string() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ ];
+ let expected = BerObject::from_obj(BerObjectContent::UTF8String("Some-State"));
+ assert_eq!(parse_ber_utf8string(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_ber_relativeoid() {
+ let empty = &b""[..];
+ let bytes = hex!("0d 04 c2 7b 03 02");
+ let expected = BerObject::from_obj(BerObjectContent::RelativeOID(
+ Oid::from_relative(&[8571, 3, 2]).unwrap(),
+ ));
+ assert_eq!(parse_ber_relative_oid(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_ber_bmpstring() {
+ let empty = &b""[..];
+ let bytes = hex!("1e 08 00 55 00 73 00 65 00 72");
+ let expected = BerObject::from_obj(BerObjectContent::BmpString("\x00U\x00s\x00e\x00r"));
+ assert_eq!(parse_ber_bmpstring(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_ber_customtags() {
+ let bytes = hex!("8f 02 12 34");
+ let hdr = ber_read_element_header(&bytes)
+ .expect("ber_read_element_header")
+ .1;
+ // println!("{:?}", hdr);
+ let expected: &[u8] = &[0x8f];
+ assert_eq!(hdr.raw_tag(), Some(expected));
+ let bytes = hex!("9f 0f 02 12 34");
+ let hdr = ber_read_element_header(&bytes)
+ .expect("ber_read_element_header")
+ .1;
+ // println!("{:?}", hdr);
+ let expected: &[u8] = &[0x9f, 0x0f];
+ assert_eq!(hdr.raw_tag(), Some(expected));
+}
+
+#[test]
+fn test_ber_indefinite() {
+ let bytes = hex!("30 80 02 03 01 00 01 00 00");
+ let (rem, val) = parse_ber_container::<_, _, BerError>(|i, _| {
+ assert!(!i.is_empty());
+ let (_, val) = parse_ber_u32(i)?;
+ Ok((i, val))
+ })(&bytes)
+ .unwrap();
+ assert!(rem.is_empty());
+ assert_eq!(val, 0x10001);
+}
+
+#[test]
+fn test_ber_indefinite_recursion() {
+ let data = &hex!(
+ "
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80
+ 24 80 24 80 24 80 24 80 24 80 24 80 24 80 24 80 00 00"
+ );
+ let _ = parse_ber_container::<_, _, BerError>(|i, _| Ok((i, ())))(data)
+ .expect_err("max parsing depth overflow");
+}
+
+#[test]
+fn test_parse_ber_content() {
+ let bytes = &hex!("02 03 01 00 01");
+ let (i, header) = ber_read_element_header(bytes).expect("parsing failed");
+ let (rem, content) =
+ parse_ber_content(header.tag())(i, &header, MAX_RECURSION).expect("parsing failed");
+ assert!(rem.is_empty());
+ assert_eq!(header.tag(), Tag::Integer);
+ assert_eq!(content.as_u32(), Ok(0x10001));
+}
+
+#[test]
+fn test_parse_ber_content2() {
+ let bytes = &hex!("02 03 01 00 01");
+ let (i, header) = ber_read_element_header(bytes).expect("parsing failed");
+ let tag = header.tag();
+ let (rem, content) = parse_ber_content2(tag)(i, header, MAX_RECURSION).expect("parsing failed");
+ assert!(rem.is_empty());
+ assert_eq!(tag, Tag::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::Unknown(_)));
+}
diff --git a/rust/vendor/der-parser/tests/constructed.rs b/rust/vendor/der-parser/tests/constructed.rs
new file mode 100644
index 0000000..7ba6644
--- /dev/null
+++ b/rust/vendor/der-parser/tests/constructed.rs
@@ -0,0 +1,441 @@
+// test_case seem to generate this warning - ignore it
+#![allow(clippy::unused_unit)]
+
+use der_parser::ber::*;
+use der_parser::der::*;
+use der_parser::error::*;
+use der_parser::*;
+use hex_literal::hex;
+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;
+use pretty_assertions::assert_eq;
+use test_case::test_case;
+
+#[derive(Debug, PartialEq)]
+struct MyStruct<'a> {
+ a: BerObject<'a>,
+ b: BerObject<'a>,
+}
+
+fn parse_struct01(i: &[u8]) -> BerResult<MyStruct> {
+ 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_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: Tag) -> BerResult<MyStruct> {
+ 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")]
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "seq ok")]
+#[test_case(&hex!("30 07 02 03 01 00 01 02 03 01"), Err(Err::Error(BerError::NomError(ErrorKind::Eof))) ; "incomplete")]
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Err(Err::Error(BerError::unexpected_tag(Some(Tag::Sequence), Tag::Set))) ; "invalid tag")]
+#[test_case(&hex!("30 80 02 03 01 00 01 00 00"), Ok(&[0x10001]) ; "indefinite seq ok")]
+#[test_case(&hex!("30 80"), Err(Err::Incomplete(Needed::new(1))) ; "indefinite incomplete")]
+fn tc_ber_seq_of(i: &[u8], out: Result<&[u32], Err<BerError>>) {
+ fn parser(i: &[u8]) -> BerResult {
+ parse_ber_sequence_of(parse_ber_integer)(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse sequence of");
+ assert!(rem.is_empty());
+ if let BerObjectContent::Sequence(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "seq ok")]
+#[test_case(&hex!("30 07 02 03 01 00 01 02 01"), Err(Err::Incomplete(Needed::new(1))) ; "incomplete")]
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Err(Err::Error(BerError::unexpected_tag(Some(Tag::Sequence), Tag::Set))) ; "invalid tag")]
+#[test_case(&hex!("30 80 02 03 01 00 01 02 03 01 00 00 00 00"), Ok(&[0x10001, 0x10000]) ; "indefinite seq")]
+fn tc_ber_seq_defined(i: &[u8], out: Result<&[u32], Err<BerError>>) {
+ fn parser(i: &[u8]) -> BerResult<BerObject> {
+ parse_ber_sequence_defined(map(
+ tuple((parse_ber_integer, parse_ber_integer)),
+ |(a, b)| vec![a, b],
+ ))(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse sequence");
+ assert!(rem.is_empty());
+ if let BerObjectContent::Sequence(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("31 00"), Ok(&[]) ; "empty set")]
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "set ok")]
+#[test_case(&hex!("31 07 02 03 01 00 01 02 03 01"), Err(Err::Error(BerError::NomError(ErrorKind::Eof))) ; "incomplete")]
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Err(Err::Error(BerError::unexpected_tag(Some(Tag::Set), Tag::Sequence))) ; "invalid tag")]
+#[test_case(&hex!("31 80 02 03 01 00 01 00 00"), Ok(&[0x10001]) ; "indefinite set ok")]
+#[test_case(&hex!("31 80"), Err(Err::Incomplete(Needed::new(1))) ; "indefinite incomplete")]
+fn tc_ber_set_of(i: &[u8], out: Result<&[u32], Err<BerError>>) {
+ fn parser(i: &[u8]) -> BerResult {
+ parse_ber_set_of(parse_ber_integer)(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse set of");
+ assert!(rem.is_empty());
+ if let BerObjectContent::Set(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "set ok")]
+#[test_case(&hex!("31 07 02 03 01 00 01 02 01"), Err(Err::Incomplete(Needed::new(1))) ; "incomplete")]
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Err(Err::Error(BerError::unexpected_tag(Some(Tag::Set), Tag::Sequence))) ; "invalid tag")]
+#[test_case(&hex!("31 80 02 03 01 00 01 02 03 01 00 00 00 00"), Ok(&[0x10001, 0x10000]) ; "indefinite set")]
+fn tc_ber_set_defined(i: &[u8], out: Result<&[u32], Err<BerError>>) {
+ fn parser(i: &[u8]) -> BerResult<BerObject> {
+ parse_ber_set_defined(map(
+ tuple((parse_ber_integer, parse_ber_integer)),
+ |(a, b)| vec![a, b],
+ ))(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse set");
+ assert!(rem.is_empty());
+ if let BerObjectContent::Set(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+#[test]
+fn empty_seq() {
+ let data = &hex!("30 00");
+ let (_, res) = parse_ber_sequence(data).expect("parsing empty sequence failed");
+ assert!(res.as_sequence().unwrap().is_empty());
+}
+
+#[test]
+fn struct01() {
+ 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)));
+}
+
+#[test]
+fn struct02() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x52,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x16, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+ ];
+ #[derive(Debug, PartialEq)]
+ struct Attr<'a> {
+ oid: Oid<'a>,
+ val: BerObject<'a>,
+ }
+ #[derive(Debug, PartialEq)]
+ struct Rdn<'a> {
+ a: Attr<'a>,
+ }
+ #[derive(Debug, PartialEq)]
+ struct Name<'a> {
+ l: Vec<Rdn<'a>>,
+ }
+ let expected = Name {
+ l: vec![
+ Rdn {
+ a: Attr {
+ oid: Oid::from(&[2, 5, 4, 6]).unwrap(), // countryName
+ val: BerObject::from_obj(BerObjectContent::PrintableString("FR")),
+ },
+ },
+ Rdn {
+ a: Attr {
+ oid: Oid::from(&[2, 5, 4, 8]).unwrap(), // stateOrProvinceName
+ val: BerObject::from_obj(BerObjectContent::UTF8String("Some-State")),
+ },
+ },
+ Rdn {
+ a: Attr {
+ oid: Oid::from(&[2, 5, 4, 10]).unwrap(), // organizationName
+ val: BerObject::from_obj(BerObjectContent::IA5String(
+ "Internet Widgits Pty Ltd",
+ )),
+ },
+ },
+ ],
+ };
+ fn parse_directory_string(i: &[u8]) -> BerResult {
+ 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_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_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_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));
+ //
+ assert_eq!(parsed.1.l[0].a.val.as_str(), Ok("FR"));
+ assert_eq!(parsed.1.l[1].a.val.as_str(), Ok("Some-State"));
+ assert_eq!(parsed.1.l[2].a.val.as_str(), Ok("Internet Widgits Pty Ltd"));
+}
+
+#[test]
+fn struct_with_garbage() {
+ let bytes = [
+ 0x30, 0x0c, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00, 0xff, 0xff,
+ ];
+ let empty = &b""[..];
+ let expected = MyStruct {
+ a: BerObject::from_int_slice(b"\x01\x00\x01"),
+ b: BerObject::from_int_slice(b"\x01\x00\x00"),
+ };
+ assert_eq!(parse_struct01(&bytes), Ok((empty, expected)));
+ assert_eq!(
+ parse_struct01_complete(&bytes),
+ Err(Err::Error(error_position!(&bytes[12..], ErrorKind::Eof)))
+ );
+}
+
+#[test]
+fn struct_verify_tag() {
+ 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_struct04(&bytes, Tag::Sequence);
+ assert_eq!(res, Ok((empty, expected)));
+ let res = parse_struct04(&bytes, Tag::Set);
+ assert_eq!(res, Err(Err::Error(BerError::InvalidTag)));
+}
+
+#[test_case(&hex!("a2 05 02 03 01 00 01"), Ok(0x10001) ; "tag ok")]
+#[test_case(&hex!("a2 80 02 03 01 00 01 00 00"), Ok(0x10001) ; "indefinite tag ok")]
+#[test_case(&hex!("a3 05 02 03 01 00 01"), Err(BerError::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+#[test_case(&hex!("22 05 02 03 01 00 01"), Err(BerError::unexpected_class(None, Class::Universal)) ; "invalid class")]
+#[test_case(&hex!("82 05 02 03 01 00 01"), Err(BerError::ConstructExpected) ; "construct expected")]
+fn tc_ber_tagged_explicit_g(i: &[u8], out: Result<u32, BerError>) {
+ fn parse_int_explicit(i: &[u8]) -> BerResult<u32> {
+ parse_ber_tagged_explicit_g(2, move |content, _hdr| {
+ let (rem, obj) = parse_ber_integer(content)?;
+ let value = obj.as_u32()?;
+ Ok((rem, value))
+ })(i)
+ }
+ let res = parse_int_explicit(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]
+fn tagged_explicit() {
+ fn parse_int_explicit(i: &[u8]) -> BerResult<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);
+ // wrong tag
+ assert_eq!(
+ parse_der_tagged_explicit(3, parse_der_integer)(bytes as &[u8]),
+ Err(Err::Error(BerError::unexpected_tag(Some(Tag(3)), Tag(2))))
+ );
+ // wrong type
+ assert_eq!(
+ parse_der_tagged_explicit(2, parse_der_bool)(bytes as &[u8]),
+ Err(Err::Error(BerError::unexpected_tag(Some(Tag(1)), Tag(2))))
+ );
+}
+
+#[test_case(&hex!("82 03 01 00 01"), Ok(0x10001) ; "tag ok")]
+#[test_case(&hex!("83 03 01 00 01"), Err(BerError::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_ber_tagged_implicit_g(i: &[u8], out: Result<u32, BerError>) {
+ fn parse_int_implicit(i: &[u8]) -> BerResult<u32> {
+ parse_ber_tagged_implicit_g(2, |content, hdr, depth| {
+ let (rem, obj) = parse_ber_content(Tag::Integer)(content, &hdr, depth)?;
+ let value = obj.as_u32()?;
+ Ok((rem, value))
+ })(i)
+ }
+ let res = parse_int_implicit(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]
+fn tagged_implicit() {
+ fn parse_int_implicit(i: &[u8]) -> BerResult<u32> {
+ map_res(
+ parse_der_tagged_implicit(2, parse_der_content(Tag::Integer)),
+ |x: BerObject| x.as_u32(),
+ )(i)
+ }
+ let bytes = &[0x82, 0x03, 0x01, 0x00, 0x01];
+ // IMPLICIT tagged value parsing
+ let (rem, val) = parse_int_implicit(bytes).expect("could not parse implicit int");
+ assert!(rem.is_empty());
+ assert_eq!(val, 0x10001);
+ // wrong tag
+ assert_eq!(
+ parse_der_tagged_implicit(3, parse_der_content(Tag::Integer))(bytes as &[u8]),
+ Err(Err::Error(BerError::unexpected_tag(Some(Tag(3)), Tag(2))))
+ );
+}
+
+#[test]
+fn application() {
+ #[derive(Debug, PartialEq)]
+ struct SimpleStruct {
+ a: u32,
+ }
+ fn parse_app01(i: &[u8]) -> BerResult<SimpleStruct> {
+ parse_der_container(|i, hdr| {
+ if hdr.class() != Class::Application {
+ return Err(Err::Error(BerError::unexpected_class(None, hdr.class())));
+ }
+ if hdr.tag() != Tag(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");
+ assert!(rem.is_empty());
+ assert_eq!(app, SimpleStruct { a: 0x10001 });
+}
+
+#[test]
+#[ignore = "not yet implemented"]
+fn ber_constructed_string() {
+ // this encoding is equivalent to "04 05 01 AB 23 7F CA"
+ let data = &hex!(
+ "
+ 24 80
+ 04 02 01 ab
+ 04 02 23 7f
+ 04 01 ca
+ 00 00"
+ );
+ let _ = parse_ber_octetstring(data).expect("parsing failed");
+}
diff --git a/rust/vendor/der-parser/tests/custom_error.rs b/rust/vendor/der-parser/tests/custom_error.rs
new file mode 100644
index 0000000..2281510
--- /dev/null
+++ b/rust/vendor/der-parser/tests/custom_error.rs
@@ -0,0 +1,53 @@
+//! This test file ensures the functions to parse containers like sequences and sets
+//! work correctly with custom errors.
+
+use der_parser::ber::{parse_ber_sequence_of_v, parse_ber_u32};
+use der_parser::error::BerError;
+use nom::error::{ErrorKind, ParseError};
+use nom::{Err, IResult};
+
+#[derive(Debug)]
+pub enum MyError<'a> {
+ Variant1,
+ Variant2,
+ BerError(BerError),
+ NomError(&'a [u8], ErrorKind),
+}
+
+impl<'a> ParseError<&'a [u8]> for MyError<'a> {
+ fn from_error_kind(input: &'a [u8], kind: ErrorKind) -> Self {
+ MyError::NomError(input, kind)
+ }
+
+ fn append(_input: &'a [u8], _kind: ErrorKind, other: Self) -> Self {
+ other
+ }
+}
+
+impl<'a> From<BerError> for MyError<'a> {
+ fn from(e: BerError) -> Self {
+ MyError::BerError(e)
+ }
+}
+
+#[test]
+fn parse_sequence_of_v_custom_errors() {
+ fn parse_element(i: &[u8]) -> IResult<&[u8], u32, MyError> {
+ // incomplete must *NOT* be mapped, or parse_ber_sequence_of_v cannot detect end of
+ // sequence
+ match parse_ber_u32(i) {
+ Ok(x) => Ok(x),
+ Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)),
+ _ => Err(Err::Error(MyError::Variant1)),
+ }
+ }
+
+ let bytes = [
+ 0x30, 0x0a, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x00,
+ ];
+
+ let (rem, v) =
+ parse_ber_sequence_of_v(parse_element)(&bytes).expect("Could not parse SEQUENCE OF");
+ assert!(rem.is_empty());
+ assert_eq!(&v, &[65537, 65536]);
+}
diff --git a/rust/vendor/der-parser/tests/der_constructed.rs b/rust/vendor/der-parser/tests/der_constructed.rs
new file mode 100644
index 0000000..d10adf0
--- /dev/null
+++ b/rust/vendor/der-parser/tests/der_constructed.rs
@@ -0,0 +1,177 @@
+// test_case seem to generate this warning - ignore it
+#![allow(clippy::unused_unit)]
+
+use der_parser::ber::Tag;
+use der_parser::der::*;
+use der_parser::error::*;
+use hex_literal::hex;
+use nom::combinator::map;
+use nom::error::ErrorKind;
+use nom::sequence::tuple;
+use nom::{Err, Needed};
+use test_case::test_case;
+
+#[test_case(&hex!("a2 05 02 03 01 00 01"), Ok(0x10001) ; "tag ok")]
+#[test_case(&hex!("a2 80 02 03 01 00 01 00 00"), Err(BerError::DerConstraintFailed(DerConstraint::IndefiniteLength)) ; "indefinite tag ok")]
+#[test_case(&hex!("a3 05 02 03 01 00 01"), Err(BerError::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+#[test_case(&hex!("22 05 02 03 01 00 01"), Err(BerError::unexpected_class(None, Class::Universal)) ; "invalid class")]
+#[test_case(&hex!("82 05 02 03 01 00 01"), Err(BerError::ConstructExpected) ; "construct expected")]
+fn tc_der_tagged_explicit_g(i: &[u8], out: Result<u32, BerError>) {
+ fn parse_int_explicit(i: &[u8]) -> BerResult<u32> {
+ parse_der_tagged_explicit_g(2, move |content, _hdr| {
+ let (rem, obj) = parse_der_integer(content)?;
+ let value = obj.as_u32()?;
+ Ok((rem, value))
+ })(i)
+ }
+ let res = parse_int_explicit(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!("82 03 01 00 01"), Ok(0x10001) ; "tag ok")]
+#[test_case(&hex!("83 03 01 00 01"), Err(BerError::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_der_tagged_implicit_g(i: &[u8], out: Result<u32, BerError>) {
+ fn parse_int_implicit(i: &[u8]) -> BerResult<u32> {
+ parse_der_tagged_implicit_g(2, |content, hdr, depth| {
+ let (rem, obj) = parse_der_content(Tag::Integer)(content, &hdr, depth)?;
+ let value = obj.as_u32()?;
+ Ok((rem, value))
+ })(i)
+ }
+ let res = parse_int_implicit(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!("30 00"), Ok(&[]) ; "empty seq")]
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "seq ok")]
+#[test_case(&hex!("30 07 02 03 01 00 01 02 03 01"), Err(BerError::NomError(ErrorKind::Eof)) ; "incomplete")]
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Err(BerError::unexpected_tag(Some(Tag::Sequence), Tag::Set)) ; "invalid tag")]
+#[test_case(&hex!("30 80 02 03 01 00 01 00 00"), Err(BerError::DerConstraintFailed(DerConstraint::IndefiniteLength)) ; "indefinite seq ok")]
+fn tc_der_seq_of(i: &[u8], out: Result<&[u32], BerError>) {
+ fn parser(i: &[u8]) -> BerResult {
+ parse_der_sequence_of(parse_der_integer)(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse sequence of");
+ assert!(rem.is_empty());
+ if let DerObjectContent::Sequence(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
+ }
+ }
+}
+
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "seq ok")]
+#[test_case(&hex!("30 07 02 03 01 00 01 02 01"), Err(Err::Incomplete(Needed::new(1))) ; "incomplete")]
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Err(Err::Error(BerError::unexpected_tag(Some(Tag::Sequence), Tag::Set))) ; "invalid tag")]
+#[test_case(&hex!("30 80 02 03 01 00 01 00 00"), Err(Err::Error(BerError::DerConstraintFailed(DerConstraint::IndefiniteLength))) ; "indefinite seq ok")]
+fn tc_der_seq_defined(i: &[u8], out: Result<&[u32], Err<BerError>>) {
+ fn parser(i: &[u8]) -> BerResult<DerObject> {
+ parse_der_sequence_defined(map(
+ tuple((parse_der_integer, parse_der_integer)),
+ |(a, b)| vec![a, b],
+ ))(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse sequence");
+ assert!(rem.is_empty());
+ if let DerObjectContent::Sequence(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
+
+#[test_case(&hex!("31 00"), Ok(&[]) ; "empty set")]
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "set ok")]
+#[test_case(&hex!("31 07 02 03 01 00 01 02 03 01"), Err(BerError::NomError(ErrorKind::Eof)) ; "incomplete")]
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Err(BerError::unexpected_tag(Some(Tag::Set), Tag::Sequence)) ; "invalid tag")]
+#[test_case(&hex!("31 80 02 03 01 00 01 00 00"), Err(BerError::DerConstraintFailed(DerConstraint::IndefiniteLength)) ; "indefinite set ok")]
+fn tc_der_set_of(i: &[u8], out: Result<&[u32], BerError>) {
+ fn parser(i: &[u8]) -> BerResult {
+ parse_der_set_of(parse_der_integer)(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse set of");
+ assert!(rem.is_empty());
+ if let DerObjectContent::Set(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
+ }
+ }
+}
+
+#[test_case(&hex!("31 0a 02 03 01 00 01 02 03 01 00 00"), Ok(&[0x10001, 0x10000]) ; "set ok")]
+#[test_case(&hex!("31 07 02 03 01 00 01 02 01"), Err(Err::Incomplete(Needed::new(1))) ; "incomplete")]
+#[test_case(&hex!("30 0a 02 03 01 00 01 02 03 01 00 00"), Err(Err::Error(BerError::unexpected_tag(Some(Tag::Set), Tag::Sequence))) ; "invalid tag")]
+#[test_case(&hex!("31 80 02 03 01 00 01 00 00"), Err(Err::Error(BerError::DerConstraintFailed(DerConstraint::IndefiniteLength))) ; "indefinite set ok")]
+fn tc_der_set_defined(i: &[u8], out: Result<&[u32], Err<BerError>>) {
+ fn parser(i: &[u8]) -> BerResult<DerObject> {
+ parse_der_set_defined(map(
+ tuple((parse_der_integer, parse_der_integer)),
+ |(a, b)| vec![a, b],
+ ))(i)
+ }
+ let res = parser(i);
+ match out {
+ Ok(l) => {
+ let (rem, res) = res.expect("could not parse set");
+ assert!(rem.is_empty());
+ if let DerObjectContent::Set(res) = res.content {
+ pretty_assertions::assert_eq!(res.len(), l.len());
+ for (a, b) in res.iter().zip(l.iter()) {
+ pretty_assertions::assert_eq!(a.as_u32().unwrap(), *b);
+ }
+ } else {
+ panic!("wrong type for parsed object");
+ }
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(e));
+ }
+ }
+}
diff --git a/rust/vendor/der-parser/tests/der_parser.rs b/rust/vendor/der-parser/tests/der_parser.rs
new file mode 100644
index 0000000..ef31c66
--- /dev/null
+++ b/rust/vendor/der-parser/tests/der_parser.rs
@@ -0,0 +1,628 @@
+// test_case seem to generate this warning - ignore it
+#![allow(clippy::unused_unit)]
+
+use asn1_rs::ASN1DateTime;
+use asn1_rs::ASN1TimeZone;
+use asn1_rs::Any;
+use der_parser::ber::*;
+use der_parser::der::*;
+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::sequence::tuple;
+use nom::Err;
+use pretty_assertions::assert_eq;
+use std::borrow::Cow;
+use test_case::test_case;
+
+#[test]
+fn test_der_bool() {
+ let empty = &b""[..];
+ let b_true = DerObject::from_obj(BerObjectContent::Boolean(true));
+ let b_false = DerObject::from_obj(BerObjectContent::Boolean(false));
+ assert_eq!(parse_der_bool(&[0x01, 0x01, 0x00]), Ok((empty, b_false)));
+ assert_eq!(parse_der_bool(&[0x01, 0x01, 0xff]), Ok((empty, b_true)));
+ assert_eq!(
+ parse_der_bool(&[0x01, 0x01, 0x7f]),
+ Err(Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::InvalidBoolean
+ )))
+ );
+}
+
+#[test]
+fn test_der_int() {
+ let empty = &b""[..];
+ let bytes = hex!("02 03 01 00 01");
+ let expected = DerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
+ assert_eq!(parse_der_integer(&bytes), Ok((empty, expected)));
+ let res = parse_der_u64(&bytes);
+ assert_eq!(res.expect("integer").1, 0x10001);
+ // wrong tag
+ let bytes = hex!("04 03 41 41 41");
+ let res = parse_der_integer(&bytes);
+ assert!(res.is_err());
+ let res = parse_der_u64(&bytes);
+ assert!(res.is_err());
+ // very long integer
+ let bytes = hex!("02 0b 40 41 02 03 04 05 06 07 08 09 0a");
+ let res = parse_der_integer(&bytes);
+ assert!(res.is_ok());
+ let res = parse_der_u64(&bytes);
+ assert!(res.is_err());
+}
+
+#[test]
+fn test_der_bitstring_primitive() {
+ let empty = &b""[..];
+ //
+ // correct DER encoding
+ //
+ let bytes = &[0x03, 0x04, 0x06, 0x6e, 0x5d, 0xc0];
+ let expected = DerObject::from_obj(BerObjectContent::BitString(
+ 6,
+ BitStringObject { data: &bytes[3..] },
+ ));
+ assert_eq!(parse_der_bitstring(bytes), Ok((empty, expected)));
+ //
+ // correct encoding, but wrong padding bits (not all set to 0)
+ //
+ let bytes = &[0x03, 0x04, 0x06, 0x6e, 0x5d, 0xe0];
+ assert_eq!(
+ parse_der_bitstring(bytes),
+ Err(Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::UnusedBitsNotZero
+ )))
+ );
+ // // XXX test disabled: the parser is laxist here, since *many* implementations do
+ // // XXX not respect this constraint!
+ // // long form of length (invalid, < 127)
+ // //
+ // let bytes = &[0x03, 0x81, 0x04, 0x06, 0x6e, 0x5d, 0xc0];
+ // assert_eq!(
+ // parse_der_bitstring(bytes),
+ // Err(Err::Error(BerError::DerConstraintFailed))
+ // );
+}
+
+#[test]
+fn test_der_bitstring_constructed() {
+ let bytes = &hex!("23 81 0c 03 03 00 0a 3b 03 05 04 5f 29 1c d0");
+ assert_eq!(
+ parse_der_bitstring(bytes),
+ Err(Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::Constructed
+ )))
+ );
+}
+
+#[test]
+fn test_der_indefinite_length() {
+ let bytes = &hex!("23 80 03 03 00 0a 3b 03 05 04 5f 29 1c d0 00 00");
+ assert_eq!(
+ parse_der_bitstring(bytes),
+ Err(Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::IndefiniteLength
+ )))
+ );
+}
+
+#[test]
+fn test_der_octetstring_primitive() {
+ let empty = &b""[..];
+ let bytes = [0x04, 0x05, 0x41, 0x41, 0x41, 0x41, 0x41];
+ let expected = DerObject::from_obj(BerObjectContent::OctetString(b"AAAAA"));
+ assert_eq!(parse_der_octetstring(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_null() {
+ let empty = &b""[..];
+ let expected = DerObject::from_obj(BerObjectContent::Null);
+ assert_eq!(parse_der_null(&[0x05, 0x00]), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_oid() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
+ ];
+ let expected = DerObject::from_obj(BerObjectContent::OID(
+ Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap(),
+ ));
+ assert_eq!(parse_der_oid(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_enum() {
+ let empty = &b""[..];
+ let expected = DerObject::from_obj(BerObjectContent::Enum(2));
+ assert_eq!(parse_der_enum(&[0x0a, 0x01, 0x02]), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_utf8string() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ ];
+ let expected = DerObject::from_obj(BerObjectContent::UTF8String("Some-State"));
+ assert_eq!(parse_der_utf8string(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_relativeoid() {
+ let empty = &b""[..];
+ let bytes = [0x0d, 0x04, 0xc2, 0x7b, 0x03, 0x02];
+ let expected = DerObject::from_obj(BerObjectContent::RelativeOID(
+ Oid::from_relative(&[8571, 3, 2]).unwrap(),
+ ));
+ assert_eq!(parse_der_relative_oid(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_seq() {
+ let empty = &b""[..];
+ let bytes = [0x30, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01];
+ let expected = DerObject::from_seq(vec![DerObject::from_int_slice(b"\x01\x00\x01")]);
+ assert_eq!(parse_der_sequence(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_set() {
+ let empty = &b""[..];
+ let bytes = [0x31, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01];
+ let expected = DerObject::from_set(vec![DerObject::from_int_slice(b"\x01\x00\x01")]);
+ assert_eq!(parse_der_set(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_seq_defined() {
+ 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"),
+ ]);
+ fn parser(i: &[u8]) -> DerResult {
+ 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)));
+}
+
+#[test]
+fn test_der_set_defined() {
+ 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"),
+ ]);
+ fn parser(i: &[u8]) -> DerResult {
+ 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)));
+}
+
+#[test]
+fn test_der_seq_of() {
+ 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"),
+ ]);
+ fn parser(i: &[u8]) -> DerResult {
+ parse_der_sequence_of(parse_der_integer)(i)
+ }
+ assert_eq!(parser(&bytes), Ok((empty, expected.clone())));
+ //
+ fn parser2(i: &[u8]) -> BerResult {
+ parse_ber_sequence_of(parse_der_integer)(i)
+ }
+ assert_eq!(parser2(&bytes), Ok((empty, expected)));
+}
+
+// extra bytes are simply ignored
+#[test]
+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(parse_der_integer)(i)
+ }
+ assert_eq!(
+ parser(&bytes),
+ Err(Err::Failure(BerError::unexpected_tag(Some(Tag(2)), Tag(0))))
+ );
+ //
+ fn parser2(i: &[u8]) -> BerResult<Vec<BerObject>> {
+ parse_ber_sequence_of_v(parse_der_integer)(i)
+ }
+ // eprintln!("trailing data");
+ assert_eq!(
+ parser2(&bytes),
+ Err(Err::Failure(BerError::unexpected_tag(Some(Tag(2)), Tag(0))))
+ );
+ let h = &hex!("30 06 02 03 01 00 01 02");
+ // eprintln!("remaining 02 at end (incomplete)");
+ assert_eq!(
+ parser2(h),
+ Err(Err::Error(BerError::NomError(ErrorKind::Eof)))
+ );
+}
+
+#[test]
+fn test_der_set_of() {
+ 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"),
+ ]);
+ fn parser(i: &[u8]) -> DerResult {
+ parse_der_set_of(parse_der_integer)(i)
+ }
+ assert_eq!(parser(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_utctime() {
+ let bytes = hex!("17 0b 39 32 30 35 32 31 32 33 34 32 5A FF");
+ let expected = DerObject::from_obj(BerObjectContent::UTCTime(ASN1DateTime::new(
+ 92,
+ 5,
+ 21,
+ 23,
+ 42,
+ 0,
+ None,
+ ASN1TimeZone::Z,
+ )));
+ assert_eq!(parse_der_utctime(&bytes), Ok((&[0xff][..], expected)));
+ // missing 'Z'
+ let bytes = hex!("17 0a 39 32 30 35 32 31 32 33 34 32");
+ let e = parse_der_utctime(&bytes).expect_err("expected error");
+ assert_eq!(
+ e,
+ Err::Error(BerError::DerConstraintFailed(
+ DerConstraint::MissingTimeZone
+ ))
+ );
+}
+
+#[test]
+fn test_der_generalizedtime() {
+ let empty = &b""[..];
+ let bytes = hex!("18 0D 31 39 39 32 30 35 32 31 32 33 34 32 5A");
+ let expected = DerObject::from_obj(BerObjectContent::GeneralizedTime(ASN1DateTime::new(
+ 1992,
+ 5,
+ 21,
+ 23,
+ 42,
+ 0,
+ None,
+ ASN1TimeZone::Z,
+ )));
+ assert_eq!(parse_der_generalizedtime(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_generalstring() {
+ let empty = &b""[..];
+ let bytes = [0x1b, 0x04, 0x63, 0x69, 0x66, 0x73];
+ let expected = DerObject::from_obj(BerObjectContent::GeneralString("cifs"));
+ assert_eq!(parse_der_generalstring(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_contextspecific() {
+ let bytes = [0xa0, 0x03, 0x02, 0x01, 0x02];
+ let empty = &b""[..];
+ let header = Header::new(Class::ContextSpecific, true, Tag(0), 3.into())
+ .with_raw_tag(Some(Cow::Borrowed(&[0xa0])));
+ let any = Any::new(header.clone(), &bytes[2..]);
+ let expected = DerObject {
+ header,
+ content: BerObjectContent::Unknown(any),
+ };
+ assert_eq!(parse_der(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_explicit_optional() {
+ let empty = &b""[..];
+ let bytes = [0xa0, 0x03, 0x02, 0x01, 0x02];
+ let header = Header::new(Class::ContextSpecific, true, Tag(0), 3.into())
+ .with_raw_tag(Some(Cow::Borrowed(&[0xa0])));
+ let expected = DerObject {
+ header: header.clone(),
+ content: BerObjectContent::Optional(Some(Box::new(BerObject::from_header_and_content(
+ header,
+ BerObjectContent::Tagged(
+ Class::ContextSpecific,
+ Tag(0),
+ Box::new(DerObject::from_int_slice(b"\x02")),
+ ),
+ )))),
+ };
+ assert_eq!(
+ parse_der_explicit_optional(&bytes, Tag(0), parse_der_integer),
+ Ok((empty, expected))
+ );
+ let expected2 = DerObject::from_obj(BerObjectContent::Optional(None));
+ assert_eq!(
+ parse_der_explicit_optional(&bytes, Tag(1), parse_der_integer),
+ Ok((&bytes[..], expected2))
+ );
+}
+
+#[test]
+fn test_der_implicit() {
+ let empty = &b""[..];
+ let bytes = [0x81, 0x04, 0x70, 0x61, 0x73, 0x73];
+ let expected = DerObject {
+ header: Header::new(Class::ContextSpecific, false, Tag(1), 4.into())
+ .with_raw_tag(Some(Cow::Borrowed(&[0x81]))),
+ content: BerObjectContent::IA5String("pass"),
+ };
+ fn der_read_ia5string_content<'a>(
+ i: &'a [u8],
+ hdr: &Header,
+ depth: usize,
+ ) -> BerResult<'a, BerObjectContent<'a>> {
+ ber_read_element_content_as(i, Tag::Ia5String, hdr.length(), hdr.is_constructed(), depth)
+ }
+ assert_eq!(
+ parse_der_implicit(&bytes, Tag(1), der_read_ia5string_content),
+ Ok((empty, expected))
+ );
+ assert_eq!(
+ parse_der_implicit(&bytes, Tag(2), der_read_ia5string_content),
+ Err(Err::Error(BerError::unexpected_tag(Some(Tag(2)), Tag(1))))
+ );
+}
+
+#[test]
+fn test_der_implicit_long_tag() {
+ let empty = &b""[..];
+ let bytes = [0x5f, 0x52, 0x04, 0x70, 0x61, 0x73, 0x73];
+ let expected = DerObject {
+ header: Header::new(Class::Application, false, Tag(0x52), 4.into())
+ .with_raw_tag(Some(Cow::Borrowed(&[0x5f, 0x52]))),
+ content: BerObjectContent::IA5String("pass"),
+ };
+ fn der_read_ia5string_content<'a>(
+ i: &'a [u8],
+ hdr: &Header,
+ depth: usize,
+ ) -> BerResult<'a, BerObjectContent<'a>> {
+ ber_read_element_content_as(i, Tag::Ia5String, hdr.length(), hdr.is_constructed(), depth)
+ }
+ assert_eq!(
+ parse_der_implicit(&bytes, Tag(0x52), der_read_ia5string_content),
+ Ok((empty, expected))
+ );
+ assert_eq!(
+ parse_der_implicit(&bytes, Tag(2), der_read_ia5string_content),
+ Err(Err::Error(BerError::unexpected_tag(
+ Some(Tag(2)),
+ Tag(0x52)
+ )))
+ );
+}
+
+#[test]
+fn test_der_optional() {
+ 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 = DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::Optional(Some(Box::new(
+ DerObject::from_obj(BerObjectContent::Enum(1)),
+ )))),
+ DerObject::from_int_slice(b"\x01\x00\x01"),
+ ]);
+ let expected2 = DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::Optional(None)),
+ DerObject::from_int_slice(b"\x01\x00\x01"),
+ ]);
+ fn parse_optional_enum(i: &[u8]) -> DerResult {
+ parse_ber_optional(parse_der_enum)(i)
+ }
+ fn parser(i: &[u8]) -> DerResult {
+ 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)));
+}
+
+#[test]
+fn test_der_seq_dn() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x52,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+ ];
+ let expected = DerObject::from_seq(vec![
+ DerObject::from_set(vec![DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::OID(Oid::from(&[2, 5, 4, 6]).unwrap())), // countryName
+ DerObject::from_obj(BerObjectContent::PrintableString("FR")),
+ ])]),
+ DerObject::from_set(vec![DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::OID(Oid::from(&[2, 5, 4, 8]).unwrap())), // stateOrProvinceName
+ DerObject::from_obj(BerObjectContent::UTF8String("Some-State")),
+ ])]),
+ DerObject::from_set(vec![DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::OID(Oid::from(&[2, 5, 4, 10]).unwrap())), // organizationName
+ DerObject::from_obj(BerObjectContent::UTF8String("Internet Widgits Pty Ltd")),
+ ])]),
+ ]);
+ assert_eq!(parse_der(&bytes), Ok((empty, expected)));
+}
+
+#[test]
+fn test_der_seq_dn_defined() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x46, 0x52,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65,
+ 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+ ];
+ let expected = DerObject::from_seq(vec![
+ DerObject::from_set(vec![DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::OID(Oid::from(&[2, 5, 4, 6]).unwrap())), // countryName
+ DerObject::from_obj(BerObjectContent::PrintableString("FR")),
+ ])]),
+ DerObject::from_set(vec![DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::OID(Oid::from(&[2, 5, 4, 8]).unwrap())), // stateOrProvinceName
+ DerObject::from_obj(BerObjectContent::UTF8String("Some-State")),
+ ])]),
+ DerObject::from_set(vec![DerObject::from_seq(vec![
+ DerObject::from_obj(BerObjectContent::OID(Oid::from(&[2, 5, 4, 10]).unwrap())), // organizationName
+ DerObject::from_obj(BerObjectContent::UTF8String("Internet Widgits Pty Ltd")),
+ ])]),
+ ]);
+ #[inline]
+ fn parse_directory_string(i: &[u8]) -> DerResult {
+ 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(
+ // 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_of(parse_attr_type_and_value)(i)
+ }
+ #[inline]
+ fn parse_name(i: &[u8]) -> DerResult {
+ parse_der_sequence_of(parse_rdn)(i)
+ }
+ assert_eq!(parse_name(&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")]
+#[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")]
+// XXX DER encoding is invalid (not minimal) in following test:
+// #[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(DerConstraint::IntegerLeadingZeroes)) ; "u32-long-leading-zeros")]
+#[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::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_der_u32(i: &[u8], out: Result<u32, BerError>) {
+ let res = parse_der_u32(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) ; "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")]
+#[test_case(&hex!("02 02 ff f0"), Err(BerError::DerConstraintFailed(DerConstraint::IntegerLeadingFF)) ; "i32-neg-leading-ff")]
+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 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 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::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_der_u64(i: &[u8], out: Result<u64, BerError>) {
+ let res = parse_der_u64(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]) ; "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")]
+#[test_case(&hex!("22 80 02 01 01 00 00"), Err(BerError::DerConstraintFailed(DerConstraint::IndefiniteLength)) ; "constructed slice")]
+#[test_case(&hex!("03 03 01 00 01"), Err(BerError::unexpected_tag(Some(Tag(2)), Tag(3))) ; "invalid tag")]
+fn tc_der_slice(i: &[u8], out: Result<&[u8], BerError>) {
+ let res = parse_der_slice(i, 2);
+ match out {
+ Ok(expected) => {
+ pretty_assertions::assert_eq!(res, Ok((&b""[..], expected)));
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
+ }
+ }
+}
diff --git a/rust/vendor/der-parser/tests/fuzz01.rs b/rust/vendor/der-parser/tests/fuzz01.rs
new file mode 100644
index 0000000..c971b56
--- /dev/null
+++ b/rust/vendor/der-parser/tests/fuzz01.rs
@@ -0,0 +1,5 @@
+#[test]
+fn test01() {
+ let data = b"\x03\x00\x00kk\x00\x00\x00\x00\x00\x00\x00.\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff;\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00\x00\x00\xff\x0a\xff";
+ let _ = der_parser::parse_der(data);
+}
diff --git a/rust/vendor/der-parser/tests/fuzz02.rs b/rust/vendor/der-parser/tests/fuzz02.rs
new file mode 100644
index 0000000..bea7c21
--- /dev/null
+++ b/rust/vendor/der-parser/tests/fuzz02.rs
@@ -0,0 +1,22 @@
+#[test]
+fn test02() {
+ let data = b"\x06\x00\x01\x00\x00\x2a";
+ let _ = der_parser::parse_der(data);
+}
+
+#[test]
+fn test03() {
+ let data = b"\x06\x0a*\xf1\x0a*\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe";
+ let _ = der_parser::parse_der(data);
+}
+
+#[test]
+fn test04() {
+ let data = &[
+ 0x50, 0x2a, 0xa, 0x8d, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xa, 0x0, 0xb, 0x22, 0x56, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf1, 0xa, 0x2a, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ ];
+ let _ = der_parser::parse_der(data);
+}
diff --git a/rust/vendor/der-parser/tests/oid.rs b/rust/vendor/der-parser/tests/oid.rs
new file mode 100644
index 0000000..3fa45c7
--- /dev/null
+++ b/rust/vendor/der-parser/tests/oid.rs
@@ -0,0 +1,25 @@
+//! Test the API provided to compare OIDs
+
+extern crate alloc;
+use der_parser::oid;
+use der_parser::oid::Oid;
+
+const OID_RSA_ENCRYPTION: &[u8] = &oid!(raw 1.2.840.113549.1.1.1);
+const OID_EC_PUBLIC_KEY: &[u8] = &oid!(raw 1.2.840.10045.2.1);
+#[allow(clippy::match_like_matches_macro)]
+fn compare_oid(oid: &Oid) -> bool {
+ match oid.as_bytes() {
+ OID_RSA_ENCRYPTION => true,
+ OID_EC_PUBLIC_KEY => true,
+ _ => false,
+ }
+}
+
+#[rustfmt::skip::macros(oid)]
+#[test]
+fn test_compare_oid() {
+ let oid = Oid::from(&[1, 2, 840, 113_549, 1, 1, 1]).unwrap();
+ assert_eq!(oid, oid!(1.2.840.113549.1.1.1));
+ let oid = Oid::from(&[1, 2, 840, 113_549, 1, 1, 1]).unwrap();
+ assert!(compare_oid(&oid));
+}
diff --git a/rust/vendor/der-parser/tests/primitive.rs b/rust/vendor/der-parser/tests/primitive.rs
new file mode 100644
index 0000000..2f3aecb
--- /dev/null
+++ b/rust/vendor/der-parser/tests/primitive.rs
@@ -0,0 +1,236 @@
+extern crate alloc;
+use std::borrow::Cow;
+
+use asn1_rs::Any;
+use der_parser::ber::*;
+use der_parser::der::*;
+use der_parser::error::*;
+use der_parser::oid::Oid;
+use hex_literal::hex;
+use nom::*;
+
+#[test]
+fn test_flat_take() {
+ let empty = &b""[..];
+ assert_eq!(
+ parse_ber_bool(&[0x01, 0x01, 0xff]),
+ Ok((empty, BerObject::from_obj(BerObjectContent::Boolean(true))))
+ );
+ assert_eq!(
+ parse_ber_bool(&[0x01, 0x01, 0x00]),
+ Ok((empty, BerObject::from_obj(BerObjectContent::Boolean(false))))
+ );
+ assert_eq!(
+ ber_read_element_content_as(&[0xff], Tag::Boolean, 0x01.into(), false, MAX_RECURSION),
+ Ok((empty, BerObjectContent::Boolean(true)))
+ );
+ assert_eq!(
+ ber_read_element_content_as(&[0x00], Tag::Boolean, 0x01.into(), false, MAX_RECURSION),
+ Ok((empty, BerObjectContent::Boolean(false)))
+ );
+}
+
+#[test]
+fn test_oid() {
+ let empty = &b""[..];
+ assert_eq!(
+ parse_der(&[0x06, 0x06, 42, 129, 122, 1, 16, 9]),
+ Ok((
+ empty,
+ BerObject::from_obj(BerObjectContent::OID(
+ Oid::from(&[1, 2, 250, 1, 16, 9]).unwrap()
+ ))
+ ))
+ );
+ // Dubuisson 433
+ assert_eq!(
+ parse_der(&[0x0d, 0x05, 129, 122, 1, 16, 9]),
+ Ok((
+ empty,
+ BerObject::from_obj(BerObjectContent::RelativeOID(
+ Oid::from_relative(&[250, 1, 16, 9]).unwrap()
+ ))
+ ))
+ );
+}
+
+#[test]
+fn test_rel_oid() {
+ let empty = &b""[..];
+ assert_eq!(
+ parse_der(&[0x0d, 0x04, 0xc2, 0x7b, 0x03, 0x02]),
+ Ok((
+ empty,
+ BerObject::from_obj(BerObjectContent::RelativeOID(
+ Oid::from_relative(&[8571, 3, 2]).unwrap()
+ ))
+ ))
+ );
+}
+
+#[rustfmt::skip::macros(oid)]
+#[test]
+fn test_oid_iter_length_check() {
+ use der_parser::oid;
+ use std::borrow::Cow;
+ // empty
+ assert!(Oid::new(Cow::Borrowed(&[])).iter().is_some());
+ assert!(Oid::new_relative(Cow::Borrowed(&[])).iter().is_some());
+ // ok
+ assert!(oid!(0).iter().is_some());
+ assert!(oid!(1.2).iter().is_some());
+ assert!(oid!(1.2.3456.23.54).iter().is_some());
+ // too long
+ assert!(oid!(1.2.18445618199572250625).iter().is_none());
+ assert!(oid!(rel 18445618199572250625).iter().is_none());
+}
+
+#[test]
+fn test_unknown_tag() {
+ let bytes = hex!("1d 01 00");
+ let res = parse_ber(&bytes).expect("parsing failed");
+ assert!(res.0.is_empty());
+ assert_eq!(
+ res.1,
+ BerObject::from_obj(BerObjectContent::Unknown(Any::from_tag_and_data(
+ Tag(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(Any::from_tag_and_data(
+ Tag(0x1d),
+ &bytes[2..]
+ )))
+ );
+}
+
+#[test]
+fn test_unknown_context_specific() {
+ let bytes = hex!("80 01 00");
+ let res = parse_ber(&bytes).expect("parsing failed");
+ assert!(res.0.is_empty());
+ assert_eq!(
+ res.1,
+ BerObject {
+ header: Header::new(Class::ContextSpecific, false, Tag(0), 1.into())
+ .with_raw_tag(Some(Cow::Borrowed(&[0x80]))),
+ content: BerObjectContent::Unknown(
+ Any::from_tag_and_data(Tag(0x0), &bytes[2..]).with_class(Class::ContextSpecific)
+ ),
+ }
+ );
+}
+
+#[test]
+fn test_unknown_long_tag() {
+ let bytes = hex!("9f 22 01 00");
+ let res = parse_ber(&bytes).expect("parsing failed");
+ assert!(res.0.is_empty());
+ assert_eq!(
+ res.1,
+ BerObject {
+ header: Header::new(Class::ContextSpecific, false, Tag(0x22), 1.into())
+ .with_raw_tag(Some(Cow::Borrowed(&[0x9f, 0x22]))),
+ content: BerObjectContent::Unknown(
+ Any::from_tag_and_data(Tag(0x22), &bytes[3..]).with_class(Class::ContextSpecific)
+ ),
+ }
+ );
+}
+
+#[test]
+fn test_unknown_longer_tag() {
+ let bytes = hex!("9f a2 22 01 00");
+ let res = parse_ber(&bytes).expect("parsing failed");
+ assert!(res.0.is_empty());
+ assert_eq!(
+ res.1,
+ BerObject {
+ header: Header::new(Class::ContextSpecific, false, Tag(0x1122), 1.into())
+ .with_raw_tag(Some(Cow::Borrowed(&[0x9f, 0xa2, 0x22]))),
+ content: BerObjectContent::Unknown(
+ Any::from_tag_and_data(Tag(0x1122), &bytes[4..]).with_class(Class::ContextSpecific)
+ ),
+ }
+ );
+}
+
+#[test]
+fn test_incomplete_tag() {
+ let bytes = hex!("9f a2 a2");
+ let res = parse_ber(&bytes);
+ assert!(res.is_err());
+}
+
+#[test]
+fn test_overflow_tag() {
+ let bytes = hex!("9f a2 a2 a2 a2 a2 22 01 00");
+ let res = parse_ber(&bytes);
+ assert!(res.is_err());
+}
+
+#[test]
+fn test_incomplete_length() {
+ let bytes = hex!("30");
+ let res = parse_ber(&bytes).err().expect("expected error");
+ assert_eq!(res, Err::Incomplete(Needed::new(1)));
+ let res = parse_der(&bytes).err().expect("expected error");
+ assert_eq!(res, Err::Incomplete(Needed::new(1)));
+ let bytes = hex!("02");
+ let res = parse_ber(&bytes).err().expect("expected error");
+ assert_eq!(res, Err::Incomplete(Needed::new(1)));
+ let bytes = hex!("02 05");
+ let _ = parse_ber(&bytes).err().expect("expected error");
+ let bytes = hex!("02 85");
+ let res = parse_ber(&bytes).err().expect("expected error");
+ assert_eq!(res, Err::Incomplete(Needed::new(5)));
+ let bytes = hex!("02 85 ff");
+ let res = parse_ber(&bytes).err().expect("expected error");
+ assert_eq!(res, Err::Incomplete(Needed::new(4)));
+}
+
+#[test]
+fn test_invalid_length() {
+ let bytes = hex!("02 ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10");
+ let _ = parse_ber(&bytes).err().expect("expected error");
+ let _ = ber_read_element_header(&bytes)
+ .err()
+ .expect("expected error");
+ //
+ let bytes = hex!("02 8a ff ff ff ff ff ff ff ff ff ff 00");
+ let res = parse_ber(&bytes).expect_err("parsing should have returned error");
+ assert_eq!(Err::Error(BerError::InvalidLength), res);
+ //
+ let bytes = hex!("02 ff 00");
+ let res = parse_ber(&bytes).expect_err("parsing should have returned error");
+ assert_eq!(Err::Error(BerError::InvalidLength), res);
+ //
+ let bytes = hex!("02 02 00");
+ let res = parse_der(&bytes).err().expect("expected error");
+ assert_eq!(res, Err::Incomplete(Needed::new(2)));
+}
+
+#[test]
+fn test_pretty_print() {
+ let bytes = hex!("01 01 ff");
+ let obj = parse_der(&bytes).map(|(_, b)| b).expect("expected error");
+ println!("{:?}", obj.as_pretty(0, 2));
+
+ // controlling the pretty-printer
+ let mut pp = obj.as_pretty(0, 4);
+ pp.set_flag(PrettyPrinterFlag::ShowHeader);
+ println!("{:?}", pp);
+}
+
+#[test]
+fn test_print_unexpected() {
+ let bytes = hex!("01 01 ff");
+ let nom_err = parse_der_integer(&bytes).expect_err("expected error");
+ nom_err.map(|e| eprintln!("{}", e));
+
+ eprintln!("{}", BerError::BerMaxDepth);
+}