From 89cf0a25b5c9355557ff625f29912d03c44e0171 Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Mon, 11 Dec 2017 21:31:57 -0800 Subject: [PATCH] Support more string types. --- src/lib.rs | 117 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 69b2162..cc66309 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,9 +15,12 @@ pub enum ASN1Block { OctetString(ASN1Class, Vec), Null(ASN1Class), ObjectIdentifier(ASN1Class, OID), + TeletexString(ASN1Class, String), + PrintableString(ASN1Class, String), + UniversalString(ASN1Class, String), IA5String(ASN1Class, String), UTF8String(ASN1Class, String), - PrintableString(ASN1Class, String), + BMPString(ASN1Class, String), Sequence(ASN1Class, Vec), Set(ASN1Class, Vec), Unknown(ASN1Class, BigUint, Vec) @@ -191,11 +194,38 @@ pub fn from_der(i: &[u8]) -> Result,ASN1DecodeErr> { } result.push(ASN1Block::PrintableString(class, res)); } + // TELETEX STRINGS + Some(0x14) => { + match String::from_utf8(body.to_vec()) { + Ok(v) => + result.push(ASN1Block::TeletexString(class, v)), + Err(_) => + return Err(ASN1DecodeErr::UTF8DecodeFailure) + } + } // IA5 (ASCII) STRING Some(0x16) => { let val = body.iter().map(|x| *x as char); result.push(ASN1Block::IA5String(class, String::from_iter(val))) } + // UNIVERSAL STRINGS + Some(0x1C) => { + match String::from_utf8(body.to_vec()) { + Ok(v) => + result.push(ASN1Block::UniversalString(class, v)), + Err(_) => + return Err(ASN1DecodeErr::UTF8DecodeFailure) + } + } + // UNIVERSAL STRINGS + Some(0x1E) => { + match String::from_utf8(body.to_vec()) { + Ok(v) => + result.push(ASN1Block::BMPString(class, v)), + Err(_) => + return Err(ASN1DecodeErr::UTF8DecodeFailure) + } + } // Dunno. _ => { result.push(ASN1Block::Unknown(class, tag, body.to_vec())); @@ -427,55 +457,18 @@ pub fn to_der(i: &ASN1Block) -> Result,ASN1EncodeErr> { res.append(&mut body); 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 - &ASN1Block::IA5String(cl, ref str) => { - let mut body = Vec::new(); - - for c in str.chars() { - body.push(c as u8); - } - - let inttag = BigUint::from_u8(0x16).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) - } - // UTF8STRING - &ASN1Block::UTF8String(cl, ref val) => { - let mut body = val.clone().into_bytes(); - let inttag = BigUint::from_u8(0x0C).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) - } + &ASN1Block::UTF8String(cl, ref str) => + encode_asn1_string(0x0c, false, cl, str), + &ASN1Block::PrintableString(cl, ref str) => + encode_asn1_string(0x13, true, cl, str), + &ASN1Block::TeletexString(cl, ref str) => + encode_asn1_string(0x14, false, cl, str), + &ASN1Block::UniversalString(cl, ref str) => + encode_asn1_string(0x1c, false, cl, str), + &ASN1Block::IA5String(cl, ref str) => + encode_asn1_string(0x16, true, cl, str), + &ASN1Block::BMPString(cl, ref str) => + encode_asn1_string(0x1e, false, cl, str), // Unknown blocks &ASN1Block::Unknown(class, ref tag, ref bytes) => { let mut tagbytes = encode_tag(class, &tag); @@ -490,6 +483,30 @@ pub fn to_der(i: &ASN1Block) -> Result,ASN1EncodeErr> { } } +fn encode_asn1_string(tag: u8, force_chars: bool, c: ASN1Class, s: &String) + -> Result,ASN1EncodeErr> +{ + let mut body = { if force_chars { + let mut out = Vec::new(); + + for c in s.chars() { + out.push(c as u8); + } + out + } else { + s.clone().into_bytes() + } }; + let inttag = BigUint::from_u8(tag).unwrap(); + let mut lenbytes = encode_len(body.len()); + let mut tagbytes = encode_tag(c, &inttag); + + let mut res = Vec::new(); + res.append(&mut tagbytes); + res.append(&mut lenbytes); + res.append(&mut body); + Ok(res) +} + fn encode_tag(c: ASN1Class, t: &BigUint) -> Vec { let cbyte = encode_class(c);