bcder-0.7.3/.cargo_vcs_info.json0000644000000001360000000000100121220ustar { "git": { "sha1": "6a7250af12b7e347f57fc918784ed5d110b3cbf7" }, "path_in_vcs": "" }bcder-0.7.3/.github/FUNDING.yml000064400000000000000000000000761046102023000140720ustar 00000000000000github: [NLnetLabs] custom: ['https://nlnetlabs.nl/funding/'] bcder-0.7.3/.github/workflows/ci.yml000064400000000000000000000013611046102023000154260ustar 00000000000000name: ci on: push: branches: - main pull_request: branches: - main jobs: test: name: test runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] rust: [1.64.0, stable, beta, nightly] steps: - name: Checkout repository uses: actions/checkout@v1 - name: Install Rust uses: hecrj/setup-rust-action@v1 with: rust-version: ${{ matrix.rust }} - if: matrix.rust != 'nightly' run: rustup component add clippy - if: matrix.rust != 'nightly' run: cargo clippy --all --all-features -- -D warnings - run: cargo build --verbose --all --all-features - run: cargo test --verbose --all --all-features bcder-0.7.3/.gitignore000064400000000000000000000000371046102023000127020ustar 00000000000000/target **/*.rs.bk /Cargo.lock bcder-0.7.3/Cargo.lock0000644000000010740000000000100100770ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "bcder" version = "0.7.3" dependencies = [ "bytes", "smallvec", ] [[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "smallvec" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" bcder-0.7.3/Cargo.toml0000644000000017770000000000100101340ustar # 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 = "bcder" version = "0.7.3" authors = ["The NLnet Labs RPKI Team "] description = "Handling of data encoded in BER, CER, and DER." documentation = "https://docs.rs/bcder/" readme = "README.md" keywords = [ "ber", "cer", "der", "asn1", "decoding", ] categories = [ "encoding", "network-programming", "parsing", ] license = "BSD-3-Clause" repository = "https://github.com/nlnetlabs/bcder" [dependencies.bytes] version = "^1.0" [dependencies.smallvec] version = "^1.1" bcder-0.7.3/Cargo.toml.orig000064400000000000000000000007331046102023000136040ustar 00000000000000[package] name = "bcder" version = "0.7.3" edition = "2018" authors = ["The NLnet Labs RPKI Team "] description = "Handling of data encoded in BER, CER, and DER." documentation = "https://docs.rs/bcder/" repository = "https://github.com/nlnetlabs/bcder" keywords = ["ber", "cer", "der", "asn1", "decoding"] categories = ["encoding", "network-programming", "parsing"] license = "BSD-3-Clause" [dependencies] bytes = "^1.0" smallvec = "^1.1" bcder-0.7.3/Changelog.md000064400000000000000000000166071046102023000131350ustar 00000000000000# Change Log ## 0.7.3 Release 2023-09-13. This release fixes a number of decoding issues that can lead to panics on invalid input data. They have been assigned CVE-2023-39914. Bug fixes * Fixes various decoding that lead to a panic on invalid data. Specifically: * error out rather than panic when a nested value has a greater length than allowed by the outer value, * check that there is enough data available before skipping over a primitive value’s content, * check that enough data is available before trying to parse a tag value, * check for correct encoding of bit strings: don’t allow the number of unused bits to be greater than 7 and that they are zero for an empty bit string, * check for correct encoding of object identifiers: they cannot be empty and the last byte must have bit 7 cleared. ## 0.7.2 Released 2023-06-01. New * Added an implementation of `FromStr` for `Oid`. ([#71] by [@Outurnate]) [#71]: https://github.com/NLnetLabs/bcder/pull/71 [@Outurnate]: https://github.com/Outurnate ## 0.7.1 Released 2022-12-09. New * Added a number of missing well-defined tags as `Tag` constants, specifically: `CHARACTER STRING`, `TIME`, `DATA`, `TIME_OF_DAY`, `DATE_TIME`, `DURATION`, `OID-IRI`, and `RELATIVE-OID-IRI`. ([#67] by [@lvkv]) Bug fixes * Fix `Tag::BMP_STRING` to `UNIVERSAL 30`. ([#67] by [@lvkv]) [#67]: https://github.com/NLnetLabs/bcder/pull/67 [@lvkv]: https://github.com/lvkv ## 0.7.0 Released 2022-07-18. Breaking Changes * Redesign error handling in `decode` module ([#65]): * three error types, `Source::Error`, `ContentError`, and `DecodeError`, for data fetching errors, syntax errors, and a combination of these, respectively; * new trait `IntoSource` to convert a type into its `Source` implementation; * `Source::advance` now panics if advancing past the end of seen data. [#65]: https://github.com/NLnetLabs/bcder/pull/65 ## 0.6.1 Released 2012-10-29. New * `int::Unsigned` can now be created from an arbitrary length big-endian representation of an unsigned integer. ([#59]) * Add `OctetString::take_opt_from`. ([#61]) [#59]: https://github.com/NLnetLabs/bcder/pull/59 [#61]: https://github.com/NLnetLabs/bcder/pull/61 ## 0.6.0 Released 2021-01-04. Breaking Changes * Minimum supported Rust version is now 1.42. ([#56]) * Upgrade *bytes* to 1.0. ([#57]) [#56]: https://github.com/NLnetLabs/bcder/pull/56 [#57]: https://github.com/NLnetLabs/bcder/pull/57 ## 0.5.1 Released 2021-01-04. Bug Fixes * Fix `oid::Iter` to actually iterate over the components. ([#50]) [#50]: https://github.com/NLnetLabs/bcder/pull/50 ## 0.5.0 Breaking * Move extending a `Captured` to an explicit `CapturedBuilder`. This becomes necessary with bytes 0.5. Both these types now reside in the module `captured` with `Captured` re-exported at crate level. ([#46], [#47]) Dependencies * Upgrade bytes to 0.5. ([#43], thanks to [@Fabian-Gruenbichler]) * Upgrade smallvec to 1.1. ([#48]) [#43]: https://github.com/NLnetLabs/bcder/pull/43 [#46]: https://github.com/NLnetLabs/bcder/pull/46 [#47]: https://github.com/NLnetLabs/bcder/pull/47 [#48]: https://github.com/NLnetLabs/bcder/pull/48 [@Fabian-Gruenbichler]: https://github.com/Fabian-Gruenbichler ## 0.4.2 Bug Fixes * Fix handling of incomplete multi-byte tags. ([#44], based on [#41] by [@dovreshef]) [#41]: https://github.com/NLnetLabs/bcder/pull/41 [#44]: https://github.com/NLnetLabs/bcder/pull/44 [@dovreshef]: https://github.com/dovreshef ## 0.4.1 New * Support for multi-byte tags with tag numbers of up to `0x1F_FFFF`. ([#37], thanks to by [@dovreshef]) Bug Fixes * Fix encoding of signed builtin integer (`i8`, `i16`, …). [(#39)] [#37]: https://github.com/NLnetLabs/bcder/pull/37 [(#39)]: https://github.com/NLnetLabs/bcder/pull/39 [@dovreshef]: https://github.com/dovreshef ## 0.4.0 Breaking * Dropped `RestrictedString::to_string` and implemented it via `Display` instead. Therefore, you will have to `use std::fmt::Display` to get it back. [(#33)] Bug Fixes * Safely decode deeply nested BER such as octet strings. Decoding such types now uses an allocated artificial stack and will thus not overflow the regular one. [(#30)] Miscellaneous * Dropped dependency on `derive_more` for fewer dependencies and faster compiling. ([#32], thanks to [@nocduro]). [(#30)]: https://github.com/NLnetLabs/bcder/pull/30 [#32]: https://github.com/NLnetLabs/bcder/pull/32 [(#33)]: https://github.com/NLnetLabs/bcder/pull/33 [@nocduro]: https://github.com/nocduro ## 0.3.1 Bug Fixes * Fix a lifetime warning from the new borrow checker. [(#27)] * Build on 32 bit systems. [(#29)] Other Changes * Switch to Rust edition 2018. [(#27)]: https://github.com/NLnetLabs/bcder/pull/27 [(#29)]: https://github.com/NLnetLabs/bcder/pull/29 ## 0.3.0 Breaking * The minimum supported Rust version is now 1.34.0. [(#22)] New * New methods for checking the class and number on `Tag`. [(#20)] * Implement `TryFrom` for builtin integers and `Integer` and `Unsigned`. [(#23)] * `RestrictedString::into_bytes` [(#24)] Other Changes * The `xerr!` macro now prints a backtrace with the `extra-debug` feature enabled instead of panicking. [(#21)] [(#20)]: https://github.com/NLnetLabs/rpki-rs/pull/20 [(#21)]: https://github.com/NLnetLabs/rpki-rs/pull/21 [(#22)]: https://github.com/NLnetLabs/rpki-rs/pull/22 [(#23)]: https://github.com/NLnetLabs/rpki-rs/pull/23 [(#24)]: https://github.com/NLnetLabs/rpki-rs/pull/24 ## 0.2.1 New * Add `BitString::encode_slice` and `encode_slice_as`. [(#17)] Bug Fixes * Fix incorrect encoding of primitive unsigned integers for values with a number of leading zero bits divisible by eight. [(#16)] * Fix the mkoid tool to correctly encode large subidentifiers. [(#18)] [(#16)]: https://github.com/NLnetLabs/rpki-rs/pull/16 [(#17)]: https://github.com/NLnetLabs/rpki-rs/pull/17 [(#18)]: https://github.com/NLnetLabs/rpki-rs/pull/18 ## 0.2.0 Breaking Changes * Drop use of _failure_ crate. Error types now provide a `Display` implementation only. [(#15)] * `PrimitiveContent`’s methods take `self` instead of `&self`. This avoids the lifetime argument in `Primitive`, its encoder. [(#7)] * For all provided type, change `encode` and `encode_as` methods to take self by value and introduce `encode_ref` and `encode_ref_as` that take self by reference. [(#12)] * `RestrictedString::from_str` replaced by an implementation of the `FromStr` trait. [(#13)] New * `encode::Values` implemented for tuples of up to twelve elements. [(#9)] * `OctetString::encode_slice` and `encode_slice_as`: allows encoding a bytes slice as an octet string without going through making an `OctetString` first. * `encode::Slice` wraps a slice of values encoding `encode::Values` and provides an encoder for it. [(#11)] * new functions: `encode::slice` and `encode::iter` as shortcuts for the respective associated functions. [(#11)] * `OctetString::is_empty` [(#13)], `OctetString::into_bytes` [(#14)]. [(#7)]: https://github.com/NLnetLabs/bcder/pull/7 [(#9)]: https://github.com/NLnetLabs/bcder/pull/9 [(#10)]: https://github.com/NLnetLabs/bcder/pull/10 [(#11)]: https://github.com/NLnetLabs/bcder/pull/11 [(#12)]: https://github.com/NLnetLabs/bcder/pull/12 [(#13)]: https://github.com/NLnetLabs/bcder/pull/13 [(#14)]: https://github.com/NLnetLabs/bcder/pull/14 [(#14)]: https://github.com/NLnetLabs/bcder/pull/15 ## 0.1.0 Initial public release. bcder-0.7.3/LICENSE000064400000000000000000000027321046102023000117230ustar 00000000000000Copyright (c) 2018, NLnet Labs. All rights reserved. This software is open source. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the NLNET LABS nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. bcder-0.7.3/README.md000064400000000000000000000015461046102023000121770ustar 00000000000000# bcder – BER, CER, and DER Encoding and Decoding for Rust This crate provides decoding and encoding for Basic Encoding Rules (BER) of the ASN.1 standard as well as the more strict variants Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER). It provides the basic machinery as well as implementation for the most important universal types of ASN.1. ## Usage Add the following dependency to your `Cargo.toml`: ``` [dependencies] bcder = "^0.1" ``` A guide introducing ASN.1, BER, and how to use this crate is part of the source as the [`ber::guide`] module. [`bcder::guide`]: https://docs.rs/bcder/0.1/bcder/guide/index.html ## Contributing If you have comments, proposed changes, or would like to contribute, please open an issue. ## License _bcder_ is distributed under the terms of the BSD-3-clause license. See LICENSE for details. bcder-0.7.3/src/bin/mkoid.rs000064400000000000000000000015271046102023000137270ustar 00000000000000//! Generates an object identifier. //! //! This replaces a procmacro that can produce the encoded object identifer //! content from its components in order to define object identifier contants. //! //! Provide a sequence of object identifiers in ‘dot integer’ notation and //! you will receive the octet array for it. use std::env; use bcder::Oid; fn process_one(arg: &str) -> Result<(), &'static str> { let oid_bytes = arg.parse::>>()?.0; print!("["); for byte in oid_bytes { // rust doesn't mind an extra trailing comma print!("{},", byte); } println!("]"); Ok(()) } fn main() { let mut args = env::args(); args.next().unwrap(); // Skip executable name. for arg in args { if let Err(err) = process_one(arg.as_ref()) { println!("{}: {}.", arg, err) } } } bcder-0.7.3/src/captured.rs000064400000000000000000000176621046102023000136720ustar 00000000000000//! Captured BER-encoded data. //! //! This is a private module. Its public items are re-exported by the parent. use std::{fmt, io, mem, ops}; use bytes::{Bytes, BytesMut}; use crate::{decode, encode}; use crate::decode::{BytesSource, DecodeError, IntoSource, Pos}; use crate::mode::Mode; //------------ Captured ------------------------------------------------------ /// A wrapper for BER encoded data. /// /// This types keeps a sequence of BER-encoded data in a [`Bytes`] value. It /// allows for delayed processing of this data and therefore zero-allocation /// handling of sequences and similar types by implementing iterators and /// helper types that work directly on the the still-encoded data. /// /// You usually acquire a value of this type trough the [`capture`] family of /// methods on constructed BER content. Alternatively, you can also construct /// a new value via the [`CapturedBuilder`]. /// /// Once you have a captured value, you can use the [`decode`] method to /// decode the entire captured value or [`decode_partial`] to decode some /// values at the start of the captured value. The latter manipulates the /// captured content by moving past the captured values and is therefore /// perfect for an iterator. /// /// The value also remembers what [`Mode`] the original data was decoded in /// and will automatically use this encoding in those methods. /// /// [`Bytes`]: ../../bytes/struct.Bytes.html /// [`capture`]: ../decode/struct.Constructed.html /// [`from_values`]: #method.from_values /// [`empty`]: #method.empty /// [`decode`]: #method.decode /// [`decode_partial`]: #method.decode /// [`Mode`]: ../enum.Mode.html #[derive(Clone)] pub struct Captured { /// The captured data. bytes: Bytes, /// The encoding mode of the captured data. mode: Mode, /// The start position of the data in the original source. start: Pos, } impl Captured { /// Creates a new captured value from bytes and a mode. /// /// Because we can’t guarantee that the bytes are properly encoded, we /// keep this function crate public. The type, however, doesn’t rely on /// content being properly encoded so this method isn’t unsafe. pub(crate) fn new(bytes: Bytes, mode: Mode, start: Pos) -> Self { Captured { bytes, mode, start } } /// Creates a captured value by encoding data. /// /// The function takes a value encoder, encodes it into a bytes value /// with the given mode, and returns the resulting data as a captured /// value. pub fn from_values(mode: Mode, values: V) -> Self { let mut builder = Self::builder(mode); builder.extend(values); builder.freeze() } /// Creates a new empty captured value in the given mode. pub fn empty(mode: Mode) -> Self { Captured { bytes: Bytes::new(), mode, start: Pos::default(), } } /// Creates a builder for a captured value in the given mode. pub fn builder(mode: Mode) -> CapturedBuilder { CapturedBuilder::new(mode) } /// Converts the captured values into a builder in order to add new values. /// /// Because the captured values might be shared, this requires copying the /// underlying data. pub fn into_builder(self) -> CapturedBuilder { self.into() } /// Decodes the full content using the provided function argument. /// /// The method consumes the value. If you want to keep it around, simply /// clone it first. Since bytes values are cheap to clone, this is /// relatively cheap. pub fn decode( self, op: F ) -> Result::Error>> where F: FnOnce( &mut decode::Constructed ) -> Result::Error>> { self.mode.decode(self.bytes, op) } /// Decodes the beginning of the content of the captured value. /// /// The method calls `op` to parse a number of values from the beginning /// of the value and then advances the content of the captured value until /// after the end of these decoded values. pub fn decode_partial( &mut self, op: F ) -> Result::Error>> where F: FnOnce( &mut decode::Constructed<&mut BytesSource> ) -> Result::Error>> { let mut source = mem::replace( &mut self.bytes, Bytes::new() ).into_source(); let res = self.mode.decode(&mut source, op); self.bytes = source.into_bytes(); res } /// Trades the value for a bytes value with the raw data. pub fn into_bytes(self) -> Bytes { self.bytes } /// Returns a bytes slice with the raw data of the captured value. pub fn as_slice(&self) -> &[u8] { self.bytes.as_ref() } } //--- Deref and AsRef impl ops::Deref for Captured { type Target = Bytes; fn deref(&self) -> &Bytes { &self.bytes } } impl AsRef for Captured { fn as_ref(&self) -> &Bytes { &self.bytes } } impl AsRef<[u8]> for Captured { fn as_ref(&self) -> &[u8] { self.bytes.as_ref() } } //--- IntoSource impl IntoSource for Captured { type Source = BytesSource; fn into_source(self) -> Self::Source { BytesSource::with_offset(self.bytes, self.start) } } //--- encode::Values impl encode::Values for Captured { fn encoded_len(&self, mode: Mode) -> usize { assert!( !(self.mode != mode && mode != Mode::Ber), "Trying to encode a captured value with incompatible mode" ); self.bytes.len() } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { assert!( !(self.mode != mode && mode != Mode::Ber), "Trying to encode a captured value with incompatible mode" ); target.write_all(self.bytes.as_ref()) } } //--- Debug impl fmt::Debug for Captured { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[ ")?; for (i, &v) in self.bytes.iter().enumerate() { write!(f, "{:02x} ", v)?; if i % 4 == 3 { write!(f, " ")?; } } write!(f, "]") } } //------------ CapturedBuilder ----------------------------------------------- pub struct CapturedBuilder { bytes: BytesMut, mode: Mode, } impl CapturedBuilder { pub fn new(mode: Mode) -> Self { CapturedBuilder { bytes: BytesMut::new(), mode } } pub fn with_capacity(capacity: usize, mode: Mode) -> Self { CapturedBuilder { bytes: BytesMut::with_capacity(capacity), mode } } /// Extends the captured value by encoding the given values. /// /// The function encodes the given values in the captured value’s own mode /// and places the encoded content at the end of the captured value. pub fn extend(&mut self, values: V) { values.write_encoded( self.mode, &mut CapturedWriter(&mut self.bytes) ).unwrap() } pub fn freeze(self) -> Captured { Captured::new(self.bytes.freeze(), self.mode, Pos::default()) } } impl From for CapturedBuilder { fn from(src: Captured) -> Self { CapturedBuilder { bytes: src.bytes.as_ref().into(), mode: src.mode } } } //------------ CapturedWriter ------------------------------------------------ struct CapturedWriter<'a>(&'a mut BytesMut); impl<'a> io::Write for CapturedWriter<'a> { fn write(&mut self, buf: &[u8]) -> Result { self.0.extend_from_slice(buf); Ok(buf.len()) } fn flush(&mut self) -> Result<(), io::Error> { Ok(()) } } bcder-0.7.3/src/decode/content.rs000064400000000000000000001523551046102023000147570ustar 00000000000000//! Parsing BER encoded values. //! //! This is an internal module. Its public types are re-exported by the //! parent. #![allow(unused_imports)] #![allow(dead_code)] use std::fmt; use std::convert::Infallible; use bytes::Bytes; use smallvec::SmallVec; use crate::captured::Captured; use crate::int::{Integer, Unsigned}; use crate::length::Length; use crate::mode::Mode; use crate::tag::Tag; use super::error::{ContentError, DecodeError}; use super::source::{ CaptureSource, IntoSource, LimitedSource, Pos, SliceSource, Source, }; //------------ Content ------------------------------------------------------- /// The content octets of a BER-encoded value. /// /// A value is either primitive, containing actual octets of an actual value, /// or constructed, in which case its content contains additional BER encoded /// values. This enum is useful for cases where a certain type may be encoded /// as either a primitive value or a complex constructed value. /// /// Note that this type represents the content octets only, i.e., it does not /// contain the tag of the value. pub enum Content<'a, S: 'a> { /// The value is a primitive value. Primitive(Primitive<'a, S>), /// The value is a constructed value. Constructed(Constructed<'a, S>) } impl<'a, S: Source + 'a> Content<'a, S> { /// Checks that the content has been parsed completely. /// /// Returns a malformed error if not. fn exhausted(self) -> Result<(), DecodeError> { match self { Content::Primitive(inner) => inner.exhausted(), Content::Constructed(mut inner) => inner.exhausted() } } /// Returns the encoding mode used by the value. pub fn mode(&self) -> Mode { match *self { Content::Primitive(ref inner) => inner.mode(), Content::Constructed(ref inner) => inner.mode() } } /// Returns whether this value is a primitive value. pub fn is_primitive(&self) -> bool { match *self { Content::Primitive(_) => true, Content::Constructed(_) => false, } } /// Returns whether this value is a constructed value. pub fn is_constructed(&self) -> bool { match *self { Content::Primitive(_) => false, Content::Constructed(_) => true, } } /// Converts a reference into into one to a primitive value or errors out. pub fn as_primitive( &mut self ) -> Result<&mut Primitive<'a, S>, DecodeError> { match *self { Content::Primitive(ref mut inner) => Ok(inner), Content::Constructed(ref inner) => { Err(inner.content_err("expected primitive value")) } } } /// Converts a reference into on to a constructed value or errors out. pub fn as_constructed( &mut self ) -> Result<&mut Constructed<'a, S>, DecodeError> { match *self { Content::Primitive(ref inner) => { Err(inner.content_err("expected constructed value")) } Content::Constructed(ref mut inner) => Ok(inner), } } /// Produces a content error at the current source position. pub fn content_err( &self, err: impl Into, ) -> DecodeError { match *self { Content::Primitive(ref inner) => inner.content_err(err), Content::Constructed(ref inner) => inner.content_err(err), } } } #[allow(clippy::wrong_self_convention)] impl<'a, S: Source + 'a> Content<'a, S> { /// Converts content into a `u8`. /// /// If the content is not primitive or does not contain a single BER /// encoded INTEGER value between 0 and 256, returns a malformed error. pub fn to_u8(&mut self) -> Result> { if let Content::Primitive(ref mut prim) = *self { prim.to_u8() } else { Err(self.content_err("expected integer (0..255)")) } } /// Skips over the content if it contains an INTEGER of value `expected`. /// /// The content needs to be primitive and contain a validly encoded /// integer of value `expected` or else a malformed error will be /// returned. pub fn skip_u8_if( &mut self, expected: u8, ) -> Result<(), DecodeError> { let res = self.to_u8()?; if res == expected { Ok(()) } else { Err(self.content_err(ExpectedIntValue(expected))) } } /// Converts content into a `u16`. /// /// If the content is not primitive or does not contain a single BER /// encoded INTEGER value between 0 and 2^16-1, returns a malformed error. pub fn to_u16(&mut self) -> Result> { if let Content::Primitive(ref mut prim) = *self { prim.to_u16() } else { Err(self.content_err("expected integer (0..65535)")) } } /// Converts content into a `u32`. /// /// If the content is not primitive or does not contain a single BER /// encoded INTEGER value between 0 and 2^32-1, returns a malformed error. pub fn to_u32(&mut self) -> Result> { if let Content::Primitive(ref mut prim) = *self { prim.to_u32() } else { Err(self.content_err("expected integer (0..4294967295)")) } } /// Converts content into a `u64`. /// /// If the content is not primitive or does not contain a single BER /// encoded INTEGER value between 0 and 2^64-1, returns a malformed error. pub fn to_u64(&mut self) -> Result> { if let Content::Primitive(ref mut prim) = *self { prim.to_u64() } else { Err(self.content_err("expected integer (0..2**64-1)")) } } /// Converts the content into a NULL value. /// /// If the content isn’t primitive and contains a single BER encoded /// NULL value (i.e., nothing), returns a malformed error. pub fn to_null(&mut self) -> Result<(), DecodeError> { if let Content::Primitive(ref mut prim) = *self { prim.to_null() } else { Err(self.content_err("expected NULL")) } } } //------------ Primitive ----------------------------------------------------- /// The content octets of a primitive value. /// /// You will receive a reference to a value of this type through a closure, /// possibly wrapped in a `Content` value. Your task will be to read out all /// the octets of the value before returning from the closure or produce an /// error if the value isn’t correctly encoded. If you read less octets than /// are available, whoever called the closure will produce an error after /// you returned. Thus, you can read as many octets as you expect and not /// bother to check whether that was all available octets. /// /// The most basic way to do this is through the primitive’s implementation /// of the `Source` trait. Thus, you can gain access to some or all of the /// octets and mark them read by advancing over them. You can safely attempt /// to read more octets than available as that will reliably result in a /// malformed error. /// /// A number of methods are available to deal with the encodings defined for /// various types. These are prefixed by `to_` to indicate that they are /// intended to convert the content to a certain type. They all read exactly /// one encoded value. /// /// The value provides access to the decoding mode via the `mode` method. /// All methodes that decode data will honour the decoding mode and enforce /// that data is encoded according to the mode. pub struct Primitive<'a, S: 'a> { /// The underlying source limited to the length of the value. source: &'a mut LimitedSource, /// The decoding mode to operate in. mode: Mode, /// The start position of the value in the source. start: Pos, } /// # Value Management /// impl<'a, S: 'a> Primitive<'a, S> { /// Creates a new primitive from the given source and mode. fn new(source: &'a mut LimitedSource, mode: Mode) -> Self where S: Source { Primitive { start: source.pos(), source, mode } } /// Returns the current decoding mode. /// /// The higher-level `to_` methods will use this mode to enforce that /// data is encoded correctly. pub fn mode(&self) -> Mode { self.mode } /// Sets the current decoding mode. pub fn set_mode(&mut self, mode: Mode) { self.mode = mode } } impl<'a, S: Source + 'a> Primitive<'a, S> { /// Produces a content error at the current source position. pub fn content_err( &self, err: impl Into, ) -> DecodeError { DecodeError::content(err, self.start) } } /// # High-level Decoding /// #[allow(clippy::wrong_self_convention)] impl<'a, S: Source + 'a> Primitive<'a, S> { /// Parses the primitive value as a BOOLEAN value. pub fn to_bool(&mut self) -> Result> { let res = self.take_u8()?; if self.mode != Mode::Ber { match res { 0 => Ok(false), 0xFF => Ok(true), _ => { Err(self.content_err("invalid boolean")) } } } else { Ok(res != 0) } } /// Parses the primitive value as an INTEGER limited to a `i8`. pub fn to_i8(&mut self) -> Result> { Integer::i8_from_primitive(self) } /// Parses the primitive value as an INTEGER limited to a `i8`. pub fn to_i16(&mut self) -> Result> { Integer::i16_from_primitive(self) } /// Parses the primitive value as an INTEGER limited to a `i8`. pub fn to_i32(&mut self) -> Result> { Integer::i32_from_primitive(self) } /// Parses the primitive value as an INTEGER limited to a `i8`. pub fn to_i64(&mut self) -> Result> { Integer::i64_from_primitive(self) } /// Parses the primitive value as an INTEGER limited to a `i8`. pub fn to_i128(&mut self) -> Result> { Integer::i128_from_primitive(self) } /// Parses the primitive value as an INTEGER limited to a `u8`. pub fn to_u8(&mut self) -> Result> { Unsigned::u8_from_primitive(self) } /// Parses the primitive value as an INTEGER limited to a `u16`. pub fn to_u16(&mut self) -> Result> { Unsigned::u16_from_primitive(self) } /// Parses the primitive value as an INTEGER limited to a `u32`. pub fn to_u32(&mut self) -> Result> { Unsigned::u32_from_primitive(self) } /// Parses the primitive value as a INTEGER value limited to a `u64`. pub fn to_u64(&mut self) -> Result> { Unsigned::u64_from_primitive(self) } /// Parses the primitive value as a INTEGER value limited to a `u128`. pub fn to_u128(&mut self) -> Result> { Unsigned::u64_from_primitive(self) } /// Converts the content octets to a NULL value. /// /// Since such a value is empty, this doesn’t really do anything. pub fn to_null(&mut self) -> Result<(), DecodeError> { if self.remaining() > 0 { Err(self.content_err("invalid NULL value")) } else { Ok(()) } } } /// # Low-level Access /// /// For basic low-level access, `Primitive` implements the `Source` trait. /// Because the length of the content is guaranteed to be known, it can /// provide a few additional methods. Note that these may still fail because /// the underlying source doesn’t guarantee that as many octets are actually /// available. impl<'a, S: Source + 'a> Primitive<'a, S> { /// Returns the number of remaining octets. /// /// The returned value reflects what is left of the expected length of /// content and therefore decreases when the primitive is advanced. pub fn remaining(&self) -> usize { self.source.limit().unwrap() } /// Skips the rest of the content. /// /// Returns a malformed error if the source ends before the expected /// length of content. pub fn skip_all(&mut self) -> Result<(), DecodeError> { self.source.skip_all() } /// Returns the remainder of the content as a `Bytes` value. pub fn take_all(&mut self) -> Result> { self.source.take_all() } /// Returns a bytes slice of the remainder of the content. pub fn slice_all(&mut self) -> Result<&[u8], DecodeError> { let remaining = self.remaining(); if self.source.request(remaining)? < remaining { Err(self.source.content_err("unexpected end of data")) } else { Ok(&self.source.slice()[..remaining]) } } /// Process a slice of the remainder of the content via a closure. pub fn with_slice_all( &mut self, op: F, ) -> Result> where F: FnOnce(&[u8]) -> Result, E: Into, { let remaining = self.remaining(); if self.source.request(remaining)? < remaining { return Err(self.source.content_err("unexpected end of data")); } let res = op(&self.source.slice()[..remaining]).map_err(|err| { self.content_err(err) })?; self.source.advance(remaining); Ok(res) } /// Checkes whether all content has been advanced over. fn exhausted(self) -> Result<(), DecodeError> { self.source.exhausted() } } /// # Support for Testing /// impl Primitive<'static, ()> { /// Decode a bytes slice via a closure. /// /// This method can be used in testing code for decoding primitive /// values by providing a bytes slice with the content. For instance, /// decoding the `to_bool` method could be tested like this: /// /// ``` /// use bcder::Mode; /// use bcder::decode::Primitive; /// /// assert_eq!( /// Primitive::decode_slice( /// b"\x00".as_ref(), Mode::Der, /// |prim| prim.to_bool() /// ).unwrap(), /// false /// ) /// ``` pub fn decode_slice( data: &[u8], mode: Mode, op: F ) -> Result> where F: FnOnce( &mut Primitive ) -> Result> { let mut lim = LimitedSource::new(data.into_source()); lim.set_limit(Some(data.len())); let mut prim = Primitive::new(&mut lim, mode); let res = op(&mut prim)?; prim.exhausted()?; Ok(res) } } //--- Source impl<'a, S: Source + 'a> Source for Primitive<'a, S> { type Error = S::Error; fn pos(&self) -> Pos { self.source.pos() } fn request(&mut self, len: usize) -> Result { self.source.request(len) } fn slice(&self) -> &[u8] { self.source.slice() } fn bytes(&self, start: usize, end: usize) -> Bytes { self.source.bytes(start, end) } fn advance(&mut self, len: usize) { self.source.advance(len) } } //------------ Constructed --------------------------------------------------- /// The content octets of a constructed value. /// /// You will only ever receive a mutable reference to a value of this type /// as an argument to a closure provided to some function. The closure will /// have to process all content of the constructed value. /// /// Since constructed values consist of a sequence of values, the methods /// allow you to process these values one by one. The most basic of these /// are [`take_value`] and [`take_opt_value`] which process exactly one /// value or up to one value. A number of convenience functions exists on /// top of them for commonly encountered types and cases. /// /// Because the caller of your closure checks whether all content has been /// advanced over and raising an error of not, you only need to read as many /// values as you expected to be present and can simply return when you think /// you are done. /// /// [`take_value`]: #method.take_value /// [`take_opt_value`]: #method.take_opt_value #[derive(Debug)] pub struct Constructed<'a, S: 'a> { /// The underlying source. source: &'a mut LimitedSource, /// The state we are in so we can determine the end of the content. state: State, /// The encoding mode to use. mode: Mode, /// The start position of the value in the source. start: Pos, } /// # General Management /// impl<'a, S: Source + 'a> Constructed<'a, S> { /// Creates a new source from the given components. fn new( source: &'a mut LimitedSource, state: State, mode: Mode ) -> Self { Constructed { start: source.pos(), source, state, mode } } /// Decode a source as constructed content. /// /// The function will start decoding of `source` in the given mode. It /// will pass a constructed content value to the closure `op` which /// has to process all the content and return a result or error. /// /// This function is identical to calling [`Mode::decode`]. /// /// [`Mode::decode`]: ../enum.Mode.html#method.decode pub fn decode( source: I, mode: Mode, op: F, ) -> Result> where I: IntoSource, F: FnOnce(&mut Constructed) -> Result> { let mut source = LimitedSource::new(source.into_source()); let mut cons = Constructed::new(&mut source, State::Unbounded, mode); let res = op(&mut cons)?; cons.exhausted()?; Ok(res) } /// Returns the encoding mode used by the value. pub fn mode(&self) -> Mode { self.mode } /// Sets the encoding mode to be used for the value. pub fn set_mode(&mut self, mode: Mode) { self.mode = mode } } impl<'a, S: Source + 'a> Constructed<'a, S> { /// Produces a content error at start of the value. pub fn content_err( &self, err: impl Into, ) -> DecodeError { DecodeError::content(err, self.start) } } /// # Fundamental Reading /// impl<'a, S: Source + 'a> Constructed<'a, S> { /// Checks whether all content has been advanced over. /// /// For a value of definite length, this is the case when the limit of the /// source has been reached. For indefinite values, we need to have either /// already read or can now read the end-of-value marker. fn exhausted(&mut self) -> Result<(), DecodeError> { match self.state { State::Done => Ok(()), State::Definite => { self.source.exhausted() } State::Indefinite => { let (tag, constructed) = Tag::take_from(self.source)?; if tag != Tag::END_OF_VALUE || constructed || !Length::take_from(self.source, self.mode)?.is_zero() { Err(self.content_err("unexpected trailing values")) } else { Ok(()) } } State::Unbounded => Ok(()) } } /// Returns whether we have already reached the end. /// /// For indefinite values, we may be at the end right now but don’t /// know it yet. fn is_exhausted(&self) -> bool { match self.state { State::Definite => { self.source.limit().unwrap() == 0 } State::Indefinite => false, State::Done => true, State::Unbounded => false, } } /// Processes the next value. /// /// If `expected` is not `None`, the method will only process a value /// with the given tag and return `Ok(None)` if there isn’t another value /// or if the next value has a different tag. /// /// If `expected` is `None`, the method will process a value with any /// tag and only return `Ok(None)` if it reached the end of the value. /// /// The closure `op` receives both the tag and content for the next /// value. It must process the value, advancing the source to its end /// or return an error. fn process_next_value( &mut self, expected: Option, op: F ) -> Result, DecodeError> where F: FnOnce(Tag, &mut Content) -> Result> { if self.is_exhausted() { return Ok(None) } let (tag, constructed) = if let Some(expected) = expected { ( expected, match expected.take_from_if(self.source)? { Some(compressed) => compressed, None => return Ok(None) } ) } else { Tag::take_from(self.source)? }; let length = Length::take_from(self.source, self.mode)?; if tag == Tag::END_OF_VALUE { if let State::Indefinite = self.state { if constructed { return Err(self.source.content_err( "constructed end of value" )) } if !length.is_zero() { return Err(self.source.content_err( "non-empty end of value" )) } self.state = State::Done; return Ok(None) } else { return Err(self.source.content_err( "unexpected end of value" )) } } match length { Length::Definite(len) => { if let Some(limit) = self.source.limit() { if len > limit { return Err(self.source.content_err( "nested value with excessive length" )) } } let old_limit = self.source.limit_further(Some(len)); let res = { let mut content = if constructed { // Definite length constructed values are not allowed // in CER. if self.mode == Mode::Cer { return Err(self.source.content_err( "definite length constructed in CER mode" )) } Content::Constructed( Constructed::new( self.source, State::Definite, self.mode ) ) } else { Content::Primitive( Primitive::new(self.source, self.mode) ) }; let res = op(tag, &mut content)?; content.exhausted()?; res }; self.source.set_limit(old_limit.map(|x| x - len)); Ok(Some(res)) } Length::Indefinite => { if !constructed || self.mode == Mode::Der { return Err(self.source.content_err( "indefinite length constructed in DER mode" )) } let mut content = Content::Constructed( Constructed::new( self.source, State::Indefinite, self.mode ) ); let res = op(tag, &mut content)?; content.exhausted()?; Ok(Some(res)) } } } /// Makes sure the next value is present. fn mandatory( &mut self, op: F, ) -> Result> where F: FnOnce( &mut Constructed ) -> Result, DecodeError>, { match op(self)? { Some(res) => Ok(res), None => Err(self.source.content_err("missing further values")), } } } /// # Processing Contained Values /// /// The methods in this section each process one value of the constructed /// value’s content. impl<'a, S: Source + 'a> Constructed<'a, S> { /// Process one value of content. /// /// The closure `op` receives the tag and content of the next value /// and must process it completely, advancing to the content’s end. /// /// Upon success, the method returns the closure’s return value. The /// method returns a malformed error if there isn’t at least one more /// value available. It also returns an error if the closure returns one /// or if reading from the source fails. pub fn take_value( &mut self, op: F, ) -> Result> where F: FnOnce(Tag, &mut Content) -> Result>, { match self.process_next_value(None, op)? { Some(res) => Ok(res), None => Err(self.content_err("missing further values")), } } /// Processes an optional value. /// /// If there is at least one more value available, the closure `op` is /// given the tag and content of that value and must process it /// completely, advancing to the end of its content. If the closure /// succeeds, its return value is returned as ‘some’ result. /// /// If there are no more values available, the method returns `Ok(None)`. /// It returns an error if the closure returns one or if reading from /// the source fails. pub fn take_opt_value( &mut self, op: F, ) -> Result, DecodeError> where F: FnOnce(Tag, &mut Content) -> Result>, { self.process_next_value(None, op) } /// Processes a value with the given tag. /// /// If the next value has the tag `expected`, its content is being given /// to the closure which has to process it completely and return whatever /// is being returned upon success. /// /// The method will return a malformed error if it encounters any other /// tag or the end of the value. It will also return an error if the /// closure returns an error or doesn’t process the complete values, or /// if accessing the underlying source fails. pub fn take_value_if( &mut self, expected: Tag, op: F ) -> Result> where F: FnOnce(&mut Content) -> Result> { let res = self.process_next_value(Some(expected), |_, content| { op(content) })?; match res { Some(res) => Ok(res), None => Err(self.content_err(ExpectedTag(expected))), } } /// Processes an optional value with the given tag. /// /// If the next value has the tag `expected`, its content is being given /// to the closure which has to process it completely and return whatever /// is to be returned as some value. /// /// If the next value has a different tag or if the end of the value has /// been reached, the method returns `Ok(None)`. It will return an error /// if the closure fails or doesn’t process the complete value, or if /// accessing the underlying source fails. pub fn take_opt_value_if( &mut self, expected: Tag, op: F ) -> Result, DecodeError> where F: FnOnce(&mut Content) -> Result> { self.process_next_value(Some(expected), |_, content| op(content)) } /// Processes a constructed value. /// /// If the next value is a constructed value, its tag and content are /// being given to the closure `op` which has to process it completely. /// If it succeeds, its return value is returned. /// /// If the next value is not a constructed value or there is no next /// value or if the closure doesn’t process the next value completely, /// a malformed error is returned. An error is also returned if the /// closure returns one or if accessing the underlying source fails. pub fn take_constructed( &mut self, op: F ) -> Result> where F: FnOnce( Tag, &mut Constructed ) -> Result>, { self.mandatory(|cons| cons.take_opt_constructed(op)) } /// Processes an optional constructed value. /// /// If the next value is a constructed value, its tag and content are /// being given to the closure `op` which has to process it completely. /// If it succeeds, its return value is returned as some value. /// /// If the end of the value has been reached, the method returns /// `Ok(None)`. /// /// If the next value is not a constructed value or if the closure /// doesn’t process the next value completely, a malformed error is /// returned. An error is also returned if the closure returns one or /// if accessing the underlying source fails. pub fn take_opt_constructed( &mut self, op: F ) -> Result, DecodeError> where F: FnOnce( Tag, &mut Constructed, ) -> Result> { self.process_next_value(None, |tag, content| { op(tag, content.as_constructed()?) }) } /// Processes a constructed value with a required tag. /// /// If the next value is a constructed value with a tag equal to /// `expected`, its content is given to the closure `op` which has to /// process it completely. If the closure succeeds, its return value /// is returned. /// /// If the next value is not constructed or has a different tag, if /// the end of the value has been reached, or if the closure does not /// process the contained value’s content completely, a malformed error /// is returned. An error is also returned if the closure returns one or /// if accessing the underlying source fails. pub fn take_constructed_if( &mut self, expected: Tag, op: F, ) -> Result> where F: FnOnce(&mut Constructed) -> Result>, { self.mandatory(|cons| cons.take_opt_constructed_if(expected, op)) } /// Processes an optional constructed value if it has a given tag. /// /// If the next value is a constructed value with a tag equal to /// `expected`, its content is given to the closure `op` which has to /// process it completely. If the closure succeeds, its return value /// is returned. /// /// If the next value is not constructed, does not have the expected tag, /// or the end of this value has been reached, the method returns /// `Ok(None)`. It returns a malformed error if the closure does not /// process the content of the next value fully. /// /// An error is also returned if the closure returns one or if accessing /// the underlying source fails. pub fn take_opt_constructed_if( &mut self, expected: Tag, op: F, ) -> Result, DecodeError> where F: FnOnce(&mut Constructed) -> Result>, { self.process_next_value(Some(expected), |_, content| { op(content.as_constructed()?) }) } /// Processes a primitive value. /// /// If the next value is primitive, its tag and content are given to the /// closure `op` which has to process it fully. Upon success, the /// closure’s return value is returned. /// /// If the next value is not primitive, if the end of value has been /// reached, or if the closure fails to process the next value’s content /// fully, a malformed error is returned. An error is also returned if /// the closure returns one or if accessing the underlying source fails. pub fn take_primitive( &mut self, op: F, ) -> Result> where F: FnOnce(Tag, &mut Primitive) -> Result>, { self.mandatory(|cons| cons.take_opt_primitive(op)) } /// Processes an optional primitive value. /// /// If the next value is primitive, its tag and content are given to the /// closure `op` which has to process it fully. Upon success, the /// closure’s return value is returned. /// /// If the next value is not primitive or if the end of value has been /// reached, `Ok(None)` is returned. /// If the closure fails to process the next value’s content fully, a /// malformed error is returned. An error is also returned if /// the closure returns one or if accessing the underlying source fails. pub fn take_opt_primitive( &mut self, op: F, ) -> Result, DecodeError> where F: FnOnce(Tag, &mut Primitive) -> Result>, { self.process_next_value(None, |tag, content| { op(tag, content.as_primitive()?) }) } /// Processes a primitive value if it has the right tag. /// /// If the next value is a primitive and its tag matches `expected`, its /// content is given to the closure `op` which has to process it /// completely or return an error, either of which is returned. /// /// The method returns a malformed error if there is no next value, if the /// next value is not a primitive, if it doesn’t have the right tag, or if /// the closure doesn’t advance over the complete content. If access to /// the underlying source fails, an error is returned, too. pub fn take_primitive_if( &mut self, expected: Tag, op: F, ) -> Result> where F: FnOnce(&mut Primitive) -> Result> { self.mandatory(|cons| cons.take_opt_primitive_if(expected, op)) } /// Processes an optional primitive value of a given tag. /// /// If the next value is a primitive and its tag matches `expected`, its /// content is given to the closure `op` which has to process it /// completely or return an error, either of which is returned. /// /// If the end of this value has been reached, if the next value is not /// a primitive or if its tag doesn’t match, the method returns /// `Ok(None)`. If the closure doesn’t process the next value’s content /// fully the method returns a malformed error. If access to the /// underlying source fails, it returns an appropriate error. pub fn take_opt_primitive_if( &mut self, expected: Tag, op: F, ) -> Result, DecodeError> where F: FnOnce(&mut Primitive) -> Result> { self.process_next_value(Some(expected), |_, content| { op(content.as_primitive()?) }) } /// Captures content for later processing /// /// The method gives a representation of the content to the closure `op`. /// If it succeeds, it returns whatever the closure advanced over as a /// [`Captured`] value. /// /// The closure may process no, one, several, or all values of this /// value’s content. /// /// If the closure returns an error, this error is returned. /// /// [`Captured`]: ../captures/struct.Captured.html pub fn capture( &mut self, op: F, ) -> Result> where F: FnOnce( &mut Constructed>> ) -> Result<(), DecodeError> { let limit = self.source.limit(); let start = self.source.pos(); let mut source = LimitedSource::new(CaptureSource::new(self.source)); source.set_limit(limit); { let mut constructed = Constructed::new( &mut source, self.state, self.mode ); op(&mut constructed)?; self.state = constructed.state; } Ok(Captured::new( source.unwrap().into_bytes(), self.mode, start, )) } /// Captures one value for later processing /// /// The method takes the next value from this value’s content, whatever /// it its, end returns its encoded form as a [`Captured`] value. /// /// If there is no next value, a malformed error is returned. If access /// to the underlying source fails, an appropriate error is returned. /// /// [`Captured`]: ../captures/struct.Captured.html pub fn capture_one(&mut self) -> Result> { self.capture(|cons| cons.mandatory(|cons| cons.skip_one())) } /// Captures all remaining content for later processing. /// /// The method takes all remaining values from this value’s content and /// returns their encoded form in a `Bytes` value. pub fn capture_all( &mut self ) -> Result> { self.capture(|cons| cons.skip_all()) } /// Skips over content. pub fn skip_opt( &mut self, mut op: F, ) -> Result, DecodeError> where F: FnMut(Tag, bool, usize) -> Result<(), ContentError> { // If we already know we are at the end of the value, we can return. if self.is_exhausted() { return Ok(None) } // The stack for unrolling the recursion. For each level, we keep the // limit the source should be set to when the value ends. For // indefinite values, we keep `None`. let mut stack = SmallVec::<[Option>; 4]>::new(); loop { // Get a the ‘header’ of a value. let (tag, constructed) = Tag::take_from(self.source)?; let length = Length::take_from(self.source, self.mode)?; if !constructed { if tag == Tag::END_OF_VALUE { if length != Length::Definite(0) { return Err(self.content_err("non-empty end of value")) } // End-of-value: The top of the stack needs to be an // indefinite value for it to be allowed. If it is, pop // that value off the stack and continue. The limit is // still that from the value one level above. match stack.pop() { Some(None) => { } None => { // We read end-of-value as the very first value. // This can only happen if the outer value is // an indefinite value. If so, change state and // return. if self.state == State::Indefinite { self.state = State::Done; return Ok(None) } else { return Err(self.content_err( "invalid nested values" )) } } _ => { return Err(self.content_err( "invalid nested values" )) } } } else { // Primitive value. Check for the length to be definite, // check that the caller likes it, then try to read over // it. if let Length::Definite(len) = length { if let Err(err) = op(tag, constructed, stack.len()) { return Err(self.content_err(err)); } if self.source.request(len)? < len { return Err(self.content_err( "short primitive value" )) } self.source.advance(len); } else { return Err(self.content_err( "primitive value with indefinite length" )) } } } else if let Length::Definite(len) = length { // Definite constructed value. First check if the caller // likes it. Check that there is enough limit left for the // value. If so, push the limit at the end of the value to // the stack, update the limit to our length, and continue. if let Err(err) = op(tag, constructed, stack.len()) { return Err(self.content_err(err)); } stack.push(Some(match self.source.limit() { Some(limit) => { match limit.checked_sub(len) { Some(len) => Some(len), None => { return Err(self.content_err( "invalid nested values" )); } } } None => None, })); self.source.set_limit(Some(len)); } else { // Indefinite constructed value. Simply push a `None` to the // stack, if the caller likes it. if let Err(err) = op(tag, constructed, stack.len()) { return Err(self.content_err(err)); } stack.push(None); continue; } // Now we need to check if we have reached the end of a // constructed value. This happens if the limit of the // source reaches 0. Since the ends of several stacked values // can align, we need to loop here. Also, if we run out of // stack, we are done. loop { if stack.is_empty() { return Ok(Some(())) } else if self.source.limit() == Some(0) { match stack.pop() { Some(Some(limit)) => { self.source.set_limit(limit) } Some(None) => { // We need a End-of-value, so running out of // data is an error. return Err(self.content_err(" missing further values" )) } None => unreachable!(), } } else { break; } } } } pub fn skip(&mut self, op: F) -> Result<(), DecodeError> where F: FnMut(Tag, bool, usize) -> Result<(), ContentError> { self.mandatory(|cons| cons.skip_opt(op)) } /// Skips over all remaining content. pub fn skip_all(&mut self) -> Result<(), DecodeError> { while let Some(()) = self.skip_one()? { } Ok(()) } /// Attempts to skip over the next value. /// /// If there is a next value, returns `Ok(Some(()))`, if the end of value /// has already been reached, returns `Ok(None)`. pub fn skip_one(&mut self) -> Result, DecodeError> { if self.is_exhausted() { Ok(None) } else { self.skip(|_, _, _| Ok(()))?; Ok(Some(())) } } } /// # Processing Standard Values /// /// These methods provide short-cuts for processing fundamental values in /// their standard form. That is, the values use their regular tag and /// encoding. impl<'a, S: Source + 'a> Constructed<'a, S> { /// Processes and returns a mandatory boolean value. pub fn take_bool(&mut self) -> Result> { self.take_primitive_if(Tag::BOOLEAN, |prim| prim.to_bool()) } /// Processes and returns an optional boolean value. pub fn take_opt_bool( &mut self, ) -> Result, DecodeError> { self.take_opt_primitive_if(Tag::BOOLEAN, |prim| prim.to_bool()) } /// Processes a mandatory NULL value. pub fn take_null(&mut self) -> Result<(), DecodeError> { self.take_primitive_if(Tag::NULL, |_| Ok(())).map(|_| ()) } /// Processes an optional NULL value. pub fn take_opt_null(&mut self) -> Result<(), DecodeError> { self.take_opt_primitive_if(Tag::NULL, |_| Ok(())).map(|_| ()) } /// Processes a mandatory INTEGER value of the `u8` range. /// /// If the integer value is less than 0 or greater than 255, a malformed /// error is returned. pub fn take_u8(&mut self) -> Result> { self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u8()) } /// Processes an optional INTEGER value of the `u8` range. /// /// If the integer value is less than 0 or greater than 255, a malformed /// error is returned. pub fn take_opt_u8( &mut self, ) -> Result, DecodeError> { self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u8()) } /// Skips over a mandatory INTEGER if it has the given value. /// /// If the next value is an integer but of a different value, returns /// a malformed error. pub fn skip_u8_if( &mut self, expected: u8, ) -> Result<(), DecodeError> { self.take_primitive_if(Tag::INTEGER, |prim| { let got = prim.take_u8()?; if got != expected { Err(prim.content_err(ExpectedIntValue(expected))) } else { Ok(()) } }) } /// Skips over an optional INTEGER if it has the given value. /// /// If the next value is an integer but of a different value, returns /// a malformed error. pub fn skip_opt_u8_if( &mut self, expected: u8, ) -> Result<(), DecodeError> { self.take_opt_primitive_if(Tag::INTEGER, |prim| { let got = prim.take_u8()?; if got != expected { Err(prim.content_err(ExpectedIntValue(expected))) } else { Ok(()) } }).map(|_| ()) } /// Processes a mandatory INTEGER value of the `u16` range. /// /// If the integer value is less than 0 or greater than 65535, a /// malformed error is returned. pub fn take_u16(&mut self) -> Result> { self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u16()) } /// Processes an optional INTEGER value of the `u16` range. /// /// If the integer value is less than 0 or greater than 65535, a /// malformed error is returned. pub fn take_opt_u16( &mut self, ) -> Result, DecodeError> { self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u16()) } /// Processes a mandatory INTEGER value of the `u32` range. /// /// If the integer value is less than 0 or greater than 2^32-1, a /// malformed error is returned. pub fn take_u32(&mut self) -> Result> { self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u32()) } /// Processes a optional INTEGER value of the `u32` range. /// /// If the integer value is less than 0 or greater than 2^32-1, a /// malformed error is returned. pub fn take_opt_u32( &mut self, ) -> Result, DecodeError> { self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u32()) } /// Processes a mandatory INTEGER value of the `u64` range. /// /// If the integer value is less than 0 or greater than 2^64-1, a /// malformed error is returned. pub fn take_u64(&mut self) -> Result> { self.take_primitive_if(Tag::INTEGER, |prim| prim.to_u64()) } /// Processes a optional INTEGER value of the `u64` range. /// /// If the integer value is less than 0 or greater than 2^64-1, a /// malformed error is returned. pub fn take_opt_u64( &mut self, ) -> Result, DecodeError> { self.take_opt_primitive_if(Tag::INTEGER, |prim| prim.to_u64()) } /// Processes a mandatory SEQUENCE value. /// /// This is a shortcut for `self.take_constructed(Tag::SEQUENCE, op)`. pub fn take_sequence( &mut self, op: F, ) -> Result> where F: FnOnce(&mut Constructed) -> Result> { self.take_constructed_if(Tag::SEQUENCE, op) } /// Processes an optional SEQUENCE value. /// /// This is a shortcut for /// `self.take_opt_constructed(Tag::SEQUENCE, op)`. pub fn take_opt_sequence( &mut self, op: F, ) -> Result, DecodeError> where F: FnOnce(&mut Constructed) -> Result> { self.take_opt_constructed_if(Tag::SEQUENCE, op) } /// Processes a mandatory SET value. /// /// This is a shortcut for `self.take_constructed(Tag::SET, op)`. pub fn take_set( &mut self, op: F, ) -> Result> where F: FnOnce(&mut Constructed) -> Result> { self.take_constructed_if(Tag::SET, op) } /// Processes an optional SET value. /// /// This is a shortcut for `self.take_opt_constructed(Tag::SET, op)`. pub fn take_opt_set( &mut self, op: F ) -> Result, DecodeError> where F: FnOnce(&mut Constructed) -> Result> { self.take_opt_constructed_if(Tag::SET, op) } } //------------ State --------------------------------------------------------- /// The processing state of a constructed value. #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum State { /// We are reading until the end of the reader. Definite, /// Indefinite value, we haven’t reached the end yet. Indefinite, /// End of indefinite value reached. Done, /// Unbounded value: read as far as we get. Unbounded, } //============ Error Types =================================================== /// A value with a certain tag was expected. #[derive(Clone, Copy, Debug)] struct ExpectedTag(Tag); impl fmt::Display for ExpectedTag { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "expected tag {}", self.0) } } impl From for ContentError { fn from(err: ExpectedTag) -> Self { ContentError::from_boxed(Box::new(err)) } } /// An integer with a certain value was expected. #[derive(Clone, Copy, Debug)] struct ExpectedIntValue(T); impl fmt::Display for ExpectedIntValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "expected integer value {}", self.0) } } impl From> for ContentError where T: fmt::Display + Send + Sync + 'static { fn from(err: ExpectedIntValue) -> Self { ContentError::from_boxed(Box::new(err)) } } //============ Tests ========================================================= #[cfg(test)] mod test { use super::*; #[test] fn constructed_skip() { // Two primitives. Constructed::decode( b"\x02\x01\x00\x02\x01\x00".into_source(), Mode::Ber, |cons| { cons.skip(|_, _, _| Ok(())).unwrap(); cons.skip(|_, _, _| Ok(())).unwrap(); Ok(()) } ).unwrap(); // One definite constructed with two primitives, then one primitive Constructed::decode( b"\x30\x06\x02\x01\x00\x02\x01\x00\x02\x01\x00".into_source(), Mode::Ber, |cons| { cons.skip(|_, _, _| Ok(())).unwrap(); cons.skip(|_, _, _| Ok(())).unwrap(); Ok(()) } ).unwrap(); // Two nested definite constructeds with two primitives, then one // primitive. Constructed::decode( b"\x30\x08\ \x30\x06\ \x02\x01\x00\x02\x01\x00\ \x02\x01\x00".into_source(), Mode::Ber, |cons| { cons.skip(|_, _, _| Ok(())).unwrap(); cons.skip(|_, _, _| Ok(())).unwrap(); Ok(()) } ).unwrap(); // One definite constructed with one indefinite with two primitives. Constructed::decode( b"\x30\x0A\ \x30\x80\ \x02\x01\x00\x02\x01\x00\ \0\0".into_source(), Mode::Ber, |cons| { cons.skip(|_, _, _| Ok(())).unwrap(); Ok(()) } ).unwrap(); } } bcder-0.7.3/src/decode/error.rs000064400000000000000000000102621046102023000144240ustar 00000000000000//! Error Handling. //! //! This is a private module. Its public content is being re-exported by the //! parent module. use std::{error, fmt}; use std::convert::Infallible; use super::source::Pos; //------------ ContentError -------------------------------------------------- /// An error happened while interpreting BER-encoded data. pub struct ContentError { /// The error message. message: ErrorMessage, } impl ContentError { /// Creates a content error from a static str. pub fn from_static(msg: &'static str) -> Self { ContentError { message: ErrorMessage::Static(msg) } } /// Creates a content error from a boxed trait object. pub fn from_boxed( msg: Box ) -> Self { ContentError { message: ErrorMessage::Boxed(msg) } } } impl From<&'static str> for ContentError { fn from(msg: &'static str) -> Self { Self::from_static(msg) } } impl From for ContentError { fn from(msg: String) -> Self { Self::from_boxed(Box::new(msg)) } } impl From> for ContentError { fn from(err: DecodeError) -> Self { match err.inner { DecodeErrorKind::Source(_) => unreachable!(), DecodeErrorKind::Content { error, .. } => error, } } } impl fmt::Display for ContentError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.message.fmt(f) } } impl fmt::Debug for ContentError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("ContentError") .field(&self.message) .finish() } } //------------ ErrorMessage -------------------------------------------------- /// The actual error message as a hidden enum. enum ErrorMessage { /// The error message is a static str. Static(&'static str), /// The error message is a boxed trait object. Boxed(Box), } impl fmt::Display for ErrorMessage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ErrorMessage::Static(msg) => f.write_str(msg), ErrorMessage::Boxed(ref msg) => msg.fmt(f), } } } impl fmt::Debug for ErrorMessage { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ErrorMessage::Static(msg) => f.write_str(msg), ErrorMessage::Boxed(ref msg) => msg.fmt(f), } } } //------------ DecodeError --------------------------------------------------- /// An error happened while decoding data. /// /// This can either be a source error – which the type is generic over – or a /// content error annotated with the position in the source where it happened. #[derive(Debug)] pub struct DecodeError { inner: DecodeErrorKind, } #[derive(Debug)] enum DecodeErrorKind { Source(S), Content { error: ContentError, pos: Pos, } } impl DecodeError { /// Creates a decode error from a content error and a position. pub fn content(error: impl Into, pos: Pos) -> Self { DecodeError { inner: DecodeErrorKind::Content { error: error.into(), pos }, } } } impl DecodeError { /// Converts a decode error from an infallible source into another error. pub fn convert(self) -> DecodeError { match self.inner { DecodeErrorKind::Source(_) => unreachable!(), DecodeErrorKind::Content { error, pos } => { DecodeError::content(error, pos) } } } } impl From for DecodeError { fn from(err: S) -> Self { DecodeError { inner: DecodeErrorKind::Source(err) } } } impl fmt::Display for DecodeError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.inner { DecodeErrorKind::Source(ref err) => err.fmt(f), DecodeErrorKind::Content { ref error, pos } => { write!(f, "{} (at position {})", error, pos) } } } } impl error::Error for DecodeError { } bcder-0.7.3/src/decode/mod.rs000064400000000000000000000041671046102023000140610ustar 00000000000000//! Parsing BER-encoded data. //! //! This modules provides the means to parse BER-encoded data. //! //! The basic idea is that for each type a function exists that knows how //! to decode one value of that type. For constructed types, this function //! in turn relies on similar functions provided for its constituent types. //! For a detailed introduction to how to write these functions, please //! refer to the [decode section of the guide][crate::guide::decode]. //! //! The two most important types of this module are [`Primitive`] and //! [`Constructed`], representing the content octets of a value in primitive //! and constructed encoding, respectively. Each provides a number of methods //! allowing to parse the content. //! //! You will never create a value of either type. Rather, you get handed a //! reference to one as an argument to a closure or function argument to be //! provided to these methods. //! //! The enum [`Content`] is used for cases where a value can be either //! primitive or constructed such as most string types. //! //! The data for decoding is provided by any type that implements the //! [`Source`] trait – or can be converted into such a type via the //! [`IntoSource`] trait. Implementations for both `bytes::Bytes` and //! `&[u8]` are available. //! //! During decoding, errors can happen. There are two kinds of errors: for //! one, the source can fail to gather more data, e.g., when reading from a //! file fails. Such errors are called _source errors._ Their type is //! provided by the source. //! //! Second, data that cannot be decoded according to the syntax is said to //! result in a _content error._ The [`ContentError`] type is used for such //! errors. //! //! When decoding data from a source, both errors can happen. The type //! `DecodeError` provides a way to store either of them and is the error //! type you will likely encounter the most. pub use self::content::{Content, Constructed, Primitive}; pub use self::error::{ContentError, DecodeError}; pub use self::source::{ BytesSource, CaptureSource, IntoSource, Pos, LimitedSource, SliceSource, Source }; mod content; mod error; mod source; bcder-0.7.3/src/decode/source.rs000064400000000000000000000556071046102023000146070ustar 00000000000000//! The source for decoding data. //! //! This is an internal module. Its public types are re-exported by the //! parent. use std::{error, fmt, mem, ops}; use std::cmp::min; use std::convert::Infallible; use bytes::Bytes; use super::error::{ContentError, DecodeError}; //------------ Source -------------------------------------------------------- /// A view into a sequence of octets. /// /// Sources form that foundation of decoding. They provide the raw octets to /// decoders. /// /// A source can only progress forward over time. It provides the ability to /// access the next few bytes as a slice or a [`Bytes`] value, and advance /// forward. /// /// _Please note:_ This trait may change as we gain more experience with /// decoding in different circumstances. If you implement it for your own /// types, we would appreciate feedback what worked well and what didn’t. pub trait Source { /// The error produced when the source failed to read more data. type Error: error::Error; /// Returns the current logical postion within the sequence of data. fn pos(&self) -> Pos; /// Request at least `len` bytes to be available. /// /// The method returns the number of bytes that are actually available. /// This may only be smaller than `len` if the source ends with less /// bytes available. It may be larger than `len` but less than the total /// number of bytes still left in the source. /// /// The method can be called multiple times without advancing in between. /// If in this case `len` is larger than when last called, the source /// should try and make the additional data available. /// /// The method should only return an error if the source somehow fails /// to get more data such as an IO error or reset connection. fn request(&mut self, len: usize) -> Result; /// Returns a bytes slice with the available data. /// /// The slice will be at least as long as the value returned by the last /// successful [`request`] call. It may be longer if more data is /// available. /// /// [`request`]: #tymethod.request fn slice(&self) -> &[u8]; /// Produces a `Bytes` value from part of the data. /// /// The method returns a [`Bytes`] value of the range `start..end` from /// the beginning of the current view of the source. Both indexes must /// not be greater than the value returned by the last successful call /// to [`request`][Self::request]. /// /// # Panics /// /// The method panics if `start` or `end` are larger than the result of /// the last successful call to [`request`][Self::request]. fn bytes(&self, start: usize, end: usize) -> Bytes; /// Advance the source by `len` bytes. /// /// The method advances the start of the view provided by the source by /// `len` bytes. This value must not be greater than the value returned /// by the last successful call to [`request`][Self::request]. /// /// # Panics /// /// The method panics if `len` is larger than the result of the last /// successful call to [`request`][Self::request]. fn advance(&mut self, len: usize); /// Skip over the next `len` bytes. /// /// The method attempts to advance the source by `len` bytes or by /// however many bytes are still available if this number is smaller, /// without making these bytes available. /// /// Returns the number of bytes skipped over. This value may only differ /// from len if the remainder of the source contains less than `len` /// bytes. /// /// The default implementation uses `request` and `advance`. However, for /// some sources it may be significantly cheaper to provide a specialised /// implementation. fn skip(&mut self, len: usize) -> Result { let res = min(self.request(len)?, len); self.advance(res); Ok(res) } //--- Advanced access /// Takes a single octet from the source. /// /// If there aren’t any more octets available from the source, returns /// a content error. fn take_u8(&mut self) -> Result> { if self.request(1)? < 1 { return Err(self.content_err("unexpected end of data")) } let res = self.slice()[0]; self.advance(1); Ok(res) } /// Takes an optional octet from the source. /// /// If there aren’t any more octets available from the source, returns /// `Ok(None)`. fn take_opt_u8(&mut self) -> Result, Self::Error> { if self.request(1)? < 1 { return Ok(None) } let res = self.slice()[0]; self.advance(1); Ok(Some(res)) } /// Returns a content error at the current position of the source. fn content_err( &self, err: impl Into ) -> DecodeError { DecodeError::content(err.into(), self.pos()) } } impl<'a, T: Source> Source for &'a mut T { type Error = T::Error; fn request(&mut self, len: usize) -> Result { Source::request(*self, len) } fn advance(&mut self, len: usize) { Source::advance(*self, len) } fn slice(&self) -> &[u8] { Source::slice(*self) } fn bytes(&self, start: usize, end: usize) -> Bytes { Source::bytes(*self, start, end) } fn pos(&self) -> Pos { Source::pos(*self) } } //------------ IntoSource ---------------------------------------------------- /// A type that can be converted into a source. pub trait IntoSource { type Source: Source; fn into_source(self) -> Self::Source; } impl IntoSource for T { type Source = Self; fn into_source(self) -> Self::Source { self } } //------------ Pos ----------------------------------------------------------- /// The logical position within a source. /// /// Values of this type can only be used for diagnostics. They can not be used /// to determine how far a source has been advanced since it was created. This /// is why we used a newtype. #[derive(Clone, Copy, Debug, Default)] pub struct Pos(usize); impl From for Pos { fn from(pos: usize) -> Pos { Pos(pos) } } impl ops::Add for Pos { type Output = Self; fn add(self, rhs: Self) -> Self { Pos(self.0 + rhs.0) } } impl fmt::Display for Pos { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } //------------ BytesSource --------------------------------------------------- /// A source for a bytes value. #[derive(Clone, Debug)] pub struct BytesSource { /// The bytes. data: Bytes, /// The current read position in the data. pos: usize, /// The offset for the reported position. /// /// This is the value reported by `Source::pos` when `self.pos` is zero. offset: Pos, } impl BytesSource { /// Creates a new bytes source from a bytes values. pub fn new(data: Bytes) -> Self { BytesSource { data, pos: 0, offset: 0.into() } } /// Creates a new bytes source with an explicit offset. /// /// When this function is used to create a bytes source, `Source::pos` /// will report a value increates by `offset`. pub fn with_offset(data: Bytes, offset: Pos) -> Self { BytesSource { data, pos: 0, offset } } /// Returns the remaining length of data. pub fn len(&self) -> usize { self.data.len() } /// Returns whether there is any data remaining. pub fn is_empty(&self) -> bool { self.data.is_empty() } /// Splits the first `len` bytes off the source and returns them. /// /// # Panics /// /// This method panics of `len` is larger than `self.len()`. pub fn split_to(&mut self, len: usize) -> Bytes { let res = self.data.split_to(len); self.pos += len; res } /// Converts the source into the remaining bytes. pub fn into_bytes(self) -> Bytes { self.data } } impl Source for BytesSource { type Error = Infallible; fn pos(&self) -> Pos { self.offset + self.pos.into() } fn request(&mut self, _len: usize) -> Result { Ok(self.data.len()) } fn slice(&self) -> &[u8] { self.data.as_ref() } fn bytes(&self, start: usize, end: usize) -> Bytes { self.data.slice(start..end) } fn advance(&mut self, len: usize) { assert!(len <= self.data.len()); bytes::Buf::advance(&mut self.data, len); self.pos += len; } } impl IntoSource for Bytes { type Source = BytesSource; fn into_source(self) -> Self::Source { BytesSource::new(self) } } //------------ SliceSource --------------------------------------------------- #[derive(Clone, Copy, Debug)] pub struct SliceSource<'a> { data: &'a [u8], pos: usize } impl<'a> SliceSource<'a> { /// Creates a new bytes source from a slice. pub fn new(data: &'a [u8]) -> Self { SliceSource { data, pos: 0 } } /// Returns the remaining length of data. pub fn len(&self) -> usize { self.data.len() } /// Returns whether there is any data remaining. pub fn is_empty(&self) -> bool { self.data.is_empty() } /// Splits the first `len` bytes off the source and returns them. /// /// # Panics /// /// This method panics of `len` is larger than `self.len()`. pub fn split_to(&mut self, len: usize) -> &'a [u8] { let (left, right) = self.data.split_at(len); self.data = right; self.pos += len; left } } impl<'a> Source for SliceSource<'a> { type Error = Infallible; fn pos(&self) -> Pos { self.pos.into() } fn request(&mut self, _len: usize) -> Result { Ok(self.data.len()) } fn advance(&mut self, len: usize) { assert!(len <= self.data.len()); self.data = &self.data[len..]; self.pos += len; } fn slice(&self) -> &[u8] { self.data } fn bytes(&self, start: usize, end: usize) -> Bytes { Bytes::copy_from_slice(&self.data[start..end]) } } impl<'a> IntoSource for &'a [u8] { type Source = SliceSource<'a>; fn into_source(self) -> Self::Source { SliceSource::new(self) } } //------------ LimitedSource ------------------------------------------------- /// A source that can be limited to a certain number of octets. /// /// This type wraps another source and allows access to be limited to a /// certain number of octets. It will never provide access to more than /// that number of octets. Any attempt to advance over more octets will /// fail with a malformed error. /// /// The limit is, however, independent of the underlying source. It can /// be larger than the number of octets actually available in the source. /// /// The limit can be changed or even removed at any time. #[derive(Clone, Debug)] pub struct LimitedSource { /// The source this value wraps. source: S, /// The current limit. /// /// If `limit` is `None`, there is no limit. If there is a limit, it /// will be decreased by calls to `advance` accordingly. I.e., this is /// the current limit, not the original limit. limit: Option, } /// # General Management /// impl LimitedSource { /// Creates a new limited source for the given source. /// /// The return limited source will have no limit just yet. pub fn new(source: S) -> Self { LimitedSource { source, limit: None } } /// Unwraps the value and returns the source it was created from. pub fn unwrap(self) -> S { self.source } /// Returns the current limit. /// /// Returns `None` if there is no limit. Otherwise, the number returned /// is the number of remaining octets before the limit is reached. This /// does not necessarily mean that that many octets are actually /// available in the underlying source. pub fn limit(&self) -> Option { self.limit } /// Sets a more strict limit. /// /// The method will panic (!) if you are trying to set a new limit that /// is larger than the current limit or if you are trying to remove /// the limit by passing `None` if there currently is a limit set. /// /// Returns the old limit. pub fn limit_further(&mut self, limit: Option) -> Option { if let Some(cur) = self.limit { match limit { Some(limit) => assert!(limit <= cur), None => panic!("relimiting to unlimited"), } } mem::replace(&mut self.limit, limit) } /// Unconditionally sets a new limit. /// /// If you pass `None`, the limit will be removed. pub fn set_limit(&mut self, limit: Option) { self.limit = limit } } /// # Advanced Access /// impl LimitedSource { /// Skip over all remaining octets until the current limit is reached. /// /// If there currently is no limit, the method will panic. Otherwise it /// will simply advance to the end of the limit which may be something /// the underlying source doesn’t like and thus produce an error. pub fn skip_all(&mut self) -> Result<(), DecodeError> { let limit = self.limit.unwrap(); if self.request(limit)? < limit { return Err(self.content_err("unexpected end of data")) } self.advance(limit); Ok(()) } /// Returns a bytes value containing all octets until the current limit. /// /// If there currently is no limit, the method will panic. Otherwise it /// tries to acquire a bytes value for the octets from the current /// position to the end of the limit and advance to the end of the limit. /// /// This will result in a source error if the underlying source returns /// an error. It will result in a content error if the underlying source /// ends before the limit is reached. pub fn take_all(&mut self) -> Result> { let limit = self.limit.unwrap(); if self.request(limit)? < limit { return Err(self.content_err("unexpected end of data")) } let res = self.bytes(0, limit); self.advance(limit); Ok(res) } /// Checks whether the end of the limit has been reached. /// /// If a limit is currently set, the method will return a malformed /// error if it is larger than zero, i.e., if there are octets left to /// advance over before reaching the limit. /// /// If there is no limit set, the method will try to access one single /// octet and return a malformed error if that is actually possible, i.e., /// if there are octets left in the underlying source. /// /// Any source errors are passed through. If there the data is not /// exhausted as described above, a content error is created. pub fn exhausted(&mut self) -> Result<(), DecodeError> { match self.limit { Some(0) => Ok(()), Some(_limit) => Err(self.content_err("trailing data")), None => { if self.source.request(1)? == 0 { Ok(()) } else { Err(self.content_err("trailing data")) } } } } } impl Source for LimitedSource { type Error = S::Error; fn pos(&self) -> Pos { self.source.pos() } fn request(&mut self, len: usize) -> Result { if let Some(limit) = self.limit { Ok(min(limit, self.source.request(min(limit, len))?)) } else { self.source.request(len) } } fn advance(&mut self, len: usize) { if let Some(limit) = self.limit { assert!( len <= limit, "advanced past end of limit" ); self.limit = Some(limit - len); } self.source.advance(len) } fn slice(&self) -> &[u8] { let res = self.source.slice(); if let Some(limit) = self.limit { if res.len() > limit { return &res[..limit] } } res } fn bytes(&self, start: usize, end: usize) -> Bytes { if let Some(limit) = self.limit { assert!(start <= limit); assert!(end <= limit); } self.source.bytes(start, end) } } //------------ CaptureSource ------------------------------------------------- /// A source that captures what has been advanced over. /// /// A capture source wraps a mutable reference to some other source and /// provides the usual source access. However, instead of dropping octets /// that have been advanced over, it keeps them around and allows taking /// them out as a bytes value. /// /// This type is used by [`Constructed::capture`]. /// /// [`Constructed::capture`]: struct.Constructed.html#method.capture pub struct CaptureSource<'a, S: 'a> { /// The wrapped real source. source: &'a mut S, /// The number of bytes the source has promised to have for us. len: usize, /// The position in the source our view starts at. pos: usize, } impl<'a, S: Source> CaptureSource<'a, S> { /// Creates a new capture source using a reference to some other source. pub fn new(source: &'a mut S) -> Self { CaptureSource { source, len: 0, pos: 0, } } /// Converts the capture source into the captured bytes. pub fn into_bytes(self) -> Bytes { let res = self.source.bytes(0, self.pos); self.skip(); res } /// Drops the captured bytes. /// /// Advances the underlying source to the end of the captured bytes. pub fn skip(self) { self.source.advance(self.pos) } } impl<'a, S: Source + 'a> Source for CaptureSource<'a, S> { type Error = S::Error; fn pos(&self) -> Pos { self.source.pos() + self.pos.into() } fn request(&mut self, len: usize) -> Result { self.len = self.source.request(self.pos + len)?; Ok(self.len - self.pos) } fn slice(&self) -> &[u8] { &self.source.slice()[self.pos..] } fn bytes(&self, start: usize, end: usize) -> Bytes { let start = start + self.pos; let end = end + self.pos; assert!( self.len >= start, "start past the end of data" ); assert!( self.len >= end, "end past the end of data" ); self.source.bytes(start, end) } fn advance(&mut self, len: usize) { assert!( self.len >= self.pos + len, "advanced past the end of data" ); self.pos += len; } } //============ Tests ========================================================= #[cfg(test)] mod test { use super::*; #[test] fn take_u8() { let mut source = b"123".into_source(); assert_eq!(source.take_u8().unwrap(), b'1'); assert_eq!(source.take_u8().unwrap(), b'2'); assert_eq!(source.take_u8().unwrap(), b'3'); assert!(source.take_u8().is_err()) } #[test] fn take_opt_u8() { let mut source = b"123".into_source(); assert_eq!(source.take_opt_u8().unwrap(), Some(b'1')); assert_eq!(source.take_opt_u8().unwrap(), Some(b'2')); assert_eq!(source.take_opt_u8().unwrap(), Some(b'3')); assert_eq!(source.take_opt_u8().unwrap(), None); } #[test] fn bytes_impl() { let mut bytes = Bytes::from_static(b"1234567890").into_source(); assert!(bytes.request(4).unwrap() >= 4); assert!(&Source::slice(&bytes)[..4] == b"1234"); assert_eq!(bytes.bytes(2, 4), Bytes::from_static(b"34")); Source::advance(&mut bytes, 4); assert!(bytes.request(4).unwrap() >= 4); assert!(&Source::slice(&bytes)[..4] == b"5678"); Source::advance(&mut bytes, 4); assert_eq!(bytes.request(4).unwrap(), 2); assert!(&Source::slice(&bytes) == b"90"); bytes.advance(2); assert_eq!(bytes.request(4).unwrap(), 0); } #[test] fn slice_impl() { let mut bytes = b"1234567890".into_source(); assert!(bytes.request(4).unwrap() >= 4); assert!(&bytes.slice()[..4] == b"1234"); assert_eq!(bytes.bytes(2, 4), Bytes::from_static(b"34")); bytes.advance(4); assert!(bytes.request(4).unwrap() >= 4); assert!(&bytes.slice()[..4] == b"5678"); bytes.advance(4); assert_eq!(bytes.request(4).unwrap(), 2); assert!(&bytes.slice() == b"90"); bytes.advance(2); assert_eq!(bytes.request(4).unwrap(), 0); } #[test] fn limited_source() { let mut the_source = LimitedSource::new( b"12345678".into_source() ); the_source.set_limit(Some(4)); let mut source = the_source.clone(); assert!(source.exhausted().is_err()); assert_eq!(source.request(6).unwrap(), 4); source.advance(2); assert!(source.exhausted().is_err()); assert_eq!(source.request(6).unwrap(), 2); source.advance(2); source.exhausted().unwrap(); assert_eq!(source.request(6).unwrap(), 0); let mut source = the_source.clone(); source.skip_all().unwrap(); let source = source.unwrap(); assert_eq!(source.slice(), b"5678"); let mut source = the_source.clone(); assert_eq!(source.take_all().unwrap(), Bytes::from_static(b"1234")); source.exhausted().unwrap(); let source = source.unwrap(); assert_eq!(source.slice(), b"5678"); } #[test] #[should_panic] fn limited_source_far_advance() { let mut source = LimitedSource::new( b"12345678".into_source() ); source.set_limit(Some(4)); assert_eq!(source.request(6).unwrap(), 4); source.advance(4); assert_eq!(source.request(6).unwrap(), 0); source.advance(6); // panics } #[test] #[should_panic] fn limit_further() { let mut source = LimitedSource::new(b"12345".into_source()); source.set_limit(Some(4)); source.limit_further(Some(5)); // panics } #[test] fn capture_source() { let mut source = b"1234567890".into_source(); { let mut capture = CaptureSource::new(&mut source); assert_eq!(capture.request(4).unwrap(), 10); capture.advance(4); assert_eq!(capture.into_bytes(), Bytes::from_static(b"1234")); } assert_eq!(source.data, b"567890"); let mut source = b"1234567890".into_source(); { let mut capture = CaptureSource::new(&mut source); assert_eq!(capture.request(4).unwrap(), 10); capture.advance(4); capture.skip(); } assert_eq!(source.data, b"567890"); } } bcder-0.7.3/src/encode/mod.rs000064400000000000000000000032161046102023000140650ustar 00000000000000//! Encoding data in BER. //! //! This modules provides means to encode data in BER. //! //! Encoding is done using helper types called _encoders_ that represent the //! structure of the BER encoding. These types implement the trait //! [`Values`]. A type that can be encoded as BER typically provides a method //! named `encode` that produces a value of its encoder type representing the //! value’s encoding. If necessary, they can also provide a method //! `encode_as` that does the same thing but allows the caller to provide an //! tag to use for encoding as is necessary for implicit tagging. //! //! The [`Values`] type can then be used to simply write the encoding to //! anything that implements the standard library’s `io::Write` trait. //! //! The trait [`PrimitiveContent`] helps with producing encoders for types //! that use the primitive encoding. Through this trait the types can declare //! how their content is encoded and receive an automatic encoder type based //! on that. //! //! The module also provides a number of helper types that make it easier //! to implement encoders in various situations. //! //! For a more detailed introduction to writing the `encode` methods of //! types, see the [encode section of the guide]. //! //! [`Values`]: trait.Values.html //! [`PrimitiveContent`]: trait.PrimitiveContent.html //! [encode section of the guide]: ../guide/encode/index.html pub use self::primitive::{PrimitiveContent, Primitive}; pub use self::values::{ Values, Choice2, Choice3, Constructed, Iter, Nothing, Slice, iter, sequence, sequence_as, set, set_as, slice, total_encoded_len, write_header, }; mod primitive; mod values; bcder-0.7.3/src/encode/primitive.rs000064400000000000000000000273271046102023000153270ustar 00000000000000//! PrimitiveContent and related types. //! //! This is an internal module. Its public types are re-exported by the //! parent. use std::io; use bytes::Bytes; use crate::length::Length; use crate::mode::Mode; use crate::tag::Tag; use super::values::Values; //------------ PrimitiveContent ---------------------------------------------- /// A type that is encoded as a primitive value. /// /// This trait should be implemented for types that use primitive encoding. /// It defines, how the content octets of a single primitive value containing /// a value of the type are to be created. As a consequence, these types /// gain the [`encode`] and [`encode_as`] methods from their implementation /// of this trait. /// /// Note that the trait requires implementing types to be `Copy` to /// avoid unnecessary lifetime parameters on the encoder type. For types that /// aren’t `Copy`, `PrimitiveContent` should be implemented on a reference to /// the type instead. /// /// [`encode`]: #tymethod.encode /// [`encode_as`]: #tymethod.encode_as pub trait PrimitiveContent: Sized { /// The natural tag of an encoded value of this type. const TAG: Tag; /// Returns the length of the encoded content of this type. fn encoded_len(&self, mode: Mode) -> usize; /// Writes the encoded content to a writer. fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error>; /// Encodes the value to bytes (useful when you need to sign a structure) fn to_encoded_bytes(&self, mode: Mode) -> Bytes { let l = self.encoded_len(mode); let mut w = Vec::with_capacity(l); self.write_encoded(mode, &mut w).unwrap(); w.into() } /// Returns a value encoder for this content using the natural tag. /// /// This is identical to `self.encode_as(Self::TAG)` fn encode(self) -> Primitive { self.encode_as(Self::TAG) } /// Returns a value encoder for this content using the given tag. /// /// The returned value is a content encoder that produces a single /// primitive BER encoded value. The tag for this value is explicitely /// given via the `tag` argument. fn encode_as(self, tag: Tag) -> Primitive { Primitive { tag, prim: self } } /// Returns a value encoder for a reference using the natural tag. fn encode_ref(&self) -> Primitive<&Self> { self.encode_ref_as(Self::TAG) } /// Returns a value encoder for a reference using the given tag. fn encode_ref_as(&self, tag: Tag) -> Primitive<&Self> { Primitive { tag, prim: self } } } //--- Blanket impls impl<'a, T: PrimitiveContent> PrimitiveContent for &'a T { const TAG: Tag = T::TAG; fn encoded_len(&self, mode: Mode) -> usize { (*self).encoded_len(mode) } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { (*self).write_encoded(mode, target) } } //--- impl for built-in types impl PrimitiveContent for u8 { const TAG: Tag = Tag::INTEGER; fn encoded_len(&self, _: Mode) -> usize { if *self > 0x7F { 2 } else { 1 } } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { if *self > 0x7F { target.write_all(&[0])?; } target.write_all(&[*self])?; Ok(()) } } macro_rules! unsigned_content { ( $type:ident, $len:expr) => { impl PrimitiveContent for $type { const TAG: Tag = Tag::INTEGER; fn encoded_len(&self, _: Mode) -> usize { if *self == 0 { 1 } else { let zeros = self.leading_zeros() as usize; if zeros % 8 == 0 { $len - (zeros >> 3) + 1 } else { $len - (zeros >> 3) } } } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { if *self == 0 { target.write_all(&[0x00])?; } else { let mut val = self.swap_bytes(); let mut i = 0; while i < $len { if val as u8 != 0 { break } val >>= 8; i += 1 } if val & 0x80 != 0 { target.write_all(&[0x00])?; } while i < $len { target.write_all(&[val as u8])?; val >>= 8; i += 1 } } Ok(()) } } } } unsigned_content!(u16, 2); unsigned_content!(u32, 4); unsigned_content!(u64, 8); unsigned_content!(u128, 16); impl PrimitiveContent for i8 { const TAG: Tag = Tag::INTEGER; fn encoded_len(&self, _: Mode) -> usize { 1 } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { target.write_all(&[*self as u8])?; Ok(()) } } macro_rules! signed_content { ($type:ident, $len:expr) => { impl PrimitiveContent for $type { const TAG: Tag = Tag::INTEGER; #[allow(clippy::verbose_bit_mask)] fn encoded_len(&self, _: Mode) -> usize { if *self == 0 || *self == -1 { return 1 } let zeros = if *self < 0 { (!*self).leading_zeros() as usize } else { self.leading_zeros() as usize }; if zeros & 0x07 == 0 { // i.e., zeros % 8 == 1 $len + 1 - (zeros >> 3) } else { $len - (zeros >> 3) } } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { if *self == 0 { target.write_all(&[0x00])?; } else if *self == -1 { target.write_all(&[0xFF])?; } else if *self < 0 { let mut val = self.swap_bytes(); let mut i = 0; // Skip over leading 0xFF. while i < $len { if val as u8 != 0xFF { break } val >>= 8; i += 1; } // If the first non-0xFF doesn’t have the left-most bit // set, we need an 0xFF for the sign. if val & 0x80 != 0x80 { target.write_all(&[0xFF])?; } while i < $len { target.write_all(&[val as u8])?; val >>= 8; i += 1 } } else { let mut val = self.swap_bytes(); let mut i = 0; // Skip over leading zero bytes. while i < $len { if val as u8 != 0x00 { break } val >>= 8; i += 1; } // If the first non-zero has the left-most bit // set, we need an 0x00 for the sign. if val & 0x80 == 0x80 { target.write_all(&[0x00])?; } while i < $len { target.write_all(&[val as u8])?; val >>= 8; i += 1 } } Ok(()) } } } } signed_content!(i16, 2); signed_content!(i32, 4); signed_content!(i64, 8); signed_content!(i128, 16); impl PrimitiveContent for () { const TAG: Tag = Tag::NULL; fn encoded_len(&self, _: Mode) -> usize { 0 } fn write_encoded( &self, _: Mode, _: &mut W ) -> Result<(), io::Error> { Ok(()) } } impl PrimitiveContent for bool { const TAG: Tag = Tag::BOOLEAN; fn encoded_len(&self, _: Mode) -> usize { 1 } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { if *self { target.write_all(&[0xff]) } else { target.write_all(&[0]) } } } impl<'a> PrimitiveContent for &'a [u8] { const TAG: Tag = Tag::OCTET_STRING; fn encoded_len(&self, _: Mode) -> usize { self.len() } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { target.write_all(self) } } //------------ Primitive ----------------------------------------------------- /// A value encoder for primitively encoded types. /// /// This type is returned by [`PrimitiveContent::encode`] and /// [`PrimitiveContent::encode_as`]. /// /// [`PrimitiveContent::encode`]: trait.PrimitiveContent.html#tymethod_encode /// [`PrimitiveContent::encode_as`]: trait.PrimitiveContent.html#tymethod_encode_as pub struct Primitive

{ /// The tag for this value. tag: Tag, /// The primitive content. prim: P } impl Values for Primitive

{ fn encoded_len(&self, mode: Mode) -> usize { let len = self.prim.encoded_len(mode); self.tag.encoded_len() + Length::Definite(len).encoded_len() + len } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { self.tag.write_encoded(false, target)?; Length::Definite(self.prim.encoded_len(mode)).write_encoded(target)?; self.prim.write_encoded(mode, target) } } //============ Tests ========================================================= #[cfg(test)] mod test { use super::*; fn test_der(value: T, expected: &[u8]) { assert_eq!(value.encoded_len(Mode::Der), expected.len()); let mut target = Vec::new(); value.write_encoded(Mode::Der, &mut target).unwrap(); assert_eq!(target, expected); } #[test] fn encode_u32() { test_der(0u32, b"\0"); test_der(0x12u32, b"\x12"); test_der(0xf2u32, b"\0\xf2"); test_der(0x1234u32, b"\x12\x34"); test_der(0xf234u32, b"\0\xf2\x34"); test_der(0x123400u32, b"\x12\x34\x00"); test_der(0xf23400u32, b"\0\xf2\x34\x00"); test_der(0x12345678u32, b"\x12\x34\x56\x78"); test_der(0xA2345678u32, b"\x00\xA2\x34\x56\x78"); } #[test] fn encode_i32() { test_der(0i32, b"\0"); test_der(0x12i32, b"\x12"); test_der(0xf2i32, b"\0\xf2"); test_der(0x1234i32, b"\x12\x34"); test_der(0xf234i32, b"\0\xf2\x34"); test_der(0x123400i32, b"\x12\x34\x00"); test_der(0xf23400i32, b"\0\xf2\x34\x00"); test_der(0x12345678i32, b"\x12\x34\x56\x78"); test_der(-1i32, b"\xFF"); test_der(-0xF0i32, b"\xFF\x10"); test_der(-0xF000i32, b"\xFF\x10\x00"); test_der(-12000i32, b"\xD1\x20"); test_der(-1200000i32, b"\xED\xB0\x80"); } } bcder-0.7.3/src/encode/values.rs000064400000000000000000000370431046102023000146120ustar 00000000000000//! Everything related to the `Values` trait. //! //! This is an internal module. Its public types are re-exported by the //! parent. use std::io; use std::marker::PhantomData; use crate::captured::Captured; use crate::length::Length; use crate::mode::Mode; use crate::tag::Tag; //------------ Values -------------------------------------------------------- /// A type that is a value encoder. /// /// Value encoders know how to encode themselves into a /// sequence of BER encoded values. While you can impl this trait for your /// type manually, in practice it is often easier to define a method called /// `encode` and let it return some dedicated value encoder type constructed /// from the types provided by this module. /// /// A type implementing this trait should encodes itself into one or more /// BER values. That is, the type becomes the content or part of the content /// of a constructed value. pub trait Values { /// Returns the length of the encoded values for the given mode. fn encoded_len(&self, mode: Mode) -> usize; /// Encodes the values in the given mode and writes them to `target`. fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error>; //--- Provided methods /// Converts the encoder into one with an explicit tag. fn explicit(self, tag: Tag) -> Constructed where Self: Sized { Constructed::new(tag, self) } /// Captures the encoded values in the given mode. fn to_captured(&self, mode: Mode) -> Captured { let mut target = Vec::new(); self.write_encoded(mode, &mut target).unwrap(); Captured::new(target.into(), mode, Default::default()) } } //--- Blanket impls impl<'a, T: Values> Values for &'a T { fn encoded_len(&self, mode: Mode) -> usize { (*self).encoded_len(mode) } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { (*self).write_encoded(mode, target) } } //--- Impls for Tuples /// Macro for implementing `Values` for tuples. /// /// This macro implements `Values` for all tuples up to a certain degree. /// It needs to be invoked as below. All the `Tx`s are the type parameters /// of the elements the tuple, the numbers are the tuple element numbers. /// The number need to be provided backwards ending in 0. /// /// The `tuple` bit of the macro does the actual impl and invokes itself with /// one less tuple element. The `write` bit below is to implement /// `write_encoded` backwards (i.e., starting with the smallest number). macro_rules! tupl_impl { // Termination: empty lists, do nothing. ( tuple > ) => { }; // Impl values for the complete lists, then recurse to the lists without // their heads. ( tuple $t:ident $( $ttail:ident )* > $i:tt $( $itail:tt )* ) => { impl<$t: Values, $( $ttail: Values ),*> Values for ($t, $( $ttail ),*) { fn encoded_len(&self, mode: Mode) -> usize { self.$i.encoded_len(mode) $( + self.$itail.encoded_len(mode) )* } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { tupl_impl!( write self, mode, target, $i $( $itail )* ); Ok(()) } } tupl_impl!( tuple $($ttail)* > $($itail)* ); }; // Termination: empty lists, do nothing. ( write $self:expr, $mode:expr, $target:expr, ) => { }; // Write all elements of tuple $self in mode $mode to $target in order. ( write $self:expr, $mode:expr, $target:expr, $i:tt $($itail:tt)*) => { tupl_impl!( write $self, $mode, $target, $($itail)* ); $self.$i.write_encoded($mode, $target)? } } // The standard library implements things for tuples up to twelve elements, // so we do the same. tupl_impl!( tuple T11 T10 T9 T8 T7 T6 T5 T4 T3 T2 T1 T0 > 11 10 9 8 7 6 5 4 3 2 1 0 ); //--- Impl for Option /// Encoding of an optional value. /// /// This implementation encodes `None` as nothing, i.e., as an OPTIONAL /// in ASN.1 parlance. impl Values for Option { fn encoded_len(&self, mode: Mode) -> usize { match self { Some(v) => v.encoded_len(mode), None => 0 } } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { match self { Some(v) => v.write_encoded(mode, target), None => Ok(()) } } } //--- Impl for slice and Vec impl Values for [V] { fn encoded_len(&self, mode: Mode) -> usize { self.iter().map(|v| v.encoded_len(mode)).sum() } fn write_encoded(&self, mode: Mode, target: &mut W) -> Result<(), io::Error> { for i in self { i.write_encoded(mode, target)?; }; Ok(()) } } impl Values for Vec { fn encoded_len(&self, mode: Mode) -> usize { self.iter().map(|v| v.encoded_len(mode)).sum() } fn write_encoded(&self, mode: Mode, target: &mut W) -> Result<(), io::Error> { for i in self { i.write_encoded(mode, target)?; }; Ok(()) } } //------------ Constructed --------------------------------------------------- /// A value encoder for a single constructed value. pub struct Constructed { /// The tag of the value. tag: Tag, /// A value encoder for the content of the value. inner: V, } impl Constructed { /// Creates a new constructed value encoder from a tag and content. /// /// The returned value will encode as a single constructed value with /// the given tag and whatever `inner` encodeds to as its content. pub fn new(tag: Tag, inner: V) -> Self { Constructed { tag, inner } } } impl Values for Constructed { fn encoded_len(&self, mode: Mode) -> usize { let len = self.inner.encoded_len(mode); let len = len + match mode { Mode::Ber | Mode::Der => { Length::Definite(len).encoded_len() } Mode::Cer => { Length::Indefinite.encoded_len() + EndOfValue.encoded_len(mode) } }; self.tag.encoded_len() + len } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { self.tag.write_encoded(true, target)?; match mode { Mode::Ber | Mode::Der => { Length::Definite(self.inner.encoded_len(mode)) .write_encoded(target)?; self.inner.write_encoded(mode, target) } Mode::Cer => { Length::Indefinite.write_encoded(target)?; self.inner.write_encoded(mode, target)?; EndOfValue.write_encoded(mode, target) } } } } //------------ Choice2 ------------------------------------------------------- /// A value encoder for a two-variant enum. /// /// Instead of implementing `Values` for an enum manually, you can just /// define a method `encode` that returns a value of this type. pub enum Choice2 { /// The first choice. One(L), /// The second choice. Two(R) } impl Values for Choice2 { fn encoded_len(&self, mode: Mode) -> usize { match *self { Choice2::One(ref inner) => inner.encoded_len(mode), Choice2::Two(ref inner) => inner.encoded_len(mode), } } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { match *self { Choice2::One(ref inner) => inner.write_encoded(mode, target), Choice2::Two(ref inner) => inner.write_encoded(mode, target), } } } //------------ Choice3 ------------------------------------------------------- /// A value encoder for a three-variant enum. /// /// Instead of implementing `Values` for an enum manually, you can just /// define a method `encode` that returns a value of this type. pub enum Choice3 { /// The first choice. One(L), /// The second choice. Two(C), /// The third choice. Three(R) } impl Values for Choice3 { fn encoded_len(&self, mode: Mode) -> usize { match *self { Choice3::One(ref inner) => inner.encoded_len(mode), Choice3::Two(ref inner) => inner.encoded_len(mode), Choice3::Three(ref inner) => inner.encoded_len(mode), } } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { match *self { Choice3::One(ref inner) => inner.write_encoded(mode, target), Choice3::Two(ref inner) => inner.write_encoded(mode, target), Choice3::Three(ref inner) => inner.write_encoded(mode, target), } } } //--------------- Iter ------------------------------------------------------- /// A wrapper for an iterator of values. /// /// The wrapper is needed because a blanket impl on any iterator type is /// currently not possible. /// /// Note that `T` needs to be clone because we need to be able to restart /// iterating at the beginning. pub struct Iter(pub T); impl Iter { /// Creates a new iterator encoder atop `iter`. pub fn new(iter: T) -> Self { Iter(iter) } } /// Wraps an iterator over value encoders into a value encoder. pub fn iter(iter: T) -> Iter { Iter::new(iter) } //--- IntoIterator impl IntoIterator for Iter { type Item = ::Item; type IntoIter = ::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } impl<'a, T: Clone + IntoIterator> IntoIterator for &'a Iter { type Item = ::Item; type IntoIter = ::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.clone().into_iter() } } //--- Values impl Values for Iter where T: Clone + IntoIterator, ::Item: Values { fn encoded_len(&self, mode: Mode) -> usize { self.into_iter().map(|item| item.encoded_len(mode)).sum() } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { self.into_iter().try_for_each(|item| item.write_encoded(mode, target)) } } //------------ Slice --------------------------------------------------------- /// A wrapper for a slice of encodable values. /// /// A value of this type will take something that can provide a reference to /// a slice of some value and a closure that converts the values of the slice /// into something encodable. pub struct Slice where T: AsRef<[U]>, F: Fn(&U) -> V { /// The slice value. value: T, /// The converter function. f: F, /// A markers for extra type arguments. marker: PhantomData<(U, V)>, } impl Slice where T: AsRef<[U]>, F: Fn(&U) -> V { /// Creates a new wrapper for a given value and closure. pub fn new(value: T, f: F) -> Self { Slice { value, f, marker: PhantomData } } } /// Creates an encodable wrapper around a slice. /// /// The function takes a value of a type that can be converted into a slice of /// some type and a function that converts references to slice elements into /// some encoder. pub fn slice(value: T, f: F) -> Slice where T: AsRef<[U]>, F: Fn(&U) -> V { Slice::new(value, f) } //--- Values impl Values for Slice where T: AsRef<[U]>, F: Fn(&U) -> V, V: Values { fn encoded_len(&self, mode: Mode) -> usize { self.value.as_ref().iter().map(|v| (self.f)(v).encoded_len(mode)).sum() } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { self.value.as_ref().iter().try_for_each(|v| (self.f)(v).write_encoded(mode, target) ) } } //------------ Nothing ------------------------------------------------------- /// A encoder for nothing. /// /// Unsurprisingly, this encodes as zero octets of content. It can be useful /// for writing an encoder for an enum where some of the variants shouldn’t /// result in content at all. pub struct Nothing; impl Values for Nothing { fn encoded_len(&self, _mode: Mode) -> usize { 0 } fn write_encoded( &self, _mode: Mode, _target: &mut W ) -> Result<(), io::Error> { Ok(()) } } //============ Standard Functions ============================================ /// Returns a value encoder for a SEQUENCE containing `inner`. pub fn sequence(inner: V) -> impl Values { Constructed::new(Tag::SEQUENCE, inner) } /// Returns a value encoder for a SEQUENCE with the given tag. /// /// This is identical to `Constructed::new(tag, inner)`. It merely provides a /// more memorial name. pub fn sequence_as(tag: Tag, inner: V) -> impl Values { Constructed::new(tag, inner) } /// Returns a value encoder for a SET containing `inner`. pub fn set(inner: V) -> impl Values { Constructed::new(Tag::SET, inner) } /// Returns a value encoder for a SET with the given tag. /// /// This is identical to `Constructed::new(tag, inner)`. It merely provides a /// more memorial name. pub fn set_as(tag: Tag, inner: V) -> impl Values { Constructed::new(tag, inner) } /// Returns the length for a structure based on the tag and content length. /// /// This is necessary because the length octets have a different length /// depending on the content length. pub fn total_encoded_len(tag: Tag, content_l: usize) -> usize { tag.encoded_len() + Length::Definite(content_l).encoded_len() + content_l } /// Writes the header for a value. /// /// The header in the sense of this function is the identifier octets and the /// length octets. pub fn write_header( target: &mut W, tag: Tag, constructed: bool, content_length: usize ) -> Result<(), io::Error> { tag.write_encoded(constructed, target)?; Length::Definite(content_length).write_encoded(target)?; Ok(()) } //============ Helper Types ================================================== //------------ EndOfValue ---------------------------------------------------- /// A value encoder for the end of value marker. struct EndOfValue; impl Values for EndOfValue { fn encoded_len(&self, _: Mode) -> usize { 2 } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { let buf = [0, 0]; target.write_all(&buf) } } //============ Tests ========================================================= #[cfg(test)] mod test { use super::*; use crate::encode::PrimitiveContent; #[test] fn encode_2_tuple() { let mut res = Vec::new(); (0.encode(), 1.encode()).write_encoded(Mode::Der, &mut res).unwrap(); assert_eq!(res, b"\x02\x01\0\x02\x01\x01"); } #[test] fn encode_4_tuple() { let mut res = Vec::new(); (0.encode(), 1.encode(), 2.encode(), 3.encode()) .write_encoded(Mode::Der, &mut res).unwrap(); assert_eq!(res, b"\x02\x01\0\x02\x01\x01\x02\x01\x02\x02\x01\x03"); } } bcder-0.7.3/src/guide/asn1_and_ber.rs000064400000000000000000000106271046102023000154660ustar 00000000000000//! A short introduction to ASN.1 and BER. //! //! # ASN.1 and Encoding Rules //! //! The _Abstract Syntax Notation One_ (ASN.1) is a formal language that can //! be used to describe the structure of data. Statements describe both data //! types and how they are composed from other types. In addition, values of //! these types can be specified. These rules do not, however, describe how //! the values are to be represented in files or on the network. This is done //! by accompanying standards known as _encoding rules._ Different such rules //! exist. //! //! On set of such encoding rules is the _Basic Encoding Rules_ (BER). They //! are a relatively simple type-length-values encoding that can be derived //! straightforwardly from the ASN.1 notation. BER gives the encoder a number //! of options to accommodate differing use cases. As this means there is not //! necessarily a canonical encoding of a type, two restrictive profiles on //! top of BER have been defined: The _Canonical Encoding Rules_ (CER) cater //! for cases where data is streamed and the final size of values is not //! necessarily known up front while _Distinguished Encoding Rules_ (DER) //! always use the most simple option but require the overall length to be //! availbale before starting to encode. //! //! ASN.1 is currently defined in ITU-T recommendation [X.680], the three //! encoding rules in [X.690]. Both these recommendations are freely available //! from the ITU. //! //! [X.680]: https://www.itu.int/rec/T-REC-X.680-201508-I/en //! [X.690]: https://www.itu.int/rec/T-REC-X.690-201508-I/en //! //! //! # ASN.1 Definitions //! //! ASN.1 collects definitions into documents called modules. All definitions //! create named objects: data types if the names start with a capital letter //! or values if they start with a small letter. //! //! As an example, here is how a certificate is defined by RFC 5280: //! //! ```text //! Certificate ::= SEQUENCE { //! tbsCertificate TBSCertificate, //! signatureAlgorithm AlgorithmIdentifier, //! signature BIT STRING } //! ``` //! //! This snippet defines a data type `Certificate` in terms of a number of //! other types. The terms in all caps are universal types that are part of //! the standard. `SEQUENCE` is a sequence of well defined elements //! provided one after another within the braces. In this case there are //! three elements. The first part is the name of the element and the //! second its type. The two types `TBSCertificate` and `AlgorithmIdentifer` //! are in turn defined elsewhere in the module while `BIT STRING` is a //! universal type representing a sequence of bits. //! //! Universal types are the fundamental building blocks that all ASN.1 //! structures eventually boil down to. Each of these types has an //! identifying code called their tag. The BIT STRING type, for instance, //! has the tag 3 in universal class. //! //! > _Continues:_ //! > * implicit v. explicit tags, //! > * OPTIONAL, DEFAULT. //! //! //! # Encoding ASN.1 Values //! //! The Basic Encoding Rules describe how to encode a values of data types //! described by ASN.1 defintions. Since these definitions are either //! fundamental types or composed from other types, BER distinguishes two //! categories of encodings: primitive encodings for those fundamental //! types and constructed encodings for types that are composed from other //! types. //! //! Both categories consist of three parts: identifier octets, length octets, //! and content octets. The idenitifer octets describe the type of the value. //! They contain its tag and whether primitive or constructed encoding is //! used. The length octets determine the length of the value, more //! specifically the number of octets in the content octet. Those content //! octets finally contain the value’s content. For values in primitive //! encoding the interpretation of those octets depends on the type. For //! values in constructed encoding, the content octets are a sequence of //! values in BER encoding – i.e., the value is constructed from a sequence //! of more values. //! //! > _Continues:_ //! > * details on encoding of tag, //! > * definite v. indefinite length. //! //! //! # Selected Universal Types //! //! ASN.1 defines a wide range of types for all sorts of occassions. In //! practice, you are likely to encounter only a few. The following has //! some details on the types that the _ber_ crate supports. //! //! > _well, it will have, soon …_ bcder-0.7.3/src/guide/decode.rs000064400000000000000000000076001046102023000143720ustar 00000000000000//! Decoding BER-encoded data. //! //! _Note: This guide is still work in progress and will be extended._ //! //! Data encoded in BER is a stream of nested values for which the length //! may or may not be known. Primitive values, for which the length _is_ //! always known, contain a sequence of octets representing a value of //! a certain type. Constructed values are a sequence of other values. These //! values may either have a pre-determined length or a bounded by a special //! value marking the end of the sequence. The overall stream of data can be //! viewed as the content of a constructed value bounded by the end of the //! stream. //! //! In the *ber* crate, the content of a value is parsed through functions. //! These functions are given a mutable reference to the value’s content and //! are tasked with reading and processing all the content of the value. It //! does so by calling methods on the content value. Some of these methods //! dive into nested values. They require their own parsing functions and //! take them as function arguments such as closures. //! //! An example will make this concept more clear. Let’s say we have the //! following ASN.1 specification: //! //! ```text //! EncapsulatedContentInfo ::= SEQUENCE { //! eContentType ContentType, //! eContent [0] EXPLICIT OCTET STRING OPTIONAL //! } //! //! ContentType ::= OBJECT IDENTIFIER //! ``` //! //! Using the types provided by the *ber* crate for object identifiers and //! octet strings, this definition is easily mapped into a Rust struct: //! //! ``` //! use bcder::{Oid, OctetString}; //! //! pub struct EncapsulatedContentInfo { //! content_type: Oid, //! content: Option, //! } //! ``` //! //! By convention, the decoder function is called `take_from`. It looks like //! this: //! //! ``` //! # use bcder::{Oid, OctetString}; //! use bcder::Tag; //! use bcder::decode; //! use bcder::decode::DecodeError; //! //! # pub struct EncapsulatedContentInfo { //! # content_type: Oid, //! # content: Option, //! # } //! # //! impl EncapsulatedContentInfo { //! pub fn take_from( //! cons: &mut decode::Constructed //! ) -> Result> { //! cons.take_sequence(|cons| { //! Ok(EncapsulatedContentInfo { //! content_type: Oid::take_from(cons)?, //! content: cons.take_opt_constructed_if(Tag::ctx(0), |cons| { //! OctetString::take_from(cons) //! })? //! }) //! }) //! } //! } //! ``` //! //! _TODO: Elaborate._ //! //! //! Some types are used with an implicit tag, i.e., the encoding uses //! a different tag than what would normally it would. For these types, a //! function should be provided that only decodes the content. Depending on //! the encoding used for the type, this function should be `from_primitive`, //! `from_constructed`, or `from_content` for types that always use //! primitive encoding, always constructed encoding, or can appear in both //! encodings, respectively. //! //! As our example type always uses constructed encoding, its content //! decoder would look like this: //! //! ``` //! # use bcder::{Oid, OctetString}; //! use bcder::Tag; //! use bcder::decode; //! use bcder::decode::DecodeError; //! //! # pub struct EncapsulatedContentInfo { //! # content_type: Oid, //! # content: Option, //! # } //! # //! impl EncapsulatedContentInfo { //! pub fn from_constructed( //! cons: &mut decode::Constructed //! ) -> Result> { //! Ok(EncapsulatedContentInfo { //! content_type: Oid::take_from(cons)?, //! content: cons.take_opt_constructed_if(Tag::ctx(0), |cons| { //! OctetString::take_from(cons) //! })? //! }) //! } //! } //! ``` //! //! _TODO: Elaborate._ bcder-0.7.3/src/guide/encode.rs000064400000000000000000000050601046102023000144020ustar 00000000000000//! Encoding data in BER. //! //! _Note: This guide is still work in progress and will be extended._ //! //! In many cases, BER requires that a value can state the length of its //! encoded content before actually starting to encode this content. Since //! this requires duplicate code in many cases, we have decided to use //! placeholder objects for encoding. These placeholders, called value //! encoders, are available for most built-in types as well as for various //! constructions such as tuples, a specific type can produce a //! value encoder by manufacturing it from these existing parts. //! //! To return to the example from the decoding guide. It was using this //! ASN.1: //! //! //! ```text //! EncapsulatedContentInfo ::= SEQUENCE { //! eContentType ContentType, //! eContent [0] EXPLICIT OCTET STRING OPTIONAL //! } //! //! ContentType ::= OBJECT IDENTIFIER //! ``` //! //! The structure was represented by this Rust struct: //! //! ``` //! use bcder::{Oid, OctetString}; //! //! pub struct EncapsulatedContentInfo { //! content_type: Oid, //! content: Option, //! } //! ``` //! //! The value encoders all implement the trait [`encode::Values`] which //! represents a sequence of BER-encodable values. The implementation of //! our struct could return such an encoder like this: //! //! ``` //! # use bcder::{Oid, OctetString}; //! # use bcder::encode::PrimitiveContent; //! use bcder::Tag; //! use bcder::encode; //! //! # pub struct EncapsulatedContentInfo { //! # content_type: Oid, //! # content: Option, //! # } //! # //! impl EncapsulatedContentInfo { //! pub fn encode(self) -> impl encode::Values { //! self.encode_as(Tag::SEQUENCE) //! } //! //! pub fn encode_as(self, tag: Tag) -> impl encode::Values { //! encode::sequence_as(tag, ( //! self.content_type.encode(), //! self.content.map(|s| s.encode()) //! )) //! } //! } //! ``` //! //! The conventional name for the method produces a value encoder with the //! natural tag is `encode`. If necessary, `encode_as` should be present to //! allow getting a value encoder with a chosen tag for implicit tagging. //! //! The signature of these methods will most likely require a lifetime bound //! for the return value as in the example above, if the returned value //! contains references to the value or its elements. This is completely fine, //! since typically the returned value will only be used to encode the value //! right away and then dropped. //! //! [`encode::Values`]: ../../encode/trait.Values.html bcder-0.7.3/src/guide/mod.rs000064400000000000000000000005541046102023000137270ustar 00000000000000//! Getting started with the ber crate. //! //! This module provides a short introduction to ASN.1 and the Basic Encoding //! Rules and how the crate can be used to decode and encode values. //! It is only for documentation and does not contain any code. //! //! The guide consists of the following sections: pub mod asn1_and_ber; pub mod decode; pub mod encode; bcder-0.7.3/src/int.rs000064400000000000000000001144111046102023000126430ustar 00000000000000//! Unbounded integers. //! //! In ASN.1 integers are unbounded and, consequently, BER encodes integer in //! a variable length way. While the [decode] and [encode] modules allow //! working with Rust’s native integer types, in some cases variable length //! integers are necessary. This module provides two types, [`Integer`] and //! [`Unsigned`] for signed and unsigned unbounded integers. While the //! second type isn’t strictly necessary, unsigned unbounded integers appear //! often enough in ASN.1 definitions to warrant a separate such type. //! //! [decode]: ../decode/index.html //! [encode]: ../encode/index.html //! [`Integer`]: struct.Integer.html //! [`Unsigned`]: struct.Unsigned.html use std::{cmp, error, fmt, hash, io, mem}; use std::convert::TryFrom; use bytes::Bytes; use crate::decode; use crate::decode::{DecodeError, Source}; use crate::encode::PrimitiveContent; use crate::mode::Mode; use crate::tag::Tag; //------------ Macros for built-in integers ---------------------------------- // // These are only for decoding. Encoding via the PrimitiveContent can be found // in the `encode::primitive` module. macro_rules! slice_to_builtin { // Decodes an integer contained in the slice $slice into the builtin // signed integer type $type. Produces an Ok(value) if this works or // an Err($err) if it doesn’t. ( signed, $slice:expr, $type:ident, $err:expr) => {{ const LEN: usize = mem::size_of::<$type>(); if $slice.len() > LEN { $err } else { // Start with all zeros if positive or all 0xFF if negative // number. There’s always at least one octet. let mut res = if $slice[0] & 0x80 == 0 { [0; LEN] } else { [0xFF; LEN] }; // Copy over all available octets. res[LEN - $slice.len()..].copy_from_slice($slice); Ok($type::from_be_bytes(res)) } }}; // Ditto for unsigned builtin integer types. ( unsigned, $slice:expr, $type:ident, $err:expr) => {{ // This is like signed above except that we can simply error // out if the sign bit is set. const LEN: usize = mem::size_of::<$type>(); if $slice[0] & 0x80 != 0 { $err } else { let val = if $slice[0] == 0 { &$slice[1..] } else { $slice }; if val.len() == 0 { Ok(0) } else if val.len() > LEN { $err } else { let mut res = [0; LEN]; res[LEN - val.len()..].copy_from_slice(val); Ok($type::from_be_bytes(res)) } } }}; } macro_rules! decode_builtin { ( $flavor:ident, $prim:expr, $type:ident) => {{ Self::check_head($prim)?; $prim.with_slice_all(|slice| { slice_to_builtin!( $flavor, slice, $type, Err("invalid integer") ) }) }} } macro_rules! from_builtin { ( $from:ident, $to:ident) => { impl From<$from> for $to { fn from(val: $from) -> $to { unsafe { $to::from_bytes_unchecked(val.to_encoded_bytes(Mode::Der)) } } } } } macro_rules! builtin_from { ($flavor:ident, $from:ident, $to:ident) => { impl<'a> TryFrom<&'a $from> for $to { type Error = OverflowError; fn try_from(val: &'a $from) -> Result<$to, Self::Error> { let val = val.as_slice(); slice_to_builtin!($flavor, val, $to, Err(OverflowError(()))) } } impl TryFrom<$from> for $to { type Error = OverflowError; fn try_from(val: $from) -> Result<$to, Self::Error> { $to::try_from(&val) } } } } //------------ Integer ------------------------------------------------------- /// A BER encoded integer. /// /// As integers are variable length in BER, this type is just a simple wrapper /// atop the underlying `Bytes` value containing the raw content. A value of /// this type is a signed integer. If a value is defined as an unsigned /// integer, i.e., as `INTEGER (0..MAX)`, you should use the sibling type /// [`Unsigned`] instead. /// /// In addition to these two generic types, the content decoders also provide /// methods to parse integers into native integer types such as `i8`. If the /// range of such a type is obviously enough, you might want to consider /// using these methods instead. /// /// # BER Encoding /// /// In BER, an INTEGER is encoded as a primitive value with the content octets /// providing a variable-length, big-endian, two‘s complement byte sequence of /// that integer. Thus, the most-significant bit of the first octet serves as /// the sign bit. /// /// [`Unsigned`]: struct.Unsigned.html #[derive(Clone, Debug)] pub struct Integer(Bytes); impl Integer { unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self { Integer(bytes) } /// Takes a single signed integer from the beginning of an encoded value. /// /// This requires the next value in `cons` to be a primitive value with /// a correctly encoded signed integer. pub fn take_from( cons: &mut decode::Constructed ) -> Result> { cons.take_primitive_if(Tag::INTEGER, Self::from_primitive) } /// Constructs a signed integer from the content of a primitive value. pub fn from_primitive( prim: &mut decode::Primitive ) -> Result> { let res = prim.take_all()?; match (res.first(), res.get(1).map(|x| x & 0x80 != 0)) { (Some(0), Some(false)) => { return Err(prim.content_err("invalid integer")) } (Some(0xFF), Some(true)) => { return Err(prim.content_err("invalid integer")) } (None, _) => { return Err(prim.content_err("invalid integer")) } _ => { } } Ok(Integer(res)) } /// Constructs an `i8` from the content of a primitive value. pub fn i8_from_primitive( prim: &mut decode::Primitive ) -> Result> { Self::check_head(prim)?; prim.take_u8().map(|x| x as i8) } /// Constructs an `i16` from the content of a primitive value. pub fn i16_from_primitive( prim: &mut decode::Primitive ) -> Result> { decode_builtin!(signed, prim, i16) } /// Constructs an `i32` from the content of a primitive value. pub fn i32_from_primitive( prim: &mut decode::Primitive ) -> Result> { decode_builtin!(signed, prim, i32) } /// Constructs an `i64` from the content of a primitive value. pub fn i64_from_primitive( prim: &mut decode::Primitive ) -> Result> { decode_builtin!(signed, prim, i64) } /// Constructs an `i128` from the content of a primitive value. pub fn i128_from_primitive( prim: &mut decode::Primitive ) -> Result> { decode_builtin!(signed, prim, i128) } /// Checks that an integer is started correctly. /// /// Specifically, checks that there is at least one octet and that the /// first nine bits of a multi-octet integer are not all the same. /// /// The latter ensures that an integer is encoded in the smallest possible /// number of octets. If we insist on this rule, we can use the content /// octets as the value for large integers and simply compare slices /// for equality comparision. fn check_head( prim: &mut decode::Primitive ) -> Result<(), DecodeError> { if prim.request(2)? == 0 { return Err(prim.content_err("invalid integer")) } let slice = prim.slice(); match (slice.first(), slice.get(1).map(|x| x & 0x80 != 0)) { (Some(0), Some(false)) => { Err(prim.content_err("invalid integer")) } (Some(0xFF), Some(true)) => { Err(prim.content_err("invalid integer")) } _ => Ok(()) } } /// Trades the integer into a bytes value with the raw content octets. pub fn into_bytes(self) -> Bytes { self.0 } /// Returns a bytes slice with the raw content. pub fn as_slice(&self) -> &[u8] { self.0.as_ref() } /// Returns whether the number is zero. pub fn is_zero(&self) -> bool { self.0[0] == 0 } /// Returns whether the integer is positive. /// /// Also returns `false` if the number is zero. pub fn is_positive(&self) -> bool { if self.0[0] == 0 && self.0.get(1).is_none() { return false } self.0[0] & 0x80 == 0x00 } /// Returns whether the integer is negative. /// /// Also returns `false` if the number is zero. pub fn is_negative(&self) -> bool { self.0[0] & 0x80 == 0x80 } } //--- From and TryFrom from_builtin!(i8, Integer); from_builtin!(i16, Integer); from_builtin!(i32, Integer); from_builtin!(i64, Integer); from_builtin!(i128, Integer); from_builtin!(u8, Integer); from_builtin!(u16, Integer); from_builtin!(u32, Integer); from_builtin!(u64, Integer); from_builtin!(u128, Integer); builtin_from!(signed, Integer, i8); builtin_from!(signed, Integer, i16); builtin_from!(signed, Integer, i32); builtin_from!(signed, Integer, i64); builtin_from!(signed, Integer, i128); builtin_from!(unsigned, Integer, u8); builtin_from!(unsigned, Integer, u16); builtin_from!(unsigned, Integer, u32); builtin_from!(unsigned, Integer, u64); builtin_from!(unsigned, Integer, u128); //--- AsRef impl AsRef for Integer { fn as_ref(&self) -> &Bytes { &self.0 } } impl AsRef<[u8]> for Integer { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } //--- PartialEq and Eq impl PartialEq for Integer { fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) } } impl PartialEq for Integer { fn eq(&self, other: &Unsigned) -> bool { self.eq(&other.0) } } impl Eq for Integer { } // XXX TODO impl for native types //--- PartialOrd and Ord impl PartialOrd for Integer { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for Integer { fn cmp(&self, other: &Self) -> cmp::Ordering { match (self.is_positive(), other.is_positive()) { (true, true) => { // i.e., both > 0 match self.0.len().cmp(&other.0.len()) { cmp::Ordering::Equal => { for (l, r) in self.0.iter().zip(other.0.iter()) { match l.cmp(r) { cmp::Ordering::Equal => { } cmp => return cmp } } cmp::Ordering::Equal } cmp => cmp } } (false, false) => { // i.e., both <= 0 match self.0.len().cmp(&other.0.len()) { cmp::Ordering::Equal => { for (l, r) in self.0.iter().zip(other.0.iter()) { match l.cmp(r) { cmp::Ordering::Equal => { } cmp => return cmp.reverse() } } cmp::Ordering::Equal } cmp => cmp.reverse() } } (false, true) => cmp::Ordering::Less, (true, false) => cmp::Ordering::Greater, } } } //--- Hash impl hash::Hash for Integer { fn hash(&self, h: &mut H) { self.0.hash(h) } } //--- encode::PrimitiveContent impl<'a> PrimitiveContent for &'a Integer { const TAG: Tag = Tag::INTEGER; fn encoded_len(&self, _mode: Mode) -> usize { self.0.len() } fn write_encoded( &self, _mode: Mode, target: &mut W ) -> Result<(), io::Error> { target.write_all(self.0.as_ref()) } } //------------ Unsigned ------------------------------------------------------ /// A BER encoded unsigned integer. /// /// As integers are variable length in BER, this type is just a simple wrapper /// atop the underlying `Bytes` value containing the raw content. It /// guarantees that the wrapped integer is greater or equal to 0. This equals /// an integer defined as `INTEGER (0..MAX)` in ASN.1. /// /// If you need a integer without any restrictions, you can use `Integer`. If /// you have even stricter range restrictions, you can also use the methods /// provided on the content types to decode into Rust’s primitive integer /// types such as `u16`. /// /// # BER Encoding /// /// In BER, an INTEGER is encoded as a primitive value with the content octets /// providing a variable-length, big-endian, two‘s complement byte sequence of /// that integer. Thus, the most-significant bit of the first octet serves as /// the sign bit and, for an unsigned integer, has to be unset. #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct Unsigned(Integer); /// # Decoding and Encoding /// impl Unsigned { unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self { Unsigned(Integer::from_bytes_unchecked(bytes)) } /// Constructs `Unsigned` by copying from a `&[u8]`. /// /// # Errors /// /// Will return a malformed error if the given slice is empty. pub fn from_slice(slice: &[u8]) -> Result { Self::from_bytes(Bytes::copy_from_slice(slice)) } /// Constructs `Unsigned` from `Bytes`, copying only if needed. /// /// # Errors /// /// Will return a malformed error if the given slice is empty. pub fn from_bytes(bytes: Bytes) -> Result { if bytes.is_empty() { return Err(InvalidInteger(())) } // Skip any leading zero bytes. let num_leading_zero_bytes = bytes.as_ref().iter().take_while(|&&b| { b == 0x00 }).count(); let value = bytes.slice(num_leading_zero_bytes..); // Create a new Unsigned integer from the given value bytes, ensuring // that the most-significant bit is zero. let new_bytes = if value[0] & 0x80 == 0 { // Use the value bytes as-is. value } else if num_leading_zero_bytes > 0 { // Use the value bytes and one of the preceeding zero "sign" bytes. bytes.slice(num_leading_zero_bytes - 1..) } else { // Copy the bytes in order to prepend a zero "sign" byte. let mut v: Vec = Vec::with_capacity(value.len() + 1); v.push(0x00); v.extend(value.iter()); Bytes::from(v) }; unsafe { Ok(Unsigned::from_bytes_unchecked(new_bytes)) } } pub fn take_from( cons: &mut decode::Constructed ) -> Result> { cons.take_primitive_if(Tag::INTEGER, Self::from_primitive) } pub fn from_primitive( prim: &mut decode::Primitive ) -> Result> { Self::check_head(prim)?; Integer::from_primitive(prim).map(Unsigned) } pub fn u8_from_primitive( prim: &mut decode::Primitive ) -> Result> { Self::check_head(prim)?; match prim.remaining() { 1 => prim.take_u8(), // sign bit has been checked above. 2 => { // First byte must be 0x00, second is the result. if prim.take_u8()? != 0 { Err(prim.content_err("invalid integer")) } else { prim.take_u8() } } _ => Err(prim.content_err("invalid integer")) } } pub fn u16_from_primitive( prim: &mut decode::Primitive ) -> Result> { Self::check_head(prim)?; match prim.remaining() { 1 => Ok(prim.take_u8()?.into()), 2 => { Ok( u16::from(prim.take_u8()?) << 8 | u16::from(prim.take_u8()?) ) } 3 => { if prim.take_u8()? != 0 { return Err(prim.content_err("invalid integer")) } let res = { u16::from(prim.take_u8()?) << 8 | u16::from(prim.take_u8()?) }; if res < 0x8000 { // This could have been in fewer bytes. Err(prim.content_err("invalid integer")) } else { Ok(res) } } _ => Err(prim.content_err("invalid integer")) } } pub fn u32_from_primitive( prim: &mut decode::Primitive ) -> Result> { decode_builtin!(unsigned, prim, u32) } pub fn u64_from_primitive( prim: &mut decode::Primitive ) -> Result> { decode_builtin!(unsigned, prim, u64) } pub fn u128_from_primitive( prim: &mut decode::Primitive ) -> Result> { decode_builtin!(unsigned, prim, u128) } /// Checks that an unsigned integer is started correctly. /// /// This is the same as `Int::check_head` followed by a check that the /// sign bit is not set. fn check_head( prim: &mut decode::Primitive ) -> Result<(), DecodeError> { Integer::check_head(prim)?; if prim.slice().first().unwrap() & 0x80 != 0 { Err(prim.content_err("invalid integer")) } else { Ok(()) } } /// Trades the integer into a bytes value with the raw content octets. pub fn into_bytes(self) -> Bytes { self.0.into_bytes() } /// Returns a bytes slice with the raw content. pub fn as_slice(&self) -> &[u8] { self.0.as_slice() } /// Returns whether the number is zero. pub fn is_zero(&self) -> bool { self.0.is_zero() } } //--- From and TryFrom from_builtin!(u8, Unsigned); from_builtin!(u16, Unsigned); from_builtin!(u32, Unsigned); from_builtin!(u64, Unsigned); from_builtin!(u128, Unsigned); builtin_from!(signed, Unsigned, i8); builtin_from!(signed, Unsigned, i16); builtin_from!(signed, Unsigned, i32); builtin_from!(signed, Unsigned, i64); builtin_from!(signed, Unsigned, i128); builtin_from!(unsigned, Unsigned, u8); builtin_from!(unsigned, Unsigned, u16); builtin_from!(unsigned, Unsigned, u32); builtin_from!(unsigned, Unsigned, u64); builtin_from!(unsigned, Unsigned, u128); impl TryFrom for Unsigned { type Error = InvalidInteger; fn try_from(value: Bytes) -> Result { Unsigned::from_bytes(value) } } //--- AsRef impl AsRef for Unsigned { fn as_ref(&self) -> &Integer { &self.0 } } impl AsRef for Unsigned { fn as_ref(&self) -> &Bytes { self.0.as_ref() } } impl AsRef<[u8]> for Unsigned { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } //--- endode::PrimitiveContent impl<'a> PrimitiveContent for &'a Unsigned { const TAG: Tag = Tag::INTEGER; fn encoded_len(&self, mode: Mode) -> usize { (&self.0).encoded_len(mode) } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { (&self.0).write_encoded(mode, target) } } //------------ InvalidInteger ------------------------------------------------ /// A octets slice does not contain a validly encoded integer. #[derive(Clone, Copy, Debug)] pub struct InvalidInteger(()); impl fmt::Display for InvalidInteger { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "invalid integer") } } impl error::Error for InvalidInteger { } //------------ OverflowError ------------------------------------------------- #[derive(Clone, Copy, Debug)] pub struct OverflowError(()); impl fmt::Display for OverflowError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "integer out of range") } } impl error::Error for OverflowError { } //============ Tests ========================================================= // XXX There should be more tests here. Especially for the Ord impl. #[cfg(test)] mod test { use super::*; use crate::Mode; use crate::decode::Primitive; fn test_der(value: T, expected: &[u8]) { assert_eq!(value.encoded_len(Mode::Der), expected.len()); let mut target = Vec::new(); value.write_encoded(Mode::Der, &mut target).unwrap(); assert_eq!(target, expected); } #[test] fn is_positive_negative() { let neg = [-0xF74402, -0xF744, -0xF7]; let pos = [0xF7, 0xF744, 0xF74402]; for &i in &neg { assert!(!Integer::from(i).is_positive(), "{}", i); assert!(Integer::from(i).is_negative(), "{}", i); } for &i in &pos { assert!(Integer::from(i).is_positive(), "{}", i); assert!(!Integer::from(i).is_negative(), "{}", i); } assert!(!Integer::from(0).is_positive()); assert!(!Integer::from(0).is_negative()); } #[test] fn cmp() { let ints = [-0xF74402, -0xF744, -0xF7, 0, 0xF7, 0xF744, 0xF74402]; for &left in &ints { for &right in &ints { assert_eq!( Integer::from(left).cmp(&Integer::from(right)), left.cmp(&right), "comparision of {} and {} failed", left, right ) } } } #[test] fn decode_unsigned_builtins() { assert_eq!( Primitive::decode_slice( b"\x00".as_ref(), Mode::Der, |prim| Unsigned::u8_from_primitive(prim) ).unwrap(), 0 ); assert_eq!( Primitive::decode_slice( b"\x7F".as_ref(), Mode::Der, |prim| Unsigned::u8_from_primitive(prim) ).unwrap(), 0x7f ); assert!( Primitive::decode_slice( b"\x80".as_ref(), Mode::Der, |prim| Unsigned::u8_from_primitive(prim) ).is_err() ); assert_eq!( Primitive::decode_slice( b"\x00\x80".as_ref(), Mode::Der, |prim| Unsigned::u8_from_primitive(prim) ).unwrap(), 0x80 ); assert_eq!( Primitive::decode_slice( b"\x00".as_ref(), Mode::Der, |prim| Unsigned::u16_from_primitive(prim) ).unwrap(), 0 ); assert_eq!( Primitive::decode_slice( b"\x12\x34".as_ref(), Mode::Der, |prim| Unsigned::u16_from_primitive(prim) ).unwrap(), 0x1234 ); assert_eq!( Primitive::decode_slice( b"\x00\xA2\x34".as_ref(), Mode::Der, |prim| Unsigned::u16_from_primitive(prim) ).unwrap(), 0xA234 ); assert!( Primitive::decode_slice( b"\xA2\x34".as_ref(), Mode::Der, |prim| Unsigned::u16_from_primitive(prim) ).is_err() ); assert!( Primitive::decode_slice( b"\x00\x12\x34".as_ref(), Mode::Der, |prim| Unsigned::u16_from_primitive(prim) ).is_err() ); assert_eq!( Primitive::decode_slice( b"\x12".as_ref(), Mode::Der, |prim| Unsigned::u32_from_primitive(prim) ).unwrap(), 0x12 ); assert_eq!( Primitive::decode_slice( b"\x12\x34".as_ref(), Mode::Der, |prim| Unsigned::u32_from_primitive(prim) ).unwrap(), 0x1234 ); assert_eq!( Primitive::decode_slice( b"\x12\x34\x56".as_ref(), Mode::Der, |prim| Unsigned::u32_from_primitive(prim) ).unwrap(), 0x123456 ); assert_eq!( Primitive::decode_slice( b"\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u32_from_primitive(prim) ).unwrap(), 0x12345678 ); assert_eq!( Primitive::decode_slice( b"\x00\xA2\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u32_from_primitive(prim) ).unwrap(), 0xA2345678 ); assert!( Primitive::decode_slice( b"\x00\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u32_from_primitive(prim) ).is_err() ); assert!( Primitive::decode_slice( b"\xa2\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u32_from_primitive(prim) ).is_err() ); assert_eq!( Primitive::decode_slice( b"\x12".as_ref(), Mode::Der, |prim| Unsigned::u64_from_primitive(prim) ).unwrap(), 0x12 ); assert_eq!( Primitive::decode_slice( b"\x12\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u64_from_primitive(prim) ).unwrap(), 0x1234567812345678 ); assert_eq!( Primitive::decode_slice( b"\0\xa2\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u64_from_primitive(prim) ).unwrap(), 0xa234567812345678 ); assert!( Primitive::decode_slice( b"\0\x12\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u64_from_primitive(prim) ).is_err() ); assert!( Primitive::decode_slice( b"\x30\x12\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u64_from_primitive(prim) ).is_err() ); assert_eq!( Primitive::decode_slice( b"\x12".as_ref(), Mode::Der, |prim| Unsigned::u64_from_primitive(prim) ).unwrap(), 0x12 ); assert_eq!( Primitive::decode_slice( b"\x12\x34\x56\x78\x12\x34\x56\x78\ \x12\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u128_from_primitive(prim) ).unwrap(), 0x12345678123456781234567812345678 ); assert_eq!( Primitive::decode_slice( b"\0\xa2\x34\x56\x78\x12\x34\x56\x78\ \x12\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u128_from_primitive(prim) ).unwrap(), 0xa2345678123456781234567812345678 ); assert!( Primitive::decode_slice( b"\0\x12\x34\x56\x78\x12\x34\x56\x78 \x12\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u128_from_primitive(prim) ).is_err() ); assert!( Primitive::decode_slice( b"\x30\x12\x34\x56\x78\x12\x34\x56\x78 \x12\x34\x56\x78\x12\x34\x56\x78".as_ref(), Mode::Der, |prim| Unsigned::u128_from_primitive(prim) ).is_err() ); } #[test] fn decode_signed_builtins() { assert_eq!( Primitive::decode_slice( b"\x00".as_ref(), Mode::Der, |prim| Integer::i8_from_primitive(prim) ).unwrap(), 0 ); assert_eq!( Primitive::decode_slice( b"\xFF".as_ref(), Mode::Der, |prim| Integer::i8_from_primitive(prim) ).unwrap(), -1 ); assert!( Primitive::decode_slice( b"\x00\xFF".as_ref(), Mode::Der, |prim| Integer::i8_from_primitive(prim) ).is_err() ); assert!( Primitive::decode_slice( b"\x40\xFF".as_ref(), Mode::Der, |prim| Integer::i8_from_primitive(prim) ).is_err() ); assert_eq!( Primitive::decode_slice( b"\x00".as_ref(), Mode::Der, |prim| Integer::i16_from_primitive(prim) ).unwrap(), 0 ); assert_eq!( Primitive::decode_slice( b"\xFF".as_ref(), Mode::Der, |prim| Integer::i16_from_primitive(prim) ).unwrap(), -1 ); assert_eq!( Primitive::decode_slice( b"\x80\xFF".as_ref(), Mode::Der, |prim| Integer::i16_from_primitive(prim) ).unwrap(), -32513 ); assert!( Primitive::decode_slice( b"\x80\xFF\x32".as_ref(), Mode::Der, |prim| Integer::i16_from_primitive(prim) ).is_err() ); assert!( Primitive::decode_slice( b"\x00\xFF\x32".as_ref(), Mode::Der, |prim| Integer::i16_from_primitive(prim) ).is_err() ); assert_eq!( Primitive::decode_slice( b"\x00".as_ref(), Mode::Der, |prim| Integer::i32_from_primitive(prim) ).unwrap(), 0 ); assert_eq!( Primitive::decode_slice( b"\xff".as_ref(), Mode::Der, |prim| Integer::i32_from_primitive(prim) ).unwrap(), -1 ); assert_eq!( Primitive::decode_slice( b"\x80\xFF".as_ref(), Mode::Der, |prim| Integer::i32_from_primitive(prim) ).unwrap(), -32513 ); } #[test] fn unsigned_builtin_from() { let int = Integer(b"\x00".as_ref().into()); assert_eq!(u8::try_from(&int).unwrap(), 0); assert_eq!(u16::try_from(&int).unwrap(), 0); assert_eq!(u32::try_from(&int).unwrap(), 0); assert_eq!(u64::try_from(&int).unwrap(), 0); assert_eq!(u128::try_from(&int).unwrap(), 0); assert_eq!(i8::try_from(&int).unwrap(), 0); assert_eq!(i16::try_from(&int).unwrap(), 0); assert_eq!(i32::try_from(&int).unwrap(), 0); assert_eq!(i64::try_from(&int).unwrap(), 0); assert_eq!(i128::try_from(&int).unwrap(), 0); let int = Integer(b"\x7F".as_ref().into()); assert_eq!(u8::try_from(&int).unwrap(), 0x7F); assert_eq!(u16::try_from(&int).unwrap(), 0x7F); assert_eq!(u32::try_from(&int).unwrap(), 0x7F); assert_eq!(u64::try_from(&int).unwrap(), 0x7F); assert_eq!(u128::try_from(&int).unwrap(), 0x7F); assert_eq!(i8::try_from(&int).unwrap(), 0x7F); assert_eq!(i16::try_from(&int).unwrap(), 0x7F); assert_eq!(i32::try_from(&int).unwrap(), 0x7F); assert_eq!(i64::try_from(&int).unwrap(), 0x7F); assert_eq!(i128::try_from(&int).unwrap(), 0x7F); let int = Integer(b"\x80".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert!(u16::try_from(&int).is_err()); assert!(u32::try_from(&int).is_err()); assert!(u64::try_from(&int).is_err()); assert!(u128::try_from(&int).is_err()); assert_eq!(i8::try_from(&int).unwrap(), -128); assert_eq!(i16::try_from(&int).unwrap(), -128); assert_eq!(i32::try_from(&int).unwrap(), -128); assert_eq!(i64::try_from(&int).unwrap(), -128); assert_eq!(i128::try_from(&int).unwrap(), -128); let int = Integer(b"\x00\x80".as_ref().into()); assert_eq!(u8::try_from(&int).unwrap(), 0x80); assert_eq!(u16::try_from(&int).unwrap(), 0x80); assert_eq!(u32::try_from(&int).unwrap(), 0x80); assert_eq!(u64::try_from(&int).unwrap(), 0x80); assert_eq!(u128::try_from(&int).unwrap(), 0x80); let int = Integer(b"\x12\x34".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert_eq!(u16::try_from(&int).unwrap(), 0x1234); assert_eq!(u32::try_from(&int).unwrap(), 0x1234); assert_eq!(u64::try_from(&int).unwrap(), 0x1234); assert_eq!(u128::try_from(&int).unwrap(), 0x1234); assert!(i8::try_from(&int).is_err()); assert_eq!(i16::try_from(&int).unwrap(), 0x1234); assert_eq!(i32::try_from(&int).unwrap(), 0x1234); assert_eq!(i64::try_from(&int).unwrap(), 0x1234); assert_eq!(i128::try_from(&int).unwrap(), 0x1234); let int = Integer(b"\xA2\x34".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert!(u16::try_from(&int).is_err()); assert!(u32::try_from(&int).is_err()); assert!(u64::try_from(&int).is_err()); assert!(u128::try_from(&int).is_err()); assert!(i8::try_from(&int).is_err()); assert_eq!(i16::try_from(&int).unwrap(), -24012); assert_eq!(i32::try_from(&int).unwrap(), -24012); assert_eq!(i64::try_from(&int).unwrap(), -24012); assert_eq!(i128::try_from(&int).unwrap(), -24012); let int = Integer(b"\x00\xA2\x34".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert_eq!(u16::try_from(&int).unwrap(), 0xA234); assert_eq!(u32::try_from(&int).unwrap(), 0xA234); assert_eq!(u64::try_from(&int).unwrap(), 0xA234); assert_eq!(u128::try_from(&int).unwrap(), 0xA234); let int = Integer(b"\x12\x34\x56".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert!(u16::try_from(&int).is_err()); assert_eq!(u32::try_from(&int).unwrap(), 0x123456); assert_eq!(u64::try_from(&int).unwrap(), 0x123456); assert_eq!(u128::try_from(&int).unwrap(), 0x123456); assert!(i8::try_from(&int).is_err()); assert!(i16::try_from(&int).is_err()); assert_eq!(i32::try_from(&int).unwrap(), 0x123456); assert_eq!(i64::try_from(&int).unwrap(), 0x123456); assert_eq!(i128::try_from(&int).unwrap(), 0x123456); let int = Integer(b"\x12\x34\x56\x78".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert!(u16::try_from(&int).is_err()); assert_eq!(u32::try_from(&int).unwrap(), 0x12345678); assert_eq!(u64::try_from(&int).unwrap(), 0x12345678); assert_eq!(u128::try_from(&int).unwrap(), 0x12345678); assert!(i8::try_from(&int).is_err()); assert!(i16::try_from(&int).is_err()); assert_eq!(i32::try_from(&int).unwrap(), 0x12345678); assert_eq!(i64::try_from(&int).unwrap(), 0x12345678); assert_eq!(i128::try_from(&int).unwrap(), 0x12345678); let int = Integer(b"\xA2\x34\x56\x78".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert!(u16::try_from(&int).is_err()); assert!(u32::try_from(&int).is_err()); assert!(u64::try_from(&int).is_err()); assert!(u128::try_from(&int).is_err()); assert!(i8::try_from(&int).is_err()); assert!(i16::try_from(&int).is_err()); assert_eq!(i32::try_from(&int).unwrap(), -1573628296); assert_eq!(i64::try_from(&int).unwrap(), -1573628296); assert_eq!(i128::try_from(&int).unwrap(), -1573628296); let int = Integer(b"\x00\xA2\x34\x56\x78".as_ref().into()); assert!(u8::try_from(&int).is_err()); assert!(u16::try_from(&int).is_err()); assert_eq!(u32::try_from(&int).unwrap(), 0xA2345678); assert_eq!(u64::try_from(&int).unwrap(), 0xA2345678); assert_eq!(u128::try_from(&int).unwrap(), 0xA2345678); } #[test] fn encode_variable_length_unsigned_from_slice() { assert!(Unsigned::from_slice(&[]).is_err()); test_der(&Unsigned::from_slice(&[0xFF]).unwrap(), b"\x00\xFF"); test_der(&Unsigned::from_slice(&[0x00, 0xFF]).unwrap(), b"\x00\xFF"); test_der( &Unsigned::from_slice(&[0x00, 0x00, 0xFF]).unwrap(), b"\x00\xFF" ); test_der( &Unsigned::from_slice( &[0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF] ).unwrap(), b"\x00\xDE\xAD\xBE\xEF" ); } #[test] fn encode_variable_length_unsigned_from_bytes() { assert!(Unsigned::from_bytes(Bytes::new()).is_err()); test_der( &Unsigned::from_bytes(Bytes::from(vec![0xFF])).unwrap(), b"\x00\xFF" ); test_der( &Unsigned::from_bytes(Bytes::from(vec![0x00, 0xFF])).unwrap(), b"\x00\xFF" ); test_der( &Unsigned::from_bytes(Bytes::from( vec![0x00, 0x00, 0xFF]) ).unwrap(), b"\x00\xFF" ); test_der( &Unsigned::from_bytes(Bytes::from( vec![0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF] )).unwrap(), b"\x00\xDE\xAD\xBE\xEF" ); } #[test] fn encode_variable_length_unsigned_try_from_bytes() { assert!(Unsigned::try_from(Bytes::new()).is_err()); test_der( &Unsigned::try_from(Bytes::from(vec![0xFF])).unwrap(), b"\x00\xFF" ); test_der( &Unsigned::try_from(Bytes::from(vec![0x00, 0xFF])).unwrap(), b"\x00\xFF" ); test_der( &Unsigned::try_from(Bytes::from(vec![0x00, 0x00, 0xFF])).unwrap(), b"\x00\xFF" ); test_der( &Unsigned::try_from(Bytes::from( vec![0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF] )).unwrap(), b"\x00\xDE\xAD\xBE\xEF" ); } } bcder-0.7.3/src/length.rs000064400000000000000000000203421046102023000133310ustar 00000000000000//! The Length Octets. //! //! This is a private module. Its public items are re-exported by the parent. use std::io; use crate::decode::{DecodeError, Source}; use crate::mode::Mode; //------------ Length ------------------------------------------------------- /// The length octets of an encoded value. /// /// A length value can either be definite, meaning it provides the actual /// number of content octets in the value, or indefinite, in which case the /// content is delimited by a special end-of-value marker. /// /// # BER Encoding /// /// The length can be encoded in one of two basic ways. Which one is used is /// determined by the most significant bit of the first octet. If it is not /// set, the length octets is one octet long and the remaining bits of this /// first octet provide the definite length. Thus, if the first octet is /// less than 128, it provides the definite length already. /// /// If the most significant bit is set, the remaining bits of the first /// octet specify the number of octets that follow to encode the actual /// length. If they specify that there are zero more octets, i.e., the /// value of the first octet is 128, the length is indefinite. Otherwise, /// those following octets give the big-endian encoding of the definite /// length of the content octets. /// /// Under both CER and DER rules, a definite length must be encoded in the /// minimum number of octets. /// /// # Limitation /// /// The current implementation is limited to 4 length bytes on 32 bit systems /// and 5 length bytes on 64 bit sytems. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Length { /// A length value in definite form. /// /// Provides the actual length of the content in octets. Definite(usize), /// A length value in indefinite form. /// /// In this form, the end of a value is determined by a special tag. Indefinite } impl Length { /// Takes a length value from the beginning of a source. pub fn take_from( source: &mut S, mode: Mode ) -> Result> { match source.take_u8()? { // Bit 7 clear: other bits are the length n if (n & 0x80) == 0 => Ok(Length::Definite(n as usize)), // Bit 7 set: other bits are the number of octets that // encode the length. Unless they are all 0, in which case this // is the indefinite form. 0x80 => Ok(Length::Indefinite), 0x81 => { let len = source.take_u8()? as usize; if mode.is_ber() || len > 127 { Ok(Length::Definite(len)) } else { Err(source.content_err("invalid length")) } } 0x82 => { let len = (source.take_u8()? as usize) << 8 | (source.take_u8()? as usize); if mode.is_ber() || len > 255 { Ok(Length::Definite(len)) } else { Err(source.content_err("invalid length")) } } 0x83 => { let len = (source.take_u8()? as usize) << 16 | (source.take_u8()? as usize) << 8 | (source.take_u8()? as usize); if mode.is_ber() || len > 0xFFFF { Ok(Length::Definite(len)) } else { Err(source.content_err("invalid length")) } } 0x84 => { let len = (source.take_u8()? as usize) << 24 | (source.take_u8()? as usize) << 16 | (source.take_u8()? as usize) << 8 | (source.take_u8()? as usize); if mode.is_ber() || len > 0x00FF_FFFF { Ok(Length::Definite(len)) } else { Err(source.content_err("invalid length")) } } _ => { // We only implement up to two length bytes for now. Err(source.content_err( "lengths over 4 bytes not implemented" )) } } } /// Returns whether the length is definite and zero. pub fn is_zero(&self) -> bool { matches!(*self, Length::Definite(0)) } /// Returns the length of the encoded representation of the value. #[cfg(not(target_pointer_width = "64"))] pub fn encoded_len(&self) -> usize { match *self { Length::Indefinite => 1, Length::Definite(len) => { if len < 0x80 { 1 } else if len < 0x1_00 { 2 } else if len < 0x1_0000 { 3 } else if len < 0x100_0000 { 4 } else { panic!("excessive length") } } } } /// Returns the length of the encoded representation of the value. #[cfg(target_pointer_width = "64")] pub fn encoded_len(&self) -> usize { match *self { Length::Indefinite => 1, Length::Definite(len) => { if len < 0x80 { 1 } else if len < 0x1_00 { 2 } else if len < 0x1_0000 { 3 } else if len < 0x100_0000 { 4 } else if len < 0x1_0000_0000 { 5 } else { panic!("excessive length") } } } } /// Writes the encoded value to a target. #[cfg(target_pointer_len = "64")] pub fn write_encoded( &self, target: &mut W ) -> Result<(), io::Error> { match *self { Length::Indefinite => { let buf = [0x80]; target.write_all(&buf) } Length::Definite(len) => { if len < 0x80 { let buf = [len as u8]; target.write_all(&buf) } else if len < 0x1_00 { let buf = [0x81, len as u8]; target.write_all(&buf) } else if len < 0x1_0000 { let buf = [ 0x82, (len >> 8) as u8, len as u8 ]; target.write_all(&buf) } else if len < 0x100_0000 { let buf = [ 0x83, (len >> 16) as u8, (len >> 8) as u8, len as u8 ]; target.write_all(&buf) } else if len < 0x1_0000_0000 { let buf = [ 0x84, (len >> 24) as u8, (len >> 16) as u8, (len >> 8) as u8, len as u8 ]; target.write_all(&buf) } else { panic!("excessive length") } } } } /// Writes the encoded value to a target. #[cfg(not(target_pointer_len = "64"))] pub fn write_encoded( &self, target: &mut W ) -> Result<(), io::Error> { match *self { Length::Indefinite => { let buf = [0x80]; target.write_all(&buf) } Length::Definite(len) => { if len < 0x80 { let buf = [len as u8]; target.write_all(&buf) } else if len < 0x1_00 { let buf = [0x81, len as u8]; target.write_all(&buf) } else if len < 0x1_0000 { let buf = [ 0x82, (len >> 8) as u8, len as u8 ]; target.write_all(&buf) } else if len < 0x100_0000 { let buf = [ 0x83, (len >> 16) as u8, (len >> 8) as u8, len as u8 ]; target.write_all(&buf) } else { panic!("excessive length") } } } } } bcder-0.7.3/src/lib.rs000064400000000000000000000042241046102023000126170ustar 00000000000000//! Handling of data in Basic Encoding Rules. //! //! This crate allows decoding and encoding of data encoded in ASN.1’s _Basic //! Encoding Rules_ as defined in ITU recommendation X.690 as well as their //! stricter companions _Cannonical Encoding Rules_ and _Distringuished //! Encoding Rules._ //! //! You will find a short introduction to ASN.1 and encoding rules as well //! as a discussion of how decoding and encoding with the crate work in //! the [guide] module. The documentation with all the other //! modules serves as a reference documentation. //! //! The most important modules of the crate are [decode] and [encode] that //! provide the machinery for implementing decoding and encoding of data. //! //! Additionally, the crate provides a number of types that help dealing //! with the more complex universal types in ASN.1. Specifically, the //! module [int] provides variable length integers, the module //! [string] contains types for the various kinds of strings defined in //! ASN.1, and [oid] deals with object identifiers. Finally, [captured] //! provides a way to keep encoded data around for later processing. //! The most important types from these modules are also re-exported at //! library level. //! //! [guide]: guide/index.html //! [decode]: decode/index.html //! [encode]: encode/index.thml //! [about_asn1]: about_asn1/index.html //! [int]: int/index.html //! [string]: string/index.html //! [oid]: oid/index.html //! [captured]: captured/index.html // We have seemingly redundant closures (i.e., closures where just providing // a function would also work) that cannot be removed due to lifetime issues. #![allow(clippy::redundant_closure)] //--- Re-exports pub use self::captured::Captured; pub use self::int::{Integer, Unsigned}; pub use self::mode::Mode; pub use self::oid::{ConstOid, Oid}; pub use self::string::{ BitString, OctetString, Ia5String, NumericString, PrintableString, Utf8String, }; pub use self::tag::Tag; //--- Public modules pub mod decode; pub mod encode; pub mod captured; pub mod int; pub mod oid; pub mod string; //--- Private modules mod length; mod mode; mod tag; //--- Elaborate documentation // pub mod guide; bcder-0.7.3/src/mode.rs000064400000000000000000000051071046102023000127760ustar 00000000000000//! The BER mode. //! //! This is a private module. It’s public items are re-exported by the parent. use crate::decode; use crate::decode::DecodeError; //------------ Mode ---------------------------------------------------------- /// The BER Mode. /// /// X.680 defines not one but three sets of related encoding rules. All three /// follow the same basic ideas but implement them in slightly different /// ways. /// /// This type represents these rules. The [`decode`] method provides a way to /// decode a source using the specific decoding mode. You can also change /// the decoding mode later on through the `set_mode` methods of [`Primitive`] /// and [`Constructed`]. /// /// [`decode´]: #method.decode /// [`Primitive`]: decode/struct.Primitive.html /// [`Constructed`]: decode/struct.Constructed.html #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub enum Mode { /// Basic Encoding Rules. /// /// These are the most flexible rules, allowing alternative encodings for /// some types as well as indefinite length values. #[default] Ber, /// Canonical Encoding Rules. /// /// These rules always employ indefinite length encoding for constructed /// values and the shortest possible form for primitive values. There /// are additional restrictions for certain types. Cer, /// Distinguished Encoding Rules. /// /// These rules always employ definite length values and require the /// shortest possible encoding. Additional rules apply to some types. Der, } impl Mode { /// Decode a source using a specific mode. /// /// The method will attempt to decode `source` using the rules represented /// by this value. The closure `op` will be given the content of the /// source as a sequence of values. The closure does not need to process /// all values in the source. pub fn decode( self, source: S, op: F, ) -> Result::Error>> where S: decode::IntoSource, F: FnOnce( &mut decode::Constructed ) -> Result::Error>>, { decode::Constructed::decode(source, self, op) } /// Returns whether the mode is `Mode::Ber`. pub fn is_ber(self) -> bool { matches!(self, Mode::Ber) } /// Returns whether the mode is `Mode::Cer`. pub fn is_cer(self) -> bool { matches!(self, Mode::Cer) } /// Returns whether the mode is `Mode::Der`. pub fn is_der(self) -> bool { matches!(self, Mode::Der) } } bcder-0.7.3/src/oid.rs000064400000000000000000000401061046102023000126230ustar 00000000000000//! ASN.1 Object Identifiers. //! //! This module contains the [`Oid`] type that implements object identifiers, //! a construct used by ANS.1 to uniquely identify all sorts of things. The //! type is also re-exported at the top-level. //! //! [`Oid`]: struct.Oid.html use std::{fmt, hash, io, str::FromStr}; use bytes::Bytes; use crate::encode; use crate::decode::{Constructed, DecodeError, Primitive, Source}; use crate::mode::Mode; use crate::tag::Tag; //------------ Oid ----------------------------------------------------------- /// An object identifer. /// /// Object identifiers are globally unique, hierarchical values that are used /// to identify objects or their type. When written, they are presented as a /// sequence of integers separated by dots such as ‘1.3.6.1.5.5.7.1’ or with /// the integers separated by white space and enclosed in curly braces such /// as ‘{ 1 3 6 1 5 5 7 1 }’. Individual integers or sequences of integers /// can also be given names which then are used instead of the integers. /// /// Values of this type keep a single object identifer in its BER encoding, /// i.e., in some form of byte sequence. Because different representations /// may be useful, the type is actually generic over something that can /// become a reference to a bytes slice. Parsing is only defined for `Bytes` /// values, though. /// /// The only use for object identifiers currently is to compare them to /// predefined values. For this purpose, you typically define your known /// object identifiers in a `oid` submodule as contants of /// `Oid<&'static [u8]>` – or its type alias `ConstOid`. This is also the /// reason why the wrapped value is `pub` for now. This will change once /// `const fn` is stable. /// /// Unfortunately, there is currently no proc macro to generate the object /// identifier constants in the code. Instead, the crate ships with a /// `mkoid` binary which accepts object identifiers in ‘dot integer’ notation /// and produces the `u8` array for their encoded value. You can install /// this binary via `cargo install ber`. #[derive(Clone, Debug)] pub struct Oid = Bytes>(pub T); /// A type alias for `Oid<&'static [u8]>. /// /// This is useful when defining object identifier constants. pub type ConstOid = Oid<&'static [u8]>; /// # Decoding and Encoding /// impl Oid { /// Skips over an object identifier value. /// /// If the source has reached its end, if the next value does not have /// the `Tag::OID`, or if it is not a primitive value containing a /// correctly encoded OID, returns a malformed error. pub fn skip_in( cons: &mut Constructed ) -> Result<(), DecodeError> { cons.take_primitive_if(Tag::OID, Self::skip_primitive) } /// Skips over an optional object identifier value. /// /// If the source has reached its end of if the next value does not have /// the `Tag::OID`, returns `Ok(None)`. If the next value has the right /// tag but is not a primitive value containing a correctly encoded OID, /// returns a malformed error. pub fn skip_opt_in( cons: &mut Constructed ) -> Result, DecodeError> { cons.take_opt_primitive_if(Tag::OID, Self::skip_primitive) } /// Takes an object identifier value from the source. /// /// If the source has reached its end, if the next value does not have /// the `Tag::OID`, or if it is not a primitive value, returns a malformed /// error. pub fn take_from( constructed: &mut Constructed ) -> Result> { constructed.take_primitive_if(Tag::OID, Self::from_primitive) } /// Takes an optional object identifier value from the source. /// /// If the source has reached its end of if the next value does not have /// the `Tag::OID`, returns `Ok(None)`. If the next value has the right /// tag but is not a primitive value, returns a malformed error. pub fn take_opt_from( constructed: &mut Constructed ) -> Result, DecodeError> { constructed.take_opt_primitive_if(Tag::OID, Self::from_primitive) } /// Skips an object identifier in the content of a primitive value. pub fn skip_primitive( prim: &mut Primitive ) -> Result<(), DecodeError> { prim.with_slice_all(Self::check_content) } /// Constructs an object identifier from the content of a primitive value. pub fn from_primitive( prim: &mut Primitive ) -> Result> { let content = prim.take_all()?; Self::check_content(content.as_ref()).map_err(|err| { prim.content_err(err) })?; Ok(Oid(content)) } /// Checks that the content contains a validly encoded OID. /// /// # Caveats /// /// This currently doesn’t check that the sub-identifiers are encoded in /// the smallest amount of octets. fn check_content(content: &[u8]) -> Result<(), &'static str> { // There always has to be a first sub-identifier, i.e., content // must not be empty. We grab the last byte while we are checking for // empty. let last = match content.last() { Some(last) => *last, None => { return Err("empty object identifier") } }; // The last byte must have bit 8 cleared to indicate the end of a // subidentifier. if last & 0x80 != 0 { return Err("illegal object identifier") } Ok(()) } } impl> Oid { /// Skip over an object identifier if it matches `self`. pub fn skip_if( &self, constructed: &mut Constructed, ) -> Result<(), DecodeError> { constructed.take_primitive_if(Tag::OID, |prim| { prim.with_slice_all(|content| { // We are assuming that self contains a properly encoded OID, // so we don’t really need to check if prim does, too, if we // compare for equality. if content != self.0.as_ref() { Err("object identifier mismatch") } else { Ok(()) } }) }) } } /// # Access to Sub-identifiers /// impl> Oid { /// Returns an iterator to the components of this object identifiers. /// /// # Panics /// /// The returned identifier will eventually panic if `self` does not /// contain a correctly encoded object identifier. pub fn iter(&self) -> Iter { Iter::new(self.0.as_ref()) } } //--- AsRef impl> AsRef<[u8]> for Oid { fn as_ref(&self) -> &[u8] { self.0.as_ref() } } //--- PartialEq and Eq impl, U: AsRef<[u8]>> PartialEq> for Oid { fn eq(&self, other: &Oid) -> bool { self.0.as_ref() == other.0.as_ref() } } impl> Eq for Oid { } //--- Hash impl> hash::Hash for Oid { fn hash(&self, state: &mut H) { self.0.as_ref().hash(state) } } //--- Display impl> fmt::Display for Oid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut components = self.iter(); match components.next() { Some(component) => component.fmt(f)?, None => { return Ok(()) } } components.try_for_each(|item| write!(f, ".{}", item)) } } //--- encode::PrimitiveContent impl> encode::PrimitiveContent for Oid { const TAG: Tag = Tag::OID; fn encoded_len(&self, _: Mode) -> usize { self.0.as_ref().len() } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { target.write_all(self.0.as_ref()) } } //--- FromStr impl + From>> FromStr for Oid { type Err = &'static str; fn from_str(s: &str) -> Result { fn from_str(s: &str) -> Result { u32::from_str(s).map_err(|_| "only integer components allowed") } let mut components = s.split('.'); let (first, second) = match (components.next(), components.next()) { (Some(first), Some(second)) => (first, second), _ => { return Err("at least two components required"); } }; let first = from_str(first)?; if first > 2 { return Err("first component can only be 0, 1, or 2.") } let second = from_str(second)?; if first < 2 && second >= 40 { return Err("second component for 0. and 1. must be less than 40"); } let mut res = vec![40 * first + second]; for item in components { res.push(from_str(item)?); } let mut bytes = vec![]; for item in res { // 1111 1111 1111 1111 1111 1111 1111 1111 // EEEE DDDD DDDC CCCC CCBB BBBB BAAA AAAA if item > 0x0FFF_FFFF { bytes.push(((item >> 28) | 0x80) as u8); } if item > 0x001F_FFFF { bytes.push((((item >> 21) & 0x7F) | 0x80) as u8); } if item > 0x0000_3FFF { bytes.push((((item >> 14) & 0x7F) | 0x80) as u8) } if item > 0x0000_007F { bytes.push((((item >> 7) & 0x7F) | 0x80) as u8); } bytes.push((item & 0x7F) as u8); } Ok(Oid(bytes.into())) } } //------------ Component ----------------------------------------------------- /// A component of an object identifier. /// /// Although these components are integers, they are encoded in a slightly /// inconvenient way. Because of this we don’t convert them to native integers /// but rather keep them as references to the underlying octets. /// /// This type allows comparison and formatting, which hopefully is all you’ll /// need. If you insist, the method `to_u32` allows you to try to convert a /// component to a native integer. #[derive(Clone, Copy, Debug)] pub struct Component<'a> { /// The position of the component in the object identifer. position: Position, /// The octets of the subidentifer. /// /// These octets translate to an integer value. The most significant bit /// of each octet indicates whether there are more octets to follow (and /// can thus be ignored in this context), the lower seven bits are then /// shifted accordingly to make up an unsigned integer in big endian /// notation. Since this isn’t bounded in any way, we can’t just simply /// turn these into, say, `u32`s although, realistically, it is unlikely /// there is anything bigger than that. slice: &'a [u8], } /// The position of the component in the object identifier. /// /// As the first two components of the object identifer are encoded in the /// first subidentifier of the encoded value, we have three different cases. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] enum Position { /// This is the first component of the identifier. /// /// This is 0 if the integer value of the subidentifer is 0..39, /// 1 for 40..79, and 2 for anything else. First, /// This is the second component of the identifier. /// /// This is the integer value of the subidentifer module 40 if the value /// is below 80 and otherwise the value minus 80. Second, /// This is any later component of the identifier. /// /// This is identical to the integer value of the subidentifier. Other, } impl<'a> Component<'a> { /// Creates a new component. fn new(position: Position, slice: &'a [u8]) -> Self { Component { position, slice } } /// Attempts to convert the component to `u32`. /// /// Since the component’s value can be larger than the maximum value of /// a `u32`, this may fail in which case the method will return `None`. pub fn to_u32(self) -> Option { // This can be at most five octets with at most four bits in the // topmost octet. if self.slice.len() > 5 || (self.slice.len() == 4 && self.slice[0] & 0x70 != 0) { return None } let mut res = 0; for &ch in self.slice { res = res << 7 | u32::from(ch & 0x7F); } match self.position { Position::First => { if res < 40 { Some(0) } else if res < 80{ Some(1) } else { Some(2) } } Position::Second => { if res < 80 { Some(res % 40) } else { Some(res - 80) } } Position::Other => Some(res) } } } //--- PartialEq and Eq impl<'a> PartialEq for Component<'a> { fn eq(&self, other: &Self) -> bool { self.position == other.position && self.slice == other.slice } } impl<'a> Eq for Component<'a> { } //--- Display impl<'a> fmt::Display for Component<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // XXX This can’t deal correctly with overly large components. // Since this is a really rare (if not non-existant) case, // I can’t be bothered to figure out how to convert a seven // bit integer into decimal. match self.to_u32() { Some(val) => val.fmt(f), None => f.write_str("(very large component)"), } } } //------------ Iter ---------------------------------------------------------- /// An iterator over the sub-identifiers in an object identifier. pub struct Iter<'a> { /// The remainder of the object identifier’s encoded octets. slice: &'a [u8], /// The position of the next component. position: Position, } impl<'a> Iter<'a> { /// Creates a new iterator. fn new(slice: &'a [u8]) -> Self { Iter { slice, position: Position::First } } fn advance_position(&mut self) -> Position { let res = self.position; self.position = match res { Position::First => Position::Second, _ => Position::Other }; res } } impl<'a> Iterator for Iter<'a> { type Item = Component<'a>; fn next(&mut self) -> Option { if self.slice.is_empty() { return None } for i in 0..self.slice.len() { if self.slice[i] & 0x80 == 0 { let (res, tail) = self.slice.split_at(i + 1); if self.position != Position::First { self.slice = tail; } return Some(Component::new(self.advance_position(), res)); } } panic!("illegal object identifier (last octet has bit 8 set)"); } } //============ Tests ======================================================== #[cfg(test)] mod test { use super::*; #[test] fn display() { assert_eq!( "2.5.29.19", format!("{}", Oid(&[85, 29, 19])).as_str() ); } #[test] fn take_and_skip_primitive() { fn check(slice: &[u8], is_ok: bool) { let take = Primitive::decode_slice( slice, Mode::Der, |prim| Oid::from_primitive(prim) ); assert_eq!(take.is_ok(), is_ok); if let Ok(oid) = take { assert_eq!(oid.0.as_ref(), slice); } assert_eq!( Primitive::decode_slice( slice, Mode::Der, |prim| Oid::skip_primitive(prim) ).is_ok(), is_ok ); } check(b"", false); check(b"\x81\x34", true); check(b"\x81\x34\x03", true); check(b"\x81\x34\x83\x03", true); check(b"\x81\x34\x83\x83\x03\x03", true); check(b"\x81\x34\x83", false); } } bcder-0.7.3/src/string/bit.rs000064400000000000000000000300551046102023000141360ustar 00000000000000//! BER-encoded bit strings. //! //! This is a private module. Its public items are re-exported by the parent. use std::io; use bytes::Bytes; use crate::{decode, encode}; use crate::decode::{DecodeError, Source}; use crate::length::Length; use crate::mode::Mode; use crate::tag::Tag; //------------ BitString ----------------------------------------------------- /// A bit string value. /// /// Bit strings are a sequence of bits. Unlike /// [`OctetString`][crate::string::OctetString]s, they do not need to contain /// a multiple of eight bits. /// /// You can parse a bit string value out of a constructed value using the /// [`take_from`][Self::take_from] function. The /// [`from_content`][Self::from_content] function parses the /// content octets of a bit string value and can be used of the bit string is /// implcitely tagged. Alternatively, you can create a new simple bit string /// via the [`new`][Self::new] method. /// /// There are two types of methods for accessing the data in a bit string. /// Methods starting with `bit` operate on the individual bits while those /// prefixed with `octet` access entire octets and ignore the fact that there /// may be unused bits in the final octet. /// /// # BER Encoding /// /// When encoded in BER, bit strings can either be a primitive or /// constructed value. /// /// If encoded as a primitive value, the first octet of the /// content contains the number of unused bits in the last octet and the /// following octets contain the bits with the first bit in the most /// significant bit of the octet. /// /// In the constructed encoding, the bit string is represented as a sequence /// of bit strings which in turn may either be constructed or primitive /// encodings. The only limitation in this nesting is that only the last /// primitively encoded bit string may have a non-zero number of unused bits. /// /// With BER, the sender can choose either form of encoding. With CER, the /// primitive encoding should be chosen if its length would be no more than /// 1000 octets long. Otherwise, the constructed encoding is to be chosen /// which must contain a sequence of primitively encoded bit strings. Each of /// these except for the last one must have content of exactly 1000 octets. /// The last one must be a least one and at most 1000 octets of content. /// With DER, only the primitive form is allowed. /// /// # Limitation /// /// At this time, the `BitString` type does not implement the constructed /// encoding of a bit string. #[derive(Clone, Debug, Eq, PartialEq)] pub struct BitString { /// The number of unused bits in the last byte. unused: u8, /// The bytes of the bit string. bits: Bytes, } impl BitString { /// Creates a new bit string. /// /// # Panic /// /// This function panics if the arguments do not make a valid bit string. /// This happens if `unused` is greater than 7 and if `bits` is /// empty and `unused` is not zero. pub fn new(unused: u8, bits: Bytes) -> Self { // XXX Temporary assertion here until we can re-design the API. assert!(unused <= 7 && (!bits.is_empty() || unused == 0)); Self { unused, bits} } /// Returns the value of the given bit. pub fn bit(&self, bit: usize) -> bool { let idx = bit >> 3; if self.bits.len() <= idx { return false } let bit = 7 - (bit as u8 & 7); if self.bits.len() + 1 == idx && self.unused > bit { return false } self.bits[idx] & (1 << bit) != 0 } /// Returns the number of bits in the bit string. pub fn bit_len(&self) -> usize { (self.bits.len() << 3) - (self.unused as usize) } /// Returns the number of unused bits in the last octet. pub fn unused(&self) -> u8 { self.unused } /// Returns the number of octets in the bit string. pub fn octet_len(&self) -> usize { self.bits.len() } /// Returns an iterator over the octets in the bit string. pub fn octets(&self) -> BitStringIter { BitStringIter(self.bits.iter()) } /// Returns a slice of the octets in the bit string if available. /// /// The method will return `None` if the bit string is constructed from /// several parts. pub fn octet_slice(&self) -> Option<&[u8]> { Some(self.bits.as_ref()) } /// Returns a bytes value of the octets of the bit string. /// /// This will be cheap for primitively encoded bit strings but requires /// allocations for complex ones. pub fn octet_bytes(&self) -> Bytes { self.bits.clone() } } /// # Decoding and Encoding /// impl BitString { /// Takes a single bit string value from constructed content. pub fn take_from( constructed: &mut decode::Constructed ) -> Result> { constructed.take_value_if(Tag::BIT_STRING, Self::from_content) } /// Skip over a single bit string value inside constructed content. pub fn skip_in( cons: &mut decode::Constructed ) -> Result<(), DecodeError> { cons.take_value_if(Tag::BIT_STRING, Self::skip_content) } /// Parses the content octets of a bit string value. pub fn from_content( content: &mut decode::Content ) -> Result> { match *content { decode::Content::Primitive(ref mut inner) => { if inner.mode() == Mode::Cer && inner.remaining() > 1000 { return Err(content.content_err( "long bit string component in CER mode" )) } let unused = inner.take_u8()?; if unused > 7 { return Err(content.content_err( "invalid bit string with large initial octet" )); } if inner.remaining() == 0 && unused > 0 { return Err(content.content_err( "invalid bit string \ (non-zero initial with empty bits)" )); } let bits = inner.take_all()?; // Strictly speaking, we should also check if the unused bits // in the last octet are zero. Ok(BitString { unused, bits }) } decode::Content::Constructed(ref inner) => { if inner.mode() == Mode::Der { Err(content.content_err( "constructed bit string in DER mode" )) } else { Err(content.content_err( "constructed bit string not implemented" )) } } } } /// Skips over the content octets of a bit string value. pub fn skip_content( content: &mut decode::Content ) -> Result<(), DecodeError> { match *content { decode::Content::Primitive(ref mut inner) => { if inner.mode() == Mode::Cer && inner.remaining() > 1000 { return Err(content.content_err( "long bit string component in CER mode" )) } let unused = inner.take_u8()?; if unused > 7 { return Err(content.content_err( "invalid bit string with large initial octet" )); } if inner.remaining() == 0 && unused > 0 { return Err(content.content_err( "invalid bit string \ (non-zero initial with empty bits)" )); } inner.skip_all() } decode::Content::Constructed(ref inner) => { if inner.mode() == Mode::Der { Err(content.content_err( "constructed bit string in DER mode" )) } else { Err(content.content_err( "constructed bit string not implemented" )) } } } } /// Returns a value encoder that encodes a bytes slice as an octet string. pub fn encode_slice(value: T, unused: u8) -> BitSliceEncoder { Self::encode_slice_as(value, unused, Tag::BIT_STRING) } /// Returns a value encoder that encodes a bytes slice as an octet string. pub fn encode_slice_as( value: T, unused: u8, tag: Tag ) -> BitSliceEncoder { BitSliceEncoder::new(value, unused, tag) } } //--- PrimitiveContent impl encode::PrimitiveContent for BitString { const TAG: Tag = Tag::BIT_STRING; fn encoded_len(&self, _: Mode) -> usize { self.bits.len() + 1 } fn write_encoded( &self, _: Mode, target: &mut W ) -> Result<(), io::Error> { target.write_all(&[self.unused])?; target.write_all(self.bits.as_ref()) } } //------------ BitStringIter ------------------------------------------------- /// An iterator over the octets in the bit string. #[derive(Clone, Debug)] pub struct BitStringIter<'a>(::std::slice::Iter<'a, u8>); impl<'a> Iterator for BitStringIter<'a> { type Item = u8; fn next(&mut self) -> Option { self.0.next().cloned() } } //------------ BitSliceEncoder ----------------------------------------------- /// A value encoder for a bytes slice as a bit string. #[derive(Clone, Debug)] pub struct BitSliceEncoder { /// The slice to encode. slice: T, /// The unused bits in the last byte. unused: u8, /// The tag to be used for encoded value. tag: Tag, } impl BitSliceEncoder { /// Creates a new bit slice encoder. fn new(slice: T, unused: u8, tag: Tag) -> Self { BitSliceEncoder { slice, unused, tag } } } //--- encode::Values impl> encode::Values for BitSliceEncoder { fn encoded_len(&self, mode: Mode) -> usize { if mode == Mode::Cer { unimplemented!() } let len = self.slice.as_ref().len() + 1; self.tag.encoded_len() + Length::Definite(len).encoded_len() + len } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { if mode == Mode::Cer { unimplemented!() } self.tag.write_encoded(false, target)?; Length::Definite(self.slice.as_ref().len() + 1).write_encoded(target)?; target.write_all(&[self.unused])?; target.write_all(self.slice.as_ref()) } } //============ Test ========================================================== #[cfg(test)] mod test { use super::*; use crate::decode::IntoSource; #[test] fn bitstring_from_der_content() { fn check(encoded: &[u8], decoded: Option<(u8, &[u8])>) { let taken = Mode::Der.decode( encoded.into_source(), |cons| { BitString::take_from(cons) }); let mut skip_source = encoded.into_source(); let skipped = Mode::Der.decode(&mut skip_source, |cons| { BitString::skip_in(cons) }); match decoded { Some((unused, bits)) => { let taken = taken.unwrap(); assert!(skipped.is_ok()); assert!(skip_source.slice().is_empty()); assert_eq!(taken.unused, unused); assert_eq!(taken.bits.as_ref(), bits); } None => { assert!(taken.is_err()); assert!(skipped.is_err()); } } } check(b"\x03\x07\x04deadb\xd0", Some((4, b"deadb\xd0"))); check(b"\x03\x01\x00", Some((0, b""))); check(b"\x03\x07\x12deadb\xd0", None); check(b"\x03\x01\x04", None); check(b"\x03\x00", None); } } bcder-0.7.3/src/string/mod.rs000064400000000000000000000037301046102023000141370ustar 00000000000000//! BER encoding for various strings types. //! //! This module provides type that match the various string encodings provided //! by ASN.1 and BER. //! //! There are two types of strings for binary data. [`OctetString`]s contain //! a unrestricted sequence of octets while [`BitString`]s contain a sequence //! of bits that does not need to be of a length divisible by eight. //! //! In addition, there are a number of so-called restricted character strings //! that each conain a sequence of characters according to a pre-defined //! character set. ASN.1 defines quite a few of those of which the crate //! currently only implements a subset that is commonly in use. Specifically: //! //! * [`Ia5String`] contains ASCII characters only (IA5 is an alternative //! name for ASCII), //! * [`NumericString`] contains only decimals digits and spaces, //! * [`PrintableString`] contains a subset of ASCII characters including //! letters, digits, and a few symbols, //! * [`Utf8String`] contains a sequence of Unicode code points encoded as //! octets through UTF-8. //! //! All of these are implemented atop a generic [`RestrictedString`] by //! providing an implementation for the [`CharSet`] trait. //! //! [`OctetString`]: struct.OctetString.html //! [`BitString`]: struct.BitString.html //! [`Ia5String`]: struct.Ia5String.html //! [`NumericString`]: struct.NumericString.html //! [`PrintableString`]: struct.PrintableString.html //! [`Utf8String`]: struct.Utf8String.html //! [`RestrictedString`]: struct.RestrictedString.html //! [`CharSet`]: trait.CharSet.html //--- Re-exports pub use self::bit::{BitString, BitStringIter}; pub use self::restricted::{ CharSet, CharSetError, RestrictedString, RestrictedStringChars, Ia5String, NumericString, PrintableString, Utf8String }; pub use self::octet::{ OctetString, OctetStringEncoder, OctetStringIter, OctetStringOctets, OctetStringSource, WrappingOctetStringEncoder }; //--- Private modules mod bit; mod restricted; mod octet; bcder-0.7.3/src/string/octet.rs000064400000000000000000000746141046102023000145070ustar 00000000000000//! A BER-encoded OCTET STRING. //! //! This is an internal module. It’s public types are re-exported by the //! parent. //! //! XXX This currently panics when trying to encode an octet string in //! CER mode. An implementation of that is TODO. use std::{cmp, hash, io, mem}; use std::convert::Infallible; use bytes::{BytesMut, Bytes}; use crate::captured::Captured; use crate::{decode, encode}; use crate::decode::{ BytesSource, DecodeError, IntoSource, Pos, SliceSource, Source }; use crate::mode::Mode; use crate::length::Length; use crate::tag::Tag; //------------ OctetString --------------------------------------------------- /// An octet string value. /// /// An octet string is a sequence of octets, i.e., a glorified `[u8]`. Basic /// Encoding Rules, however, allow this sequence to be broken up into chunks /// that are encoded separatedly to allow for very large octet strings and /// cases where one doesn’t yet know the length of the string. /// /// In order to avoid unnecessary allocations, this type wraps the raw content /// octets of a BER encoded octet string. As a consequence, assembling the /// complete string may actually be costly and should only be done if really /// necessary. As an alternative, there is an iterator over the parts via the /// `iter` method or the `IntoIterator` trait as well as an iterator over the /// individual octets via the `octets` method. /// /// Octet strings are sometimes used to store BER encoded data. The /// `OctetStringSource` type, accessible via the `to_source` method, provides /// an implementation of the `Source` trait to run a decoder on. /// /// # BER Encoding /// /// Octet strings are either encoded as a primitive or a constructed value. /// In the primitive form, the content octets are the string’s octets. In a /// constructed form, the content is a sequence of encoded octets strings /// which in turn may be primitive or constructed. In this case, the string’s /// octets are the concatenation of all the content octets of the primitive /// forms in the order as encountered. /// /// In CER, the string must use the primitive form if it is less than 1000 /// octets long and the constructed form otherwise. The constructed form must /// consists of a sequence of primitive values each exactly with a 1000 /// octets of content except for the last one. /// /// In DER, only the primitive form is allowed. #[derive(Clone, Debug)] pub struct OctetString(Inner); /// A type allowing to distinguish between primitive and constructed encoding. #[derive(Clone, Debug)] enum Inner { /// The value is encoded in primitive encoding. Primitive(P), /// The value is encoded in constructed encoding. Constructed(C), } /// # Content Access /// impl OctetString { /// Creates an octet string from a Bytes value. pub fn new(bytes: Bytes) -> Self { OctetString(Inner::Primitive(bytes)) } /// Returns an iterator over the parts of the octet string. /// /// The iterator will produce `&[u8]` which, when appended produce the /// complete content of the octet string. pub fn iter(&self) -> OctetStringIter { match self.0 { Inner::Primitive(ref inner) => { OctetStringIter(Inner::Primitive(inner.as_ref())) } Inner::Constructed(ref inner) => { OctetStringIter( Inner::Constructed(inner.as_slice().into_source()) ) } } } /// Returns an iterator over the individual octets of the string. pub fn octets(&self) -> OctetStringOctets { OctetStringOctets::new(self.iter()) } /// Returns a reference to the complete content if possible. /// /// The method will return a bytes slice of the content if the octet /// string was encoded as a single primitive value or `None` otherwise. /// /// This is guaranteed to return some slice if the value was produced by /// decoding in DER mode. pub fn as_slice(&self) -> Option<&[u8]> { match self.0 { Inner::Primitive(ref inner) => Some(inner.as_ref()), Inner::Constructed(_) => None } } /// Produces a bytes value with the string’s content. /// /// If the octet string was encoded as a single primitive value, the /// method will simply clone the content. Otherwise it will produce /// an entirely new bytes value from the concatenated content of all /// the primitive values. pub fn to_bytes(&self) -> Bytes { if let Inner::Primitive(ref inner) = self.0 { return inner.clone() } let mut res = BytesMut::new(); self.iter().for_each(|x| res.extend_from_slice(x)); res.freeze() } /// Converts the octet string into bytes value. /// /// If the octet string was encoded as a single primitive value, the /// method will simply return the content. Otherwise it will produce /// an entirely new bytes value from the concatenated content of all /// the primitive values. pub fn into_bytes(self) -> Bytes { if let Inner::Primitive(inner) = self.0 { return inner } let mut res = BytesMut::new(); self.iter().for_each(|x| res.extend_from_slice(x)); res.freeze() } /// Returns the length of the content. /// /// This is _not_ the length of the encoded value but of the actual /// octet string. pub fn len(&self) -> usize { if let Inner::Primitive(ref inner) = self.0 { return inner.len() } self.iter().fold(0, |len, x| len + x.len()) } /// Returns whether the content is empty. pub fn is_empty(&self) -> bool { if let Inner::Primitive(ref inner) = self.0 { return inner.is_empty() } !self.iter().any(|s| !s.is_empty()) } } /// # Parsing and Encoding of Octet Strings /// impl OctetString { /// Takes a single octet string value from constructed value content. /// /// If there is no next value, if the next value does not have the tag /// `Tag::OCTET_STRING`, or if it doesn’t contain a correctly encoded /// octet string, a malformed error is returned. pub fn take_from( cons: &mut decode::Constructed ) -> Result> { cons.take_value_if(Tag::OCTET_STRING, Self::from_content) } /// Takes an optional octet string value from constructed value content. /// /// If there is no next value, or if the next value does not have the /// tag `Tag::OCTET_STRING`, then `Ok(None)` is returned. /// /// If there is an octet string, but it is not correctly encoded, a /// malformed error is returned. pub fn take_opt_from( cons: &mut decode::Constructed ) -> Result, DecodeError> { cons.take_opt_value_if(Tag::OCTET_STRING, Self::from_content) } /// Takes an octet string value from content. pub fn from_content( content: &mut decode::Content ) -> Result> { match *content { decode::Content::Primitive(ref mut inner) => { if inner.mode() == Mode::Cer && inner.remaining() > 1000 { return Err(content.content_err( "long string component in CER mode" )) } Ok(OctetString(Inner::Primitive(inner.take_all()?))) } decode::Content::Constructed(ref mut inner) => { match inner.mode() { Mode::Ber => Self::take_constructed_ber(inner), Mode::Cer => Self::take_constructed_cer(inner), Mode::Der => { Err(content.content_err( "constructed string in DER mode" )) } } } } } /// Parses a constructed BER encoded octet string. /// /// It consists octet string values either primitive or constructed. fn take_constructed_ber( cons: &mut decode::Constructed ) -> Result> { cons.capture(|cons| { while cons.skip_opt(|tag, _, _| if tag == Tag::OCTET_STRING { Ok(()) } else { Err("expected octet string".into()) } )?.is_some() { } Ok(()) }).map(|captured| OctetString(Inner::Constructed(captured))) } /// Parses a constructed CER encoded octet string. /// /// The constructed form contains a sequence of primitive OCTET STRING /// values each except for the last one exactly 1000 octets long. fn take_constructed_cer( constructed: &mut decode::Constructed ) -> Result> { let mut short = false; constructed.capture(|con| { while let Some(()) = con.take_opt_primitive_if(Tag::OCTET_STRING, |primitive| { if primitive.remaining() > 1000 { return Err(primitive.content_err( "long string component in CER mode" )); } if primitive.remaining() < 1000 { if short { return Err(primitive.content_err( "short non-terminal string component in CER mode" )); } short = true } primitive.skip_all() })? { } Ok(()) }).map(|captured| OctetString(Inner::Constructed(captured))) } /// Returns a value encoder for the octet string using the natural tag. pub fn encode(self) -> impl encode::Values { self.encode_as(Tag::OCTET_STRING) } /// Returns a value encoder for the octet string using the given tag. pub fn encode_as(self, tag: Tag) -> impl encode::Values { OctetStringEncoder::new(self, tag) } /// Returns a value encoder for the octet string using the natural tag. pub fn encode_ref(&self) -> impl encode::Values + '_ { self.encode_ref_as(Tag::OCTET_STRING) } /// Returns a value encoder for the octet string using the given tag. pub fn encode_ref_as(&self, tag: Tag) -> impl encode::Values + '_ { OctetStringEncoder::new(self, tag) } /// Returns a value encoder that wraps values into an octet string. /// /// This function allows an octet string wrapping some values to be /// created without having to first create the octet string. pub fn encode_wrapped( mode: Mode, values: V ) -> impl encode::Values { WrappingOctetStringEncoder::new(mode, values) } /// Returns a value encoder that encodes a bytes slice as an octet string. pub fn encode_slice(value: T) -> OctetSliceEncoder { Self::encode_slice_as(value, Tag::OCTET_STRING) } /// Returns a value encoder that encodes a bytes slice as an octet string. pub fn encode_slice_as(value: T, tag: Tag) -> OctetSliceEncoder { OctetSliceEncoder::new(value, tag) } } //--- AsRef // // We need this for OctetStringEncoder below. impl AsRef for OctetString { fn as_ref(&self) -> &Self { self } } //--- PartialEq and Eq impl PartialEq for OctetString { fn eq(&self, other: &OctetString) -> bool { if let (Some(l), Some(r)) = (self.as_slice(), other.as_slice()) { return l == r } let mut sit = self.iter(); let mut oit = other.iter(); let (mut ssl, mut osl) = match (sit.next(), oit.next()) { (Some(ssl), Some(osl)) => (ssl, osl), (None, None) => return true, _ => return false, }; loop { if ssl.is_empty() { ssl = sit.next().unwrap_or(b""); } if osl.is_empty() { osl = oit.next().unwrap_or(b""); } match (ssl.is_empty(), osl.is_empty()) { (true, true) => return true, (false, false) => { }, _ => return false, } let len = cmp::min(ssl.len(), osl.len()); if ssl[..len] != osl[..len] { return false } ssl = &ssl[len..]; osl = &osl[len..]; } } } impl> PartialEq for OctetString { fn eq(&self, other: &T) -> bool { let mut other = other.as_ref(); if let Some(slice) = self.as_slice() { return slice == other } for part in self.iter() { if part.len() > other.len() { return false } if part.len() == other.len() { return part == other } if part != &other[..part.len()] { return false } other = &other[part.len()..] } false } } impl Eq for OctetString { } //--- PartialOrd and Ord impl PartialOrd for OctetString { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl> PartialOrd for OctetString { fn partial_cmp(&self, other: &T) -> Option { let mut other = other.as_ref(); if let Some(slice ) = self.as_slice() { return slice.partial_cmp(other) } for part in self.iter() { if part.len() >= other.len() { return Some(part.cmp(other)) } match part.cmp(&other[..part.len()]) { cmp::Ordering::Equal => { } other => return Some(other) } other = &other[part.len()..] } Some(cmp::Ordering::Less) } } impl Ord for OctetString { fn cmp(&self, other: &Self) -> cmp::Ordering { if let (Some(l), Some(r)) = (self.as_slice(), other.as_slice()) { return l.cmp(r) } let mut siter = self.iter(); let mut oiter = other.iter(); let mut spart = b"".as_ref(); let mut opart = b"".as_ref(); loop { if spart.is_empty() { spart = siter.next().unwrap_or(b""); } if opart.is_empty() { opart = oiter.next().unwrap_or(b""); } match (spart.is_empty(), opart.is_empty()) { (true, true) => return cmp::Ordering::Equal, (true, false) => return cmp::Ordering::Less, (false, true) => return cmp::Ordering::Greater, (false, false) => { }, } let len = cmp::min(spart.len(), opart.len()); match spart[..len].cmp(&opart[..len]) { cmp::Ordering::Equal => { } other => return other } spart = &spart[len..]; opart = &opart[len..]; } } } //--- Hash impl hash::Hash for OctetString { fn hash(&self, state: &mut H) { for part in self.iter() { part.hash(state) } } } //--- IntoIterator impl<'a> IntoIterator for &'a OctetString { type Item = &'a [u8]; type IntoIter = OctetStringIter<'a>; fn into_iter(self) -> Self::IntoIter { self.iter() } } //--- IntoSource impl IntoSource for OctetString { type Source = OctetStringSource; fn into_source(self) -> Self::Source { OctetStringSource::new(self) } } //------------ OctetStringSource --------------------------------------------- /// A decode source atop an octet string. // // Assuming we have a correctly encoded octet string, its content is a // sequence of value headers (i.e., tag and length octets) and actual string // content. There’s three types of headers we could encounter: primitive // octet strings, constructed octet strings, and end-of-values. The first // one is followed by as many octets of actual content as given in the // length octets. The second one is followed by more values recursively and // the third one is by nothing. So, only the primitive values actually // contain content and, because however they are nested, they appear in // order, we can ignore all the rest. pub struct OctetStringSource { /// The content of primitive value we currently work on. current: Bytes, /// The remainder of the value after the value in `current`. remainder: BytesSource, /// The current position in the string. pos: Pos, } impl OctetStringSource { /// Creates a new source atop an existing octet string. fn new(from: OctetString) -> Self { Self::with_offset(from, Pos::default()) } /// Creates a new source with a given start position. fn with_offset(from: OctetString, offset: Pos) -> Self { match from.0 { Inner::Primitive(inner) => { OctetStringSource { current: inner, remainder: Bytes::new().into_source(), pos: offset, } } Inner::Constructed(inner) => { OctetStringSource { current: Bytes::new(), remainder: inner.into_bytes().into_source(), pos: offset, } } } } /// Returns the next value for `self.current`. /// /// This is the content of the first primitive value found in the /// remainder. /// /// Returns `None` if we are done. fn next_current(&mut self) -> Option { // Unwrapping here is okay. The only error that can happen is that // the tag is longer that we support. However, we already checked that // there’s only OctetString or End of Value tags which we _do_ // support. while let Some((tag, cons)) = Tag::take_opt_from( &mut self.remainder ).unwrap() { let length = Length::take_from( &mut self.remainder, Mode::Ber ).unwrap(); match tag { Tag::OCTET_STRING => { if cons { continue } let length = match length { Length::Definite(len) => len, _ => unreachable!() }; return Some(self.remainder.split_to(length)) } Tag::END_OF_VALUE => continue, _ => unreachable!() } } None } } impl decode::Source for OctetStringSource { type Error = Infallible; fn pos(&self) -> Pos { self.pos } fn request(&mut self, len: usize) -> Result { if self.current.len() < len && !self.remainder.is_empty() { // Make a new current that is at least `len` long. let mut current = BytesMut::with_capacity(self.current.len()); current.extend_from_slice(&self.current.clone()); while current.len() < len { if let Some(bytes) = self.next_current() { current.extend_from_slice(bytes.as_ref()) } else { break } } self.current = current.freeze() } Ok(self.current.len()) } fn advance(&mut self, len: usize) { assert!(len <= self.current.len()); self.pos = self.pos + len.into(); bytes::Buf::advance(&mut self.current, len) } fn slice(&self) -> &[u8] { self.current.as_ref() } fn bytes(&self, start: usize, end: usize) -> Bytes { self.current.slice(start..end) } } //------------ OctetStringIter ----------------------------------------------- /// An iterator over the segments of an octet string. /// /// You can get a value of this type by calling `OctetString::iter` or relying /// on the `IntoIterator` impl for a `&OctetString`. #[derive(Clone, Debug)] pub struct OctetStringIter<'a>(Inner<&'a [u8], SliceSource<'a>>); impl<'a> Iterator for OctetStringIter<'a> { type Item = &'a [u8]; fn next(&mut self) -> Option { match self.0 { Inner::Primitive(ref mut inner) => { if inner.is_empty() { None } else { Some(mem::replace(inner, &b""[..])) } } Inner::Constructed(ref mut inner) => { while !inner.is_empty() { let (tag, cons) = Tag::take_from(inner).unwrap(); let length = Length::take_from(inner, Mode::Ber).unwrap(); match tag { Tag::OCTET_STRING => { if cons { continue } let length = match length { Length::Definite(len) => len, _ => unreachable!() }; return Some(inner.split_to(length)) } Tag::END_OF_VALUE => continue, _ => unreachable!() } } None } } } } //------------ OctetStringOctets --------------------------------------------- /// An iterator over the octets in an octet string. /// /// You can get a value of this type by calling `OctetString::octets`. #[derive(Clone, Debug)] pub struct OctetStringOctets<'a> { cur: &'a [u8], iter: OctetStringIter<'a>, } impl<'a> OctetStringOctets<'a> { fn new(iter: OctetStringIter<'a>) -> Self { OctetStringOctets { cur: b"", iter } } } impl<'a> Iterator for OctetStringOctets<'a> { type Item = u8; fn next(&mut self) -> Option { while self.cur.is_empty() { let next = match self.iter.next() { Some(some) => some, None => return None, }; self.cur = next; } let res = self.cur[0]; self.cur = &self.cur[1..]; Some(res) } } //------------ OctetStringEncoder -------------------------------------------- /// A value encoder for an octet string. /// /// You can get a value of this type via octet string’s [`encode`] and /// [`encode_as`] methods. /// /// [`encode`]: struct.OctetString.html#method.encode /// [`encode_as`]: struct.OctetString.html#method.encode_as #[derive(Clone, Debug)] pub struct OctetStringEncoder { /// The octet string to encode. value: T, /// The tag to used for the encoded value. tag: Tag, } impl OctetStringEncoder { /// Creates a new octet string encoder. fn new(value: T, tag: Tag) -> Self { OctetStringEncoder { value, tag } } } //--- encode::Values impl> encode::Values for OctetStringEncoder { fn encoded_len(&self, mode: Mode) -> usize { match mode { Mode::Ber => { let len = match self.value.as_ref().0 { Inner::Primitive(ref bytes) => bytes.len(), Inner::Constructed(ref captured) => captured.len(), }; self.tag.encoded_len() + Length::Definite(len).encoded_len() + len } Mode::Cer => { unimplemented!() } Mode::Der => { let len = self.value.as_ref().len(); self.tag.encoded_len() + Length::Definite(len).encoded_len() + len } } } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { match mode { Mode::Ber => { match self.value.as_ref().0 { Inner::Primitive(ref bytes) => { self.tag.write_encoded(false, target)?; Length::Definite(bytes.len()).write_encoded(target)?; target.write_all(bytes.as_ref()) } Inner::Constructed(ref captured) => { self.tag.write_encoded(true, target)?; Length::Definite(captured.len()).write_encoded(target)?; target.write_all(captured.as_slice()) } } } Mode::Cer => { unimplemented!() } Mode::Der => { self.tag.write_encoded(false, target)?; Length::Definite( self.value.as_ref().len() ).write_encoded(target)?; for slice in self.value.as_ref().iter() { target.write_all(slice)?; } Ok(()) } } } } //------------ OctetSliceEncoder --------------------------------------------- /// A value encoder for a bytes slice as an octet string. /// /// You can get a value of this type via octet string’s [`encode_slice`] and /// [`encode_slice_as`] functions. /// /// [`encode_slice`]: struct.OctetString.html#method.encode_slice /// [`encode_slice_as`]: struct.OctetString.html#method.encode_slice_as #[derive(Clone, Debug)] pub struct OctetSliceEncoder { /// The slice to encode. slice: T, /// The tag to be used for the encoded value. tag: Tag, } impl OctetSliceEncoder { /// Creates a new octet slice encoder. fn new(slice: T, tag: Tag) -> Self { OctetSliceEncoder { slice, tag } } } //--- encode::Values impl> encode::Values for OctetSliceEncoder { fn encoded_len(&self, mode: Mode) -> usize { if mode == Mode::Cer { unimplemented!() } let len = self.slice.as_ref().len(); self.tag.encoded_len() + Length::Definite(len).encoded_len() + len } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { if mode == Mode::Cer { unimplemented!() } self.tag.write_encoded(false, target)?; Length::Definite(self.slice.as_ref().len()).write_encoded(target)?; target.write_all(self.slice.as_ref()) } } //------------ WrappingOctetStringEncoder ------------------------------------ /// A value encoder that wraps the encoded inner values into an octet string. /// /// You can get a value of this type from octet string’s [`encode_wrapped`] /// method. /// /// [`encode_wrapped`]: struct.OctetString.html#method.encode_wrapped pub struct WrappingOctetStringEncoder { /// The value to wrap in the octet string. values: V, /// The mode to encode those values in. mode: Mode } impl WrappingOctetStringEncoder { /// Creates a new value from the mode and inner values. fn new(mode: Mode, values: V) -> Self { WrappingOctetStringEncoder { values, mode } } } //--- encode::Values impl encode::Values for WrappingOctetStringEncoder { fn encoded_len(&self, mode: Mode) -> usize { if mode == Mode::Cer { unimplemented!() } encode::total_encoded_len( Tag::OCTET_STRING, self.values.encoded_len(self.mode) ) } fn write_encoded( &self, mode: Mode, target: &mut W ) -> Result<(), io::Error> { if mode == Mode::Cer { unimplemented!() } encode::write_header( target, Tag::OCTET_STRING, false, self.values.encoded_len(self.mode))?; self.values.write_encoded(self.mode, target) } } //------------ Tests --------------------------------------------------------- #[cfg(test)] mod tests { use crate::encode::{Values, PrimitiveContent}; use super::*; #[test] fn take_from_ber() { // D .. definite constructed // I .. indefinied constructed // p .. primitive // D(p) assert_eq!( decode::Constructed::decode( b"\x24\x04\ \x04\x02ab".into_source(), Mode::Ber, |cons| { OctetString::take_from(cons) } ).unwrap().to_bytes(), "ab" ); // D(pp) assert_eq!( decode::Constructed::decode( b"\x24\x06\ \x04\x01a\ \x04\x01b".into_source(), Mode::Ber, |cons| { OctetString::take_from(cons) } ).unwrap().to_bytes(), "ab" ); // D(I(p)) assert_eq!( decode::Constructed::decode( b"\x24\x08\ \x24\x80\ \x04\x02ab\ \0\0".into_source(), Mode::Ber, |cons| { OctetString::take_from(cons) } ).unwrap().to_bytes(), "ab" ); // I(p) assert_eq!( decode::Constructed::decode( b"\x24\x80\ \x04\x02ab\ \0\0".into_source(), Mode::Ber, |cons| { OctetString::take_from(cons) } ).unwrap().to_bytes(), "ab" ); // D(pI(p)) assert_eq!( decode::Constructed::decode( b"\x24\x0a\ \x04\x01a\ \x24\x80\ \x04\x01b\ \0\0".into_source(), Mode::Ber, |cons| { OctetString::take_from(cons) } ).unwrap().to_bytes(), "ab" ); } #[test] fn encode_wrapped() { let mut v = Vec::new(); let enc = OctetString::encode_wrapped(Mode::Der, true.encode()); enc.write_encoded(Mode::Der, &mut v).unwrap(); // 4, 3 OctetString with content length 3 // 1, 1, 255 Boolean, length 1, Value true assert_eq!(vec![4, 3, 1, 1, 255], v); let l = enc.encoded_len(Mode::Der); assert_eq!(l, v.len()); } } bcder-0.7.3/src/string/restricted.rs000064400000000000000000000434021046102023000155300ustar 00000000000000//! BER-encoded Restricted Character String types. //! //! This is an internal module. It’s public items are re-exported by the //! parent. use std::{char, cmp, fmt, hash, ops, str}; use std::borrow::Cow; use std::marker::PhantomData; use bytes::Bytes; use crate::{decode, encode}; use crate::decode::DecodeError; use crate::tag::Tag; use super::octet::{OctetString, OctetStringIter, OctetStringOctets}; //------------ CharSet ------------------------------------------------------- /// The character set of a restricted character string type. /// /// The trait only includes associated functions and can thus be implemented /// for marker types. It main purpose is to take an iterator over `u8`s and /// produce `char`s or errors. This happens in [`next_char`]. /// /// The trait is primarily used to define the character set of the /// [`RestrictedString`] type. /// /// [`next_char`]: #tymethod.next_char /// [`RestrictedString`]: struct.RestrictedString.html pub trait CharSet { /// The natural tag of the related restricted character string type. const TAG: Tag; /// Returns the next character from a octet sequence. fn next_char>( iter: &mut I ) -> Result, CharSetError>; /// Converts a `str` into a octet sequence. /// /// The method takes a `str` and converts it into one of three things. /// If the string can be encoded in this character set and its own octet /// sequence is identical to the encoded sequence, it returns its octet /// sequence as a `Ok(Cow::Borrowed(_))`. If the octet sequence differs, /// it creates that and returns it as a `Ok(Cow::Owned(_))`. Finally, if /// the string cannot be encoded in this character set, it returns an /// error. fn from_str(s: &str) -> Result, CharSetError>; /// Checks whether a sequence of octets is a valid string. /// /// The method returns an error if the sequence of the octets represented /// by `iter` is not in fact a valid string for this character set. fn check>(iter: &mut I) -> Result<(), CharSetError> { while Self::next_char(iter)?.is_some() { } Ok(()) } } //------------ RestrictedString ---------------------------------------------- /// A generic restricted character string. /// /// Restricted character strings essentially are a sequence of characters from /// a specific character set mapped into a sequence of octets. In BER, these /// are in fact encoded just like an [`OctetString`] with a different tag. /// Consequently, this type is a wrapper around [`OctetString`] that makes /// sure that the sequence of octets is correctly encoded for the given /// character set. /// /// As usual, you can parse a restricted character string from encoded data /// by way of the [`take_from`] and [`from_content`] methods. /// Alternatively, you can create a new value from a `String` or `str` via /// the [`from_string`] and [`from_str`] associated functions. /// /// Conversely, a restricted character string can be converted into a string /// by way of the [`to_string`] and [`to_str`] methods. /// /// In addition, the restricted character string mirrors the standard /// library’s string types by dereffing to [`OctetString`] and using the /// octet string’s iterators. In addition, the [`chars`] method provides an /// iterator over the characters encoded in the string. /// /// [`CharSet`]: trait.CharSet.html /// [`OctetString`]: struct.OctetString.html /// [`take_from`]: #method.take_from /// [`from_content`]: #method.take_content /// [`from_string`]: #method.from_string /// [`from_str`]: #method.from_str /// [`to_string`]: #method.to_string /// [`to_str`]: #method.to_str /// [`chars`]: #method.chars #[derive(Clone, Debug)] pub struct RestrictedString { /// The underlying octet string. octets: OctetString, /// Marker for our character set. marker: PhantomData } impl RestrictedString { /// Creates a new character string without any checks. unsafe fn new_unchecked(octets: OctetString) -> Self { RestrictedString { octets, marker: PhantomData } } /// Creates a new character string from an octet string. /// /// If the octet string contains octet sequences that are not valid for /// the character set, an appropriate error will be returned. pub fn new(os: OctetString) -> Result { L::check(&mut os.octets())?; Ok(unsafe { Self::new_unchecked(os) }) } /// Creates a new character string from a `String`. /// /// If the string’s internal representation is identical to the encoding /// of restricted character string, the string will be reused and no /// allocation occurs. Otherwise, a new bytes value is created. /// /// If the string cannot be encoded in the character set, an error is /// returned. pub fn from_string(s: String) -> Result { let octets = match L::from_str(s.as_ref())? { Cow::Borrowed(_) => s.into_bytes().into(), Cow::Owned(owned) => owned.into(), }; Ok(unsafe { Self::new_unchecked(OctetString::new(octets)) }) } /// Returns an iterator over the character in the character string. pub fn chars(&self) -> RestrictedStringChars { RestrictedStringChars::new(self.octets.octets()) } /// Converts the string into its underlying bytes. /// /// Note that the bytes value will contain the raw octets of the string /// which are not necessarily a valid Rust string. pub fn into_bytes(self) -> Bytes { self.octets.into_bytes() } } /// # Decoding and Encoding /// impl RestrictedString { /// Takes a single character set value from constructed value content. /// /// If there is no next value, if the next value does not have the natural /// tag appropriate for this character set implementation, or if it does /// not contain a correctly encoded character string, a malformed error is /// returned. pub fn take_from( cons: &mut decode::Constructed ) -> Result> { cons.take_value_if(L::TAG, Self::from_content) } /// Takes a character set from content. pub fn from_content( content: &mut decode::Content ) -> Result> { let os = OctetString::from_content(content)?; Self::new(os).map_err(|_| content.content_err("invalid character")) } /// Returns a value encoder for the character string with the natural tag. pub fn encode(self) -> impl encode::Values { self.encode_as(L::TAG) } /// Returns a value encoder for the character string with the given tag. pub fn encode_as(self, tag: Tag) -> impl encode::Values { self.octets.encode_as(tag) } /// Returns a value encoder for the character string with the natural tag. pub fn encode_ref(&self) -> impl encode::Values + '_ { self.encode_ref_as(L::TAG) } /// Returns a value encoder for the character string with the given tag. pub fn encode_ref_as(&self, tag: Tag) -> impl encode::Values + '_ { self.octets.encode_ref_as(tag) } } //--- FromStr impl str::FromStr for RestrictedString { type Err = CharSetError; fn from_str(s: &str) -> Result { Ok(unsafe { Self::new_unchecked(OctetString::new( L::from_str(s)?.into_owned().into() ))}) } } //--- Deref and AsRef impl ops::Deref for RestrictedString { type Target = OctetString; fn deref(&self) -> &OctetString { self.as_ref() } } impl AsRef for RestrictedString { fn as_ref(&self) -> &OctetString { &self.octets } } //--- PartialEq and Eq, PartialOrd and Ord // // We only supply PartialEq because two identical octet sequences in // different character sets can mean different things. // // XXX Once specialization lands we can bring back the generic comparision // and implement it over `Self::chars`. impl PartialEq for RestrictedString { fn eq(&self, other: &Self) -> bool { self.octets.eq(&other.octets) } } impl Eq for RestrictedString { } impl PartialOrd for RestrictedString { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for RestrictedString { fn cmp(&self, other: &Self) -> cmp::Ordering { self.octets.cmp(&other.octets) } } //--- Hash impl hash::Hash for RestrictedString { fn hash(&self, state: &mut H) { self.octets.hash(state) } } //--- IntoIterator impl<'a, L: CharSet> IntoIterator for &'a RestrictedString { type Item = &'a [u8]; type IntoIter = OctetStringIter<'a>; fn into_iter(self) -> Self::IntoIter { self.iter() } } //--- Display impl fmt::Display for RestrictedString { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { self.chars().try_for_each(|ch| fmt::Display::fmt(&ch, fmt)) } } //------------ RestrictedStringChars ------------------------------------------ /// An iterator over the characters in a restricted character string. /// /// You can obtain a value of this type via a restricted string’s [`chars`] /// method. /// /// [`chars`]: struct.RestrictedStringChars.html#method.chars #[derive(Clone, Debug)] pub struct RestrictedStringChars<'a, L: CharSet> { /// The underlying octet iterator. octets: OctetStringOctets<'a>, /// Our character set. marker: PhantomData, } impl<'a, L: CharSet> RestrictedStringChars<'a, L> { /// Creates a new character iterator from an octet iterator. fn new(octets: OctetStringOctets<'a>) -> Self { RestrictedStringChars { octets, marker: PhantomData } } } impl<'a, L: CharSet> Iterator for RestrictedStringChars<'a, L> { type Item = char; fn next(&mut self) -> Option { L::next_char(&mut self.octets).unwrap() } } //============ Concrete Restricted String Types ============================== //------------ Utf8String ---------------------------------------------------- /// A restricted character string containing UTF-8 encoded characters. /// /// This character string allows all Unicode code points. It represents them /// as a sequence of octets according to the UTF-8 encoding defined in /// [RFC 3629]. /// /// See [`RestrictedString`] for more details on restricged character strings /// in general. /// /// [`RestrictedString`]: struct.RestrictedString.html /// [RFC 3629]: https://tools.ietf.org/html/rfc3629 pub type Utf8String = RestrictedString; /// The character set for the UTF8String ASN.1 type. #[derive(Clone, Copy, Debug)] pub struct Utf8CharSet; impl CharSet for Utf8CharSet { const TAG: Tag = Tag::UTF8_STRING; fn next_char>( iter: &mut I ) -> Result, CharSetError> { let first = match iter.next() { Some(ch) => ch, None => return Ok(None) }; if first < 0x80 { return Ok(Some(char::from(first))) } let second = match iter.next() { Some(ch) => ch, None => return Err(CharSetError), }; if first < 0xC0 || second < 0x80 { return Err(CharSetError) } if first < 0xE0 { return Ok(Some(unsafe { char::from_u32_unchecked( (u32::from(first & 0x1F)) << 6 | u32::from(second & 0x3F) ) })) } let third = match iter.next() { Some(ch) => ch, None => return Err(CharSetError) }; if third < 0x80 { return Err(CharSetError) } if first < 0xF0 { return Ok(Some(unsafe { char::from_u32_unchecked( (u32::from(first & 0x0F)) << 12 | (u32::from(second & 0x3F)) << 6 | u32::from(third & 0x3F) ) })) } let fourth = match iter.next() { Some(ch) => ch, None => return Err(CharSetError) }; if first > 0xF7 || fourth < 0x80 { return Err(CharSetError) } Ok(Some(unsafe { char::from_u32_unchecked( (u32::from(first & 0x07)) << 18 | (u32::from(second & 0x3F)) << 12 | (u32::from(third & 0x3F)) << 6 | u32::from(fourth & 0x3F) ) })) } fn from_str(s: &str) -> Result, CharSetError> { Ok(Cow::Borrowed(s.as_bytes())) } } //------------ NumericString ------------------------------------------------- /// A restricted character string containing only digits and spaces. /// /// This character string allows only decimal digits `0` to `9` and the /// space character ` `. It encodes them with their ASCII value. /// /// See [`RestrictedString`] for more details on restricged character strings /// in general. /// /// [`RestrictedString`]: struct.RestrictedString.html pub type NumericString = RestrictedString; /// The character set for the NumericString ASN.1 type. #[derive(Clone, Copy, Debug)] pub struct NumericCharSet; impl CharSet for NumericCharSet { const TAG: Tag = Tag::NUMERIC_STRING; fn next_char>( iter: &mut I ) -> Result, CharSetError> { match iter.next() { Some(ch) if ch == b' ' || ch.is_ascii_digit() => { Ok(Some(char::from(ch))) } Some(_) => Err(CharSetError), None => Ok(None) } } fn from_str(s: &str) -> Result, CharSetError> { Ok(Cow::Borrowed(s.as_bytes())) } } //------------ PrintableString ----------------------------------------------- /// A restricted character string allowing a subset of ASCII characters. /// /// This character string allows the following characters from the ASCII /// character set and encodes them with their ASCII value: /// /// * the letters `A` to `Z` and `a` to `z`, /// * the digits `0` to `9`, /// * the space character ` `, /// * the symbols `'`, `(`, `)`, `+`, `,`, `-`, `.`, `/`, `:`, `=`, and `?`. /// /// See [`RestrictedString`] for more details on restricged character strings /// in general. /// /// [`RestrictedString`]: struct.RestrictedString.html pub type PrintableString = RestrictedString; /// The character set for the PrintableString ASN.1 type. #[derive(Clone, Debug)] pub struct PrintableCharSet; impl CharSet for PrintableCharSet { const TAG: Tag = Tag::PRINTABLE_STRING; fn next_char>( iter: &mut I ) -> Result, CharSetError> { match iter.next() { Some(x) if x.is_ascii_alphanumeric() || // A-Z a-z 0-9 x == b' ' || x == b'\'' || x == b'(' || x == b')' || x == b'+' || x == b',' || x == b'-' || x == b'.' || x == b'/' || x == b':' || x == b'=' || x == b'?' => { Ok(Some(char::from(x))) } Some(_) => Err(CharSetError), None => Ok(None) } } fn from_str(s: &str) -> Result, CharSetError> { Ok(Cow::Borrowed(s.as_bytes())) } } //------------ Ia5String ----------------------------------------------------- /// A restricted character string containing ASCII characters. /// /// This character string allows all ASCII characters (i.e., octets with /// values `0x00` to `0x7F`) and encodes them with their ASCII value. /// /// The type’s name is derived from the name used in ASN.1. It is derived /// from the name IA5 or International Alphabet No. 5 which is the ITU name /// for ASCII and is specified in ITU.T recommendation T.50. /// /// See [`RestrictedString`] for more details on restricged character strings /// in general. /// /// [`RestrictedString`]: struct.RestrictedString.html pub type Ia5String = RestrictedString; /// The character set for the IA5String ASN.1 type. #[derive(Clone, Copy, Debug)] pub struct Ia5CharSet; impl CharSet for Ia5CharSet { const TAG: Tag = Tag::IA5_STRING; fn next_char>( iter: &mut I ) -> Result, CharSetError> { match iter.next() { Some(ch) if ch.is_ascii() => Ok(Some(char::from(ch))), Some(_) => Err(CharSetError), None => Ok(None) } } fn from_str(s: &str) -> Result, CharSetError> { Ok(Cow::Borrowed(s.as_bytes())) } } //------------ CharSetError -------------------------------------------------- /// An illegal value was encountered during character set conversion. #[derive(Debug)] pub struct CharSetError; //------------ Testing ------------------------------------------------------- #[cfg(test)] mod test { use super::*; use bytes::Bytes; use crate::decode::IntoSource; use crate::mode::Mode; use crate::encode::Values; #[test] fn should_encode_decode_printable_string() { let os = OctetString::new(Bytes::from_static(b"This is okay")); let ps = PrintableString::new(os).unwrap(); let mut v = Vec::new(); ps.encode_ref().write_encoded(Mode::Der, &mut v).unwrap(); let decoded = Mode::Der.decode( v.as_slice().into_source(), PrintableString::take_from ).unwrap(); assert_eq!(ps, decoded); } #[test] fn should_restrict_printable_string() { let os = OctetString::new(Bytes::from_static(b"This is wrong!")); assert!(PrintableString::new(os).is_err()); } } bcder-0.7.3/src/tag.rs000064400000000000000000000624501046102023000126310ustar 00000000000000//! The identifier octets of a BER encoded value. //! //! This is a private module. Its public items are re-exported by the parent. use std::{fmt, io}; use crate::decode::{DecodeError, Source}; //------------ Tag ----------------------------------------------------------- /// The tag of a BER encoded value. /// /// Each BER encoded value starts with a sequence of one or more octets called /// the _identifier octets._ They encode both the tag of the value as well as /// whether the value uses primitive or constructed encoding. The `Tag` type /// represents the tag only. The distinction between primitive and constructed /// encoding is captured by the decoder types [`Primitive`] and /// [`Constructed`] instead. /// /// The tag in turn consists of two parts: the class and the number – the /// `Tag` type includes both of them. /// /// # Limitations /// /// We can only decode up to four identifier octets. That is, we only support /// tag numbers between 0 and 1fffff. /// /// [`Primitive`]: decode/struct.Primitive.html /// [`Constructed`]: decode/struct.Constructed.html // // For the moment, the tag is stored with the constructed bit always cleared. #[derive(Clone, Copy, Eq, PartialEq)] pub struct Tag([u8; 4]); /// # Constants for Often Used Tag Values /// impl Tag { /// The mask for checking the class. const CLASS_MASK: u8 = 0xc0; /// The mask for checking whether the value is a primitive /// /// A value of 0 indicates primitive. const CONSTRUCTED_MASK: u8 = 0x20; /// The mask for the fourth octet data (bits 24-32). /// /// (5 bits – 0b0001_1111). const SINGLEBYTE_DATA_MASK: u8 = 0x1f; /// The mask for octet data. /// /// (7 bits – 0b0111_1111). const MULTIBYTE_DATA_MASK: u8 = 0x7f; /// The mask for the last octet with identifier data /// /// (1 bit – 0b1000_0000, it is cleared in the last octet). const LAST_OCTET_MASK: u8 = 0x80; /// The largest tag number possible with three octets. const MAX_VAL_SPAN_3_OCTETS: u32 = 0x001f_ffff; /// The largest tag number possible with two octets. const MAX_VAL_SPAN_2_OCTETS: u32 = 0x3fff; /// The largest tag number possible with one octet. const MAX_VAL_SPAN_1_OCTET: u32 = 0x7f; /// The largest tag number possible with the fourth octet. const MAX_VAL_FOURTH_OCTET: u32 = 0x1e; /// The tag value representing for the ‘universal’ class. const UNIVERSAL: u8 = 0x00; /// The tag value representing the ‘application’ class. const APPLICATION: u8 = 0x40; /// The tag value representing the ‘context-specific’ class. const CONTEXT_SPECIFIC: u8 = 0x80; /// The tag value representing the `private` class. const PRIVATE: u8 = 0xc0; /// The tag marking the end-of-value in an indefinite length value. /// /// This is UNIVERSAL 0. pub const END_OF_VALUE: Self = Tag([0, 0, 0, 0]); //--- Universal Tags // // See clause 8.4 of X.690. /// The tag for the BOOLEAN type, UNIVERSAL 1. pub const BOOLEAN: Self = Tag([1, 0, 0, 0]); /// The tag for the INTEGER type, UNIVERSAL 2. pub const INTEGER: Self = Tag([2, 0, 0, 0]); /// The tag for the BIT STRING type, UNIVERSAL 3. pub const BIT_STRING: Self = Tag([3, 0, 0, 0]); /// The tag for the OCTET STRING type, UNIVERSAL 4. pub const OCTET_STRING: Self = Tag([4, 0, 0, 0]); /// The tag for the NULL type, UNIVERSAL 5. pub const NULL: Self = Tag([5, 0, 0, 0]); /// The tag for the OBJECT IDENTIFIER type, UNIVERSAL 6. pub const OID: Self = Tag([6, 0, 0, 0]); /// The tag for the ObjectDescriptor type, UNIVERSAL 7. pub const OBJECT_DESCRIPTOR: Self = Tag([7, 0, 0, 0]); /// The tag for the EXTERNAL and Instance-of types, UNIVERSAL 8. pub const EXTERNAL: Self = Tag([8, 0, 0, 0]); /// The tag for the REAL type, UNIVERSAL 9. pub const REAL: Self = Tag([9, 0, 0, 0]); /// The tag for the ENUMERATED type, UNIVERSAL 10. pub const ENUMERATED: Self = Tag([10, 0, 0, 0]); /// The tag for the EMBEDDED PDV type, UNIVERSAL 11. pub const EMBEDDED_PDV: Self = Tag([11, 0, 0, 0]); /// The tag for the UTF8String type, UNIVERSAL 12 pub const UTF8_STRING: Self = Tag([12, 0, 0, 0]); /// The tag for the RELATIVE-OID type, UNIVERSAL 13. pub const RELATIVE_OID: Self = Tag([13, 0, 0, 0]); /// The tag for the TIME type, UNIVERSAL 14. pub const TIME: Self = Tag([14, 0, 0, 0]); /// The tag for the SEQUENCE and SEQUENCE OF types, UNIVERSAL 16. pub const SEQUENCE: Self = Tag([16, 0, 0, 0]); /// The tag for the SET and SET OF types, UNIVERSAL 17. pub const SET: Self = Tag([17, 0, 0, 0]); /// The tag for the NumericString type, UNIVERSAL 18. pub const NUMERIC_STRING: Self = Tag([18, 0, 0, 0]); /// The tag for the PrintableString type, UNIVERSAL 19. pub const PRINTABLE_STRING: Self = Tag([19, 0, 0, 0]); /// The tag for the TeletexString type, UNIVERSAL 20. pub const TELETEX_STRING: Self = Tag([20, 0, 0, 0]); /// The tag for the VideotexString type, UNIVERSAL 21. pub const VIDEOTEX_STRING: Self = Tag([21, 0, 0, 0]); /// The tag for the IA5String type, UNIVERSAL 22. pub const IA5_STRING: Self = Tag([22, 0, 0, 0]); /// The tag for the UTCTime type, UNIVERSAL 23. pub const UTC_TIME: Self = Tag([23, 0, 0, 0]); /// The tag for the GeneralizedType type, UNIVERSAL 24. pub const GENERALIZED_TIME: Self = Tag([24, 0, 0, 0]); /// The tag for the GraphicString type, UNIVERSAL 25. pub const GRAPHIC_STRING: Self = Tag([25, 0, 0, 0]); /// The tag for the VisibleString type, UNIVERSAL 26. pub const VISIBLE_STRING: Self = Tag([26, 0, 0, 0]); /// The tag for the GeneralString type, UNIVERSAL 27. pub const GENERAL_STRING: Self = Tag([27, 0, 0, 0]); /// The tag for the UniversalString type, UNIVERSAL 28. pub const UNIVERSAL_STRING: Self = Tag([28, 0, 0, 0]); /// The tag for the CHARACTER STRING type, UNIVERSAL 29. pub const CHARACTER_STRING: Self = Tag([29, 0, 0, 0]); /// The tag for the BMPString type, UNIVERSAL 30. pub const BMP_STRING: Self = Tag([30, 0, 0, 0]); /// The tag for the DATE type, UNIVERSAL 31. pub const DATE: Self = Tag([31, 0, 0, 0]); /// The tag for the TIME-OF-DAY type, UNIVERSAL 32. pub const TIME_OF_DAY: Self = Tag([32, 0, 0, 0]); /// The tag for the DATE-TIME type, UNIVERSAL 33. pub const DATE_TIME: Self = Tag([33, 0, 0, 0]); /// The tag for the DURATION type, UNIVERSAL 34. pub const DURATION: Self = Tag([34, 0, 0, 0]); /// The tag for the OID-IRI type, UNIVERSAL 35. pub const OID_IRI: Self = Tag([35, 0, 0, 0]); /// The tag for the RELATIVE-OID-IRI type, UNIVERSAL 36. pub const RELATIVE_OID_IRI: Self = Tag([36, 0, 0, 0]); //--- The first few context-specific tags. // // These will be removed once we can have `ctx` be a const fn. /// The tag context specific tag `[0]`. pub const CTX_0: Self = Tag([Tag::CONTEXT_SPECIFIC, 0, 0, 0]); /// The tag context specific tag `[1]`. pub const CTX_1: Self = Tag([Tag::CONTEXT_SPECIFIC | 1, 0, 0, 0]); /// The tag context specific tag `[2]`. pub const CTX_2: Self = Tag([Tag::CONTEXT_SPECIFIC | 2, 0, 0, 0]); /// The tag context specific tag `[3]`. pub const CTX_3: Self = Tag([Tag::CONTEXT_SPECIFIC | 3, 0, 0, 0]); /// The tag context specific tag `[4]`. pub const CTX_4: Self = Tag([Tag::CONTEXT_SPECIFIC | 4, 0, 0, 0]); /// The tag context specific tag `[5]`. pub const CTX_5: Self = Tag([Tag::CONTEXT_SPECIFIC | 5, 0, 0, 0]); /// The tag context specific tag `[6]`. pub const CTX_6: Self = Tag([Tag::CONTEXT_SPECIFIC | 6, 0, 0, 0]); } impl Tag { /// Encodes a number into the identifier representation. /// /// There are two forms: /// * low tag number (for tag numbers between 0 and 30): /// One octet. Bits 8 and 7 specify the class, bit 6 indicates whether /// the encoding is primitive (0), and bits 5-1 give the tag number. /// * high tag number (for tag numbers 31 and greater): /// Two or more octets. First octet is as in low-tag-number form, /// except that bits 5-1 all have value 1. Second and following octets /// give the tag number, base 128, most significant digit first, with /// as few digits as possible, and with the bit 8 of each octet except /// the last set to 1. // /// # Panics /// /// This function panics if the tag number is greater than /// `Self::MAX_VAL_SPAN_3_OCTETS`. #[inline] fn new(class_mask: u8, number: u32) -> Self { assert!(number <= Tag::MAX_VAL_SPAN_3_OCTETS); if number <= Tag::MAX_VAL_FOURTH_OCTET { Tag([class_mask | number as u8, 0, 0, 0]) } else if number <= Tag::MAX_VAL_SPAN_1_OCTET { // Fit the number in the third octets let number = number as u8; Tag([class_mask | Tag::SINGLEBYTE_DATA_MASK, number, 0, 0]) } else if number <= Tag::MAX_VAL_SPAN_2_OCTETS { // Fit the number in the second and the third octets let first_part = { Tag::MULTIBYTE_DATA_MASK & ((number >> 7) as u8) | Tag::LAST_OCTET_MASK }; let second_part = Tag::MULTIBYTE_DATA_MASK & (number as u8); Tag([ class_mask | Tag::SINGLEBYTE_DATA_MASK, first_part, second_part, 0 ]) } else { // Fit the number in the first, second and the third octets let first_part = { Tag::MULTIBYTE_DATA_MASK & ((number >> 14) as u8) | Tag::LAST_OCTET_MASK }; let second_part = { Tag::MULTIBYTE_DATA_MASK & ((number >> 7) as u8) | Tag::LAST_OCTET_MASK }; let third_part = Tag::MULTIBYTE_DATA_MASK & (number as u8); Tag([ class_mask | Tag::SINGLEBYTE_DATA_MASK, first_part, second_part, third_part ]) } } /// Creates a new tag in the universal class with the given tag number. /// /// # Panics /// /// Currently, this function panics if the tag number is greater than /// `MAX_VAL_SPAN_3_OCTETS`. pub fn universal(number: u32) -> Self { Tag::new(Tag::UNIVERSAL, number) } /// Creates a new tag in the application class with the given tag number. /// /// # Panics /// /// Currently, this function panics if the tag number is greater than /// `MAX_VAL_SPAN_3_OCTETS`. pub fn application(number: u32) -> Self { Tag::new(Tag::APPLICATION, number) } /// Creates a new tag in the context specific class. /// /// # Panics /// /// Currently, this function panics if the provided tag number is greater /// than `MAX_VAL_SPAN_3_OCTETS`. pub fn ctx(number: u32) -> Self { Tag::new(Tag::CONTEXT_SPECIFIC, number) } /// Creates a new tag in the private class with the given tag number. /// /// # Panics /// /// Currently, this function panics if the provided tag number is greater /// than `MAX_VAL_SPAN_3_OCTETS`. pub fn private(number: u32) -> Self { Tag::new(Tag::PRIVATE, number) } /// Returns whether the tag is of the universal class. pub fn is_universal(self) -> bool { self.0[0] & Self::CLASS_MASK == Self::UNIVERSAL } /// Returns whether the tag is of the application class. pub fn is_application(self) -> bool { self.0[0] & Self::CLASS_MASK == Self::APPLICATION } /// Returns whether the tag is of the context specific class. pub fn is_context_specific(self) -> bool { self.0[0] & Self::CLASS_MASK == Self::CONTEXT_SPECIFIC } /// Returns whether the tag is of the private class. pub fn is_private(self) -> bool { self.0[0] & Self::CLASS_MASK == Self::PRIVATE } /// Returns the number of the tag. pub fn number(self) -> u32 { if (Tag::SINGLEBYTE_DATA_MASK & self.0[0]) != Tag::SINGLEBYTE_DATA_MASK { // It's a single byte identifier u32::from(Tag::SINGLEBYTE_DATA_MASK & self.0[0]) } else if Tag::LAST_OCTET_MASK & self.0[1] == 0 { // It's a multibyte that starts and ends in the third octet u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) } else if Tag::LAST_OCTET_MASK & self.0[2] == 0 { // It's a multibyte that starts in the second octet and ends in // the third octet u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) << 7 | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[2]) } else { // It's a multibyte that spans the first three octets u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[1]) << 14 | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[2]) << 7 | u32::from(Tag::MULTIBYTE_DATA_MASK & self.0[3]) } } /// Takes an optional tag from the beginning of a source. /// /// Upon success, returns both the tag and whether the value is /// constructed. pub fn take_opt_from( source: &mut S, ) -> Result, DecodeError> { let byte = match source.take_opt_u8()? { Some(byte) => byte, None => return Ok(None) }; // clear constructed bit let mut data = [byte & !Tag::CONSTRUCTED_MASK, 0, 0, 0]; let constructed = byte & Tag::CONSTRUCTED_MASK != 0; if (data[0] & Tag::SINGLEBYTE_DATA_MASK) == Tag::SINGLEBYTE_DATA_MASK { for i in 1..=3 { data[i] = source.take_u8()?; if data[i] & Tag::LAST_OCTET_MASK == 0 { return Ok(Some((Tag(data), constructed))); } } } else { return Ok(Some((Tag(data), constructed))); } Err(source.content_err( "tag values longer than 4 bytes not implemented" )) } /// Takes a tag from the beginning of a source. /// /// Upon success, returns both the tag and whether the value is /// constructed. If there are no more octets available in the source, /// an error is returned. pub fn take_from( source: &mut S, ) -> Result<(Self, bool), DecodeError> { match Self::take_opt_from(source)? { Some(res) => Ok(res), None => Err(source.content_err("additional values expected")) } } /// Takes a tag from the beginning of a resource if it matches this tag. /// /// If there is no more data available in the source or if the tag is /// something else, returns `Ok(None)`. If the tag matches `self`, returns /// whether the value is constructed. pub fn take_from_if( self, source: &mut S, ) -> Result, DecodeError> { if source.request(1)? == 0 { return Ok(None) } let byte = source.slice()[0]; // clear constructed bit let mut data = [byte & !Tag::CONSTRUCTED_MASK, 0, 0, 0]; if (data[0] & Tag::SINGLEBYTE_DATA_MASK) == Tag::SINGLEBYTE_DATA_MASK { let mut i = 1; loop { if source.request(i + 1)? <= i { // Not enough data for a complete tag. return Err(source.content_err("short tag value")) } data[i] = source.slice()[i]; if data[i] & Tag::LAST_OCTET_MASK == 0 { break } // We don’t support tags larger than 4 bytes. if i == 3 { return Err(source.content_err( "tag values longer than 4 bytes not implemented" )) } i += 1; } } let (tag, constructed) = ( Tag(data), byte & Tag::CONSTRUCTED_MASK != 0 ); if tag == self { source.advance(tag.encoded_len()); Ok(Some(constructed)) } else { Ok(None) } } /// Returns the number of octets of the encoded form of the tag. #[allow(clippy::trivially_copy_pass_by_ref)] // for possible multi-byte tags pub fn encoded_len(&self) -> usize { if (Tag::SINGLEBYTE_DATA_MASK & self.0[0]) != Tag::SINGLEBYTE_DATA_MASK { 1 } else if Tag::LAST_OCTET_MASK & self.0[1] == 0 { 2 } else if Tag::LAST_OCTET_MASK & self.0[2] == 0 { 3 } else { 4 } } /// Encodes the tag into a target. /// /// If `constructed` is `true`, the encoded tag will signal a value in /// constructed encoding and primitive encoding otherwise. #[allow(clippy::trivially_copy_pass_by_ref)] // for possible multi-byte tags pub fn write_encoded( &self, constructed: bool, target: &mut W ) -> Result<(), io::Error> { let mut buf = self.0; if constructed { buf[0] |= Tag::CONSTRUCTED_MASK } target.write_all(&buf[..self.encoded_len()]) } } impl fmt::Display for Tag { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Tag::BOOLEAN => write!(f, "BOOLEAN"), Tag::INTEGER => write!(f, "INTEGER"), Tag::BIT_STRING => write!(f, "BIT STRING"), Tag::OCTET_STRING => write!(f, "OCTET STRING"), Tag::NULL => write!(f, "NULL"), Tag::OID => write!(f, "OBJECT IDENTIFIER"), Tag::OBJECT_DESCRIPTOR => write!(f, "ObjectDescriptor"), Tag::EXTERNAL => write!(f, "EXTERNAL"), Tag::REAL => write!(f, "REAL"), Tag::ENUMERATED => write!(f, "ENUMERATED"), Tag::EMBEDDED_PDV => write!(f, "EMBEDDED PDV"), Tag::UTF8_STRING => write!(f, "UTF8String"), Tag::RELATIVE_OID => write!(f, "RELATIVE-OID"), Tag::TIME => write!(f, "TIME"), Tag::SEQUENCE => write!(f, "SEQUENCE"), Tag::SET => write!(f, "SET"), Tag::NUMERIC_STRING => write!(f, "NumericString"), Tag::PRINTABLE_STRING => write!(f, "PrintableString"), Tag::TELETEX_STRING => write!(f, "TeletexString"), Tag::VIDEOTEX_STRING => write!(f, "VideotexString"), Tag::IA5_STRING => write!(f, "IA5String"), Tag::UTC_TIME => write!(f, "UTCTime"), Tag::GENERALIZED_TIME => write!(f, "GeneralizedTime"), Tag::GRAPHIC_STRING => write!(f, "GraphicString"), Tag::VISIBLE_STRING => write!(f, "VisibleString"), Tag::GENERAL_STRING => write!(f, "GeneralString"), Tag::UNIVERSAL_STRING => write!(f, "UniversalString"), Tag::CHARACTER_STRING => write!(f, "CHARACTER STRING"), Tag::BMP_STRING => write!(f, "BMPString"), Tag::DATE => write!(f, "DATE"), Tag::TIME_OF_DAY => write!(f, "TIME-OF-DAY"), Tag::DATE_TIME => write!(f, "DATE-TIME"), Tag::DURATION => write!(f, "DURATION"), Tag::OID_IRI => write!(f, "OID-IRI"), Tag::RELATIVE_OID_IRI => write!(f, "RELATIVE-OID-IRI"), tag => { match tag.0[0] & Tag::CLASS_MASK { Tag::UNIVERSAL => write!(f, "[UNIVERSAL ")?, Tag::APPLICATION => write!(f, "[APPLICATION ")?, Tag::CONTEXT_SPECIFIC => write!(f, "[")?, Tag::PRIVATE => write!(f, "[PRIVATE ")?, _ => unreachable!() } write!(f, "{}]", tag.number()) } } } } impl fmt::Debug for Tag { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Tag({})", self) } } //============ Tests ========================================================= #[cfg(test)] mod test { use super::*; use crate::decode::IntoSource; const TYPES: &[u8] = &[Tag::UNIVERSAL, Tag::APPLICATION, Tag::CONTEXT_SPECIFIC, Tag::PRIVATE]; #[test] fn test_single_octet_tags() { // Test edge cases. let range: Vec = (0..5).chain( Tag::MAX_VAL_FOURTH_OCTET-5..Tag::MAX_VAL_FOURTH_OCTET ).collect(); for &typ in TYPES { for i in range.clone() { let tag = Tag::new(typ, i); let expected = Tag([typ | i as u8, 0, 0, 0]); let decoded = Tag::take_from( &mut tag.0.into_source() ).unwrap(); assert_eq!( tag.take_from_if(&mut tag.0.into_source()).unwrap(), Some(false) ); // The value is not constructed. assert!(!decoded.1); // The tag is the same assert_eq!(decoded.0, expected); // We get the same number back. assert_eq!(tag.number(), i); // The representation is correct. assert_eq!(tag, expected); } } } #[test] fn test_double_octets_tags() { // Test edge cases. let range: Vec = ( Tag::MAX_VAL_FOURTH_OCTET+1..Tag::MAX_VAL_FOURTH_OCTET+5 ).chain( Tag::MAX_VAL_SPAN_1_OCTET-5..Tag::MAX_VAL_SPAN_1_OCTET ).collect(); for &typ in TYPES { for i in range.clone() { let tag = Tag::new(typ, i); let expected = Tag([ Tag::SINGLEBYTE_DATA_MASK | typ, i as u8, 0, 0 ]); let decoded = Tag::take_from( &mut tag.0.into_source() ).unwrap(); assert_eq!( tag.take_from_if(&mut tag.0.into_source()).unwrap(), Some(false) ); assert!( tag.take_from_if( &mut tag.0[0..1].into_source() ).is_err(), ); // The value is not constructed. assert!(!decoded.1); // The tag is the same assert_eq!(decoded.0, expected); assert_eq!(tag.number(), i); assert_eq!(tag, expected); } } } #[test] fn test_three_octets_tags() { // Test edge cases. let range: Vec = ( Tag::MAX_VAL_SPAN_1_OCTET+1..Tag::MAX_VAL_SPAN_1_OCTET + 5 ).chain( Tag::MAX_VAL_SPAN_2_OCTETS-5..Tag::MAX_VAL_SPAN_2_OCTETS ).collect(); for &typ in TYPES { for i in range.clone() { let tag = Tag::new(typ, i); let expected = Tag([ Tag::SINGLEBYTE_DATA_MASK | typ, (i >> 7) as u8 | Tag::LAST_OCTET_MASK, i as u8 & !Tag::LAST_OCTET_MASK, 0 ]); let decoded = Tag::take_from( &mut tag.0.into_source() ).unwrap(); assert_eq!( tag.take_from_if(&mut tag.0.into_source()).unwrap(), Some(false) ); assert!( tag.take_from_if( &mut tag.0[0..2].into_source() ).is_err(), ); // The value is not constructed. assert!(!decoded.1); // The tag is the same assert_eq!(decoded.0, expected); assert_eq!(tag.number(), i); assert_eq!(tag, expected); } } } #[test] fn test_four_octets_tags() { // Test edge cases. let range: Vec = ( Tag::MAX_VAL_SPAN_2_OCTETS+1..Tag::MAX_VAL_SPAN_2_OCTETS + 5 ).chain( Tag::MAX_VAL_SPAN_3_OCTETS-5..Tag::MAX_VAL_SPAN_3_OCTETS ).collect(); for &typ in TYPES { for i in range.clone() { let tag = Tag::new(typ, i); let expected = Tag([ Tag::SINGLEBYTE_DATA_MASK | typ, (i >> 14) as u8 | Tag::LAST_OCTET_MASK, (i >> 7) as u8 | Tag::LAST_OCTET_MASK, i as u8 & !Tag::LAST_OCTET_MASK ]); let decoded = Tag::take_from( &mut tag.0.into_source() ).unwrap(); assert_eq!( tag.take_from_if(&mut tag.0.into_source()).unwrap(), Some(false) ); assert!( tag.take_from_if( &mut tag.0[0..3].into_source() ).is_err(), ); // The value is not constructed. assert!(!decoded.1); // The tag is the same assert_eq!(decoded.0, expected); assert_eq!(tag.number(), i); assert_eq!(tag, expected); } } } #[test] fn test_tags_failures() { let large_tag = [ 0b1111_1111, 0b1000_0000, 0b1000_0000, 0b1000_0000, 0b1000_0000 ]; assert!( Tag::take_from(&mut large_tag.into_source()).is_err() ); let short_tag = [0b1111_1111, 0b1000_0000]; assert!( Tag::take_from(&mut short_tag.into_source()).is_err() ); } }