yasna-0.5.2/.cargo_vcs_info.json0000644000000001360000000000100121530ustar { "git": { "sha1": "b7e65f9a4c317494cce2d18ea02b3d6eaaea7985" }, "path_in_vcs": "" }yasna-0.5.2/Cargo.toml0000644000000025340000000000100101550ustar # 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 = "yasna" version = "0.5.2" authors = ["Masaki Hara "] include = [ "src/**/*.rs", "Cargo.toml", ] description = "ASN.1 library for Rust" homepage = "https://github.com/qnighy/yasna.rs" documentation = "https://docs.rs/yasna" readme = "README.md" keywords = [ "parser", "serialization", ] license = "MIT OR Apache-2.0" repository = "https://github.com/qnighy/yasna.rs" [package.metadata.docs.rs] features = [ "num-bigint", "bit-vec", "time", "std", ] [dependencies.bit-vec] version = "0.6.1" features = ["std"] optional = true default-features = false [dependencies.num-bigint] version = "0.4" optional = true [dependencies.time] version = "0.3.1" features = ["std"] optional = true default-features = false [dev-dependencies.num-traits] version = "0.2" default-features = false [features] default = [] std = [] yasna-0.5.2/Cargo.toml.orig000064400000000000000000000016301046102023000136320ustar 00000000000000[package] name = "yasna" version = "0.5.2" authors = ["Masaki Hara "] description = "ASN.1 library for Rust" documentation = "https://docs.rs/yasna" homepage = "https://github.com/qnighy/yasna.rs" repository = "https://github.com/qnighy/yasna.rs" readme = "README.md" keywords = ["parser", "serialization"] license = "MIT OR Apache-2.0" edition = "2018" include = [ "src/**/*.rs", "Cargo.toml", ] [features] default = [] std = [] [package.metadata.docs.rs] features = ["num-bigint", "bit-vec", "time", "std"] [dependencies] [dependencies.num-bigint] version = "0.4" optional = true [dev-dependencies.num-traits] version = "0.2" default-features = false [dependencies.bit-vec] version = "0.6.1" default-features = false features = ["std"] optional = true [dependencies.time] version = "0.3.1" optional = true default-features = false features = ["std"] [workspace] members = ["fuzz"] yasna-0.5.2/README.md000064400000000000000000000063321046102023000122260ustar 00000000000000# yasna.rs: ASN.1 library for Rust [![Build Status](https://github.com/qnighy/yasna.rs/actions/workflows/test.yml/badge.svg)](https://github.com/qnighy/yasna.rs/actions) [![](https://img.shields.io/crates/v/yasna.svg)](https://crates.io/crates/yasna) This is a Rust library for reading and writing ASN.1 data. - [crates.io/crates/yasna](https://crates.io/crates/yasna) - [Documentation](https://qnighy.github.io/yasna.rs/yasna/index.html) Since this library is at an early stage, the APIs are subject to change. However, `BERReader` and `DERWriter` functionalities are getting stable. ## Serialization/Construction Serialization in DER (Distinguished Encoding Rules) is supported. It can also be used for serialization in BER (Basic Encoding Rules). ```rust fn main() { let der = yasna::construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_i64(10); writer.next().write_bool(true); return Ok(()); }) }); println!("(10, true) = {:?}", der); } ``` Currently, these datatypes are supported: - BOOLEAN, INTEGER, BITSTRING, OCTETSTRING, NULL, OBJECT IDENTIFIER, - SEQUENCE, SEQUENCE OF, SET, SET OF, CHOICE, - UTF8String, NumericString, PrintableString, VisibleString, IA5String, BMPString, - UTCTime, GeneralizedTime, - Explicitly/Implicitly tagged types, - DEFAULT/OPTIONAL in SEQUENCE/SET. These datatypes are *not* supported: - REAL - TeletexString, VideotexString, GraphicString, GeneralString, UniversalString, - TIME, DATE, TIME-OF-DAY, DATE-TIME, DURATION. ## Deserialization/Parsing Deserialization in BER (Basic Encoding Rules) or DER (Distinguished Encoding Rules) is supported. ```rust fn main() { let asn = yasna::parse_der(&[48, 6, 2, 1, 10, 1, 1, 255], |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }).unwrap(); println!("{:?} = [48, 6, 2, 1, 10, 1, 1, 255]", asn); } ``` Currently, these datatypes are supported: - BOOLEAN, INTEGER, BITSTRING, OCTETSTRING, NULL, OBJECT IDENTIFIER, - SEQUENCE, SEQUENCE OF, SET, SET OF, CHOICE, - UTF8String, NumericString, PrintableString, VisibleString, IA5String, BMPString, - UTCTime, GeneralizedTime, - Explicitly/Implicitly tagged types, - DEFAULT/OPTIONAL in SEQUENCE. These datatypes are *not* supported: - REAL - TeletexString, VideotexString, GraphicString, GeneralString, UniversalString, - TIME, DATE, TIME-OF-DAY, DATE-TIME, DURATION. - DEFAULT/OPTIONAL in SET. ## Other encodings This library is currently specialized for BER (Basic Encoding Rules) and DER (Distinguished Encoding Rules). Other encodings such as CER (Canonical Encoding Rules), PER (Packed Encoding Rules), and XER (XML Encoding Rules) are currently out of scope. ## Streaming This library is currently specialized for on-memory serialization/deserialization. There are no plans for streaming ones. ## Compatibility The minimum supported Rust version (MSRV) of `yasna.rs` is Rust 1.36.0. Optional feature flags that enable interoperability with third-party crates (e.g. `time`) follow the policy of that crate if stricter. ## License This library is distributed under MIT/Apache-2.0 dual license. yasna-0.5.2/src/deserializer/mod.rs000064400000000000000000000367471046102023000153620ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![forbid(missing_docs)] use alloc::vec::Vec; use alloc::string::String; #[cfg(feature = "num-bigint")] use num_bigint::{BigInt,BigUint}; #[cfg(feature = "bit-vec")] use bit_vec::BitVec; use super::{ASN1Result,BERMode,BERReader,parse_ber_general}; use super::models::{ObjectIdentifier,TaggedDerValue}; #[cfg(feature = "time")] use super::models::{UTCTime,GeneralizedTime}; /// Types decodable in BER. /// /// # Examples /// /// ``` /// use yasna; /// let asn : i64 = yasna::decode_der(&[2, 3, 0, 255, 255]).unwrap(); /// assert_eq!(asn, 65535); /// ``` /// /// # Limitations /// /// Rust types don't correspond to ASN.1 types one-to-one. Not all kinds /// of ASN.1 types can be decoded via default `BERDecodable` implementation. /// /// If you want to decode ASN.1, you may implement `BERDecodable` for your /// own types or use [`parse_der`](crate::parse_der)/ /// [`parse_ber`](crate::parse_ber). /// /// # Default implementations /// /// - The decoder for `Vec` is implemented as SEQUENCE OF decoder. /// - `()` as NULL decoder. /// - Tuples (except `()`) as SEQUENCE decoder. /// - `Vec` as OCTETSTRING decoder. /// - `BitVec` as BITSTRING decoder. /// - `String` as UTF8String decoder. /// - `i64`, `u64`, `i32`, `u32`, `i16`, `u16`, `BigInt`, `BigUint` /// as INTEGER decoder. (`u8` is avoided because of confliction.) /// - `bool` as BOOLEAN decoder. /// - `ObjectIdentifier` as OBJECTT IDENTIFIER decoder. /// - `UTCTime`/`GeneralizedTime` as UTCTime/GeneralizedTime decoder. pub trait BERDecodable: Sized { /// Reads an ASN.1 value from `BERReader` and converts it to `Self`. /// /// # Examples /// /// ``` /// use yasna::{BERDecodable,BERReader,ASN1Result}; /// struct Entry { /// name: String, /// age: i64, /// } /// /// impl BERDecodable for Entry { /// fn decode_ber(reader: BERReader) -> ASN1Result { /// reader.read_sequence(|reader| { /// let name = reader.next().read_visible_string()?; /// let age = reader.next().read_i64()?; /// return Ok(Entry { /// name: name, /// age: age, /// }); /// }) /// } /// } /// fn main() { /// let entry : Entry = yasna::decode_der( /// &[48, 9, 26, 4, 74, 111, 104, 110, 2, 1, 32]).unwrap(); /// assert_eq!(entry.name, "John"); /// assert_eq!(entry.age, 32); /// } /// ``` fn decode_ber<'a, 'b>(reader: BERReader<'a, 'b>) -> ASN1Result; } /// Decodes DER/BER-encoded data. /// /// [`decode_ber`] and [`decode_der`] are shorthands /// for this function. pub fn decode_ber_general(src: &[u8], mode: BERMode) -> ASN1Result { parse_ber_general(src, mode, |reader| { T::decode_ber(reader) }) } /// Reads an ASN.1 value from `&[u8]`. /// /// If you want to accept only DER-encoded data, /// use [`decode_der`]. /// /// # Examples /// /// ``` /// use yasna; /// let asn : i64 = yasna::decode_ber(&[2, 3, 0, 255, 255]).unwrap(); /// assert_eq!(asn, 65535); /// ``` pub fn decode_ber(src: &[u8]) -> ASN1Result { decode_ber_general(src, BERMode::Ber) } /// Reads an ASN.1 value from `&[u8]`. /// /// If you want to decode BER-encoded data in general, /// use [`decode_ber`]. /// /// # Examples /// /// ``` /// use yasna; /// let asn : i64 = yasna::decode_der(&[2, 3, 0, 255, 255]).unwrap(); /// assert_eq!(asn, 65535); /// ``` pub fn decode_der(src: &[u8]) -> ASN1Result { decode_ber_general(src, BERMode::Der) } impl BERDecodable for Vec where T: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let mut ret = Vec::new(); loop { let result = reader.read_optional(|reader| { T::decode_ber(reader) })?; match result { Some(result) => { ret.push(result); }, None => { break; } }; } return Ok(ret); }) } } impl BERDecodable for i64 { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_i64() } } impl BERDecodable for u64 { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_u64() } } impl BERDecodable for i32 { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_i32() } } impl BERDecodable for u32 { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_u32() } } impl BERDecodable for i16 { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_i16() } } impl BERDecodable for u16 { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_u16() } } #[cfg(feature = "num-bigint")] impl BERDecodable for BigInt { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_bigint() } } #[cfg(feature = "num-bigint")] impl BERDecodable for BigUint { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_biguint() } } impl BERDecodable for bool { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_bool() } } #[cfg(feature = "bit-vec")] impl BERDecodable for BitVec { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_bitvec() } } impl BERDecodable for Vec { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_bytes() } } impl BERDecodable for String { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_utf8string() } } impl BERDecodable for ObjectIdentifier { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_oid() } } #[cfg(feature = "time")] impl BERDecodable for UTCTime { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_utctime() } } #[cfg(feature = "time")] impl BERDecodable for GeneralizedTime { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_generalized_time() } } impl BERDecodable for () { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_null() } } impl BERDecodable for (T0,) where T0: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; return Ok((t0,)); }) } } impl BERDecodable for (T0, T1) where T0: BERDecodable, T1: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; return Ok((t0, t1)); }) } } impl BERDecodable for (T0, T1, T2) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; return Ok((t0, t1, t2)); }) } } impl BERDecodable for (T0, T1, T2, T3) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4, T5) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable, T5: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; let t5 = T5::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4, t5)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4, T5, T6) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable, T5: BERDecodable, T6: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; let t5 = T5::decode_ber(reader.next())?; let t6 = T6::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4, t5, t6)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4, T5, T6, T7) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable, T5: BERDecodable, T6: BERDecodable, T7: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; let t5 = T5::decode_ber(reader.next())?; let t6 = T6::decode_ber(reader.next())?; let t7 = T7::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4, t5, t6, t7)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable, T5: BERDecodable, T6: BERDecodable, T7: BERDecodable, T8: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; let t5 = T5::decode_ber(reader.next())?; let t6 = T6::decode_ber(reader.next())?; let t7 = T7::decode_ber(reader.next())?; let t8 = T8::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4, t5, t6, t7, t8)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable, T5: BERDecodable, T6: BERDecodable, T7: BERDecodable, T8: BERDecodable, T9: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; let t5 = T5::decode_ber(reader.next())?; let t6 = T6::decode_ber(reader.next())?; let t7 = T7::decode_ber(reader.next())?; let t8 = T8::decode_ber(reader.next())?; let t9 = T9::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4, t5, t6, t7, t8, t9)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable, T5: BERDecodable, T6: BERDecodable, T7: BERDecodable, T8: BERDecodable, T9: BERDecodable, T10: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; let t5 = T5::decode_ber(reader.next())?; let t6 = T6::decode_ber(reader.next())?; let t7 = T7::decode_ber(reader.next())?; let t8 = T8::decode_ber(reader.next())?; let t9 = T9::decode_ber(reader.next())?; let t10 = T10::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); }) } } impl BERDecodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) where T0: BERDecodable, T1: BERDecodable, T2: BERDecodable, T3: BERDecodable, T4: BERDecodable, T5: BERDecodable, T6: BERDecodable, T7: BERDecodable, T8: BERDecodable, T9: BERDecodable, T10: BERDecodable, T11: BERDecodable { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_sequence(|reader| { let t0 = T0::decode_ber(reader.next())?; let t1 = T1::decode_ber(reader.next())?; let t2 = T2::decode_ber(reader.next())?; let t3 = T3::decode_ber(reader.next())?; let t4 = T4::decode_ber(reader.next())?; let t5 = T5::decode_ber(reader.next())?; let t6 = T6::decode_ber(reader.next())?; let t7 = T7::decode_ber(reader.next())?; let t8 = T8::decode_ber(reader.next())?; let t9 = T9::decode_ber(reader.next())?; let t10 = T10::decode_ber(reader.next())?; let t11 = T11::decode_ber(reader.next())?; return Ok((t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11)); }) } } impl BERDecodable for TaggedDerValue { fn decode_ber(reader: BERReader) -> ASN1Result { reader.read_tagged_der() } } yasna-0.5.2/src/lib.rs000064400000000000000000000112111046102023000126420ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A library for reading and writing ASN.1 data. //! //! # Examples //! //! ## Encoding/decoding simple data //! //! A type implementing [`DEREncodable`] can be easily encoded: //! //! ``` //! fn main() { //! let der = yasna::encode_der(&(10, true)); //! println!("(10, true) = {:?}", der); //! } //! ``` //! //! Similarly, a type implementing [`BERDecodable`] can be //! easily decoded: //! //! ``` //! fn main() { //! let asn: (i64, bool) = yasna::decode_der( //! &[48, 6, 2, 1, 10, 1, 1, 255]).unwrap(); //! println!("{:?} = [48, 6, 2, 1, 10, 1, 1, 255]", asn); //! } //! ``` //! //! ## Encoding/decoding by hand //! //! The default [`DEREncodable`]/[`BERDecodable`] implementations can't handle //! all ASN.1 types. In many cases you have to write your reader/writer //! by hand. //! //! To serialize ASN.1 data, you can use [`construct_der`]. //! //! ``` //! fn main() { //! let der = yasna::construct_der(|writer| { //! writer.write_sequence(|writer| { //! writer.next().write_i64(10); //! writer.next().write_bool(true); //! }) //! }); //! println!("(10, true) = {:?}", der); //! } //! ``` //! //! To deserialize ASN.1 data, you can use [`parse_ber`] or [`parse_der`]. //! //! ``` //! fn main() { //! let asn = yasna::parse_der(&[48, 6, 2, 1, 10, 1, 1, 255], |reader| { //! reader.read_sequence(|reader| { //! let i = reader.next().read_i64()?; //! let b = reader.next().read_bool()?; //! return Ok((i, b)); //! }) //! }).unwrap(); //! println!("{:?} = [48, 6, 2, 1, 10, 1, 1, 255]", asn); //! } //! ``` #![forbid(unsafe_code)] #![deny(missing_docs)] #![no_std] extern crate alloc; #[cfg(any(test, feature = "std"))] extern crate std; pub mod tags; pub mod models; mod writer; mod reader; mod deserializer; mod serializer; pub use crate::writer::{construct_der,try_construct_der}; pub use crate::writer::{construct_der_seq,try_construct_der_seq}; pub use crate::writer::{DERWriter,DERWriterSeq,DERWriterSet}; pub use crate::reader::{parse_ber_general,parse_ber,parse_der,BERMode}; pub use crate::reader::{BERReader,BERReaderSeq,BERReaderSet}; pub use crate::reader::{ASN1Error,ASN1ErrorKind,ASN1Result}; pub use crate::deserializer::{BERDecodable,decode_ber_general,decode_ber,decode_der}; pub use crate::serializer::{DEREncodable,encode_der}; /// A value of the ASN.1 primitive/constructed ("P/C") bit. #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum PCBit { /// The bit's value is "Primitive" Primitive = 0, /// The bit's value is "Constructed" Constructed = 1, } /// An ASN.1 tag class, used in [`Tag`]. /// /// A tag class is one of: /// /// - UNIVERSAL /// - APPLICATION /// - context specific /// - PRIVATE #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum TagClass { /// The UNIVERSAL tag class Universal = 0, /// The APPLICATION tag class Application = 1, /// The CONTEXT-SPECIFIC tag class ContextSpecific = 2, /// The PRIVATE tag class Private = 3, } const TAG_CLASSES : [TagClass; 4] = [ TagClass::Universal, TagClass::Application, TagClass::ContextSpecific, TagClass::Private, ]; /// An ASN.1 tag. /// /// An ASN.1 tag is a pair of a tag class and a tag number. /// /// - A tag class is one of: /// - UNIVERSAL /// - APPLICATION /// - context specific /// - PRIVATE /// - A tag number is a nonnegative integer. /// In this library, tag numbers are assumed to fit into `u64`. #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Tag { /// The tag class pub tag_class: TagClass, /// The tag number pub tag_number: u64, } impl Tag { /// Constructs an APPLICATION tag, namely \[APPLICATION n\]. pub fn application(tag_number: u64) -> Tag { return Tag { tag_class: TagClass::Application, tag_number, } } /// Constructs a context specific tag, namely \[n\]. pub fn context(tag_number: u64) -> Tag { return Tag { tag_class: TagClass::ContextSpecific, tag_number, } } /// Constructs a PRIVATE tag, namely \[PRIVATE n\]. pub fn private(tag_number: u64) -> Tag { return Tag { tag_class: TagClass::Private, tag_number, } } } yasna-0.5.2/src/models/der.rs000064400000000000000000000065231046102023000141430ustar 00000000000000// Copyright 2017 Fortanix, Inc. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use alloc::vec::Vec; use super::super::{PCBit, Tag}; use super::super::tags::*; /// Container for a tag and arbitrary DER value. /// /// When obtained by `BERReader::read_tagged_der` in DER mode, /// the reader verifies that the payload is actually valid DER. /// When constructed from bytes, the caller is responsible for /// providing valid DER. #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct TaggedDerValue { tag: Tag, pcbit: PCBit, value: Vec, } impl TaggedDerValue { /// Constructs a new `TaggedDerValue` as an octet string pub fn from_octetstring(bytes: Vec) -> Self { TaggedDerValue { tag: TAG_OCTETSTRING, pcbit: PCBit::Primitive, value: bytes, } } /// Constructs a new `TaggedDerValue` from its tag and content pub fn from_tag_and_bytes(tag: Tag, bytes: Vec) -> Self { let pcbit = match tag { TAG_SEQUENCE | TAG_SET => PCBit::Constructed, _ => PCBit::Primitive, }; TaggedDerValue { tag, pcbit, value: bytes, } } /// Constructs a new `TaggedDerValue` from its tag, /// primitive/constructed bit, and content pub fn from_tag_pc_and_bytes(tag: Tag, pcbit: PCBit, bytes: Vec) -> Self { TaggedDerValue { tag, pcbit, value: bytes, } } /// Returns the tag pub fn tag(&self) -> Tag { self.tag } /// Returns the primitive/constructed bit pub fn pcbit(&self) -> PCBit { self.pcbit } /// Returns the value pub fn value(&self) -> &[u8] { &self.value } /// If the value is something that contains raw bytes, /// returns its content. /// /// # Examples /// ``` /// use yasna::models::TaggedDerValue; /// let value = TaggedDerValue::from_octetstring(vec![1, 2, 3, 4, 5, 6]); /// assert!(value.as_bytes() == Some(&[1, 2, 3, 4, 5, 6])); /// ``` pub fn as_bytes(&self) -> Option<&[u8]> { match (self.tag, self.pcbit) { (TAG_BITSTRING, PCBit::Primitive) => { // First byte of bitstring value is number of unused bits. // We only accept bitstrings that are multiples of bytes. if let Some(&0) = self.value.first() { Some(&self.value[1..]) } else { None } }, (TAG_OCTETSTRING, PCBit::Primitive) => Some(&self.value), _ => None } } /// If the value is something string-like, returns it as string. pub fn as_str(&self) -> Option<&str> { use alloc::str::from_utf8; match (self.tag, self.pcbit) { (TAG_IA5STRING, PCBit::Primitive) => from_utf8(&self.value).ok(), (TAG_PRINTABLESTRING, PCBit::Primitive) => from_utf8(&self.value).ok(), (TAG_UTF8STRING, PCBit::Primitive) => from_utf8(&self.value).ok(), _ => None } } } yasna-0.5.2/src/models/mod.rs000064400000000000000000000011701046102023000141410ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Provides datatypes which correspond to ASN.1 types. #![forbid(missing_docs)] mod oid; #[cfg(feature = "time")] mod time; mod der; pub use self::oid::{ObjectIdentifier, ParseOidError}; #[cfg(feature = "time")] pub use self::time::{UTCTime,GeneralizedTime}; pub use self::der::TaggedDerValue; yasna-0.5.2/src/models/oid.rs000064400000000000000000000112171046102023000141400ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use core::fmt::{self, Display}; #[cfg(feature = "std")] use std::error::Error; use alloc::str::FromStr; use alloc::vec::Vec; /// A type that represents object identifiers. /// /// This is actually a thin wrapper of `Vec`. /// /// # Examples /// /// ``` /// use yasna::models::ObjectIdentifier; /// let sha384WithRSAEncryption = ObjectIdentifier::from_slice(& /// [1, 2, 840, 113549, 1, 1, 12]); /// println!("{}", sha384WithRSAEncryption); /// ``` #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct ObjectIdentifier { components: Vec, } impl ObjectIdentifier { /// Constructs a new `ObjectIdentifier` from `Vec`. /// /// # Examples /// /// ``` /// use yasna::models::ObjectIdentifier; /// let pkcs1 = ObjectIdentifier::new( /// [1, 2, 840, 113549, 1, 1].to_vec()); /// println!("{}", pkcs1); /// ``` pub fn new(components: Vec) -> Self { return ObjectIdentifier { components, }; } /// Constructs a new `ObjectIdentifier` from `&[u64]`. /// /// # Examples /// /// ``` /// use yasna::models::ObjectIdentifier; /// let pkcs1 = ObjectIdentifier::from_slice(& /// [1, 2, 840, 113549, 1, 1]); /// println!("{}", pkcs1); /// ``` pub fn from_slice(components: &[u64]) -> Self { return ObjectIdentifier { components: components.to_vec(), }; } /// Borrows its internal vector of components. /// /// # Examples /// /// ``` /// use yasna::models::ObjectIdentifier; /// let pkcs1 = ObjectIdentifier::from_slice(& /// [1, 2, 840, 113549, 1, 1]); /// let components : &Vec = pkcs1.components(); /// ``` pub fn components(&self) -> &Vec { &self.components } /// Mutably borrows its internal vector of components. /// /// # Examples /// /// ``` /// use yasna::models::ObjectIdentifier; /// let mut pkcs1 = ObjectIdentifier::from_slice(& /// [1, 2, 840, 113549, 1, 1]); /// let components : &mut Vec = pkcs1.components_mut(); /// ``` pub fn components_mut(&mut self) -> &mut Vec { &mut self.components } /// Extracts its internal vector of components. /// /// # Examples /// /// ``` /// use yasna::models::ObjectIdentifier; /// let pkcs1 = ObjectIdentifier::from_slice(& /// [1, 2, 840, 113549, 1, 1]); /// let mut components : Vec = pkcs1.into_components(); /// ``` pub fn into_components(self) -> Vec { self.components } } impl Display for ObjectIdentifier { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { let mut fst = true; for &component in &self.components { if fst { write!(f, "{}", component)?; } else { write!(f, ".{}", component)?; } fst = false; } return Ok(()); } } #[derive(Debug, Clone)] /// An error indicating failure to parse an Object identifier pub struct ParseOidError(()); #[cfg(feature = "std")] impl Error for ParseOidError {} impl Display for ParseOidError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { f.write_str("Failed to parse OID") } } impl FromStr for ObjectIdentifier { type Err = ParseOidError; fn from_str(s: &str) -> Result { s.split(".") .map(|s| s.parse().map_err(|_| ParseOidError(()) )) .collect::>() .map(ObjectIdentifier::new) } } impl AsRef<[u64]> for ObjectIdentifier { fn as_ref(&self) -> &[u64] { &self.components } } impl From> for ObjectIdentifier { fn from(components: Vec) -> ObjectIdentifier { Self::new(components) } } #[test] fn test_display_oid() { use alloc::format; let pkcs1 = ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1]); assert_eq!(format!("{}", pkcs1), "1.2.840.113549.1.1"); } #[test] fn parse_oid() { assert_eq!("1.2.840.113549.1.1".parse::().unwrap().components(), &[1, 2, 840, 113549, 1, 1]); "1.2.840.113549.1.1.".parse::().unwrap_err(); "1.2.840.113549.1.1x".parse::().unwrap_err(); "".parse::().unwrap_err(); } yasna-0.5.2/src/models/time.rs000064400000000000000000000572651046102023000143400ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use alloc::string::String; use alloc::vec::Vec; use core::convert::TryFrom; use time::{Date, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset}; /// Date and time between 1950-01-01T00:00:00Z and 2049-12-31T23:59:59Z. /// It cannot express fractional seconds and leap seconds. /// It doesn't carry timezone information. /// /// Corresponds to ASN.1 UTCTime type. Often used in conjunction with /// [`GeneralizedTime`]. /// /// # Features /// /// This struct is enabled by `time` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["time"] } /// ``` /// /// # Examples /// /// ``` /// # fn main() { /// use yasna::models::UTCTime; /// let datetime = *UTCTime::parse(b"8201021200Z").unwrap().datetime(); /// assert_eq!(datetime.year(), 1982); /// assert_eq!(datetime.month() as u8, 1); /// assert_eq!(datetime.day(), 2); /// assert_eq!(datetime.hour(), 12); /// assert_eq!(datetime.minute(), 0); /// assert_eq!(datetime.second(), 0); /// assert_eq!(datetime.nanosecond(), 0); /// # } /// ``` #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct UTCTime { datetime: OffsetDateTime, } impl UTCTime { /// Parses ASN.1 string representation of UTCTime. /// /// # Examples /// /// ``` /// use yasna::models::UTCTime; /// let datetime = UTCTime::parse(b"000229123456Z").unwrap(); /// assert_eq!(&datetime.to_string(), "000229123456Z"); /// ``` /// /// # Errors /// /// It returns `None` if the given string does not specify a correct /// datetime. /// /// # Interpretation /// /// While neither X.680 nor X.690 specify interpretation of 2-digits year, /// X.501 specifies that UTCTime in Time shall be interpreted as between /// 1950 and 2049. This method parses the string according to the X.501 /// rule. pub fn parse(buf: &[u8]) -> Option { if buf.len() < 11 { return None; } // i: a position of [Z+-]. let i = if [b'+', b'-', b'Z'].contains(&buf[10]) { 10 } else { 12 }; if buf.len() < i+1 || ![b'+', b'-', b'Z'].contains(&buf[i]) { return None; } let len = if buf[i] == b'Z' { i+1 } else { i+5 }; if len != buf.len() { return None; } if !buf[..i].iter().all(|&b| b'0' <= b && b <= b'9') || !buf[i+1..].iter().all(|&b| b'0' <= b && b <= b'9') { return None; } let year_short: i32 = ((buf[0] - b'0') as i32) * 10 + ((buf[1] - b'0') as i32); let year = if year_short < 50 { year_short + 2000 } else { year_short + 1900 }; let month = Month::try_from((buf[2] - b'0') * 10 + (buf[3] - b'0')).ok()?; let day = (buf[4] - b'0') * 10 + (buf[5] - b'0'); let hour = (buf[6] - b'0') * 10 + (buf[7] - b'0'); let minute = (buf[8] - b'0') * 10 + (buf[9] - b'0'); let second = if i == 12 { (buf[10] - b'0') * 10 + (buf[11] - b'0') } else { 0 }; let offset_hour: i8 = if buf[i] == b'Z' { 0 } else { ((buf[i+1] - b'0') as i8) * 10 + ((buf[i+2] - b'0') as i8) }; let offset_minute: i8 = if buf[i] == b'Z' { 0 } else { ((buf[i+3] - b'0') as i8) * 10 + ((buf[i+4] - b'0') as i8) }; let date = Date::from_calendar_date(year, month, day).ok()?; let time = Time::from_hms(hour, minute, second).ok()?; let datetime = PrimitiveDateTime::new(date, time); if !(offset_hour < 24 && offset_minute < 60) { return None; } let offset = if buf[i] == b'+' { UtcOffset::from_hms(offset_hour, offset_minute, 0).ok()? } else { UtcOffset::from_hms(-offset_hour, -offset_minute, 0).ok()? }; let datetime = datetime.assume_offset(offset).to_offset(UtcOffset::UTC); // While the given local datatime is in [1950, 2050) by definition, // the UTC datetime can be out of bounds. We check this. if !(1950 <= datetime.year() && datetime.year() < 2050) { return None; } return Some(UTCTime { datetime: datetime, }); } /// Constructs `UTCTime` from an `OffsetDateTime`. /// /// # Panics /// /// Panics when UTCTime can't represent the datetime. That is: /// /// - The year is not between 1950 and 2049. /// - It is in a leap second. /// - It has a non-zero nanosecond value. pub fn from_datetime(datetime: OffsetDateTime) -> Self { let datetime = datetime.to_offset(UtcOffset::UTC); assert!(1950 <= datetime.year() && datetime.year() < 2050, "Can't express a year {:?} in UTCTime", datetime.year()); assert!(datetime.nanosecond() < 1_000_000_000, "Can't express a leap second in UTCTime"); assert!(datetime.nanosecond() == 0, "Can't express a non-zero nanosecond in UTCTime"); return UTCTime { datetime: datetime, }; } /// Constructs `UTCTime` from an `OffsetDateTime`. /// /// # Errors /// /// It returns `None` when UTCTime can't represent the datetime. That is: /// /// - The year is not between 1950 and 2049. /// - It is in a leap second. /// - It has a non-zero nanosecond value. pub fn from_datetime_opt(datetime: OffsetDateTime) -> Option { let datetime = datetime.to_offset(UtcOffset::UTC); if !(1950 <= datetime.year() && datetime.year() < 2050) { return None; } if !(datetime.nanosecond() == 0) { return None; } return Some(UTCTime { datetime: datetime, }); } /// Returns the `OffsetDateTime` it represents. pub fn datetime(&self) -> &OffsetDateTime { &self.datetime } /// Returns ASN.1 canonical representation of the datetime as `Vec`. pub fn to_bytes(&self) -> Vec { let mut buf = Vec::with_capacity(13); buf.push((self.datetime.year() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.year() % 10) as u8 + b'0'); buf.push((self.datetime.month() as u8 / 10 % 10) + b'0'); buf.push((self.datetime.month() as u8 % 10) + b'0'); buf.push((self.datetime.day() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.day() % 10) as u8 + b'0'); buf.push((self.datetime.hour() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.hour() % 10) as u8 + b'0'); buf.push((self.datetime.minute() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.minute() % 10) as u8 + b'0'); buf.push((self.datetime.second() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.second() % 10) as u8 + b'0'); buf.push(b'Z'); return buf; } /// Returns ASN.1 canonical representation of the datetime as `String`. pub fn to_string(&self) -> String { String::from_utf8(self.to_bytes()).unwrap() } } /// Date and time between 0000-01-01T00:00:00Z and 9999-12-31T23:59:60.999...Z. /// /// It can contain arbitrary length of decimal fractional seconds. /// However, it doesn't carry accuracy information. /// It can also contain leap seconds. /// /// The datetime is canonicalized to UTC. /// It doesn't carry timezone information. /// /// Corresponds to ASN.1 GeneralizedTime type. Often used in conjunction with /// [`UTCTime`]. /// /// # Features /// /// This struct is enabled by `time` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["time"] } /// ``` /// /// # Examples /// /// ``` /// # fn main() { /// use yasna::models::GeneralizedTime; /// let datetime = /// *GeneralizedTime::parse(b"19851106210627.3Z").unwrap().datetime(); /// assert_eq!(datetime.year(), 1985); /// assert_eq!(datetime.month() as u8, 11); /// assert_eq!(datetime.day(), 6); /// assert_eq!(datetime.hour(), 21); /// assert_eq!(datetime.minute(), 6); /// assert_eq!(datetime.second(), 27); /// assert_eq!(datetime.nanosecond(), 300_000_000); /// # } /// ``` #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct GeneralizedTime { datetime: OffsetDateTime, sub_nano: Vec, // TODO: time does not support leap seconds. This is a simple hack to support round-tripping. is_leap_second: bool, } impl GeneralizedTime { /// Almost same as `parse`. It takes `default_offset` however. /// GeneralizedTime value can omit offset in local time. /// In that case, `default_offset` is used instead. fn parse_general(buf: &[u8], default_offset: Option) -> Option { if buf.len() < 10 { return None; } if !buf[..10].iter().all(|&b| b'0' <= b && b <= b'9') { return None; } let year: i32 = ((buf[0] - b'0') as i32) * 1000 + ((buf[1] - b'0') as i32) * 100 + ((buf[2] - b'0') as i32) * 10 + ((buf[3] - b'0') as i32); let month = Month::try_from((buf[4] - b'0') * 10 + (buf[5] - b'0')).ok()?; let day = (buf[6] - b'0') * 10 + (buf[7] - b'0'); let hour = (buf[8] - b'0') * 10 + (buf[9] - b'0'); // i: current position on `buf` let mut i = 10; // The factor to scale the fraction part to nanoseconds. let mut fraction_scale : i64 = 1_000_000_000; let mut minute: u8; if i+2 <= buf.len() && buf[i..i+2].iter().all(|&b| b'0' <= b && b <= b'9') { minute = (buf[i] - b'0') * 10 + (buf[i + 1] - b'0'); i += 2; } else { fraction_scale = 3_600_000_000_000; minute = 0; } let mut second: u8; if i+2 <= buf.len() && buf[i..i+2].iter().all(|&b| b'0' <= b && b <= b'9') { second = (buf[i] - b'0') * 10 + (buf[i + 1] - b'0'); i += 2; } else { if fraction_scale == 1_000_000_000 { fraction_scale = 60_000_000_000; } second = 0; } let mut nanosecond = 0; let mut sub_nano = Vec::new(); if i+2 <= buf.len() && (buf[i] == b'.' || buf[i] == b',') && b'0' <= buf[i+1] && buf[i+1] <= b'9' { i += 1; let mut j = 0; while i+j < buf.len() && b'0' <= buf[i+j] && buf[i+j] <= b'9' { sub_nano.push(b'0'); j += 1; } let mut carry : i64 = 0; for k in (0..j).rev() { let digit = (buf[i+k] - b'0') as i64; let sum = digit * fraction_scale + carry; carry = sum / 10; sub_nano[k] = b'0' + ((sum % 10) as u8); } nanosecond = (carry % 1_000_000_000) as u32; second += (carry / 1_000_000_000 % 60) as u8; minute += (carry / 60_000_000_000) as u8; while let Some(&digit) = sub_nano.last() { if digit == b'0' { sub_nano.pop(); } else { break; } } i += j; } let mut is_leap_second = false; if second == 60 { // TODO: `time` doesn't accept leap seconds, so we use a flag to preserve is_leap_second = true; second = 59; } let date = Date::from_calendar_date(year, month, day).ok()?; let time = Time::from_hms_nano(hour, minute, second, nanosecond).ok()?; let naive_datetime = PrimitiveDateTime::new(date, time); let datetime: OffsetDateTime; if i == buf.len() { // Local datetime with no timezone information. datetime = naive_datetime .assume_offset(default_offset?) .to_offset(UtcOffset::UTC); } else if i < buf.len() && buf[i] == b'Z' { // UTC time. datetime = naive_datetime.assume_utc(); i += 1; } else if i < buf.len() && (buf[i] == b'+' || buf[i] == b'-') { // Local datetime with offset information. let offset_sign = buf[i]; i += 1; if !(i+2 <= buf.len() && buf[i..i+2].iter().all(|&b| b'0' <= b && b <= b'9')) { return None; } let offset_hour = ((buf[i] - b'0') as i8) * 10 + ((buf[i+1] - b'0') as i8); i += 2; let offset_minute; if i+2 <= buf.len() && buf[i..i+2].iter().all(|&b| b'0' <= b && b <= b'9') { offset_minute = ((buf[i] - b'0') as i8) * 10 + ((buf[i+1] - b'0') as i8); i += 2; } else { offset_minute = 0; } if !(offset_hour < 24 && offset_minute < 60) { return None; } let offset = if offset_sign == b'+' { UtcOffset::from_hms(offset_hour, offset_minute, 0) } else { UtcOffset::from_hms(-offset_hour, -offset_minute, 0) }; datetime = naive_datetime .assume_offset(offset.ok()?) .to_offset(UtcOffset::UTC); } else { return None; } if i != buf.len() { return None; } // While the given local datatime is in [0, 10000) by definition, // the UTC datetime can be out of bounds. We check this. if !(0 <= datetime.year() && datetime.year() < 10000) { return None; } return Some(GeneralizedTime { datetime: datetime, sub_nano: sub_nano, is_leap_second, }); } /// Parses ASN.1 string representation of GeneralizedTime. /// /// # Examples /// /// ``` /// use yasna::models::GeneralizedTime; /// let datetime = GeneralizedTime::parse(b"1985110621.14159Z").unwrap(); /// assert_eq!(&datetime.to_string(), "19851106210829.724Z"); /// ``` /// /// # Errors /// /// It returns `None` if the given string does not specify a correct /// datetime. pub fn parse(buf: &[u8]) -> Option { Self::parse_general(buf, None) } /// Parses ASN.1 string representation of GeneralizedTime, with the /// default timezone for local time given. /// /// # Examples /// /// ``` /// use yasna::models::GeneralizedTime; /// let datetime = GeneralizedTime::parse(b"1985110621.14159Z").unwrap(); /// assert_eq!(&datetime.to_string(), "19851106210829.724Z"); /// ``` /// /// # Errors /// /// It returns `None` if the given string does not specify a correct /// datetime. pub fn parse_with_offset(buf: &[u8], default_offset: UtcOffset) -> Option { Self::parse_general(buf, Some(default_offset)) } /// Constructs `GeneralizedTime` from an `OffsetDateTime`. /// /// # Panics /// /// Panics when GeneralizedTime can't represent the datetime. That is: /// /// - The year is not between 0 and 9999. pub fn from_datetime(datetime: OffsetDateTime) -> Self { let datetime = datetime.to_offset(UtcOffset::UTC); assert!(0 <= datetime.year() && datetime.year() < 10000, "Can't express a year {:?} in GeneralizedTime", datetime.year()); return GeneralizedTime { datetime: datetime, sub_nano: Vec::new(), is_leap_second: false, }; } /// Constructs `GeneralizedTime` from an `OffsetDateTime`. /// /// # Errors /// /// It returns `None` when GeneralizedTime can't represent the datetime. /// That is: /// /// - The year is not between 0 and 9999. pub fn from_datetime_opt(datetime: OffsetDateTime) -> Option { let datetime = datetime.to_offset(UtcOffset::UTC); if !(0 <= datetime.year() && datetime.year() < 10000) { return None; } return Some(GeneralizedTime { datetime: datetime, sub_nano: Vec::new(), is_leap_second: false, }); } /// Constructs `GeneralizedTime` from an `OffsetDateTime` and sub-nanoseconds /// digits. /// /// # Panics /// /// Panics when GeneralizedTime can't represent the datetime. That is: /// /// - The year is not between 0 and 9999. /// /// It also panics if `sub_nano` contains a non-digit character. pub fn from_datetime_and_sub_nano(datetime: OffsetDateTime, sub_nano: &[u8]) -> Self { let datetime = datetime.to_offset(UtcOffset::UTC); assert!(0 <= datetime.year() && datetime.year() < 10000, "Can't express a year {:?} in GeneralizedTime", datetime.year()); assert!(sub_nano.iter().all(|&b| b'0' <= b && b <= b'9'), "sub_nano contains a non-digit character"); let mut sub_nano = sub_nano.to_vec(); while sub_nano.len() > 0 && *sub_nano.last().unwrap() == b'0' { sub_nano.pop(); } return GeneralizedTime { datetime: datetime, sub_nano: sub_nano, is_leap_second: false, }; } /// Constructs `GeneralizedTime` from an `OffsetDateTime` and sub-nanoseconds /// digits. /// /// # Errors /// /// It returns `None` when GeneralizedTime can't represent the datetime. /// That is: /// /// - The year is not between 0 and 9999. /// /// It also returns `None` if `sub_nano` contains a non-digit character. pub fn from_datetime_and_sub_nano_opt( datetime: OffsetDateTime, sub_nano: &[u8], ) -> Option { let datetime = datetime.to_offset(UtcOffset::UTC); if !(0 <= datetime.year() && datetime.year() < 10000) { return None; } if !(sub_nano.iter().all(|&b| b'0' <= b && b <= b'9')) { return None; } let mut sub_nano = sub_nano.to_vec(); while sub_nano.len() > 0 && *sub_nano.last().unwrap() == b'0' { sub_nano.pop(); } return Some(GeneralizedTime { datetime: datetime, sub_nano: sub_nano, is_leap_second: false, }); } /// Returns the `OffsetDateTime` it represents. /// /// Leap seconds and sub-nanoseconds digits will be discarded. pub fn datetime(&self) -> &OffsetDateTime { &self.datetime } /// Returns sub-nanoseconds digits of the datetime. pub fn sub_nano(&self) -> &[u8] { &self.sub_nano } /// Returns ASN.1 canonical representation of the datetime as `Vec`. pub fn to_bytes(&self) -> Vec { let mut buf = Vec::with_capacity(24); buf.push((self.datetime.year() / 1000 % 10) as u8 + b'0'); buf.push((self.datetime.year() / 100 % 10) as u8 + b'0'); buf.push((self.datetime.year() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.year() % 10) as u8 + b'0'); buf.push((self.datetime.month() as u8 / 10 % 10) + b'0'); buf.push((self.datetime.month() as u8 % 10) + b'0'); buf.push((self.datetime.day() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.day() % 10) as u8 + b'0'); buf.push((self.datetime.hour() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.hour() % 10) as u8 + b'0'); buf.push((self.datetime.minute() / 10 % 10) as u8 + b'0'); buf.push((self.datetime.minute() % 10) as u8 + b'0'); let mut second = self.datetime.second(); let nanosecond = self.datetime.nanosecond(); // Cope with leap seconds. if self.is_leap_second { debug_assert!(second == 59, "is_leap_second is set, but second = {}", second); second += 1; } buf.push((second / 10 % 10) as u8 + b'0'); buf.push((second % 10) as u8 + b'0'); buf.push(b'.'); buf.push((nanosecond / 100_000_000 % 10) as u8 + b'0'); buf.push((nanosecond / 10_000_000 % 10) as u8 + b'0'); buf.push((nanosecond / 1_000_000 % 10) as u8 + b'0'); buf.push((nanosecond / 100_000 % 10) as u8 + b'0'); buf.push((nanosecond / 10_000 % 10) as u8 + b'0'); buf.push((nanosecond / 1_000 % 10) as u8 + b'0'); buf.push((nanosecond / 100 % 10) as u8 + b'0'); buf.push((nanosecond / 10 % 10) as u8 + b'0'); buf.push((nanosecond % 10) as u8 + b'0'); buf.extend_from_slice(&self.sub_nano); // Truncates trailing zeros. while buf.len() > 14 && { let b = *buf.last().unwrap(); b == b'0' || b == b'.' } { buf.pop(); } buf.push(b'Z'); return buf; } /// Returns ASN.1 canonical representation of the datetime as `String`. pub fn to_string(&self) -> String { String::from_utf8(self.to_bytes()).unwrap() } } #[test] fn test_utctime_parse() { let datetime = *UTCTime::parse(b"8201021200Z").unwrap().datetime(); assert_eq!(datetime.year(), 1982); assert_eq!(datetime.month() as u8, 1); assert_eq!(datetime.day(), 2); assert_eq!(datetime.hour(), 12); assert_eq!(datetime.minute(), 0); assert_eq!(datetime.second(), 0); assert_eq!(datetime.nanosecond(), 0); let datetime = *UTCTime::parse(b"0101021200Z").unwrap().datetime(); assert_eq!(datetime.year(), 2001); assert_eq!(datetime.month() as u8, 1); assert_eq!(datetime.day(), 2); assert_eq!(datetime.hour(), 12); assert_eq!(datetime.minute(), 0); assert_eq!(datetime.second(), 0); assert_eq!(datetime.nanosecond(), 0); let datetime = UTCTime::parse(b"8201021200Z").unwrap(); assert_eq!(&datetime.to_string(), "820102120000Z"); let datetime = UTCTime::parse(b"8201020700-0500").unwrap(); assert_eq!(&datetime.to_string(), "820102120000Z"); let datetime = UTCTime::parse(b"0101021200Z").unwrap(); assert_eq!(&datetime.to_string(), "010102120000Z"); let datetime = UTCTime::parse(b"010102120034Z").unwrap(); assert_eq!(&datetime.to_string(), "010102120034Z"); let datetime = UTCTime::parse(b"000229123456Z").unwrap(); assert_eq!(&datetime.to_string(), "000229123456Z"); } #[test] fn test_generalized_time_parse() { let datetime = *GeneralizedTime::parse(b"19851106210627.3Z").unwrap().datetime(); assert_eq!(datetime.year(), 1985); assert_eq!(datetime.month() as u8, 11); assert_eq!(datetime.day(), 6); assert_eq!(datetime.hour(), 21); assert_eq!(datetime.minute(), 6); assert_eq!(datetime.second(), 27); assert_eq!(datetime.nanosecond(), 300_000_000); let datetime = GeneralizedTime::parse(b"19851106210627.3-0500").unwrap(); assert_eq!(&datetime.to_string(), "19851107020627.3Z"); let datetime = GeneralizedTime::parse(b"198511062106Z").unwrap(); assert_eq!(&datetime.to_string(), "19851106210600Z"); let datetime = GeneralizedTime::parse(b"198511062106.456Z").unwrap(); assert_eq!(&datetime.to_string(), "19851106210627.36Z"); let datetime = GeneralizedTime::parse(b"1985110621Z").unwrap(); assert_eq!(&datetime.to_string(), "19851106210000Z"); let datetime = GeneralizedTime::parse(b"1985110621.14159Z").unwrap(); assert_eq!(&datetime.to_string(), "19851106210829.724Z"); let datetime = GeneralizedTime::parse(b"19990101085960.1234+0900").unwrap(); assert_eq!(&datetime.to_string(), "19981231235960.1234Z"); let datetime = GeneralizedTime::parse( b"20080229033411.3625431984612391672391625532918636000680000-0500" ).unwrap(); assert_eq!(&datetime.to_string(), "20080229083411.362543198461239167239162553291863600068Z"); } yasna-0.5.2/src/reader/error.rs000064400000000000000000000031411046102023000144720ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "std")] use std::{error::Error, io}; use core::fmt::{self, Display}; #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct ASN1Error { kind: ASN1ErrorKind, } #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum ASN1ErrorKind { Eof, Extra, IntegerOverflow, StackOverflow, Invalid, } pub type ASN1Result = Result; impl ASN1Error { pub fn new(kind: ASN1ErrorKind) -> Self { ASN1Error { kind, } } pub fn kind(&self) -> ASN1ErrorKind { self.kind } } impl Display for ASN1Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "{:?}", self)?; return Ok(()); } } #[cfg(feature = "std")] impl Error for ASN1Error { fn description(&self) -> &str { match self.kind { ASN1ErrorKind::Eof => "End of file", ASN1ErrorKind::Extra => "Extra data in file", ASN1ErrorKind::IntegerOverflow => "Integer overflow", ASN1ErrorKind::StackOverflow => "Stack overflow", ASN1ErrorKind::Invalid => "Invalid data", } } } #[cfg(feature = "std")] impl From for io::Error { fn from(e: ASN1Error) -> Self { return io::Error::new(io::ErrorKind::InvalidData, e); } } yasna-0.5.2/src/reader/mod.rs000064400000000000000000001700041046102023000141230ustar 00000000000000// Copyright 2016 Masaki Hara // Copyright 2017,2019 Fortanix, Inc. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(missing_docs)] use alloc::vec::Vec; use alloc::string::String; use alloc::borrow::ToOwned; mod error; #[cfg(feature = "num-bigint")] use num_bigint::{BigInt,BigUint,Sign}; #[cfg(feature = "bit-vec")] use bit_vec::BitVec; use super::{PCBit,Tag,TAG_CLASSES}; use super::tags::{TAG_EOC,TAG_BOOLEAN,TAG_INTEGER,TAG_OCTETSTRING}; use super::tags::{TAG_NULL,TAG_OID,TAG_UTF8STRING,TAG_SEQUENCE,TAG_SET,TAG_ENUM}; use super::tags::{TAG_NUMERICSTRING,TAG_PRINTABLESTRING,TAG_VISIBLESTRING,TAG_IA5STRING,TAG_BMPSTRING}; use super::models::{ObjectIdentifier,TaggedDerValue}; #[cfg(feature = "time")] use super::models::{UTCTime,GeneralizedTime}; pub use self::error::*; /// Parses DER/BER-encoded data. /// /// [`parse_ber`] and [`parse_der`] are shorthands /// for this function. pub fn parse_ber_general<'a, T, F>(buf: &'a [u8], mode: BERMode, callback: F) -> ASN1Result where F: for<'b> FnOnce(BERReader<'a, 'b>) -> ASN1Result { let mut reader_impl = BERReaderImpl::new(buf, mode); let result; { result = callback(BERReader::new(&mut reader_impl))?; } reader_impl.end_of_buf()?; return Ok(result); } /// Parses BER-encoded data. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReader`], from which the ASN.1 value is read. /// /// If you want to accept only DER-encoded data, use [`parse_der`]. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 128, 2, 1, 10, 1, 1, 255, 0, 0]; /// let asn = yasna::parse_ber(data, |reader| { /// reader.read_sequence(|reader| { /// let i = reader.next().read_i64()?; /// let b = reader.next().read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// println!("{:?} = [48, 128, 2, 1, 10, 1, 1, 255, 0, 0]", asn); /// ``` pub fn parse_ber<'a, T, F>(buf: &'a [u8], callback: F) -> ASN1Result where F: for<'b> FnOnce(BERReader<'a, 'b>) -> ASN1Result { parse_ber_general(buf, BERMode::Ber, callback) } /// Parses DER-encoded data. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReader`], from which the ASN.1 value is read. /// /// If you want to parse BER-encoded data in general, /// use [`parse_ber`]. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 6, 2, 1, 10, 1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_sequence(|reader| { /// let i = reader.next().read_i64()?; /// let b = reader.next().read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// println!("{:?} = [48, 6, 2, 1, 10, 1, 1, 255]", asn); /// ``` pub fn parse_der<'a, T, F>(buf: &'a [u8], callback: F) -> ASN1Result where F: for<'b> FnOnce(BERReader<'a, 'b>) -> ASN1Result { parse_ber_general(buf, BERMode::Der, callback) } /// Used by [`BERReader`] to determine whether or not to enforce /// DER restrictions when parsing. #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum BERMode { /// Use BER (Basic Encoding Rules). Ber, /// Use DER (Distinguished Encoding Rules). Der, } #[derive(Debug)] struct BERReaderImpl<'a> { buf: &'a [u8], pos: usize, mode: BERMode, depth: usize, } const PC_BITS : [PCBit; 2] = [PCBit::Primitive, PCBit::Constructed]; #[derive(Debug)] enum Contents<'a, 'b> where 'a: 'b { Primitive(&'a [u8]), Constructed(&'b mut BERReaderImpl<'a>), } const BER_READER_STACK_DEPTH : usize = 100; impl<'a> BERReaderImpl<'a> { fn new(buf: &'a [u8], mode: BERMode) -> Self { return BERReaderImpl { buf, pos: 0, mode, depth: 0, }; } fn with_pos(buf: &'a [u8], pos: usize, mode: BERMode) -> Self { return BERReaderImpl { buf, pos, mode, depth: 0, }; } fn read_u8(&mut self) -> ASN1Result { if self.pos < self.buf.len() { let ret = self.buf[self.pos]; self.pos += 1; return Ok(ret); } else { return Err(ASN1Error::new(ASN1ErrorKind::Eof)); } } fn end_of_buf(&mut self) -> ASN1Result<()> { if self.pos != self.buf.len() { return Err(ASN1Error::new(ASN1ErrorKind::Extra)); } return Ok(()); } fn end_of_contents(&mut self) -> ASN1Result<()> { let (tag, pcbit) = self.read_identifier()?; if tag != TAG_EOC || pcbit != PCBit::Primitive { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } let b = self.read_u8()?; if b != 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(()); } fn read_identifier(&mut self) -> ASN1Result<(Tag, PCBit)> { let tagbyte = self.read_u8()?; let tag_class = TAG_CLASSES[(tagbyte >> 6) as usize]; let pcbit = PC_BITS[((tagbyte >> 5) & 1) as usize]; let mut tag_number = (tagbyte & 31) as u64; if tag_number == 31 { tag_number = 0; loop { let b = self.read_u8()? as u64; let x = tag_number.checked_mul(128).ok_or( ASN1Error::new(ASN1ErrorKind::IntegerOverflow))?; tag_number = x + (b & 127); if (b & 128) == 0 { break; } } if tag_number < 31 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } let tag = Tag { tag_class, tag_number, }; return Ok((tag, pcbit)); } fn lookahead_tag(&self) -> ASN1Result { let mut pos = self.pos; let mut read_u8 = || { if pos < self.buf.len() { let ret = self.buf[pos]; pos += 1; return Ok(ret); } else { return Err(ASN1Error::new(ASN1ErrorKind::Eof)); } }; let tagbyte = read_u8()?; let tag_class = TAG_CLASSES[(tagbyte >> 6) as usize]; let mut tag_number = (tagbyte & 31) as u64; if tag_number == 31 { tag_number = 0; loop { let b = read_u8()? as u64; let x = tag_number.checked_mul(128).ok_or( ASN1Error::new(ASN1ErrorKind::IntegerOverflow))?; tag_number = x + (b & 127); if (b & 128) == 0 { break; } } if tag_number < 31 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } let tag = Tag { tag_class, tag_number, }; return Ok(tag); } fn read_length(&mut self) -> ASN1Result> { let lbyte = self.read_u8()? as usize; if lbyte == 128 { return Ok(None); } if lbyte == 255 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } if (lbyte & 128) == 0 { return Ok(Some(lbyte)); } let mut length : usize = 0; for _ in 0..(lbyte & 127) { let x = length.checked_mul(256).ok_or( ASN1Error::new(ASN1ErrorKind::Eof))?; length = x + (self.read_u8()? as usize); } if self.mode == BERMode::Der && length < 128 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(Some(length)); } fn read_general(&mut self, tag: Tag, callback: F) -> ASN1Result where F: for<'b> FnOnce(Contents<'a, 'b>) -> ASN1Result { if self.depth > BER_READER_STACK_DEPTH { return Err(ASN1Error::new(ASN1ErrorKind::StackOverflow)); } let old_pos = self.pos; let (tag2, pcbit) = self.read_identifier()?; if tag2 != tag { self.pos = old_pos; return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } let length_spec = self.read_length()?; let old_buf = self.buf; match length_spec { Some(length) => { let limit = match self.pos.checked_add(length) { Some(l) => l, None => return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)), }; if old_buf.len() < limit { return Err(ASN1Error::new(ASN1ErrorKind::Eof)); } self.buf = &old_buf[..limit]; }, None => { if pcbit != PCBit::Constructed { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } if self.mode == BERMode::Der { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } }, }; self.depth += 1; let result = callback(match pcbit { PCBit::Primitive => { let buf = &self.buf[self.pos..]; self.pos = self.buf.len(); Contents::Primitive(&buf) }, PCBit::Constructed => Contents::Constructed(self), })?; self.depth -= 1; match length_spec { Some(_) => { self.end_of_buf()?; }, None => { self.end_of_contents()?; }, }; self.buf = old_buf; return Ok(result); } fn skip_general(&mut self) -> ASN1Result<(Tag, PCBit, usize)> { let mut skip_depth = 0; let mut skip_tag = None; let mut data_pos = None; while skip_depth > 0 || skip_tag == None { let old_pos = self.pos; let (tag, pcbit) = self.read_identifier()?; if tag == TAG_EOC { if skip_depth == 0 { self.pos = old_pos; return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } skip_depth -= 1; // EOC is a pair of zero bytes, consume the second. if self.read_u8()? != 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } continue; } if skip_depth == 0 { skip_tag = Some((tag, pcbit)); } if let Some(length) = self.read_length()? { if skip_depth == 0 { data_pos = Some(self.pos); } let limit = self.pos+length; if self.buf.len() < limit { return Err(ASN1Error::new(ASN1ErrorKind::Eof)); } self.pos = limit; } else { if skip_depth == 0 { data_pos = Some(self.pos); } if pcbit != PCBit::Constructed || self.mode == BERMode::Der { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } skip_depth += 1; } } return Ok((skip_tag.unwrap().0, skip_tag.unwrap().1, data_pos.unwrap())); } fn read_with_buffer<'b, T, F>(&'b mut self, callback: F) -> ASN1Result<(T, &'a [u8])> where F: FnOnce(&mut Self) -> ASN1Result { let old_pos = self.pos; let result = callback(self)?; let new_pos = self.pos; let buf = &self.buf[old_pos..new_pos]; return Ok((result, buf)); } fn read_optional(&mut self, callback: F) -> ASN1Result> where F: FnOnce(&mut Self) -> ASN1Result { let old_pos = self.pos; match callback(self) { Ok(result) => Ok(Some(result)), Err(e) => if old_pos == self.pos { Ok(None) } else { Err(e) }, } } } /// A reader object for BER/DER-encoded ASN.1 data. /// /// The two main sources of `BERReaderSeq` are: /// /// - The [`parse_ber`]/[`parse_der`] function, /// the starting point of DER serialization. /// - The [`next`](BERReaderSeq::next) method of [`BERReaderSeq`]. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[2, 1, 10]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_i64() /// }).unwrap(); /// assert_eq!(asn, 10); /// ``` #[derive(Debug)] pub struct BERReader<'a, 'b> where 'a: 'b { inner: &'b mut BERReaderImpl<'a>, implicit_tag: Option, } impl<'a, 'b> BERReader<'a, 'b> { fn new(inner: &'b mut BERReaderImpl<'a>) -> Self { BERReader { inner, implicit_tag: None, } } fn read_general(self, tag: Tag, callback: F) -> ASN1Result where F: for<'c> FnOnce(Contents<'a, 'c>) -> ASN1Result { let tag = self.implicit_tag.unwrap_or(tag); self.inner.read_general(tag, callback) } /// Tells which format we are parsing, BER or DER. pub fn mode(&self) -> BERMode { self.inner.mode } /// Reads an ASN.1 BOOLEAN value as `bool`. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_bool() /// }).unwrap(); /// assert_eq!(asn, true); /// ``` pub fn read_bool(self) -> ASN1Result { let mode = self.mode(); self.read_general(TAG_BOOLEAN, |contents| { let buf = match contents { Contents::Primitive(buf) => buf, Contents::Constructed(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, }; if buf.len() != 1 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } let b = buf[0]; if mode == BERMode::Der && b != 0 && b != 255 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(b != 0); }) } fn read_integer(self, tag: Tag) -> ASN1Result { self.read_general(tag, |contents| { let buf = match contents { Contents::Primitive(buf) => buf, Contents::Constructed(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, }; if buf.len() == 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } else if buf.len() == 1 { return Ok(buf[0] as i8 as i64); } let mut x = ((buf[0] as i8 as i64) << 8) + (buf[1] as i64); if -128 <= x && x < 128 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } if buf.len() > 8 { return Err(ASN1Error::new( ASN1ErrorKind::IntegerOverflow)); } for &b in buf[2..].iter() { x = (x << 8) | (b as i64); } return Ok(x); }) } /// Reads an ASN.1 ENUMERATED value as `i64`. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[10, 1, 13]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_enum() /// }).unwrap(); /// assert_eq!(asn, 13); /// ``` /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_enum(self) -> ASN1Result { self.read_integer(TAG_ENUM) } /// Reads an ASN.1 INTEGER value as `i64`. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[2, 4, 73, 150, 2, 210]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_i64() /// }).unwrap(); /// assert_eq!(asn, 1234567890); /// ``` /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_i64(self) -> ASN1Result { self.read_integer(TAG_INTEGER) } /// Reads an ASN.1 INTEGER value as `u64`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_u64(self) -> ASN1Result { self.read_general(TAG_INTEGER, |contents| { let buf = match contents { Contents::Primitive(buf) => buf, Contents::Constructed(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, }; if buf.len() == 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } else if buf[0] >= 128 { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } else if buf.len() == 1 { return Ok(buf[0] as u64); } let mut x = ((buf[0] as u64) << 8) + (buf[1] as u64); if x < 128 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } if buf.len() > 9 || (buf.len() == 9 && buf[0] != 0) { return Err(ASN1Error::new( ASN1ErrorKind::IntegerOverflow)); } for &b in buf[2..].iter() { x = (x << 8) | (b as u64); } return Ok(x); }) } /// Reads an ASN.1 INTEGER value as `i32`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_i32(self) -> ASN1Result { let val = self.read_i64()?; if -(1 << 31) <= val && val < (1 << 31) { return Ok(val as i32); } else { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } } /// Reads an ASN.1 INTEGER value as `u32`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_u32(self) -> ASN1Result { let val = self.read_u64()?; if val < (1 << 32) { return Ok(val as u32); } else { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } } /// Reads an ASN.1 INTEGER value as `i16`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_i16(self) -> ASN1Result { let val = self.read_i64()?; if -(1 << 15) <= val && val < (1 << 15) { return Ok(val as i16); } else { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } } /// Reads an ASN.1 INTEGER value as `u16`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_u16(self) -> ASN1Result { let val = self.read_u64()?; if val < (1 << 16) { return Ok(val as u16); } else { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } } /// Reads an ASN.1 INTEGER value as `i8`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_i8(self) -> ASN1Result { let val = self.read_i64()?; if -(1 << 7) <= val && val < (1 << 7) { return Ok(val as i8); } else { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } } /// Reads an ASN.1 INTEGER value as `u8`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. pub fn read_u8(self) -> ASN1Result { let val = self.read_u64()?; if val < (1 << 8) { return Ok(val as u8); } else { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } } #[cfg(feature = "num-bigint")] /// Reads an ASN.1 INTEGER value as `BigInt`. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// use num_bigint::BigInt; /// let data = &[2, 4, 73, 150, 2, 210]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_bigint() /// }).unwrap(); /// assert_eq!(&asn, &BigInt::parse_bytes(b"1234567890", 10).unwrap()); /// # } /// ``` /// /// # Features /// /// This method is enabled by `num` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["num"] } /// ``` pub fn read_bigint(self) -> ASN1Result { let (mut bytes, non_negative) = self.read_bigint_bytes()?; let sign = if non_negative { Sign::Plus } else { let mut carry: usize = 1; for b in bytes.iter_mut().rev() { let bval = 255 - (*b as usize); *b = (bval + carry) as u8; carry = (bval + carry) >> 8; } Sign::Minus }; Ok(BigInt::from_bytes_be(sign, &bytes)) } /// Reads an ASN.1 INTEGER value as `Vec` and a sign bit. /// /// The number given is in big endian byte ordering, and in two's /// complement. /// /// The sign bit is `true` if the number is positive, /// and false if it is negative. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// let data = &[2, 4, 73, 150, 2, 210]; /// let (bytes, nonnegative) = yasna::parse_der(data, |reader| { /// reader.read_bigint_bytes() /// }).unwrap(); /// assert_eq!(&bytes, &[73, 150, 2, 210]); /// assert_eq!(nonnegative, true); /// # } /// ``` pub fn read_bigint_bytes(self) -> ASN1Result<(Vec, bool)> { self.read_general(TAG_INTEGER, |contents| { let buf = match contents { Contents::Primitive(buf) => buf, Contents::Constructed(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, }; if buf.len() == 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } else if buf.len() == 1 { return Ok((buf.to_vec(), buf[0] & 128 == 0)); } let x2 = ((buf[0] as i8 as i32) << 8) + (buf[1] as i32); if -128 <= x2 && x2 < 128 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } let sign = 0 <= x2; Ok((buf.to_vec(), sign)) }) } #[cfg(feature = "num-bigint")] /// Reads an ASN.1 INTEGER value as `BigUint`. /// /// # Errors /// /// Except parse errors, it can raise integer overflow errors. /// /// # Features /// /// This method is enabled by `num` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["num"] } /// ``` pub fn read_biguint(self) -> ASN1Result { self.read_general(TAG_INTEGER, |contents| { let buf = match contents { Contents::Primitive(buf) => buf, Contents::Constructed(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, }; if buf.len() == 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } else if buf[0] >= 128 { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } else if buf.len() == 1 { return Ok(BigUint::from(buf[0])); } let x2 = ((buf[0] as i8 as i32) << 8) + (buf[1] as i32); if -128 <= x2 && x2 < 128 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } else if x2 < 0 { return Err(ASN1Error::new(ASN1ErrorKind::IntegerOverflow)); } return Ok(BigUint::from_bytes_be(buf)); }) } fn read_bitvec_impl(self, unused_bits: &mut usize, bytes: &mut Vec) -> ASN1Result<()> { use super::tags::TAG_BITSTRING; if *unused_bits != 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } let mode = self.inner.mode; self.read_general(TAG_BITSTRING, |contents| { match contents { Contents::Primitive(buf) => { if buf.len() == 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } if buf[0] >= 8 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } if buf[0] > 0 { if buf.len() == 1 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } if mode == BERMode::Der && (buf[buf.len()-1] & ((1< { if mode == BERMode::Der { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } loop { let result = inner.read_optional(|inner| { BERReader::new(inner) .read_bitvec_impl(unused_bits, bytes) })?; match result { Some(()) => {}, None => { break; }, } } return Ok(()); }, }; }) } #[cfg(feature = "bit-vec")] /// Reads an ASN.1 BITSTRING value as `BitVec`. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// use bit_vec::BitVec; /// let data = &[3, 5, 3, 206, 213, 116, 24]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_bitvec() /// }).unwrap(); /// assert_eq!( /// asn.into_iter().map(|b| b as usize).collect::>(), /// vec![1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, /// 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1]); /// # } /// ``` /// /// # Features /// /// This method is enabled by `bit-vec` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["bit-vec"] } /// ``` pub fn read_bitvec(self) -> ASN1Result { let (bytes, len) = self.read_bitvec_bytes()?; let mut ret = BitVec::from_bytes(&bytes); ret.truncate(len); return Ok(ret); } /// Reads an ASN.1 BITSTRING value as `(Vec, usize)`. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// let data = &[3, 4, 6, 117, 13, 64]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_bitvec_bytes() /// }).unwrap(); /// assert_eq!(asn, (vec![117, 13, 64], 18)); /// # } /// ``` /// /// # Features /// /// This method is enabled by `bit-vec` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["bit-vec"] } /// ``` pub fn read_bitvec_bytes(self) -> ASN1Result<(Vec, usize)> { let mut unused_bits = 0; let mut bytes = Vec::new(); self.read_bitvec_impl(&mut unused_bits, &mut bytes)?; let len = bytes.len() * 8 - unused_bits; return Ok((bytes, len)); } fn read_bytes_impl(self, vec: &mut Vec) -> ASN1Result<()> { self.read_general(TAG_OCTETSTRING, |contents| { match contents { Contents::Primitive(buf) => { vec.extend(buf); return Ok(()); }, Contents::Constructed(inner) => { if inner.mode == BERMode::Der { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } loop { let result = inner.read_optional(|inner| { BERReader::new(inner).read_bytes_impl(vec) })?; match result { Some(()) => {}, None => { break; }, } } return Ok(()); }, }; }) } /// Reads an ASN.1 OCTETSTRING value as `Vec`. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[36, 128, 4, 2, 72, 101, 4, 4, 108, 108, 111, 33, 0, 0]; /// let asn = yasna::parse_ber(data, |reader| { /// reader.read_bytes() /// }).unwrap(); /// assert_eq!(&asn, b"Hello!"); /// ``` pub fn read_bytes(self) -> ASN1Result> { let mut ret = Vec::new(); self.read_bytes_impl(&mut ret)?; return Ok(ret); } /// Reads the ASN.1 NULL value. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[5, 0]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_null() /// }).unwrap(); /// assert_eq!(asn, ()); /// ``` pub fn read_null(self) -> ASN1Result<()> { self.read_general(TAG_NULL, |contents| { let buf = match contents { Contents::Primitive(buf) => buf, Contents::Constructed(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, }; if buf.len() != 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(()); }) } /// Reads an ASN.1 object identifier. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[6, 8, 42, 134, 72, 134, 247, 13, 1, 1]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_oid() /// }).unwrap(); /// assert_eq!(&*asn.components(), &[1, 2, 840, 113549, 1, 1]); /// ``` pub fn read_oid(self) -> ASN1Result { self.read_general(TAG_OID, |contents| { let buf = match contents { Contents::Primitive(buf) => buf, Contents::Constructed(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, }; let mut components = Vec::new(); if buf.len() == 0 || buf[buf.len()-1] >= 128 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } let mut subid : u64 = 0; for &b in buf.iter() { if b == 128 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } subid = subid.checked_mul(128) .ok_or(ASN1Error::new( ASN1ErrorKind::IntegerOverflow))? + ((b & 127) as u64); if (b & 128) == 0 { if components.len() == 0 { let id0 = if subid < 40 { 0 } else if subid < 80 { 1 } else { 2 }; let id1 = subid - 40 * id0; components.push(id0); components.push(id1); } else { components.push(subid); } subid = 0; } } return Ok(ObjectIdentifier::new(components)); }) } /// Reads an ASN.1 UTF8String. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[ /// 12, 29, 103, 110, 97, 119, 32, 207, 129, 206, 191, 206, /// 186, 206, 177, 206, 189, 206, 175, 206, 182, 207, /// 137, 32, 240, 170, 152, 130, 227, 130, 139]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_utf8string() /// }).unwrap(); /// assert_eq!(&asn, "gnaw ροκανίζω 𪘂る"); /// ``` pub fn read_utf8string(self) -> ASN1Result { self.read_tagged_implicit(TAG_UTF8STRING, |reader| { let bytes = reader.read_bytes()?; match String::from_utf8(bytes) { Ok(string) => Ok(string), Err(_) => Err(ASN1Error::new(ASN1ErrorKind::Invalid)), } }) } /// Reads an ASN.1 SEQUENCE value. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReaderSeq`], from which the contents of the /// SEQUENCE is read. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 6, 2, 1, 10, 1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_sequence(|reader| { /// let i = reader.next().read_i64()?; /// let b = reader.next().read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (10, true)); /// ``` pub fn read_sequence(self, callback: F) -> ASN1Result where F: for<'c> FnOnce( &mut BERReaderSeq<'a, 'c>) -> ASN1Result { self.read_general(TAG_SEQUENCE, |contents| { let inner = match contents { Contents::Primitive(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, Contents::Constructed(inner) => inner, }; return callback(&mut BERReaderSeq { inner, }); }) } /// Reads an ASN.1 SEQUENCE OF value. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReader`], from which the contents of the /// SEQUENCE OF is read. /// /// This function doesn't return values. Instead, use mutable values to /// maintain read values. `collect_set_of` can be an alternative. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 7, 2, 1, 10, 2, 2, 255, 127]; /// let asn = yasna::parse_der(data, |reader| { /// let mut numbers = Vec::new(); /// reader.read_sequence_of(|reader| { /// numbers.push(reader.read_i64()?); /// return Ok(()); /// })?; /// return Ok(numbers); /// }).unwrap(); /// assert_eq!(&asn, &[10, -129]); /// ``` pub fn read_sequence_of(self, mut callback: F) -> ASN1Result<()> where F: for<'c> FnMut(BERReader<'a, 'c>) -> ASN1Result<()> { self.read_sequence(|reader| { loop { if let None = reader.read_optional(|reader| { callback(reader) })? { break; } } return Ok(()); }) } /// Collects an ASN.1 SEQUENCE OF value. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReader`], from which the contents of the /// SEQUENCE OF is read. /// /// If you don't like `Vec`, you can use `read_sequence_of` instead. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 7, 2, 1, 10, 2, 2, 255, 127]; /// let asn = yasna::parse_der(data, |reader| { /// reader.collect_sequence_of(|reader| { /// reader.read_i64() /// }) /// }).unwrap(); /// assert_eq!(&asn, &[10, -129]); /// ``` pub fn collect_sequence_of(self, mut callback: F) -> ASN1Result> where F: for<'c> FnMut(BERReader<'a, 'c>) -> ASN1Result { let mut collection = Vec::new(); self.read_sequence_of(|reader| { collection.push(callback(reader)?); return Ok(()); })?; return Ok(collection); } /// Reads an ASN.1 SET value. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReaderSet`], from which the contents of the /// SET are read. /// /// For SET OF values, use `read_set_of` instead. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::tags::{TAG_INTEGER,TAG_BOOLEAN}; /// let data = &[49, 6, 1, 1, 255, 2, 1, 10]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_set(|reader| { /// let i = reader.next(&[TAG_INTEGER])?.read_i64()?; /// let b = reader.next(&[TAG_BOOLEAN])?.read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (10, true)); /// ``` pub fn read_set(self, callback: F) -> ASN1Result where F: for<'c> FnOnce( &mut BERReaderSet<'a, 'c>) -> ASN1Result { self.read_general(TAG_SET, |contents| { let inner = match contents { Contents::Primitive(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, Contents::Constructed(inner) => inner, }; let mut elements = Vec::new(); loop { let old_pos = inner.pos; if let Some(tag) = inner.read_optional(|inner| { inner.skip_general().map(|t| t.0) })? { let new_pos = inner.pos; // TODO: this should store the P/C bit as well elements.push((tag, &inner.buf[..new_pos], old_pos)); } else { break; } } if inner.mode == BERMode::Der { for i in 1..elements.len() { if elements[i] <= elements[i-1] { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } } let mut new_impl = BERReaderImpl::new(&[], inner.mode); let result = callback(&mut BERReaderSet { impl_ref: &mut new_impl, elements: &mut elements, })?; if elements.len() > 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(result); }) } /// Reads an ASN.1 SET OF value. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReader`], from which the contents of the /// SET OF are read. /// /// This function doesn't return values. Instead, use mutable values to /// maintain read values. `collect_set_of` can be an alternative. /// /// This function doesn't sort the elements. In DER, it is assumed that /// the elements occur in an order determined by DER encodings of them. /// /// For SET values, use `read_set` instead. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[49, 7, 2, 1, 10, 2, 2, 255, 127]; /// let asn = yasna::parse_der(data, |reader| { /// let mut numbers = Vec::new(); /// reader.read_set_of(|reader| { /// numbers.push(reader.read_i64()?); /// return Ok(()); /// })?; /// return Ok(numbers); /// }).unwrap(); /// assert_eq!(asn, vec![10, -129]); /// ``` pub fn read_set_of(self, mut callback: F) -> ASN1Result<()> where F: for<'c> FnMut(BERReader<'a, 'c>) -> ASN1Result<()> { self.read_general(TAG_SET, |contents| { let inner = match contents { Contents::Primitive(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, Contents::Constructed(inner) => inner, }; let mut last_buf = None; while let Some((_, buf)) = inner.read_optional(|inner| { inner.read_with_buffer(|inner| { callback(BERReader::new(inner)) }) })? { if let Some(last_buf) = last_buf { if inner.mode == BERMode::Der && buf < last_buf { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } last_buf = Some(buf); } return Ok(()); }) } /// Collects an ASN.1 SET OF value. /// /// This function uses the loan pattern: `callback` is called back with /// a [`BERReader`], from which the contents of the /// SET OF is read. /// /// If you don't like `Vec`, you can use `read_set_of` instead. /// /// This function doesn't sort the elements. In DER, it is assumed that /// the elements occur in an order determined by DER encodings of them. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[49, 7, 2, 1, 10, 2, 2, 255, 127]; /// let asn = yasna::parse_der(data, |reader| { /// reader.collect_set_of(|reader| { /// reader.read_i64() /// }) /// }).unwrap(); /// assert_eq!(asn, vec![10, -129]); /// ``` pub fn collect_set_of(self, mut callback: F) -> ASN1Result> where F: for<'c> FnMut(BERReader<'a, 'c>) -> ASN1Result { let mut collection = Vec::new(); self.read_set_of(|reader| { collection.push(callback(reader)?); return Ok(()); })?; return Ok(collection); } /// Reads an ASN.1 NumericString. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[18, 7, 49, 50, 56, 32, 50, 53, 54]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_numeric_string() /// }).unwrap(); /// assert_eq!(&asn, "128 256"); /// ``` pub fn read_numeric_string(self) -> ASN1Result { self.read_tagged_implicit(TAG_NUMERICSTRING, |reader| { let bytes = reader.read_bytes()?; for &byte in bytes.iter() { if !(byte == b' ' || (b'0' <= byte && byte <= b'9')) { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } return Ok(String::from_utf8(bytes).unwrap()); }) } /// Reads an ASN.1 PrintableString. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[19, 9, 67, 111, 46, 44, 32, 76, 116, 100, 46]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_printable_string() /// }).unwrap(); /// assert_eq!(&asn, "Co., Ltd."); /// ``` pub fn read_printable_string(self) -> ASN1Result { self.read_tagged_implicit(TAG_PRINTABLESTRING, |reader| { let bytes = reader.read_bytes()?; for &byte in bytes.iter() { if !( byte == b' ' || (b'\'' <= byte && byte <= b':' && byte != b'*') || byte == b'=' || (b'A' <= byte && byte <= b'Z') || (b'a' <= byte && byte <= b'z')) { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } return Ok(String::from_utf8(bytes).unwrap()); }) } /// Reads an ASN.1 IA5String. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[22, 9, 0x41, 0x53, 0x43, 0x49, 0x49, 0x20, 0x70, 0x6C, 0x7A]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_ia5_string() /// }).unwrap(); /// assert_eq!(&asn, "ASCII plz"); /// ``` pub fn read_ia5_string(self) -> ASN1Result { self.read_tagged_implicit(TAG_IA5STRING, |reader| { let bytes = reader.read_bytes()?; match String::from_utf8(bytes) { Ok(string) => { if !string.is_ascii() { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } Ok(string) } Err(_) => Err(ASN1Error::new(ASN1ErrorKind::Invalid)) } }) } /// Reads an ASN.1 BMPString. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[30, 14, 0x00, 0xA3, 0x03, 0xC0, 0x00, 0x20, 0x00, 0x71, 0x00, 0x75, 0x00, 0x75, 0x00, 0x78]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_bmp_string() /// }).unwrap(); /// assert_eq!(&asn, "£π quux"); /// ``` pub fn read_bmp_string(self) -> ASN1Result { self.read_tagged_implicit(TAG_BMPSTRING, |reader| { let bytes = reader.read_bytes()?; if bytes.len() % 2 != 0 { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } let utf16 : Vec = bytes.chunks(2).map(|c| (c[0] as u16) * 256 + c[1] as u16).collect(); Ok(String::from_utf16_lossy(&utf16)) }) } #[cfg(feature = "time")] /// Reads an ASN.1 UTCTime. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[ /// 23, 15, 56, 50, 48, 49, 48, 50, 48, /// 55, 48, 48, 45, 48, 53, 48, 48]; /// let asn = yasna::parse_ber(data, |reader| { /// reader.read_utctime() /// }).unwrap(); /// assert_eq!(asn.datetime().unix_timestamp(), 378820800); /// ``` /// /// # Features /// /// This method is enabled by `time` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["time"] } /// ``` pub fn read_utctime(self) -> ASN1Result { use super::tags::TAG_UTCTIME; let mode = self.inner.mode; self.read_tagged_implicit(TAG_UTCTIME, |reader| { let bytes = reader.read_bytes()?; let datetime = UTCTime::parse(&bytes).ok_or_else( || ASN1Error::new(ASN1ErrorKind::Invalid))?; if mode == BERMode::Der && &datetime.to_bytes() != &bytes { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(datetime); }) } #[cfg(feature = "time")] /// Reads an ASN.1 GeneralizedTime. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[ /// 24, 17, 49, 57, 56, 53, 49, 49, 48, 54, /// 50, 49, 46, 49, 52, 49, 53, 57, 90]; /// let asn = yasna::parse_ber(data, |reader| { /// reader.read_generalized_time() /// }).unwrap(); /// assert_eq!(asn.datetime().unix_timestamp(), 500159309); /// ``` /// /// # Features /// /// This method is enabled by `time` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["time"] } /// ``` pub fn read_generalized_time(self) -> ASN1Result { use super::tags::TAG_GENERALIZEDTIME; let mode = self.inner.mode; self.read_tagged_implicit(TAG_GENERALIZEDTIME, |reader| { let bytes = reader.read_bytes()?; let datetime = GeneralizedTime::parse(&bytes).ok_or_else( || ASN1Error::new(ASN1ErrorKind::Invalid))?; if mode == BERMode::Der && &datetime.to_bytes() != &bytes { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(datetime); }) } /// Reads an ASN.1 VisibleString. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[26, 3, 72, 105, 33]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_visible_string() /// }).unwrap(); /// assert_eq!(&asn, "Hi!"); /// ``` pub fn read_visible_string(self) -> ASN1Result { self.read_tagged_implicit(TAG_VISIBLESTRING, |reader| { let bytes = reader.read_bytes()?; for &byte in bytes.iter() { if !(b' ' <= byte && byte <= b'~') { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } return Ok(String::from_utf8(bytes).unwrap()); }) } /// Reads a (explicitly) tagged value. /// /// # Examples /// /// ``` /// use yasna::{self,Tag}; /// let data = &[163, 3, 2, 1, 10]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_tagged(Tag::context(3), |reader| { /// reader.read_i64() /// }) /// }).unwrap(); /// assert_eq!(asn, 10); /// ``` pub fn read_tagged(self, tag: Tag, callback: F) -> ASN1Result where F: for<'c> FnOnce(BERReader<'a, 'c>) -> ASN1Result { self.read_general(tag, |contents| { let inner = match contents { Contents::Primitive(_) => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }, Contents::Constructed(inner) => inner, }; callback(BERReader::new(inner)) }) } /// Reads an implicitly tagged value. /// /// # Examples /// /// ``` /// use yasna::{self,Tag}; /// let data = &[131, 1, 10]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_tagged_implicit(Tag::context(3), |reader| { /// reader.read_i64() /// }) /// }).unwrap(); /// assert_eq!(asn, 10); /// ``` pub fn read_tagged_implicit(self, tag: Tag, callback: F) -> ASN1Result where F: for<'c> FnOnce(BERReader<'a, 'c>) -> ASN1Result { let tag = self.implicit_tag.unwrap_or(tag); return callback(BERReader { inner: self.inner, implicit_tag: Some(tag), }); } /// Lookaheads the tag in the next value. Used to parse CHOICE values. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::tags::*; /// let data = &[48, 5, 2, 1, 10, 5, 0]; /// let asn = yasna::parse_der(data, |reader| { /// reader.collect_sequence_of(|reader| { /// let tag = reader.lookahead_tag()?; /// let choice; /// if tag == TAG_INTEGER { /// choice = Some(reader.read_i64()?); /// } else { /// reader.read_null()?; /// choice = None; /// } /// return Ok(choice); /// }) /// }).unwrap(); /// assert_eq!(&asn, &[Some(10), None]); /// ``` pub fn lookahead_tag(&self) -> ASN1Result { self.inner.lookahead_tag() } pub fn read_with_buffer(self, callback: F) -> ASN1Result<(T, &'a [u8])> where F: for<'c> FnOnce(BERReader<'a, 'c>) -> ASN1Result { let implicit_tag = self.implicit_tag; self.inner.read_with_buffer(|inner| { callback(BERReader { inner, implicit_tag, }) }) } /// Read an arbitrary (tag, value) pair as a TaggedDerValue. /// The length is not included in the returned payload. If the /// payload has indefinite-length encoding, the EOC bytes are /// included in the returned payload. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::models::TaggedDerValue; /// use yasna::tags::TAG_OCTETSTRING; /// let data = b"\x04\x06Hello!"; /// let res = yasna::parse_der(data, |reader| reader.read_tagged_der()).unwrap(); /// assert_eq!(res, TaggedDerValue::from_tag_and_bytes(TAG_OCTETSTRING, b"Hello!".to_vec())); /// ``` pub fn read_tagged_der(self) -> ASN1Result { let (tag, pcbit, data_pos) = self.inner.skip_general()?; Ok(TaggedDerValue::from_tag_pc_and_bytes( tag, pcbit, self.inner.buf[data_pos..self.inner.pos].to_vec())) } /// Reads a DER object as raw bytes. Tag and length are included /// in the returned buffer. For indefinite length encoding, EOC bytes /// are included in the returned buffer as well. /// /// # Examples /// /// ``` /// use yasna; /// let data = b"\x04\x06Hello!"; /// let res = yasna::parse_der(data, |reader| reader.read_der()).unwrap(); /// assert_eq!(res, data); /// ``` pub fn read_der(self) -> ASN1Result> { Ok(self.inner.read_with_buffer(|inner| { inner.skip_general() })?.1.to_owned()) } } /// A reader object for a sequence of BER/DER-encoded ASN.1 data. /// /// The main source of this object is the [`read_sequence`] method from /// [`BERReader`]. /// /// [`read_sequence`]: BERReader::read_sequence /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 6, 2, 1, 10, 1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_sequence(|reader| { /// let i = reader.next().read_i64()?; /// let b = reader.next().read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (10, true)); /// ``` #[derive(Debug)] pub struct BERReaderSeq<'a, 'b> where 'a: 'b { inner: &'b mut BERReaderImpl<'a>, } impl<'a, 'b> BERReaderSeq<'a, 'b> { /// Tells which format we are parsing, BER or DER. pub fn mode(&self) -> BERMode { self.inner.mode } /// Generates a new [`BERReader`]. pub fn next<'c>(&'c mut self) -> BERReader<'a, 'c> { BERReader::new(self.inner) } /// Tries to read an ASN.1 value. If it fails at the first tag, /// it doesn't consume buffer and returns `None`. /// /// Used to parse OPTIONAL elements. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 3, 1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_sequence(|reader| { /// let i = reader.read_optional(|reader| { /// reader.read_i64() /// })?; /// let b = reader.next().read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (None, true)); /// ``` pub fn read_optional(&mut self, callback: F) -> ASN1Result> where F: for<'c> FnOnce(BERReader<'a, 'c>) -> ASN1Result { self.inner.read_optional(|inner| { callback(BERReader::new(inner)) }) } /// Similar to [`read_optional`](Self::read_optional), /// but uses `default` if it fails. /// /// `T: Eq` is required because it fails in DER mode if the read value /// is equal to `default`. /// /// Used to parse DEFAULT elements. /// /// # Examples /// /// ``` /// use yasna; /// let data = &[48, 3, 1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_sequence(|reader| { /// let i = reader.read_default(10, |reader| { /// reader.read_i64() /// })?; /// let b = reader.next().read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (10, true)); /// ``` pub fn read_default(&mut self, default: T, callback: F) -> ASN1Result where F: for<'c> FnOnce(BERReader<'a, 'c>) -> ASN1Result, T: Eq { match self.read_optional(callback)? { Some(result) => { if self.inner.mode == BERMode::Der && result == default { return Err( ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(result); }, None => Ok(default), } } pub fn read_with_buffer(&mut self, callback: F) -> ASN1Result<(T, &'a [u8])> where F: for<'c> FnOnce( &mut BERReaderSeq<'a, 'c>) -> ASN1Result { self.inner.read_with_buffer(|inner| { callback(&mut BERReaderSeq { inner, }) }) } } /// A reader object for a set of BER/DER-encoded ASN.1 data. /// /// The main source of this object is the [`read_set`](BERReader::read_set) /// method from [`BERReader`]. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::tags::{TAG_INTEGER,TAG_BOOLEAN}; /// let data = &[49, 6, 1, 1, 255, 2, 1, 10]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_set(|reader| { /// let i = reader.next(&[TAG_INTEGER])?.read_i64()?; /// let b = reader.next(&[TAG_BOOLEAN])?.read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (10, true)); /// ``` #[derive(Debug)] pub struct BERReaderSet<'a, 'b> where 'a: 'b { impl_ref: &'b mut BERReaderImpl<'a>, elements: &'b mut Vec<(Tag, &'a [u8], usize)>, } impl<'a, 'b> BERReaderSet<'a, 'b> { /// Tells which format we are parsing, BER or DER. pub fn mode(&self) -> BERMode { self.impl_ref.mode } /// Generates a new [`BERReader`]. /// /// This method needs `tag_hint` to determine the position of the data. pub fn next<'c>(&'c mut self, tag_hint: &[Tag]) -> ASN1Result> { if let Some(elem_pos) = self.elements.iter().position(|&(tag,_,_)| { tag_hint.contains(&tag) }) { let (_, buf, pos) = self.elements.remove(elem_pos); *self.impl_ref = BERReaderImpl::with_pos( buf, pos, self.impl_ref.mode); return Ok(BERReader::new(self.impl_ref)) } else { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); } } /// If there is a set element with a tag in `tag_hint`, reads an ASN.1 /// value from that element and returns `Some(_)`. /// Otherwise, returns `None`. /// /// Used to parse OPTIONAL elements. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::tags::*; /// let data = &[49, 3, 1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_set(|reader| { /// let i = reader.read_optional(&[TAG_INTEGER], |reader| { /// reader.read_i64() /// })?; /// let b = reader.next(&[TAG_BOOLEAN])?.read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (None, true)); /// ``` pub fn read_optional(&mut self, tag_hint: &[Tag], callback: F) -> ASN1Result> where F: for<'c> FnOnce(BERReader<'a, 'c>) -> ASN1Result { if let Some(elem_pos) = self.elements.iter().position(|&(tag,_,_)| { tag_hint.contains(&tag) }) { let (_, buf, pos) = self.elements.remove(elem_pos); let mut reader_impl = BERReaderImpl::with_pos( buf, pos, self.impl_ref.mode); let result = callback(BERReader::new(&mut reader_impl))?; reader_impl.end_of_buf()?; return Ok(Some(result)); } else { return Ok(None); } } /// Similar to [`read_optional`](Self::read_optional), /// but uses `default` if it fails. /// /// `T: Eq` is required because it fails in DER mode if the read value /// is equal to `default`. /// /// Used to parse DEFAULT elements. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::tags::*; /// let data = &[49, 3, 1, 1, 255]; /// let asn = yasna::parse_der(data, |reader| { /// reader.read_set(|reader| { /// let i = reader.read_default(&[TAG_INTEGER], 10, |reader| { /// reader.read_i64() /// })?; /// let b = reader.next(&[TAG_BOOLEAN])?.read_bool()?; /// return Ok((i, b)); /// }) /// }).unwrap(); /// assert_eq!(asn, (10, true)); /// ``` pub fn read_default (&mut self, tag_hint: &[Tag], default: T, callback: F) -> ASN1Result where F: for<'c> FnOnce(BERReader<'a, 'c>) -> ASN1Result, T: Eq { let mode = self.impl_ref.mode; match self.read_optional(tag_hint, callback)? { Some(result) => { if mode == BERMode::Der && result == default { return Err( ASN1Error::new(ASN1ErrorKind::Invalid)); } return Ok(result); }, None => Ok(default), } } } #[cfg(test)] mod tests; yasna-0.5.2/src/reader/tests.rs000064400000000000000000001551771046102023000145240ustar 00000000000000// Copyright 2016 Masaki Hara // Copyright 2017 Fortanix, Inc. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #[cfg(feature = "num-bigint")] use num_bigint::{BigUint, BigInt}; use super::super::Tag; use super::super::tags::TAG_SEQUENCE; use super::*; #[test] fn test_der_read_bool_ok() { let tests : &[(bool, &[u8])] = &[ (false, &[1, 1, 0]), (true, &[1, 1, 255]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_bool() }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_der_read_bool_err() { let tests : &[&[u8]] = &[ &[], &[1], &[0, 0], &[0, 1, 0], &[2, 1, 0], &[33, 1, 0], &[65, 1, 0], &[1, 0], &[1, 2, 0, 0], &[1, 128, 1, 1, 0, 0, 0], &[1, 1, 1], &[1, 1, 191], &[1, 1, 254], ]; for &data in tests { parse_der(data, |reader| { reader.read_bool() }).unwrap_err(); } } #[test] fn test_ber_read_bool_ok() { let tests : &[(bool, &[u8])] = &[ (false, &[1, 1, 0]), (true, &[1, 1, 1]), (true, &[1, 1, 191]), (true, &[1, 1, 254]), (true, &[1, 1, 255]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_bool() }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_ber_read_bool_err() { let tests : &[&[u8]] = &[ &[], &[1], &[0, 0], &[0, 1, 0], &[2, 1, 0], &[33, 1, 0], &[65, 1, 0], &[1, 0], &[1, 2, 0, 0], &[1, 128, 1, 1, 0, 0, 0], ]; for &data in tests { parse_ber(data, |reader| { reader.read_bool() }).unwrap_err(); } } #[test] fn test_der_read_i64_ok() { test_general_read_i64_ok(BERMode::Der); } #[test] fn test_der_read_i64_err() { test_general_read_i64_err(BERMode::Der); } #[test] fn test_ber_read_i64_ok() { test_general_read_i64_ok(BERMode::Ber); } #[test] fn test_ber_read_i64_err() { test_general_read_i64_err(BERMode::Ber); } fn test_general_read_i64_ok(mode: BERMode) { let tests : &[(i64, &[u8])] = &[ (-9223372036854775808, &[2, 8, 128, 0, 0, 0, 0, 0, 0, 0]), (-65537, &[2, 3, 254, 255, 255]), (-65536, &[2, 3, 255, 0, 0]), (-32769, &[2, 3, 255, 127, 255]), (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_i64() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_i64_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 0], &[2, 9, 255, 127, 255, 255, 255, 255, 255, 255, 255], &[2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0], &[2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_i64() }).unwrap_err(); } } #[test] fn test_der_read_u64_ok() { test_general_read_u64_ok(BERMode::Der); } #[test] fn test_der_read_u64_err() { test_general_read_u64_err(BERMode::Der); } #[test] fn test_ber_read_u64_ok() { test_general_read_u64_ok(BERMode::Ber); } #[test] fn test_ber_read_u64_err() { test_general_read_u64_err(BERMode::Ber); } fn test_general_read_u64_ok(mode: BERMode) { let tests : &[(u64, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), (18446744073709551615, &[2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_u64() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_u64_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 8, 128, 0, 0, 0, 0, 0, 0, 0], &[2, 3, 254, 255, 255], &[2, 3, 255, 0, 0], &[2, 3, 255, 127, 255], &[2, 2, 128, 0], &[2, 2, 255, 127], &[2, 1, 128], &[2, 1, 255], &[2, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0], &[2, 9, 1, 128, 0, 0, 0, 0, 0, 0, 0], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_u64() }).unwrap_err(); } } #[test] fn test_der_read_i32_ok() { test_general_read_i32_ok(BERMode::Der); } #[test] fn test_der_read_i32_err() { test_general_read_i32_err(BERMode::Der); } #[test] fn test_ber_read_i32_ok() { test_general_read_i32_ok(BERMode::Ber); } #[test] fn test_ber_read_i32_err() { test_general_read_i32_err(BERMode::Ber); } fn test_general_read_i32_ok(mode: BERMode) { let tests : &[(i32, &[u8])] = &[ (-2147483648, &[2, 4, 128, 0, 0, 0]), (-65537, &[2, 3, 254, 255, 255]), (-65536, &[2, 3, 255, 0, 0]), (-32769, &[2, 3, 255, 127, 255]), (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (2147483647, &[2, 4, 127, 255, 255, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_i32() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_i32_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 5, 255, 0, 0, 0, 0], &[2, 5, 255, 127, 255, 255, 255], &[2, 5, 0, 128, 0, 0, 0], &[2, 5, 0, 255, 255, 255, 255], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_i32() }).unwrap_err(); } } #[test] fn test_der_read_u32_err() { test_general_read_u32_err(BERMode::Der); } #[test] fn test_ber_read_u32_ok() { test_general_read_u32_ok(BERMode::Ber); } #[test] fn test_ber_read_u32_err() { test_general_read_u32_err(BERMode::Ber); } fn test_general_read_u32_ok(mode: BERMode) { let tests : &[(u32, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (2147483647, &[2, 4, 127, 255, 255, 255]), (4294967295, &[2, 5, 0, 255, 255, 255, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_u32() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_u32_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 4, 128, 0, 0, 0], &[2, 3, 254, 255, 255], &[2, 3, 255, 0, 0], &[2, 3, 255, 127, 255], &[2, 2, 128, 0], &[2, 2, 255, 127], &[2, 1, 128], &[2, 1, 255], &[2, 5, 1, 0, 0, 0, 0], &[2, 5, 1, 128, 0, 0, 0], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_u32() }).unwrap_err(); } } #[test] fn test_der_read_i16_ok() { test_general_read_i16_ok(BERMode::Der); } #[test] fn test_der_read_i16_err() { test_general_read_i16_err(BERMode::Der); } #[test] fn test_ber_read_i16_ok() { test_general_read_i16_ok(BERMode::Ber); } #[test] fn test_ber_read_i16_err() { test_general_read_i16_err(BERMode::Ber); } fn test_general_read_i16_ok(mode: BERMode) { let tests : &[(i16, &[u8])] = &[ (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_i16() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_i16_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 3, 255, 0, 0], &[2, 3, 255, 127, 255], &[2, 3, 0, 128, 0], &[2, 3, 0, 255, 255], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_i16() }).unwrap_err(); } } #[test] fn test_der_read_u16_ok() { test_general_read_u16_ok(BERMode::Der); } #[test] fn test_der_read_u16_err() { test_general_read_u16_err(BERMode::Der); } #[test] fn test_ber_read_u16_ok() { test_general_read_u16_ok(BERMode::Ber); } #[test] fn test_ber_read_u16_err() { test_general_read_u16_err(BERMode::Ber); } fn test_general_read_u16_ok(mode: BERMode) { let tests : &[(u16, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (65535, &[2, 3, 0, 255, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_u16() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_u16_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 2, 128, 0], &[2, 2, 255, 127], &[2, 1, 128], &[2, 1, 255], &[2, 3, 1, 0, 0], &[2, 3, 1, 128, 0], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_u16() }).unwrap_err(); } } #[test] fn test_der_read_i8_ok() { test_general_read_i8_ok(BERMode::Der); } #[test] fn test_der_read_i8_err() { test_general_read_i8_err(BERMode::Der); } #[test] fn test_ber_read_i8_ok() { test_general_read_i8_ok(BERMode::Ber); } #[test] fn test_ber_read_i8_err() { test_general_read_i8_err(BERMode::Ber); } fn test_general_read_i8_ok(mode: BERMode) { let tests : &[(i8, &[u8])] = &[ (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_i8() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_i8_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 2, 255, 0], &[2, 2, 255, 127], &[2, 2, 0, 128], &[2, 2, 0, 255], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_i8() }).unwrap_err(); } } #[test] fn test_der_read_u8_ok() { test_general_read_u8_ok(BERMode::Der); } #[test] fn test_der_read_u8_err() { test_general_read_u8_err(BERMode::Der); } #[test] fn test_ber_read_u8_ok() { test_general_read_u8_ok(BERMode::Ber); } #[test] fn test_ber_read_u8_err() { test_general_read_u8_err(BERMode::Ber); } fn test_general_read_u8_ok(mode: BERMode) { let tests : &[(u8, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (255, &[2, 2, 0, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_u8() }).unwrap(); assert_eq!(value, evalue); } } fn test_general_read_u8_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 1, 128], &[2, 1, 255], &[2, 2, 1, 0], &[2, 2, 1, 128], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_u8() }).unwrap_err(); } } #[cfg(feature = "num-bigint")] #[test] fn test_der_read_bigint_ok() { test_general_read_bigint_ok(BERMode::Der); } #[cfg(feature = "num-bigint")] #[test] fn test_der_read_bigint_err() { test_general_read_bigint_err(BERMode::Der); } #[cfg(feature = "num-bigint")] #[test] fn test_ber_read_bigint_ok() { test_general_read_bigint_ok(BERMode::Ber); } #[cfg(feature = "num-bigint")] #[test] fn test_ber_read_bigint_err() { test_general_read_bigint_err(BERMode::Ber); } #[cfg(feature = "num-bigint")] fn test_general_read_bigint_ok(mode: BERMode) { use num_traits::FromPrimitive; let tests : &[(i64, &[u8])] = &[ (-9223372036854775808, &[2, 8, 128, 0, 0, 0, 0, 0, 0, 0]), (-65537, &[2, 3, 254, 255, 255]), (-65536, &[2, 3, 255, 0, 0]), (-32769, &[2, 3, 255, 127, 255]), (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_bigint() }).unwrap(); assert_eq!(value, BigInt::from_i64(evalue).unwrap()); } let tests : &[(BigInt, &[u8])] = &[ (BigInt::parse_bytes( b"1234567890123456789012345678901234567890", 10).unwrap(), &[2, 17, 3, 160, 201, 32, 117, 192, 219, 243, 184, 172, 188, 95, 150, 206, 63, 10, 210]), (BigInt::parse_bytes( b"-1234567890123456789012345678901234567890", 10).unwrap(), &[2, 17, 252, 95, 54, 223, 138, 63, 36, 12, 71, 83, 67, 160, 105, 49, 192, 245, 46]), (BigInt::parse_bytes(b"-18446744073709551616", 10).unwrap(), &[2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 0]), (BigInt::parse_bytes(b"-9223372036854775809", 10).unwrap(), &[2, 9, 255, 127, 255, 255, 255, 255, 255, 255, 255]), (BigInt::parse_bytes(b"9223372036854775808", 10).unwrap(), &[2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0]), (BigInt::parse_bytes(b"18446744073709551615", 10).unwrap(), &[2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255]), ]; for &(ref evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_bigint() }).unwrap(); assert_eq!(&value, evalue); } } #[cfg(feature = "num-bigint")] fn test_general_read_bigint_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_bigint() }).unwrap_err(); } } #[cfg(feature = "num-bigint")] #[test] fn test_der_read_biguint_ok() { test_general_read_biguint_ok(BERMode::Der); } #[cfg(feature = "num-bigint")] #[test] fn test_der_read_biguint_err() { test_general_read_biguint_err(BERMode::Der); } #[cfg(feature = "num-bigint")] #[test] fn test_ber_read_biguint_ok() { test_general_read_biguint_ok(BERMode::Ber); } #[cfg(feature = "num-bigint")] #[test] fn test_ber_read_biguint_err() { test_general_read_biguint_err(BERMode::Ber); } #[cfg(feature = "num-bigint")] fn test_general_read_biguint_ok(mode: BERMode) { use num_traits::FromPrimitive; let tests : &[(u64, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), (18446744073709551615, &[2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255]), ]; for &(evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_biguint() }).unwrap(); assert_eq!(value, BigUint::from_u64(evalue).unwrap()); } let tests : &[(BigUint, &[u8])] = &[ (BigUint::parse_bytes( b"1234567890123456789012345678901234567890", 10).unwrap(), &[2, 17, 3, 160, 201, 32, 117, 192, 219, 243, 184, 172, 188, 95, 150, 206, 63, 10, 210]), (BigUint::parse_bytes(b"9223372036854775808", 10).unwrap(), &[2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0]), (BigUint::parse_bytes(b"18446744073709551615", 10).unwrap(), &[2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255]), ]; for &(ref evalue, data) in tests { let value = parse_ber_general(data, mode, |reader| { reader.read_biguint() }).unwrap(); assert_eq!(&value, evalue); } } #[cfg(feature = "num-bigint")] fn test_general_read_biguint_err(mode: BERMode) { let tests : &[&[u8]] = &[ &[], &[2], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[34, 1, 0], &[66, 1, 0], &[2, 0], &[2, 128, 2, 1, 0, 0, 0], &[2, 2, 0], &[2, 1, 1, 1], &[2, 2, 255, 128], &[2, 2, 255, 200], &[2, 2, 0, 127], &[2, 2, 0, 56], &[2, 3, 255, 151, 55], &[2, 3, 0, 1, 2], &[2, 8, 128, 0, 0, 0, 0, 0, 0, 0], &[2, 3, 254, 255, 255], &[2, 3, 255, 0, 0], &[2, 3, 255, 127, 255], &[2, 2, 128, 0], &[2, 2, 255, 127], &[2, 1, 128], &[2, 1, 255], &[2, 17, 252, 95, 54, 223, 138, 63, 36, 12, 71, 83, 67, 160, 105, 49, 192, 245, 46], &[2, 9, 255, 0, 0, 0, 0, 0, 0, 0, 0], &[2, 9, 255, 127, 255, 255, 255, 255, 255, 255, 255], ]; for &data in tests { parse_ber_general(data, mode, |reader| { reader.read_biguint() }).unwrap_err(); } } #[test] fn test_der_read_bytes_ok() { let tests : &[(&[u8], &[u8])] = &[ (&[1, 0, 100, 255], &[4, 4, 1, 0, 100, 255]), (&[], &[4, 0]), (&[4, 4, 4, 4], &[4, 4, 4, 4, 4, 4]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_bytes() }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_der_read_bytes_err() { let tests : &[&[u8]] = &[ &[], &[4], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[36, 1, 0], &[68, 1, 0], &[4, 4, 0], &[4, 1, 1, 1], &[36, 128, 1, 0, 0], &[36, 128, 0, 0], &[36, 128, 4, 2, 12, 34, 0, 0], &[36, 128, 36, 128, 4, 3, 12, 34, 56, 0, 0, 0, 0], &[36, 128, 36, 128, 36, 128, 36, 128, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0], &[36, 128, 4, 1, 2, 36, 128, 4, 2, 3, 1, 0, 0, 0, 0], &[36, 0], &[36, 4, 4, 2, 12, 34], &[36, 128, 36, 5, 4, 3, 12 ,34, 56, 0, 0], &[36, 9, 36, 128, 4, 3, 12, 34, 56, 0, 0], &[36, 7, 36, 5, 4, 3, 12 ,34, 56], ]; for &data in tests { parse_der(data, |reader| { reader.read_bytes() }).unwrap_err(); } } #[test] fn test_ber_read_bytes_ok() { let tests : &[(&[u8], &[u8])] = &[ (&[1, 0, 100, 255], &[4, 4, 1, 0, 100, 255]), (&[], &[4, 0]), (&[4, 4, 4, 4], &[4, 4, 4, 4, 4, 4]), (&[], &[36, 128, 0, 0]), (&[12, 34], &[36, 128, 4, 2, 12, 34, 0, 0]), (&[12, 34, 56], &[36, 128, 36, 128, 4, 3, 12, 34, 56, 0, 0, 0, 0]), (&[], &[36, 128, 36, 128, 36, 128, 36, 128, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0]), (&[2, 3, 1], &[36, 128, 4, 1, 2, 36, 128, 4, 2, 3, 1, 0, 0, 0, 0]), (&[], &[36, 0]), (&[12, 34], &[36, 4, 4, 2, 12, 34]), (&[12, 34, 56], &[36, 128, 36, 5, 4, 3, 12 ,34, 56, 0, 0]), (&[12, 34, 56], &[36, 9, 36, 128, 4, 3, 12, 34, 56, 0, 0]), (&[12, 34, 56], &[36, 7, 36, 5, 4, 3, 12 ,34, 56]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_bytes() }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_ber_read_bytes_err() { let tests : &[&[u8]] = &[ &[], &[4], &[0, 0], &[0, 1, 0], &[1, 1, 0], &[36, 1, 0], &[68, 1, 0], &[4, 4, 0], &[4, 1, 1, 1], &[4, 128, 1, 0, 0], ]; for &data in tests { parse_ber(data, |reader| { reader.read_bytes() }).unwrap_err(); } } #[test] fn test_der_read_null_ok() { let value = parse_der(&[5, 0], |reader| { reader.read_null() }).unwrap(); assert_eq!(value, ()); } #[test] fn test_der_read_null_err() { let tests : &[&[u8]] = &[ &[], &[5], &[0, 0], &[0, 1, 0], &[2, 1, 0], &[37, 0], &[69, 0], &[5, 128, 0], &[37, 128, 0], &[5, 1, 0], &[5, 2, 0, 0], &[5, 1], &[5, 0, 1], ]; for &data in tests { parse_der(data, |reader| { reader.read_null() }).unwrap_err(); } } #[test] fn test_ber_read_null_ok() { let value = parse_ber(&[5, 0], |reader| { reader.read_null() }).unwrap(); assert_eq!(value, ()); } #[test] fn test_ber_read_null_err() { let tests : &[&[u8]] = &[ &[], &[5], &[0, 0], &[0, 1, 0], &[2, 1, 0], &[37, 0], &[69, 0], &[5, 128, 0], &[37, 128, 0], &[5, 1, 0], &[5, 2, 0, 0], &[5, 1], &[5, 0, 1], ]; for &data in tests { parse_ber(data, |reader| { reader.read_null() }).unwrap_err(); } } #[test] fn test_der_read_sequence_ok() { let tests : &[((i64, bool), &[u8])] = &[ ((10, true), &[48, 6, 2, 1, 10, 1, 1, 255]), ((266, true), &[48, 7, 2, 2, 1, 10, 1, 1, 255]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }).unwrap(); assert_eq!(value, evalue); } let tests : &[((), &[u8])] = &[ ((), &[48, 0]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_sequence(|_| { Ok(()) }) }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_der_read_sequence_err() { let tests : &[&[u8]] = &[ &[], &[48], &[0, 0], &[0, 1, 0], &[49, 6, 2, 1, 10, 1, 1, 255], &[16, 6, 2, 1, 10, 1, 1, 255], &[112, 6, 2, 1, 10, 1, 1, 255], &[48, 6, 2, 1, 10, 1, 1, 255, 0], &[48, 6, 2, 2, 1, 10, 1, 1, 255], &[48, 7, 2, 1, 10, 1, 1, 255, 0], &[48, 7, 2, 1, 10, 1, 1, 255], &[48, 8, 48, 6, 2, 1, 10, 1, 1, 255], &[49, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[16, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[112, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[48, 128, 2, 1, 10, 1, 1, 255, 0, 0, 0], &[48, 128, 48, 6, 2, 1, 10, 1, 1, 255, 0, 0], &[48, 10, 48, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[48, 128, 48, 128, 2, 1, 10, 1, 1, 255, 0, 0, 0, 0], &[48, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[48, 128, 2, 2, 1, 10, 1, 1, 255, 0, 0], ]; for &data in tests { parse_der(data, |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }).unwrap_err(); } } #[test] fn test_der_read_tagged_der_err() { let tests : &[&[u8]] = &[ &[], &[48], &[0, 0], &[0, 1, 0], &[48, 6, 2, 1, 10, 1, 1, 255, 0], &[48, 6, 2, 2, 1, 10, 1, 1, 255], &[48, 7, 2, 1, 10, 1, 1, 255], &[48, 128, 2, 1, 10, 1, 1, 255, 0, 0, 0], // Otherwise valid indefinite-length encodings &[48, 128, 48, 6, 2, 1, 10, 1, 1, 255, 0, 0], &[48, 128, 48, 128, 2, 1, 10, 1, 1, 255, 0, 0, 0, 0], &[48, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[48, 128, 2, 2, 1, 10, 1, 1, 255, 0, 0], ]; for &data in tests { parse_der(data, |reader| { reader.read_tagged_der() }).unwrap_err(); } } #[test] fn test_ber_read_sequence_ok() { let tests : &[((i64, bool), TaggedDerValue, &[u8])] = &[ // Definite-length encoding ((10, true), TaggedDerValue::from_tag_and_bytes( TAG_SEQUENCE, [2, 1, 10, 1, 1, 255].to_vec()), &[48, 6, 2, 1, 10, 1, 1, 255]), // Definite-length encoding ((266, true), TaggedDerValue::from_tag_and_bytes( TAG_SEQUENCE, [2, 2, 1, 10, 1, 1, 255].to_vec()), &[48, 7, 2, 2, 1, 10, 1, 1, 255]), // Indefinite-length encoding ((10, true), TaggedDerValue::from_tag_and_bytes( TAG_SEQUENCE, [2, 1, 10, 1, 1, 255, 0, 0].to_vec()), &[48, 128, 2, 1, 10, 1, 1, 255, 0, 0]), // Indefinite-length encoding ((266, true), TaggedDerValue::from_tag_and_bytes( TAG_SEQUENCE, [2, 2, 1, 10, 1, 1, 255, 0, 0].to_vec()), &[48, 128, 2, 2, 1, 10, 1, 1, 255, 0, 0]), ]; for &(evalue, ref ervalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }).unwrap(); assert_eq!(value, evalue); let rvalue = parse_ber(data, |reader| { reader.read_tagged_der() }).unwrap(); assert_eq!(&rvalue, ervalue); } let tests : &[((), &[u8])] = &[ ((), &[48, 0]), ((), &[48, 128, 0, 0]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_sequence(|_| { Ok(()) }) }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_ber_read_sequence_err() { let tests : &[&[u8]] = &[ &[], &[48], &[0, 0], &[0, 1, 0], &[49, 6, 2, 1, 10, 1, 1, 255], &[16, 6, 2, 1, 10, 1, 1, 255], &[112, 6, 2, 1, 10, 1, 1, 255], &[48, 6, 2, 1, 10, 1, 1, 255, 0], &[48, 6, 2, 2, 1, 10, 1, 1, 255], &[48, 7, 2, 1, 10, 1, 1, 255, 0], &[48, 7, 2, 1, 10, 1, 1, 255], &[48, 8, 48, 6, 2, 1, 10, 1, 1, 255], &[49, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[16, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[112, 128, 2, 1, 10, 1, 1, 255, 0, 0], &[48, 128, 2, 1, 10, 1, 1, 255, 0, 0, 0], &[48, 128, 48, 6, 2, 1, 10, 1, 1, 255, 0, 0], ]; for &data in tests { parse_ber(data, |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }).unwrap_err(); } } #[test] fn test_der_read_set_ok() { let tests : &[((i64, Vec, i64, Vec), &[u8])] = &[ ((456789, b"Foo".to_vec(), 456790, b"Bar".to_vec()), &[ 49, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111]), ]; for &(ref evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_set(|reader| { let a = reader.next(&[Tag::context(28)])? .read_tagged_implicit(Tag::context(28), |reader| { reader.read_i64() })?; let b = reader.next(&[Tag::context(345678)])? .read_tagged(Tag::context(345678), |reader| { reader.read_bytes() })?; let c = reader.next(&[Tag::context(27)])? .read_tagged(Tag::context(27), |reader| { reader.read_i64() })?; let d = reader.next(&[Tag::context(345677)])? .read_tagged(Tag::context(345677), |reader| { reader.read_bytes() })?; return Ok((a, b, c, d)); }) }).unwrap(); assert_eq!(&value, evalue); } } #[test] fn test_der_read_set_err() { let tests : &[&[u8]] = &[ &[], &[49], &[0, 0], &[0, 1, 0], &[17, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[113, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[48, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 33, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 33, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 0], &[49, 31, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 31, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111], &[49, 22, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114], &[49, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 191, 149, 140, 79, 5, 4, 3, 70, 111, 111], &[49, 128, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 0, 0], &[49, 32, 156, 3, 6, 248, 85, 187, 5, 2, 3, 6, 248, 86, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 32, 187, 5, 2, 3, 6, 248, 86, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 156, 3, 6, 248, 85, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114], ]; for &data in tests { parse_der(data, |reader| { reader.read_set(|reader| { let a = reader.next(&[Tag::context(28)])? .read_tagged_implicit(Tag::context(28), |reader| { reader.read_i64() })?; let b = reader.next(&[Tag::context(345678)])? .read_tagged(Tag::context(345678), |reader| { reader.read_bytes() })?; let c = reader.next(&[Tag::context(27)])? .read_tagged(Tag::context(27), |reader| { reader.read_i64() })?; let d = reader.next(&[Tag::context(345677)])? .read_tagged(Tag::context(345677), |reader| { reader.read_bytes() })?; return Ok((a, b, c, d)); }) }).unwrap_err(); } } #[test] fn test_ber_read_set_ok() { let tests : &[((i64, Vec, i64, Vec), &[u8])] = &[ ((456789, b"Foo".to_vec(), 456790, b"Bar".to_vec()), &[ 49, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111]), ((456789, b"Foo".to_vec(), 456790, b"Bar".to_vec()), &[ 49, 128, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 0, 0]), ((456789, b"Foo".to_vec(), 456790, b"Bar".to_vec()), &[ 49, 32, 156, 3, 6, 248, 85, 187, 5, 2, 3, 6, 248, 86, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111]), ((456789, b"Foo".to_vec(), 456790, b"Bar".to_vec()), &[ 49, 32, 187, 5, 2, 3, 6, 248, 86, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 156, 3, 6, 248, 85, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111]), ((456789, b"Foo".to_vec(), 456790, b"Bar".to_vec()), &[ 49, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114]), ]; for &(ref evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_set(|reader| { let a = reader.next(&[Tag::context(28)])? .read_tagged_implicit(Tag::context(28), |reader| { reader.read_i64() })?; let b = reader.next(&[Tag::context(345678)])? .read_tagged(Tag::context(345678), |reader| { reader.read_bytes() })?; let c = reader.next(&[Tag::context(27)])? .read_tagged(Tag::context(27), |reader| { reader.read_i64() })?; let d = reader.next(&[Tag::context(345677)])? .read_tagged(Tag::context(345677), |reader| { reader.read_bytes() })?; return Ok((a, b, c, d)); }) }).unwrap(); assert_eq!(&value, evalue); } } #[test] fn test_ber_read_set_err() { let tests : &[&[u8]] = &[ &[], &[49], &[0, 0], &[0, 1, 0], &[17, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[113, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[48, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 33, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 33, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 0], &[49, 31, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111], &[49, 31, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111], &[49, 22, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114], &[49, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111, 191, 149, 140, 79, 5, 4, 3, 70, 111, 111], ]; for &data in tests { parse_ber(data, |reader| { reader.read_set(|reader| { let a = reader.next(&[Tag::context(28)])? .read_tagged_implicit(Tag::context(28), |reader| { reader.read_i64() })?; let b = reader.next(&[Tag::context(345678)])? .read_tagged(Tag::context(345678), |reader| { reader.read_bytes() })?; let c = reader.next(&[Tag::context(27)])? .read_tagged(Tag::context(27), |reader| { reader.read_i64() })?; let d = reader.next(&[Tag::context(345677)])? .read_tagged(Tag::context(345677), |reader| { reader.read_bytes() })?; return Ok((a, b, c, d)); }) }).unwrap_err(); } } #[test] fn test_der_read_set_of_ok() { use std::collections::HashSet; let tests : &[(&[i64], &[u8])] = &[ (&[-129, -128, 127, 128], &[ 49, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127]), (&[-128, 127, 128], &[ 49, 10, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128]), (&[-129, -128, 127, 128, 32768], &[ 49, 19, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127, 2, 3, 0, 128, 0]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.collect_set_of(|reader| { reader.read_i64() }) }).unwrap(); let value_set = value.iter().collect::>(); let evalue_set = evalue.iter().collect::>(); assert_eq!(value_set, evalue_set); } } #[test] fn test_der_read_set_of_err() { let tests : &[&[u8]] = &[ &[], &[49], &[0, 0], &[0, 1, 0], &[17, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[113, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[48, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[49, 15, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[49, 15, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127, 0], &[49, 13, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[49, 13, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255], &[49, 128, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127, 0, 0], &[49, 14, 2, 1, 128, 2, 1, 127, 2, 2, 0, 128, 2, 2, 255, 127], &[49, 14, 2, 1, 127, 2, 2, 0, 128, 2, 1, 128, 2, 2, 255, 127], &[49, 14, 2, 1, 127, 2, 1, 128, 2, 2, 255, 127, 2, 2, 0, 128], &[49, 14, 2, 2, 255, 127, 2, 1, 128, 2, 2, 0, 128, 2, 1, 127], ]; for &data in tests { parse_der(data, |reader| { reader.read_set(|reader| { let a = reader.next(&[Tag::context(28)])? .read_tagged_implicit(Tag::context(28), |reader| { reader.read_i64() })?; let b = reader.next(&[Tag::context(345678)])? .read_tagged(Tag::context(345678), |reader| { reader.read_bytes() })?; let c = reader.next(&[Tag::context(27)])? .read_tagged(Tag::context(27), |reader| { reader.read_i64() })?; let d = reader.next(&[Tag::context(345677)])? .read_tagged(Tag::context(345677), |reader| { reader.read_bytes() })?; return Ok((a, b, c, d)); }) }).unwrap_err(); } } #[test] fn test_ber_read_set_of_ok() { use std::collections::HashSet; let tests : &[(&[i64], &[u8])] = &[ (&[-129, -128, 127, 128], &[ 49, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127]), (&[-128, 127, 128], &[ 49, 10, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128]), (&[-129, -128, 127, 128, 32768], &[ 49, 19, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127, 2, 3, 0, 128, 0]), (&[-129, -128, 127, 128], &[ 49, 128, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127, 0, 0]), (&[-129, -128, 127, 128], &[ 49, 14, 2, 1, 128, 2, 1, 127, 2, 2, 0, 128, 2, 2, 255, 127]), (&[-129, -128, 127, 128], &[ 49, 14, 2, 1, 127, 2, 2, 0, 128, 2, 1, 128, 2, 2, 255, 127]), (&[-129, -128, 127, 128], &[ 49, 14, 2, 1, 127, 2, 1, 128, 2, 2, 255, 127, 2, 2, 0, 128]), (&[-129, -128, 127, 128], &[ 49, 14, 2, 2, 255, 127, 2, 1, 128, 2, 2, 0, 128, 2, 1, 127]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.collect_set_of(|reader| { reader.read_i64() }) }).unwrap(); let value_set = value.iter().collect::>(); let evalue_set = evalue.iter().collect::>(); assert_eq!(value_set, evalue_set); } } #[test] fn test_ber_read_set_of_err() { let tests : &[&[u8]] = &[ &[], &[49], &[0, 0], &[0, 1, 0], &[17, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[113, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[48, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[49, 15, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[49, 15, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127, 0], &[49, 13, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127], &[49, 13, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255], ]; for &data in tests { parse_ber(data, |reader| { reader.read_set(|reader| { let a = reader.next(&[Tag::context(28)])? .read_tagged_implicit(Tag::context(28), |reader| { reader.read_i64() })?; let b = reader.next(&[Tag::context(345678)])? .read_tagged(Tag::context(345678), |reader| { reader.read_bytes() })?; let c = reader.next(&[Tag::context(27)])? .read_tagged(Tag::context(27), |reader| { reader.read_i64() })?; let d = reader.next(&[Tag::context(345677)])? .read_tagged(Tag::context(345677), |reader| { reader.read_bytes() })?; return Ok((a, b, c, d)); }) }).unwrap_err(); } } #[test] fn test_der_read_tagged_ok() { let tests : &[(i64, &[u8])] = &[ (10, &[163, 3, 2, 1, 10]), (266, &[163, 4, 2, 2, 1, 10]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap(); assert_eq!(value, evalue); } let tests : &[((i64, bool), &[u8])] = &[ ((10, false), &[163, 8, 48, 6, 2, 1, 10, 1, 1, 0]), ((266, false), &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1, 0]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_der_read_tagged_err() { let tests : &[&[u8]] = &[ &[], &[163], &[0, 0], &[0, 1, 0], &[160, 3, 2, 1, 10], &[35, 3, 2, 1, 10], &[131, 3, 2, 1, 10], &[131, 1, 10], &[163, 128, 2, 1, 10, 0, 0], ]; for &data in tests { parse_der(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap_err(); } let tests : &[&[u8]] = &[ &[], &[163], &[0, 0], &[0, 1, 0], &[160, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[35, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[131, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[163, 8, 48, 6, 2, 1, 10, 1, 1, 0, 0], &[163, 8, 48, 6, 2, 1, 10, 1, 1], &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0], &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1], &[163, 6, 2, 1, 10, 1, 1, 0], &[163, 7, 2, 2, 1, 10, 1, 1, 0], &[163, 128, 48, 6, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 48, 6, 2, 1, 10, 1, 1, 0, 0, 0], &[163, 128, 48, 6, 2, 1, 10, 1, 1, 0, 0], &[163, 128, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0, 0], &[163, 128, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0], ]; for &data in tests { parse_der(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap_err(); } } #[test] fn test_ber_read_tagged_ok() { let tests : &[(i64, &[u8])] = &[ (10, &[163, 3, 2, 1, 10]), (266, &[163, 4, 2, 2, 1, 10]), (10, &[163, 128, 2, 1, 10, 0, 0]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap(); assert_eq!(value, evalue); } let tests : &[((i64, bool), &[u8])] = &[ ((10, false), &[163, 8, 48, 6, 2, 1, 10, 1, 1, 0]), ((266, false), &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1, 0]), ((10, false), &[163, 128, 48, 6, 2, 1, 10, 1, 1, 0, 0, 0]), ((266, false), &[163, 128, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0, 0]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_ber_read_tagged_err() { let tests : &[&[u8]] = &[ &[], &[163], &[0, 0], &[0, 1, 0], &[160, 3, 2, 1, 10], &[35, 3, 2, 1, 10], &[131, 3, 2, 1, 10], &[131, 1, 10], ]; for &data in tests { parse_ber(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap_err(); } let tests : &[&[u8]] = &[ &[], &[163], &[0, 0], &[0, 1, 0], &[160, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[35, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[131, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[163, 8, 48, 6, 2, 1, 10, 1, 1, 0, 0], &[163, 8, 48, 6, 2, 1, 10, 1, 1], &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0], &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1], &[163, 6, 2, 1, 10, 1, 1, 0], &[163, 7, 2, 2, 1, 10, 1, 1, 0], &[163, 128, 48, 6, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 48, 6, 2, 1, 10, 1, 1, 0, 0], &[163, 128, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 48, 7, 2, 2, 1, 10, 1, 1, 0, 0], ]; for &data in tests { parse_ber(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap_err(); } } #[test] fn test_der_read_tagged_implicit_ok() { let tests : &[(i64, &[u8])] = &[ (10, &[131, 1, 10]), (266, &[131, 2, 1, 10]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_tagged_implicit(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap(); assert_eq!(value, evalue); } let tests : &[((i64, bool), &[u8])] = &[ ((10, false), &[163, 6, 2, 1, 10, 1, 1, 0]), ((266, false), &[163, 7, 2, 2, 1, 10, 1, 1, 0]), ]; for &(evalue, data) in tests { let value = parse_der(data, |reader| { reader.read_tagged_implicit(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_der_read_tagged_implicit_err() { let tests : &[&[u8]] = &[ &[], &[131], &[0, 0], &[0, 1, 0], &[128, 3, 2, 1, 10], &[3, 3, 2, 1, 10], &[163, 3, 2, 1, 10], &[163, 3, 2, 1, 10], &[131, 128, 1, 10, 0, 0], &[163, 128, 2, 1, 10, 0, 0], ]; for &data in tests { parse_der(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap_err(); } let tests : &[&[u8]] = &[ &[], &[163], &[0, 0], &[0, 1, 0], &[160, 6, 2, 1, 10, 1, 1, 0], &[35, 6, 2, 1, 10, 1, 1, 0], &[131, 6, 2, 1, 10, 1, 1, 0], &[163, 6, 2, 1, 10, 1, 1, 0, 0], &[163, 6, 2, 1, 10, 1, 1], &[163, 7, 2, 2, 1, 10, 1, 1, 0, 0], &[163, 7, 2, 2, 1, 10, 1, 1], &[163, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1, 0], &[163, 128, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 2, 1, 10, 1, 1, 0, 0, 0], &[163, 128, 2, 1, 10, 1, 1, 0, 0], &[163, 128, 2, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 2, 2, 1, 10, 1, 1, 0, 0, 0], &[163, 128, 2, 2, 1, 10, 1, 1, 0, 0], ]; for &data in tests { parse_der(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap_err(); } } #[test] fn test_ber_read_tagged_implicit_ok() { let tests : &[(i64, &[u8])] = &[ (10, &[131, 1, 10]), (266, &[131, 2, 1, 10]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_tagged_implicit(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap(); assert_eq!(value, evalue); } let tests : &[((i64, bool), &[u8])] = &[ ((10, false), &[163, 6, 2, 1, 10, 1, 1, 0]), ((266, false), &[163, 7, 2, 2, 1, 10, 1, 1, 0]), ((10, false), &[163, 128, 2, 1, 10, 1, 1, 0, 0, 0]), ((266, false), &[163, 128, 2, 2, 1, 10, 1, 1, 0, 0, 0]), ]; for &(evalue, data) in tests { let value = parse_ber(data, |reader| { reader.read_tagged_implicit(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap(); assert_eq!(value, evalue); } } #[test] fn test_ber_read_tagged_implicit_err() { let tests : &[&[u8]] = &[ &[], &[131], &[0, 0], &[0, 1, 0], &[128, 3, 2, 1, 10], &[3, 3, 2, 1, 10], &[163, 3, 2, 1, 10], &[163, 3, 2, 1, 10], &[131, 128, 1, 10, 0, 0], &[163, 128, 2, 1, 10, 0, 0], ]; for &data in tests { parse_ber(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_sequence(|reader| { let i = reader.next().read_i64()?; let b = reader.next().read_bool()?; return Ok((i, b)); }) }) }).unwrap_err(); } let tests : &[&[u8]] = &[ &[], &[163], &[0, 0], &[0, 1, 0], &[160, 6, 2, 1, 10, 1, 1, 0], &[35, 6, 2, 1, 10, 1, 1, 0], &[131, 6, 2, 1, 10, 1, 1, 0], &[163, 6, 2, 1, 10, 1, 1, 0, 0], &[163, 6, 2, 1, 10, 1, 1], &[163, 7, 2, 2, 1, 10, 1, 1, 0, 0], &[163, 7, 2, 2, 1, 10, 1, 1], &[163, 8, 48, 6, 2, 1, 10, 1, 1, 0], &[163, 9, 48, 7, 2, 2, 1, 10, 1, 1, 0], &[163, 128, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 2, 1, 10, 1, 1, 0, 0], &[163, 128, 2, 2, 1, 10, 1, 1, 0, 0, 0, 0], &[163, 128, 2, 2, 1, 10, 1, 1, 0, 0], ]; for &data in tests { parse_ber(data, |reader| { reader.read_tagged(Tag::context(3), |reader| { reader.read_i64() }) }).unwrap_err(); } } #[test] fn test_ber_read_overflow() { let data = [33, 136, 255, 255, 255, 255, 255, 255, 255, 255]; let r: Result = parse_ber(&data, |reader| { reader.read_bool() }); let err = r.unwrap_err(); assert_eq!(err.kind(), ASN1ErrorKind::IntegerOverflow); } yasna-0.5.2/src/serializer/mod.rs000064400000000000000000000317211046102023000150340ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![forbid(missing_docs)] use alloc::vec::Vec; use alloc::string::String; #[cfg(feature = "num-bigint")] use num_bigint::{BigInt,BigUint}; #[cfg(feature = "bit-vec")] use bit_vec::BitVec; use super::{DERWriter,construct_der}; use super::models::ObjectIdentifier; #[cfg(feature = "time")] use super::models::{UTCTime,GeneralizedTime}; /// Types encodable in DER. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::encode_der::(&65535); /// assert_eq!(&der, &[2, 3, 0, 255, 255]); /// ``` /// /// # Limitations /// /// Rust types don't correspond to ASN.1 types one-to-one. Not all kinds /// of ASN.1 types can be encoded via default `DEREncodable` implementation. /// /// If you want to encode ASN.1, you may implement `DEREncodable` for your /// own types or use [`construct_der`]. /// /// # Default implementations /// /// - The encoder for `Vec`/`[T]` is implemented as SEQUENCE OF encoder. /// - `()` as NULL encoder. /// - Tuples (except `()`) as SEQUENCE encoder. /// - `Vec`/`[u8]` as OCTETSTRING encoder. /// - `BitVec` as BITSTRING encoder. /// - `String`/`str` as UTF8String encoder. /// - `i64`, `u64`, `i32`, `u32`, `i16`, `u16`, `BigInt`, `BigUint` /// as INTEGER encoder. (`u8` is avoided because of confliction.) /// - `bool` as BOOLEAN encoder. /// - `ObjectIdentifier` as OBJECTT IDENTIFIER encoder. /// - `UTCTime`/`GeneralizedTime` as UTCTime/GeneralizedTime encoder. pub trait DEREncodable { /// Writes the value as an DER-encoded ASN.1 value. /// /// # Examples /// /// ``` /// use yasna::{DEREncodable,DERWriter}; /// struct Entry { /// name: String, /// age: i64, /// } /// /// impl DEREncodable for Entry { /// fn encode_der(&self, writer: DERWriter) { /// writer.write_sequence(|writer| { /// writer.next().write_visible_string(&self.name); /// writer.next().write_i64(self.age); /// }) /// } /// } /// fn main() { /// let entry = Entry { /// name: String::from("John"), /// age: 32, /// }; /// let der = yasna::encode_der(&entry); /// assert_eq!(&der, &[48, 9, 26, 4, 74, 111, 104, 110, 2, 1, 32]); /// } /// ``` fn encode_der<'a>(&self, writer: DERWriter<'a>); } /// Encodes a value to DER-encoded ASN.1 data. pub fn encode_der(value: &T) -> Vec { construct_der(|writer| { value.encode_der(writer) }) } impl DEREncodable for Vec where T: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { for elem in self.iter() { elem.encode_der(writer.next()); } }) } } impl DEREncodable for [T] where T: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { for elem in self.iter() { elem.encode_der(writer.next()); } }) } } impl DEREncodable for i64 { fn encode_der(&self, writer: DERWriter) { writer.write_i64(*self) } } impl DEREncodable for u64 { fn encode_der(&self, writer: DERWriter) { writer.write_u64(*self) } } impl DEREncodable for i32 { fn encode_der(&self, writer: DERWriter) { writer.write_i32(*self) } } impl DEREncodable for u32 { fn encode_der(&self, writer: DERWriter) { writer.write_u32(*self) } } impl DEREncodable for i16 { fn encode_der(&self, writer: DERWriter) { writer.write_i16(*self) } } impl DEREncodable for u16 { fn encode_der(&self, writer: DERWriter) { writer.write_u16(*self) } } #[cfg(feature = "num-bigint")] impl DEREncodable for BigInt { fn encode_der(&self, writer: DERWriter) { writer.write_bigint(self) } } #[cfg(feature = "num-bigint")] impl DEREncodable for BigUint { fn encode_der(&self, writer: DERWriter) { writer.write_biguint(self) } } impl DEREncodable for bool { fn encode_der(&self, writer: DERWriter) { writer.write_bool(*self) } } #[cfg(feature = "bit-vec")] impl DEREncodable for BitVec { fn encode_der(&self, writer: DERWriter) { writer.write_bitvec(self) } } impl DEREncodable for Vec { fn encode_der(&self, writer: DERWriter) { writer.write_bytes(self) } } impl DEREncodable for [u8] { fn encode_der(&self, writer: DERWriter) { writer.write_bytes(self) } } impl DEREncodable for String { fn encode_der(&self, writer: DERWriter) { writer.write_utf8string(self) } } impl DEREncodable for str { fn encode_der(&self, writer: DERWriter) { writer.write_utf8string(self) } } impl DEREncodable for ObjectIdentifier { fn encode_der(&self, writer: DERWriter) { writer.write_oid(self) } } #[cfg(feature = "time")] impl DEREncodable for UTCTime { fn encode_der(&self, writer: DERWriter) { writer.write_utctime(self) } } #[cfg(feature = "time")] impl DEREncodable for GeneralizedTime{ fn encode_der(&self, writer: DERWriter) { writer.write_generalized_time(self) } } impl DEREncodable for () { fn encode_der(&self, writer: DERWriter) { writer.write_null() } } impl DEREncodable for (T0,) where T0: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1) where T0: DEREncodable, T1: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4, T5) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable, T5: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); self.5.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4, T5, T6) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable, T5: DEREncodable, T6: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); self.5.encode_der(writer.next()); self.6.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4, T5, T6, T7) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable, T5: DEREncodable, T6: DEREncodable, T7: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); self.5.encode_der(writer.next()); self.6.encode_der(writer.next()); self.7.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable, T5: DEREncodable, T6: DEREncodable, T7: DEREncodable, T8: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); self.5.encode_der(writer.next()); self.6.encode_der(writer.next()); self.7.encode_der(writer.next()); self.8.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable, T5: DEREncodable, T6: DEREncodable, T7: DEREncodable, T8: DEREncodable, T9: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); self.5.encode_der(writer.next()); self.6.encode_der(writer.next()); self.7.encode_der(writer.next()); self.8.encode_der(writer.next()); self.9.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable, T5: DEREncodable, T6: DEREncodable, T7: DEREncodable, T8: DEREncodable, T9: DEREncodable, T10: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); self.5.encode_der(writer.next()); self.6.encode_der(writer.next()); self.7.encode_der(writer.next()); self.8.encode_der(writer.next()); self.9.encode_der(writer.next()); self.10.encode_der(writer.next()); }) } } impl DEREncodable for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) where T0: DEREncodable, T1: DEREncodable, T2: DEREncodable, T3: DEREncodable, T4: DEREncodable, T5: DEREncodable, T6: DEREncodable, T7: DEREncodable, T8: DEREncodable, T9: DEREncodable, T10: DEREncodable, T11: DEREncodable { fn encode_der(&self, writer: DERWriter) { writer.write_sequence(|writer| { self.0.encode_der(writer.next()); self.1.encode_der(writer.next()); self.2.encode_der(writer.next()); self.3.encode_der(writer.next()); self.4.encode_der(writer.next()); self.5.encode_der(writer.next()); self.6.encode_der(writer.next()); self.7.encode_der(writer.next()); self.8.encode_der(writer.next()); self.9.encode_der(writer.next()); self.10.encode_der(writer.next()); self.11.encode_der(writer.next()); }) } } yasna-0.5.2/src/tags/mod.rs000064400000000000000000000122151046102023000136160ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Provides universal tag constants. use super::{Tag,TagClass}; /// A special tag representing "end of contents". pub const TAG_EOC : Tag = Tag { tag_class: TagClass::Universal, tag_number: 0, }; /// A universal tag for BOOLEAN. pub const TAG_BOOLEAN : Tag = Tag { tag_class: TagClass::Universal, tag_number: 1, }; /// A universal tag for INTEGER. pub const TAG_INTEGER : Tag = Tag { tag_class: TagClass::Universal, tag_number: 2, }; /// A universal tag for BITSTRING. pub const TAG_BITSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 3, }; /// A universal tag for OCTETSTRING. pub const TAG_OCTETSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 4, }; /// A universal tag for NULL. pub const TAG_NULL : Tag = Tag { tag_class: TagClass::Universal, tag_number: 5, }; /// A universal tag for object identifiers. pub const TAG_OID : Tag = Tag { tag_class: TagClass::Universal, tag_number: 6, }; /// A universal tag for object descriptors. pub const TAG_OBJECT_DESCRIPTOR : Tag = Tag { tag_class: TagClass::Universal, tag_number: 7, }; /// A universal tag for external/instance-of types. pub const TAG_EXT : Tag = Tag { tag_class: TagClass::Universal, tag_number: 8, }; /// A universal tag for REAL. pub const TAG_REAL : Tag = Tag { tag_class: TagClass::Universal, tag_number: 9, }; /// A universal tag for enumerated types. pub const TAG_ENUM : Tag = Tag { tag_class: TagClass::Universal, tag_number: 10, }; /// A universal tag for embedded-pdv types. pub const TAG_EMBEDDED_PDV : Tag = Tag { tag_class: TagClass::Universal, tag_number: 11, }; /// A universal tag for UTF8String. pub const TAG_UTF8STRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 12, }; /// A universal tag for relative object identifiers. pub const TAG_RELATIVE_OID : Tag = Tag { tag_class: TagClass::Universal, tag_number: 13, }; /// A universal tag for TIME. pub const TAG_TIME : Tag = Tag { tag_class: TagClass::Universal, tag_number: 14, }; /// A universal tag for SEQUENCE/SEQUENCE OF. pub const TAG_SEQUENCE : Tag = Tag { tag_class: TagClass::Universal, tag_number: 16, }; /// A universal tag for SET/SET OF. pub const TAG_SET : Tag = Tag { tag_class: TagClass::Universal, tag_number: 17, }; /// A universal tag for NumericString. pub const TAG_NUMERICSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 18, }; /// A universal tag for PrintableString. pub const TAG_PRINTABLESTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 19, }; /// A universal tag for TeletexString. pub const TAG_TELETEXSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 20, }; /// A universal tag for VideotexString. pub const TAG_VIDEOTEXSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 21, }; /// A universal tag for IA5String. pub const TAG_IA5STRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 22, }; /// A universal tag for UTCTime. pub const TAG_UTCTIME : Tag = Tag { tag_class: TagClass::Universal, tag_number: 23, }; /// A universal tag for GeneralizedTime. pub const TAG_GENERALIZEDTIME : Tag = Tag { tag_class: TagClass::Universal, tag_number: 24, }; /// A universal tag for GraphicString. pub const TAG_GRAPHICSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 25, }; /// A universal tag for VisibleString. pub const TAG_VISIBLESTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 26, }; /// A universal tag for GeneralString. pub const TAG_GENERALSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 27, }; /// A universal tag for UniversalString. pub const TAG_UNIVERSALSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 28, }; /// A universal tag for BMPString. pub const TAG_BMPSTRING : Tag = Tag { tag_class: TagClass::Universal, tag_number: 30, }; /// A universal tag for DATE. pub const TAG_DATE : Tag = Tag { tag_class: TagClass::Universal, tag_number: 31, }; /// A universal tag for TIME-OF-DAY. pub const TAG_TIME_OF_DAY : Tag = Tag { tag_class: TagClass::Universal, tag_number: 32, }; /// A universal tag for DATE-TIME. pub const TAG_DATE_TIME : Tag = Tag { tag_class: TagClass::Universal, tag_number: 33, }; /// A universal tag for DURATION. pub const TAG_DURATION : Tag = Tag { tag_class: TagClass::Universal, tag_number: 34, }; /// A universal tag for OID internationalized resource identifiers. pub const TAG_OID_INTL_RESID : Tag = Tag { tag_class: TagClass::Universal, tag_number: 35, }; /// A universal tag for relative OID internationalized resource identifiers. pub const TAG_RELATIVE_OID_INTL_RESID : Tag = Tag { tag_class: TagClass::Universal, tag_number: 36, }; yasna-0.5.2/src/writer/mod.rs000064400000000000000000001134311046102023000141760ustar 00000000000000// Copyright 2016 Masaki Hara // Copyright 2019 Fortanix, Inc. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![forbid(missing_docs)] use alloc::vec::Vec; #[cfg(feature = "num-bigint")] use num_bigint::{BigUint, BigInt}; #[cfg(feature = "bit-vec")] use bit_vec::BitVec; use super::{PCBit, Tag}; use super::tags::{TAG_BOOLEAN,TAG_INTEGER,TAG_OCTETSTRING}; use super::tags::{TAG_NULL,TAG_OID,TAG_UTF8STRING,TAG_SEQUENCE,TAG_SET,TAG_ENUM,TAG_IA5STRING,TAG_BMPSTRING}; use super::tags::{TAG_NUMERICSTRING,TAG_PRINTABLESTRING,TAG_VISIBLESTRING}; use super::models::{ObjectIdentifier,TaggedDerValue}; #[cfg(feature = "time")] use super::models::{UTCTime,GeneralizedTime}; /// Constructs DER-encoded data as `Vec`. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriter`], to which the ASN.1 value is written. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_sequence(|writer| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// }) /// }); /// assert_eq!(der, vec![48, 6, 2, 1, 10, 1, 1, 255]); /// ``` pub fn construct_der(callback: F) -> Vec where F: FnOnce(DERWriter) { let mut buf = Vec::new(); { let mut writer = DERWriterSeq { buf: &mut buf, }; callback(writer.next()); } return buf; } /// Tries to construct DER-encoded data as `Vec`. /// /// Same as [`construct_der`], only that it allows /// returning an error from the passed closure. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriterSeq`], to which the ASN.1 values are written. /// /// # Examples /// /// ``` /// use yasna; /// let res_ok = yasna::try_construct_der::<_, ()>(|writer| { /// writer.write_sequence(|writer| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// }); /// Ok(()) /// }); /// let res_err = yasna::try_construct_der::<_, &str>(|writer| { /// writer.write_sequence(|writer| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// return Err("some error here"); /// })?; /// Ok(()) /// }); /// assert_eq!(res_ok, Ok(vec![48, 6, 2, 1, 10, 1, 1, 255])); /// assert_eq!(res_err, Err("some error here")); /// ``` pub fn try_construct_der(callback: F) -> Result, E> where F: FnOnce(DERWriter) -> Result<(), E> { let mut buf = Vec::new(); { let mut writer = DERWriterSeq { buf: &mut buf, }; callback(writer.next())?; } return Ok(buf); } /// Constructs DER-encoded sequence of data as `Vec`. /// /// This is similar to [`construct_der`], but this function /// accepts more than one ASN.1 values. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriterSeq`], to which the ASN.1 values are written. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der_seq(|writer| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// }); /// assert_eq!(der, vec![2, 1, 10, 1, 1, 255]); /// ``` pub fn construct_der_seq(callback: F) -> Vec where F: FnOnce(&mut DERWriterSeq) { let mut buf = Vec::new(); { let mut writer = DERWriterSeq { buf: &mut buf, }; callback(&mut writer); } return buf; } /// Tries to construct a DER-encoded sequence of data as `Vec`. /// /// Same as [`construct_der_seq`], only that it allows /// returning an error from the passed closure. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriterSeq`], to which the ASN.1 values are written. /// /// # Examples /// /// ``` /// use yasna; /// let res_ok = yasna::try_construct_der_seq::<_, ()>(|writer| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// Ok(()) /// }); /// let res_err = yasna::try_construct_der_seq::<_, &str>(|writer| { /// return Err("some error here"); /// }); /// assert_eq!(res_ok, Ok(vec![2, 1, 10, 1, 1, 255])); /// assert_eq!(res_err, Err("some error here")); /// ``` pub fn try_construct_der_seq(callback: F) -> Result , E> where F: FnOnce(&mut DERWriterSeq) -> Result<(), E> { let mut buf = Vec::new(); { let mut writer = DERWriterSeq { buf: &mut buf, }; callback(&mut writer)?; } return Ok(buf); } /// A writer object that accepts an ASN.1 value. /// /// The two main sources of `DERWriterSeq` are: /// /// - The [`construct_der`] function, the starting point of /// DER serialization. /// - The [`next`](DERWriterSeq::next) method of [`DERWriterSeq`]. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_i64(10) /// }); /// assert_eq!(der, vec![2, 1, 10]); /// ``` #[derive(Debug)] pub struct DERWriter<'a> { buf: &'a mut Vec, implicit_tag: Option, } impl<'a> DERWriter<'a> { fn from_buf(buf: &'a mut Vec) -> Self { return DERWriter { buf, implicit_tag: None, } } /// Writes BER identifier (tag + primitive/constructed) octets. fn write_identifier(&mut self, tag: Tag, pc: PCBit) { let tag = if let Some(tag) = self.implicit_tag { tag } else { tag }; self.implicit_tag = None; let classid = tag.tag_class as u8; let pcid = pc as u8; if tag.tag_number < 31 { self.buf.push( (classid << 6) | (pcid << 5) | (tag.tag_number as u8)); return; } self.buf.push((classid << 6) | (pcid << 5) | 31); let mut shiftnum = 63; // ceil(64 / 7) * 7 - 7 while (tag.tag_number >> shiftnum) == 0 { shiftnum -= 7; } while shiftnum > 0 { self.buf.push(128 | (((tag.tag_number >> shiftnum) & 127) as u8)); shiftnum -= 7; } self.buf.push((tag.tag_number & 127) as u8); } /// Writes BER length octets. fn write_length(&mut self, length: usize) { let length = length as u64; if length < 128 { self.buf.push(length as u8); return; } let mut shiftnum = 56; // ceil(64 / 8) * 8 - 8 while (length >> shiftnum) == 0 { shiftnum -= 8; } self.buf.push(128 | ((shiftnum / 8 + 1) as u8)); loop { self.buf.push((length >> shiftnum) as u8); if shiftnum == 0 { break; } shiftnum -= 8; } } /// Deals with unknown length procedures. /// This function first marks the current position and /// allocates 3 bytes. Then it calls back `callback`. /// It then calculates the length and moves the written data /// to the actual position. Finally, it writes the length. fn with_length(&mut self, callback: F) -> T where F: FnOnce(&mut Self) -> T { let expected_length_length = 3; for _ in 0..3 { self.buf.push(255); } let start_pos = self.buf.len(); let result = callback(self); let length = (self.buf.len() - start_pos) as u64; let length_length; let mut shiftnum = 56; // ceil(64 / 8) * 8 - 8 if length < 128 { length_length = 1; } else { while (length >> shiftnum) == 0 { shiftnum -= 8; } length_length = shiftnum / 8 + 2; } let new_start_pos; if length_length < expected_length_length { let diff = expected_length_length - length_length; new_start_pos = start_pos - diff; self.buf.drain(new_start_pos .. start_pos); } else if length_length > expected_length_length { let diff = length_length - expected_length_length; new_start_pos = start_pos + diff; for _ in 0..diff { self.buf.insert(start_pos, 0); } } else { new_start_pos = start_pos; } let mut idx = new_start_pos - length_length; if length < 128 { self.buf[idx] = length as u8; } else { self.buf[idx] = 128 | ((shiftnum / 8 + 1) as u8); idx += 1; loop { self.buf[idx] = (length >> shiftnum) as u8; idx += 1; if shiftnum == 0 { break; } shiftnum -= 8; } } return result; } /// Writes `bool` as an ASN.1 BOOLEAN value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_bool(true) /// }); /// assert_eq!(der, vec![1, 1, 255]); /// ``` pub fn write_bool(mut self, val: bool) { self.write_identifier(TAG_BOOLEAN, PCBit::Primitive); self.write_length(1); self.buf.push(if val { 255 } else { 0 }); } fn write_integer(mut self, tag: Tag, val: i64) { let mut shiftnum = 56; while shiftnum > 0 && (val >> (shiftnum-1) == 0 || val >> (shiftnum-1) == -1) { shiftnum -= 8; } self.write_identifier(tag, PCBit::Primitive); self.write_length(shiftnum / 8 + 1); loop { self.buf.push((val >> shiftnum) as u8); if shiftnum == 0 { break; } shiftnum -= 8; } } /// Writes `i64` as an ASN.1 ENUMERATED value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_enum(2) /// }); /// assert_eq!(der, vec![10, 1, 2]); /// ``` pub fn write_enum(self, val: i64) { self.write_integer(TAG_ENUM, val); } /// Writes `i64` as an ASN.1 INTEGER value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_i64(1234567890) /// }); /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]); /// ``` pub fn write_i64(self, val: i64) { self.write_integer(TAG_INTEGER, val); } /// Writes `u64` as an ASN.1 INTEGER value. pub fn write_u64(mut self, val: u64) { let mut shiftnum = 64; while shiftnum > 0 && val >> (shiftnum-1) == 0 { shiftnum -= 8; } self.write_identifier(TAG_INTEGER, PCBit::Primitive); self.write_length(shiftnum / 8 + 1); if shiftnum == 64 { self.buf.push(0); shiftnum -= 8; } loop { self.buf.push((val >> shiftnum) as u8); if shiftnum == 0 { break; } shiftnum -= 8; } } /// Writes `i32` as an ASN.1 INTEGER value. pub fn write_i32(self, val: i32) { self.write_i64(val as i64) } /// Writes `u32` as an ASN.1 INTEGER value. pub fn write_u32(self, val: u32) { self.write_i64(val as i64) } /// Writes `i16` as an ASN.1 INTEGER value. pub fn write_i16(self, val: i16) { self.write_i64(val as i64) } /// Writes `u16` as an ASN.1 INTEGER value. pub fn write_u16(self, val: u16) { self.write_i64(val as i64) } /// Writes `i8` as an ASN.1 INTEGER value. pub fn write_i8(self, val: i8) { self.write_i64(val as i64) } /// Writes `u8` as an ASN.1 INTEGER value. pub fn write_u8(self, val: u8) { self.write_i64(val as i64) } #[cfg(feature = "num-bigint")] /// Writes `BigInt` as an ASN.1 INTEGER value. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// use num_bigint::BigInt; /// let der = yasna::construct_der(|writer| { /// writer.write_bigint( /// &BigInt::parse_bytes(b"1234567890", 10).unwrap()) /// }); /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]); /// # } /// ``` /// /// # Features /// /// This method is enabled by `num` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["num-bigint"] } /// ``` pub fn write_bigint(self, val: &BigInt) { use num_bigint::Sign; let (sign, mut bytes) = val.to_bytes_be(); if sign == Sign::Minus { let mut carry: usize = 1; for b in bytes.iter_mut().rev() { let bval = 255 - (*b as usize); *b = (bval + carry) as u8; carry = (bval + carry) >> 8; } } self.write_bigint_bytes(&bytes, sign != Sign::Minus); } /// Writes `&[u8]` and `bool` as an ASN.1 INTEGER value. /// /// The first parameter encodes the bytes of the integer, in big-endian /// byte ordering and two's complement format. The second parameter encodes /// the sign, and is true if the number is non-negative, and false if it is /// negative. Zero is encoded by passing an empty slice. /// /// The number is expected to be in two's complement format, so for example /// `1` is encoded as `[1]` and `-1` as `[255]`. /// /// You don't have to worry about leading bits, meaning that if the leading /// bit of a positive number is not zero, a leading zero byte will be /// encoded by the function. Similarly, if the leading bit of a negative /// number is not one, a leading byte will be added by the function as well. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// let der = yasna::construct_der(|writer| { /// // Encodes 1234567890 /// writer.write_bigint_bytes(&[73, 150, 2, 210], true) /// }); /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]); /// # } /// ``` pub fn write_bigint_bytes(mut self, bytes: &[u8], positive: bool) { let mut bytes = bytes; // Remove leading zero bytes while bytes.get(0) == Some(&0) { bytes = &bytes[1..]; } if !positive { // Remove leading 255 bytes // (the order is important here, [255, 0] should be a fixpoint input) while bytes.len() > 1 && bytes[0] == 255 && bytes.get(1).unwrap_or(&0) & 128 != 0 { bytes = &bytes[1..]; } } self.write_identifier(TAG_INTEGER, PCBit::Primitive); if bytes.len() == 0 || bytes[0] == 0 { self.write_length(1); self.buf.push(0); } else if positive { if bytes[0] >= 128 { self.write_length(bytes.len() + 1); self.buf.push(0); } else { self.write_length(bytes.len()); } self.buf.extend_from_slice(&bytes); } else { debug_assert!(bytes[0] != 0); if bytes[0] < 128 { self.write_length(bytes.len() + 1); self.buf.push(255); } else { self.write_length(bytes.len()); } self.buf.extend_from_slice(&bytes); } } #[cfg(feature = "num-bigint")] /// Writes `BigUint` as an ASN.1 INTEGER value. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// use num_bigint::BigUint; /// let der = yasna::construct_der(|writer| { /// writer.write_biguint( /// &BigUint::parse_bytes(b"1234567890", 10).unwrap()) /// }); /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]); /// # } /// ``` /// /// # Features /// /// This method is enabled by `num` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["num-bigint"] } /// ``` pub fn write_biguint(mut self, val: &BigUint) { self.write_identifier(TAG_INTEGER, PCBit::Primitive); let mut bytes = val.to_bytes_le(); if &bytes == &[0] { self.write_length(1); self.buf.push(0); return; } let byteslen = bytes.len(); debug_assert!(bytes[byteslen-1] != 0); if bytes[byteslen-1] >= 128 { self.write_length(byteslen+1); self.buf.push(0); } else { self.write_length(byteslen); } bytes.reverse(); self.buf.extend_from_slice(&bytes); } #[cfg(feature = "bit-vec")] /// Writes [`BitVec`] as an ASN.1 BITSTRING value. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// use bit_vec::BitVec; /// let der = yasna::construct_der(|writer| { /// writer.write_bitvec(& /// [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, /// 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1] /// .iter().map(|&i| i != 0).collect()) /// }); /// assert_eq!(&der, &[3, 5, 3, 206, 213, 116, 24]); /// # } /// ``` /// /// # Features /// /// This method is enabled by `bit-vec` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["bit-vec"] } /// ``` pub fn write_bitvec(self, bitvec: &BitVec) { let len = bitvec.len(); let bytes = bitvec.to_bytes(); self.write_bitvec_bytes(&bytes, len); } /// Writes `&[u8]` and `usize` as an ASN.1 BITSTRING value. /// /// The `len` parameter represents the number of bits to be encoded. /// This function is similar to `write_bitvec`, with `to_bytes` applied to /// the bitvec, but is available even if the `bit-vec` feature is disabled. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// let der_1 = yasna::construct_der(|writer| { /// writer.write_bitvec_bytes(&[117, 13, 64], 18) /// }); /// let der_2 = yasna::construct_der(|writer| { /// writer.write_bitvec_bytes(&[117, 13, 65], 18) /// }); /// assert_eq!(&der_1, &[3, 4, 6, 117, 13, 64]); /// assert_eq!(&der_2, &[3, 4, 6, 117, 13, 64]); /// # } /// ``` pub fn write_bitvec_bytes(mut self, bytes: &[u8], len: usize) { use super::tags::TAG_BITSTRING; self.write_identifier(TAG_BITSTRING, PCBit::Primitive); debug_assert!(len <= 8 * bytes.len()); debug_assert!(8 * bytes.len() < len + 8); self.write_length(1 + bytes.len()); let len_diff = 8 * bytes.len() - len; self.buf.push(len_diff as u8); if bytes.len() > 0 { self.buf.extend_from_slice(&bytes[0 .. bytes.len() - 1]); let mask = !(255u16 >> (8 - len_diff)) as u8; self.buf.push(bytes[bytes.len() - 1] & mask); } } /// Writes `&[u8]` as an ASN.1 OCTETSTRING value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_bytes(b"Hello!") /// }); /// assert_eq!(der, vec![4, 6, 72, 101, 108, 108, 111, 33]); /// ``` pub fn write_bytes(mut self, bytes: &[u8]) { self.write_identifier(TAG_OCTETSTRING, PCBit::Primitive); self.write_length(bytes.len()); self.buf.extend_from_slice(bytes); } /// Writes `&str` as an ASN.1 UTF8String value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_utf8_string("Hello!") /// }); /// assert_eq!(der, vec![12, 6, 72, 101, 108, 108, 111, 33]); /// ``` pub fn write_utf8_string(mut self, string: &str) { self.write_identifier(TAG_UTF8STRING, PCBit::Primitive); self.write_length(string.len()); self.buf.extend_from_slice(string.as_bytes()); } /// Writes `&str` as an ASN.1 IA5String value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_ia5_string("Hello!") /// }); /// assert_eq!(der, vec![22, 6, 72, 101, 108, 108, 111, 33]); /// ``` pub fn write_ia5_string(mut self, string: &str) { assert!(string.is_ascii(), "IA5 string must be ASCII"); self.write_identifier(TAG_IA5STRING, PCBit::Primitive); self.write_length(string.len()); self.buf.extend_from_slice(string.as_bytes()); } /// Writes `&str` as an ASN.1 BMPString value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_bmp_string("❤πü2?") /// }); /// assert_eq!(der, vec![30, 10, 39, 100, 3, 192, 0, 252, 0, 50, 0, 63]); /// ``` pub fn write_bmp_string(mut self, string: &str) { let utf16 : Vec = string.encode_utf16().collect(); let mut bytes = Vec::with_capacity(utf16.len() * 2); for c in utf16 { bytes.push((c / 256) as u8); bytes.push((c % 256) as u8); } self.write_identifier(TAG_BMPSTRING, PCBit::Primitive); self.write_length(bytes.len()); self.buf.extend_from_slice(&bytes); } /// Writes the ASN.1 NULL value. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_null() /// }); /// assert_eq!(der, vec![5, 0]); /// ``` pub fn write_null(mut self) { self.write_identifier(TAG_NULL, PCBit::Primitive); self.write_length(0); } /// Writes an ASN.1 object identifier. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::models::ObjectIdentifier; /// let der = yasna::construct_der(|writer| { /// writer.write_oid(&ObjectIdentifier::from_slice( /// &[1, 2, 840, 113549, 1, 1])) /// }); /// assert_eq!(&der, &[6, 8, 42, 134, 72, 134, 247, 13, 1, 1]); /// ``` /// /// # Panics /// /// It panics when the OID cannot be canonically encoded in BER. pub fn write_oid(mut self, oid: &ObjectIdentifier) { assert!(oid.components().len() >= 2, "Invalid OID: too short"); let id0 = oid.components()[0]; let id1 = oid.components()[1]; assert!( (id0 < 3) && (id1 < 18446744073709551535) && (id0 >= 2 || id1 < 40), "Invalid OID {{{} {} ...}}", id0, id1); let subid0 = id0 * 40 + id1; let mut length = 0; for i in 1..oid.components().len() { let mut subid = if i == 1 { subid0 } else { oid.components()[i] } | 1; while subid > 0 { length += 1; subid >>= 7; } } self.write_identifier(TAG_OID, PCBit::Primitive); self.write_length(length); for i in 1..oid.components().len() { let subid = if i == 1 { subid0 } else { oid.components()[i] }; let mut shiftnum = 63; // ceil(64 / 7) * 7 - 7 while ((subid|1) >> shiftnum) == 0 { shiftnum -= 7; } while shiftnum > 0 { self.buf.push(128 | ((((subid|1) >> shiftnum) & 127) as u8)); shiftnum -= 7; } self.buf.push((subid & 127) as u8); } } /// Writes an ASN.1 UTF8String. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_utf8string("gnaw ροκανίζω 𪘂る") /// }); /// assert_eq!(&der, &[ /// 12, 29, 103, 110, 97, 119, 32, 207, 129, 206, 191, 206, /// 186, 206, 177, 206, 189, 206, 175, 206, 182, 207, /// 137, 32, 240, 170, 152, 130, 227, 130, 139]); /// ``` pub fn write_utf8string(self, string: &str) { self.write_tagged_implicit(TAG_UTF8STRING, |writer| { writer.write_bytes(string.as_bytes()) }) } /// Writes ASN.1 SEQUENCE. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriterSeq`], to which the contents of the /// SEQUENCE is written. /// /// This is equivalent to [`write_sequence_of`](Self::write_sequence_of) /// in behavior. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_sequence(|writer| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// }) /// }); /// assert_eq!(der, vec![48, 6, 2, 1, 10, 1, 1, 255]); /// ``` pub fn write_sequence(mut self, callback: F) -> T where F: FnOnce(&mut DERWriterSeq) -> T { self.write_identifier(TAG_SEQUENCE, PCBit::Constructed); return self.with_length(|writer| { callback(&mut DERWriterSeq { buf: writer.buf, }) }); } /// Writes ASN.1 SEQUENCE OF. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriterSeq`], to which the contents of the /// SEQUENCE OF are written. /// /// This is equivalent to [`write_sequence`](Self::write_sequence) in /// behavior. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_sequence_of(|writer| { /// for &i in &[10, -129] { /// writer.next().write_i64(i); /// } /// }) /// }); /// assert_eq!(der, vec![48, 7, 2, 1, 10, 2, 2, 255, 127]); /// ``` pub fn write_sequence_of(self, callback: F) -> T where F: FnOnce(&mut DERWriterSeq) -> T { self.write_sequence(callback) } /// Writes ASN.1 SET. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriterSet`], to which the contents of the /// SET are written. /// /// For SET OF values, use [`write_set_of`](Self::write_set_of) instead. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_set(|writer| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// }) /// }); /// assert_eq!(der, vec![49, 6, 1, 1, 255, 2, 1, 10]); /// ``` pub fn write_set(mut self, callback: F) -> T where F: FnOnce(&mut DERWriterSet) -> T { let mut bufs = Vec::new(); let result = callback(&mut DERWriterSet { bufs: &mut bufs, }); for buf in bufs.iter() { assert!(buf.len() > 0, "Empty output in write_set()"); } bufs.sort_by(|buf0, buf1| { let buf00 = buf0[0] & 223; let buf10 = buf1[0] & 223; if buf00 != buf10 || (buf0[0] & 31) != 31 { return buf00.cmp(&buf10); } let len0 = buf0[1..].iter().position(|x| x & 128 == 0).unwrap(); let len1 = buf1[1..].iter().position(|x| x & 128 == 0).unwrap(); if len0 != len1 { return len0.cmp(&len1); } return buf0[1..].cmp(&buf1[1..]); }); // let bufs_len = bufs.iter().map(|buf| buf.len()).sum(); let bufs_len = bufs.iter().map(|buf| buf.len()).fold(0, |x, y| x + y); self.write_identifier(TAG_SET, PCBit::Constructed); self.write_length(bufs_len); for buf in bufs.iter() { self.buf.extend_from_slice(buf); } return result; } /// Writes ASN.1 SET OF. /// /// This function uses the loan pattern: `callback` is called back with /// a [`DERWriterSet`], to which the contents of the /// SET OF are written. /// /// For SET values, use [`write_set`](Self::write_set) instead. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_set_of(|writer| { /// for &i in &[10, -129] { /// writer.next().write_i64(i); /// } /// }) /// }); /// assert_eq!(der, vec![49, 7, 2, 1, 10, 2, 2, 255, 127]); /// ``` pub fn write_set_of(mut self, callback: F) -> T where F: FnOnce(&mut DERWriterSet) -> T { let mut bufs = Vec::new(); let result = callback(&mut DERWriterSet { bufs: &mut bufs, }); for buf in bufs.iter() { assert!(buf.len() > 0, "Empty output in write_set_of()"); } bufs.sort(); // let bufs_len = bufs.iter().map(|buf| buf.len()).sum(); let bufs_len = bufs.iter().map(|buf| buf.len()).fold(0, |x, y| x + y); self.write_identifier(TAG_SET, PCBit::Constructed); self.write_length(bufs_len); for buf in bufs.iter() { self.buf.extend_from_slice(buf); } return result; } /// Writes an ASN.1 NumericString. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_numeric_string("128 256") /// }); /// assert_eq!(&der, &[18, 7, 49, 50, 56, 32, 50, 53, 54]); /// ``` pub fn write_numeric_string(self, string: &str) { let bytes = string.as_bytes(); for &byte in bytes { assert!(byte == b' ' || (b'0' <= byte && byte <= b'9'), "Invalid NumericString: {:?} appeared", byte); } self.write_tagged_implicit(TAG_NUMERICSTRING, |writer| { writer.write_bytes(bytes) }); } /// Writes an ASN.1 PrintableString. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_printable_string("Co., Ltd.") /// }); /// assert_eq!(&der, &[19, 9, 67, 111, 46, 44, 32, 76, 116, 100, 46]); /// ``` pub fn write_printable_string(self, string: &str) { let bytes = string.as_bytes(); for &byte in bytes { assert!( byte == b' ' || (b'\'' <= byte && byte <= b':' && byte != b'*') || byte == b'=' || (b'A' <= byte && byte <= b'Z') || (b'a' <= byte && byte <= b'z'), "Invalid PrintableString: {:?} appeared", byte); } self.write_tagged_implicit(TAG_PRINTABLESTRING, |writer| { writer.write_bytes(bytes) }); } #[cfg(feature = "time")] /// Writes an ASN.1 UTCTime. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// use yasna::models::UTCTime; /// use time::OffsetDateTime; /// let der = yasna::construct_der(|writer| { /// writer.write_utctime( /// &UTCTime::from_datetime( /// OffsetDateTime::from_unix_timestamp(378820800).unwrap())) /// }); /// assert_eq!(&der, &[ /// 23, 13, 56, 50, 48, 49, 48, 50, 49, 50, 48, 48, 48, 48, 90]); /// # } /// ``` /// /// # Features /// /// This method is enabled by `time` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["time"] } /// ``` pub fn write_utctime(self, datetime: &UTCTime) { use super::tags::TAG_UTCTIME; self.write_tagged_implicit(TAG_UTCTIME, |writer| { writer.write_bytes(&datetime.to_bytes()) }); } #[cfg(feature = "time")] /// Writes an ASN.1 GeneralizedTime. /// /// # Examples /// /// ``` /// # fn main() { /// use yasna; /// use yasna::models::GeneralizedTime; /// use time::OffsetDateTime; /// let der = yasna::construct_der(|writer| { /// writer.write_generalized_time( /// &GeneralizedTime::from_datetime( /// OffsetDateTime::from_unix_timestamp_nanos( /// 500_159_309_724_000_000).unwrap())) /// }); /// assert_eq!(&der, &[ /// 24, 19, 49, 57, 56, 53, 49, 49, 48, 54, 50, /// 49, 48, 56, 50, 57, 46, 55, 50, 52, 90]); /// # } /// ``` /// /// # Features /// /// This method is enabled by `time` feature. /// /// ```toml /// [dependencies] /// yasna = { version = "*", features = ["time"] } /// ``` pub fn write_generalized_time(self, datetime: &GeneralizedTime) { use super::tags::TAG_GENERALIZEDTIME; self.write_tagged_implicit(TAG_GENERALIZEDTIME, |writer| { writer.write_bytes(&datetime.to_bytes()) }); } /// Writes an ASN.1 VisibleString. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_visible_string("Hi!") /// }); /// assert_eq!(&der, &[26, 3, 72, 105, 33]); /// ``` pub fn write_visible_string(self, string: &str) { let bytes = string.as_bytes(); for &byte in bytes { assert!(b' ' <= byte && byte <= b'~', "Invalid VisibleString: {:?} appeared", byte); } self.write_tagged_implicit(TAG_VISIBLESTRING, |writer| { writer.write_bytes(bytes) }); } /// Writes an (explicitly) tagged value. /// /// # Examples /// /// ``` /// use yasna::{self,Tag}; /// let der = yasna::construct_der(|writer| { /// writer.write_tagged(Tag::context(3), |writer| { /// writer.write_i64(10) /// }) /// }); /// assert_eq!(der, vec![163, 3, 2, 1, 10]); /// ``` /// /// Note: you can achieve the same using /// [`write_tagged_implicit`](Self::write_tagged_implicit): /// /// ``` /// use yasna::{self,Tag}; /// let der = yasna::construct_der(|writer| { /// writer.write_tagged_implicit(Tag::context(3), |writer| { /// writer.write_sequence(|writer| { /// let writer = writer.next(); /// writer.write_i64(10) /// }) /// }) /// }); /// assert_eq!(der, vec![163, 3, 2, 1, 10]); /// ``` pub fn write_tagged(mut self, tag: Tag, callback: F) -> T where F: FnOnce(DERWriter) -> T { self.write_identifier(tag, PCBit::Constructed); return self.with_length(|writer| { callback(DERWriter::from_buf(writer.buf)) }); } /// Writes an implicitly tagged value. /// /// # Examples /// /// ``` /// use yasna::{self,Tag}; /// let der = yasna::construct_der(|writer| { /// writer.write_tagged_implicit(Tag::context(3), |writer| { /// writer.write_i64(10) /// }) /// }); /// assert_eq!(der, vec![131, 1, 10]); /// ``` pub fn write_tagged_implicit (mut self, tag: Tag, callback: F) -> T where F: FnOnce(DERWriter) -> T { let tag = if let Some(tag) = self.implicit_tag { tag } else { tag }; self.implicit_tag = None; let mut writer = DERWriter::from_buf(self.buf); writer.implicit_tag = Some(tag); return callback(writer); } /// Writes the arbitrary tagged DER value in `der`. /// /// # Examples /// /// ``` /// use yasna; /// use yasna::models::TaggedDerValue; /// use yasna::tags::TAG_OCTETSTRING; /// let tagged_der_value = TaggedDerValue::from_tag_and_bytes(TAG_OCTETSTRING, b"Hello!".to_vec()); /// let der1 = yasna::construct_der(|writer| { /// writer.write_tagged_der(&tagged_der_value) /// }); /// let der2 = yasna::construct_der(|writer| { /// writer.write_bytes(b"Hello!") /// }); /// assert_eq!(der1, der2); /// ``` pub fn write_tagged_der(mut self, der: &TaggedDerValue) { self.write_identifier(der.tag(), der.pcbit()); self.write_length(der.value().len()); self.buf.extend_from_slice(der.value()); } /// Writes `&[u8]` into the DER output buffer directly. Properly encoded tag /// and length must be included at the start of the passed buffer. /// /// # Examples /// /// ``` /// use yasna; /// let raw_der = yasna::construct_der(|writer| { /// writer.write_der(b"\x04\x06Hello!") /// }); /// let der = yasna::construct_der(|writer| { /// writer.write_bytes(b"Hello!") /// }); /// assert_eq!(raw_der, der); /// ``` pub fn write_der(self, der: &[u8]) { self.buf.extend_from_slice(der); } } /// A writer object that accepts ASN.1 values. /// /// The main source of this object is the [`write_sequence`][write_sequence] /// method from [`DERWriter`]. /// /// [write_sequence]: DERWriter::write_sequence /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_sequence(|writer : &mut yasna::DERWriterSeq| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// }) /// }); /// assert_eq!(der, vec![48, 6, 2, 1, 10, 1, 1, 255]); /// ``` #[derive(Debug)] pub struct DERWriterSeq<'a> { buf: &'a mut Vec, } impl<'a> DERWriterSeq<'a> { /// Generates a new [`DERWriter`]. pub fn next<'b>(&'b mut self) -> DERWriter<'b> { return DERWriter::from_buf(self.buf); } } /// A writer object that accepts ASN.1 values. /// /// The main source of this object is the [`write_set`](DERWriter::write_set) /// method from [`DERWriter`]. /// /// # Examples /// /// ``` /// use yasna; /// let der = yasna::construct_der(|writer| { /// writer.write_set(|writer : &mut yasna::DERWriterSet| { /// writer.next().write_i64(10); /// writer.next().write_bool(true); /// }) /// }); /// assert_eq!(der, vec![49, 6, 1, 1, 255, 2, 1, 10]); /// ``` #[derive(Debug)] pub struct DERWriterSet<'a> { bufs: &'a mut Vec>, } impl<'a> DERWriterSet<'a> { /// Generates a new [`DERWriter`]. pub fn next<'b>(&'b mut self) -> DERWriter<'b> { self.bufs.push(Vec::new()); return DERWriter::from_buf(self.bufs.last_mut().unwrap()); } } #[cfg(test)] mod tests; yasna-0.5.2/src/writer/tests.rs000064400000000000000000000343111046102023000145600ustar 00000000000000// Copyright 2016 Masaki Hara // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use alloc::vec; #[cfg(feature = "num-bigint")] use num_bigint::{BigUint, BigInt}; use super::super::Tag; use super::*; #[test] fn test_der_write_bool() { let tests : &[(bool, &[u8])] = &[ (false, &[1, 1, 0]), (true, &[1, 1, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_bool(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_i64() { let tests : &[(i64, &[u8])] = &[ (-9223372036854775808, &[2, 8, 128, 0, 0, 0, 0, 0, 0, 0]), (-65537, &[2, 3, 254, 255, 255]), (-65536, &[2, 3, 255, 0, 0]), (-32769, &[2, 3, 255, 127, 255]), (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_i64(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_u64() { let tests : &[(u64, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), (18446744073709551615, &[2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_u64(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_i32() { let tests : &[(i32, &[u8])] = &[ (-2147483648, &[2, 4, 128, 0, 0, 0]), (-65537, &[2, 3, 254, 255, 255]), (-65536, &[2, 3, 255, 0, 0]), (-32769, &[2, 3, 255, 127, 255]), (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (2147483647, &[2, 4, 127, 255, 255, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_i32(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_u32() { let tests : &[(u32, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (2147483647, &[2, 4, 127, 255, 255, 255]), (4294967295, &[2, 5, 0, 255, 255, 255, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_u32(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_i16() { let tests : &[(i16, &[u8])] = &[ (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_i16(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_u16() { let tests : &[(u16, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_u16(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_i8() { let tests : &[(i8, &[u8])] = &[ (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_i8(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_u8() { let tests : &[(u8, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (255, &[2, 2, 0, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_u8(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_bigint_bytes() { let tests: &[(_, &[_], &[_])] = &[ // First group: identical to test_der_write_bigint (false, &(-9223372036854775808_i64).to_be_bytes(), &[2, 8, 128, 0, 0, 0, 0, 0, 0, 0]), (false, &(-65537_i32).to_be_bytes(), &[2, 3, 254, 255, 255]), (false, &(-65536_i32).to_be_bytes(), &[2, 3, 255, 0, 0]), (false, &(-32769_i32).to_be_bytes(), &[2, 3, 255, 127, 255]), (false, &(-32768_i32).to_be_bytes(), &[2, 2, 128, 0]), (false, &(-129_i16).to_be_bytes(), &[2, 2, 255, 127]), (false, &(-128_i16).to_be_bytes(), &[2, 1, 128]), (false, &(-1_i16).to_be_bytes(), &[2, 1, 255]), (false, &[0], &[2, 1, 0]), (true, &[1], &[2, 1, 1]), (true, &127_i16.to_be_bytes(), &[2, 1, 127]), (true, &128_i16.to_be_bytes(), &[2, 2, 0, 128]), (true, &32767_u16.to_be_bytes(), &[2, 2, 127, 255]), (true, &32768_u16.to_be_bytes(), &[2, 3, 0, 128, 0]), (true, &65535_u16.to_be_bytes(), &[2, 3, 0, 255, 255]), (true, &65536_u32.to_be_bytes(), &[2, 3, 1, 0, 0]), (true, &9223372036854775807_u64.to_be_bytes(), &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), // Second group: more special tests // Leading zeros are stripped: (true, &[0, 1, 2, 3], &[2, 3, 1, 2, 3]), (true, &[0, 0, 1, 2, 3], &[2, 3, 1, 2, 3]), (true, &[0, 0, 0, 1, 2, 3], &[2, 3, 1, 2, 3]), // [255, 0] is a fixpoint of normalization (it encodes -256): (false, &[255, 0], &[2, 2, 255, 0]), ]; for &(is_nonnegative, ref value, edata) in tests { let data = construct_der(|writer| { writer.write_bigint_bytes(*value, is_nonnegative) }); assert_eq!(data, edata); } } #[cfg(feature = "num-bigint")] #[test] fn test_der_write_bigint() { use num_traits::FromPrimitive; let tests : &[(i64, &[u8])] = &[ (-9223372036854775808, &[2, 8, 128, 0, 0, 0, 0, 0, 0, 0]), (-65537, &[2, 3, 254, 255, 255]), (-65536, &[2, 3, 255, 0, 0]), (-32769, &[2, 3, 255, 127, 255]), (-32768, &[2, 2, 128, 0]), (-129, &[2, 2, 255, 127]), (-128, &[2, 1, 128]), (-1, &[2, 1, 255]), (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_bigint(&BigInt::from_i64(value).unwrap()) }); assert_eq!(data, edata); } let tests : &[(BigInt, &[u8])] = &[ (BigInt::parse_bytes( b"1234567890123456789012345678901234567890", 10).unwrap(), &[2, 17, 3, 160, 201, 32, 117, 192, 219, 243, 184, 172, 188, 95, 150, 206, 63, 10, 210]), (BigInt::parse_bytes( b"-1234567890123456789012345678901234567890", 10).unwrap(), &[2, 17, 252, 95, 54, 223, 138, 63, 36, 12, 71, 83, 67, 160, 105, 49, 192, 245, 46]), ]; for &(ref value, edata) in tests { let data = construct_der(|writer| { writer.write_bigint(value) }); assert_eq!(data, edata); } } #[cfg(feature = "num-bigint")] #[test] fn test_der_write_biguint() { use num_traits::FromPrimitive; let tests : &[(u64, &[u8])] = &[ (0, &[2, 1, 0]), (1, &[2, 1, 1]), (127, &[2, 1, 127]), (128, &[2, 2, 0, 128]), (32767, &[2, 2, 127, 255]), (32768, &[2, 3, 0, 128, 0]), (65535, &[2, 3, 0, 255, 255]), (65536, &[2, 3, 1, 0, 0]), (9223372036854775807, &[2, 8, 127, 255, 255, 255, 255, 255, 255, 255]), (18446744073709551615, &[2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_biguint(&BigUint::from_u64(value).unwrap()) }); assert_eq!(data, edata); } let tests : &[(BigUint, &[u8])] = &[ (BigUint::parse_bytes( b"1234567890123456789012345678901234567890", 10).unwrap(), &[2, 17, 3, 160, 201, 32, 117, 192, 219, 243, 184, 172, 188, 95, 150, 206, 63, 10, 210]), ]; for &(ref value, edata) in tests { let data = construct_der(|writer| { writer.write_biguint(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_bytes() { let tests : &[(&[u8], &[u8])] = &[ (&[1, 0, 100, 255], &[4, 4, 1, 0, 100, 255]), (&[], &[4, 0]), (&[4, 4, 4, 4], &[4, 4, 4, 4, 4, 4]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_bytes(value) }); assert_eq!(data, edata); } } #[test] fn test_der_write_null() { let data = construct_der(|writer| { writer.write_null() }); assert_eq!(data, vec![5, 0]); } #[test] fn test_der_write_sequence_small() { let data = construct_der(|writer| { writer.write_sequence(|_| {}) }); assert_eq!(data, vec![48, 0]); let data = construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_bytes(&vec![91; 20]); }) }); assert_eq!(data, vec![ 48, 22, 4, 20, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91]); let data = construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_bytes(&vec![91; 200]); }) }); assert_eq!(data[0..9].to_vec(), vec![48, 129, 203, 4, 129, 200, 91, 91, 91]); assert_eq!(data.len(), 206); let data = construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_bytes(&vec![91; 2000]); }) }); assert_eq!(data[0..11].to_vec(), vec![48, 130, 7, 212, 4, 130, 7, 208, 91, 91, 91]); assert_eq!(data.len(), 2008); } #[test] fn test_der_write_sequence_medium() { let data = construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_bytes(&vec![91; 200000]); }) }); assert_eq!(data[0..13].to_vec(), vec![48, 131, 3, 13, 69, 4, 131, 3, 13, 64, 91, 91, 91]); assert_eq!(data.len(), 200010); } #[test] #[ignore] fn test_der_write_sequence_large() { let data = construct_der(|writer| { writer.write_sequence(|writer| { writer.next().write_bytes(&vec![91; 20000000]); }) }); assert_eq!(data[0..15].to_vec(), vec![48, 132, 1, 49, 45, 6, 4, 132, 1, 49, 45, 0, 91, 91, 91]); assert_eq!(data.len(), 20000012); } #[test] fn test_der_write_set() { let data = construct_der(|writer| { writer.write_set(|writer| { writer.next().write_tagged_implicit(Tag::context(28), |writer| { writer.write_i64(456789) }); writer.next().write_tagged(Tag::context(345678), |writer| { writer.write_bytes(b"Foo") }); writer.next().write_tagged(Tag::context(27), |writer| { writer.write_i64(456790) }); writer.next().write_tagged(Tag::context(345677), |writer| { writer.write_bytes(b"Bar") }); }) }); assert_eq!(data, vec![ 49, 32, 187, 5, 2, 3, 6, 248, 86, 156, 3, 6, 248, 85, 191, 149, 140, 77, 5, 4, 3, 66, 97, 114, 191, 149, 140, 78, 5, 4, 3, 70, 111, 111]); } #[test] fn test_der_write_set_of() { let tests : &[(&[i64], &[u8])] = &[ (&[-129, -128, 127, 128], &[ 49, 14, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127]), (&[-128, 127, 128], &[ 49, 10, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128]), (&[-129, -128, 127, 128, 32768], &[ 49, 19, 2, 1, 127, 2, 1, 128, 2, 2, 0, 128, 2, 2, 255, 127, 2, 3, 0, 128, 0]), ]; for &(value, edata) in tests { let data = construct_der(|writer| { writer.write_set_of(|writer| { for &x in value { writer.next().write_i64(x); } }) }); assert_eq!(data, edata); } } #[test] fn test_der_write_tagged() { let data = construct_der(|writer| { writer.write_tagged(Tag::context(3), |writer| { writer.write_i64(10) }) }); assert_eq!(data, vec![163, 3, 2, 1, 10]); } #[test] fn test_der_write_tagged_implicit() { let data = construct_der(|writer| { writer.write_tagged_implicit(Tag::context(3), |writer| { writer.write_i64(10) }) }); assert_eq!(data, vec![131, 1, 10]); }