Merge branch 'master' of github.com:acw/simple_asn1
This commit is contained in:
12
Cargo.toml
12
Cargo.toml
@@ -5,15 +5,15 @@ authors = ["Adam Wick <awick@uhsure.com>"]
|
|||||||
description = "A simple DER/ASN.1 encoding/decoding library."
|
description = "A simple DER/ASN.1 encoding/decoding library."
|
||||||
categories = ["encoding"]
|
categories = ["encoding"]
|
||||||
keywords = ["ASN1","encoding","DER"]
|
keywords = ["ASN1","encoding","DER"]
|
||||||
license-file = "LICENSE"
|
license = "ISC"
|
||||||
repository = "https://github.com/acw/simple_asn1"
|
repository = "https://github.com/acw/simple_asn1"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = "^0.4.0"
|
chrono = { default-features = false, features = ["alloc"], version = "0.4" }
|
||||||
num-bigint = "^0.2.0"
|
num-bigint = { default-features = false, version = "0.3" }
|
||||||
num-traits = "^0.2.0"
|
num-traits = { default-features = false, version = "0.2" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
quickcheck = "^0.7.1"
|
quickcheck = "0.9"
|
||||||
rand = "0.5.5"
|
rand = "0.7"
|
||||||
|
|||||||
75
src/lib.rs
75
src/lib.rs
@@ -31,6 +31,7 @@ pub use num_bigint::{BigInt, BigUint};
|
|||||||
use num_traits::{FromPrimitive, One, ToPrimitive, Zero};
|
use num_traits::{FromPrimitive, One, ToPrimitive, Zero};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use quickcheck::quickcheck;
|
use quickcheck::quickcheck;
|
||||||
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
@@ -335,22 +336,42 @@ pub enum ASN1EncodeErr {
|
|||||||
ObjectIdentVal2TooLarge,
|
ObjectIdentVal2TooLarge,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ASN1EncodeErr {
|
impl ASN1EncodeErr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn description(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
ASN1EncodeErr::ObjectIdentHasTooFewFields => {
|
ASN1EncodeErr::ObjectIdentHasTooFewFields => {
|
||||||
write!(f, "ASN1 object identifier has too few fields.")
|
"ASN1 object identifier has too few fields."
|
||||||
}
|
}
|
||||||
ASN1EncodeErr::ObjectIdentVal1TooLarge => {
|
ASN1EncodeErr::ObjectIdentVal1TooLarge => {
|
||||||
write!(f, "First value in ASN1 OID is too big.")
|
"First value in ASN1 OID is too big."
|
||||||
}
|
}
|
||||||
ASN1EncodeErr::ObjectIdentVal2TooLarge => {
|
ASN1EncodeErr::ObjectIdentVal2TooLarge => {
|
||||||
write!(f, "Second value in ASN1 OID is too big.")
|
"Second value in ASN1 OID is too big."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ASN1EncodeErr {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.write_str(self.description())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ASN1EncodeErr {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
self.description()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&dyn Error> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Translate a binary blob into a series of `ASN1Block`s, or provide an
|
/// Translate a binary blob into a series of `ASN1Block`s, or provide an
|
||||||
/// error if it didn't work.
|
/// error if it didn't work.
|
||||||
pub fn from_der(i: &[u8]) -> Result<Vec<ASN1Block>, ASN1DecodeErr> {
|
pub fn from_der(i: &[u8]) -> Result<Vec<ASN1Block>, ASN1DecodeErr> {
|
||||||
@@ -1072,7 +1093,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use chrono::offset::LocalResult;
|
use chrono::offset::LocalResult;
|
||||||
use quickcheck::{Arbitrary, Gen};
|
use quickcheck::{Arbitrary, Gen};
|
||||||
use rand::{distributions::Standard, Rng};
|
use rand::{distributions::Standard, prelude::SliceRandom, Rng};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
@@ -1178,7 +1199,7 @@ mod tests {
|
|||||||
|
|
||||||
impl Arbitrary for OID {
|
impl Arbitrary for OID {
|
||||||
fn arbitrary<G: Gen>(g: &mut G) -> OID {
|
fn arbitrary<G: Gen>(g: &mut G) -> OID {
|
||||||
let count = g.gen_range::<usize>(0, 40);
|
let count = g.gen_range::<usize, _, _>(0, 40);
|
||||||
let val1 = g.gen::<u8>() % 3;
|
let val1 = g.gen::<u8>() % 3;
|
||||||
let v2mod = if val1 == 2 { 176 } else { 40 };
|
let v2mod = if val1 == 2 { 176 } else { 40 };
|
||||||
let val2 = g.gen::<u8>() % v2mod;
|
let val2 = g.gen::<u8>() % v2mod;
|
||||||
@@ -1201,7 +1222,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn arb_seq<G: Gen>(g: &mut G, d: usize) -> ASN1Block {
|
fn arb_seq<G: Gen>(g: &mut G, d: usize) -> ASN1Block {
|
||||||
let count = g.gen_range::<usize>(1, 64);
|
let count = g.gen_range::<usize, _, _>(1, 64);
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
@@ -1212,7 +1233,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn arb_set<G: Gen>(g: &mut G, d: usize) -> ASN1Block {
|
fn arb_set<G: Gen>(g: &mut G, d: usize) -> ASN1Block {
|
||||||
let count = g.gen_range::<usize>(1, 64);
|
let count = g.gen_range::<usize, _, _>(1, 64);
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
@@ -1223,11 +1244,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn arb_print<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
fn arb_print<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
||||||
let count = g.gen_range::<usize>(0, 384);
|
let count = g.gen_range::<usize, _, _>(0, 384);
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
let v = g.choose(PRINTABLE_CHARS.as_bytes()).unwrap();
|
let v = PRINTABLE_CHARS.as_bytes().choose(g).unwrap();
|
||||||
items.push(*v as char);
|
items.push(*v as char);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1235,7 +1256,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn arb_ia5<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
fn arb_ia5<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
||||||
let count = g.gen_range::<usize>(0, 384);
|
let count = g.gen_range::<usize, _, _>(0, 384);
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
@@ -1267,15 +1288,15 @@ mod tests {
|
|||||||
|
|
||||||
fn arb_utc<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
fn arb_utc<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
||||||
loop {
|
loop {
|
||||||
let y = g.gen_range::<i32>(1970, 2069);
|
let y = g.gen_range::<i32, _, _>(1970, 2069);
|
||||||
let m = g.gen_range::<u32>(1, 13);
|
let m = g.gen_range::<u32, _, _>(1, 13);
|
||||||
let d = g.gen_range::<u32>(1, 32);
|
let d = g.gen_range::<u32, _, _>(1, 32);
|
||||||
match Utc.ymd_opt(y, m, d) {
|
match Utc.ymd_opt(y, m, d) {
|
||||||
LocalResult::None => {}
|
LocalResult::None => {}
|
||||||
LocalResult::Single(d) => {
|
LocalResult::Single(d) => {
|
||||||
let h = g.gen_range::<u32>(0, 24);
|
let h = g.gen_range::<u32, _, _>(0, 24);
|
||||||
let m = g.gen_range::<u32>(0, 60);
|
let m = g.gen_range::<u32, _, _>(0, 60);
|
||||||
let s = g.gen_range::<u32>(0, 60);
|
let s = g.gen_range::<u32, _, _>(0, 60);
|
||||||
let t = d.and_hms(h, m, s);
|
let t = d.and_hms(h, m, s);
|
||||||
return ASN1Block::UTCTime(0, t);
|
return ASN1Block::UTCTime(0, t);
|
||||||
}
|
}
|
||||||
@@ -1286,16 +1307,16 @@ mod tests {
|
|||||||
|
|
||||||
fn arb_time<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
fn arb_time<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
||||||
loop {
|
loop {
|
||||||
let y = g.gen_range::<i32>(0, 10000);
|
let y = g.gen_range::<i32, _, _>(0, 10000);
|
||||||
let m = g.gen_range::<u32>(1, 13);
|
let m = g.gen_range::<u32, _, _>(1, 13);
|
||||||
let d = g.gen_range::<u32>(1, 32);
|
let d = g.gen_range::<u32, _, _>(1, 32);
|
||||||
match Utc.ymd_opt(y, m, d) {
|
match Utc.ymd_opt(y, m, d) {
|
||||||
LocalResult::None => {}
|
LocalResult::None => {}
|
||||||
LocalResult::Single(d) => {
|
LocalResult::Single(d) => {
|
||||||
let h = g.gen_range::<u32>(0, 24);
|
let h = g.gen_range::<u32, _, _>(0, 24);
|
||||||
let m = g.gen_range::<u32>(0, 60);
|
let m = g.gen_range::<u32, _, _>(0, 60);
|
||||||
let s = g.gen_range::<u32>(0, 60);
|
let s = g.gen_range::<u32, _, _>(0, 60);
|
||||||
let n = g.gen_range::<u32>(0, 1000000000);
|
let n = g.gen_range::<u32, _, _>(0, 1000000000);
|
||||||
let t = d.and_hms_nano(h, m, s, n);
|
let t = d.and_hms_nano(h, m, s, n);
|
||||||
return ASN1Block::GeneralizedTime(0, t);
|
return ASN1Block::GeneralizedTime(0, t);
|
||||||
}
|
}
|
||||||
@@ -1319,7 +1340,7 @@ mod tests {
|
|||||||
fn arb_unknown<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
fn arb_unknown<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
|
||||||
let class = ASN1Class::arbitrary(g);
|
let class = ASN1Class::arbitrary(g);
|
||||||
let tag = RandomUint::arbitrary(g);
|
let tag = RandomUint::arbitrary(g);
|
||||||
let size = g.gen_range::<usize>(0, 128);
|
let size = g.gen_range::<usize, _, _>(0, 128);
|
||||||
let items = g.sample_iter::<u8, _>(&Standard).take(size).collect();
|
let items = g.sample_iter::<u8, _>(&Standard).take(size).collect();
|
||||||
|
|
||||||
ASN1Block::Unknown(class, false, 0, tag.x, items)
|
ASN1Block::Unknown(class, false, 0, tag.x, items)
|
||||||
@@ -1350,7 +1371,7 @@ mod tests {
|
|||||||
possibles.push(arb_explicit);
|
possibles.push(arb_explicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
match g.choose(&possibles[..]) {
|
match possibles[..].choose(g) {
|
||||||
Some(f) => f(g, d),
|
Some(f) => f(g, d),
|
||||||
None => panic!("Couldn't generate arbitrary value."),
|
None => panic!("Couldn't generate arbitrary value."),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user