Add support for printable strings.

This commit is contained in:
2017-12-10 21:54:01 -08:00
parent 5328ade70e
commit dd281edcd1

View File

@@ -17,6 +17,7 @@ pub enum ASN1Block {
ObjectIdentifier(ASN1Class, OID), ObjectIdentifier(ASN1Class, OID),
IA5String(ASN1Class, String), IA5String(ASN1Class, String),
UTF8String(ASN1Class, String), UTF8String(ASN1Class, String),
PrintableString(ASN1Class, String),
Sequence(ASN1Class, Vec<ASN1Block>), Sequence(ASN1Class, Vec<ASN1Block>),
Set(ASN1Class, Vec<ASN1Block>), Set(ASN1Class, Vec<ASN1Block>),
Unknown(ASN1Class, BigUint, Vec<u8>) Unknown(ASN1Class, BigUint, Vec<u8>)
@@ -62,6 +63,8 @@ macro_rules! oid {
}}; }};
} }
const PRINTABLE_CHARS: &'static str =
"ABCDEFGHIJKLMOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'()+,-./:=? ";
#[derive(Clone,Copy,Debug,PartialEq)] #[derive(Clone,Copy,Debug,PartialEq)]
pub enum ASN1Class { Universal, Application, ContextSpecific, Private } pub enum ASN1Class { Universal, Application, ContextSpecific, Private }
@@ -71,7 +74,8 @@ pub enum ASN1DecodeErr {
EmptyBuffer, EmptyBuffer,
BadBooleanLength, BadBooleanLength,
LengthTooLarge, LengthTooLarge,
UTF8DecodeFailure UTF8DecodeFailure,
PrintableStringDecodeFailure
} }
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
@@ -173,6 +177,20 @@ pub fn from_der(i: &[u8]) -> Result<Vec<ASN1Block>,ASN1DecodeErr> {
return Err(e) return Err(e)
} }
} }
// PRINTABLE STRING
Some(0x13) => {
let mut res = String::new();
let mut val = body.iter().map(|x| *x as char);
for c in val {
if PRINTABLE_CHARS.contains(c) {
res.push(c);
} else {
return Err(ASN1DecodeErr::PrintableStringDecodeFailure);
}
}
result.push(ASN1Block::PrintableString(class, res));
}
// IA5 (ASCII) STRING // IA5 (ASCII) STRING
Some(0x16) => { Some(0x16) => {
let val = body.iter().map(|x| *x as char); let val = body.iter().map(|x| *x as char);
@@ -409,6 +427,24 @@ pub fn to_der(i: &ASN1Block) -> Result<Vec<u8>,ASN1EncodeErr> {
res.append(&mut body); res.append(&mut body);
Ok(res) Ok(res)
} }
// PrintableString
&ASN1Block::PrintableString(cl, ref str) => {
let mut body = Vec::new();
for c in str.chars() {
body.push(c as u8);
}
let inttag = BigUint::from_u8(0x13).unwrap();
let mut lenbytes = encode_len(body.len());
let mut tagbytes = encode_tag(cl, &inttag);
let mut res = Vec::new();
res.append(&mut tagbytes);
res.append(&mut lenbytes);
res.append(&mut body);
Ok(res)
}
// IA5String // IA5String
&ASN1Block::IA5String(cl, ref str) => { &ASN1Block::IA5String(cl, ref str) => {
let mut body = Vec::new(); let mut body = Vec::new();
@@ -724,6 +760,19 @@ mod tests {
ASN1Block::Set(class, items) ASN1Block::Set(class, items)
} }
fn arb_print<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
let class = ASN1Class::arbitrary(g);
let count = g.gen_range::<usize>(0, 384);
let mut items = Vec::new();
for _ in 0..count {
let v = g.choose(PRINTABLE_CHARS.as_bytes()).unwrap();
items.push(*v as char);
}
ASN1Block::PrintableString(class, String::from_iter(items.iter()))
}
fn arb_ia5<G: Gen>(g: &mut G, _d: usize) -> ASN1Block { fn arb_ia5<G: Gen>(g: &mut G, _d: usize) -> ASN1Block {
let class = ASN1Class::arbitrary(g); let class = ASN1Class::arbitrary(g);
let count = g.gen_range::<usize>(0, 384); let count = g.gen_range::<usize>(0, 384);
@@ -759,6 +808,7 @@ mod tests {
arb_octstr, arb_octstr,
arb_null, arb_null,
arb_objid, arb_objid,
arb_print,
arb_ia5, arb_ia5,
arb_utf8, arb_utf8,
arb_unknown]; arb_unknown];