summaryrefslogtreecommitdiffstats
path: root/rust/vendor/der-parser-6.0.1
diff options
context:
space:
mode:
Diffstat (limited to 'rust/vendor/der-parser-6.0.1')
-rw-r--r--rust/vendor/der-parser-6.0.1/.cargo-checksum.json1
-rw-r--r--rust/vendor/der-parser-6.0.1/CHANGELOG.md319
-rw-r--r--rust/vendor/der-parser-6.0.1/Cargo.toml65
-rw-r--r--rust/vendor/der-parser-6.0.1/LICENSE-APACHE201
-rw-r--r--rust/vendor/der-parser-6.0.1/LICENSE-MIT25
-rw-r--r--rust/vendor/der-parser-6.0.1/README.md244
-rw-r--r--rust/vendor/der-parser-6.0.1/UPGRADING.md101
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/ber.rs1174
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/integer.rs130
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/mod.rs69
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/multi.rs533
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/parser.rs1313
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/print.rs173
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/serialize.rs413
-rw-r--r--rust/vendor/der-parser-6.0.1/src/ber/tagged.rs262
-rw-r--r--rust/vendor/der-parser-6.0.1/src/der/mod.rs88
-rw-r--r--rust/vendor/der-parser-6.0.1/src/der/multi.rs535
-rw-r--r--rust/vendor/der-parser-6.0.1/src/der/parser.rs668
-rw-r--r--rust/vendor/der-parser-6.0.1/src/der/tagged.rs263
-rw-r--r--rust/vendor/der-parser-6.0.1/src/error.rs114
-rw-r--r--rust/vendor/der-parser-6.0.1/src/lib.rs294
-rw-r--r--rust/vendor/der-parser-6.0.1/src/oid.rs463
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/ber_parser.rs550
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/constructed.rs438
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/custom_error.rs53
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/der_constructed.rs173
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/der_parser.rs582
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/fuzz01.rs5
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/fuzz02.rs22
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/oid.rs25
-rw-r--r--rust/vendor/der-parser-6.0.1/tests/primitive.rs228
31 files changed, 9524 insertions, 0 deletions
diff --git a/rust/vendor/der-parser-6.0.1/.cargo-checksum.json b/rust/vendor/der-parser-6.0.1/.cargo-checksum.json
new file mode 100644
index 0000000..9c3841d
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"3525e594d2b397d7c1c9921871fe494c27d003b7b5c84459c1d881dbd2afe2f3","Cargo.toml":"f226a20732969e80e305eefd56c45157434b1626af9f1118ce14e0d1f531d0e9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"a5c61b93b6ee1d104af9920cf020ff3c7efe818e31fe562c72261847a728f513","README.md":"f11dfcb7f73a917e02e12398c416142ae1d3f6fdf94d9b4c0585a31e5122a5e8","UPGRADING.md":"0225b97be90b6a5323ce1697843efb27773c6e15edfae05935dd0dafcc0d3d88","src/ber/ber.rs":"6de5e67a1e2ab1e593f793c9fd8b1a6991ef728baa009867431d77d788996828","src/ber/integer.rs":"509cc8017ac90b0f0231be2e09dae80674460653521bbdda65622e04405ac010","src/ber/mod.rs":"6deb7bf5a82931816c749b4542232d8c00737d1afd303662784bf06f5b2b5dab","src/ber/multi.rs":"42c93d96215c38704918b31f92d30725f870dfd3d71c5bc036981c5a23cd462f","src/ber/parser.rs":"dc59e670105e58ef7254f34a42c13af98c766d66238f75b715240721a4ba77d7","src/ber/print.rs":"72eef562f72a5476610ba7c5bd79a9b468b5fc73fc19ea99e3cd00e21c30cd9a","src/ber/serialize.rs":"bb516e8e73a077b212ad2b4e16ab739ae90c8518bef5d15de9708abe1759387a","src/ber/tagged.rs":"380e74d9a5c347d453cc539f3cc4eca5125a42c86d42164452a37ac49563f162","src/der/mod.rs":"378cf1382be9bdbf824682985ebdd861298d9e38f2639efcc2d0f832e8f9a7af","src/der/multi.rs":"ff6bdba861f5eb1d186084b6b31a07224cc1f013dca58b8b7c586c50f86ea5bb","src/der/parser.rs":"8516566c2ca05c5f469924ec803658fa33624c4f783faa489408acdf6ce63dfa","src/der/tagged.rs":"2c25b88971e2b0d0b4c0d1db9d2cb9e149a347682f11fdea2692932c88da22e1","src/error.rs":"328516dbb0a7df2ed088f5ee2260636ac49345d31fc5b465d830606198476225","src/lib.rs":"4fa3dc08646c540db025f14e1d0649ce255fe56f976dd85248696f44e6dd1ae6","src/oid.rs":"e567aa4215b78aac9b0e8ab19e0342bdebae269d484d0f7c3d2104d224fbd5f8","tests/ber_parser.rs":"998cff869c91615e2f303498983669937e4c0545f16c7a69bb16a7050c3a0d8b","tests/constructed.rs":"0414c8cf65eb7b6340d87ce86c6d64c1a5b127598b4c67464a2900bd05f17953","tests/custom_error.rs":"8f92380a8b71df6033e15806c162bc502c6beea086ebed7c3106c76da71ec95b","tests/der_constructed.rs":"08e01714292e789260fed3bed2c2444e6dd38c5182401a55ed27c929b216a9a4","tests/der_parser.rs":"0c67e70eeb160725529e28f6e0771a2dabdc4c68cc830bd5f3ee116da80a702a","tests/fuzz01.rs":"b1929c8183fdba11ea73618ef48b23d4d3d39df79ac70e1c46787c3dcfcf9ec9","tests/fuzz02.rs":"b1e4ae20a40bb74887b7d62e9bbec5919f7c963b3f699e01888755e3637877a5","tests/oid.rs":"925d7317d9947a500128e5c707dd73fd2da8e29c25b48ea9174dfa719a8fe818","tests/primitive.rs":"124a252e140b08a1fb7fd1fe6d30181c9ebdf6aa730878af9da21a7f2066c9ce"},"package":"4cddf120f700b411b2b02ebeb7f04dc0b7c8835909a6c2f52bf72ed0dd3433b2"} \ No newline at end of file
diff --git a/rust/vendor/der-parser-6.0.1/CHANGELOG.md b/rust/vendor/der-parser-6.0.1/CHANGELOG.md
new file mode 100644
index 0000000..cba3b02
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/CHANGELOG.md
@@ -0,0 +1,319 @@
+# Change Log
+
+## [Unreleased][unreleased]
+
+### Changed/Fixed
+
+### Added
+
+### Thanks
+
+## 6.0.1
+
+### Changed/Fixed
+
+- Report number of missing bytes when having a complete header and incomplete data
+
+## 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-6.0.1/Cargo.toml b/rust/vendor/der-parser-6.0.1/Cargo.toml
new file mode 100644
index 0000000..c87704d
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/Cargo.toml
@@ -0,0 +1,65 @@
+# 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 = "6.0.1"
+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.bitvec]
+version = "0.22"
+optional = true
+
+[dependencies.cookie-factory]
+version = "0.3.0"
+optional = true
+
+[dependencies.der-oid-macro]
+version = "0.5"
+
+[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 = "1.0"
+
+[features]
+bigint = ["num-bigint"]
+default = ["std"]
+serialize = ["std", "cookie-factory"]
+std = []
+unstable = []
diff --git a/rust/vendor/der-parser-6.0.1/LICENSE-APACHE b/rust/vendor/der-parser-6.0.1/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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-6.0.1/LICENSE-MIT b/rust/vendor/der-parser-6.0.1/LICENSE-MIT
new file mode 100644
index 0000000..290e7b9
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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-6.0.1/README.md b/rust/vendor/der-parser-6.0.1/README.md
new file mode 100644
index 0000000..42f3ee4
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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/5.0.0/status.svg)](https://deps.rs/crate/der-parser/5.0.1)
+[![Github CI](https://github.com/rusticata/der-parser/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/der-parser/actions)
+[![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.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 6.0 series of `der-parser` requires **Rustc version 1.48 or greater**, based on 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-6.0.1/UPGRADING.md b/rust/vendor/der-parser-6.0.1/UPGRADING.md
new file mode 100644
index 0000000..e06b13f
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/UPGRADING.md
@@ -0,0 +1,101 @@
+## 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-6.0.1/src/ber/ber.rs b/rust/vendor/der-parser-6.0.1/src/ber/ber.rs
new file mode 100644
index 0000000..47d5069
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/ber/ber.rs
@@ -0,0 +1,1174 @@
+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;
+#[cfg(feature = "bitvec")]
+use bitvec::{order::Msb0, slice::BitSlice};
+use core::convert::AsRef;
+use core::convert::From;
+use core::convert::TryFrom;
+use core::fmt;
+use core::ops::Index;
+use rusticata_macros::newtype_enum;
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct BerClassFromIntError(pub(crate) ());
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct BerSizeError(pub(crate) ());
+
+/// BER Object class of tag
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[repr(u8)]
+pub enum BerClass {
+ Universal = 0b00,
+ Application = 0b01,
+ ContextSpecific = 0b10,
+ Private = 0b11,
+}
+
+/// Ber Object Length
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum BerSize {
+ /// Definite form (X.690 8.1.3.3)
+ Definite(usize),
+ /// Indefinite form (X.690 8.1.3.6)
+ Indefinite,
+}
+
+/// BER/DER Tag as defined in X.680 section 8.4
+///
+/// X.690 doesn't specify the maximum tag size so we're assuming that people
+/// aren't going to need anything more than a u32.
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct BerTag(pub u32);
+
+newtype_enum! {
+impl debug BerTag {
+ EndOfContent = 0x0,
+ Boolean = 0x1,
+ Integer = 0x2,
+ BitString = 0x3,
+ OctetString = 0x4,
+ Null = 0x05,
+ Oid = 0x06,
+ ObjDescriptor = 0x07,
+ External = 0x08,
+ RealType = 0x09,
+ Enumerated = 0xa,
+ EmbeddedPdv = 0xb,
+ Utf8String = 0xc,
+ RelativeOid = 0xd,
+
+ Sequence = 0x10,
+ Set = 0x11,
+ NumericString = 0x12,
+ PrintableString = 0x13,
+ T61String = 0x14,
+ VideotexString = 0x15,
+
+ Ia5String = 0x16,
+ UtcTime = 0x17,
+ GeneralizedTime = 0x18,
+
+ GraphicString = 25, // 0x19
+ VisibleString = 26, // 0x1a
+ GeneralString = 27, // 0x1b
+
+ UniversalString = 0x1c,
+ BmpString = 0x1e,
+
+ Invalid = 0xff,
+}
+}
+
+/// 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: BerObjectHeader<'a>,
+ pub content: BerObjectContent<'a>,
+}
+
+/// BER object header (identifier and length)
+#[derive(Clone, Debug)]
+pub struct BerObjectHeader<'a> {
+ /// Object class: universal, application, context-specific, or private
+ pub class: BerClass,
+ /// Constructed attribute: 1 if constructed, else 0
+ pub structured: u8,
+ /// Tag number
+ pub tag: BerTag,
+ /// Object length: definite or indefinite
+ pub len: BerSize,
+
+ /// Optionally, the raw encoding of the tag
+ ///
+ /// This is useful in some cases, where different representations of the same
+ /// BER tags have different meanings (BER only)
+ pub raw_tag: Option<&'a [u8]>,
+}
+
+/// 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: raw object bytes
+ T61String(&'a [u8]),
+ /// VideotexString: raw object bytes
+ VideotexString(&'a [u8]),
+
+ /// BmpString: raw object bytes
+ BmpString(&'a [u8]),
+ /// 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(&'a str),
+ /// GeneralizedTime: decoded string
+ GeneralizedTime(&'a str),
+
+ /// Object descriptor: raw object bytes
+ ObjectDescriptor(&'a [u8]),
+ /// GraphicString: raw object bytes
+ GraphicString(&'a [u8]),
+ /// GeneralString: raw object bytes
+ GeneralString(&'a [u8]),
+
+ /// Optional object
+ Optional(Option<Box<BerObject<'a>>>),
+ /// Tagged object (EXPLICIT): class, tag and content of inner object
+ Tagged(BerClass, BerTag, Box<BerObject<'a>>),
+ /// Private
+ Private(BerObjectHeader<'a>, &'a [u8]),
+
+ /// Unknown object: object tag (copied from header), and raw content
+ Unknown(BerClass, BerTag, &'a [u8]),
+}
+
+impl fmt::Display for BerClass {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let s = match self {
+ BerClass::Universal => "UNIVERSAL",
+ BerClass::Application => "APPLICATION",
+ BerClass::ContextSpecific => "CONTEXT-SPECIFIC",
+ BerClass::Private => "PRIVATE",
+ };
+ write!(f, "{}", s)
+ }
+}
+
+impl From<u32> for BerTag {
+ fn from(v: u32) -> Self {
+ BerTag(v)
+ }
+}
+
+impl BerSize {
+ /// Return true if length is definite and equal to 0
+ pub fn is_null(&self) -> bool {
+ *self == BerSize::Definite(0)
+ }
+
+ /// Get length of primitive object
+ #[inline]
+ pub fn primitive(&self) -> Result<usize, BerError> {
+ match self {
+ BerSize::Definite(sz) => Ok(*sz),
+ BerSize::Indefinite => Err(BerError::IndefiniteLengthUnexpected),
+ }
+ }
+}
+
+impl From<usize> for BerSize {
+ fn from(v: usize) -> Self {
+ BerSize::Definite(v)
+ }
+}
+
+impl TryFrom<u64> for BerSize {
+ type Error = BerSizeError;
+
+ fn try_from(value: u64) -> Result<Self, Self::Error> {
+ let v = usize::try_from(value).or(Err(BerSizeError(())))?;
+ Ok(BerSize::Definite(v))
+ }
+}
+
+impl TryFrom<BerSize> for usize {
+ type Error = BerSizeError;
+
+ #[inline]
+ fn try_from(value: BerSize) -> Result<Self, Self::Error> {
+ match value {
+ BerSize::Definite(sz) => Ok(sz),
+ BerSize::Indefinite => Err(BerSizeError(())),
+ }
+ }
+}
+
+impl TryFrom<u8> for BerClass {
+ type Error = BerClassFromIntError;
+
+ #[inline]
+ fn try_from(value: u8) -> Result<Self, Self::Error> {
+ match value {
+ 0b00 => Ok(BerClass::Universal),
+ 0b01 => Ok(BerClass::Application),
+ 0b10 => Ok(BerClass::ContextSpecific),
+ 0b11 => Ok(BerClass::Private),
+ _ => Err(BerClassFromIntError(())),
+ }
+ }
+}
+
+impl<'a> BerObjectHeader<'a> {
+ /// Build a new BER header
+ pub fn new<Len: Into<BerSize>>(class: BerClass, structured: u8, tag: BerTag, len: Len) -> Self {
+ BerObjectHeader {
+ tag,
+ structured,
+ class,
+ len: len.into(),
+ raw_tag: None,
+ }
+ }
+
+ /// Update header class
+ #[inline]
+ pub fn with_class(self, class: BerClass) -> Self {
+ BerObjectHeader { class, ..self }
+ }
+
+ /// Update header tag
+ #[inline]
+ pub fn with_tag(self, tag: BerTag) -> Self {
+ BerObjectHeader { tag, ..self }
+ }
+
+ /// Update header length
+ #[inline]
+ pub fn with_len(self, len: BerSize) -> Self {
+ BerObjectHeader { len, ..self }
+ }
+
+ /// Update header to add reference to raw tag
+ #[inline]
+ pub fn with_raw_tag(self, raw_tag: Option<&'a [u8]>) -> Self {
+ BerObjectHeader { raw_tag, ..self }
+ }
+
+ /// Test if object class is Universal
+ #[inline]
+ pub fn is_universal(&self) -> bool {
+ self.class == BerClass::Universal
+ }
+ /// Test if object class is Application
+ #[inline]
+ pub fn is_application(&self) -> bool {
+ self.class == BerClass::Application
+ }
+ /// Test if object class is Context-specific
+ #[inline]
+ pub fn is_contextspecific(&self) -> bool {
+ self.class == BerClass::ContextSpecific
+ }
+ /// Test if object class is Private
+ #[inline]
+ pub fn is_private(&self) -> bool {
+ self.class == BerClass::Private
+ }
+
+ /// Test if object is primitive
+ #[inline]
+ pub fn is_primitive(&self) -> bool {
+ self.structured == 0
+ }
+ /// Test if object is constructed
+ #[inline]
+ pub fn is_constructed(&self) -> bool {
+ self.structured == 1
+ }
+}
+
+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.
+ pub fn from_header_and_content<'o>(
+ header: BerObjectHeader<'o>,
+ content: BerObjectContent<'o>,
+ ) -> BerObject<'o> {
+ BerObject { header, content }
+ }
+
+ /// Build a BerObject from its content, using default flags (no class, correct tag,
+ /// and structured flag set only for Set and Sequence)
+ pub fn from_obj(c: BerObjectContent) -> BerObject {
+ let class = BerClass::Universal;
+ let tag = c.tag();
+ let structured = match tag {
+ BerTag::Sequence | BerTag::Set => 1,
+ _ => 0,
+ };
+ let header = BerObjectHeader::new(class, structured, tag, BerSize::Definite(0));
+ BerObject { header, content: c }
+ }
+
+ /// Build a DER integer object from a slice containing an encoded integer
+ pub fn from_int_slice(i: &'a [u8]) -> BerObject<'a> {
+ let header = BerObjectHeader::new(
+ BerClass::Universal,
+ 0,
+ BerTag::Integer,
+ BerSize::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 = BerObjectHeader {
+ raw_tag,
+ ..self.header
+ };
+ BerObject { header, ..self }
+ }
+
+ /// Build a DER sequence object from a vector of DER objects
+ pub 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 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(&'a 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(&'a self) -> Result<(BerClass, BerTag, &'_ 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(&'a 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 NumericString, VisibleString, UTCTime, GeneralizedTime,
+ /// PrintableString, UTF8String and IA5String 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()
+ }
+
+ /// Test if object class is Universal
+ pub fn is_universal(&self) -> bool {
+ self.header.class == BerClass::Universal
+ }
+ /// Test if object class is Application
+ pub fn is_application(&self) -> bool {
+ self.header.class == BerClass::Application
+ }
+ /// Test if object class is Context-specific
+ pub fn is_contextspecific(&self) -> bool {
+ self.header.class == BerClass::ContextSpecific
+ }
+ /// Test if object class is Private
+ pub fn is_private(&self) -> bool {
+ self.header.class == BerClass::Private
+ }
+
+ /// Test if object is primitive
+ pub fn is_primitive(&self) -> bool {
+ self.header.structured == 0
+ }
+ /// Test if object is constructed
+ pub fn is_constructed(&self) -> bool {
+ self.header.structured == 1
+ }
+}
+
+/// 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)
+ }
+}
+
+/// Compare two BER headers. `len` fields are compared only if both objects have it set (same for `raw_tag`)
+impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> {
+ fn eq(&self, other: &BerObjectHeader) -> bool {
+ self.class == other.class
+ && self.tag == other.tag
+ && self.structured == other.structured
+ && {
+ if self.len.is_null() && other.len.is_null() {
+ self.len == other.len
+ } else {
+ true
+ }
+ }
+ && {
+ // it tag is present for both, compare it
+ if self.raw_tag.xor(other.raw_tag).is_none() {
+ self.raw_tag == other.raw_tag
+ } else {
+ true
+ }
+ }
+ }
+}
+
+impl<'a> BerObjectContent<'a> {
+ /// Attempt to read a signed integer value from this object.
+ ///
+ /// This can fail if the object is not an integer, or if it is too large.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use der_parser::ber::BerObject;
+ /// let der_int = BerObject::from_int_slice(b"\x80");
+ /// assert_eq!(
+ /// der_int.as_i64(),
+ /// Ok(-128)
+ /// );
+ /// ```
+ pub fn as_i64(&self) -> Result<i64, BerError> {
+ if let BerObjectContent::Integer(bytes) = self {
+ let result = if is_highest_bit_set(bytes) {
+ <i64>::from_be_bytes(decode_array_int8(bytes)?)
+ } else {
+ <u64>::from_be_bytes(decode_array_uint8(bytes)?) as i64
+ };
+ Ok(result)
+ } else {
+ Err(BerError::InvalidTag)
+ }
+ }
+
+ /// Attempt to read a signed integer value from this object.
+ ///
+ /// This can fail if the object is not an integer, or if it is too large.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use der_parser::ber::BerObject;
+ /// let der_int = BerObject::from_int_slice(b"\x80");
+ /// assert_eq!(
+ /// der_int.as_i32(),
+ /// Ok(-128)
+ /// );
+ /// ```
+ pub fn as_i32(&self) -> Result<i32, BerError> {
+ if let BerObjectContent::Integer(bytes) = self {
+ let result = if is_highest_bit_set(bytes) {
+ <i32>::from_be_bytes(decode_array_int4(bytes)?)
+ } else {
+ <u32>::from_be_bytes(decode_array_uint4(bytes)?) as i32
+ };
+ Ok(result)
+ } else {
+ Err(BerError::InvalidTag)
+ }
+ }
+
+ /// Attempt to read integer value from this object.
+ ///
+ /// This can fail if the object is not an unsigned integer, or if it is too large.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// # use der_parser::ber::BerObject;
+ /// let der_int = BerObject::from_int_slice(b"\x01\x00\x01");
+ /// assert_eq!(
+ /// der_int.as_u64(),
+ /// Ok(0x10001)
+ /// );
+ /// ```
+ pub fn as_u64(&self) -> Result<u64, BerError> {
+ match self {
+ BerObjectContent::Integer(i) => {
+ let result = <u64>::from_be_bytes(decode_array_uint8(i)?);
+ Ok(result)
+ }
+ BerObjectContent::BitString(ignored_bits, data) => {
+ bitstring_to_u64(*ignored_bits as usize, data)
+ }
+ BerObjectContent::Enum(i) => Ok(*i as u64),
+ _ => 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(&'a 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(&'a self) -> Result<(BerClass, BerTag, &'_ 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(&'a 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::GeneralizedTime(s) |
+ BerObjectContent::UTCTime(s) |
+ BerObjectContent::VisibleString(s) |
+ BerObjectContent::PrintableString(s) |
+ BerObjectContent::UTF8String(s) |
+ BerObjectContent::IA5String(s) => Ok(s.as_ref()),
+ BerObjectContent::Integer(s) |
+ BerObjectContent::BitString(_,BitStringObject{data:s}) |
+ BerObjectContent::OctetString(s) |
+ BerObjectContent::T61String(s) |
+ BerObjectContent::VideotexString(s) |
+ BerObjectContent::BmpString(s) |
+ BerObjectContent::UniversalString(s) |
+ BerObjectContent::ObjectDescriptor(s) |
+ BerObjectContent::GraphicString(s) |
+ BerObjectContent::GeneralString(s) |
+ BerObjectContent::Unknown(_, _,s) |
+ BerObjectContent::Private(_,s) => Ok(s),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ #[rustfmt::skip]
+ pub fn as_str(&self) -> Result<&'a str,BerError> {
+ match *self {
+ BerObjectContent::NumericString(s) |
+ BerObjectContent::GeneralizedTime(s) |
+ BerObjectContent::UTCTime(s) |
+ BerObjectContent::VisibleString(s) |
+ BerObjectContent::PrintableString(s) |
+ BerObjectContent::UTF8String(s) |
+ BerObjectContent::IA5String(s) => Ok(s),
+ _ => Err(BerError::BerTypeError),
+ }
+ }
+
+ #[rustfmt::skip]
+ fn tag(&self) -> BerTag {
+ match self {
+ BerObjectContent::EndOfContent => BerTag::EndOfContent,
+ BerObjectContent::Boolean(_) => BerTag::Boolean,
+ BerObjectContent::Integer(_) => BerTag::Integer,
+ BerObjectContent::BitString(_,_) => BerTag::BitString,
+ BerObjectContent::OctetString(_) => BerTag::OctetString,
+ BerObjectContent::Null => BerTag::Null,
+ BerObjectContent::Enum(_) => BerTag::Enumerated,
+ BerObjectContent::OID(_) => BerTag::Oid,
+ BerObjectContent::NumericString(_) => BerTag::NumericString,
+ BerObjectContent::VisibleString(_) => BerTag::VisibleString,
+ BerObjectContent::PrintableString(_) => BerTag::PrintableString,
+ BerObjectContent::IA5String(_) => BerTag::Ia5String,
+ BerObjectContent::UTF8String(_) => BerTag::Utf8String,
+ BerObjectContent::RelativeOID(_) => BerTag::RelativeOid,
+ BerObjectContent::T61String(_) => BerTag::T61String,
+ BerObjectContent::VideotexString(_) => BerTag::VideotexString,
+ BerObjectContent::BmpString(_) => BerTag::BmpString,
+ BerObjectContent::UniversalString(_) => BerTag::UniversalString,
+ BerObjectContent::Sequence(_) => BerTag::Sequence,
+ BerObjectContent::Set(_) => BerTag::Set,
+ BerObjectContent::UTCTime(_) => BerTag::UtcTime,
+ BerObjectContent::GeneralizedTime(_) => BerTag::GeneralizedTime,
+ BerObjectContent::ObjectDescriptor(_) => BerTag::ObjDescriptor,
+ BerObjectContent::GraphicString(_) => BerTag::GraphicString,
+ BerObjectContent::GeneralString(_) => BerTag::GeneralString,
+ BerObjectContent::Tagged(_,x,_) |
+ BerObjectContent::Unknown(_, x,_) => *x,
+ &BerObjectContent::Private(ref hdr, _) => hdr.tag,
+ BerObjectContent::Optional(Some(obj)) => obj.content.tag(),
+ BerObjectContent::Optional(None) => BerTag(0x00), // XXX invalid !
+ }
+ }
+}
+
+#[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::InvalidTag),
+ }
+ }
+
+ /// 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::InvalidTag),
+ }
+ }
+}
+
+// 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 structured"),
+ }
+ // 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-6.0.1/src/ber/integer.rs b/rust/vendor/der-parser-6.0.1/src/ber/integer.rs
new file mode 100644
index 0000000..1c05bec
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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
+ .get(0)
+ .map(|byte| byte & 0b10000000 != 0)
+ .unwrap_or(false)
+}
diff --git a/rust/vendor/der-parser-6.0.1/src/ber/mod.rs b/rust/vendor/der-parser-6.0.1/src/ber/mod.rs
new file mode 100644
index 0000000..c674d93
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/ber/mod.rs
@@ -0,0 +1,69 @@
+//! 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;
+
+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::*;
+
+use alloc::borrow::Cow;
+use alloc::boxed::Box;
+use alloc::vec::Vec;
+use core::convert::{Into, TryFrom};
diff --git a/rust/vendor/der-parser-6.0.1/src/ber/multi.rs b/rust/vendor/der-parser-6.0.1/src/ber/multi.rs
new file mode 100644
index 0000000..dc030d2
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/ber/multi.rs
@@ -0,0 +1,533 @@
+use crate::ber::*;
+use crate::error::*;
+use nom::bytes::streaming::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], BerObjectHeader<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_ber_container(move |i, hdr| {
+ if hdr.tag != BerTag::Sequence {
+ return Err(Err::Error(BerError::InvalidTag.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], BerObjectHeader<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_ber_container(move |i, hdr| {
+ if hdr.tag != BerTag::Set {
+ return Err(Err::Error(BerError::InvalidTag.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 structured 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: BerObjectHeader| {
+/// if hdr.tag != BerTag::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], BerObjectHeader<'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.len {
+ BerSize::Definite(len) => take(len)(i)?,
+ BerSize::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-6.0.1/src/ber/parser.rs b/rust/vendor/der-parser-6.0.1/src/ber/parser.rs
new file mode 100644
index 0000000..24cbfc7
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/ber/parser.rs
@@ -0,0 +1,1313 @@
+use crate::ber::*;
+use crate::error::*;
+use crate::oid::*;
+use nom::bytes::streaming::take;
+use nom::combinator::{complete, map, verify};
+use nom::multi::{many0, many_till};
+use nom::number::streaming::be_u8;
+use nom::{Err, Needed, Offset};
+use rusticata_macros::{combinator::parse_hex_to_u64, custom_check};
+
+/// 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: &BerObjectHeader,
+ max_depth: usize,
+) -> BerResult<'a, bool> {
+ if max_depth == 0 {
+ return Err(Err::Error(BerError::BerMaxDepth));
+ }
+ match hdr.len {
+ BerSize::Definite(l) => {
+ if l == 0 && hdr.tag == BerTag::EndOfContent {
+ return Ok((i, true));
+ }
+ let (i, _) = take(l)(i)?;
+ Ok((i, false))
+ }
+ BerSize::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: &BerObjectHeader,
+ 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.len == BerSize::Indefinite {
+ let len = content.len();
+ assert!(len >= 2);
+ Ok((i, &content[..len - 2]))
+ } else {
+ Ok((i, content))
+ }
+}
+
+/// Try to parse input bytes as u64
+#[inline]
+pub(crate) fn bytes_to_u64(s: &[u8]) -> Result<u64, BerError> {
+ let mut u: u64 = 0;
+ for &c in s {
+ if u & 0xff00_0000_0000_0000 != 0 {
+ return Err(BerError::IntegerTooLarge);
+ }
+ u <<= 8;
+ u |= u64::from(c);
+ }
+ Ok(u)
+}
+
+/// 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)
+}
+
+pub(crate) fn parse_identifier(i: &[u8]) -> BerResult<(u8, u8, u32, &[u8])> {
+ if i.is_empty() {
+ Err(Err::Incomplete(Needed::new(1)))
+ } else {
+ let a = i[0] >> 6;
+ let b = if i[0] & 0b0010_0000 != 0 { 1 } else { 0 };
+ let mut c = u32::from(i[0] & 0b0001_1111);
+
+ let mut tag_byte_count = 1;
+
+ if c == 0x1f {
+ c = 0;
+ loop {
+ // Make sure we don't read past the end of our data.
+ custom_check!(i, tag_byte_count >= i.len(), BerError::InvalidTag)?;
+
+ // With tag defined as u32 the most we can fit in is four tag bytes.
+ // (X.690 doesn't actually specify maximum tag width.)
+ custom_check!(i, tag_byte_count > 5, BerError::InvalidTag)?;
+
+ c = (c << 7) | (u32::from(i[tag_byte_count]) & 0x7f);
+ let done = i[tag_byte_count] & 0x80 == 0;
+ tag_byte_count += 1;
+ if done {
+ break;
+ }
+ }
+ }
+
+ let (raw_tag, rem) = i.split_at(tag_byte_count);
+
+ Ok((rem, (a, b, c, raw_tag)))
+ }
+}
+
+/// Return the MSB and the rest of the first byte, or an error
+pub(crate) fn parse_ber_length_byte(i: &[u8]) -> BerResult<(u8, u8)> {
+ if i.is_empty() {
+ Err(Err::Incomplete(Needed::new(1)))
+ } else {
+ let a = i[0] >> 7;
+ let b = i[0] & 0b0111_1111;
+ Ok((&i[1..], (a, b)))
+ }
+}
+
+/// Read an object header
+///
+/// ### Example
+///
+/// ```
+/// # use der_parser::ber::{ber_read_element_header, BerClass, BerSize, BerTag};
+/// #
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (i, hdr) = ber_read_element_header(bytes).expect("could not read header");
+///
+/// assert_eq!(hdr.class, BerClass::Universal);
+/// assert_eq!(hdr.tag, BerTag::Integer);
+/// assert_eq!(hdr.len, BerSize::Definite(3));
+/// ```
+pub fn ber_read_element_header(i: &[u8]) -> BerResult<BerObjectHeader> {
+ let (i1, el) = parse_identifier(i)?;
+ let class = match BerClass::try_from(el.0) {
+ Ok(c) => c,
+ Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits
+ };
+ let (i2, len) = parse_ber_length_byte(i1)?;
+ let (i3, len) = match (len.0, len.1) {
+ (0, l1) => {
+ // Short form: MSB is 0, the rest encodes the length (which can be 0) (8.1.3.4)
+ (i2, BerSize::Definite(usize::from(l1)))
+ }
+ (_, 0) => {
+ // Indefinite form: MSB is 1, the rest is 0 (8.1.3.6)
+ // If encoding is primitive, definite form shall be used (8.1.3.2)
+ if el.1 == 0 {
+ return Err(Err::Error(BerError::ConstructExpected));
+ }
+ (i2, BerSize::Indefinite)
+ }
+ (_, l1) => {
+ // if len is 0xff -> error (8.1.3.5)
+ if l1 == 0b0111_1111 {
+ return Err(::nom::Err::Error(BerError::InvalidTag));
+ }
+ let (i3, llen) = take(l1)(i2)?;
+ match bytes_to_u64(llen) {
+ Ok(l) => {
+ let l =
+ usize::try_from(l).or(Err(::nom::Err::Error(BerError::InvalidLength)))?;
+ (i3, BerSize::Definite(l))
+ }
+ Err(_) => {
+ return Err(::nom::Err::Error(BerError::InvalidTag));
+ }
+ }
+ }
+ };
+ let hdr = BerObjectHeader::new(class, el.1, BerTag(el.2), len).with_raw_tag(Some(el.3));
+ Ok((i3, hdr))
+}
+
+#[allow(clippy::unnecessary_wraps)]
+#[inline]
+fn ber_read_content_eoc(i: &[u8]) -> BerResult<BerObjectContent> {
+ Ok((i, BerObjectContent::EndOfContent))
+}
+
+#[inline]
+fn ber_read_content_bool(i: &[u8]) -> BerResult<BerObjectContent> {
+ match be_u8(i) {
+ Ok((rem, 0)) => Ok((rem, BerObjectContent::Boolean(false))),
+ Ok((rem, _)) => Ok((rem, BerObjectContent::Boolean(true))),
+ Err(e) => Err(e),
+ }
+}
+
+#[inline]
+fn ber_read_content_integer(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::Integer)(i)
+}
+
+#[inline]
+fn ber_read_content_bitstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ custom_check!(i, len == 0, BerError::InvalidLength)?;
+
+ let (i, ignored_bits) = be_u8(i)?;
+ let (i, data) = take(len - 1)(i)?;
+ Ok((
+ i,
+ BerObjectContent::BitString(ignored_bits, BitStringObject { data }),
+ ))
+}
+
+#[inline]
+fn ber_read_content_octetstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::OctetString)(i)
+}
+
+#[allow(clippy::unnecessary_wraps)]
+#[inline]
+fn ber_read_content_null(i: &[u8]) -> BerResult<BerObjectContent> {
+ Ok((i, BerObjectContent::Null))
+}
+
+fn ber_read_content_oid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ custom_check!(i, len == 0, BerError::InvalidLength)?;
+
+ let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?;
+
+ let obj = BerObjectContent::OID(Oid::new(Cow::Borrowed(oid)));
+ Ok((i1, obj))
+}
+
+#[inline]
+fn ber_read_content_enum(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ let (rem, num) = parse_hex_to_u64(i, len).map_err(|_| BerError::BerValueError)?;
+ Ok((rem, BerObjectContent::Enum(num)))
+}
+
+fn ber_read_content_utf8string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ let (i, bytes) = take(len)(i)?;
+ let s = core::str::from_utf8(bytes)
+ .map_err(|_| Err::Error(BerError::StringInvalidCharset))
+ .map(BerObjectContent::UTF8String)?;
+ Ok((i, s))
+}
+
+fn ber_read_content_relativeoid(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ custom_check!(i, len == 0, BerError::InvalidLength)?;
+
+ let (i1, oid) = verify(take(len), |os: &[u8]| os.last().unwrap() >> 7 == 0u8)(i)?;
+
+ let obj = BerObjectContent::RelativeOID(Oid::new_relative(Cow::Borrowed(oid)));
+ Ok((i1, obj))
+}
+
+fn ber_read_content_sequence(
+ i: &[u8],
+ len: BerSize,
+ max_depth: usize,
+) -> BerResult<BerObjectContent> {
+ custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
+ match len {
+ BerSize::Definite(len) => {
+ let (i, data) = take(len)(i)?;
+ let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?;
+ // trailing bytes are ignored
+ Ok((i, BerObjectContent::Sequence(l)))
+ }
+ BerSize::Indefinite => {
+ // indefinite form
+ // read until end-of-content
+ let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?;
+ Ok((rem, BerObjectContent::Sequence(l)))
+ }
+ }
+}
+
+fn ber_read_content_set(i: &[u8], len: BerSize, max_depth: usize) -> BerResult<BerObjectContent> {
+ custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
+ match len {
+ BerSize::Definite(len) => {
+ let (i, data) = take(len)(i)?;
+ let (_, l) = many0(complete(r_parse_ber(max_depth - 1)))(data)?;
+ // trailing bytes are ignored
+ Ok((i, BerObjectContent::Set(l)))
+ }
+ BerSize::Indefinite => {
+ // indefinite form
+ // read until end-of-content
+ let (rem, (l, _)) = many_till(r_parse_ber(max_depth - 1), parse_ber_endofcontent)(i)?;
+ Ok((rem, BerObjectContent::Set(l)))
+ }
+ }
+}
+
+fn ber_read_content_numericstring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
+ // Argument must be a reference, because of the .iter().all(F) call below
+ #[allow(clippy::trivially_copy_pass_by_ref)]
+ fn is_numeric(b: &u8) -> bool {
+ matches!(*b, b'0'..=b'9' | b' ')
+ }
+ let (i, bytes) = take(len)(i)?;
+ if !bytes.iter().all(is_numeric) {
+ return Err(Err::Error(BerError::StringInvalidCharset));
+ }
+ let s = core::str::from_utf8(bytes)
+ .map_err(|_| Err::Error(BerError::StringInvalidCharset))
+ .map(BerObjectContent::NumericString)?;
+ Ok((i, s))
+}
+
+fn ber_read_content_visiblestring<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
+ // Argument must be a reference, because of the .iter().all(F) call below
+ #[allow(clippy::trivially_copy_pass_by_ref)]
+ fn is_visible(b: &u8) -> bool {
+ 0x20 <= *b && *b <= 0x7f
+ }
+ let (i, bytes) = take(len)(i)?;
+ if !bytes.iter().all(is_visible) {
+ return Err(Err::Error(BerError::StringInvalidCharset));
+ }
+ let s = core::str::from_utf8(bytes)
+ .map_err(|_| Err::Error(BerError::StringInvalidCharset))
+ .map(BerObjectContent::VisibleString)?;
+ Ok((i, s))
+}
+
+fn ber_read_content_printablestring<'a>(
+ i: &'a [u8],
+ len: usize,
+) -> BerResult<BerObjectContent<'a>> {
+ // Argument must be a reference, because of the .iter().all(F) call below
+ #[allow(clippy::trivially_copy_pass_by_ref)]
+ fn is_printable(b: &u8) -> bool {
+ matches!(*b,
+ b'a'..=b'z'
+ | b'A'..=b'Z'
+ | b'0'..=b'9'
+ | b' '
+ | b'\''
+ | b'('
+ | b')'
+ | b'+'
+ | b','
+ | b'-'
+ | b'.'
+ | b'/'
+ | b':'
+ | b'='
+ | b'?')
+ }
+ let (i, bytes) = take(len)(i)?;
+ if !bytes.iter().all(is_printable) {
+ return Err(Err::Error(BerError::StringInvalidCharset));
+ }
+ let s = core::str::from_utf8(bytes)
+ .map_err(|_| Err::Error(BerError::StringInvalidCharset))
+ .map(BerObjectContent::PrintableString)?;
+ Ok((i, s))
+}
+
+#[inline]
+fn ber_read_content_t61string(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::T61String)(i)
+}
+
+#[inline]
+fn ber_read_content_videotexstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::VideotexString)(i)
+}
+
+fn ber_read_content_ia5string<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
+ let (i, bytes) = take(len)(i)?;
+ if !bytes.iter().all(u8::is_ascii) {
+ return Err(Err::Error(BerError::StringInvalidCharset));
+ }
+ let s = core::str::from_utf8(bytes)
+ .map_err(|_| Err::Error(BerError::StringInvalidCharset))
+ .map(BerObjectContent::IA5String)?;
+ Ok((i, s))
+}
+
+fn ber_read_content_utctime<'a>(i: &'a [u8], len: usize) -> BerResult<BerObjectContent<'a>> {
+ // Argument must be a reference, because of the .iter().all(F) call below
+ #[allow(clippy::trivially_copy_pass_by_ref)]
+ fn is_visible(b: &u8) -> bool {
+ 0x20 <= *b && *b <= 0x7f
+ }
+ let (i, bytes) = take(len)(i)?;
+ if !bytes.iter().all(is_visible) {
+ return Err(Err::Error(BerError::StringInvalidCharset));
+ }
+ let s = core::str::from_utf8(bytes)
+ .map_err(|_| Err::Error(BerError::StringInvalidCharset))
+ .map(BerObjectContent::UTCTime)?;
+ Ok((i, s))
+}
+
+fn ber_read_content_generalizedtime<'a>(
+ i: &'a [u8],
+ len: usize,
+) -> BerResult<BerObjectContent<'a>> {
+ // Argument must be a reference, because of the .iter().all(F) call below
+ #[allow(clippy::trivially_copy_pass_by_ref)]
+ fn is_visible(b: &u8) -> bool {
+ 0x20 <= *b && *b <= 0x7f
+ }
+ let (i, bytes) = take(len)(i)?;
+ if !bytes.iter().all(is_visible) {
+ return Err(Err::Error(BerError::StringInvalidCharset));
+ }
+ let s = core::str::from_utf8(bytes)
+ .map_err(|_| Err::Error(BerError::StringInvalidCharset))
+ .map(BerObjectContent::GeneralizedTime)?;
+ Ok((i, s))
+}
+
+#[inline]
+fn ber_read_content_objectdescriptor(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::ObjectDescriptor)(i)
+}
+
+#[inline]
+fn ber_read_content_graphicstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::GraphicString)(i)
+}
+
+#[inline]
+fn ber_read_content_generalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::GeneralString)(i)
+}
+
+#[inline]
+fn ber_read_content_bmpstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::BmpString)(i)
+}
+
+#[inline]
+fn ber_read_content_universalstring(i: &[u8], len: usize) -> BerResult<BerObjectContent> {
+ map(take(len), BerObjectContent::UniversalString)(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, BerTag};
+/// #
+/// # 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.len, hdr.is_constructed(), 5
+/// ).expect("parsing failed");
+/// #
+/// # assert_eq!(hdr.tag, BerTag::Integer);
+/// # assert_eq!(content.as_u32(), Ok(0x10001));
+/// ```
+pub fn ber_read_element_content_as(
+ i: &[u8],
+ tag: BerTag,
+ len: BerSize,
+ constructed: bool,
+ max_depth: usize,
+) -> BerResult<BerObjectContent> {
+ if let BerSize::Definite(l) = len {
+ custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
+ if i.len() < l {
+ return Err(Err::Incomplete(Needed::new(l)));
+ }
+ }
+ match tag {
+ // 0x00 end-of-content
+ BerTag::EndOfContent => {
+ custom_check!(i, len != BerSize::Definite(0), BerError::InvalidLength)?;
+ ber_read_content_eoc(i)
+ }
+ // 0x01 bool
+ BerTag::Boolean => {
+ let len = len.primitive()?;
+ custom_check!(i, len != 1, BerError::InvalidLength)?;
+ ber_read_content_bool(i)
+ }
+ // 0x02
+ BerTag::Integer => {
+ custom_check!(i, constructed, BerError::ConstructUnexpected)?;
+ let len = len.primitive()?;
+ ber_read_content_integer(i, len)
+ }
+ // 0x03: bitstring
+ BerTag::BitString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.6.3)
+ let len = len.primitive()?;
+ ber_read_content_bitstring(i, len)
+ }
+ // 0x04: octetstring
+ BerTag::OctetString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.7.1)
+ let len = len.primitive()?;
+ ber_read_content_octetstring(i, len)
+ }
+ // 0x05: null
+ BerTag::Null => {
+ custom_check!(i, constructed, BerError::ConstructUnexpected)?;
+ let len = len.primitive()?;
+ custom_check!(i, len != 0, BerError::InvalidLength)?;
+ ber_read_content_null(i)
+ }
+ // 0x06: object identifier
+ BerTag::Oid => {
+ custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.19.1
+ let len = len.primitive()?;
+ ber_read_content_oid(i, len)
+ }
+ // 0x07: object descriptor - Alias for GraphicString with a different
+ // implicit tag, see below
+ BerTag::ObjDescriptor => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_objectdescriptor(i, len)
+ }
+ // 0x0a: enumerated
+ BerTag::Enumerated => {
+ custom_check!(i, constructed, BerError::ConstructUnexpected)?; // forbidden in 8.4
+ let len = len.primitive()?;
+ ber_read_content_enum(i, len)
+ }
+ // 0x0c: UTF8String - Unicode encoded with the UTF-8 charset (ISO/IEC
+ // 10646-1, Annex D)
+ BerTag::Utf8String => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_utf8string(i, len)
+ }
+ // 0x0d: relative object identified
+ BerTag::RelativeOid => {
+ custom_check!(i, constructed, BerError::ConstructUnexpected)?;
+ let len = len.primitive()?;
+ ber_read_content_relativeoid(i, len)
+ }
+ // 0x10: sequence
+ BerTag::Sequence => {
+ custom_check!(i, !constructed, BerError::ConstructExpected)?;
+ ber_read_content_sequence(i, len, max_depth)
+ }
+ // 0x11: set
+ BerTag::Set => {
+ custom_check!(i, !constructed, BerError::ConstructExpected)?;
+ ber_read_content_set(i, len, max_depth)
+ }
+ // 0x12: numericstring - ASCII string with digits an spaces only
+ BerTag::NumericString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_numericstring(i, len)
+ }
+ // 0x13: printablestring - ASCII string with certain printable
+ // characters only (specified in Table 10 of X.680)
+ BerTag::PrintableString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_printablestring(i, len)
+ }
+ // 0x14: t61string - ISO 2022 string with a Teletex (T.61) charset,
+ // ASCII is possible but only when explicit escaped, as by default
+ // the G0 character range (0x20-0x7f) will match the graphic character
+ // set. https://en.wikipedia.org/wiki/ITU_T.61
+ BerTag::T61String => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_t61string(i, len)
+ }
+ // 0x15: videotexstring - ISO 2022 string with a Videotex (T.100/T.101)
+ // charset, excluding ASCII. https://en.wikipedia.org/wiki/Videotex_character_set
+ BerTag::VideotexString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_videotexstring(i, len)
+ }
+ // 0x16: ia5string - ASCII string
+ BerTag::Ia5String => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_ia5string(i, len)
+ }
+ // 0x17: utctime - Alias for a VisibleString with a different implicit
+ // tag, see below
+ BerTag::UtcTime => {
+ let len = len.primitive()?;
+ ber_read_content_utctime(i, len)
+ }
+ // 0x18: generalizedtime - Alias for a VisibleString with a different
+ // implicit tag, see below
+ BerTag::GeneralizedTime => {
+ let len = len.primitive()?;
+ ber_read_content_generalizedtime(i, len)
+ }
+ // 0x19: graphicstring - Generic ISO 2022 container with explicit
+ // escape sequences, without control characters
+ BerTag::GraphicString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_graphicstring(i, len)
+ }
+ // 0x1a: visiblestring - ASCII string with no control characters except
+ // SPACE
+ BerTag::VisibleString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_visiblestring(i, len)
+ }
+ // 0x1b: generalstring - Generic ISO 2022 container with explicit
+ // escape sequences
+ BerTag::GeneralString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_generalstring(i, len)
+ }
+ // 0x1e: bmpstring - Unicode encoded with the UCS-2 big-endian charset
+ // (ISO/IEC 10646-1, section 13.1), restricted to the BMP (Basic
+ // Multilingual Plane) except certain control cahracters
+ BerTag::BmpString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_bmpstring(i, len)
+ }
+ // 0x1c: universalstring - Unicode encoded with the UCS-4 big-endian
+ // charset (ISO/IEC 10646-1, section 13.2)
+ BerTag::UniversalString => {
+ custom_check!(i, constructed, BerError::Unsupported)?; // XXX valid in BER (8.21)
+ let len = len.primitive()?;
+ ber_read_content_universalstring(i, len)
+ }
+ // all unknown values
+ _ => Err(Err::Error(BerError::UnknownTag)),
+ }
+}
+
+/// 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, BerTag::Integer);
+/// ```
+pub fn parse_ber_content<'a>(
+ tag: BerTag,
+) -> impl Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>> {
+ move |i: &[u8], hdr: &BerObjectHeader, max_recursion: usize| {
+ ber_read_element_content_as(i, tag, hdr.len, 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, BerTag::Integer);
+/// ```
+pub fn parse_ber_content2<'a>(
+ tag: BerTag,
+) -> impl Fn(&'a [u8], BerObjectHeader<'a>, usize) -> BerResult<'a, BerObjectContent<'a>> {
+ move |i: &[u8], hdr: BerObjectHeader, max_recursion: usize| {
+ ber_read_element_content_as(i, tag, hdr.len, 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::BerTag;
+/// use der_parser::ber::parse_ber_with_tag;
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_ber_with_tag(bytes, BerTag::Integer).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag, BerTag::Integer);
+/// ```
+pub fn parse_ber_with_tag<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult {
+ let tag = tag.into();
+ let (i, hdr) = ber_read_element_header(i)?;
+ if hdr.tag != tag {
+ return Err(nom::Err::Error(BerError::InvalidTag));
+ }
+ let (i, content) =
+ ber_read_element_content_as(i, hdr.tag, hdr.len, 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, BerTag::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, BerTag::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, BerTag::Integer)
+}
+
+/// Read an bitstring value
+#[inline]
+pub fn parse_ber_bitstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::BitString)
+}
+
+/// Read an octetstring value
+#[inline]
+pub fn parse_ber_octetstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::OctetString)
+}
+
+/// Read a null value
+#[inline]
+pub fn parse_ber_null(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::Null)
+}
+
+/// Read an object identifier value
+#[inline]
+pub fn parse_ber_oid(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::Oid)
+}
+
+/// Read an enumerated value
+#[inline]
+pub fn parse_ber_enum(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::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, BerTag::Utf8String)
+}
+
+/// Read a relative object identifier value
+#[inline]
+pub fn parse_ber_relative_oid(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::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 structured 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, BerTag::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 structured 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, BerTag::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, BerTag::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, BerTag::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, BerTag::PrintableString)
+}
+
+/// Read a T61 string value
+#[inline]
+pub fn parse_ber_t61string(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::T61String)
+}
+
+/// Read a Videotex string value
+#[inline]
+pub fn parse_ber_videotexstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::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, BerTag::Ia5String)
+}
+
+/// Read an UTC time value
+#[inline]
+pub fn parse_ber_utctime(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::UtcTime)
+}
+
+/// Read a Generalized time value
+#[inline]
+pub fn parse_ber_generalizedtime(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::GeneralizedTime)
+}
+
+/// Read an ObjectDescriptor value
+#[inline]
+pub fn parse_ber_objectdescriptor(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::ObjDescriptor)
+}
+
+/// Read a GraphicString value
+#[inline]
+pub fn parse_ber_graphicstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::GraphicString)
+}
+
+/// Read a GeneralString value
+#[inline]
+pub fn parse_ber_generalstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::GeneralString)
+}
+
+/// Read a BmpString value
+#[inline]
+pub fn parse_ber_bmpstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::BmpString)
+}
+
+/// Read a UniversalString value
+#[inline]
+pub fn parse_ber_universalstring(i: &[u8]) -> BerResult {
+ parse_ber_with_tag(i, BerTag::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: BerTag, 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(BerTag::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, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> BerResult<'a>
+where
+ F: Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>,
+ Tag: Into<BerTag>,
+{
+ 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, BerTag::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> {
+ let (rem, ber) = parse_ber_integer(i)?;
+ let int = ber.as_i32().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse BER object and try to decode it as a 64-bits signed integer
+///
+/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
+/// integer type.
+#[inline]
+pub fn parse_ber_i64(i: &[u8]) -> BerResult<i64> {
+ let (rem, ber) = parse_ber_integer(i)?;
+ let int = ber.as_i64().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse BER object and try to decode it as a 32-bits unsigned integer
+///
+/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
+/// integer type.
+#[inline]
+pub fn parse_ber_u32(i: &[u8]) -> BerResult<u32> {
+ let (rem, ber) = parse_ber_integer(i)?;
+ let int = ber.as_u32().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse BER 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> {
+ let (rem, ber) = parse_ber_integer(i)?;
+ let int = ber.as_u64().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse BER object and get content as slice
+#[inline]
+pub fn parse_ber_slice<Tag: Into<BerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]> {
+ let tag = tag.into();
+ parse_ber_container(move |content, hdr| {
+ if hdr.tag != tag {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ Ok((&b""[..], content))
+ })(i)
+}
+
+/// Helper combinator, to create a parser with a maximum parsing depth
+#[inline]
+pub(crate) fn r_parse_ber(max_depth: usize) -> impl Fn(&[u8]) -> BerResult {
+ move |i: &[u8]| parse_ber_recursive(i, max_depth)
+}
+
+/// 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, BerTag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_ber_recursive(bytes, 1).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag, BerTag::Integer);
+/// ```
+pub fn parse_ber_recursive(i: &[u8], max_depth: usize) -> BerResult {
+ custom_check!(i, max_depth == 0, BerError::BerMaxDepth)?;
+ let (rem, hdr) = ber_read_element_header(i)?;
+ if let BerSize::Definite(l) = hdr.len {
+ custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
+ }
+ match hdr.class {
+ BerClass::Universal => (),
+ BerClass::Private => {
+ let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
+ let content = BerObjectContent::Private(hdr.clone(), content);
+ let obj = BerObject::from_header_and_content(hdr, content);
+ return Ok((rem, obj));
+ }
+ _ => {
+ let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
+ let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
+ let obj = BerObject::from_header_and_content(hdr, content);
+ return Ok((rem, obj));
+ }
+ }
+ match ber_read_element_content_as(rem, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) {
+ Ok((rem, content)) => Ok((rem, BerObject::from_header_and_content(hdr, content))),
+ Err(Err::Error(BerError::UnknownTag)) => {
+ let (rem, content) = ber_get_object_content(rem, &hdr, max_depth)?;
+ let content = BerObjectContent::Unknown(hdr.class, hdr.tag, content);
+ let obj = BerObject::from_header_and_content(hdr, content);
+ Ok((rem, obj))
+ }
+ Err(e) => Err(e),
+ }
+}
+
+/// 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, BerTag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_ber(bytes).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag, BerTag::Integer);
+/// ```
+#[inline]
+pub fn parse_ber(i: &[u8]) -> BerResult {
+ parse_ber_recursive(i, MAX_RECURSION)
+}
+
+#[test]
+fn test_numericstring() {
+ assert_eq!(
+ ber_read_content_numericstring(b" 0123 4495768 ", 15),
+ Ok((
+ [].as_ref(),
+ BerObjectContent::NumericString(" 0123 4495768 ")
+ )),
+ );
+ assert_eq!(
+ ber_read_content_numericstring(b"", 0),
+ Ok(([].as_ref(), BerObjectContent::NumericString(""))),
+ );
+ assert!(ber_read_content_numericstring(b"123a", 4).is_err());
+}
+
+#[test]
+fn text_visiblestring() {
+ assert_eq!(
+ ber_read_content_visiblestring(b"AZaz]09 '()+,-./:=?", 19),
+ Ok((
+ [].as_ref(),
+ BerObjectContent::VisibleString("AZaz]09 '()+,-./:=?")
+ )),
+ );
+ assert_eq!(
+ ber_read_content_visiblestring(b"", 0),
+ Ok(([].as_ref(), BerObjectContent::VisibleString(""))),
+ );
+ assert!(ber_read_content_visiblestring(b"\n", 1).is_err());
+}
+
+#[test]
+fn test_printablestring() {
+ assert_eq!(
+ ber_read_content_printablestring(b"AZaz09 '()+,-./:=?", 18),
+ Ok((
+ [].as_ref(),
+ BerObjectContent::PrintableString("AZaz09 '()+,-./:=?")
+ )),
+ );
+ assert_eq!(
+ ber_read_content_printablestring(b"", 0),
+ Ok(([].as_ref(), BerObjectContent::PrintableString(""))),
+ );
+ assert!(ber_read_content_printablestring(b"]\n", 2).is_err());
+}
+
+#[test]
+fn test_ia5string() {
+ assert_eq!(
+ ber_read_content_ia5string(b"AZaz\n09 '()+,-./:=?[]{}\0\n", 25),
+ Ok((
+ [].as_ref(),
+ BerObjectContent::IA5String("AZaz\n09 '()+,-./:=?[]{}\0\n")
+ )),
+ );
+ assert_eq!(
+ ber_read_content_ia5string(b"", 0),
+ Ok(([].as_ref(), BerObjectContent::IA5String(""))),
+ );
+ assert!(ber_read_content_ia5string(b"\xFF", 1).is_err());
+}
+
+#[test]
+fn test_utf8string() {
+ assert_eq!(
+ ber_read_content_utf8string("AZaz09 '()+,-./:=?[]{}\0\nüÜ".as_ref(), 28),
+ Ok((
+ [].as_ref(),
+ BerObjectContent::UTF8String("AZaz09 '()+,-./:=?[]{}\0\nüÜ")
+ )),
+ );
+ assert_eq!(
+ ber_read_content_utf8string(b"", 0),
+ Ok(([].as_ref(), BerObjectContent::UTF8String(""))),
+ );
+ assert!(ber_read_content_utf8string(b"\xe2\x28\xa1", 3).is_err());
+}
+
+#[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-6.0.1/src/ber/print.rs b/rust/vendor/der-parser-6.0.1/src/ber/print.rs
new file mode 100644
index 0000000..e80eb5e
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/ber/print.rs
@@ -0,0 +1,173 @@
+use crate::ber::BitStringObject;
+use crate::ber::{BerObject, BerObjectContent, BerTag};
+use alloc::string::String;
+use alloc::vec::Vec;
+use core::fmt;
+use core::iter::FromIterator;
+use core::str;
+
+use rusticata_macros::debug;
+
+#[derive(Clone, Debug, PartialEq)]
+pub enum PrettyPrinterFlag {
+ ShowHeader,
+}
+
+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 {
+ obj: self,
+ indent,
+ inc: increment,
+
+ flags: Vec::new(),
+ }
+ }
+}
+
+impl<'a> PrettyBer<'a> {
+ pub fn set_flag(&mut self, flag: PrettyPrinterFlag) {
+ if !self.flags.contains(&flag) {
+ self.flags.push(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(),
+ }
+ }
+}
+
+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) {
+ write!(f, "[c:{:?}, s:{}, t:{}] ", self.obj.header.class, self.obj.header.structured, self.obj.header.tag)?;
+ };
+ fn print_utf8_string_with_type(f: &mut fmt::Formatter, s: &[u8], ty: &str) -> fmt::Result {
+ match str::from_utf8(s) {
+ Ok(b) => writeln!(f, "{}(\"{}\")", ty, b),
+ Err(e) => writeln!(f, "{}({:?}) <error decoding utf8 string: {:?}>", ty, s, e),
+ }
+ }
+ fn print_utf16_string_with_type(f: &mut fmt::Formatter, s: &[u8], ty: &str) -> fmt::Result {
+ let chars: Vec<u16> = s
+ .chunks_exact(2)
+ .map(|a| u16::from_be_bytes([a[0], a[1]]))
+ .collect();
+
+ match String::from_utf16(&chars) {
+ Ok(b) => writeln!(f, "{}(\"{}\")", ty, b),
+ Err(e) => writeln!(f, "{}({:?}) <error decoding utf16 string: {:?}>", ty, s, e),
+ }
+ }
+ 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 => writeln!(f, "EndOfContent"),
+ BerObjectContent::Boolean(b) => writeln!(f, "Boolean({:?})", b),
+ BerObjectContent::Integer(i) => writeln!(f, "Integer({:?})", debug::HexSlice(i)),
+ BerObjectContent::Enum(i) => writeln!(f, "Enum({})", i),
+ BerObjectContent::OID(ref v) => writeln!(f, "OID({:?})", v),
+ BerObjectContent::RelativeOID(ref v) => writeln!(f, "RelativeOID({:?})", v),
+ BerObjectContent::Null => writeln!(f, "Null"),
+ BerObjectContent::OctetString(v) => writeln!(f, "OctetString({:?})", debug::HexSlice(v)),
+ BerObjectContent::BitString(u,BitStringObject{data:v})
+ => writeln!(f, "BitString({},{:?})", u, debug::HexSlice(v)),
+ BerObjectContent::GeneralizedTime(s) => writeln!(f, "GeneralizedTime(\"{}\")", s),
+ BerObjectContent::UTCTime(s) => writeln!(f, "UTCTime(\"{}\")", s),
+ BerObjectContent::VisibleString(s) => writeln!(f, "VisibleString(\"{}\")", s),
+ BerObjectContent::PrintableString(s) => writeln!(f, "PrintableString(\"{}\")", s),
+ BerObjectContent::NumericString(s) => writeln!(f, "NumericString(\"{}\")", s),
+ BerObjectContent::UTF8String(s) => writeln!(f, "UTF8String(\"{}\")", s),
+ BerObjectContent::IA5String(s) => writeln!(f, "IA5String(\"{}\")", s),
+ BerObjectContent::T61String(v) => writeln!(f, "T61String({:?})", debug::HexSlice(v)),
+ BerObjectContent::VideotexString(v) => writeln!(f, "VideotexString({:?})", debug::HexSlice(v)),
+ BerObjectContent::BmpString(s) => print_utf16_string_with_type(f, s, "BmpString"),
+ BerObjectContent::UniversalString(s) => print_utf32_string_with_type(f, s, "UniversalString"),
+ BerObjectContent::ObjectDescriptor(s) => print_utf8_string_with_type(f, s, "ObjectDescriptor"),
+ BerObjectContent::GraphicString(s) => print_utf8_string_with_type(f, s, "GraphicString"),
+ BerObjectContent::GeneralString(s) => print_utf8_string_with_type(f, s, "GeneralString"),
+ BerObjectContent::Optional(ref o) => {
+ match o {
+ Some(obj) => writeln!(f, "OPTION {:?}", obj),
+ None => writeln!(f, "NONE"),
+ }
+ }
+ BerObjectContent::Private(ref hdr, bytes) => {
+ writeln!(f, "Private(c:{} s:{} t:{}): {:?}", hdr.class, hdr.structured, hdr.tag.0, debug::HexSlice(bytes))
+ },
+ BerObjectContent::Tagged(class, tag, ref obj) => {
+ writeln!(f, "ContextSpecific [{} {}] {{", class, tag)?;
+ write!(f, "{:?}", self.next_indent(obj))?;
+ if self.indent > 0 {
+ write!(f, "{:1$}", " ", self.indent)?;
+ };
+ writeln!(f, "}}")?;
+ Ok(())
+ },
+ BerObjectContent::Set(ref v) |
+ BerObjectContent::Sequence(ref v) => {
+ let ty = if self.obj.header.tag == BerTag::Sequence { "Sequence" } else { "Set" };
+ writeln!(f, "{}[", ty)?;
+ for o in v {
+ write!(f, "{:?}", self.next_indent(o))?;
+ };
+ if self.indent > 0 {
+ write!(f, "{:1$}", " ", self.indent)?;
+ };
+ writeln!(f, "]")?;
+ Ok(())
+ },
+ BerObjectContent::Unknown(class, tag,o) => writeln!(f, "Unknown({:?},{:?},{:x?})", class, tag, o),
+ }
+ }
+}
+
+#[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-6.0.1/src/ber/serialize.rs b/rust/vendor/der-parser-6.0.1/src/ber/serialize.rs
new file mode 100644
index 0000000..8c82e29
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/ber/serialize.rs
@@ -0,0 +1,413 @@
+#![cfg(feature = "std")]
+use crate::ber::*;
+use crate::oid::Oid;
+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<BerSize>>(len: Len) -> impl SerializeFn<W> + 'a {
+ let l = len.into();
+ move |out| {
+ match l {
+ BerSize::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 as u8), slice(v)))(out)
+ }
+ }
+ BerSize::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 BerObjectHeader,
+) -> impl SerializeFn<W> + 'a {
+ move |out| {
+ // identifier octets (X.690 8.1.2)
+ let class_u8 = (hdr.class as u8) << 6;
+ let pc_u8 = (hdr.structured & 1) << 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.len)))(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.bytes())(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: BerTag,
+ class: BerClass,
+ 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 = BerObjectHeader::new(class, 1 /* X.690 8.14.2 */, tag, len);
+ 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: BerTag,
+ class: BerClass,
+ 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 structured attribute)
+ let len = v.as_ref().len();
+ let hdr = BerObjectHeader::new(class, obj.header.structured, tag, len);
+ 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::NumericString(s)
+ | BerObjectContent::UTCTime(s)
+ | BerObjectContent::GeneralizedTime(s)
+ | BerObjectContent::VisibleString(s)
+ | BerObjectContent::PrintableString(s)
+ | BerObjectContent::IA5String(s)
+ | BerObjectContent::UTF8String(s) => slice(s)(out),
+ BerObjectContent::T61String(s)
+ | BerObjectContent::VideotexString(s)
+ | BerObjectContent::BmpString(s)
+ | BerObjectContent::UniversalString(s)
+ | BerObjectContent::ObjectDescriptor(s)
+ | BerObjectContent::GraphicString(s)
+ | BerObjectContent::GeneralString(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::Private(_hdr, bytes) => slice(bytes)(out),
+ BerObjectContent::Tagged(_class, _tag, inner) => {
+ // directly encode inner object
+ // XXX wrong, we should wrap it!
+ ber_encode_object(inner)(out)
+ }
+ BerObjectContent::Unknown(_, _, s) => slice(s)(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 BerObjectHeader,
+ 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_len(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, BerTag(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(BerTag(0), BerClass::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, BerTag(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: &BerObjectHeader,
+ depth: usize,
+ ) -> BerResult<'a, BerObjectContent<'a>> {
+ ber_read_element_content_as(i, BerTag::Integer, hdr.len, false, depth)
+ }
+ fn local_parse(i: &[u8]) -> BerResult<BerObject> {
+ parse_ber_implicit(i, BerTag(3), der_read_integer_content)
+ }
+ let obj = BerObject::from_int_slice(b"\x02");
+ let v = gen_simple(
+ ber_encode_tagged_implicit(BerTag(3), BerClass::ContextSpecific, &obj),
+ Vec::new(),
+ )
+ .expect("could not encode");
+ let (_, obj2) = local_parse(&v).expect("could not re-parse");
+ assert_eq!(obj2.header.tag, BerTag(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, BerTag(2), parse_ber_integer)
+ }
+ let obj = BerObject::from_int_slice(b"\x02");
+ let v = gen_simple(
+ ber_encode_tagged_explicit(BerTag(2), BerClass::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, BerTag(2));
+ assert_eq!(&obj, inner);
+ let bytes = hex!("62 03 02 01 02");
+ assert_eq!(&v[..], bytes);
+ }
+}
diff --git a/rust/vendor/der-parser-6.0.1/src/ber/tagged.rs b/rust/vendor/der-parser-6.0.1/src/ber/tagged.rs
new file mode 100644
index 0000000..84a9208
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/ber/tagged.rs
@@ -0,0 +1,262 @@
+use crate::ber::*;
+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_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, Tag, F>(tag: Tag, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult<BerObject>,
+ Tag: Into<BerTag>,
+{
+ 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, Tag, Output, F, E>(
+ tag: Tag,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Output, E>
+where
+ F: Fn(&'a [u8], BerObjectHeader<'a>) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ Tag: Into<BerTag>,
+{
+ let tag = tag.into();
+ parse_ber_container(move |i, hdr| {
+ if hdr.class == BerClass::Universal {
+ return Err(Err::Error(BerError::InvalidClass.into()));
+ }
+ if hdr.tag != tag {
+ return Err(Err::Error(BerError::InvalidTag.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_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(BerTag::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(BerTag::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, Tag, F>(tag: Tag, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8], &'_ BerObjectHeader, usize) -> BerResult<'a, BerObjectContent<'a>>,
+ Tag: Into<BerTag>,
+{
+ 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(BerTag::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(BerTag::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, Tag, Output, F, E>(
+ tag: Tag,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&[u8], Output, E>
+where
+ F: Fn(&'a [u8], BerObjectHeader<'a>, usize) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ Tag: Into<BerTag>,
+{
+ let tag = tag.into();
+ parse_ber_container(move |i, hdr| {
+ if hdr.tag != tag {
+ return Err(Err::Error(BerError::InvalidTag.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-6.0.1/src/der/mod.rs b/rust/vendor/der-parser-6.0.1/src/der/mod.rs
new file mode 100644
index 0000000..bad3f23
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/der/mod.rs
@@ -0,0 +1,88 @@
+//! 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::{BerClass, BerObject, BerObjectContent, BerObjectHeader, BerTag};
+
+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, TryFrom};
+
+/// DER Object class of tag (same as `BerClass`)
+pub type DerClass = BerClass;
+
+/// DER tag (same as BER tag)
+pub type DerTag = BerTag;
+
+/// 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`.
+pub type DerObjectHeader<'a> = BerObjectHeader<'a>;
+
+/// BER object content
+///
+/// This is the same object as `BerObjectContent`.
+pub type DerObjectContent<'a> = BerObjectContent<'a>;
diff --git a/rust/vendor/der-parser-6.0.1/src/der/multi.rs b/rust/vendor/der-parser-6.0.1/src/der/multi.rs
new file mode 100644
index 0000000..f4f22fa
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/der/multi.rs
@@ -0,0 +1,535 @@
+use crate::ber::BerSize;
+use crate::der::*;
+use crate::error::*;
+use nom::bytes::streaming::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], DerObjectHeader<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_der_container(move |i, hdr| {
+ if hdr.tag != DerTag::Sequence {
+ return Err(Err::Error(BerError::InvalidTag.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], DerObjectHeader<'a>) -> IResult<&'a [u8], O, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+{
+ parse_der_container(move |i, hdr| {
+ if hdr.tag != DerTag::Set {
+ return Err(Err::Error(BerError::InvalidTag.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 structured 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: DerObjectHeader| {
+/// if hdr.tag != DerTag::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], DerObjectHeader<'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.len {
+ BerSize::Definite(len) => take(len)(i)?,
+ BerSize::Indefinite => {
+ return Err(Err::Error(BerError::DerConstraintFailed.into()));
+ }
+ };
+ let (_rest, v) = f(data, hdr)?;
+ Ok((i, v))
+ }
+}
diff --git a/rust/vendor/der-parser-6.0.1/src/der/parser.rs b/rust/vendor/der-parser-6.0.1/src/der/parser.rs
new file mode 100644
index 0000000..04b4b23
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/der/parser.rs
@@ -0,0 +1,668 @@
+use crate::ber::*;
+use crate::der::*;
+use crate::error::*;
+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, DerTag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_der(bytes).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag, DerTag::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, DerTag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_der_recursive(bytes, 1).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag, DerTag::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 BerSize::Definite(l) = hdr.len {
+ custom_check!(i, l > MAX_OBJECT_SIZE, BerError::InvalidLength)?;
+ }
+ der_read_element_content_recursive(i, hdr, max_depth)
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! der_constraint_fail_if(
+ ($slice:expr, $cond:expr) => (
+ {
+ if $cond {
+ return Err(::nom::Err::Error(BerError::DerConstraintFailed));
+ }
+ }
+ );
+);
+
+/// 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, DerTag};
+///
+/// let bytes = &[0x02, 0x03, 0x01, 0x00, 0x01];
+/// let (_, obj) = parse_der_with_tag(bytes, DerTag::Integer).expect("parsing failed");
+///
+/// assert_eq!(obj.header.tag, DerTag::Integer);
+/// ```
+pub fn parse_der_with_tag<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> DerResult {
+ let tag = tag.into();
+ let (i, hdr) = der_read_element_header(i)?;
+ if hdr.tag != tag {
+ return Err(nom::Err::Error(BerError::InvalidTag));
+ }
+ let (i, content) =
+ der_read_element_content_as(i, hdr.tag, hdr.len, 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, DerTag::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, DerTag::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, DerTag::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, DerTag::BitString)
+}
+
+/// Read an octetstring value
+#[inline]
+pub fn parse_der_octetstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::OctetString)
+}
+
+/// Read a null value
+#[inline]
+pub fn parse_der_null(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::Null)
+}
+
+/// Read an object identifier value
+#[inline]
+pub fn parse_der_oid(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::Oid)
+}
+
+/// Read an enumerated value
+#[inline]
+pub fn parse_der_enum(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::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, DerTag::Utf8String)
+}
+
+/// Read a relative object identifier value
+#[inline]
+pub fn parse_der_relative_oid(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::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 structured 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, DerTag::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 structured 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, DerTag::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, DerTag::NumericString)
+}
+
+/// Read a printable string value. The content is verified to
+/// contain only the allowed characters.
+#[inline]
+pub fn visiblestring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::VisibleString)
+}
+
+/// 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, DerTag::PrintableString)
+}
+
+/// Read a T61 string value
+#[inline]
+pub fn parse_der_t61string(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::T61String)
+}
+
+/// Read a Videotex string value
+#[inline]
+pub fn parse_der_videotexstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::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, DerTag::Ia5String)
+}
+
+/// Read an UTC time value
+#[inline]
+pub fn parse_der_utctime(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::UtcTime)
+}
+
+/// Read a Generalized time value
+#[inline]
+pub fn parse_der_generalizedtime(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::GeneralizedTime)
+}
+
+/// Read a ObjectDescriptor value
+#[inline]
+pub fn parse_der_objectdescriptor(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::ObjDescriptor)
+}
+
+/// Read a GraphicString value
+#[inline]
+pub fn parse_der_graphicstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::GraphicString)
+}
+
+/// Read a GeneralString value
+#[inline]
+pub fn parse_der_generalstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::GeneralString)
+}
+
+/// Read a BmpString value
+#[inline]
+pub fn parse_der_bmpstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::BmpString)
+}
+
+/// Read a UniversalString value
+#[inline]
+pub fn parse_der_universalstring(i: &[u8]) -> DerResult {
+ parse_der_with_tag(i, DerTag::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: DerTag, 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(DerTag::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, Tag, F>(i: &'a [u8], tag: Tag, f: F) -> DerResult<'a>
+where
+ F: Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>>,
+ Tag: Into<DerTag>,
+{
+ parse_ber_implicit(i, tag, f)
+}
+
+/// Parse DER object and try to decode it as a 32-bits signed integer
+///
+/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
+/// integer type.
+#[inline]
+pub fn parse_der_i32(i: &[u8]) -> BerResult<i32> {
+ let (rem, der) = parse_der_integer(i)?;
+ let int = der.as_i32().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse DER object and try to decode it as a 64-bits signed integer
+///
+/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
+/// integer type.
+#[inline]
+pub fn parse_der_i64(i: &[u8]) -> BerResult<i64> {
+ let (rem, der) = parse_der_integer(i)?;
+ let int = der.as_i64().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse DER object and try to decode it as a 32-bits unsigned integer
+///
+/// Return `IntegerTooLarge` if object is an integer, but can not be represented in the target
+/// integer type.
+pub fn parse_der_u32(i: &[u8]) -> BerResult<u32> {
+ let (rem, der) = parse_der_integer(i)?;
+ let int = der.as_u32().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse DER 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> {
+ let (rem, der) = parse_der_integer(i)?;
+ let int = der.as_u64().map_err(nom::Err::Error)?;
+ Ok((rem, int))
+}
+
+/// Parse DER object and get content as slice
+#[inline]
+pub fn parse_der_slice<Tag: Into<DerTag>>(i: &[u8], tag: Tag) -> BerResult<&[u8]> {
+ let tag = tag.into();
+ parse_der_container(move |content, hdr| {
+ if hdr.tag != tag {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ 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, DerTag::Integer);
+/// ```
+pub fn parse_der_content<'a>(
+ tag: DerTag,
+) -> impl Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>> {
+ move |i: &[u8], hdr: &DerObjectHeader, max_recursion: usize| {
+ der_read_element_content_as(i, tag, hdr.len, 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, DerTag::Integer);
+/// let (rem, content) = parse_der_content2(header.tag)(i, header, MAX_RECURSION)
+/// .expect("parsing failed");
+/// ```
+pub fn parse_der_content2<'a>(
+ tag: DerTag,
+) -> impl Fn(&'a [u8], DerObjectHeader<'a>, usize) -> BerResult<'a, DerObjectContent<'a>> {
+ move |i: &[u8], hdr: DerObjectHeader, max_recursion: usize| {
+ der_read_element_content_as(i, tag, hdr.len, 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: DerTag,
+ len: BerSize,
+ constructed: bool,
+ max_depth: usize,
+) -> BerResult<DerObjectContent> {
+ // Indefinite lengths are not allowed in DER (X.690 section 10.1)
+ let l = len.primitive()?;
+ if i.len() < l {
+ return Err(Err::Incomplete(Needed::new(l)));
+ }
+ match tag {
+ DerTag::Boolean => {
+ custom_check!(i, l != 1, BerError::InvalidLength)?;
+ der_constraint_fail_if!(i, i[0] != 0 && i[0] != 0xff);
+ }
+ DerTag::BitString => {
+ der_constraint_fail_if!(i, constructed);
+ // exception: read and verify padding bits
+ return der_read_content_bitstring(i, l);
+ }
+ DerTag::Integer => {
+ // verify leading zeros
+ match i[..l] {
+ [] => return Err(nom::Err::Error(BerError::DerConstraintFailed)),
+ [0, 0, ..] => return Err(nom::Err::Error(BerError::DerConstraintFailed)),
+ [0, byte, ..] if byte < 0x80 => {
+ return Err(nom::Err::Error(BerError::DerConstraintFailed));
+ }
+ _ => (),
+ }
+ }
+ DerTag::NumericString
+ | DerTag::VisibleString
+ | DerTag::PrintableString
+ | DerTag::Ia5String
+ | DerTag::Utf8String
+ | DerTag::T61String
+ | DerTag::VideotexString
+ | DerTag::BmpString
+ | DerTag::UniversalString
+ | DerTag::ObjDescriptor
+ | DerTag::GraphicString
+ | DerTag::GeneralString => {
+ der_constraint_fail_if!(i, constructed);
+ }
+ DerTag::UtcTime | DerTag::GeneralizedTime => {
+ if l == 0 || i.get(l - 1).cloned() != Some(b'Z') {
+ return Err(Err::Error(BerError::DerConstraintFailed));
+ }
+ }
+ _ => (),
+ }
+ ber_read_element_content_as(i, tag, len, 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: DerObjectHeader<'a>) -> DerResult<'a> {
+ der_read_element_content_recursive(i, hdr, MAX_RECURSION)
+}
+
+fn der_read_element_content_recursive<'a>(
+ i: &'a [u8],
+ hdr: DerObjectHeader<'a>,
+ max_depth: usize,
+) -> DerResult<'a> {
+ match hdr.class {
+ BerClass::Universal => (),
+ BerClass::Private => {
+ let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?;
+ let content = BerObjectContent::Private(hdr.clone(), content);
+ let obj = BerObject::from_header_and_content(hdr, content);
+ return Ok((rem, obj));
+ }
+ _ => {
+ let (i, content) = ber_get_object_content(i, &hdr, max_depth)?;
+ let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content);
+ let obj = DerObject::from_header_and_content(hdr, content);
+ return Ok((i, obj));
+ }
+ }
+ match der_read_element_content_as(i, hdr.tag, hdr.len, hdr.is_constructed(), max_depth) {
+ Ok((rem, content)) => Ok((rem, DerObject::from_header_and_content(hdr, content))),
+ Err(Err::Error(BerError::UnknownTag)) => {
+ let (rem, content) = ber_get_object_content(i, &hdr, max_depth)?;
+ let content = DerObjectContent::Unknown(hdr.class, hdr.tag, content);
+ 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::DerConstraintFailed));
+ }
+ 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);
+ 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)
+pub fn der_read_element_header(i: &[u8]) -> BerResult<DerObjectHeader> {
+ let (i1, el) = parse_identifier(i)?;
+ let class = match DerClass::try_from(el.0) {
+ Ok(c) => c,
+ Err(_) => unreachable!(), // Cannot fail, we have read exactly 2 bits
+ };
+ let (i2, len) = parse_ber_length_byte(i1)?;
+ let (i3, len) = match (len.0, len.1) {
+ (0, l1) => {
+ // Short form: MSB is 0, the rest encodes the length (which can be 0) (8.1.3.4)
+ (i2, BerSize::Definite(usize::from(l1)))
+ }
+ (_, 0) => {
+ // Indefinite form is not allowed in DER (10.1)
+ return Err(::nom::Err::Error(BerError::DerConstraintFailed));
+ }
+ (_, l1) => {
+ // if len is 0xff -> error (8.1.3.5)
+ if l1 == 0b0111_1111 {
+ return Err(::nom::Err::Error(BerError::InvalidTag));
+ }
+ // DER(9.1) if len is 0 (indefinite form), obj must be constructed
+ der_constraint_fail_if!(&i[1..], len.1 == 0 && el.1 != 1);
+ let (i3, llen) = take(l1)(i2)?;
+ match bytes_to_u64(llen) {
+ Ok(l) => {
+ // DER: should have been encoded in short form (< 127)
+ der_constraint_fail_if!(i, l < 127);
+ let l =
+ usize::try_from(l).or(Err(::nom::Err::Error(BerError::InvalidLength)))?;
+ (i3, BerSize::Definite(l))
+ }
+ Err(_) => {
+ return Err(::nom::Err::Error(BerError::InvalidTag));
+ }
+ }
+ }
+ };
+ let hdr = DerObjectHeader::new(class, el.1, BerTag(el.2), len).with_raw_tag(Some(el.3));
+ Ok((i3, hdr))
+}
diff --git a/rust/vendor/der-parser-6.0.1/src/der/tagged.rs b/rust/vendor/der-parser-6.0.1/src/der/tagged.rs
new file mode 100644
index 0000000..c7d0fec
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/der/tagged.rs
@@ -0,0 +1,263 @@
+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, Tag, F>(tag: Tag, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8]) -> BerResult<DerObject>,
+ Tag: Into<DerTag>,
+{
+ 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, Tag, Output, F, E>(
+ tag: Tag,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], Output, E>
+where
+ F: Fn(&'a [u8], DerObjectHeader<'a>) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ Tag: Into<DerTag>,
+{
+ let tag = tag.into();
+ parse_der_container(move |i, hdr| {
+ if hdr.class == DerClass::Universal {
+ return Err(Err::Error(BerError::InvalidClass.into()));
+ }
+ if hdr.tag != tag {
+ return Err(Err::Error(BerError::InvalidTag.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(DerTag::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(DerTag::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, Tag, F>(tag: Tag, f: F) -> impl FnMut(&'a [u8]) -> BerResult
+where
+ F: Fn(&'a [u8], &'_ DerObjectHeader, usize) -> BerResult<'a, DerObjectContent<'a>>,
+ Tag: Into<DerTag>,
+{
+ 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(DerTag::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(DerTag::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, Tag, Output, F, E>(
+ tag: Tag,
+ f: F,
+) -> impl FnMut(&'a [u8]) -> IResult<&[u8], Output, E>
+where
+ F: Fn(&'a [u8], DerObjectHeader<'a>, usize) -> IResult<&'a [u8], Output, E>,
+ E: ParseError<&'a [u8]> + From<BerError>,
+ Tag: Into<DerTag>,
+{
+ let tag = tag.into();
+ parse_der_container(move |i, hdr| {
+ if hdr.tag != tag {
+ return Err(Err::Error(BerError::InvalidTag.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-6.0.1/src/error.rs b/rust/vendor/der-parser-6.0.1/src/error.rs
new file mode 100644
index 0000000..8a496a8
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/error.rs
@@ -0,0 +1,114 @@
+//! Error type for BER/DER parsers
+
+use crate::ber::BerObject;
+use crate::der::DerObject;
+use alloc::fmt;
+use nom::error::{ErrorKind, FromExternalError, ParseError};
+use nom::IResult;
+
+/// 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>>;
+
+/// Error for BER/DER parsers
+#[derive(Debug, PartialEq, Copy, Clone)]
+pub enum BerError {
+ /// BER object does not have the expected type
+ BerTypeError,
+ /// BER object does not have the expected value
+ BerValueError,
+
+ InvalidTag,
+ InvalidClass,
+ InvalidLength,
+
+ IndefiniteLengthUnexpected,
+
+ /// DER object was expected to be constructed (and found to be primitive)
+ ConstructExpected,
+ /// DER object was expected to be primitive (and found to be constructed)
+ ConstructUnexpected,
+
+ /// BER string has characters forbidden in standard
+ StringInvalidCharset,
+
+ /// BER integer is too large to fit in a native type. Use `as_bigint()`
+ IntegerTooLarge,
+ /// BER integer is negative, while an unsigned integer was requested
+ IntegerNegative,
+
+ /// BER recursive parsing reached maximum depth (See
+ /// [MAX_RECURSION](../ber/constant.MAX_RECURSION.html))
+ BerMaxDepth,
+
+ /// When parsing a defined sequence, some items could not be found
+ ObjectTooShort,
+
+ /// A DER constraint failed (object may be using BER encoding?)
+ DerConstraintFailed,
+
+ UnknownTag,
+ /// Feature is not yet implemented
+ Unsupported,
+
+ /// Custom error type left for parsers on top of this crate, so they can handle their custom
+ /// errors
+ Custom(u32),
+
+ /// Error raised by the underlying nom parser
+ NomError(ErrorKind),
+}
+
+impl From<BerError> for nom::Err<BerError> {
+ fn from(e: BerError) -> nom::Err<BerError> {
+ nom::Err::Error(e)
+ }
+}
+
+impl<I> ParseError<I> for BerError {
+ fn from_error_kind(_input: I, kind: ErrorKind) -> Self {
+ BerError::NomError(kind)
+ }
+ fn append(_input: I, kind: ErrorKind, _other: Self) -> Self {
+ BerError::NomError(kind)
+ }
+}
+
+impl<I, E> FromExternalError<I, E> for BerError {
+ fn from_external_error(_input: I, kind: ErrorKind, _e: E) -> BerError {
+ BerError::NomError(kind)
+ }
+}
+
+impl fmt::Display for BerError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for BerError {}
+
+#[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-6.0.1/src/lib.rs b/rust/vendor/der-parser-6.0.1/src/lib.rs
new file mode 100644
index 0000000..a5f6e2e
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/lib.rs
@@ -0,0 +1,294 @@
+//! [![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/5.0.0/status.svg)](https://deps.rs/crate/der-parser/5.0.1)
+//! [![Github CI](https://github.com/rusticata/der-parser/workflows/Continuous%20integration/badge.svg)](https://github.com/rusticata/der-parser/actions)
+//! [![Minimum rustc version](https://img.shields.io/badge/rustc-1.48.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 6.0 series of `der-parser` requires **Rustc version 1.48 or greater**, based on 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 nom;
+#[cfg(feature = "bigint")]
+#[cfg_attr(docsrs, doc(cfg(feature = "bigint")))]
+pub use num_bigint;
+
+// re-exports nom macros, so this crate's macros can be used without importing nom
+pub use nom::IResult;
+#[doc(hidden)]
+pub use rusticata_macros::custom_check;
+
+#[doc(hidden)]
+pub mod exports {
+ pub use alloc::borrow;
+ pub use der_oid_macro;
+}
+
+/// Procedural macro to get encoded oids, see the [oid module](oid/index.html).
+#[macro_export]
+macro_rules! oid {
+ (raw $($args:tt)*) => {{
+ $crate::exports::der_oid_macro::encode_oid!($($args)*)
+ }};
+ (rel $($args:tt)*) => {{
+ $crate::oid::Oid::new_relative(
+ $crate::exports::borrow::Cow::Borrowed(&
+ $crate::exports::der_oid_macro::encode_oid!(rel $($args)*)
+ )
+ )
+ }};
+ ($($args:tt)*) => {{
+ $crate::oid::Oid::new(
+ $crate::exports::borrow::Cow::Borrowed(&
+ $crate::exports::der_oid_macro::encode_oid!($($args)*)
+ )
+ )
+ }};
+}
diff --git a/rust/vendor/der-parser-6.0.1/src/oid.rs b/rust/vendor/der-parser-6.0.1/src/oid.rs
new file mode 100644
index 0000000..618988d
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/src/oid.rs
@@ -0,0 +1,463 @@
+//! Object ID (OID) representations.
+//!
+//! The parser does not copy oids when parsing. The [Oid struct](struct.Oid.html)
+//! only has a reference to the DER encoded form of the oid.
+//!
+//! # The `der_parser::oid!` macro
+//!
+//! Since the DER encoded oids are not very readable we provide a
+//! procedural macro `oid!`. The macro can be used the following ways:
+//!
+//! - `oid!(1.4.42.23)`: Create a const expression for the corresponding `Oid<'static>`
+//! - `oid!(rel 42.23)`: Create a const expression for the corresponding relative `Oid<'static>`
+//! - `oid!(raw 1.4.42.23)`/`oid!(raw rel 42.23)`: Obtain the DER encoded form as a byte array.
+//!
+//! # Comparing oids
+//!
+//! Comparing a parsed oid to a static oid is probably the most common
+//! thing done with oids in your code. The `oid!` macro can be used in expression positions for
+//! this purpose. For example
+//! ```
+//! use der_parser::{oid, oid::Oid};
+//!
+//! # let some_oid: Oid<'static> = oid!(1.2.456);
+//! const SOME_STATIC_OID: Oid<'static> = oid!(1.2.456);
+//! assert_eq!(some_oid, SOME_STATIC_OID)
+//! ```
+//! To get a relative Oid use `oid!(rel 1.2)`.
+//!
+//! Because of limitations for 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:
+//! ```
+//! # 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.
+use alloc::borrow::Cow;
+use alloc::fmt;
+use alloc::str::FromStr;
+use alloc::string::{String, ToString};
+use alloc::vec::Vec;
+use core::convert::From;
+use core::iter::{ExactSizeIterator, FusedIterator, Iterator};
+use core::ops::Shl;
+
+#[cfg(feature = "bigint")]
+use num_bigint::BigUint;
+use num_traits::Num;
+
+#[cfg(not(feature = "std"))]
+use alloc::format;
+
+#[derive(Debug)]
+pub enum ParseError {
+ TooShort,
+ /// Signalizes that the first or second component is too large.
+ /// The first must be within the range 0 to 6 (inclusive).
+ /// The second component must be less than 40.
+ FirstComponentsTooLarge,
+ ParseIntError,
+}
+
+/// Object ID (OID) representation which can be relative or non-relative.
+/// An example for an oid in string representation is "1.2.840.113549.1.1.5".
+///
+/// For non-relative oids restrictions apply to the first two components.
+///
+/// This library contains a procedural macro `oid` which can be used to
+/// create oids. For example `oid!(1.2.44.233)` or `oid!(rel 44.233)`
+/// for relative oids. See the [module documentation](index.html) for more information.
+#[derive(Hash, PartialEq, Eq, Clone)]
+pub struct Oid<'a> {
+ asn1: Cow<'a, [u8]>,
+ pub relative: bool,
+}
+
+fn encode_relative(ids: &'_ [u64]) -> impl Iterator<Item = u8> + '_ {
+ ids.iter()
+ .map(|id| {
+ let bit_count = 64 - id.leading_zeros();
+ let octets_needed = ((bit_count + 6) / 7).max(1);
+ (0..octets_needed).map(move |i| {
+ let flag = if i == octets_needed - 1 { 0 } else { 1 << 7 };
+ ((id >> (7 * (octets_needed - 1 - i))) & 0b111_1111) as u8 | flag
+ })
+ })
+ .flatten()
+}
+
+impl<'a> Oid<'a> {
+ /// Create an OID from the ASN.1 DER encoded form. See the [module documentation](index.html)
+ /// for other ways to create oids.
+ pub const fn new(asn1: Cow<'a, [u8]>) -> Oid {
+ Oid {
+ asn1,
+ relative: false,
+ }
+ }
+
+ /// Create a relative OID from the ASN.1 DER encoded form. See the [module documentation](index.html)
+ /// for other ways to create relative oids.
+ pub const fn new_relative(asn1: Cow<'a, [u8]>) -> Oid {
+ Oid {
+ asn1,
+ relative: true,
+ }
+ }
+
+ /// Build an OID from an array of object identifier components.
+ /// This method allocates memory on the heap.
+ // we do not use .copied() for compatibility with 1.34
+ #[allow(clippy::map_clone)]
+ pub fn from<'b>(s: &'b [u64]) -> Result<Oid<'static>, ParseError> {
+ if s.len() < 2 {
+ if s.len() == 1 && s[0] == 0 {
+ return Ok(Oid {
+ asn1: Cow::Borrowed(&[0]),
+ relative: false,
+ });
+ }
+ return Err(ParseError::TooShort);
+ }
+ if s[0] >= 7 || s[1] >= 40 {
+ return Err(ParseError::FirstComponentsTooLarge);
+ }
+ let asn1_encoded: Vec<u8> = [(s[0] * 40 + s[1]) as u8]
+ .iter()
+ .map(|&x| x)
+ .chain(encode_relative(&s[2..]))
+ .collect();
+ Ok(Oid {
+ asn1: Cow::from(asn1_encoded),
+ relative: false,
+ })
+ }
+
+ /// Build a relative OID from an array of object identifier components.
+ pub fn from_relative<'b>(s: &'b [u64]) -> Result<Oid<'static>, ParseError> {
+ if s.is_empty() {
+ return Err(ParseError::TooShort);
+ }
+ let asn1_encoded: Vec<u8> = encode_relative(s).collect();
+ Ok(Oid {
+ asn1: Cow::from(asn1_encoded),
+ relative: true,
+ })
+ }
+
+ /// Create a deep copy of the oid.
+ ///
+ /// This method allocates data on the heap. The returned oid
+ /// can be used without keeping the ASN.1 representation around.
+ ///
+ /// Cloning the returned oid does again allocate data.
+ pub fn to_owned(&self) -> Oid<'static> {
+ Oid {
+ asn1: Cow::from(self.asn1.to_vec()),
+ relative: self.relative,
+ }
+ }
+
+ /// Get the encoded oid without the header.
+ pub fn bytes(&self) -> &[u8] {
+ self.asn1.as_ref()
+ }
+
+ /// Convert the OID to a string representation.
+ /// The string contains the IDs separated by dots, for ex: "1.2.840.113549.1.1.5"
+ #[cfg(feature = "bigint")]
+ pub fn to_id_string(&self) -> String {
+ let ints: Vec<String> = self.iter_bigint().map(|i| i.to_string()).collect();
+ ints.join(".")
+ }
+
+ #[cfg(not(feature = "bigint"))]
+ /// Convert the OID to a string representation.
+ ///
+ /// If every arc fits into a u64 a string like "1.2.840.113549.1.1.5"
+ /// is returned, otherwise a hex representation.
+ ///
+ /// See also the "bigint" feature of this crate.
+ pub fn to_id_string(&self) -> String {
+ if let Some(arcs) = self.iter() {
+ let ints: Vec<String> = arcs.map(|i| i.to_string()).collect();
+ ints.join(".")
+ } else {
+ let mut ret = String::with_capacity(self.asn1.len() * 3);
+ for (i, o) in self.asn1.iter().enumerate() {
+ ret.push_str(&format!("{:02x}", o));
+ if i + 1 != self.asn1.len() {
+ ret.push(' ');
+ }
+ }
+ ret
+ }
+ }
+
+ /// Return an iterator over the sub-identifiers (arcs).
+ #[cfg(feature = "bigint")]
+ pub fn iter_bigint(
+ &'_ self,
+ ) -> impl Iterator<Item = BigUint> + FusedIterator + ExactSizeIterator + '_ {
+ SubIdentifierIterator {
+ oid: self,
+ pos: 0,
+ first: false,
+ n: core::marker::PhantomData,
+ }
+ }
+
+ /// Return an iterator over the sub-identifiers (arcs).
+ /// Returns `None` if at least one arc does not fit into `u64`.
+ pub fn iter(
+ &'_ self,
+ ) -> Option<impl Iterator<Item = u64> + FusedIterator + ExactSizeIterator + '_> {
+ // Check that every arc fits into u64
+ let bytes = if self.relative {
+ &self.asn1
+ } else if self.asn1.is_empty() {
+ &[]
+ } else {
+ &self.asn1[1..]
+ };
+ let max_bits = bytes
+ .iter()
+ .fold((0usize, 0usize), |(max, cur), c| {
+ let is_end = (c >> 7) == 0u8;
+ if is_end {
+ (max.max(cur + 7), 0)
+ } else {
+ (max, cur + 7)
+ }
+ })
+ .0;
+ if max_bits > 64 {
+ return None;
+ }
+
+ Some(SubIdentifierIterator {
+ oid: self,
+ pos: 0,
+ first: false,
+ n: core::marker::PhantomData,
+ })
+ }
+}
+
+trait Repr: Num + Shl<usize, Output = Self> + From<u8> {}
+impl<N> Repr for N where N: Num + Shl<usize, Output = N> + From<u8> {}
+
+struct SubIdentifierIterator<'a, N: Repr> {
+ oid: &'a Oid<'a>,
+ pos: usize,
+ first: bool,
+ n: core::marker::PhantomData<&'a N>,
+}
+
+impl<'a, N: Repr> Iterator for SubIdentifierIterator<'a, N> {
+ type Item = N;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ use num_traits::identities::Zero;
+
+ if self.pos == self.oid.asn1.len() {
+ return None;
+ }
+ if !self.oid.relative {
+ if !self.first {
+ debug_assert!(self.pos == 0);
+ self.first = true;
+ return Some((self.oid.asn1[0] / 40).into());
+ } else if self.pos == 0 {
+ self.pos += 1;
+ if self.oid.asn1[0] == 0 && self.oid.asn1.len() == 1 {
+ return None;
+ }
+ return Some((self.oid.asn1[0] % 40).into());
+ }
+ }
+ // decode objet sub-identifier according to the asn.1 standard
+ let mut res = <N as Zero>::zero();
+ for o in self.oid.asn1[self.pos..].iter() {
+ self.pos += 1;
+ res = (res << 7) + (o & 0b111_1111).into();
+ let flag = o >> 7;
+ if flag == 0u8 {
+ break;
+ }
+ }
+ Some(res)
+ }
+}
+
+impl<'a, N: Repr> FusedIterator for SubIdentifierIterator<'a, N> {}
+
+impl<'a, N: Repr> ExactSizeIterator for SubIdentifierIterator<'a, N> {
+ fn len(&self) -> usize {
+ if self.oid.relative {
+ self.oid.asn1.iter().filter(|o| (*o >> 7) == 0u8).count()
+ } else if self.oid.asn1.len() == 0 {
+ 0
+ } else if self.oid.asn1.len() == 1 {
+ if self.oid.asn1[0] == 0 {
+ 1
+ } else {
+ 2
+ }
+ } else {
+ 2 + self.oid.asn1[2..]
+ .iter()
+ .filter(|o| (*o >> 7) == 0u8)
+ .count()
+ }
+ }
+
+ #[cfg(feature = "exact_size_is_empty")]
+ fn is_empty(&self) -> bool {
+ self.oid.asn1.is_empty()
+ }
+}
+
+impl<'a> fmt::Display for Oid<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.relative {
+ f.write_str("rel. ")?;
+ }
+ f.write_str(&self.to_id_string())
+ }
+}
+
+impl<'a> fmt::Debug for Oid<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("OID(")?;
+ <Oid as fmt::Display>::fmt(self, f)?;
+ f.write_str(")")
+ }
+}
+
+impl<'a> FromStr for Oid<'a> {
+ type Err = ParseError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let v: Result<Vec<_>, _> = s.split('.').map(|c| c.parse::<u64>()).collect();
+ v.map_err(|_| ParseError::ParseIntError)
+ .and_then(|v| Oid::from(&v))
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::oid::Oid;
+ use std::borrow::Cow;
+ use std::borrow::ToOwned;
+ use std::str::FromStr;
+
+ #[test]
+ fn test_oid_fmt() {
+ let oid = Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap();
+ assert_eq!(format!("{}", oid), "1.2.840.113549.1.1.5".to_owned());
+ assert_eq!(format!("{:?}", oid), "OID(1.2.840.113549.1.1.5)".to_owned());
+
+ let oid = Oid::from_relative(&[840, 113_549, 1, 1, 5]).unwrap();
+ let byte_ref = [0x86, 0x48, 0x86, 0xf7, 0x0d, 1, 1, 5];
+ assert_eq!(byte_ref.as_ref(), oid.asn1.as_ref());
+ assert_eq!(format!("{}", oid), "rel. 840.113549.1.1.5".to_owned());
+ assert_eq!(
+ format!("{:?}", oid),
+ "OID(rel. 840.113549.1.1.5)".to_owned()
+ );
+ }
+
+ #[test]
+ fn test_iter_len() {
+ #[cfg(feature = "bigint")]
+ {
+ assert_eq!(Oid::new(Cow::Borrowed(&[])).iter_bigint().len(), 0);
+ assert_eq!(Oid::from(&[0]).unwrap().iter_bigint().len(), 1);
+ assert_eq!(Oid::from(&[1, 2]).unwrap().iter_bigint().len(), 2);
+ assert_eq!(
+ Oid::from(&[1, 29, 459, 342]).unwrap().iter_bigint().len(),
+ 4
+ );
+ assert_eq!(
+ Oid::from_relative(&[459, 342]).unwrap().iter_bigint().len(),
+ 2
+ );
+ }
+ {
+ assert_eq!(Oid::new(Cow::Borrowed(&[])).iter().unwrap().len(), 0);
+ assert_eq!(Oid::from(&[0]).unwrap().iter().unwrap().len(), 1);
+ assert_eq!(Oid::from(&[1, 2]).unwrap().iter().unwrap().len(), 2);
+ assert_eq!(
+ Oid::from(&[1, 29, 459, 342]).unwrap().iter().unwrap().len(),
+ 4
+ );
+ assert_eq!(
+ Oid::from_relative(&[459, 342])
+ .unwrap()
+ .iter()
+ .unwrap()
+ .len(),
+ 2
+ );
+ }
+ }
+
+ #[test]
+ fn test_oid_from_str() {
+ let oid_ref = Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap();
+ let byte_ref = [42, 0x86, 0x48, 0x86, 0xf7, 0x0d, 1, 1, 5];
+ let oid = Oid::from_str("1.2.840.113549.1.1.5").unwrap();
+ assert_eq!(byte_ref.as_ref(), oid.asn1.as_ref());
+ assert_eq!(oid_ref, oid);
+ }
+
+ /// This test case will test an OID beginning with two zero
+ /// subidentifiers (literally: "itu-t recommendation"), as
+ /// used for example in the TCAP (Q.773) specification.
+
+ #[test]
+ fn test_itu_t_rec_oid() {
+ let oid = Oid::from(&[0, 0, 17, 773, 1, 1, 1]).unwrap();
+ assert_eq!(format!("{}", oid), "0.0.17.773.1.1.1".to_owned());
+ assert_eq!(format!("{:?}", oid), "OID(0.0.17.773.1.1.1)".to_owned());
+ }
+
+ #[test]
+ fn test_zero_oid() {
+ #[cfg(feature = "bigint")]
+ {
+ use num_bigint::BigUint;
+ use num_traits::FromPrimitive;
+ use std::vec::Vec;
+
+ let oid_raw = Oid::new(Cow::Borrowed(&[0]));
+ let ids: Vec<BigUint> = oid_raw.iter_bigint().collect();
+ assert_eq!(vec![BigUint::from_u8(0).unwrap()], ids);
+ assert_eq!(oid_raw.iter_bigint().len(), 1);
+ }
+ {
+ use std::vec::Vec;
+ let oid_raw = Oid::new(Cow::Borrowed(&[0]));
+ let ids: Vec<u64> = oid_raw.iter().unwrap().collect();
+ assert_eq!(vec![0], ids);
+ assert_eq!(oid_raw.iter().unwrap().len(), 1);
+ }
+ let oid_from = Oid::from(&[0]).unwrap();
+ assert_eq!(oid_from.asn1.as_ref(), &[0]);
+ }
+}
diff --git a/rust/vendor/der-parser-6.0.1/tests/ber_parser.rs b/rust/vendor/der-parser-6.0.1/tests/ber_parser.rs
new file mode 100644
index 0000000..6f020e3
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/tests/ber_parser.rs
@@ -0,0 +1,550 @@
+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 true")]
+#[test_case(&hex!("01 01 ff"), Some(true) ; "val false")]
+#[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 06 00 00 01 23 45 67"), Ok(0x0123_4567) ; "u32-long-leading-zeros-ok")]
+#[test_case(&hex!("02 05 01 23 45 67 01"), Err(BerError::IntegerTooLarge) ; "u32 too large")]
+#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Err(BerError::IntegerTooLarge) ; "u32 too large 2")]
+#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
+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::InvalidTag) ; "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!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
+fn tc_ber_i64(i: &[u8], out: Result<i64, BerError>) {
+ let res = parse_ber_i64(i);
+ match out {
+ Ok(expected) => {
+ pretty_assertions::assert_eq!(res, Ok((&b""[..], expected)));
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
+ }
+ }
+}
+
+#[cfg(feature = "bigint")]
+#[test_case(&hex!("02 01 01"), Ok(BigInt::from(1)) ; "bigint-1")]
+#[test_case(&hex!("02 02 00 ff"), Ok(BigInt::from(255)) ; "bigint-255")]
+#[test_case(&hex!("02 01 ff"), Ok(BigInt::from(-1)) ; "bigint-neg1")]
+#[test_case(&hex!("02 01 80"), Ok(BigInt::from(-128)) ; "bigint-neg128")]
+#[test_case(&hex!("02 02 ff 7f"), Ok(BigInt::from(-129)) ; "bigint-neg129")]
+#[test_case(&hex!("02 09 00 ff ff ff ff ff ff ff ff"), Ok(BigInt::from(0xffff_ffff_ffff_ffff_u64)) ; "bigint-long2-ok")]
+#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Ok(BigInt::from_bytes_be(Sign::Plus, &hex!("01 23 45 67 01 23 45 67 ab"))) ; "bigint-longer1")]
+fn tc_ber_bigint(i: &[u8], out: Result<BigInt, BerError>) {
+ let res = parse_ber_integer(i);
+ match out {
+ Ok(expected) => {
+ let (rem, ber) = res.expect("parsing failed");
+ assert!(rem.is_empty());
+ let int = ber.as_bigint().expect("failed to convert to bigint");
+ pretty_assertions::assert_eq!(int, expected);
+ }
+ Err(e) => {
+ pretty_assertions::assert_eq!(res, Err(Err::Error(e)));
+ }
+ }
+}
+
+#[cfg(feature = "bigint")]
+#[test_case(&hex!("02 01 01"), Ok(BigUint::from(1_u8)) ; "biguint-1")]
+#[test_case(&hex!("02 02 00 ff"), Ok(BigUint::from(255_u8)) ; "biguint-255")]
+#[test_case(&hex!("02 01 ff"), Err(BerError::IntegerNegative) ; "biguint-neg1")]
+#[test_case(&hex!("02 01 80"), Err(BerError::IntegerNegative) ; "biguint-neg128")]
+#[test_case(&hex!("02 02 ff 7f"), Err(BerError::IntegerNegative) ; "biguint-neg129")]
+#[test_case(&hex!("02 09 00 ff ff ff ff ff ff ff ff"), Ok(BigUint::from(0xffff_ffff_ffff_ffff_u64)) ; "biguint-long2-ok")]
+#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Ok(BigUint::from_bytes_be(&hex!("01 23 45 67 01 23 45 67 ab"))) ; "biguint-longer1")]
+#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
+fn tc_ber_biguint(i: &[u8], out: Result<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::InvalidTag) ; "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(b"\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, BerTag::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, BerTag::Integer);
+ assert_eq!(content.as_u32(), Ok(0x10001));
+}
+
+#[test]
+fn parse_ber_private() {
+ let bytes = &hex!("c0 03 01 00 01");
+ let (rem, res) = parse_ber(bytes).expect("parsing failed");
+ assert!(rem.is_empty());
+ assert!(matches!(res.content, BerObjectContent::Private(_, _)));
+}
diff --git a/rust/vendor/der-parser-6.0.1/tests/constructed.rs b/rust/vendor/der-parser-6.0.1/tests/constructed.rs
new file mode 100644
index 0000000..20a83a0
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/tests/constructed.rs
@@ -0,0 +1,438 @@
+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: BerTag) -> 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::InvalidTag)) ; "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::InvalidTag)) ; "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::InvalidTag)) ; "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::InvalidTag)) ; "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, BerTag::Sequence);
+ assert_eq!(res, Ok((empty, expected)));
+ let res = parse_struct04(&bytes, BerTag::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::InvalidTag) ; "invalid tag")]
+#[test_case(&hex!("22 05 02 03 01 00 01"), Err(BerError::InvalidClass) ; "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::InvalidTag))
+ );
+ // wrong type
+ assert_eq!(
+ parse_der_tagged_explicit(2, parse_der_bool)(bytes as &[u8]),
+ Err(Err::Error(BerError::InvalidTag))
+ );
+}
+
+#[test_case(&hex!("82 03 01 00 01"), Ok(0x10001) ; "tag ok")]
+#[test_case(&hex!("83 03 01 00 01"), Err(BerError::InvalidTag) ; "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(BerTag::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(DerTag::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(DerTag::Integer))(bytes as &[u8]),
+ Err(Err::Error(BerError::InvalidTag))
+ );
+}
+
+#[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 != BerClass::Application {
+ return Err(Err::Error(BerError::InvalidClass));
+ }
+ if hdr.tag != BerTag(2) {
+ return Err(Err::Error(BerError::InvalidTag));
+ }
+ let (i, a) = map_res(parse_ber_integer, |x: BerObject| x.as_u32())(i)?;
+ Ok((i, SimpleStruct { a }))
+ })(i)
+ }
+ let bytes = &[0x62, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01];
+ let (rem, app) = parse_app01(bytes).expect("could not parse application");
+ 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-6.0.1/tests/custom_error.rs b/rust/vendor/der-parser-6.0.1/tests/custom_error.rs
new file mode 100644
index 0000000..2281510
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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-6.0.1/tests/der_constructed.rs b/rust/vendor/der-parser-6.0.1/tests/der_constructed.rs
new file mode 100644
index 0000000..0785189
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/tests/der_constructed.rs
@@ -0,0 +1,173 @@
+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) ; "indefinite tag ok")]
+#[test_case(&hex!("a3 05 02 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
+#[test_case(&hex!("22 05 02 03 01 00 01"), Err(BerError::InvalidClass) ; "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::InvalidTag) ; "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(DerTag::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::InvalidTag) ; "invalid tag")]
+#[test_case(&hex!("30 80 02 03 01 00 01 00 00"), Err(BerError::DerConstraintFailed) ; "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::InvalidTag)) ; "invalid tag")]
+#[test_case(&hex!("30 80 02 03 01 00 01 00 00"), Err(Err::Error(BerError::DerConstraintFailed)) ; "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::InvalidTag) ; "invalid tag")]
+#[test_case(&hex!("31 80 02 03 01 00 01 00 00"), Err(BerError::DerConstraintFailed) ; "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::InvalidTag)) ; "invalid tag")]
+#[test_case(&hex!("31 80 02 03 01 00 01 00 00"), Err(Err::Error(BerError::DerConstraintFailed)) ; "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-6.0.1/tests/der_parser.rs b/rust/vendor/der-parser-6.0.1/tests/der_parser.rs
new file mode 100644
index 0000000..33665f3
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/tests/der_parser.rs
@@ -0,0 +1,582 @@
+#![allow(deprecated)]
+
+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 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))
+ );
+}
+
+#[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))
+ );
+ //
+ // 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))
+ );
+}
+
+#[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))
+ );
+}
+
+#[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::InvalidTag)));
+ //
+ 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::InvalidTag)));
+ 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 0D 30 32 31 32 31 33 31 34 32 39 32 33 5A FF");
+ let expected = DerObject::from_obj(BerObjectContent::UTCTime(
+ std::str::from_utf8(&bytes[2..(2 + 0x0d)]).unwrap(),
+ ));
+ assert_eq!(parse_der_utctime(&bytes), Ok((&[0xff][..], expected)));
+ let bytes = hex!("17 0c 30 32 31 32 31 33 31 34 32 39 32 33");
+ parse_der_utctime(&bytes).err().expect("expected error");
+}
+
+#[test]
+fn test_der_generalizedtime() {
+ let empty = &b""[..];
+ let bytes = [
+ 0x18, 0x0D, 0x30, 0x32, 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x32, 0x39, 0x32, 0x33, 0x5A,
+ ];
+ let expected = DerObject::from_obj(BerObjectContent::GeneralizedTime(
+ std::str::from_utf8(&bytes[2..]).unwrap(),
+ ));
+ 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(b"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 expected = DerObject {
+ header: BerObjectHeader::new(BerClass::ContextSpecific, 1, BerTag(0), 3)
+ .with_raw_tag(Some(&[0xa0])),
+ content: BerObjectContent::Unknown(BerClass::ContextSpecific, BerTag(0), &bytes[2..]),
+ };
+ 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 = BerObjectHeader::new(BerClass::ContextSpecific, 1, BerTag(0), 3)
+ .with_raw_tag(Some(&[0xa0]));
+ let expected = DerObject {
+ header: header.clone(),
+ content: BerObjectContent::Optional(Some(Box::new(BerObject::from_header_and_content(
+ header,
+ BerObjectContent::Tagged(
+ BerClass::ContextSpecific,
+ BerTag(0),
+ Box::new(DerObject::from_int_slice(b"\x02")),
+ ),
+ )))),
+ };
+ assert_eq!(
+ parse_der_explicit_optional(&bytes, BerTag(0), parse_der_integer),
+ Ok((empty, expected))
+ );
+ let expected2 = DerObject::from_obj(BerObjectContent::Optional(None));
+ assert_eq!(
+ parse_der_explicit_optional(&bytes, BerTag(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: BerObjectHeader::new(BerClass::ContextSpecific, 0, BerTag(1), 4)
+ .with_raw_tag(Some(&[0x81])),
+ content: BerObjectContent::IA5String("pass"),
+ };
+ fn der_read_ia5string_content<'a>(
+ i: &'a [u8],
+ hdr: &BerObjectHeader,
+ depth: usize,
+ ) -> BerResult<'a, BerObjectContent<'a>> {
+ ber_read_element_content_as(i, DerTag::Ia5String, hdr.len, hdr.is_constructed(), depth)
+ }
+ assert_eq!(
+ parse_der_implicit(&bytes, BerTag(1), der_read_ia5string_content),
+ Ok((empty, expected))
+ );
+ assert_eq!(
+ parse_der_implicit(&bytes, BerTag(2), der_read_ia5string_content),
+ Err(Err::Error(BerError::InvalidTag))
+ );
+}
+
+#[test]
+fn test_der_implicit_long_tag() {
+ let empty = &b""[..];
+ let bytes = [0x5f, 0x52, 0x04, 0x70, 0x61, 0x73, 0x73];
+ let expected = DerObject {
+ header: BerObjectHeader::new(BerClass::Application, 0, BerTag(0x52), 4)
+ .with_raw_tag(Some(&[0x5f, 0x52])),
+ content: BerObjectContent::IA5String("pass"),
+ };
+ fn der_read_ia5string_content<'a>(
+ i: &'a [u8],
+ hdr: &BerObjectHeader,
+ depth: usize,
+ ) -> BerResult<'a, BerObjectContent<'a>> {
+ ber_read_element_content_as(i, DerTag::Ia5String, hdr.len, hdr.is_constructed(), depth)
+ }
+ assert_eq!(
+ parse_der_implicit(&bytes, BerTag(0x52), der_read_ia5string_content),
+ Ok((empty, expected))
+ );
+ assert_eq!(
+ parse_der_implicit(&bytes, BerTag(2), der_read_ia5string_content),
+ Err(Err::Error(BerError::InvalidTag))
+ );
+}
+
+#[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")]
+#[test_case(&hex!("02 04 ff ff ff ff"), Err(BerError::IntegerNegative) ; "u32-long2-neg")]
+#[test_case(&hex!("02 06 00 00 01 23 45 67"), Err(BerError::DerConstraintFailed) ; "u32-long-leading-zeros")]
+#[test_case(&hex!("02 05 01 23 45 67 01"), Err(BerError::IntegerTooLarge) ; "u32 too large")]
+#[test_case(&hex!("02 09 01 23 45 67 01 23 45 67 ab"), Err(BerError::IntegerTooLarge) ; "u32 too large 2")]
+#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "invalid tag")]
+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")]
+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::InvalidTag) ; "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) ; "constructed slice")]
+#[test_case(&hex!("03 03 01 00 01"), Err(BerError::InvalidTag) ; "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-6.0.1/tests/fuzz01.rs b/rust/vendor/der-parser-6.0.1/tests/fuzz01.rs
new file mode 100644
index 0000000..c971b56
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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-6.0.1/tests/fuzz02.rs b/rust/vendor/der-parser-6.0.1/tests/fuzz02.rs
new file mode 100644
index 0000000..bea7c21
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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-6.0.1/tests/oid.rs b/rust/vendor/der-parser-6.0.1/tests/oid.rs
new file mode 100644
index 0000000..5cffad4
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/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.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-6.0.1/tests/primitive.rs b/rust/vendor/der-parser-6.0.1/tests/primitive.rs
new file mode 100644
index 0000000..4c07b0a
--- /dev/null
+++ b/rust/vendor/der-parser-6.0.1/tests/primitive.rs
@@ -0,0 +1,228 @@
+extern crate alloc;
+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], BerTag::Boolean, 0x01.into(), false, MAX_RECURSION),
+ Ok((empty, BerObjectContent::Boolean(true)))
+ );
+ assert_eq!(
+ ber_read_element_content_as(&[0x00], BerTag::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(
+ BerClass::Universal,
+ BerTag(0x1d),
+ &bytes[2..]
+ ))
+ );
+ let res = parse_der(&bytes).expect("parsing failed");
+ assert!(res.0.is_empty());
+ assert_eq!(
+ res.1,
+ BerObject::from_obj(BerObjectContent::Unknown(
+ BerClass::Universal,
+ BerTag(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: BerObjectHeader::new(BerClass::ContextSpecific, 0, BerTag(0), 1)
+ .with_raw_tag(Some(&[0x80])),
+ content: BerObjectContent::Unknown(BerClass::ContextSpecific, BerTag(0x0), &bytes[2..]),
+ }
+ );
+}
+
+#[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: BerObjectHeader::new(BerClass::ContextSpecific, 0, BerTag(0x22), 1)
+ .with_raw_tag(Some(&[0x9f, 0x22])),
+ content: BerObjectContent::Unknown(
+ BerClass::ContextSpecific,
+ BerTag(0x22),
+ &bytes[3..]
+ ),
+ }
+ );
+}
+
+#[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: BerObjectHeader::new(BerClass::ContextSpecific, 0, BerTag(0x1122), 1)
+ .with_raw_tag(Some(&[0x9f, 0xa2, 0x22])),
+ content: BerObjectContent::Unknown(
+ BerClass::ContextSpecific,
+ BerTag(0x1122),
+ &bytes[4..]
+ ),
+ }
+ );
+}
+
+#[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 85 ff ff ff ff ff 00");
+ let res = parse_ber(&bytes).expect_err("parsing should have returned error");
+ // get error
+ match res {
+ Err::Error(e) => {
+ assert_eq!(e, BerError::InvalidLength);
+ }
+ _ => panic!("not the expected nom error kind {:?}", 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);
+}